93 lines
2.9 KiB
Vue
93 lines
2.9 KiB
Vue
<script setup lang="ts">
|
|
import { t } from '@/i18n'
|
|
|
|
import { computed } from 'vue'
|
|
import ConfirmDialog from '@/components/ConfirmDialog.vue'
|
|
import MediaBadge from '@/components/MediaBadge.vue'
|
|
import VariantRemovalNote from '@/components/variants/VariantRemovalNote.vue'
|
|
import type { MediaItem } from '@/composables/useMedia'
|
|
import { pluralArticles } from '@/lib/mediaFormat'
|
|
|
|
const BROKEN_IMAGE = 'which will show a broken image.'
|
|
const FINAL_WARNING = "This can't be undone."
|
|
|
|
const props = defineProps<{
|
|
items: MediaItem[]
|
|
action: () => Promise<void | boolean>
|
|
}>()
|
|
|
|
const emit = defineEmits<{ close: [confirmed: boolean] }>()
|
|
|
|
const total = computed(() => props.items.length)
|
|
const imageLabel = computed(() => t(total.value === 1 ? '{0} image' : '{0} images', [total.value]))
|
|
const inUse = computed(() => props.items.filter((item) => item.used_in > 0))
|
|
const variantCount = computed(() =>
|
|
props.items.reduce((sum, item) => sum + (item.variant_count ?? 0), 0),
|
|
)
|
|
const variantBytes = computed(() =>
|
|
props.items.reduce((sum, item) => sum + (item.variant_size ?? 0), 0),
|
|
)
|
|
const articleCount = computed(() => inUse.value.reduce((sum, item) => sum + item.used_in, 0))
|
|
const description = computed(() => {
|
|
const usedCount = inUse.value.length
|
|
const unusedCount = total.value - usedCount
|
|
const articles = pluralArticles(articleCount.value)
|
|
if (usedCount === 0) {
|
|
return total.value === 1
|
|
? t("It isn't used in any article. {0}", [t(FINAL_WARNING)])
|
|
: t('None of them are used in any article. {0}', [t(FINAL_WARNING)])
|
|
}
|
|
if (unusedCount === 0) {
|
|
const subject = total.value === 1 ? t("It's") : t('All {0} are', [total.value])
|
|
return t('{0} used in {1}, {2} {3}', [subject, articles, t(BROKEN_IMAGE), t(FINAL_WARNING)])
|
|
}
|
|
const rest =
|
|
unusedCount === 1
|
|
? t("The other one isn't used anywhere.")
|
|
: t("The other {0} aren't used anywhere.", [unusedCount])
|
|
return t('{0} of them are used in {1}, {2} {3} {4}', [
|
|
usedCount,
|
|
articles,
|
|
t(BROKEN_IMAGE),
|
|
rest,
|
|
t(FINAL_WARNING),
|
|
])
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<ConfirmDialog
|
|
:title="t('Delete {0}?', [imageLabel])"
|
|
:description="description"
|
|
:confirm-label="t('Delete {0}', [imageLabel])"
|
|
:cancel-label="t('Cancel')"
|
|
:pending-label="t('Deleting…')"
|
|
tone="danger"
|
|
:action="action"
|
|
@close="emit('close', $event)"
|
|
>
|
|
<template #body>
|
|
<ul class="border border-default">
|
|
<li
|
|
v-for="(item, index) in items"
|
|
:key="item.id"
|
|
data-testid="bulk-delete-row"
|
|
class="flex min-h-9 items-center gap-2 px-3"
|
|
:class="{ 'border-t border-muted': index > 0 }"
|
|
>
|
|
<span class="min-w-0 flex-1 truncate text-highlighted">{{
|
|
item.filename
|
|
}}</span>
|
|
<MediaBadge
|
|
v-if="item.used_in > 0"
|
|
kind="used"
|
|
:label="t('Used in {0}', [item.used_in])"
|
|
/>
|
|
<MediaBadge v-else kind="unused" :label="t('Unused')" />
|
|
</li>
|
|
</ul>
|
|
<VariantRemovalNote :count="variantCount" :bytes="variantBytes" />
|
|
</template>
|
|
</ConfirmDialog>
|
|
</template>
|