mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-21 14:59:39 +00:00
Feat: Rename and Delete for imported Models ☁️ (#6969)
## Summary Add Rename and Delete options for Personal Models. Also updates and standardizes some styles for Cards and adds a simple Confirmation dialog. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6969-WIP-Feat-Rename-and-Delete-for-custom-Models-2b86d73d36508140a687e929b0544ae6) by [Unito](https://www.unito.io) --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1,17 +1,15 @@
|
||||
<template>
|
||||
<div :class="iconGroupClasses">
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'flex justify-center items-center shrink-0 outline-hidden border-none p-0 rounded-lg bg-secondary-background shadow-sm transition-all duration-200 cursor-pointer'
|
||||
)
|
||||
"
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { cn } from '@/utils/tailwindUtil'
|
||||
|
||||
const iconGroupClasses = cn(
|
||||
'flex justify-center items-center shrink-0',
|
||||
'outline-hidden border-none p-0 rounded-lg',
|
||||
'bg-secondary-background shadow-sm',
|
||||
'transition-all duration-200',
|
||||
'cursor-pointer'
|
||||
)
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="relative inline-flex items-center">
|
||||
<IconButton :size="size" :type="type" @click="toggle">
|
||||
<IconButton :size="size" :type="type" @click="popover?.toggle">
|
||||
<i v-if="!isVertical" class="icon-[lucide--ellipsis] text-sm" />
|
||||
<i v-else class="icon-[lucide--more-vertical] text-sm" />
|
||||
</IconButton>
|
||||
@@ -25,8 +25,18 @@
|
||||
)
|
||||
}
|
||||
}"
|
||||
@show="$emit('menuOpened')"
|
||||
@hide="$emit('menuClosed')"
|
||||
@show="
|
||||
() => {
|
||||
isOpen = true
|
||||
$emit('menuOpened')
|
||||
}
|
||||
"
|
||||
@hide="
|
||||
() => {
|
||||
isOpen = false
|
||||
$emit('menuClosed')
|
||||
}
|
||||
"
|
||||
>
|
||||
<div class="flex min-w-40 flex-col gap-2 p-2">
|
||||
<slot :close="hide" />
|
||||
@@ -48,8 +58,6 @@ interface MoreButtonProps extends BaseButtonProps {
|
||||
isVertical?: boolean
|
||||
}
|
||||
|
||||
const popover = ref<InstanceType<typeof Popover>>()
|
||||
|
||||
const {
|
||||
size = 'md',
|
||||
type = 'secondary',
|
||||
@@ -61,15 +69,15 @@ defineEmits<{
|
||||
menuClosed: []
|
||||
}>()
|
||||
|
||||
const toggle = (event: Event) => {
|
||||
popover.value?.toggle(event)
|
||||
}
|
||||
const isOpen = ref(false)
|
||||
const popover = ref<InstanceType<typeof Popover>>()
|
||||
|
||||
const hide = () => {
|
||||
function hide() {
|
||||
popover.value?.hide()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
hide
|
||||
hide,
|
||||
isOpen
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
...inputAttrs
|
||||
}
|
||||
}"
|
||||
@keyup.enter="blurInputElement"
|
||||
@keyup.escape="cancelEditing"
|
||||
@keyup.enter.capture.stop="blurInputElement"
|
||||
@keyup.escape.stop="cancelEditing"
|
||||
@click.stop
|
||||
@pointerdown.stop.capture
|
||||
@pointermove.stop.capture
|
||||
@@ -38,7 +38,7 @@ const {
|
||||
} = defineProps<{
|
||||
modelValue: string
|
||||
isEditing?: boolean
|
||||
inputAttrs?: Record<string, any>
|
||||
inputAttrs?: Record<string, string>
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'edit', 'cancel'])
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<component
|
||||
:is="item.headerComponent"
|
||||
v-if="item.headerComponent"
|
||||
v-bind="item.headerProps"
|
||||
:id="item.key"
|
||||
/>
|
||||
<h3 v-else :id="item.key">
|
||||
|
||||
19
src/components/dialog/confirm/ConfirmBody.vue
Normal file
19
src/components/dialog/confirm/ConfirmBody.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div
|
||||
class="flex flex-col px-4 py-2 text-sm text-muted-foreground border-t border-border-default"
|
||||
>
|
||||
<p v-if="promptTextReal">
|
||||
{{ promptTextReal }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, toValue } from 'vue'
|
||||
import type { MaybeRefOrGetter } from 'vue'
|
||||
|
||||
const { promptText } = defineProps<{
|
||||
promptText?: MaybeRefOrGetter<string>
|
||||
}>()
|
||||
|
||||
const promptTextReal = computed(() => toValue(promptText))
|
||||
</script>
|
||||
43
src/components/dialog/confirm/ConfirmFooter.vue
Normal file
43
src/components/dialog/confirm/ConfirmFooter.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<section class="w-full flex gap-2 justify-end px-2 pb-2">
|
||||
<TextButton
|
||||
:label="cancelTextX"
|
||||
:disabled
|
||||
type="transparent"
|
||||
autofocus
|
||||
@click="$emit('cancel')"
|
||||
/>
|
||||
<TextButton
|
||||
:label="confirmTextX"
|
||||
:disabled
|
||||
type="transparent"
|
||||
:class="confirmClass"
|
||||
@click="$emit('confirm')"
|
||||
/>
|
||||
</section>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, toValue } from 'vue'
|
||||
import type { MaybeRefOrGetter } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import TextButton from '@/components/button/TextButton.vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const { cancelText, confirmText, confirmClass, optionsDisabled } = defineProps<{
|
||||
cancelText?: string
|
||||
confirmText?: string
|
||||
confirmClass?: string
|
||||
optionsDisabled?: MaybeRefOrGetter<boolean>
|
||||
}>()
|
||||
|
||||
defineEmits<{
|
||||
cancel: []
|
||||
confirm: []
|
||||
}>()
|
||||
|
||||
const confirmTextX = computed(() => confirmText || t('g.confirm'))
|
||||
const cancelTextX = computed(() => cancelText || t('g.cancel'))
|
||||
const disabled = computed(() => toValue(optionsDisabled))
|
||||
</script>
|
||||
12
src/components/dialog/confirm/ConfirmHeader.vue
Normal file
12
src/components/dialog/confirm/ConfirmHeader.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<div
|
||||
class="flex items-center gap-2 p-4 font-bold text-sm text-base-foreground font-inter"
|
||||
>
|
||||
<span v-if="title" class="flex-auto">{{ title }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
title?: string
|
||||
}>()
|
||||
</script>
|
||||
31
src/components/dialog/confirm/confirmDialog.ts
Normal file
31
src/components/dialog/confirm/confirmDialog.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import ConfirmBody from '@/components/dialog/confirm/ConfirmBody.vue'
|
||||
import ConfirmFooter from '@/components/dialog/confirm/ConfirmFooter.vue'
|
||||
import ConfirmHeader from '@/components/dialog/confirm/ConfirmHeader.vue'
|
||||
import { useDialogStore } from '@/stores/dialogStore'
|
||||
import type { ComponentAttrs } from 'vue-component-type-helpers'
|
||||
|
||||
interface ConfirmDialogOptions {
|
||||
headerProps?: ComponentAttrs<typeof ConfirmHeader>
|
||||
props?: ComponentAttrs<typeof ConfirmBody>
|
||||
footerProps?: ComponentAttrs<typeof ConfirmFooter>
|
||||
}
|
||||
|
||||
export function showConfirmDialog(options: ConfirmDialogOptions = {}) {
|
||||
const dialogStore = useDialogStore()
|
||||
const { headerProps, props, footerProps } = options
|
||||
return dialogStore.showDialog({
|
||||
headerComponent: ConfirmHeader,
|
||||
component: ConfirmBody,
|
||||
footerComponent: ConfirmFooter,
|
||||
headerProps,
|
||||
props,
|
||||
footerProps,
|
||||
dialogComponentProps: {
|
||||
pt: {
|
||||
header: 'py-0! px-0!',
|
||||
content: 'p-0!',
|
||||
footer: 'p-0!'
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user