import { watch, type Ref } from 'vue' import { useRoute, useRouter, type LocationQueryRaw } from 'vue-router' import { locale, t } from '@/i18n' import { useLocalizedOverlay } from '@/i18n/presentation' import AddTranslationDialog, { type AddTranslationResult, } from '@/components/AddTranslationDialog.vue' import type { Article, CoverageEntry } from '@/composables/useArticles' import { ADD_TRANSLATION_DIALOG as DIALOG_NAME } from '@/lib/addTranslationLocation' import { holds } from '@/lib/editorCapabilities' import type { VersionRow } from '@/lib/editorVersions' import { languageName, type SiteLanguage } from '@/lib/siteLanguages' interface TranslationOptions { article: Ref
loaded: Ref languages: () => SiteLanguage[] refetchLanguages: () => Promise switchTo: (row: VersionRow, announcement?: string) => Promise onGone: () => void } function versionRowFor(id: number, lang: string): VersionRow { return { key: `version-${id}`, lang, name: languageName(lang, locale.value), code: lang.toUpperCase(), articleId: id, title: '', current: false, online: false, readOnly: false, languageDisabled: false, addTranslation: false, } } function entryOf(created: Article, lang: string): CoverageEntry { return { id: created.id, lang, title: created.title, is_online: created.is_online, language_enabled: true, capabilities: created.capabilities, } } export function useEditorTranslation(options: TranslationOptions) { const route = useRoute() const router = useRouter() const overlay = useLocalizedOverlay() let instance: ReturnType | null = null function strippedQuery(): LocationQueryRaw { const rest = { ...route.query } delete rest.dialog delete rest.lang return rest } function stripParameters() { if (route.query.dialog !== undefined || route.query.lang !== undefined) { return router.replace({ query: strippedQuery() }) } return undefined } function open(lang?: string) { return router.push({ query: { ...route.query, dialog: DIALOG_NAME, ...(lang ? { lang } : {}) }, }) } async function settle(result: AddTranslationResult | undefined) { if (!result) { await stripParameters() return } if (result.kind === 'gone') { await stripParameters() options.onGone() return } await stripParameters() if (result.kind === 'open') { await options.switchTo(versionRowFor(result.id, result.lang)) return } const current = options.article.value if (current) { options.article.value = { ...current, translations: [ ...(current.translations ?? []), entryOf(result.article, result.lang), ], } } const name = languageName(result.lang, locale.value) await options.switchTo( versionRowFor(result.article.id, result.lang), t('{0} draft created', [name]), ) } async function show(lang: string | undefined) { const created = overlay.create(AddTranslationDialog, { props: { get article() { return options.article.value! }, get languages() { return options.languages() }, initialLang: lang, refetchLanguages: options.refetchLanguages, }, }) instance = created const result = (await created.open()) as AddTranslationResult | undefined instance = null await settle(result) } watch( () => [route.query.dialog, route.query.lang, options.loaded.value] as const, ([dialog, lang, loaded]) => { if (!loaded) { return } if (dialog !== DIALOG_NAME) { instance?.close() return } if (!holds(options.article.value?.capabilities, 'create_translation')) { stripParameters() return } if (!instance) { show(typeof lang === 'string' ? lang : undefined) } }, { immediate: true }, ) return { open } }