feat: make display name editable in ModelInfoPanel

This commit is contained in:
Alexander Brown
2026-01-16 20:00:57 -08:00
parent 0289cc8c65
commit cfd03ab282
5 changed files with 32 additions and 8 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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')
}

View File

@@ -10,7 +10,14 @@
</span>
</template>
<ModelInfoField :label="$t('assetBrowser.modelInfo.displayName')">
<span class="break-all">{{ displayName }}</span>
<EditableText
:model-value="displayName"
:is-editing="isEditingDisplayName"
class="break-all"
@dblclick="isEditingDisplayName = !isImmutable"
@edit="handleDisplayNameEdit"
@cancel="isEditingDisplayName = false"
/>
</ModelInfoField>
<ModelInfoField :label="$t('assetBrowser.modelInfo.fileName')">
<span class="break-all">{{ asset.name }}</span>
@@ -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<AssetUserMetadata>({})
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<AssetUserMetadata>({})
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)

View File

@@ -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()