mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 18:52:19 +00:00
feat: add ownership and base model filtering, unify asset/dropdown types (#8497)
Add ownership and base model filtering to AssetBrowserModal and FormDropdown widgets. ## Changes - **Ownership filter**: Filter by All/My Models/Public Models (uses `is_immutable` field) - **Base model filter**: Multi-select filter with Clear Filters button - **Type unification**: Replace `AssetDropdownItem` with `FormDropdownItem` - **Sorting unification**: Extract shared utilities to `assetSortUtils.ts` - **UI refactor**: Use `Button` component, Vue 3.5 prop shorthand, i18n improvements --------- Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -29,12 +29,10 @@ vi.mock('@/stores/modelToNodeStore', () => ({
|
||||
describe('useAssetWidgetData (desktop/isCloud=false)', () => {
|
||||
it('returns empty/default values without calling stores', () => {
|
||||
const nodeType = ref('CheckpointLoaderSimple')
|
||||
const { category, assets, dropdownItems, isLoading, error } =
|
||||
useAssetWidgetData(nodeType)
|
||||
const { category, assets, isLoading, error } = useAssetWidgetData(nodeType)
|
||||
|
||||
expect(category.value).toBeUndefined()
|
||||
expect(assets.value).toEqual([])
|
||||
expect(dropdownItems.value).toEqual([])
|
||||
expect(isLoading.value).toBe(false)
|
||||
expect(error.value).toBeNull()
|
||||
expect(mockUpdateModelsForNodeType).not.toHaveBeenCalled()
|
||||
|
||||
@@ -64,7 +64,7 @@ describe('useAssetWidgetData (cloud mode, isCloud=true)', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('fetches assets and transforms to dropdown items', async () => {
|
||||
it('fetches assets for a given node type', async () => {
|
||||
const mockAssets: AssetItem[] = [
|
||||
createMockAsset(
|
||||
'asset-1',
|
||||
@@ -87,8 +87,7 @@ describe('useAssetWidgetData (cloud mode, isCloud=true)', () => {
|
||||
)
|
||||
|
||||
const nodeType = ref('CheckpointLoaderSimple')
|
||||
const { category, assets, dropdownItems, isLoading } =
|
||||
useAssetWidgetData(nodeType)
|
||||
const { category, assets, isLoading } = useAssetWidgetData(nodeType)
|
||||
|
||||
await nextTick()
|
||||
await vi.waitFor(() => !isLoading.value)
|
||||
@@ -98,13 +97,10 @@ describe('useAssetWidgetData (cloud mode, isCloud=true)', () => {
|
||||
)
|
||||
expect(category.value).toBe('checkpoints')
|
||||
expect(assets.value).toEqual(mockAssets)
|
||||
|
||||
expect(dropdownItems.value).toHaveLength(2)
|
||||
const item = dropdownItems.value[0]
|
||||
expect(item.id).toBe('asset-1')
|
||||
expect(item.name).toBe('models/beautiful_model.safetensors')
|
||||
expect(item.label).toBe('Beautiful Model')
|
||||
expect(item.mediaSrc).toBe('/api/preview/asset-1')
|
||||
expect(assets.value).toHaveLength(2)
|
||||
expect(assets.value[0].id).toBe('asset-1')
|
||||
expect(assets.value[0].name).toBe('Beautiful Model')
|
||||
expect(assets.value[0].preview_url).toBe('/api/preview/asset-1')
|
||||
})
|
||||
|
||||
it('handles API errors gracefully', async () => {
|
||||
@@ -238,7 +234,7 @@ describe('useAssetWidgetData (cloud mode, isCloud=true)', () => {
|
||||
})
|
||||
|
||||
it('handles undefined node type gracefully', async () => {
|
||||
const { category, assets, dropdownItems, isLoading, error } =
|
||||
const { category, assets, isLoading, error } =
|
||||
useAssetWidgetData(undefined)
|
||||
|
||||
await nextTick()
|
||||
@@ -246,7 +242,6 @@ describe('useAssetWidgetData (cloud mode, isCloud=true)', () => {
|
||||
expect(mockUpdateModelsForNodeType).not.toHaveBeenCalled()
|
||||
expect(category.value).toBeUndefined()
|
||||
expect(assets.value).toEqual([])
|
||||
expect(dropdownItems.value).toEqual([])
|
||||
expect(isLoading.value).toBe(false)
|
||||
expect(error.value).toBeNull()
|
||||
})
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { computed, toValue, watch } from 'vue'
|
||||
import type { MaybeRefOrGetter } from 'vue'
|
||||
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
|
||||
import type { DropdownItem } from '@/renderer/extensions/vueNodes/widgets/components/form/dropdown/types'
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { useAssetsStore } from '@/stores/assetsStore'
|
||||
import { useModelToNodeStore } from '@/stores/modelToNodeStore'
|
||||
|
||||
@@ -47,17 +46,6 @@ export function useAssetWidgetData(
|
||||
return resolvedType ? (assetsStore.getError(resolvedType) ?? null) : null
|
||||
})
|
||||
|
||||
const dropdownItems = computed<DropdownItem[]>(() => {
|
||||
return (assets.value ?? []).map((asset) => ({
|
||||
id: asset.id,
|
||||
name:
|
||||
(asset.user_metadata?.filename as string | undefined) ?? asset.name,
|
||||
label: asset.name,
|
||||
mediaSrc: asset.preview_url ?? '',
|
||||
metadata: ''
|
||||
}))
|
||||
})
|
||||
|
||||
watch(
|
||||
() => toValue(nodeType),
|
||||
async (currentNodeType) => {
|
||||
@@ -78,7 +66,6 @@ export function useAssetWidgetData(
|
||||
return {
|
||||
category,
|
||||
assets,
|
||||
dropdownItems,
|
||||
isLoading,
|
||||
error
|
||||
}
|
||||
@@ -86,8 +73,7 @@ export function useAssetWidgetData(
|
||||
|
||||
return {
|
||||
category: computed(() => undefined),
|
||||
assets: computed(() => []),
|
||||
dropdownItems: computed(() => []),
|
||||
assets: computed<AssetItem[]>(() => []),
|
||||
isLoading: computed(() => false),
|
||||
error: computed(() => null)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user