diff --git a/src/components/common/EditableText.vue b/src/components/common/EditableText.vue index 322d332a4..ba4340913 100644 --- a/src/components/common/EditableText.vue +++ b/src/components/common/EditableText.vue @@ -19,7 +19,7 @@ } }" @keyup.enter.capture.stop="blurInputElement" - @keyup.escape.stop="cancelEditing" + @keydown.escape.capture.stop="cancelEditing" @click.stop @contextmenu.stop @pointerdown.stop.capture diff --git a/src/components/widget/layout/BaseModalLayout.vue b/src/components/widget/layout/BaseModalLayout.vue index 48886dad0..0f64afa98 100644 --- a/src/components/widget/layout/BaseModalLayout.vue +++ b/src/components/widget/layout/BaseModalLayout.vue @@ -171,6 +171,13 @@ const toggleRightPanel = () => { } function handleEscape(event: KeyboardEvent) { + const target = event.target + if ( + target instanceof HTMLInputElement || + target instanceof HTMLTextAreaElement + ) { + return + } if (isRightPanelOpen.value) { event.stopPropagation() isRightPanelOpen.value = false diff --git a/src/platform/assets/components/AssetCard.vue b/src/platform/assets/components/AssetCard.vue index b2a801af5..a4bfb4f62 100644 --- a/src/platform/assets/components/AssetCard.vue +++ b/src/platform/assets/components/AssetCard.vue @@ -166,10 +166,10 @@ onClickOutside( () => { if (focused) { const activeElement = document.activeElement - const isSelectInPanel = - activeElement?.tagName === 'SELECT' && - activeElement.closest('[data-component-id="ModelInfoPanel"]') - if (isSelectInPanel) return + const isInPanel = !!activeElement?.closest( + '[data-component-id="ModelInfoPanel"]' + ) + if (isInPanel) return emit('blur') } diff --git a/src/platform/assets/components/modelInfo/ModelInfoPanel.vue b/src/platform/assets/components/modelInfo/ModelInfoPanel.vue index a3dcb5382..7dd35876c 100644 --- a/src/platform/assets/components/modelInfo/ModelInfoPanel.vue +++ b/src/platform/assets/components/modelInfo/ModelInfoPanel.vue @@ -10,7 +10,14 @@ - {{ displayName }} + {{ asset.name }} @@ -153,6 +160,7 @@ import { useDebounceFn } from '@vueuse/core' import { computed, ref, useTemplateRef, watch } from 'vue' +import EditableText from '@/components/common/EditableText.vue' import PropertiesAccordionItem from '@/components/rightSidePanel/layout/PropertiesAccordionItem.vue' import TagsInput from '@/components/ui/tags-input/TagsInput.vue' import TagsInputInput from '@/components/ui/tags-input/TagsInputInput.vue' @@ -194,6 +202,9 @@ const { asset, cacheKey } = defineProps<{ const assetsStore = useAssetsStore() const { modelTypes } = useModelTypes() +const pendingUpdates = ref({}) +const isEditingDisplayName = ref(false) + const isImmutable = computed(() => asset.is_immutable ?? true) const displayName = computed(() => getAssetDisplayName(asset)) const sourceUrl = computed(() => getAssetSourceUrl(asset)) @@ -203,8 +214,6 @@ const sourceName = computed(() => const description = computed(() => getAssetDescription(asset)) const triggerPhrases = computed(() => getAssetTriggerPhrases(asset)) -const pendingUpdates = ref({}) - watch( () => asset.user_metadata, () => { @@ -226,6 +235,13 @@ function queueMetadataUpdate(updates: AssetUserMetadata) { debouncedFlushMetadata() } +function handleDisplayNameEdit(newName: string) { + isEditingDisplayName.value = false + if (newName && newName !== displayName.value) { + queueMetadataUpdate({ name: newName }) + } +} + const debouncedSaveModelType = useDebounceFn((newModelType: string) => { if (isImmutable.value) return const currentModelType = getAssetModelType(asset) diff --git a/src/platform/assets/schemas/assetSchema.ts b/src/platform/assets/schemas/assetSchema.ts index 984703adf..e21b10cd6 100644 --- a/src/platform/assets/schemas/assetSchema.ts +++ b/src/platform/assets/schemas/assetSchema.ts @@ -97,6 +97,7 @@ export type AssetUpdatePayload = Partial< /** User-editable metadata fields for model assets */ const zAssetUserMetadata = z.object({ + name: z.string().optional(), base_model: z.array(z.string()).optional(), additional_tags: z.array(z.string()).optional(), user_description: z.string().optional()