@webx-ui/module-inbox 0.8.1 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FieldDialog.d.ts +5 -1
- package/dist/FormEditorPage-C3ULFulJ.js +843 -0
- package/dist/FormEditorPage-C3ULFulJ.js.map +1 -0
- package/dist/FormNotifications.d.ts +19 -13
- package/dist/{InboxPage-CCYXnZed.js → InboxPage-DsYFI3g9.js} +2 -2
- package/dist/{InboxPage-CCYXnZed.js.map → InboxPage-DsYFI3g9.js.map} +1 -1
- package/dist/{StatusesPage-Mra8TB7G.js → StatusesPage-DIrk5z13.js} +2 -2
- package/dist/{StatusesPage-Mra8TB7G.js.map → StatusesPage-DIrk5z13.js.map} +1 -1
- package/dist/{SubmissionPage-DVNKYpWH.js → SubmissionPage-BUd7Gd7d.js} +176 -208
- package/dist/SubmissionPage-BUd7Gd7d.js.map +1 -0
- package/dist/index-CZWksX_k.js +1799 -0
- package/dist/index-CZWksX_k.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/style.css +1 -1
- package/dist/types.d.ts +16 -3
- package/package.json +3 -3
- package/dist/FormEditorPage-BoHzlFfz.js +0 -786
- package/dist/FormEditorPage-BoHzlFfz.js.map +0 -1
- package/dist/SubmissionPage-DVNKYpWH.js.map +0 -1
- package/dist/index-BQj2UlUS.js +0 -1735
- package/dist/index-BQj2UlUS.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FormEditorPage-BoHzlFfz.js","sources":["../src/FormAntispam.vue","../src/FormEmbed.vue","../src/FormGeneral.vue","../src/recipients.ts","../src/FormNotifications.vue","../src/FormEditorPage.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport {\n WxAlert,\n WxCard,\n WxFormItem,\n WxInputNumber,\n WxSelect,\n WxSwitch,\n WxText,\n} from '@webx-ui/core'\nimport { option } from './options'\nimport type { CaptchaProvider, CaptchaSite, FormOptions } from './types'\n\n/**\n * The four layers in front of the door (§7), as the three anybody would want to change.\n *\n * The origin check is not here: it is not a dial, it is a fact about where the site is served\n * from, and it lives in the configuration with the rest of the deployment. The captcha keys\n * are not here either — they are the site's, one pair for every form, and a secret repeated\n * in each form's settings is a secret scattered over rows (§5).\n *\n * What is here is what the site has, under the select: a reCAPTCHA key of the wrong kind is\n * the widget's \"Invalid key type\" and nothing else, and the select alone gives an editor no\n * way of knowing which kind the site expects.\n */\nconst options = defineModel<FormOptions>({ required: true })\n\nconst props = defineProps<{\n /** From the form as the server sent it; absent on a server older than this. */\n site?: Record<CaptchaProvider, CaptchaSite>\n}>()\n\nconst t = useTranslate('webx-inbox')\n\nconst honeypot = option<boolean>(options, 'antispam.honeypot', true)\nconst seconds = option<number>(options, 'antispam.min_seconds', 3)\nconst throttle = option<number>(options, 'antispam.throttle', 5)\nconst captcha = option<string>(options, 'antispam.captcha', 'off')\n\nconst captchas = computed(() => [\n { value: 'off', label: t('panel.captcha-off') },\n { value: 'recaptcha', label: t('panel.captcha-recaptcha') },\n { value: 'turnstile', label: t('panel.captcha-turnstile') },\n])\n\n/** The provider chosen and what the site has for it, or null for none. */\nconst chosen = computed(() => {\n const provider = captcha.value\n\n if (provider !== 'recaptcha' && provider !== 'turnstile') return null\n\n return { provider, site: props.site?.[provider] ?? null }\n})\n\nconst kind = computed(() => {\n const site = chosen.value?.site\n\n return site ? t(`panel.captcha-${chosen.value!.provider}-${site.type}`) : null\n})\n</script>\n\n<template>\n <wx-card>\n <wx-form-item :help=\"t('panel.honeypot-help')\">\n <wx-switch v-model=\"honeypot\" :label=\"t('panel.honeypot')\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.min-seconds')\" :help=\"t('panel.min-seconds-help')\">\n <wx-input-number v-model=\"seconds\" :min=\"0\" :max=\"120\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.throttle')\" :help=\"t('panel.throttle-help')\">\n <wx-input-number v-model=\"throttle\" :min=\"0\" :max=\"120\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.captcha')\" :help=\"t('panel.captcha-keys')\">\n <wx-select v-model=\"captcha\" :options=\"captchas\" />\n </wx-form-item>\n\n <wx-text v-if=\"kind\" size=\"sm\" tone=\"muted\">{{ kind }}</wx-text>\n\n <wx-alert\n v-if=\"chosen?.site && !chosen.site.configured\"\n type=\"warning\"\n variant=\"soft\"\n :closable=\"false\"\n :description=\"t('panel.captcha-unconfigured')\"\n />\n </wx-card>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useAdmin, useTranslate } from '@webx-ui/module-admin'\nimport { toast, WxAction, WxCard, WxTable, WxText, type TableColumn } from '@webx-ui/core'\nimport { useInboxMessages } from './i18n'\nimport type { InboxField, InboxForm } from './types'\n\n/**\n * How the form gets onto a page.\n *\n * Two answers and both are one line, because the module's whole public half is one tag (§10):\n * a template prints it, and a block type prints the same thing so that an editor never opens\n * a template at all.\n *\n * Under them, the names. A hidden field is filled in by the page it stands on — the address\n * somebody wrote from, the product they were looking at, the campaign that brought them — and\n * the only way to fill one in is to know what it is called (§2.6).\n *\n * Where a block's template lives depends on the site: with `module-blocks` it is written in\n * the panel's Blocks section, and a hint pointing at `resources/views/blocks/…` sent people\n * looking for a file that is not there. Without it, a block type is the site's own view.\n */\nconst props = defineProps<{ form: InboxForm; slug: string; fields: InboxField[] }>()\n\nuseInboxMessages()\nconst t = useTranslate('webx-inbox')\nconst admin = useAdmin()\n\nconst hasBlocks = computed(\n () => admin.state.manifest?.modules.some((module) => module.id === 'blocks') ?? false,\n)\n\nconst blade = computed(() => `<x-webx-inbox::form slug=\"${props.slug}\" />`)\n\nconst block = computed(() =>\n hasBlocks.value\n ? blade.value\n : `{{-- resources/views/blocks/contact.blade.php --}}\\n<x-webx-inbox::form slug=\"${props.slug}\" />`,\n)\n\n/** The first hidden field, so the example fills a name this form actually has. */\nconst hidden = computed(\n () => props.fields.find((field) => field.type === 'hidden' && field.is_enabled)?.key ?? 'page',\n)\n\nconst extras = computed(\n () =>\n `<x-webx-inbox::form slug=\"${props.slug}\" :values=\"['${hidden.value}' => url()->current()]\" />\\n` +\n `<x-webx-inbox::form slug=\"${props.slug}\" placement=\"footer\" />`,\n)\n\nconst columns = computed<TableColumn<InboxField>[]>(() => [\n { key: 'key', label: t('fields.name') },\n { key: 'title', label: t('fields.title') },\n { key: 'type', label: t('fields.type'), hideBelow: 520 },\n])\n\n/** Only the ones a page can actually fill in or a visitor can actually answer. */\nconst listed = computed(() => props.fields.filter((field) => field.is_enabled))\n\nasync function copy(text: string): Promise<void> {\n try {\n await navigator.clipboard.writeText(text)\n toast.success(t('panel.copied'))\n } catch {\n // A browser that refuses the clipboard — an insecure origin, a denied permission — still\n // shows the line, and selecting it by hand is what anybody does next anyway.\n }\n}\n</script>\n\n<template>\n <div class=\"wx-inbox-embed\">\n <wx-card :title=\"t('panel.embed-blade')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.embed-blade-help') }}</wx-text>\n\n <div class=\"wx-inbox-embed__snippet\">\n <code>{{ blade }}</code>\n <wx-action icon=\"copy\" :title=\"t('panel.copy')\" @click=\"copy(blade)\" />\n </div>\n </wx-card>\n\n <wx-card :title=\"t('panel.embed-block')\">\n <wx-text size=\"sm\" tone=\"muted\">\n {{ t(hasBlocks ? 'panel.embed-block-panel-help' : 'panel.embed-block-help') }}\n </wx-text>\n\n <div class=\"wx-inbox-embed__snippet\">\n <code>{{ block }}</code>\n <wx-action icon=\"copy\" :title=\"t('panel.copy')\" @click=\"copy(block)\" />\n </div>\n </wx-card>\n\n <wx-card :title=\"t('panel.embed-extras')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.embed-extras-help') }}</wx-text>\n\n <div class=\"wx-inbox-embed__snippet\">\n <code>{{ extras }}</code>\n <wx-action icon=\"copy\" :title=\"t('panel.copy')\" @click=\"copy(extras)\" />\n </div>\n </wx-card>\n\n <wx-card :title=\"t('panel.embed-names')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.embed-names-help') }}</wx-text>\n\n <wx-table\n :data=\"listed\"\n :columns=\"columns\"\n row-key=\"id\"\n flush\n :empty-text=\"t('fields.no-fields')\"\n >\n <template #cell-key=\"{ row }\">\n <wx-text mono size=\"sm\">fields[{{ row.key }}]</wx-text>\n </template>\n\n <template #cell-title=\"{ row }\">\n {{ Object.values(row.title)[0] ?? row.key }}\n </template>\n\n <template #cell-type=\"{ row }\">\n {{ t(`fields.type-${row.type}`) }}\n </template>\n </wx-table>\n </wx-card>\n </div>\n</template>\n\n<style scoped>\n.wx-inbox-embed {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n}\n\n.wx-inbox-embed__snippet {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n margin-top: var(--wx-space-12);\n padding: var(--wx-space-10) var(--wx-space-12);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-subtle);\n}\n\n.wx-inbox-embed__snippet code {\n flex: 1 1 auto;\n min-width: 0;\n overflow-x: auto;\n white-space: pre;\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-sm);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxCard, WxFormItem, WxInput, WxSwitch, type LocalizedValue } from '@webx-ui/core'\nimport LocalizedRichText from './LocalizedRichText.vue'\nimport { option } from './options'\nimport type { FormOptions } from './types'\n\n/**\n * What the form is, and what it says once it has been sent.\n *\n * The two halves are on two cards because they are read at two different times: the first is\n * set up once, the second is the sentence a visitor sees and is rewritten whenever the\n * marketing does.\n */\ndefineProps<{ errors: Record<string, string[]> }>()\n\nconst settings = defineModel<{ slug: string; title: LocalizedValue; is_enabled: boolean }>(\n 'settings',\n { required: true },\n)\n\nconst options = defineModel<FormOptions>('options', { required: true })\n\nconst t = useTranslate('webx-inbox')\n\nconst heading = option<LocalizedValue>(options, 'thank-you.heading', {})\nconst text = option<LocalizedValue>(options, 'thank-you.text', {})\nconst submit = option<LocalizedValue>(options, 'design.submit-text', {})\nconst redirect = option<string>(options, 'redirect', '')\n</script>\n\n<template>\n <div class=\"wx-inbox-general\">\n <wx-card>\n <wx-form-item :label=\"t('panel.title')\" :error=\"errors.title?.[0]\" required>\n <wx-input v-model=\"settings.title\" localized />\n </wx-form-item>\n\n <wx-form-item\n :label=\"t('panel.slug')\"\n :help=\"t('panel.slug-help')\"\n :error=\"errors.slug?.[0]\"\n required\n >\n <wx-input v-model=\"settings.slug\" placeholder=\"contact\" />\n </wx-form-item>\n\n <wx-form-item :help=\"t('panel.is-enabled-help')\">\n <wx-switch v-model=\"settings.is_enabled\" :label=\"t('panel.is-enabled')\" />\n </wx-form-item>\n </wx-card>\n\n <wx-card :title=\"t('panel.after-sending')\">\n <wx-form-item :label=\"t('panel.submit-text')\">\n <wx-input v-model=\"submit\" localized />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.thank-you-heading')\">\n <wx-input v-model=\"heading\" localized />\n </wx-form-item>\n\n <!-- Printed raw on the site, which is why it is written where formatting is possible. -->\n <wx-form-item :label=\"t('panel.thank-you-text')\">\n <localized-rich-text v-model=\"text\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.redirect')\" :help=\"t('panel.redirect-help')\">\n <wx-input v-model=\"redirect\" placeholder=\"/thank-you\" />\n </wx-form-item>\n </wx-card>\n </div>\n</template>\n\n<style scoped>\n.wx-inbox-general {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n}\n</style>\n","import type { Recipient, RecipientProblem, RecipientState } from './types'\n\n/**\n * Whether a letter would reach somebody, judged on the recipients as they stand in the editor.\n *\n * The server says it for what was saved (`InboxForm.recipients`): who is deleted, who is\n * switched off. The editor has to say it before a save too, so this reads the list being edited\n * and borrows the server's verdict only for the administrators it already knows about — one\n * picked a moment ago from the list of people who may read the section is somebody who exists.\n */\n\n/** Loose on purpose: the server checks the address for real, this only spots an empty line. */\nconst ADDRESS = /^[^\\s@]+@[^\\s@]+$/\n\nexport function isAdmin(recipient: Recipient): recipient is { admin_id: number } {\n return 'admin_id' in recipient\n}\n\n/** Why this recipient would not get a letter, or null when it would. */\nexport function problemOf(\n recipient: Recipient,\n reported: RecipientState[] = [],\n): RecipientProblem | null {\n if (isAdmin(recipient)) {\n const known = reported.find(\n (one) => one.type === 'admin' && one.admin_id === recipient.admin_id,\n )\n\n return known?.problem ?? null\n }\n\n return ADDRESS.test((recipient.email ?? '').trim()) ? null : 'invalid_email'\n}\n\n/** Whether anybody on the list would be written to. */\nexport function reachesAnybody(\n recipients: Recipient[] | undefined,\n reported: RecipientState[] = [],\n): boolean {\n return (recipients ?? []).some((recipient) => problemOf(recipient, reported) === null)\n}\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref } from 'vue'\nimport { useRouter } from 'vue-router'\nimport { useAdmin, useTranslate, WxRelationsField } from '@webx-ui/module-admin'\nimport {\n confirm,\n WxAction,\n WxAlert,\n WxButton,\n WxIcon,\n WxCard,\n WxFormItem,\n WxInput,\n WxLink,\n WxSelect,\n WxSpace,\n WxText,\n} from '@webx-ui/core'\nimport { createInboxApi } from './api'\nimport { option } from './options'\nimport { isAdmin, problemOf } from './recipients'\nimport type { FormOptions, InboxField, InboxRecipient, Recipient, RecipientState } from './types'\n\n/**\n * Who hears that something arrived (§9).\n *\n * Two kinds of recipient and they are not interchangeable. An administrator is written to at\n * the address on their account and in the language they keep the panel in, so changing either\n * changes it everywhere; a typed address is written to in the language the submission came in.\n * The list offered is not every administrator but the ones who may open a submission — a\n * notification is a link, and sending one to somebody who gets a 403 looks like the panel is\n * broken rather than like the form is.\n *\n * Beside the letter, and never instead of it: the channels of the notifications module, when it\n * is installed (NOTIFICATIONS §15.2) — a Telegram chat, another letter with its own template.\n * The picker asks the event's target on the server for names, so this package needs nothing of\n * that module's code; a site without it never sees the card.\n */\nconst props = defineProps<{\n fields: InboxField[]\n errors: Record<string, string[]>\n /** What the server said about the saved list: who is deleted or switched off. */\n reported?: RecipientState[]\n /** Whether the notifications module is installed — the server says so on the form. */\n notifications?: boolean\n}>()\n\nconst options = defineModel<FormOptions>({ required: true })\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\nconst t = useTranslate('webx-inbox')\n\nconst admins = ref<InboxRecipient[]>([])\n\nconst recipients = option<Recipient[]>(options, 'recipients', [])\nconst emailField = option<string>(options, 'email_field', '')\nconst channels = option<number[]>(options, 'notify_channels', [])\n\nconst router = useRouter()\n\n/* The channels are set up in their own section; only somebody who may do it gets the way there. */\nconst canSetUp = computed(() => context.can('notifications.manage'))\nconst channelsLink = computed(() => `${context.basePath}/notifications`.replace(/\\/{2,}/g, '/'))\n\n/* Inside the panel, without loading it again: the address is for a middle click. */\nfunction setUpChannels(event: MouseEvent): void {\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.button !== 0) return\n\n event.preventDefault()\n void router.push('/notifications')\n}\n\nonMounted(async () => {\n try {\n admins.value = await api.recipients()\n } catch {\n // Only the shortcut is gone: an address can still be typed, and that is the half of this\n // that has to work.\n }\n})\n\nconst adminOptions = computed(() =>\n admins.value.map((admin) => ({ value: admin.id, label: `${admin.name} · ${admin.email}` })),\n)\n\n/** The fields that could hold the sender's address, plus the option of naming none. */\nconst emailOptions = computed(() => [\n { value: '', label: t('panel.no-email-field') },\n ...props.fields\n .filter((field) => field.type === 'email')\n .map((field) => ({ value: field.key, label: field.key })),\n])\n\n/*\n * Only the administrators' problems are said beside the row: an address being typed is not\n * wrong yet, and the server refuses a bad one on save in words of its own.\n */\nfunction adminProblem(recipient: Recipient): string | null {\n if (!isAdmin(recipient)) return null\n\n const problem = problemOf(recipient, props.reported)\n\n return problem === null ? null : t(`panel.recipient-${problem}`)\n}\n\nfunction add(recipient: Recipient): void {\n recipients.value = [...recipients.value, recipient]\n}\n\n/**\n * A recipient goes behind a question, unless there is nothing there to lose.\n *\n * The row that was just added and never filled in is a blank line, and asking about a blank\n * line teaches the reader to click through the question without reading it — which is the\n * one thing a confirmation must not do.\n */\nasync function remove(index: number): Promise<void> {\n const recipient = recipients.value[index]\n const written =\n recipient !== undefined && (isAdmin(recipient) || (recipient.email ?? '').trim() !== '')\n\n if (written) {\n const agreed = await confirm({\n title: t('panel.remove-recipient-title'),\n message: t('panel.remove-recipient-text'),\n confirmText: t('panel.remove'),\n cancelText: t('panel.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n }\n\n recipients.value = recipients.value.filter((_, at) => at !== index)\n}\n\nfunction setAdmin(index: number, id: number): void {\n recipients.value = recipients.value.map((one, at) => (at === index ? { admin_id: id } : one))\n}\n\nfunction setEmail(index: number, email: string): void {\n recipients.value = recipients.value.map((one, at) => (at === index ? { email } : one))\n}\n</script>\n\n<template>\n <div class=\"wx-inbox-notifications\">\n <wx-card :title=\"t('panel.recipients')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.recipients-help') }}</wx-text>\n\n <wx-alert\n v-if=\"errors['options.recipients']\"\n type=\"danger\"\n variant=\"soft\"\n :description=\"errors['options.recipients']?.[0]\"\n />\n\n <div class=\"wx-inbox-recipients\">\n <wx-text v-if=\"recipients.length === 0\" size=\"sm\" tone=\"placeholder\">\n {{ t('panel.no-recipients') }}\n </wx-text>\n\n <div\n v-for=\"(recipient, index) in recipients\"\n :key=\"index\"\n class=\"wx-inbox-recipients__item\"\n >\n <div class=\"wx-inbox-recipients__row\">\n <wx-select\n v-if=\"isAdmin(recipient)\"\n :model-value=\"recipient.admin_id\"\n :options=\"adminOptions\"\n @update:model-value=\"(id) => setAdmin(index, Number(id))\"\n />\n <wx-input\n v-else\n :model-value=\"recipient.email\"\n type=\"email\"\n placeholder=\"sales@example.com\"\n @update:model-value=\"(email) => setEmail(index, String(email))\"\n />\n\n <!-- Red, like every other way of taking something away in the panel: the colour is\n what tells the two buttons of a row apart before either is read. -->\n <wx-action\n icon=\"trash\"\n tone=\"danger\"\n :title=\"t('panel.remove')\"\n @click=\"remove(index)\"\n />\n </div>\n <wx-text v-if=\"adminProblem(recipient)\" size=\"sm\" tone=\"danger\">\n {{ adminProblem(recipient) }}\n </wx-text>\n </div>\n </div>\n\n <wx-space size=\"sm\">\n <wx-button\n variant=\"outline\"\n icon=\"user\"\n :disabled=\"adminOptions.length === 0\"\n @click=\"add({ admin_id: Number(adminOptions[0]?.value) })\"\n >\n {{ t('panel.add-admin') }}\n </wx-button>\n <wx-button variant=\"outline\" @click=\"add({ email: '' })\">\n <template #icon><wx-icon name=\"mail\" /></template>\n {{ t('panel.add-email') }}\n </wx-button>\n </wx-space>\n\n <wx-form-item\n :label=\"t('panel.email-field')\"\n :help=\"t('panel.email-field-help')\"\n :error=\"errors['options.email_field']?.[0]\"\n >\n <wx-select v-model=\"emailField\" :options=\"emailOptions\" />\n </wx-form-item>\n </wx-card>\n\n <wx-card v-if=\"props.notifications\" :title=\"t('panel.notify-through')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.notify-through-help') }}</wx-text>\n\n <div class=\"wx-inbox-channels\">\n <wx-relations-field\n v-model=\"channels\"\n target=\"notify-inbox-submission\"\n :sortable=\"false\"\n :add-text=\"t('panel.pick-channels')\"\n :empty-text=\"t('panel.no-channels')\"\n />\n <wx-link v-if=\"canSetUp\" :href=\"channelsLink\" size=\"sm\" @click=\"setUpChannels\">{{\n t('panel.set-up-channels')\n }}</wx-link>\n </div>\n </wx-card>\n </div>\n</template>\n\n<style scoped>\n/* The letter and the channels: two cards, the panel's step between them. */\n.wx-inbox-notifications {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n}\n\n/*\n * As wide as a field, because that is what each row is: an address is typed into it and read\n * back off it. The rows are not form items — one of them is a select, the next an input, and\n * both carry a bin — so the cap that a form item applies has to be said here.\n */\n.wx-inbox-recipients {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n margin-block: var(--wx-space-12);\n max-width: var(--wx-field-max-width, 640px);\n}\n\n.wx-inbox-channels {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--wx-space-8);\n margin-block-start: var(--wx-space-12);\n max-width: var(--wx-field-max-width, 640px);\n}\n\n.wx-inbox-channels > :first-child {\n align-self: stretch;\n}\n\n.wx-inbox-recipients__item {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n}\n\n.wx-inbox-recipients__row {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n}\n\n.wx-inbox-recipients__row > :first-child {\n flex: 1 1 auto;\n min-width: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, reactive, ref, watch } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport { useAdmin, useErrorText, useTranslate, WxScreenHead } from '@webx-ui/module-admin'\nimport {\n localizedValue,\n toast,\n useLocales,\n WxActionBar,\n WxAlert,\n WxBadge,\n WxButton,\n WxCard,\n WxSkeleton,\n WxTab,\n WxTabs,\n type LocalizedValue,\n} from '@webx-ui/core'\nimport FieldList from './FieldList.vue'\nimport FormAntispam from './FormAntispam.vue'\nimport FormEmbed from './FormEmbed.vue'\nimport FormGeneral from './FormGeneral.vue'\nimport FormNotifications from './FormNotifications.vue'\nimport { createInboxApi } from './api'\nimport { reachesAnybody } from './recipients'\nimport { useInboxMessages } from './i18n'\nimport type { FormOptions, InboxField, InboxForm, Recipient } from './types'\n\n/**\n * One form: what it is called, what it asks, who hears about it, and how it is put on a page.\n *\n * Five tabs and one save. The fields are the exception — a question is written in its own\n * dialog and saved on its own, because it is a row with an identity (§2.1) and because a\n * dragged order that waited for a save button would be an order nobody trusts.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/inbox' })\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\nconst route = useRoute()\nconst router = useRouter()\nconst locales = useLocales()\nuseInboxMessages()\n\nconst t = useTranslate('webx-inbox')\n/* Not the server's `message`: the panel says how a request failed in its own words. */\nconst message = useErrorText()\n\nconst form = ref<InboxForm | null>(null)\nconst fields = ref<InboxField[]>([])\nconst loading = ref(true)\nconst saving = ref(false)\nconst errors = ref<Record<string, string[]>>({})\n\nconst settings = reactive<{ slug: string; title: LocalizedValue; is_enabled: boolean }>({\n slug: '',\n title: {},\n is_enabled: true,\n})\n\nconst options = ref<FormOptions>({})\n\nconst TABS = ['general', 'fields', 'notifications', 'antispam', 'embed']\n\n/* Opened on the tab the address names, so the audit's \"open\" lands on the recipients. */\nconst tab = ref(TABS.includes(String(route.query.tab)) ? String(route.query.tab) : 'general')\n\n/*\n * Said above the tabs and not only inside Notifications: a form that tells nobody works in\n * every way somebody can see — the site thanks the visitor, the panel keeps the enquiry — so\n * the only place the gap shows is a line nobody went looking for.\n */\nconst silent = computed(\n () =>\n settings.is_enabled &&\n !reachesAnybody(options.value.recipients as Recipient[] | undefined, form.value?.recipients) &&\n !channelsSend.value,\n)\n\n/*\n * A channel chosen and switched on tells somebody too. One chosen since the form was loaded is\n * taken at its word until the save says otherwise: the server names only what was saved.\n */\nconst channelsSend = computed(() => {\n if (form.value?.notifications !== true) return false\n\n const reported = form.value.channels ?? []\n\n return (options.value.notify_channels ?? []).some(\n (id) => reported.find((channel) => channel.id === id)?.sends ?? true,\n )\n})\n\nconst canManage = computed(() => context.can('inbox.manage'))\n\nconst id = computed(() => Number(route.params.id))\n\nconst name = computed(() =>\n form.value === null ? '' : localizedValue(settings.title, locales.active.value, settings.slug),\n)\n\n/** Where a submission would come back to: the section, with this form already chosen. */\nconst backTo = computed(() => `${props.base}?form=${id.value}`)\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n const loaded = await api.form(id.value)\n\n form.value = loaded\n fields.value = loaded.fields ?? []\n settings.slug = loaded.slug\n settings.title = { ...loaded.title }\n settings.is_enabled = loaded.is_enabled\n options.value = { ...loaded.options }\n } catch (error) {\n toast.danger(message(error))\n void router.replace(props.base)\n } finally {\n loading.value = false\n }\n}\n\nwatch(id, () => void load(), { immediate: true })\n\nasync function save(): Promise<void> {\n saving.value = true\n errors.value = {}\n\n try {\n const saved = await api.saveForm(id.value, {\n slug: settings.slug.trim(),\n title: settings.title,\n is_enabled: settings.is_enabled,\n options: options.value,\n })\n\n form.value = saved\n toast.success(t('panel.saved'))\n } catch (error) {\n const body = (error as { body?: { errors?: Record<string, string[]> } }).body\n\n if (body?.errors) {\n errors.value = body.errors\n toast.danger(t('panel.failed'))\n } else {\n toast.danger(message(error))\n }\n } finally {\n saving.value = false\n }\n}\n</script>\n\n<template>\n <!--\n Not a screen that fills its column, whatever the first draft said. `data-wx-fill` makes the\n screen exactly as tall as the window, and nothing inside these tabs scrolls on its own — so\n a form longer than the window grew straight through the box, and the save bar, which is the\n next thing in the column, was drawn across the middle of it with fields still going on\n underneath. What this screen wants is the ordinary thing: the page scrolls, the bar sticks\n to the bottom of it, and `WxMain` gives the screen a floor to push that bar down to.\n -->\n <div class=\"wx-inbox-editor\">\n <!-- On a card, like everything else on this screen: a bare skeleton flush against the\n page is a shape the form that follows it never takes, so the screen jumps twice —\n once when the card appears around it, once when the fields land inside. -->\n <wx-card v-if=\"loading\">\n <wx-skeleton title :rows=\"8\" />\n </wx-card>\n\n <template v-else-if=\"form\">\n <wx-screen-head\n class=\"wx-inbox-editor__head\"\n :title=\"name\"\n :subtitle=\"form.slug\"\n :back=\"backTo\"\n :back-label=\"t('panel.forms')\"\n >\n <template #title-after>\n <wx-badge v-if=\"!settings.is_enabled\" type=\"default\">{{ t('panel.off') }}</wx-badge>\n </template>\n </wx-screen-head>\n\n <!--\n Every tab is mounted at once and the hidden ones keep their state: somebody who wrote\n a thank-you, went to look at the fields and came back should find it still written.\n -->\n <wx-alert\n v-if=\"silent\"\n class=\"wx-inbox-editor__silent\"\n type=\"warning\"\n variant=\"soft\"\n :closable=\"false\"\n :title=\"t('panel.notifies-nobody')\"\n :description=\"t('panel.notifies-nobody-text')\"\n />\n\n <wx-tabs v-model=\"tab\" class=\"wx-inbox-editor__tabs\" keep-alive>\n <wx-tab value=\"general\" :label=\"t('panel.tab-general')\">\n <form-general v-model:settings=\"settings\" v-model:options=\"options\" :errors=\"errors\" />\n </wx-tab>\n\n <wx-tab value=\"fields\" :label=\"t('panel.tab-fields')\">\n <field-list v-model=\"fields\" :form=\"form\" :can-manage=\"canManage\" />\n </wx-tab>\n\n <wx-tab value=\"notifications\" :label=\"t('panel.tab-notifications')\">\n <form-notifications\n v-model=\"options\"\n :fields=\"fields\"\n :errors=\"errors\"\n :reported=\"form.recipients\"\n :notifications=\"form.notifications\"\n />\n </wx-tab>\n\n <wx-tab value=\"antispam\" :label=\"t('panel.tab-antispam')\">\n <form-antispam v-model=\"options\" :site=\"form.captcha\" />\n </wx-tab>\n\n <wx-tab value=\"embed\" :label=\"t('panel.tab-embed')\">\n <form-embed :form=\"form\" :slug=\"settings.slug\" :fields=\"fields\" />\n </wx-tab>\n </wx-tabs>\n\n <wx-action-bar v-if=\"canManage\">\n <wx-button type=\"primary\" :loading=\"saving\" @click=\"save\">{{ t('panel.save') }}</wx-button>\n </wx-action-bar>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-inbox-editor {\n display: flex;\n flex-direction: column;\n /* The panel's own step, which is smaller on a phone than on a desktop. */\n gap: var(--wx-gap, var(--wx-space-16));\n}\n\n/* The tabs take what is left of the column, so the save bar under them is at its bottom\n rather than under the last field. Nothing inside them scrolls on its own — the page does. */\n/* The address it posts to, in the type an address is written in. */\n.wx-inbox-editor__head :deep(.wx-screen-head__subtitle) {\n font-family: var(--wx-font-family-mono);\n}\n\n.wx-inbox-editor__tabs {\n flex: 1 1 auto;\n}\n</style>\n"],"names":["options","_useModel","__props","props","t","useTranslate","honeypot","option","seconds","throttle","captcha","captchas","computed","chosen","provider","kind","site","_createBlock","_unref","WxCard","_createVNode","WxFormItem","WxSwitch","$event","WxInputNumber","WxSelect","WxText","WxAlert","useInboxMessages","admin","useAdmin","hasBlocks","module","blade","block","hidden","field","extras","columns","listed","copy","text","toast","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","WxAction","_cache","_createTextVNode","_toDisplayString","_hoisted_3","_hoisted_4","WxTable","_withCtx","row","settings","heading","submit","redirect","WxInput","LocalizedRichText","ADDRESS","isAdmin","recipient","problemOf","reported","one","reachesAnybody","recipients","context","api","createInboxApi","admins","ref","emailField","channels","router","useRouter","canSetUp","channelsLink","setUpChannels","event","onMounted","adminOptions","emailOptions","adminProblem","problem","add","remove","index","confirm","_","at","setAdmin","id","setEmail","email","_Fragment","_renderList","WxSpace","WxButton","WxIcon","WxRelationsField","WxLink","route","useRoute","locales","useLocales","message","useErrorText","form","fields","loading","saving","errors","reactive","tab","silent","channelsSend","channel","canManage","name","localizedValue","backTo","load","loaded","error","watch","save","saved","body","WxSkeleton","WxScreenHead","WxBadge","WxTabs","WxTab","FormGeneral","FieldList","FormNotifications","FormAntispam","FormEmbed","WxActionBar"],"mappings":";;;;;;;;;;;;;;;AA2BA,UAAMA,IAAUC,EAAwBC,GAAA,YAAmB,GAErDC,IAAQD,GAKRE,IAAIC,EAAa,YAAY,GAE7BC,IAAWC,EAAgBP,GAAS,qBAAqB,EAAI,GAC7DQ,IAAUD,EAAeP,GAAS,wBAAwB,CAAC,GAC3DS,IAAWF,EAAeP,GAAS,qBAAqB,CAAC,GACzDU,IAAUH,EAAeP,GAAS,oBAAoB,KAAK,GAE3DW,IAAWC,EAAS,MAAM;AAAA,MAC9B,EAAE,OAAO,OAAO,OAAOR,EAAE,mBAAmB,EAAA;AAAA,MAC5C,EAAE,OAAO,aAAa,OAAOA,EAAE,yBAAyB,EAAA;AAAA,MACxD,EAAE,OAAO,aAAa,OAAOA,EAAE,yBAAyB,EAAA;AAAA,IAAE,CAC3D,GAGKS,IAASD,EAAS,MAAM;AAC5B,YAAME,IAAWJ,EAAQ;AAEzB,aAAII,MAAa,eAAeA,MAAa,cAAoB,OAE1D,EAAE,UAAAA,GAAU,MAAMX,EAAM,OAAOW,CAAQ,KAAK,KAAA;AAAA,IACrD,CAAC,GAEKC,IAAOH,EAAS,MAAM;AAC1B,YAAMI,IAAOH,EAAO,OAAO;AAE3B,aAAOG,IAAOZ,EAAE,iBAAiBS,EAAO,MAAO,QAAQ,IAAIG,EAAK,IAAI,EAAE,IAAI;AAAA,IAC5E,CAAC;2BAICC,EA0BUC,EAAAC,CAAA,GAAA,MAAA;AAAA,iBAzBR,MAEe;AAAA,QAFfC,EAEeF,EAAAG,CAAA,GAAA;AAAA,UAFA,MAAMH,EAAAd,CAAA,EAAC,qBAAA;AAAA,QAAA;qBACpB,MAA6D;AAAA,YAA7DgB,EAA6DF,EAAAI,EAAA,GAAA;AAAA,0BAAzCJ,EAAAZ,CAAA;AAAA,mEAAAA,EAAQ,QAAAiB,IAAA;AAAA,cAAG,OAAOL,EAAAd,CAAA,EAAC,gBAAA;AAAA,YAAA;;;;QAGzCgB,EAEeF,EAAAG,CAAA,GAAA;AAAA,UAFA,OAAOH,EAAAd,CAAA,EAAC,mBAAA;AAAA,UAAwB,MAAMc,EAAAd,CAAA,EAAC,wBAAA;AAAA,QAAA;qBACpD,MAAyD;AAAA,YAAzDgB,EAAyDF,EAAAM,EAAA,GAAA;AAAA,0BAA/BN,EAAAV,CAAA;AAAA,mEAAAA,EAAO,QAAAe,IAAA;AAAA,cAAG,KAAK;AAAA,cAAI,KAAK;AAAA,YAAA;;;;QAGpDH,EAEeF,EAAAG,CAAA,GAAA;AAAA,UAFA,OAAOH,EAAAd,CAAA,EAAC,gBAAA;AAAA,UAAqB,MAAMc,EAAAd,CAAA,EAAC,qBAAA;AAAA,QAAA;qBACjD,MAA0D;AAAA,YAA1DgB,EAA0DF,EAAAM,EAAA,GAAA;AAAA,0BAAhCN,EAAAT,CAAA;AAAA,mEAAAA,EAAQ,QAAAc,IAAA;AAAA,cAAG,KAAK;AAAA,cAAI,KAAK;AAAA,YAAA;;;;QAGrDH,EAEeF,EAAAG,CAAA,GAAA;AAAA,UAFA,OAAOH,EAAAd,CAAA,EAAC,eAAA;AAAA,UAAoB,MAAMc,EAAAd,CAAA,EAAC,oBAAA;AAAA,QAAA;qBAChD,MAAmD;AAAA,YAAnDgB,EAAmDF,EAAAO,EAAA,GAAA;AAAA,0BAA/BP,EAAAR,CAAA;AAAA,mEAAAA,EAAO,QAAAa,IAAA;AAAA,cAAG,SAASZ,EAAA;AAAA,YAAA;;;;QAG1BI,EAAA,cAAfE,EAAgEC,EAAAQ,CAAA,GAAA;AAAA;UAA3C,MAAK;AAAA,UAAK,MAAK;AAAA,QAAA;qBAAQ,MAAU;AAAA,gBAAPX,EAAA,KAAI,GAAA,CAAA;AAAA,UAAA;;;QAG3CF,EAAA,OAAQ,QAAI,CAAKA,QAAO,KAAK,mBADrCI,EAMEC,EAAAS,EAAA,GAAA;AAAA;UAJA,MAAK;AAAA,UACL,SAAQ;AAAA,UACP,UAAU;AAAA,UACV,aAAaT,EAAAd,CAAA,EAAC,4BAAA;AAAA,QAAA;;;;;;;;;;;;;AClErB,UAAMD,IAAQD;AAEd,IAAA0B,GAAA;AACA,UAAMxB,IAAIC,EAAa,YAAY,GAC7BwB,IAAQC,GAAA,GAERC,IAAYnB;AAAA,MAChB,MAAMiB,EAAM,MAAM,UAAU,QAAQ,KAAK,CAACG,MAAWA,EAAO,OAAO,QAAQ,KAAK;AAAA,IAAA,GAG5EC,IAAQrB,EAAS,MAAM,6BAA6BT,EAAM,IAAI,MAAM,GAEpE+B,IAAQtB;AAAA,MAAS,MACrBmB,EAAU,QACNE,EAAM,QACN;AAAA,4BAAiF9B,EAAM,IAAI;AAAA,IAAA,GAI3FgC,IAASvB;AAAA,MACb,MAAMT,EAAM,OAAO,KAAK,CAACiC,MAAUA,EAAM,SAAS,YAAYA,EAAM,UAAU,GAAG,OAAO;AAAA,IAAA,GAGpFC,IAASzB;AAAA,MACb,MACE,6BAA6BT,EAAM,IAAI,gBAAgBgC,EAAO,KAAK;AAAA,4BACtChC,EAAM,IAAI;AAAA,IAAA,GAGrCmC,IAAU1B,EAAoC,MAAM;AAAA,MACxD,EAAE,KAAK,OAAO,OAAOR,EAAE,aAAa,EAAA;AAAA,MACpC,EAAE,KAAK,SAAS,OAAOA,EAAE,cAAc,EAAA;AAAA,MACvC,EAAE,KAAK,QAAQ,OAAOA,EAAE,aAAa,GAAG,WAAW,IAAA;AAAA,IAAI,CACxD,GAGKmC,IAAS3B,EAAS,MAAMT,EAAM,OAAO,OAAO,CAACiC,MAAUA,EAAM,UAAU,CAAC;AAE9E,mBAAeI,EAAKC,GAA6B;AAC/C,UAAI;AACF,cAAM,UAAU,UAAU,UAAUA,CAAI,GACxCC,EAAM,QAAQtC,EAAE,cAAc,CAAC;AAAA,MACjC,QAAQ;AAAA,MAGR;AAAA,IACF;sBAIEuC,EAAA,GAAAC,EAqDM,OArDNC,IAqDM;AAAA,MApDJzB,EAOUF,EAAAC,CAAA,GAAA;AAAA,QAPA,OAAOD,EAAAd,CAAA,EAAC,mBAAA;AAAA,MAAA;mBAChB,MAA2E;AAAA,UAA3EgB,EAA2EF,EAAAQ,CAAA,GAAA;AAAA,YAAlE,MAAK;AAAA,YAAK,MAAK;AAAA,UAAA;uBAAQ,MAAiC;AAAA,kBAA9BR,EAAAd,CAAA,EAAC,wBAAA,CAAA,GAAA,CAAA;AAAA,YAAA;;;UAEpC0C,EAGM,OAHNC,IAGM;AAAA,YAFJD,EAAwB,gBAAfb,EAAA,KAAK,GAAA,CAAA;AAAA,YACdb,EAAuEF,EAAA8B,CAAA,GAAA;AAAA,cAA5D,MAAK;AAAA,cAAQ,OAAO9B,EAAAd,CAAA,EAAC,YAAA;AAAA,cAAiB,SAAK6C,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAA1B,MAAEiB,EAAKP,EAAA,KAAK;AAAA,YAAA;;;;;MAItEb,EASUF,EAAAC,CAAA,GAAA;AAAA,QATA,OAAOD,EAAAd,CAAA,EAAC,mBAAA;AAAA,MAAA;mBAChB,MAEU;AAAA,UAFVgB,EAEUF,EAAAQ,CAAA,GAAA;AAAA,YAFD,MAAK;AAAA,YAAK,MAAK;AAAA,UAAA;uBACtB,MAA8E;AAAA,cAA3EwB,EAAAC,EAAAjC,EAAAd,CAAA,EAAE2B,EAAA,QAAS,iCAAA,wBAAA,CAAA,GAAA,CAAA;AAAA,YAAA;;;UAGhBe,EAGM,OAHNM,IAGM;AAAA,YAFJN,EAAwB,gBAAfZ,EAAA,KAAK,GAAA,CAAA;AAAA,YACdd,EAAuEF,EAAA8B,CAAA,GAAA;AAAA,cAA5D,MAAK;AAAA,cAAQ,OAAO9B,EAAAd,CAAA,EAAC,YAAA;AAAA,cAAiB,SAAK6C,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAA1B,MAAEiB,EAAKN,EAAA,KAAK;AAAA,YAAA;;;;;MAItEd,EAOUF,EAAAC,CAAA,GAAA;AAAA,QAPA,OAAOD,EAAAd,CAAA,EAAC,oBAAA;AAAA,MAAA;mBAChB,MAA4E;AAAA,UAA5EgB,EAA4EF,EAAAQ,CAAA,GAAA;AAAA,YAAnE,MAAK;AAAA,YAAK,MAAK;AAAA,UAAA;uBAAQ,MAAkC;AAAA,kBAA/BR,EAAAd,CAAA,EAAC,yBAAA,CAAA,GAAA,CAAA;AAAA,YAAA;;;UAEpC0C,EAGM,OAHNO,IAGM;AAAA,YAFJP,EAAyB,gBAAhBT,EAAA,KAAM,GAAA,CAAA;AAAA,YACfjB,EAAwEF,EAAA8B,CAAA,GAAA;AAAA,cAA7D,MAAK;AAAA,cAAQ,OAAO9B,EAAAd,CAAA,EAAC,YAAA;AAAA,cAAiB,SAAK6C,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAA1B,MAAEiB,EAAKH,EAAA,KAAM;AAAA,YAAA;;;;;MAIvEjB,EAsBUF,EAAAC,CAAA,GAAA;AAAA,QAtBA,OAAOD,EAAAd,CAAA,EAAC,mBAAA;AAAA,MAAA;mBAChB,MAA2E;AAAA,UAA3EgB,EAA2EF,EAAAQ,CAAA,GAAA;AAAA,YAAlE,MAAK;AAAA,YAAK,MAAK;AAAA,UAAA;uBAAQ,MAAiC;AAAA,kBAA9BR,EAAAd,CAAA,EAAC,wBAAA,CAAA,GAAA,CAAA;AAAA,YAAA;;;UAEpCgB,EAkBWF,EAAAoC,EAAA,GAAA;AAAA,YAjBR,MAAMf,EAAA;AAAA,YACN,SAASD,EAAA;AAAA,YACV,WAAQ;AAAA,YACR,OAAA;AAAA,YACC,cAAYpB,EAAAd,CAAA,EAAC,kBAAA;AAAA,UAAA;YAEH,YAAQmD,EACjB,CAAuD,EADlC,KAAAC,QAAG;AAAA,cACxBpC,EAAuDF,EAAAQ,CAAA,GAAA;AAAA,gBAA9C,MAAA;AAAA,gBAAK,MAAK;AAAA,cAAA;2BAAK,MAAO;AAAA,kBAAPwB,EAAA,YAAOC,EAAGK,EAAI,GAAG,IAAG,KAAC,CAAA;AAAA,gBAAA;;;;YAGpC,cAAUD,EACnB,CAA4C,EADrB,KAAAC,QAAG;AAAA,kBACvB,OAAO,OAAOA,EAAI,KAAK,EAAA,CAAA,KAAQA,EAAI,GAAG,GAAA,CAAA;AAAA,YAAA;YAGhC,aAASD,EAClB,CAAkC,EADZ,KAAAC,QAAG;AAAA,kBACtBtC,EAAAd,CAAA,EAAC,eAAgBoD,EAAI,IAAI,EAAA,CAAA,GAAA,CAAA;AAAA,YAAA;;;;;;;;;;;;;;;;;;;;ACzGtC,UAAMC,IAAWxD;AAAAA,MAChBC;AAAA,MAAC;AAAA,IAAA,GAIIF,IAAUC,EAAwBC,GAAC,SAA6B,GAEhEE,IAAIC,EAAa,YAAY,GAE7BqD,IAAUnD,EAAuBP,GAAS,qBAAqB,CAAA,CAAE,GACjEyC,IAAOlC,EAAuBP,GAAS,kBAAkB,CAAA,CAAE,GAC3D2D,IAASpD,EAAuBP,GAAS,sBAAsB,CAAA,CAAE,GACjE4D,IAAWrD,EAAeP,GAAS,YAAY,EAAE;sBAIrD2C,EAAA,GAAAC,EAsCM,OAtCNC,IAsCM;AAAA,MArCJzB,EAiBUF,EAAAC,CAAA,GAAA,MAAA;AAAA,mBAhBR,MAEe;AAAA,UAFfC,EAEeF,EAAAG,CAAA,GAAA;AAAA,YAFA,OAAOH,EAAAd,CAAA,EAAC,aAAA;AAAA,YAAkB,OAAOF,EAAA,OAAO,QAAK,CAAA;AAAA,YAAO,UAAA;AAAA,UAAA;uBACjE,MAA+C;AAAA,cAA/CkB,EAA+CF,EAAA2C,CAAA,GAAA;AAAA,gBAA5B,YAAAJ,EAAA,MAAS;AAAA,gBAAT,uBAAAR,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAA1B,MAAAkC,EAAA,MAAS,QAAKlC;AAAA,gBAAE,WAAA;AAAA,cAAA;;;;UAGrCH,EAOeF,EAAAG,CAAA,GAAA;AAAA,YANZ,OAAOH,EAAAd,CAAA,EAAC,YAAA;AAAA,YACR,MAAMc,EAAAd,CAAA,EAAC,iBAAA;AAAA,YACP,OAAOF,EAAA,OAAO,OAAI,CAAA;AAAA,YACnB,UAAA;AAAA,UAAA;uBAEA,MAA0D;AAAA,cAA1DkB,EAA0DF,EAAA2C,CAAA,GAAA;AAAA,gBAAvC,YAAAJ,EAAA,MAAS;AAAA,gBAAT,uBAAAR,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAA1B,MAAAkC,EAAA,MAAS,OAAIlC;AAAA,gBAAE,aAAY;AAAA,cAAA;;;;UAGhDH,EAEeF,EAAAG,CAAA,GAAA;AAAA,YAFA,MAAMH,EAAAd,CAAA,EAAC,uBAAA;AAAA,UAAA;uBACpB,MAA0E;AAAA,cAA1EgB,EAA0EF,EAAAI,EAAA,GAAA;AAAA,gBAAtD,YAAAmC,EAAA,MAAS;AAAA,gBAAT,uBAAAR,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAA1B,MAAAkC,EAAA,MAAS,aAAUlC;AAAA,gBAAG,OAAOL,EAAAd,CAAA,EAAC,kBAAA;AAAA,cAAA;;;;;;;MAItDgB,EAiBUF,EAAAC,CAAA,GAAA;AAAA,QAjBA,OAAOD,EAAAd,CAAA,EAAC,qBAAA;AAAA,MAAA;mBAChB,MAEe;AAAA,UAFfgB,EAEeF,EAAAG,CAAA,GAAA;AAAA,YAFA,OAAOH,EAAAd,CAAA,EAAC,mBAAA;AAAA,UAAA;uBACrB,MAAuC;AAAA,cAAvCgB,EAAuCF,EAAA2C,CAAA,GAAA;AAAA,4BAApB3C,EAAAyC,CAAA;AAAA,qEAAAA,EAAM,QAAApC,IAAA;AAAA,gBAAE,WAAA;AAAA,cAAA;;;;UAG7BH,EAEeF,EAAAG,CAAA,GAAA;AAAA,YAFA,OAAOH,EAAAd,CAAA,EAAC,yBAAA;AAAA,UAAA;uBACrB,MAAwC;AAAA,cAAxCgB,EAAwCF,EAAA2C,CAAA,GAAA;AAAA,4BAArB3C,EAAAwC,CAAA;AAAA,qEAAAA,EAAO,QAAAnC,IAAA;AAAA,gBAAE,WAAA;AAAA,cAAA;;;;UAI9BH,EAEeF,EAAAG,CAAA,GAAA;AAAA,YAFA,OAAOH,EAAAd,CAAA,EAAC,sBAAA;AAAA,UAAA;uBACrB,MAAsC;AAAA,cAAtCgB,EAAsC0C,IAAA;AAAA,4BAAR5C,EAAAuB,CAAA;AAAA,qEAAAA,EAAI,QAAAlB,IAAA;AAAA,cAAA;;;;UAGpCH,EAEeF,EAAAG,CAAA,GAAA;AAAA,YAFA,OAAOH,EAAAd,CAAA,EAAC,gBAAA;AAAA,YAAqB,MAAMc,EAAAd,CAAA,EAAC,qBAAA;AAAA,UAAA;uBACjD,MAAwD;AAAA,cAAxDgB,EAAwDF,EAAA2C,CAAA,GAAA;AAAA,4BAArC3C,EAAA0C,CAAA;AAAA,qEAAAA,EAAQ,QAAArC,IAAA;AAAA,gBAAE,aAAY;AAAA,cAAA;;;;;;;;;oECvD3CwC,KAAU;AAET,SAASC,EAAQC,GAAyD;AAC/E,SAAO,cAAcA;AACvB;AAGO,SAASC,GACdD,GACAE,IAA6B,IACJ;AACzB,SAAIH,EAAQC,CAAS,IACLE,EAAS;AAAA,IACrB,CAACC,MAAQA,EAAI,SAAS,WAAWA,EAAI,aAAaH,EAAU;AAAA,EAAA,GAGhD,WAAW,OAGpBF,GAAQ,MAAME,EAAU,SAAS,IAAI,KAAA,CAAM,IAAI,OAAO;AAC/D;AAGO,SAASI,GACdC,GACAH,IAA6B,IACpB;AACT,UAAQG,KAAc,CAAA,GAAI,KAAK,CAACL,MAAcC,GAAUD,GAAWE,CAAQ,MAAM,IAAI;AACvF;;;;;;;;;;;;;;ACFA,UAAMhE,IAAQD,GASRF,IAAUC,EAAwBC,GAAA,YAAmB,GAErDqE,IAAUzC,GAAA,GACV0C,IAAMC,GAAeF,CAAO,GAC5BnE,IAAIC,EAAa,YAAY,GAE7BqE,IAASC,EAAsB,EAAE,GAEjCL,IAAa/D,EAAoBP,GAAS,cAAc,CAAA,CAAE,GAC1D4E,IAAarE,EAAeP,GAAS,eAAe,EAAE,GACtD6E,IAAWtE,EAAiBP,GAAS,mBAAmB,CAAA,CAAE,GAE1D8E,IAASC,GAAA,GAGTC,IAAWpE,EAAS,MAAM2D,EAAQ,IAAI,sBAAsB,CAAC,GAC7DU,IAAerE,EAAS,MAAM,GAAG2D,EAAQ,QAAQ,iBAAiB,QAAQ,WAAW,GAAG,CAAC;AAG/F,aAASW,EAAcC,GAAyB;AAC9C,MAAIA,EAAM,WAAWA,EAAM,WAAWA,EAAM,YAAYA,EAAM,WAAW,MAEzEA,EAAM,eAAA,GACDL,EAAO,KAAK,gBAAgB;AAAA,IACnC;AAEA,IAAAM,GAAU,YAAY;AACpB,UAAI;AACF,QAAAV,EAAO,QAAQ,MAAMF,EAAI,WAAA;AAAA,MAC3B,QAAQ;AAAA,MAGR;AAAA,IACF,CAAC;AAED,UAAMa,IAAezE;AAAA,MAAS,MAC5B8D,EAAO,MAAM,IAAI,CAAC7C,OAAW,EAAE,OAAOA,EAAM,IAAI,OAAO,GAAGA,EAAM,IAAI,MAAMA,EAAM,KAAK,KAAK;AAAA,IAAA,GAItFyD,IAAe1E,EAAS,MAAM;AAAA,MAClC,EAAE,OAAO,IAAI,OAAOR,EAAE,sBAAsB,EAAA;AAAA,MAC5C,GAAGD,EAAM,OACN,OAAO,CAACiC,MAAUA,EAAM,SAAS,OAAO,EACxC,IAAI,CAACA,OAAW,EAAE,OAAOA,EAAM,KAAK,OAAOA,EAAM,MAAM;AAAA,IAAA,CAC3D;AAMD,aAASmD,EAAatB,GAAqC;AACzD,UAAI,CAACD,EAAQC,CAAS,EAAG,QAAO;AAEhC,YAAMuB,IAAUtB,GAAUD,GAAW9D,EAAM,QAAQ;AAEnD,aAAOqF,MAAY,OAAO,OAAOpF,EAAE,mBAAmBoF,CAAO,EAAE;AAAA,IACjE;AAEA,aAASC,EAAIxB,GAA4B;AACvC,MAAAK,EAAW,QAAQ,CAAC,GAAGA,EAAW,OAAOL,CAAS;AAAA,IACpD;AASA,mBAAeyB,EAAOC,GAA8B;AAClD,YAAM1B,IAAYK,EAAW,MAAMqB,CAAK;AAIxC,MAFE1B,MAAc,WAAcD,EAAQC,CAAS,MAAMA,EAAU,SAAS,IAAI,KAAA,MAAW,OAWjF,CARW,MAAM2B,GAAQ;AAAA,QAC3B,OAAOxF,EAAE,8BAA8B;AAAA,QACvC,SAASA,EAAE,6BAA6B;AAAA,QACxC,aAAaA,EAAE,cAAc;AAAA,QAC7B,YAAYA,EAAE,cAAc;AAAA,QAC5B,MAAM;AAAA,MAAA,CACP,MAKHkE,EAAW,QAAQA,EAAW,MAAM,OAAO,CAACuB,GAAGC,MAAOA,MAAOH,CAAK;AAAA,IACpE;AAEA,aAASI,GAASJ,GAAeK,GAAkB;AACjD,MAAA1B,EAAW,QAAQA,EAAW,MAAM,IAAI,CAACF,GAAK0B,MAAQA,MAAOH,IAAQ,EAAE,UAAUK,EAAA,IAAO5B,CAAI;AAAA,IAC9F;AAEA,aAAS6B,EAASN,GAAeO,GAAqB;AACpD,MAAA5B,EAAW,QAAQA,EAAW,MAAM,IAAI,CAACF,GAAK0B,MAAQA,MAAOH,IAAQ,EAAE,OAAAO,EAAA,IAAU9B,CAAI;AAAA,IACvF;sBAIEzB,EAAA,GAAAC,EA2FM,OA3FNC,IA2FM;AAAA,MA1FJzB,EAwEUF,EAAAC,CAAA,GAAA;AAAA,QAxEA,OAAOD,EAAAd,CAAA,EAAC,kBAAA;AAAA,MAAA;mBAChB,MAA0E;AAAA,UAA1EgB,EAA0EF,EAAAQ,CAAA,GAAA;AAAA,YAAjE,MAAK;AAAA,YAAK,MAAK;AAAA,UAAA;uBAAQ,MAAgC;AAAA,kBAA7BR,EAAAd,CAAA,EAAC,uBAAA,CAAA,GAAA,CAAA;AAAA,YAAA;;;UAG5BF,EAAA,OAAM,oBAAA,UADde,EAKEC,EAAAS,EAAA,GAAA;AAAA;YAHA,MAAK;AAAA,YACL,SAAQ;AAAA,YACP,aAAazB,EAAA,OAAM,oBAAA,IAAA,CAAA;AAAA,UAAA;UAGtB4C,EAsCM,OAtCNC,IAsCM;AAAA,YArCW7B,EAAAoD,CAAA,EAAW,WAAM,UAAhCrD,EAEUC,EAAAQ,CAAA,GAAA;AAAA;cAF8B,MAAK;AAAA,cAAK,MAAK;AAAA,YAAA;yBACrD,MAA8B;AAAA,oBAA3BR,EAAAd,CAAA,EAAC,qBAAA,CAAA,GAAA,CAAA;AAAA,cAAA;;;aAGNuC,EAAA,EAAA,GAAAC,EAgCMuD,IAAA,MAAAC,GA/ByBlF,EAAAoD,CAAA,GAAU,CAA/BL,GAAW0B,YADrB/C,EAgCM,OAAA;AAAA,cA9BH,KAAK+C;AAAA,cACN,OAAM;AAAA,YAAA;cAEN7C,EAuBM,OAvBNM,IAuBM;AAAA,gBArBIlC,EAAA8C,CAAA,EAAQC,CAAS,UADzBhD,EAKEC,EAAAO,EAAA,GAAA;AAAA;kBAHC,eAAawC,EAAU;AAAA,kBACvB,SAASoB,EAAA;AAAA,kBACT,uBAAkB,CAAGW,MAAOD,GAASJ,GAAO,OAAOK,CAAE,CAAA;AAAA,gBAAA,wEAExD/E,EAMEC,EAAA2C,CAAA,GAAA;AAAA;kBAJC,eAAaI,EAAU;AAAA,kBACxB,MAAK;AAAA,kBACL,aAAY;AAAA,kBACX,uBAAkB,CAAGiC,MAAUD,EAASN,GAAO,OAAOO,CAAK,CAAA;AAAA,gBAAA;gBAK9D9E,EAKEF,EAAA8B,CAAA,GAAA;AAAA,kBAJA,MAAK;AAAA,kBACL,MAAK;AAAA,kBACJ,OAAO9B,EAAAd,CAAA,EAAC,cAAA;AAAA,kBACR,SAAK,CAAAmB,MAAEmE,EAAOC,CAAK;AAAA,gBAAA;;cAGTJ,EAAatB,CAAS,UAArChD,EAEUC,EAAAQ,CAAA,GAAA;AAAA;gBAF8B,MAAK;AAAA,gBAAK,MAAK;AAAA,cAAA;2BACrD,MAA6B;AAAA,kBAA1BwB,EAAAC,EAAAoC,EAAatB,CAAS,CAAA,GAAA,CAAA;AAAA,gBAAA;;;;;UAK/B7C,EAaWF,EAAAmF,EAAA,GAAA,EAbD,MAAK,QAAI;AAAA,uBACjB,MAOY;AAAA,cAPZjF,EAOYF,EAAAoF,EAAA,GAAA;AAAA,gBANV,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACJ,UAAUjB,EAAA,MAAa,WAAM;AAAA,gBAC7B,gCAAOI,EAAG,EAAA,UAAa,OAAOJ,EAAA,UAAiB,KAAK,GAAA;AAAA,cAAA;2BAErD,MAA0B;AAAA,sBAAvBnE,EAAAd,CAAA,EAAC,iBAAA,CAAA,GAAA,CAAA;AAAA,gBAAA;;;cAENgB,EAGYF,EAAAoF,EAAA,GAAA;AAAA,gBAHD,SAAQ;AAAA,gBAAW,gCAAOb,EAAG,EAAA,OAAA,IAAA;AAAA,cAAA;gBAC3B,QAAK,MAAuB;AAAA,kBAAvBrE,EAAuBF,EAAAqF,EAAA,GAAA,EAAd,MAAK,QAAM;AAAA,gBAAA;2BAAc,MAClD;AAAA,kBADkDrD,EAAA,QAC/ChC,EAAAd,CAAA,EAAC,iBAAA,CAAA,GAAA,CAAA;AAAA,gBAAA;;;;;;UAIRgB,EAMeF,EAAAG,CAAA,GAAA;AAAA,YALZ,OAAOH,EAAAd,CAAA,EAAC,mBAAA;AAAA,YACR,MAAMc,EAAAd,CAAA,EAAC,wBAAA;AAAA,YACP,OAAOF,EAAA,OAAM,qBAAA,IAAA,CAAA;AAAA,UAAA;uBAEd,MAA0D;AAAA,cAA1DkB,EAA0DF,EAAAO,EAAA,GAAA;AAAA,4BAAtCP,EAAA0D,CAAA;AAAA,qEAAAA,EAAU,QAAArD,IAAA;AAAA,gBAAG,SAAS+D,EAAA;AAAA,cAAA;;;;;;;MAI/BnF,EAAM,sBAArBc,EAeUC,EAAAC,CAAA,GAAA;AAAA;QAf2B,OAAOD,EAAAd,CAAA,EAAC,sBAAA;AAAA,MAAA;mBAC3C,MAA8E;AAAA,UAA9EgB,EAA8EF,EAAAQ,CAAA,GAAA;AAAA,YAArE,MAAK;AAAA,YAAK,MAAK;AAAA,UAAA;uBAAQ,MAAoC;AAAA,kBAAjCR,EAAAd,CAAA,EAAC,2BAAA,CAAA,GAAA,CAAA;AAAA,YAAA;;;UAEpC0C,EAWM,OAXNO,IAWM;AAAA,YAVJjC,EAMEF,EAAAsF,EAAA,GAAA;AAAA,0BALStF,EAAA2D,CAAA;AAAA,mEAAAA,EAAQ,QAAAtD,IAAA;AAAA,cACjB,QAAO;AAAA,cACN,UAAU;AAAA,cACV,YAAUL,EAAAd,CAAA,EAAC,qBAAA;AAAA,cACX,cAAYc,EAAAd,CAAA,EAAC,mBAAA;AAAA,YAAA;YAED4E,EAAA,cAAf/D,EAEYC,EAAAuF,EAAA,GAAA;AAAA;cAFc,MAAMxB,EAAA;AAAA,cAAc,MAAK;AAAA,cAAM,SAAOC;AAAA,YAAA;yBAAe,MAE7E;AAAA,oBADAhE,EAAAd,CAAA,EAAC,uBAAA,CAAA,GAAA,CAAA;AAAA,cAAA;;;;;;;;;;;;;;;ACvMX,UAAMD,IAAQD,GAERqE,IAAUzC,GAAA,GACV0C,IAAMC,GAAeF,CAAO,GAC5BmC,IAAQC,GAAA,GACR7B,IAASC,GAAA,GACT6B,IAAUC,GAAA;AAChB,IAAAjF,GAAA;AAEA,UAAMxB,IAAIC,EAAa,YAAY,GAE7ByG,IAAUC,GAAA,GAEVC,IAAOrC,EAAsB,IAAI,GACjCsC,IAAStC,EAAkB,EAAE,GAC7BuC,IAAUvC,EAAI,EAAI,GAClBwC,IAASxC,EAAI,EAAK,GAClByC,IAASzC,EAA8B,EAAE;AAE/C,QAAMlB,IAAW4D,GAAuE;AAAA,MACtF,MAAM;AAAA,MACN,OAAO,CAAA;AAAA,MACP,YAAY;AAAA,IAAA,CACb;AAED,UAAMrH,IAAU2E,EAAiB,EAAE,GAK7B2C,IAAM3C,EAHC,CAAC,WAAW,UAAU,iBAAiB,YAAY,OAAO,EAGlD,SAAS,OAAO+B,EAAM,MAAM,GAAG,CAAC,IAAI,OAAOA,EAAM,MAAM,GAAG,IAAI,SAAS,GAOtFa,IAAS3G;AAAA,MACb,MACE6C,EAAS,cACT,CAACY,GAAerE,EAAQ,MAAM,YAAuCgH,EAAK,OAAO,UAAU,KAC3F,CAACQ,GAAa;AAAA,IAAA,GAOZA,KAAe5G,EAAS,MAAM;AAClC,UAAIoG,EAAK,OAAO,kBAAkB,GAAM,QAAO;AAE/C,YAAM7C,IAAW6C,EAAK,MAAM,YAAY,CAAA;AAExC,cAAQhH,EAAQ,MAAM,mBAAmB,CAAA,GAAI;AAAA,QAC3C,CAACgG,MAAO7B,EAAS,KAAK,CAACsD,MAAYA,EAAQ,OAAOzB,CAAE,GAAG,SAAS;AAAA,MAAA;AAAA,IAEpE,CAAC,GAEK0B,IAAY9G,EAAS,MAAM2D,EAAQ,IAAI,cAAc,CAAC,GAEtDyB,IAAKpF,EAAS,MAAM,OAAO8F,EAAM,OAAO,EAAE,CAAC,GAE3CiB,IAAO/G;AAAA,MAAS,MACpBoG,EAAK,UAAU,OAAO,KAAKY,GAAenE,EAAS,OAAOmD,EAAQ,OAAO,OAAOnD,EAAS,IAAI;AAAA,IAAA,GAIzFoE,IAASjH,EAAS,MAAM,GAAGT,EAAM,IAAI,SAAS6F,EAAG,KAAK,EAAE;AAE9D,mBAAe8B,IAAsB;AACnC,MAAAZ,EAAQ,QAAQ;AAEhB,UAAI;AACF,cAAMa,IAAS,MAAMvD,EAAI,KAAKwB,EAAG,KAAK;AAEtC,QAAAgB,EAAK,QAAQe,GACbd,EAAO,QAAQc,EAAO,UAAU,CAAA,GAChCtE,EAAS,OAAOsE,EAAO,MACvBtE,EAAS,QAAQ,EAAE,GAAGsE,EAAO,MAAA,GAC7BtE,EAAS,aAAasE,EAAO,YAC7B/H,EAAQ,QAAQ,EAAE,GAAG+H,EAAO,QAAA;AAAA,MAC9B,SAASC,GAAO;AACd,QAAAtF,EAAM,OAAOoE,EAAQkB,CAAK,CAAC,GACtBlD,EAAO,QAAQ3E,EAAM,IAAI;AAAA,MAChC,UAAA;AACE,QAAA+G,EAAQ,QAAQ;AAAA,MAClB;AAAA,IACF;AAEA,IAAAe,GAAMjC,GAAI;AAAM,MAAK8B,EAAA;AAAA,OAAQ,EAAE,WAAW,IAAM;AAEhD,mBAAeI,IAAsB;AACnC,MAAAf,EAAO,QAAQ,IACfC,EAAO,QAAQ,CAAA;AAEf,UAAI;AACF,cAAMe,IAAQ,MAAM3D,EAAI,SAASwB,EAAG,OAAO;AAAA,UACzC,MAAMvC,EAAS,KAAK,KAAA;AAAA,UACpB,OAAOA,EAAS;AAAA,UAChB,YAAYA,EAAS;AAAA,UACrB,SAASzD,EAAQ;AAAA,QAAA,CAClB;AAED,QAAAgH,EAAK,QAAQmB,GACbzF,EAAM,QAAQtC,EAAE,aAAa,CAAC;AAAA,MAChC,SAAS4H,GAAO;AACd,cAAMI,IAAQJ,EAA2D;AAEzE,QAAII,GAAM,UACRhB,EAAO,QAAQgB,EAAK,QACpB1F,EAAM,OAAOtC,EAAE,cAAc,CAAC,KAE9BsC,EAAM,OAAOoE,EAAQkB,CAAK,CAAC;AAAA,MAE/B,UAAA;AACE,QAAAb,EAAO,QAAQ;AAAA,MACjB;AAAA,IACF;sBAYExE,EAAA,GAAAC,EAmEM,OAnENC,IAmEM;AAAA,MA/DWqE,EAAA,cAAfjG,EAEUC,EAAAC,CAAA,GAAA,EAAA,KAAA,KAAA;AAAA,mBADR,MAA+B;AAAA,UAA/BC,EAA+BF,EAAAmH,EAAA,GAAA;AAAA,YAAlB,OAAA;AAAA,YAAO,MAAM;AAAA,UAAA;;;YAGPrB,EAAA,cAArBpE,EA0DWuD,IAAA,EAAA,KAAA,KAAA;AAAA,QAzDT/E,EAUiBF,EAAAoH,EAAA,GAAA;AAAA,UATf,OAAM;AAAA,UACL,OAAOX,EAAA;AAAA,UACP,UAAUX,EAAA,MAAK;AAAA,UACf,MAAMa,EAAA;AAAA,UACN,cAAY3G,EAAAd,CAAA,EAAC,aAAA;AAAA,QAAA;UAEH,iBACT,MAAoF;AAAA,YAAnEc,EAAAuC,CAAA,EAAS,+BAA1BxC,EAAoFC,EAAAqH,EAAA,GAAA;AAAA;cAA9C,MAAK;AAAA,YAAA;yBAAU,MAAoB;AAAA,oBAAjBrH,EAAAd,CAAA,EAAC,WAAA,CAAA,GAAA,CAAA;AAAA,cAAA;;;;;;QASrDmH,EAAA,cADRtG,EAQEC,EAAAS,EAAA,GAAA;AAAA;UANA,OAAM;AAAA,UACN,MAAK;AAAA,UACL,SAAQ;AAAA,UACP,UAAU;AAAA,UACV,OAAOT,EAAAd,CAAA,EAAC,uBAAA;AAAA,UACR,aAAac,EAAAd,CAAA,EAAC,4BAAA;AAAA,QAAA;QAGjBgB,EA0BUF,EAAAsH,EAAA,GAAA;AAAA,sBA1BQlB,EAAA;AAAA,wDAAAA,EAAG,QAAA/F;AAAA,UAAE,OAAM;AAAA,UAAwB,cAAA;AAAA,QAAA;qBACnD,MAES;AAAA,YAFTH,EAESF,EAAAuH,CAAA,GAAA;AAAA,cAFD,OAAM;AAAA,cAAW,OAAOvH,EAAAd,CAAA,EAAC,mBAAA;AAAA,YAAA;yBAC/B,MAAuF;AAAA,gBAAvFgB,EAAuFsH,IAAA;AAAA,kBAAjE,UAAUxH,EAAAuC,CAAA;AAAA,qEAAAA,EAAQ,QAAAlC,IAAAkC,IAAAlC;AAAA,kBAAU,SAASvB,EAAA;AAAA,6DAAAA,EAAO,QAAAuB;AAAA,kBAAG,QAAQ6F,EAAA;AAAA,gBAAA;;;;YAG/EhG,EAESF,EAAAuH,CAAA,GAAA;AAAA,cAFD,OAAM;AAAA,cAAU,OAAOvH,EAAAd,CAAA,EAAC,kBAAA;AAAA,YAAA;yBAC9B,MAAoE;AAAA,gBAApEgB,EAAoEuH,IAAA;AAAA,8BAA/C1B,EAAA;AAAA,gEAAAA,EAAM,QAAA1F;AAAA,kBAAG,MAAMyF,EAAA;AAAA,kBAAO,cAAYU,EAAA;AAAA,gBAAA;;;;YAGzDtG,EAQSF,EAAAuH,CAAA,GAAA;AAAA,cARD,OAAM;AAAA,cAAiB,OAAOvH,EAAAd,CAAA,EAAC,yBAAA;AAAA,YAAA;yBACrC,MAME;AAAA,gBANFgB,EAMEwH,IAAA;AAAA,8BALS5I,EAAA;AAAA,gEAAAA,EAAO,QAAAuB;AAAA,kBACf,QAAQ0F,EAAA;AAAA,kBACR,QAAQG,EAAA;AAAA,kBACR,UAAUJ,EAAA,MAAK;AAAA,kBACf,eAAeA,EAAA,MAAK;AAAA,gBAAA;;;;YAIzB5F,EAESF,EAAAuH,CAAA,GAAA;AAAA,cAFD,OAAM;AAAA,cAAY,OAAOvH,EAAAd,CAAA,EAAC,oBAAA;AAAA,YAAA;yBAChC,MAAwD;AAAA,gBAAxDgB,EAAwDyH,IAAA;AAAA,8BAAhC7I,EAAA;AAAA,gEAAAA,EAAO,QAAAuB;AAAA,kBAAG,MAAMyF,EAAA,MAAK;AAAA,gBAAA;;;;YAG/C5F,EAESF,EAAAuH,CAAA,GAAA;AAAA,cAFD,OAAM;AAAA,cAAS,OAAOvH,EAAAd,CAAA,EAAC,iBAAA;AAAA,YAAA;yBAC7B,MAAkE;AAAA,gBAAlEgB,EAAkE0H,IAAA;AAAA,kBAArD,MAAM9B,EAAA;AAAA,kBAAO,MAAM9F,EAAAuC,CAAA,EAAS;AAAA,kBAAO,QAAQwD,EAAA;AAAA,gBAAA;;;;;;;QAIvCS,EAAA,cAArBzG,EAEgBC,EAAA6H,EAAA,GAAA,EAAA,KAAA,KAAA;AAAA,qBADd,MAA2F;AAAA,YAA3F3H,EAA2FF,EAAAoF,EAAA,GAAA;AAAA,cAAhF,MAAK;AAAA,cAAW,SAASa,EAAA;AAAA,cAAS,SAAOe;AAAA,YAAA;yBAAM,MAAqB;AAAA,oBAAlBhH,EAAAd,CAAA,EAAC,YAAA,CAAA,GAAA,CAAA;AAAA,cAAA;;;;;;;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SubmissionPage-DVNKYpWH.js","sources":["../src/SubmissionPage.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxDate,\n WxNotes,\n WxScreenHead,\n type ScreenAction,\n} from '@webx-ui/module-admin'\nimport {\n confirm,\n localizedValue,\n toast,\n useLocales,\n WxAction,\n WxAlert,\n WxBadge,\n WxButton,\n WxCard,\n WxDescriptions,\n WxDescriptionsItem,\n WxEmpty,\n WxFileCard,\n WxSelect,\n WxSkeleton,\n WxTab,\n WxTabs,\n WxText,\n WxTimeline,\n WxTimelineItem,\n} from '@webx-ui/core'\nimport { createInboxApi } from './api'\nimport { useInboxMessages, useStatusName } from './i18n'\nimport type {\n ChannelDelivery,\n InboxRecipient,\n InboxStatus,\n InboxSubmission,\n SubmissionEvent,\n} from './types'\n\n/**\n * One submission, on a screen of its own (§11).\n *\n * A dialog over the list would have kept the filters under the reader's hand, and it was\n * rejected for one reason: a submission needs an address somebody can send. It goes into the\n * mail to whoever deals with it, it gets pasted into a chat, an agent links to it. What the\n * dialog would have given back is paid for here instead — the list's whole state travels in\n * the address, so the way out lands exactly where the reader was, and the arrows walk the same\n * filtered pile.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/inbox' })\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\nconst route = useRoute()\nconst router = useRouter()\nconst locales = useLocales()\nuseInboxMessages()\n\nconst t = useTranslate('webx-inbox')\n/* The notes feed is the panel's own, and so is the word for it: a second \"Notes\" in this\n module's dictionary would be the same line translated twice. */\nconst panel = useTranslate('webx-admin')\n/* Not the server's `message`: the panel says how a request failed in its own words. */\nconst message = useErrorText()\n\nconst submission = ref<InboxSubmission | null>(null)\nconst statuses = ref<InboxStatus[]>([])\nconst admins = ref<InboxRecipient[]>([])\nconst loading = ref(true)\n\nconst canUpdate = computed(() => context.can('inbox.update'))\n\nconst id = computed(() => Number(route.params.id))\n\n/** Everything the list was looking at, carried along so the arrows walk the same pile. */\nconst filter = computed(() => ({\n view: typeof route.query.view === 'string' ? route.query.view : undefined,\n search: typeof route.query.search === 'string' ? route.query.search : undefined,\n assignee: typeof route.query.assignee === 'string' ? route.query.assignee : undefined,\n}))\n\n/** Back to the list, on the form, the tab and the page it was left at. */\nconst backTo = computed(() => ({ path: props.base, query: { ...route.query } }))\n\nconst statusOptions = computed(() =>\n statuses.value.map((status) => ({ value: status.id, label: name(status) })),\n)\n\n/* Nobody is not an option in the list but the empty state of the control: a select whose\n first line means \"none\" is one somebody picks by accident, and `clearable` already says\n it. */\nconst assigneeOptions = computed(() =>\n admins.value.map((admin) => ({ value: admin.id, label: admin.name })),\n)\n\n/* In the panel's language, not the content's: a status is a word of the interface. */\nconst name = useStatusName()\n\nconst heading = computed(() => t('panel.submission', { id: String(id.value) }))\n\nconst formTitle = computed(() => {\n const form = submission.value?.form\n\n return form === undefined\n ? ''\n : localizedValue(form.title ?? {}, locales.active.value, form.slug ?? '')\n})\n\n/**\n * Where a reply goes.\n *\n * The form says which field holds the sender's address (`email_field`); without one, the first\n * answer that was asked as an e-mail is the honest guess, and where there is none the button\n * is simply not there — a `mailto:` with nothing after it opens an empty window.\n */\nconst replyTo = computed(() => {\n const values = submission.value?.values ?? []\n const answer = values.find((value) => value.type === 'email' && (value.value ?? '') !== '')\n\n return answer?.value ?? null\n})\n\nconst mailto = computed(() => {\n if (replyTo.value === null) return null\n\n const subject = encodeURIComponent(`${formTitle.value} — ${heading.value}`)\n\n return `mailto:${replyTo.value}?subject=${subject}`\n})\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n submission.value = await api.submission(id.value, filter.value)\n } catch (error) {\n toast.danger(message(error))\n void router.replace(backTo.value)\n } finally {\n loading.value = false\n }\n}\n\nasync function lists(): Promise<void> {\n try {\n statuses.value = await api.statuses()\n\n // Only where there is something to do with them: assigning is `inbox.update`, and the\n // list of administrators is not a reader's business.\n if (canUpdate.value) {\n admins.value = await api.recipients()\n }\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\n/* The arrows change the address without leaving the screen, so the record has to follow it. */\nwatch(id, () => void load(), { immediate: true })\n\nvoid lists()\n\nasync function save(input: { status_id?: number; assignee_id?: number | null }): Promise<void> {\n try {\n submission.value = await api.saveSubmission(id.value, input)\n toast.success(t('panel.saved'))\n } catch (error) {\n toast.danger(message(error))\n await load()\n }\n}\n\nfunction onStatus(value: unknown): void {\n if (typeof value === 'number') void save({ status_id: value })\n}\n\nfunction onAssignee(value: unknown): void {\n void save({ assignee_id: typeof value === 'number' ? value : null })\n}\n\n/*\n * What the screen offers: answering it, and — behind the `···` — what is done to the pile it\n * came from. Replying is the main action by §18.3, so it is the one that keeps a button of its\n * own once the head runs out of room.\n */\nconst actions = computed<ScreenAction[]>(() => {\n const list: ScreenAction[] = []\n\n if (mailto.value) {\n list.push({\n key: 'reply',\n label: t('panel.reply'),\n icon: 'mail',\n primary: true,\n href: mailto.value,\n target: '_self',\n })\n }\n\n if (canUpdate.value && submission.value !== null) {\n list.push(\n {\n key: 'unread',\n icon: 'eye-off',\n label: t('panel.mark-unread'),\n menu: true,\n run: () => void unread(),\n },\n {\n key: 'notify',\n icon: 'mail',\n label: t('panel.notify-again'),\n menu: true,\n run: () => void notifyAgain(),\n },\n {\n key: 'delete',\n icon: 'trash',\n label: t('panel.delete'),\n danger: true,\n run: () => void remove(),\n },\n )\n }\n\n return list\n})\n\n/*\n * The letter once more — after the mail settings were fixed, or for one stuck in a queue that\n * no worker reads. A form that names nobody is refused by the server, and that is said here.\n */\nasync function notifyAgain(): Promise<void> {\n try {\n submission.value = await api.notifySubmission(id.value)\n toast.success(t('panel.notify-sent-again'))\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nconst notification = computed(() => submission.value?.notification ?? null)\n\nfunction recipientState(state: string): string {\n return t(`panel.notify-recipient-${state}`)\n}\n\n/*\n * What the channels of the notifications module made of it (NOTIFICATIONS §15.3) — null on a\n * site without that module, and then there is no tab for it at all.\n */\nconst channels = computed(() => submission.value?.channels ?? null)\n\n/* A channel that did not deliver is said above the strip: nobody opens a tab to look for it. */\nconst channelsFailed = computed(() => (channels.value ?? []).some((row) => row.status === 'failed'))\n\nconst channelsRetryable = computed(() => (channels.value ?? []).some((row) => row.retryable))\n\nfunction channelTone(row: ChannelDelivery): 'danger' | 'success' | 'warning' | 'default' {\n if (row.status === 'failed') return 'danger'\n if (row.status === 'sent') return 'success'\n if (row.status === 'skipped') return 'warning'\n\n return 'default'\n}\n\nasync function unread(): Promise<void> {\n try {\n await api.massSubmissions({ ids: [id.value], action: 'unread' })\n // Straight back to the list: a submission marked unread and then left open is one the\n // next request would mark read again.\n void router.push(backTo.value)\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nasync function remove(): Promise<void> {\n const agreed = await confirm({\n title: t('panel.delete-submission-title'),\n message: t('panel.delete-submission-text'),\n confirmText: t('panel.delete'),\n cancelText: t('panel.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n try {\n await api.removeSubmission(id.value)\n toast.success(t('panel.deleted'))\n void router.push(backTo.value)\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nfunction go(to: number | null): void {\n if (to === null) return\n\n void router.push({ path: `${props.base}/submissions/${to}`, query: { ...route.query } })\n}\n\n/**\n * A status the log names, in the words the panel calls it by.\n *\n * The log stores the key on purpose — read months later, the row it pointed at may have been\n * renamed or deleted, and history must not be rewritten by either. So the key is translated\n * where the panel still has that status, and shown as it stands where it does not: `spam` is\n * a poorer line than \"Спам\", and an invented one would be worse than both.\n */\nfunction statusName(key: string): string {\n const status = statuses.value.find((one) => one.key === key)\n\n return status === undefined ? key : name(status)\n}\n\nconst namesNobody = computed(\n () => submission.value?.events?.some((event) => event.type === 'no_recipients') ?? false,\n)\n\n/** One line of the log, in words rather than as a pair of columns. */\nfunction line(event: SubmissionEvent): string {\n switch (event.type) {\n case 'created':\n return t('panel.event-created')\n case 'status':\n return t('panel.event-status', { to: statusName(event.to ?? '') })\n case 'assignee':\n return event.to === null || event.to === ''\n ? t('panel.event-unassigned')\n : t('panel.event-assignee', { to: event.to })\n case 'note':\n return t('panel.event-note')\n case 'notified':\n return t('panel.event-notified')\n // A handler of `webx-inbox.handlers`: `from` is its class, shown by its own short name.\n case 'handled':\n return t('panel.event-handled', { name: handlerName(event.from) })\n case 'handler_error':\n return t('panel.event-handler-error', {\n name: handlerName(event.from),\n error: event.to ?? '',\n })\n case 'no_recipients':\n return t('panel.event-no-recipients')\n case 'notify_queued':\n return t('panel.event-notify-queued')\n case 'notify_failed':\n return t('panel.event-notify-failed', { to: event.to ?? '' })\n // An answer corrected by hand: named by the label it was asked under, when it still has one.\n case 'value':\n return t('panel.event-value', {\n field: answerLabel(event.field ?? ''),\n from: event.from ?? '',\n to: event.to ?? '',\n })\n default:\n return event.type\n }\n}\n\nfunction answerLabel(name: string): string {\n const answer = submission.value?.values.find((value) => value.name === name)\n\n return answer?.label || name\n}\n\nfunction handlerName(name: string | null): string {\n return (name ?? '').split('\\\\').pop() ?? ''\n}\n\nfunction kilobytes(size: number): string {\n return `${Math.max(1, Math.round(size / 1024))} KB`\n}\n\n/** The metadata worth showing, in the order somebody reads it, with the empty ones left out. */\nconst details = computed(() => {\n const meta = submission.value?.meta ?? {}\n\n const rows: { label: string; value: string; link?: boolean }[] = []\n\n if (typeof meta.page === 'string' && meta.page !== '') {\n rows.push({ label: t('panel.meta-page'), value: meta.page, link: true })\n }\n\n // Where on that page the form stood — the footer, an article — beside the page it answers.\n const placement = submission.value?.placement\n if (typeof placement === 'string' && placement !== '') {\n rows.push({ label: t('panel.meta-placement'), value: placement })\n }\n\n if (typeof meta.referrer === 'string' && meta.referrer !== '') {\n rows.push({ label: t('panel.meta-referrer'), value: meta.referrer, link: true })\n }\n\n for (const [key, value] of Object.entries(meta.utm ?? {})) {\n rows.push({ label: key, value: String(value) })\n }\n\n if (typeof meta.locale === 'string' && meta.locale !== '') {\n rows.push({ label: t('panel.meta-locale'), value: meta.locale })\n }\n\n if (typeof meta.ip === 'string' && meta.ip !== '') {\n rows.push({ label: t('panel.meta-ip'), value: meta.ip })\n }\n\n if (typeof meta.user_agent === 'string' && meta.user_agent !== '') {\n rows.push({ label: t('panel.meta-agent'), value: meta.user_agent })\n }\n\n return rows\n})\n</script>\n\n<template>\n <div class=\"wx-submission\">\n <wx-screen-head :title=\"heading\" :subtitle=\"formTitle\" :back=\"backTo\" :actions=\"actions\">\n <!--\n The same pile the reader was looking at, one step at a time. Not an action with a word\n on it, so not something the head can fold into a menu: an arrow with nowhere to go is\n disabled rather than hidden, because a control that changes shape at the ends is one\n that moves under the hand.\n -->\n <template #extra>\n <wx-action\n icon=\"chevron-left\"\n size=\"lg\"\n :title=\"t('panel.previous')\"\n :disabled=\"!submission?.previous_id\"\n @click=\"go(submission?.previous_id ?? null)\"\n />\n <wx-action\n icon=\"chevron-right\"\n size=\"lg\"\n :title=\"t('panel.next')\"\n :disabled=\"!submission?.next_id\"\n @click=\"go(submission?.next_id ?? null)\"\n />\n </template>\n </wx-screen-head>\n\n <wx-skeleton v-if=\"loading\" :rows=\"6\" />\n\n <div v-else-if=\"submission\" class=\"wx-submission__panes\">\n <div class=\"wx-submission__main\">\n <wx-card :title=\"t('panel.answers')\">\n <wx-empty\n v-if=\"submission.values.length === 0\"\n size=\"sm\"\n :description=\"t('panel.no-answers')\"\n />\n <!-- The labels are the snapshot written when it arrived, never the field's current\n words: a submission from a year ago has to read as it did (§2.2). -->\n <wx-descriptions v-else :columns=\"1\" layout=\"vertical\">\n <wx-descriptions-item\n v-for=\"value in submission.values\"\n :key=\"value.id\"\n :label=\"value.label ?? value.name\"\n >\n <p class=\"wx-submission__value\">{{ value.value || '—' }}</p>\n </wx-descriptions-item>\n </wx-descriptions>\n </wx-card>\n\n <wx-card v-if=\"submission.files.length > 0\" :title=\"t('panel.attachments')\">\n <div class=\"wx-submission__files\">\n <!-- Through the panel and not from the disk: the bytes are behind the same\n permission as the submission, for as long as the reader has it (§8). -->\n <wx-file-card\n v-for=\"file in submission.files\"\n :key=\"file.id\"\n :name=\"file.name\"\n :type=\"file.mime ?? undefined\"\n :download-url=\"file.url\"\n :download-label=\"t('panel.download')\"\n size=\"sm\"\n >\n <template #meta>{{ kilobytes(file.size) }}</template>\n </wx-file-card>\n </div>\n </wx-card>\n\n <!--\n Everything about the submission rather than in it, behind one strip.\n\n Three cards stacked down a column is three headings to read past before the eye gets\n to the one that was wanted, and on a phone it is three screens of scrolling. They are\n not read together — a note is written while replying, the log is opened when\n something looks wrong, the metadata once — so only one of them is ever the answer.\n Pills rather than a line, and inside the card rather than over it: this is one card\n changing its contents, not a place in the panel that can be navigated to. The strip is\n the card's heading — which is why there is no other one.\n -->\n <wx-alert\n v-if=\"channelsFailed\"\n type=\"warning\"\n :closable=\"false\"\n :title=\"t('panel.channels-failed')\"\n />\n\n <wx-card class=\"wx-submission__more\">\n <wx-tabs variant=\"pill\" :aria-label=\"heading\">\n <wx-tab value=\"notes\" :label=\"panel('notes.title')\">\n <!-- The feed is the panel's own, not this module's: the same one will hang off\n an order and a client (§2.17). Its heading is the tab. -->\n <wx-notes\n :id=\"submission.id\"\n type=\"inbox_submission\"\n title=\"\"\n :can=\"canUpdate\"\n @change=\"load\"\n />\n </wx-tab>\n\n <wx-tab value=\"log\" :label=\"t('panel.log')\">\n <wx-timeline size=\"sm\">\n <wx-timeline-item v-for=\"event in submission.events\" :key=\"event.id\">\n <!-- What happened on one line and who did it when on the next: three inline\n pieces in a row run into each other, and a log is read down. -->\n <wx-text size=\"sm\" as=\"p\" class=\"wx-submission__event\">{{ line(event) }}</wx-text>\n <p class=\"wx-submission__by\">\n <wx-text size=\"sm\" tone=\"muted\">\n {{ event.author?.name ?? t('panel.system') }}\n </wx-text>\n <wx-date :value=\"event.created_at\" />\n </p>\n </wx-timeline-item>\n </wx-timeline>\n </wx-tab>\n\n <wx-tab value=\"details\" :label=\"t('panel.details')\">\n <div class=\"wx-submission__fields\">\n <wx-descriptions :columns=\"1\" layout=\"vertical\" size=\"sm\">\n <wx-descriptions-item :label=\"t('panel.received')\">\n <wx-date :value=\"submission.created_at\" tone=\"default\" />\n </wx-descriptions-item>\n <wx-descriptions-item :label=\"t('panel.meta-source')\">\n <wx-badge :type=\"submission.source === 'panel' ? 'info' : 'default'\">\n {{\n submission.source === 'panel'\n ? t('panel.source-panel')\n : t('panel.source-web')\n }}\n </wx-badge>\n </wx-descriptions-item>\n <wx-descriptions-item v-for=\"row in details\" :key=\"row.label\" :label=\"row.label\">\n <a v-if=\"row.link\" :href=\"row.value\" target=\"_blank\" rel=\"noreferrer\">{{\n row.value\n }}</a>\n <span v-else class=\"wx-submission__detail\">{{ row.value }}</span>\n </wx-descriptions-item>\n </wx-descriptions>\n\n <!-- An unsent notification is a mark on the submission, not a lost one\n (§2.10). Queued is not sent: on a site with a queue a worker sends it,\n and a worker can be missing or hold old mail settings (§9). -->\n <wx-alert\n v-if=\"notification?.state === 'failed'\"\n type=\"warning\"\n :closable=\"false\"\n :title=\"t('panel.notify-failed')\"\n >\n <span class=\"wx-submission__detail\">{{ notification.error }}</span>\n </wx-alert>\n <wx-text v-else-if=\"notification?.state === 'queued'\" size=\"sm\" tone=\"muted\">\n {{ t('panel.notify-queued') }}\n </wx-text>\n <wx-text v-else-if=\"notification?.state === 'delivered'\" size=\"sm\" tone=\"muted\">\n {{ t('panel.notified') }}\n </wx-text>\n <!-- Nobody named is not a letter waiting in the queue, and says so. -->\n <wx-text v-else-if=\"namesNobody\" size=\"sm\" tone=\"muted\">\n {{ t('panel.notified-nobody') }}\n </wx-text>\n <wx-text v-else size=\"sm\" tone=\"muted\">{{ t('panel.not-notified') }}</wx-text>\n\n <ul\n v-if=\"notification && notification.recipients.length > 0\"\n class=\"wx-submission__recipients\"\n >\n <li v-for=\"one in notification.recipients\" :key=\"one.address\">\n <wx-text size=\"sm\">{{ one.address }}</wx-text>\n <wx-badge\n :type=\"\n one.state === 'failed'\n ? 'danger'\n : one.state === 'delivered'\n ? 'success'\n : 'default'\n \"\n >\n {{ recipientState(one.state) }}\n </wx-badge>\n </li>\n </ul>\n\n <div\n v-if=\"\n canUpdate &&\n (notification?.state === 'failed' || notification?.state === 'queued')\n \"\n >\n <wx-button size=\"sm\" @click=\"notifyAgain\">{{\n t('panel.notify-again')\n }}</wx-button>\n </div>\n </div>\n </wx-tab>\n <wx-tab v-if=\"channels\" value=\"channels\" :label=\"t('panel.channels')\">\n <div class=\"wx-submission__fields\">\n <wx-text v-if=\"channels.length === 0\" size=\"sm\" tone=\"muted\">\n {{ t('panel.channels-none') }}\n </wx-text>\n <ul v-else class=\"wx-submission__recipients\">\n <li v-for=\"row in channels\" :key=\"row.id\" class=\"wx-submission__channel\">\n <div class=\"wx-submission__channel-text\">\n <wx-text size=\"sm\">{{ row.channel }}</wx-text>\n <wx-text v-if=\"row.recipient !== ''\" size=\"sm\" tone=\"muted\">\n {{ row.recipient_label ?? row.recipient }}\n </wx-text>\n <wx-text\n v-if=\"row.error ?? row.reason_label\"\n size=\"sm\"\n tone=\"muted\"\n class=\"wx-submission__detail\"\n >\n {{ row.error ?? row.reason_label }}\n </wx-text>\n </div>\n <wx-badge :type=\"channelTone(row)\">{{ row.status_label }}</wx-badge>\n </li>\n </ul>\n\n <div v-if=\"canUpdate && channelsRetryable\">\n <wx-button size=\"sm\" @click=\"notifyAgain\">{{\n t('panel.notify-again')\n }}</wx-button>\n </div>\n </div>\n </wx-tab>\n </wx-tabs>\n </wx-card>\n </div>\n\n <aside class=\"wx-submission__aside\">\n <wx-card>\n <div class=\"wx-submission__fields\">\n <label class=\"wx-submission__field\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.status') }}</wx-text>\n <wx-select\n :model-value=\"submission.status?.id ?? null\"\n :options=\"statusOptions\"\n :disabled=\"!canUpdate\"\n @update:model-value=\"onStatus\"\n />\n </label>\n\n <label class=\"wx-submission__field\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.assignee') }}</wx-text>\n <wx-select\n :model-value=\"submission.assignee?.id ?? null\"\n :options=\"assigneeOptions\"\n :disabled=\"!canUpdate\"\n clearable\n :placeholder=\"t('panel.unassigned')\"\n @update:model-value=\"onAssignee\"\n />\n </label>\n </div>\n </wx-card>\n </aside>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-submission {\n display: flex;\n flex-direction: column;\n /* The panel says how far apart things stand, and it says something different on a phone\n than on a desktop (8, 12, 16). Writing the desktop number here is what made this screen\n the one place in the panel with desktop air on a 375px screen. */\n gap: var(--wx-gap, var(--wx-space-16));\n min-width: 0;\n /* The panes below decide their own layout from the width of the screen rather than of the\n window: the panel has a sidebar, and the window knows nothing about it. */\n container-type: inline-size;\n}\n\n.wx-submission__panes {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n min-width: 0;\n}\n\n.wx-submission__main,\n.wx-submission__aside {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n min-width: 0;\n}\n\n/* The answers are what the screen is for, so they take the room; everything about the\n submission rather than in it stands beside them. */\n@container (min-width: 900px) {\n .wx-submission__panes {\n flex-direction: row;\n align-items: flex-start;\n }\n\n .wx-submission__main {\n flex: 1 1 auto;\n }\n\n .wx-submission__aside {\n flex: 0 0 320px;\n max-width: 320px;\n }\n}\n\n.wx-submission__value {\n margin: 0;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n.wx-submission__detail {\n overflow-wrap: anywhere;\n}\n\n.wx-submission__recipients {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.wx-submission__recipients li {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-8);\n overflow-wrap: anywhere;\n}\n\n/* The channel, who it went to and why not on the left; the badge stays on the right. */\n.wx-submission__recipients li.wx-submission__channel {\n flex-wrap: nowrap;\n justify-content: space-between;\n align-items: flex-start;\n}\n\n.wx-submission__channel-text {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.wx-submission__event {\n margin: 0;\n}\n\n.wx-submission__by {\n display: flex;\n align-items: baseline;\n gap: var(--wx-space-6);\n flex-wrap: wrap;\n margin: 0;\n}\n\n.wx-submission__files {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-8);\n}\n\n.wx-submission__fields {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n.wx-submission__field {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n}\n</style>\n"],"names":["props","__props","context","useAdmin","api","createInboxApi","route","useRoute","router","useRouter","locales","useLocales","useInboxMessages","useTranslate","panel","message","useErrorText","submission","ref","statuses","admins","loading","canUpdate","computed","id","filter","backTo","statusOptions","status","name","assigneeOptions","admin","useStatusName","heading","formTitle","form","localizedValue","replyTo","value","mailto","subject","load","error","toast","lists","watch","save","input","onStatus","onAssignee","actions","list","unread","notifyAgain","remove","notification","recipientState","state","channels","channelsFailed","row","channelsRetryable","channelTone","confirm","go","to","statusName","key","one","namesNobody","event","line","handlerName","answerLabel","kilobytes","size","details","meta","rows","placement","_openBlock","_createElementBlock","_hoisted_1","_createVNode","_unref","WxScreenHead","WxAction","_cache","$event","_createBlock","WxSkeleton","_hoisted_2","_createElementVNode","_hoisted_3","WxCard","WxEmpty","WxDescriptions","_Fragment","_renderList","WxDescriptionsItem","_hoisted_4","_toDisplayString","_hoisted_5","file","WxFileCard","WxAlert","WxTabs","WxTab","WxNotes","WxTimeline","WxTimelineItem","WxText","_createTextVNode","_hoisted_6","WxDate","_hoisted_7","WxBadge","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","WxButton","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","_hoisted_17","_hoisted_18","_hoisted_19","WxSelect","_hoisted_20"],"mappings":"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"}
|