mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-02 06:19:58 +00:00
WIP: Deleting assets, UI only, also not wired up
This commit is contained in:
@@ -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">
|
||||
|
||||
14
src/components/dialog/confirm/ConfirmBody.vue
Normal file
14
src/components/dialog/confirm/ConfirmBody.vue
Normal file
@@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<div
|
||||
class="flex flex-col px-4 py-2 text-sm text-muted-foreground border-t border-border-default"
|
||||
>
|
||||
<p v-if="confirmationText">
|
||||
{{ confirmationText }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
confirmationText?: string
|
||||
}>()
|
||||
</script>
|
||||
38
src/components/dialog/confirm/ConfirmFooter.vue
Normal file
38
src/components/dialog/confirm/ConfirmFooter.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<section class="w-full flex gap-2 justify-end px-2 pb-2">
|
||||
<TextButton
|
||||
:label="cancelTextX"
|
||||
type="transparent"
|
||||
autofocus
|
||||
@click="$emit('cancel')"
|
||||
/>
|
||||
<TextButton
|
||||
:label="confirmTextX"
|
||||
type="transparent"
|
||||
:class="confirmClass"
|
||||
@click="$emit('confirm')"
|
||||
/>
|
||||
</section>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import TextButton from '@/components/button/TextButton.vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const { cancelText, confirmText, confirmClass } = defineProps<{
|
||||
cancelText?: string
|
||||
confirmText?: string
|
||||
confirmClass?: string
|
||||
}>()
|
||||
|
||||
defineEmits<{
|
||||
cancel: []
|
||||
confirm: []
|
||||
}>()
|
||||
|
||||
const confirmTextX = computed(() => confirmText || t('g.confirm'))
|
||||
const cancelTextX = computed(() => cancelText || t('g.cancel'))
|
||||
</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!'
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -54,7 +54,12 @@
|
||||
<i class="icon-[lucide--pencil]" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<IconTextButton :label="$t('g.delete')" type="secondary" size="md">
|
||||
<IconTextButton
|
||||
:label="$t('g.delete')"
|
||||
type="secondary"
|
||||
size="md"
|
||||
@click="confirmDeletion"
|
||||
>
|
||||
<template #icon>
|
||||
<i class="icon-[lucide--trash-2]" />
|
||||
</template>
|
||||
@@ -120,9 +125,11 @@ import IconGroup from '@/components/button/IconGroup.vue'
|
||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||
import MoreButton from '@/components/button/MoreButton.vue'
|
||||
import EditableText from '@/components/common/EditableText.vue'
|
||||
import { showConfirmDialog } from '@/components/dialog/confirm/confirmDialog'
|
||||
import AssetBadgeGroup from '@/platform/assets/components/AssetBadgeGroup.vue'
|
||||
import type { AssetDisplayItem } from '@/platform/assets/composables/useAssetBrowser'
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import { useDialogStore } from '@/stores/dialogStore'
|
||||
import { cn } from '@/utils/tailwindUtil'
|
||||
|
||||
const { asset, interactive } = defineProps<{
|
||||
@@ -135,6 +142,7 @@ defineEmits<{
|
||||
}>()
|
||||
|
||||
const settingStore = useSettingStore()
|
||||
const { closeDialog } = useDialogStore()
|
||||
|
||||
const dropdownMenuButton = useTemplateRef<InstanceType<typeof MoreButton>>(
|
||||
'dropdown-menu-button'
|
||||
@@ -155,6 +163,32 @@ const { isLoading, error } = useImage({
|
||||
alt: asset.name
|
||||
})
|
||||
|
||||
async function confirmDeletion() {
|
||||
dropdownMenuButton.value?.hide()
|
||||
const confirmDialog = showConfirmDialog({
|
||||
headerProps: {
|
||||
title: 'Delete this model?'
|
||||
},
|
||||
props: {
|
||||
confirmationText:
|
||||
'This model will be permanently removed from your library.'
|
||||
},
|
||||
footerProps: {
|
||||
confirmText: 'Delete',
|
||||
// TODO: These need to be put into the new Button Variants once we have them.
|
||||
confirmClass: cn(
|
||||
'bg-danger-200 text-base-foreground hover:bg-danger-200/80 focus:bg-danger-200/80 focus:ring ring-base-foreground'
|
||||
),
|
||||
onCancel: () => {
|
||||
closeDialog(confirmDialog)
|
||||
},
|
||||
onConfirm: () => {
|
||||
closeDialog(confirmDialog)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function startAssetRename() {
|
||||
dropdownMenuButton.value?.hide()
|
||||
isEditing.value = true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div
|
||||
class="upload-model-dialog flex flex-col justify-between gap-6 p-4 pt-6 border-t-[1px] border-border-default"
|
||||
class="upload-model-dialog flex flex-col justify-between gap-6 p-4 pt-6 border-t border-border-default"
|
||||
>
|
||||
<!-- Step 1: Enter URL -->
|
||||
<UploadModelUrlInput
|
||||
|
||||
@@ -46,6 +46,7 @@ interface DialogInstance<
|
||||
visible: boolean
|
||||
title?: string
|
||||
headerComponent?: H
|
||||
headerProps?: ComponentAttrs<H>
|
||||
component: B
|
||||
contentProps: ComponentAttrs<B>
|
||||
footerComponent?: F
|
||||
@@ -133,17 +134,11 @@ export const useDialogStore = defineStore('dialog', () => {
|
||||
updateCloseOnEscapeStates()
|
||||
}
|
||||
|
||||
function createDialog(options: {
|
||||
key: string
|
||||
title?: string
|
||||
headerComponent?: Component
|
||||
footerComponent?: Component
|
||||
component: Component
|
||||
props?: Record<string, any>
|
||||
footerProps?: Record<string, any>
|
||||
dialogComponentProps?: DialogComponentProps
|
||||
priority?: number
|
||||
}) {
|
||||
function createDialog<
|
||||
H extends Component = Component,
|
||||
B extends Component = Component,
|
||||
F extends Component = Component
|
||||
>(options: ShowDialogOptions<H, B, F> & { key: string }) {
|
||||
if (dialogStack.value.length >= 10) {
|
||||
dialogStack.value.shift()
|
||||
}
|
||||
@@ -159,6 +154,7 @@ export const useDialogStore = defineStore('dialog', () => {
|
||||
? markRaw(options.footerComponent)
|
||||
: undefined,
|
||||
component: markRaw(options.component),
|
||||
headerProps: { ...options.headerProps },
|
||||
contentProps: { ...options.props },
|
||||
footerProps: { ...options.footerProps },
|
||||
priority: options.priority ?? 1,
|
||||
|
||||
Reference in New Issue
Block a user