import { t } from '@/i18n' import type { MediaUsageItem, UsageState } from '@/composables/useMedia' import { describeCell, plainCellText } from '@/lib/entryCells' import { pluralArticles } from '@/lib/mediaFormat' const ENTRY_ROWS_SHOWN = 3 const ARTICLE_TYPE = 'article' const ENTRY_TYPE = 'entry' export interface UsageArticle { id: number title: string published: boolean } export interface UsageEntry { id: number key: string typeName: string title: string } export interface UsageSplit { articles: UsageArticle[] entries: UsageEntry[] entryCount: number more: number } export function pluralEntries(count: number) { return t(count === 1 ? '1 entry' : '{0} entries', [count]) } export function usageEntryTitle(item: MediaUsageItem) { const fallback = t('Entry {0}', [item.id]) const first = item.first_field if (!first) { return fallback } const cell = describeCell( { key: first.key, label: first.key, type: first.type, required: false, unique: false, default: null, min: null, max: null, options: null, }, first.value, ) return cell.kind === 'empty' || cell.kind === 'thumbnail' || cell.kind === 'relation' ? fallback : plainCellText(cell) } function toEntry(item: MediaUsageItem): UsageEntry { return { id: item.id, key: item.content_type_key ?? '', typeName: item.content_type_name ?? '', title: usageEntryTitle(item), } } export function splitUsage(items: MediaUsageItem[]): UsageSplit { const articles = items .filter((item) => item.type === undefined || item.type === ARTICLE_TYPE) .map((item) => ({ id: item.id, title: item.title ?? '', published: item.published === true, })) const entryItems = items.filter((item) => item.type === ENTRY_TYPE) return { articles, entries: entryItems.slice(0, ENTRY_ROWS_SHOWN).map(toEntry), entryCount: entryItems.length, more: Math.max(0, entryItems.length - ENTRY_ROWS_SHOWN), } } export function tooltipLines(items: MediaUsageItem[]) { const split = splitUsage(items) return [ split.articles.length > 0 ? t('Used in articles: {0}', [split.articles.length]) : '', split.entryCount > 0 ? t('Used in entries: {0}', [split.entryCount]) : '', ].filter(Boolean) } export function usageSplitOf(state: UsageState | null) { return state?.status === 'ready' ? splitUsage(state.items) : null } function inUseDescription(filename: string, split: UsageSplit | null) { const articles = split?.articles.length ?? 0 const entries = split?.entryCount ?? 0 if (articles > 0 && entries > 0) { return t( "\u0022{0}\u0022 is used in {1} and {2}. Those entry fields will show \u0022This image is no longer in the library\u0022, and the articles will show a broken image. This can't be undone.", [filename, pluralEntries(entries), pluralArticles(articles)], ) } if (articles > 0) { return t( "\u0022{0}\u0022 is used in {1}. If you delete it, they will show a broken image. This can't be undone.", [filename, pluralArticles(articles)], ) } if (entries > 0) { return t( "\u0022{0}\u0022 is used in {1}. Those entry fields will show \u0022This image is no longer in the library\u0022. This can't be undone.", [filename, pluralEntries(entries)], ) } return t( "\u0022{0}\u0022 is in use. Articles will show a broken image and entry fields will show \u0022This image is no longer in the library\u0022. This can't be undone.", [filename], ) } export function deleteCopy(filename: string, usedIn: number, state: UsageState | null) { if (usedIn <= 0) { return { title: t('Delete this image?'), description: t( "\u0022{0}\u0022 will be deleted from your library. No article uses it. This can't be undone.", [filename], ), split: null, } } const split = usageSplitOf(state) const known = split !== null && (split.articles.length > 0 || split.entryCount > 0) return { title: t("Delete an image that's in use?"), description: inUseDescription(filename, known ? split : null), split: known ? split : null, } }