mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-22 15:54:09 +00:00
## Summary Adds an editable Model Info Panel to show and modify asset details in the asset browser. ## Changes - Add `ModelInfoPanel` component with editable display name, description, model type, base models, and tags - Add `updateAssetMetadata` action in `assetsStore` with optimistic cache updates - Add shadcn-vue `Select` components with design system styling - Add utility functions in `assetMetadataUtils` for extracting model metadata - Convert `BaseModalLayout` right panel state to `defineModel` pattern - Add slide-in animation and collapse button for right panel - Add `class` prop to `PropertiesAccordionItem` for custom styling - Fix keyboard handling: Escape in TagsInput/TextArea doesn't close parent modal ## Testing - Unit tests for `ModelInfoPanel` component - Unit tests for `assetMetadataUtils` functions --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: GitHub Action <action@github.com>
95 lines
3.0 KiB
TypeScript
95 lines
3.0 KiB
TypeScript
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 { useAssetsStore } from '@/stores/assetsStore'
|
|
import { useModelToNodeStore } from '@/stores/modelToNodeStore'
|
|
|
|
/**
|
|
* Composable for fetching and transforming asset data for Vue node widgets.
|
|
* Provides reactive asset data based on node type with automatic category detection.
|
|
* Uses store-based caching to avoid duplicate fetches across multiple instances.
|
|
*
|
|
* Cloud-only composable - returns empty data when not in cloud environment.
|
|
*
|
|
* @param nodeType - ComfyUI node type (ref, getter, or plain value). Can be undefined.
|
|
* Accepts: ref('CheckpointLoaderSimple'), () => 'CheckpointLoaderSimple', or 'CheckpointLoaderSimple'
|
|
* @returns Reactive data including category, assets, dropdown items, loading state, and errors
|
|
*/
|
|
export function useAssetWidgetData(
|
|
nodeType: MaybeRefOrGetter<string | undefined>
|
|
) {
|
|
if (isCloud) {
|
|
const assetsStore = useAssetsStore()
|
|
const modelToNodeStore = useModelToNodeStore()
|
|
|
|
const category = computed(() => {
|
|
const resolvedType = toValue(nodeType)
|
|
return resolvedType
|
|
? modelToNodeStore.getCategoryForNodeType(resolvedType)
|
|
: undefined
|
|
})
|
|
|
|
const assets = computed<AssetItem[]>(() => {
|
|
const resolvedType = toValue(nodeType)
|
|
return resolvedType ? (assetsStore.getAssets(resolvedType) ?? []) : []
|
|
})
|
|
|
|
const isLoading = computed(() => {
|
|
const resolvedType = toValue(nodeType)
|
|
return resolvedType ? assetsStore.isModelLoading(resolvedType) : false
|
|
})
|
|
|
|
const error = computed<Error | null>(() => {
|
|
const resolvedType = toValue(nodeType)
|
|
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) => {
|
|
if (!currentNodeType) {
|
|
return
|
|
}
|
|
|
|
const isLoading = assetsStore.isModelLoading(currentNodeType)
|
|
const hasBeenInitialized = assetsStore.hasAssetKey(currentNodeType)
|
|
|
|
if (!isLoading && !hasBeenInitialized) {
|
|
await assetsStore.updateModelsForNodeType(currentNodeType)
|
|
}
|
|
},
|
|
{ immediate: true }
|
|
)
|
|
|
|
return {
|
|
category,
|
|
assets,
|
|
dropdownItems,
|
|
isLoading,
|
|
error
|
|
}
|
|
}
|
|
|
|
return {
|
|
category: computed(() => undefined),
|
|
assets: computed(() => []),
|
|
dropdownItems: computed(() => []),
|
|
isLoading: computed(() => false),
|
|
error: computed(() => null)
|
|
}
|
|
}
|