@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":"index-BQj2UlUS.js","sources":["../src/messages.ts","../src/i18n.ts","../src/FormField.vue","../src/module.ts","../src/api.ts","../src/options.ts","../src/SubmissionCreateDialog.vue","../src/SubmissionList.vue","../src/LocalizedRichText.vue","../src/types.ts","../src/FieldDialog.vue","../src/FieldList.vue","../src/index.ts"],"sourcesContent":["import type { Messages } from '@webx-ui/module-admin'\n\n/**\n * What this package says, in English — the same keys `webx-ui/module-inbox` ships as\n * `lang/en/*.php`, so a key never reaches the screen while the dictionary is still on its way.\n *\n * The server's dictionary wins over these. There is no second dictionary inside this package:\n * a module translated into ten languages with an English dialog in the middle of it is worse\n * than one that is not translated at all, and the only way to notice that gap is to compare\n * the two lists — which `messages.test.ts` does.\n *\n * Placeholders are Laravel's, `:like-this`: the same line is read from a PHP file and from\n * here, and only one of the two spellings can be right.\n */\nexport const inboxMessages: Record<string, Messages> = {\n module: {\n title: 'Inbox',\n },\n\n panel: {\n forms: 'Forms',\n 'new-form': 'New form',\n 'no-forms': 'No forms yet.',\n 'no-forms-help': 'A form is a few questions and a list of who hears the answers.',\n unread: 'Unread',\n submissions: 'Submissions in all',\n off: 'Off',\n settings: 'Settings',\n duplicate: 'Duplicate',\n delete: 'Delete',\n 'delete-form-title': 'Delete “:form”?',\n 'delete-form-text': 'The form and its questions go. This cannot be undone.',\n cancel: 'Cancel',\n save: 'Save',\n saved: 'Saved.',\n deleted: 'Deleted.',\n duplicated: 'A copy was made.',\n failed: 'Some values were not accepted. Check the highlighted fields.',\n 'reorder-failed': 'The new order could not be saved.',\n reorder: 'Reorder',\n 'new-form-title': 'New form',\n title: 'Title',\n slug: 'Address',\n 'slug-help': 'What the form is called on the site and where it posts.',\n 'is-enabled': 'Active',\n 'is-enabled-help': 'A form that is off is neither drawn nor accepted.',\n 'tab-general': 'General',\n 'tab-fields': 'Fields',\n 'tab-notifications': 'Notifications',\n 'tab-antispam': 'Antispam',\n 'tab-embed': 'Embedding',\n 'after-sending': 'After sending',\n 'thank-you-heading': 'Heading',\n 'thank-you-text': 'Text',\n 'submit-text': 'Text on the button',\n redirect: 'Go to this address instead',\n 'redirect-help': 'Left empty, the thank-you takes the form’s place on the page.',\n recipients: 'Who is written to',\n 'recipients-help': 'Nobody here means nobody is told. The submission is kept either way.',\n 'no-recipients': 'Nobody yet.',\n 'add-admin': 'Add an administrator',\n 'add-email': 'Add an address',\n remove: 'Remove',\n 'remove-recipient-title': 'Remove this recipient?',\n 'remove-recipient-text': 'They stop being told when something arrives.',\n 'email-field': 'The field holding the sender’s address',\n 'email-field-help': 'A reply to the notification then goes to whoever wrote in.',\n 'notify-through': 'Notify through',\n 'notify-through-help':\n 'Channels of the Notifications section: Telegram, e-mail and others. A submission from the site goes to each of them by its own template, beside the letter above.',\n 'pick-channels': 'Add a channel',\n 'no-channels': 'No channels chosen.',\n 'set-up-channels': 'Set up channels',\n channels: 'Channels',\n 'channels-none': 'Nothing was sent through channels.',\n 'channels-failed': 'A channel did not deliver the notification',\n 'no-email-field': 'None',\n honeypot: 'Hidden field',\n 'honeypot-help': 'A field nobody sees and a robot fills in.',\n 'min-seconds': 'Fastest a person could send it, in seconds',\n 'min-seconds-help': 'Zero switches the check off.',\n throttle: 'Sends a minute from one address',\n 'throttle-help': 'Zero switches the limit off.',\n captcha: 'Captcha',\n 'captcha-keys':\n 'The keys are not set in the panel but in the site’s .env: WEBX_INBOX_RECAPTCHA_KEY / WEBX_INBOX_RECAPTCHA_SECRET for reCAPTCHA, WEBX_INBOX_TURNSTILE_KEY / WEBX_INBOX_TURNSTILE_SECRET for Turnstile.',\n 'captcha-off': 'Off',\n 'captcha-recaptcha': 'reCAPTCHA',\n 'captcha-turnstile': 'Turnstile',\n 'captcha-unconfigured':\n 'The site has no keys for this captcha yet, so the form refuses every submission until they are in its .env.',\n 'captcha-recaptcha-checkbox':\n 'This site draws reCAPTCHA as the “I’m not a robot” checkbox, so its keys must be v2 Checkbox keys. To run it invisibly, create v2 Invisible keys and set WEBX_INBOX_RECAPTCHA_TYPE=invisible.',\n 'captcha-recaptcha-invisible':\n 'This site runs reCAPTCHA invisibly when the form is sent, so its keys must be v2 Invisible keys (WEBX_INBOX_RECAPTCHA_TYPE=invisible).',\n 'captcha-recaptcha-v3':\n 'This site runs reCAPTCHA v3: no widget, only a score checked when the form is sent, so its keys must be v3 keys (WEBX_INBOX_RECAPTCHA_TYPE=v3).',\n 'captcha-turnstile-checkbox':\n 'This site draws Turnstile when the page opens, and a Managed widget shows visitors “Verify you are human”. To run it invisibly, set WEBX_INBOX_TURNSTILE_MODE=invisible and the widget mode to Invisible in Cloudflare.',\n 'captcha-turnstile-invisible':\n 'This site runs Turnstile invisibly when the form is sent. Set the widget mode to Invisible in Cloudflare: a Managed widget still shows a challenge when it decides one is needed.',\n 'embed-blade': 'On a page of the site',\n 'embed-blade-help':\n 'Put the tag where the form belongs. The markup is published and rewritten by the site.',\n 'embed-block': 'In the block builder',\n 'embed-block-help':\n 'A block type prints the same tag, so an editor drops the form in without touching a template.',\n 'embed-block-panel-help':\n 'On this site block templates are written in the panel, in Blocks: put the same tag into the template of a block there.',\n 'embed-extras': 'Filled in and placed',\n 'embed-extras-help':\n ':values fills the hidden fields by their name; placement names where the form stands, so the submission remembers it and the site can style each place.',\n loading: 'Loading…',\n 'embed-names': 'Names of the fields',\n 'embed-names-help':\n 'A hidden field is filled in by the page: the address it was sent from, a product, a campaign.',\n copy: 'Copy',\n copied: 'Copied.',\n statuses: 'Statuses',\n 'new-status': 'New status',\n 'status-key': 'Key',\n 'status-color': 'Colour',\n 'status-default': 'Given to a new submission',\n 'status-spam': 'Spam',\n 'status-closed': 'Nothing further expected',\n 'in-use': 'In use',\n 'delete-status-title': 'Delete “:status”?',\n 'delete-status-text': 'Only a status nothing is in can go.',\n 'no-statuses': 'No statuses yet.',\n 'color-default': 'Grey',\n 'color-primary': 'Blue',\n 'color-success': 'Green',\n 'color-warning': 'Amber',\n 'color-info': 'Cyan',\n 'color-danger': 'Red',\n\n // The submissions: the list on the right of the section, and one of them opened.\n id: 'ID',\n received: 'Received',\n status: 'Status',\n assignee: 'Assignee',\n unassigned: 'Nobody',\n 'submissions-empty': 'Nothing has come in through this form yet.',\n 'search-submissions': 'Search the answers',\n 'view-all': 'All',\n 'view-unread': 'Unread',\n export: 'Export',\n 'new-submission': 'New submission',\n 'new-submission-title': 'A submission by hand',\n 'new-submission-help':\n 'For one that came by telephone or on paper. It is written the same way and lands in the same list.',\n created: 'Added.',\n submission: 'Submission :id',\n previous: 'Previous',\n next: 'Next',\n 'mark-read': 'Mark as read',\n 'mark-unread': 'Mark as unread',\n 'delete-submission-title': 'Delete this submission?',\n 'delete-submission-text': 'It goes with its attachments. This cannot be undone.',\n selected: ':count selected',\n 'move-to': 'Move to',\n 'delete-selected-title': 'Delete :count submissions?',\n answers: 'Answers',\n attachments: 'Attachments',\n details: 'Details',\n 'meta-page': 'Page',\n 'meta-placement': 'Placement',\n 'any-placement': 'Any placement',\n 'placement-none': 'Not specified',\n 'meta-referrer': 'Came from',\n 'meta-ip': 'Address',\n 'meta-agent': 'Browser',\n 'meta-locale': 'Language',\n 'meta-source': 'How it arrived',\n 'source-web': 'From the site',\n 'source-panel': 'Typed in',\n notified: 'The notification went out',\n 'not-notified': 'No notification was sent',\n 'notify-failed': 'The notification could not be sent',\n reply: 'Reply by mail',\n log: 'What has happened',\n 'event-created': 'Arrived',\n 'event-status': 'Status: :to',\n 'event-assignee': 'Given to :to',\n 'event-unassigned': 'Left to nobody',\n 'event-note': 'A note was added',\n 'event-notified': 'The notification went out',\n 'event-handled': 'Handed to :name',\n 'event-handler-error': ':name failed: :error',\n system: 'System',\n 'no-answers': 'Nothing was filled in.',\n download: 'Download',\n 'no-files-by-hand':\n 'A file cannot be attached by hand: the files a submission carries are what was posted with it.',\n 'submissions-none': 'Nothing here under this filter.',\n 'notifies-nobody': 'Nobody is told about this form',\n 'notifies-nobody-text':\n 'Every submission is kept here, but no letter goes out. Add a recipient on the Notifications tab.',\n 'notifies-nobody-short': 'Nobody is told',\n 'recipient-admin_deleted': 'This administrator no longer exists and gets no letter.',\n 'recipient-admin_inactive': 'This administrator is switched off and gets no letter.',\n 'recipient-invalid_email': 'This is not an e-mail address.',\n 'event-no-recipients': 'Nobody was told: the form names no recipients',\n 'notified-nobody': 'No notification: the form names nobody to tell',\n 'notify-queued': 'The notification is waiting in the queue',\n 'notify-again': 'Send the notification again',\n 'notify-sent-again': 'The notification has been sent again',\n 'notify-recipient-queued': 'waiting',\n 'notify-recipient-delivered': 'sent',\n 'notify-recipient-failed': 'failed',\n 'event-notify-queued': 'The notification was queued',\n 'event-notify-failed': 'The notification to :to failed',\n 'event-value': 'Answer “:field” corrected: “:from” → “:to”',\n },\n\n fields: {\n field: 'Field',\n 'new-field': 'New field',\n 'edit-field': 'Field',\n edit: 'Edit',\n 'no-fields': 'No questions yet.',\n 'no-fields-help': 'A form with no fields draws nothing on the page.',\n 'save-first': 'Save the form first, then write its questions.',\n delete: 'Delete',\n 'delete-title': 'Delete “:field”?',\n 'delete-text': 'It stops being asked. Answers already given keep it.',\n cancel: 'Cancel',\n save: 'Save',\n name: 'Name',\n 'name-help': 'What the field is called in the HTML. Left empty, it answers to f17.',\n type: 'Type',\n title: 'Label',\n placeholder: 'Placeholder',\n help: 'Hint under the field',\n 'is-enabled': 'Shown',\n 'is-required': 'Required',\n 'is-fullsize': 'Full width',\n 'in-table': 'A column in the list',\n choices: 'Choices',\n 'choice-value': 'Value',\n 'choice-label': 'Label',\n 'add-choice': 'Add a choice',\n 'no-choices': 'No choices yet. A field with none accepts nothing.',\n maxlength: 'Longest answer, in characters',\n rows: 'Height, in lines',\n pattern: 'Pattern the answer has to match',\n 'pattern-help': 'The browser’s own, written without delimiters: [0-9+ ()-]{6,}',\n earliest: 'Earliest date',\n latest: 'Latest date',\n 'min-choices': 'Fewest ticks',\n 'max-choices': 'Most ticks',\n 'consent-text': 'The sentence beside the tick',\n 'consent-text-help': 'A link is allowed here: it is printed as written.',\n 'max-size': 'Largest file, in kilobytes',\n extensions: 'Extensions allowed',\n 'extensions-help': 'Comma separated. Empty means the list the site allows.',\n multiple: 'Several files at once',\n 'type-text': 'Text',\n 'type-email': 'E-mail',\n 'type-tel': 'Telephone',\n 'type-textarea': 'Long text',\n 'type-select': 'Drop-down',\n 'type-radio': 'One of several',\n 'type-checkbox': 'Several of several',\n 'type-consent': 'Consent',\n 'type-date': 'Date',\n 'type-file': 'File',\n 'type-hidden': 'Hidden',\n },\n\n relations: {\n form: 'Form',\n 'field-search': 'Find a form by its name or address',\n 'field-empty': 'No form',\n 'field-remove': 'Remove the form',\n 'field-missing': 'No such form',\n 'field-off': 'Switched off',\n 'field-nothing': 'No form matches',\n 'field-searching': 'Searching…',\n unknown: 'The Inbox has no form “:slug”. It has: :forms.',\n 'unknown-none': 'The Inbox has no form “:slug” — it has no forms yet.',\n },\n}\n","import { inject } from 'vue'\nimport { localizedValue, useLocales } from '@webx-ui/core'\nimport { i18nKey, useAdmin } from '@webx-ui/module-admin'\nimport { inboxMessages } from './messages'\nimport type { InboxStatus } from './types'\n\nconst seeded = new WeakSet<object>()\n\n/** Puts this package's English under the panel's dictionary, once per panel. */\nexport function useInboxMessages(): void {\n try {\n const { i18n } = useAdmin()\n\n if (!seeded.has(i18n)) {\n i18n.defaults('webx-inbox', inboxMessages)\n seeded.add(i18n)\n }\n } catch {\n // Outside a panel there is no dictionary to seed, and `useTranslate` falls back on its own.\n }\n}\n\n/**\n * A status's name in the language the panel is drawn in.\n *\n * A status is a panel word — \"New\", \"In progress\", \"Done\" — read by whoever works the inbox,\n * never by a visitor, so it follows the interface and not the content language picked for\n * editing; that one only stands in when the status has no line in the panel's language. Then\n * any line it has, then its key.\n */\nexport function useStatusName(): (status: InboxStatus) => string {\n const panel = inject(i18nKey, null)\n const locales = useLocales()\n\n return (status) => {\n const locale = panel?.state.locale\n const own = locale === undefined ? undefined : status.title[locale]\n\n return own || localizedValue(status.title, locales.active.value, status.key)\n }\n}\n","<script setup lang=\"ts\">\nimport { computed, nextTick, ref, watch } from 'vue'\nimport { WxAction, WxAutocomplete, WxBadge, type AutocompleteOption } from '@webx-ui/core'\nimport { createRelationsApi, useAdmin, useTranslate } from '@webx-ui/module-admin'\nimport { useInboxMessages } from './i18n'\nimport type { FormCandidate } from './types'\n\n/**\n * `wx-inbox-form`: one form of the Inbox, chosen by name and kept by its slug — the value\n * `<x-webx-inbox::form slug=\"…\" />` takes and the blocks that print a form have always held as\n * typed text. So a block written before this field opens with its form already chosen.\n *\n * The forms come from the panel's relation target `inbox-form` (`GET /api/cms/relations/inbox-form`),\n * the one a vacancy picks its application form from: no inbox permission is needed to choose a\n * form, only to read what it receives. The target searches the slug as well as the title and puts\n * the exact slug first, which is how a stored slug is named when the field opens.\n *\n * A slug no form has stays in the field, marked: dropping it silently would change the block\n * without anybody touching it, and the server refuses such a slug only when it is written anew.\n */\ndefineOptions({ name: 'WxInboxFormField' })\n\nconst props = withDefaults(\n defineProps<{\n disabled?: boolean\n placeholder?: string\n emptyText?: string\n }>(),\n { disabled: false, placeholder: undefined, emptyText: undefined },\n)\n\nconst value = defineModel<string | null>({ default: null })\n\nuseInboxMessages()\n\nconst admin = useAdmin()\nconst t = useTranslate('webx-inbox')\nconst api = createRelationsApi(admin, 'inbox-form')\n\nconst slug = computed(() => (typeof value.value === 'string' ? value.value.trim() : ''))\n\n/** Forms the server described, by slug, kept for the life of the field. */\nconst known = ref(new Map<string, FormCandidate>())\n/** Slugs the server was asked about and has no form for. */\nconst missing = ref(new Set<string>())\n\nconst candidates = ref<FormCandidate[]>([])\nconst searching = ref(false)\nconst term = ref('')\n\nfunction remember(rows: FormCandidate[]): void {\n const next = new Map(known.value)\n\n for (const row of rows) if (row.slug) next.set(row.slug, row)\n\n known.value = next\n}\n\nasync function name(wanted: string): Promise<void> {\n if (wanted === '' || known.value.has(wanted) || missing.value.has(wanted)) return\n\n try {\n const rows = (await api.search(wanted)) as FormCandidate[]\n remember(rows)\n\n if (!rows.some((row) => row.slug === wanted))\n missing.value = new Set([...missing.value, wanted])\n } catch {\n // A request that did not come back is not an answer: the slug shows as it is until the next try.\n }\n}\n\nwatch(slug, (wanted) => void name(wanted), { immediate: true })\n\nconst chosen = computed(() => (slug.value === '' ? null : (known.value.get(slug.value) ?? null)))\n\n/** A mark for the chosen form: the server has none by that slug, or the site does not print it. */\nconst mark = computed(() => {\n if (slug.value === '') return null\n if (chosen.value === null)\n return missing.value.has(slug.value) ? t('relations.field-missing') : null\n\n return chosen.value.visible ? null : t('relations.field-off')\n})\n\nconst options = computed<AutocompleteOption[]>(() =>\n candidates.value\n .filter((one) => one.slug && one.slug !== slug.value)\n .map((one) => ({\n value: one.title,\n description: [one.slug, one.visible ? null : t('relations.field-off')]\n .filter((part): part is string => typeof part === 'string' && part !== '')\n .join(' · '),\n id: one.slug,\n })),\n)\n\nasync function search(query: string): Promise<void> {\n searching.value = true\n\n try {\n const found = (await api.search(query)) as FormCandidate[]\n candidates.value = found\n remember(found)\n } catch {\n candidates.value = []\n } finally {\n searching.value = false\n }\n}\n\n/** A site has a handful of forms: the list is there on the first click, before anything is typed. */\nfunction opened(): void {\n if (candidates.value.length === 0 && !searching.value) void search(term.value)\n}\n\nfunction pick(option: AutocompleteOption): void {\n if (typeof option.id !== 'string' || option.id === '') return\n\n value.value = option.id\n\n // The box writes the picked title into itself after this handler; emptied on the next tick it\n // reads as a search box again rather than as a second copy of the choice above it.\n void nextTick(() => {\n term.value = ''\n })\n}\n\nfunction clear(): void {\n value.value = null\n}\n\nconst placeholder = computed(() => props.placeholder ?? t('relations.field-search'))\n</script>\n\n<template>\n <div class=\"wx-inbox-form-field\">\n <div v-if=\"slug !== ''\" class=\"wx-inbox-form-field__chosen\">\n <span class=\"wx-inbox-form-field__text\">\n <span class=\"wx-inbox-form-field__title\">{{ chosen?.title ?? slug }}</span>\n <span v-if=\"chosen\" class=\"wx-inbox-form-field__slug\">{{ slug }}</span>\n </span>\n <wx-badge v-if=\"mark\" type=\"warning\">{{ mark }}</wx-badge>\n <wx-action\n v-if=\"!props.disabled\"\n type=\"remove\"\n size=\"sm\"\n :title=\"t('relations.field-remove')\"\n @click=\"clear\"\n />\n </div>\n <p v-else class=\"wx-inbox-form-field__empty\">\n {{ props.emptyText ?? t('relations.field-empty') }}\n </p>\n\n <!-- A wrapper rather than a class on the box: its root is a fragment, and a scoped rule on it\n would reach nothing. -->\n <div class=\"wx-inbox-form-field__search\">\n <wx-autocomplete\n v-model=\"term\"\n :options=\"options\"\n remote\n teleport\n :loading=\"searching\"\n :loading-text=\"t('relations.field-searching')\"\n :empty-text=\"t('relations.field-nothing')\"\n :placeholder=\"placeholder\"\n :aria-label=\"placeholder\"\n :disabled=\"props.disabled\"\n @search=\"search\"\n @open=\"opened\"\n @select=\"pick\"\n />\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-inbox-form-field {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n.wx-inbox-form-field__chosen {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n min-width: 0;\n padding: var(--wx-space-6) var(--wx-space-8) var(--wx-space-6) var(--wx-space-12);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n background: var(--wx-bg-surface);\n}\n\n.wx-inbox-form-field__text {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.wx-inbox-form-field__title,\n.wx-inbox-form-field__slug {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-inbox-form-field__slug,\n.wx-inbox-form-field__empty {\n font-size: var(--wx-font-size-sm);\n color: var(--wx-text-muted);\n}\n\n.wx-inbox-form-field__empty {\n margin: 0;\n}\n\n.wx-inbox-form-field :deep(.wx-badge) {\n flex: none;\n}\n</style>\n","import type { AdminModule } from '@webx-ui/module-admin'\nimport FormField from './FormField.vue'\n\nexport interface InboxOptions {\n /** Where the section lives inside the panel. */\n path?: string\n /**\n * Whether the panel opens on this section.\n *\n * On by default, and that is the point of the module: a panel with an inbox is a panel\n * somebody opens in the morning to see what came in overnight, and the pages, the blocks\n * and the settings are what they do afterwards (§2.18). A panel whose front page is\n * something else says so here.\n */\n landing?: boolean\n}\n\n/**\n * Forms and submissions as a section of the panel.\n *\n * The id matches the module the server reports, which is what makes the entry appear in the\n * navigation: the section shows up when both halves are installed, and stays out of the way\n * when only one is.\n */\nexport function inbox(options: InboxOptions = {}): AdminModule {\n const path = options.path ?? '/inbox'\n\n return {\n id: 'inbox',\n path,\n landing: options.landing ?? true,\n routes: [\n // The section's own path travels as a prop, so a panel that mounted it somewhere else\n // still links between its screens correctly.\n {\n path,\n name: 'webx.inbox',\n component: () => import('./InboxPage.vue'),\n props: { base: path },\n },\n {\n path: `${path}/statuses`,\n name: 'webx.inbox.statuses',\n component: () => import('./StatusesPage.vue'),\n props: { base: path },\n },\n {\n path: `${path}/forms/:id(\\\\d+)`,\n name: 'webx.inbox.form',\n component: () => import('./FormEditorPage.vue'),\n props: { base: path },\n },\n // A submission has an address of its own, not a dialog over the list (§11): it goes in\n // the mail to whoever deals with it, it gets pasted into a chat, an agent links to it.\n {\n path: `${path}/submissions/:id(\\\\d+)`,\n name: 'webx.inbox.submission',\n component: () => import('./SubmissionPage.vue'),\n props: { base: path },\n },\n ],\n // A form of the Inbox as a field of any screen or block — the contact block's form — chosen\n // by name and kept by slug. Here and not in the panel: what it lists is this section's.\n types: {\n 'wx-inbox-form': { component: FormField, kind: 'field' },\n },\n }\n}\n","import type { AdminContext } from '@webx-ui/module-admin'\nimport type {\n FieldInput,\n FormInput,\n InboxField,\n InboxForm,\n InboxRecipient,\n InboxStatus,\n InboxSubmission,\n StatusInput,\n SubmissionInput,\n SubmissionMassInput,\n SubmissionQuery,\n SubmissionsPage,\n} from './types'\n\nexport interface InboxApi {\n /** Every form, in the order of the column, with what is waiting in each. */\n forms(): Promise<InboxForm[]>\n /** One form with its fields — what the editor opens. */\n form(id: number): Promise<InboxForm>\n createForm(input: FormInput): Promise<InboxForm>\n saveForm(id: number, input: FormInput): Promise<InboxForm>\n /** Refused with a 422 when the form has submissions: it is switched off, not deleted. */\n removeForm(id: number): Promise<void>\n /** A copy, switched off, with the questions and none of the answers. */\n duplicateForm(id: number): Promise<InboxForm>\n sortForms(ids: number[]): Promise<void>\n\n fields(formId: number): Promise<InboxField[]>\n createField(formId: number, input: FieldInput): Promise<InboxField>\n saveField(id: number, input: FieldInput): Promise<InboxField>\n /** Softly: the answers already given through it keep reading. */\n removeField(id: number): Promise<void>\n sortFields(formId: number, ids: number[]): Promise<void>\n\n statuses(): Promise<InboxStatus[]>\n createStatus(input: StatusInput): Promise<InboxStatus>\n saveStatus(id: number, input: StatusInput): Promise<InboxStatus>\n /** Refused with a 422 while submissions are still in it. */\n removeStatus(id: number): Promise<void>\n sortStatuses(ids: number[]): Promise<void>\n\n /** The administrators a form can be told to write to: the ones who may read the section. */\n recipients(): Promise<InboxRecipient[]>\n\n /** One form's submissions, with the columns of the list and the counts of its tabs. */\n submissions(formId: number, query?: SubmissionQuery): Promise<SubmissionsPage>\n /**\n * One of them, open. Opening it marks it read.\n *\n * The filters travel with it so that the neighbours it reports are the ones either side of\n * it in the list somebody was actually looking at.\n */\n submission(id: number, query?: SubmissionQuery): Promise<InboxSubmission>\n /** Typed in by hand — a call that came by telephone. `fields` is by machine name. */\n createSubmission(formId: number, fields: Record<string, unknown>): Promise<InboxSubmission>\n saveSubmission(id: number, input: SubmissionInput): Promise<InboxSubmission>\n removeSubmission(id: number): Promise<void>\n /** The notification once more, to whoever the form names now. Refused for a form naming nobody. */\n notifySubmission(id: number): Promise<InboxSubmission>\n /** A pile moved, marked or thrown away at once. */\n massSubmissions(input: SubmissionMassInput): Promise<{ count: number }>\n /**\n * Where the spreadsheet is. An address rather than a request: a download is the browser's\n * own job, and fetching a file into memory to hand it back to the browser is work for\n * nothing.\n */\n exportUrl(formId: number, query?: SubmissionQuery): string\n}\n\n/**\n * The statuses, asked once for everything on screen.\n *\n * The list of submissions and the one open beside it each want them, and each made its own\n * request — the section opened with `GET /statuses` twice. Every component makes its own api\n * object, so the answer is kept here — per HTTP client, which is one per panel — until the\n * statuses themselves are changed through this api or the request fails. Each caller gets its\n * own copy of the list: a page that reorders its statuses must not reorder everybody else's.\n */\nconst statusRequests = new WeakMap<object, Promise<InboxStatus[]>>()\n\n/** Everything under `/inbox`, below the panel's API path. */\nexport function createInboxApi(admin: AdminContext): InboxApi {\n const base = `${admin.apiPath}/inbox`\n const data = <T>(body: { data: T }): T => body.data\n const nothing = (): void => undefined\n const forgetStatuses = <T>(result: T): T => {\n statusRequests.delete(admin.http)\n\n return result\n }\n\n function statuses(): Promise<InboxStatus[]> {\n const known = statusRequests.get(admin.http)\n\n if (known !== undefined) {\n return known.then((list) => [...list])\n }\n\n const asked = admin.http.get<{ data: InboxStatus[] }>(`${base}/statuses`).then(data)\n\n statusRequests.set(admin.http, asked)\n asked.catch(() => statusRequests.delete(admin.http))\n\n return asked.then((list) => [...list])\n }\n\n return {\n forms: () => admin.http.get<{ data: InboxForm[] }>(`${base}/forms`).then(data),\n form: (id) => admin.http.get<{ data: InboxForm }>(`${base}/forms/${id}`).then(data),\n createForm: (input) => admin.http.post<{ data: InboxForm }>(`${base}/forms`, input).then(data),\n saveForm: (id, input) =>\n admin.http.put<{ data: InboxForm }>(`${base}/forms/${id}`, input).then(data),\n removeForm: (id) => admin.http.delete(`${base}/forms/${id}`).then(nothing),\n duplicateForm: (id) =>\n admin.http.post<{ data: InboxForm }>(`${base}/forms/${id}/duplicate`, {}).then(data),\n sortForms: (ids) => admin.http.post(`${base}/forms/sorting`, { ids }).then(nothing),\n\n fields: (formId) =>\n admin.http.get<{ data: InboxField[] }>(`${base}/forms/${formId}/fields`).then(data),\n createField: (formId, input) =>\n admin.http.post<{ data: InboxField }>(`${base}/forms/${formId}/fields`, input).then(data),\n saveField: (id, input) =>\n admin.http.put<{ data: InboxField }>(`${base}/fields/${id}`, input).then(data),\n removeField: (id) => admin.http.delete(`${base}/fields/${id}`).then(nothing),\n sortFields: (formId, ids) =>\n admin.http.post(`${base}/forms/${formId}/fields/sorting`, { ids }).then(nothing),\n\n statuses,\n createStatus: (input) =>\n admin.http\n .post<{ data: InboxStatus }>(`${base}/statuses`, input)\n .then(data)\n .then(forgetStatuses),\n saveStatus: (id, input) =>\n admin.http\n .put<{ data: InboxStatus }>(`${base}/statuses/${id}`, input)\n .then(data)\n .then(forgetStatuses),\n removeStatus: (id) =>\n admin.http.delete(`${base}/statuses/${id}`).then(nothing).then(forgetStatuses),\n sortStatuses: (ids) =>\n admin.http.post(`${base}/statuses/sorting`, { ids }).then(nothing).then(forgetStatuses),\n\n recipients: () => admin.http.get<{ data: InboxRecipient[] }>(`${base}/recipients`).then(data),\n\n submissions: (formId, query = {}) =>\n admin.http\n .get<{\n data: SubmissionsPage['data']\n meta: Omit<SubmissionsPage, 'data' | 'columns' | 'counts' | 'placements'>\n columns: SubmissionsPage['columns']\n counts: SubmissionsPage['counts']\n placements?: SubmissionsPage['placements']\n }>(`${base}/forms/${formId}/submissions`, { query: listQuery(query) })\n .then((body) => ({\n ...body.meta,\n data: body.data,\n columns: body.columns,\n counts: body.counts,\n // Optional on the wire: a server from before placements answers without them.\n placements: body.placements ?? [],\n })),\n\n submission: (id, query = {}) =>\n admin.http\n .get<{ data: InboxSubmission }>(`${base}/submissions/${id}`, { query: listQuery(query) })\n .then(data),\n\n createSubmission: (formId, fields) =>\n admin.http\n .post<{ data: InboxSubmission }>(`${base}/forms/${formId}/submissions`, { fields })\n .then(data),\n\n saveSubmission: (id, input) =>\n admin.http.put<{ data: InboxSubmission }>(`${base}/submissions/${id}`, input).then(data),\n\n removeSubmission: (id) => admin.http.delete(`${base}/submissions/${id}`).then(nothing),\n\n notifySubmission: (id) =>\n admin.http.post<{ data: InboxSubmission }>(`${base}/submissions/${id}/notify`).then(data),\n\n massSubmissions: (input) =>\n admin.http.post<{ data: { count: number } }>(`${base}/submissions/mass`, input).then(data),\n\n exportUrl: (formId, query = {}) => {\n const search = new URLSearchParams()\n\n for (const [key, value] of Object.entries(listQuery(query))) {\n if (value !== undefined && value !== null && value !== '') {\n search.set(key, String(value))\n }\n }\n\n const suffix = search.toString()\n\n return `${base}/forms/${formId}/submissions/export${suffix === '' ? '' : `?${suffix}`}`\n },\n }\n}\n\n/**\n * The filters as query parameters, with the empty ones left out.\n *\n * `page` and `per_page` go too, because the same shape is what the export is asked for — the\n * server ignores them there, and a second almost-identical builder is a second thing to get\n * out of step.\n */\nfunction listQuery(query: SubmissionQuery): Record<string, string | number | undefined> {\n return {\n view: query.view === undefined || query.view === '' ? undefined : query.view,\n search: query.search === undefined || query.search === '' ? undefined : query.search,\n assignee: query.assignee ?? undefined,\n placement: query.placement ?? undefined,\n sort: query.sort ?? undefined,\n page: query.page,\n per_page: query.per_page,\n }\n}\n","import { computed, type Ref, type WritableComputedRef } from 'vue'\nimport type { FormOptions } from './types'\n\n/**\n * One setting of a form, as something a control can be bound to.\n *\n * The keys are literal and several of them have dots in them — `thank-you.heading` is one key\n * (§5) — so nothing here splits on a dot, and a whole new object is written on every change\n * rather than a property being set in place: the editor holds the options as one value, and a\n * mutation underneath it is a change nothing is told about.\n *\n * An empty value is not written as an empty value: it is taken out. The server does the same\n * when it saves, and a form whose settings are twelve blank strings reads as configured when\n * it is not.\n */\nexport function option<T>(\n options: Ref<FormOptions>,\n key: string,\n fallback: T,\n): WritableComputedRef<T> {\n return computed({\n get: () => (options.value[key] ?? fallback) as T,\n set: (value: T) => {\n const next = { ...options.value }\n\n if (value === '' || value === null || value === undefined) {\n delete next[key]\n } else {\n next[key] = value\n }\n\n options.value = next\n },\n })\n}\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport {\n localizedValue,\n toast,\n useLocales,\n useModal,\n WxAlert,\n WxButton,\n WxCheckbox,\n WxCheckboxGroup,\n WxDatePicker,\n WxDialog,\n WxFormItem,\n WxInput,\n WxRadioGroup,\n WxSelect,\n WxSkeleton,\n WxSpace,\n WxTextarea,\n} from '@webx-ui/core'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport type { InboxField, InboxForm, InboxSubmission } from './types'\n\n/**\n * A submission typed in by hand — a call that came by telephone, a form filled in on paper.\n *\n * The same questions the site asks, drawn from the same fields, and sent to the same intake:\n * the rules are the form's own, so a required field is required here too and a refusal reads\n * the same way. The one thing the panel cannot do is attach a visitor's file, because there is\n * no visitor — the files a submission carries are what was posted with it.\n */\nconst props = defineProps<{ form: InboxForm }>()\n\nconst { resolve, dismiss, open } = useModal<InboxSubmission>()\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\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 fields = ref<InboxField[]>([])\nconst loading = ref(true)\nconst saving = ref(false)\nconst values = ref<Record<string, unknown>>({})\nconst errors = ref<Record<string, string[]>>({})\n\n/** Everything the form actually asks, files excepted. */\nconst asked = computed(() => fields.value.filter((field) => field.type !== 'file'))\n\nconst hasFiles = computed(() => fields.value.some((field) => field.type === 'file'))\n\nfunction errorOf(field: InboxField): string | undefined {\n return errors.value[`fields.${field.key}`]?.[0]\n}\n\nfunction label(field: InboxField): string {\n return localizedValue(field.title, locales.active.value, field.key)\n}\n\nfunction text(value: unknown, fallback = ''): string {\n return localizedValue(\n value as Parameters<typeof localizedValue>[0],\n locales.active.value,\n fallback,\n )\n}\n\n/** The written-down answers of a `select`, `radio` or `checkbox`, in the panel's language. */\nfunction choices(field: InboxField): { value: string; label: string }[] {\n return (field.options.choices ?? []).map((choice) => ({\n value: choice.value,\n label: text(choice.label, choice.value),\n }))\n}\n\nasync function load(): Promise<void> {\n try {\n const form = await api.form(props.form.id)\n\n fields.value = (form.fields ?? []).filter((field) => field.is_enabled)\n\n for (const field of fields.value) {\n values.value[field.key] =\n field.type === 'checkbox' ? [] : field.type === 'consent' ? false : ''\n }\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n}\n\nvoid load()\n\nasync function save(): Promise<void> {\n saving.value = true\n errors.value = {}\n\n try {\n resolve(await api.createSubmission(props.form.id, values.value))\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 <wx-dialog v-model:open=\"open\" :title=\"t('panel.new-submission-title')\" :width=\"560\">\n <div class=\"wx-inbox-by-hand\">\n <wx-alert type=\"info\" :closable=\"false\">{{ t('panel.new-submission-help') }}</wx-alert>\n\n <wx-skeleton v-if=\"loading\" :rows=\"4\" />\n\n <template v-else>\n <wx-form-item\n v-for=\"field in asked\"\n :key=\"field.id\"\n :label=\"label(field)\"\n :help=\"text(field.help)\"\n :error=\"errorOf(field)\"\n :required=\"field.is_required\"\n >\n <wx-textarea\n v-if=\"field.type === 'textarea'\"\n v-model=\"values[field.key] as string\"\n :rows=\"field.options.rows ?? 4\"\n :placeholder=\"text(field.placeholder)\"\n />\n <wx-select\n v-else-if=\"field.type === 'select'\"\n v-model=\"values[field.key] as string\"\n :options=\"choices(field)\"\n clearable\n :placeholder=\"text(field.placeholder)\"\n />\n <wx-radio-group\n v-else-if=\"field.type === 'radio'\"\n v-model=\"values[field.key] as string\"\n :options=\"choices(field)\"\n />\n <wx-checkbox-group\n v-else-if=\"field.type === 'checkbox'\"\n v-model=\"values[field.key] as string[]\"\n :options=\"choices(field)\"\n />\n <!-- The sentence beside the tick is the form's own and may carry a link, so it is\n the field's label rather than text written here. -->\n <wx-checkbox\n v-else-if=\"field.type === 'consent'\"\n v-model=\"values[field.key] as boolean\"\n :label=\"text(field.options.text, label(field))\"\n />\n <wx-date-picker\n v-else-if=\"field.type === 'date'\"\n v-model=\"values[field.key] as string\"\n :placeholder=\"text(field.placeholder)\"\n />\n <wx-input\n v-else\n v-model=\"values[field.key] as string\"\n :type=\"field.type === 'email' ? 'email' : field.type === 'tel' ? 'tel' : 'text'\"\n :placeholder=\"text(field.placeholder)\"\n :maxlength=\"field.options.maxlength\"\n />\n </wx-form-item>\n\n <!-- Said rather than silently left out: a form whose point is the attachment would\n otherwise look like it had lost a field. -->\n <wx-alert v-if=\"hasFiles\" type=\"warning\" :closable=\"false\">\n {{ t('panel.no-files-by-hand') }}\n </wx-alert>\n </template>\n </div>\n\n <template #footer>\n <wx-space size=\"sm\">\n <wx-button variant=\"outline\" @click=\"dismiss()\">{{ t('panel.cancel') }}</wx-button>\n <wx-button type=\"primary\" :loading=\"saving\" :disabled=\"loading\" @click=\"save\">\n {{ t('panel.save') }}\n </wx-button>\n </wx-space>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-inbox-by-hand {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, useTemplateRef, watch } from 'vue'\nimport { useRoute, useRouter, type LocationQueryRaw } from 'vue-router'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxDate,\n rowMenuWidth,\n WxFilterChips,\n WxRowMenu,\n WxScreenHead,\n type AppliedFilter,\n type RowAction,\n type ScreenAction,\n} from '@webx-ui/module-admin'\nimport {\n confirm,\n createModal,\n localizedValue,\n toast,\n useLocales,\n WxAvatar,\n WxBadge,\n WxButton,\n WxIcon,\n WxSelect,\n WxTable,\n WxTabs,\n WxText,\n WxEntityCard,\n WxFormItem,\n WxTooltip,\n useElementWidth,\n type TabItem,\n type TableColumn,\n type TableState,\n} from '@webx-ui/core'\nimport SubmissionCreateDialog from './SubmissionCreateDialog.vue'\nimport { createInboxApi } from './api'\nimport { useInboxMessages, useStatusName } from './i18n'\nimport type {\n InboxForm,\n InboxStatus,\n InboxSubmission,\n SubmissionRow,\n SubmissionsPage,\n} from './types'\n\n/**\n * What has come in through the chosen form — the right-hand side of the section (§11).\n *\n * Its columns are the form's own `in_table` fields and arrive with the rows, so this never has\n * to fetch the form to know what it is drawing. Which of them survive a narrow pane is decided\n * here and not by the form: the first answer identifies the row and stays at any width, and\n * each one after it goes a step earlier than the last. Pairing two of them into one cell — the\n * e-mail under the name — would mean guessing which fields mean what, and the panel does not\n * know that about somebody else's form.\n *\n * The state of the list lives in the address: coming back from a submission has to land on the\n * same form, the same tab and the same page, or the screen costs exactly that over the dialog\n * it was chosen instead of (§11).\n */\nconst props = withDefaults(\n defineProps<{\n form: InboxForm\n /** Where the section is mounted. */\n base?: string\n }>(),\n { base: '/inbox' },\n)\n\nconst emit = defineEmits<{\n /** Something changed that the column of forms counts. */\n changed: []\n}>()\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\nconst route = useRoute()\nconst router = useRouter()\nconst locales = useLocales()\nuseInboxMessages()\n\n/** Where a row stops being a row. */\nconst CARDS = 640\n\nconst root = useTemplateRef<HTMLElement>('root')\nconst width = useElementWidth(root)\nconst asCards = computed(() => width.value > 0 && width.value < CARDS)\n\n/**\n * One decision about it, not two.\n *\n * The pane measures itself and the table measures itself, and between the two stands the\n * pane's own step — so the same number meant two different widths, and in the band between\n * them the table drew cards out of the full set of columns: five lines of \"Label: value\" for\n * one enquiry, which is exactly what the card exists instead of. The table is told rather\n * than left to work it out: never, or always, and by the same measurement the columns use.\n */\nconst cardsBelow = computed(() => (asCards.value ? Number.POSITIVE_INFINITY : 0))\n\nconst t = useTranslate('webx-inbox')\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 page = ref<SubmissionsPage | null>(null)\nconst statuses = ref<InboxStatus[]>([])\nconst loading = ref(false)\nconst selected = ref<SubmissionRow[]>([])\nconst moving = ref(false)\n\nconst canUpdate = computed(() => context.can('inbox.update'))\n\nconst add = createModal<InboxSubmission, { form: InboxForm }>(SubmissionCreateDialog)\n\n/** The tab, kept in the address so the way back lands on it. */\nconst view = computed({\n get: () =>\n typeof route.query.view === 'string' && route.query.view !== '' ? route.query.view : 'all',\n set: (value: string) => {\n // A new tab is a new list: the page it was on belongs to the tab it was on.\n void router.replace({\n query: { ...route.query, view: value === 'all' ? undefined : value, page: undefined },\n })\n },\n})\n\n/** Everything the list is looking at, as it travels to the server and into the address. */\nconst query = computed(() => ({\n view: view.value,\n search: typeof route.query.search === 'string' ? route.query.search : '',\n assignee: typeof route.query.assignee === 'string' ? route.query.assignee : null,\n placement: typeof route.query.placement === 'string' ? route.query.placement : null,\n sort: typeof route.query.sort === 'string' ? route.query.sort : null,\n page: Number(route.query.page ?? 1) || 1,\n}))\n\n/*\n * Where on the site the form has been sent from — the footer, an article (layout regions §11).\n *\n * The list carries the places with its rows, over the whole form rather than the filter, so the\n * filter costs no request of its own and its choices never shrink to the one already picked. It\n * is offered only when there is more than one place: one form in one place is nothing to filter.\n * And it stays while a placement is in the address, or a filter that arrived by link could not be\n * taken off.\n */\nconst placementOptions = computed(() =>\n (page.value?.placements ?? []).map((placement) =>\n placement === null\n ? { value: 'none', label: t('panel.placement-none') }\n : { value: placement, label: placement },\n ),\n)\n\nconst hasPlacements = computed(\n () => placementOptions.value.length > 1 || query.value.placement !== null,\n)\n\nconst applied = computed<AppliedFilter[]>(() => {\n const placement = query.value.placement\n\n if (placement === null) return []\n\n const label =\n placementOptions.value.find((option) => option.value === placement)?.label ??\n (placement === 'none' ? t('panel.placement-none') : placement)\n\n return [\n {\n key: 'placement',\n label: `${t('panel.meta-placement')}: ${label}`,\n clear: () => narrow(undefined),\n },\n ]\n})\n\nfunction narrow(placement: unknown): void {\n void router.replace({\n query: {\n ...route.query,\n placement: typeof placement === 'string' && placement !== '' ? placement : undefined,\n page: undefined,\n },\n })\n}\n\nconst views = computed<TabItem[]>(() => {\n const counts = page.value?.counts\n\n const items: TabItem[] = [\n { value: 'all', label: t('panel.view-all'), badge: counts?.all || undefined },\n { value: 'unread', label: t('panel.view-unread'), badge: counts?.unread || undefined },\n ]\n\n for (const status of statuses.value) {\n items.push({\n value: status.key,\n label: name(status),\n badge: counts?.statuses[status.key] || undefined,\n })\n }\n\n return items\n})\n\n/**\n * The n-th answer of a submission, for the card that has no columns to put them in.\n *\n * By position rather than by name, because a form's fields are the form's own: the first answer\n * is what the row is recognised by wherever it came from, and the second is the next most likely\n * way to reach whoever wrote it.\n */\nfunction answer(row: SubmissionRow, index: number): string {\n const column = page.value?.columns?.[index]\n\n return column ? (row.values[column.key] ?? '') : ''\n}\n\nconst columns = computed<TableColumn<SubmissionRow>[]>(() => {\n const answers = page.value?.columns ?? []\n\n /*\n * Narrow, a submission is one entity rather than five labelled lines: who wrote it, the next\n * answer under that, and the state of it beside the date. Five lines of \"Label: value\" is four\n * hundred pixels for one enquiry, and an inbox is read in a list.\n */\n if (asCards.value) return [{ key: 'card', label: '' }]\n\n return [\n ...answers.map((column, index) => ({\n key: `values.${column.key}`,\n label: column.label,\n sortable: true,\n // The first answer is what the row is recognised by and stays at any width; every one\n // after it is worth less than the room it takes, so it goes a step sooner. The steps are\n // wide — 640, 960 — because an answer is a sentence and not a number: two of them plus\n // the status and the date is already what a 755px pane holds without scrolling sideways,\n // which is what the pane beside the forms actually is on a 1280 screen (§11).\n hideBelow: index === 0 ? undefined : 320 + index * 320,\n })),\n // A floor rather than a width: the cell holds a badge, sometimes an avatar and sometimes\n // a paperclip, and a fixed width that any of them overflows makes the whole table scroll\n // sideways by two pixels.\n { key: 'status', label: t('panel.status'), minWidth: 100 },\n {\n key: 'created_at',\n label: t('panel.received'),\n sortable: true,\n width: 120,\n // \"today at 16:22\" is three words the table will break over two lines given half a\n // chance, and a date read down a column has to be one line to be read at all.\n cellClass: 'wx-submissions__when',\n hideBelow: 520,\n // Kept on the card, unlike most dates: \"when did this come in\" is one of the two\n // questions a submission is looked at for, and the other one is who sent it.\n },\n { key: 'actions', label: '', width: rowMenuWidth, align: 'right', hideOnCards: true },\n ]\n})\n\n/**\n * Two different nothings, said differently.\n *\n * \"Nothing has ever come in through this form\" is a fact about the form; \"nothing matches\" is\n * a fact about the tab somebody is standing on. Saying the first one on a filtered tab tells a\n * reader their form is dead when it is not.\n */\nconst emptyText = computed(() =>\n query.value.view === 'all' &&\n query.value.search === '' &&\n query.value.assignee === null &&\n query.value.placement === null\n ? t('panel.submissions-empty')\n : t('panel.submissions-none'),\n)\n\nconst statusOptions = computed(() =>\n statuses.value.map((status) => ({ value: status.id, label: name(status) })),\n)\n\n/* In the panel's language, not the content's: a status is a word of the interface. */\nconst name = useStatusName()\n\nfunction formName(): string {\n return localizedValue(props.form.title, locales.active.value, props.form.slug)\n}\n\nasync function load(state?: TableState): Promise<void> {\n loading.value = true\n\n try {\n page.value = await api.submissions(props.form.id, {\n view: query.value.view,\n search: state?.search ?? query.value.search,\n assignee: query.value.assignee,\n placement: query.value.placement,\n sort: state?.sort ? `${state.sort.order === 'desc' ? '-' : ''}${state.sort.key}` : null,\n page: state?.page ?? query.value.page,\n per_page: state?.perPage,\n })\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n}\n\n/**\n * The table reports everything it knows in one event, and that is the one place the address is\n * written from — so a page, a sort and a search all survive opening a submission and coming\n * back, and none of them has its own half of the bookkeeping.\n */\nfunction onState(state: TableState): void {\n const wanted: LocationQueryRaw = {\n ...route.query,\n search: state.search === '' ? undefined : state.search,\n sort:\n state.sort === null\n ? undefined\n : `${state.sort.order === 'desc' ? '-' : ''}${state.sort.key}`,\n page: state.page === 1 ? undefined : String(state.page),\n }\n\n void router.replace({ query: wanted })\n void load(state)\n}\n\n/* The form changes under the pane — the left column is a list, not a navigation — so the list\n has to notice rather than go on showing the previous form's submissions. One source per value,\n not a getter returning an array: that array is new on every change of the address, so a page\n turn would clear the selection and ask a second time, racing the request `onState` sent. */\nwatch([() => props.form.id, view, () => query.value.assignee, () => query.value.placement], () => {\n selected.value = []\n void load()\n})\n\n/* No `load()` of its own here: the table reports its state once it is mounted, and that\n report is the first request — with the page size the table draws. Asking here as well sent\n the list twice on every opening, the first time without `per_page`. */\nvoid statusList()\n\nasync function statusList(): Promise<void> {\n try {\n statuses.value = await api.statuses()\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\n/** Opening one carries the whole filter along, so its arrows walk the list it came from. */\nfunction open(row: SubmissionRow): void {\n void router.push({ path: `${props.base}/submissions/${row.id}`, query: { ...route.query } })\n}\n\nfunction actionsFor(row: SubmissionRow): RowAction[] {\n if (!canUpdate.value) return []\n\n return [\n {\n key: 'read',\n icon: row.is_read ? 'eye-off' : 'eye',\n label: row.is_read ? t('panel.mark-unread') : t('panel.mark-read'),\n run: () => void mass([row.id], row.is_read ? 'unread' : 'read'),\n },\n {\n key: 'delete',\n icon: 'trash',\n label: t('panel.delete'),\n danger: true,\n run: () => void remove([row.id]),\n },\n ]\n}\n\nasync function moveTo(statusId: unknown): Promise<void> {\n if (typeof statusId !== 'number') return\n\n moving.value = true\n await mass(\n selected.value.map((row) => row.id),\n 'status',\n statusId,\n )\n moving.value = false\n}\n\nasync function remove(ids: number[]): Promise<void> {\n const agreed = await confirm({\n title:\n ids.length === 1\n ? t('panel.delete-submission-title')\n : t('panel.delete-selected-title', { count: ids.length }),\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 await mass(ids, 'delete')\n}\n\nasync function mass(\n ids: number[],\n action: 'status' | 'read' | 'unread' | 'delete',\n statusId?: number,\n): Promise<void> {\n if (ids.length === 0) return\n\n try {\n await api.massSubmissions({ ids, action, status_id: statusId })\n selected.value = []\n await load()\n emit('changed')\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nasync function byHand(): Promise<void> {\n const made = await add({ form: props.form })\n\n if (!made) return\n\n toast.success(t('panel.created'))\n await load()\n emit('changed')\n void router.push({ path: `${props.base}/submissions/${made.id}`, query: { ...route.query } })\n}\n\n/**\n * A plain link and not a fetch: the browser downloads files, and pulling a spreadsheet into\n * memory to hand it straight back is work for nothing. It carries the filter that is on, so\n * what comes out is what is on screen.\n */\nconst exportHref = computed(() =>\n api.exportUrl(props.form.id, {\n view: query.value.view,\n search: query.value.search,\n assignee: query.value.assignee,\n placement: query.value.placement,\n sort: query.value.sort,\n }),\n)\n\n/*\n * The tools of the pane are what is done to this list of answers, and that is one thing:\n * take them away as a file.\n *\n * What the form is — its fields, its letters, its address — belongs to the form's own ··· in\n * the list of forms. And writing a submission is the section's own action, so it stands in\n * the head of the section beside its name (§11); the dialog is still this component's, which\n * is why it is exposed rather than moved: what is created has to land in this list, in this\n * filter, and be counted in these tabs.\n */\nconst actions = computed<ScreenAction[]>(() => [\n { key: 'export', label: t('panel.export'), icon: 'download', href: exportHref.value },\n])\n\ndefineExpose({ create: byHand })\n</script>\n\n<template>\n <div ref=\"root\" class=\"wx-submissions\">\n <wx-screen-head\n class=\"wx-submissions__head\"\n :level=\"3\"\n :title=\"formName()\"\n :subtitle=\"form.slug\"\n :actions=\"actions\"\n />\n\n <!--\n `items` and one panel: the table stays mounted while the tab changes, so the search\n somebody typed does not go with it.\n -->\n <wx-tabs\n v-model=\"view\"\n class=\"wx-submissions__views\"\n :items=\"views\"\n :collapse-below=\"560\"\n :aria-label=\"t('panel.status')\"\n >\n <wx-table\n :data=\"page\"\n :columns=\"columns\"\n row-key=\"id\"\n searchable\n clickable\n hover\n flush\n :loading=\"loading\"\n :loading-text=\"t('panel.loading')\"\n :selectable=\"canUpdate\"\n :select-row-label=\"panel('filters.select-row')\"\n :select-all-label=\"panel('filters.select-all')\"\n :row-class=\"(row: SubmissionRow) => (row.is_read ? undefined : 'is-unread')\"\n :search-placeholder=\"t('panel.search-submissions')\"\n :empty-text=\"emptyText\"\n :cards-below=\"cardsBelow\"\n :filters-count=\"applied.length\"\n @row-click=\"open\"\n @state-change=\"onState\"\n @selection-change=\"(_keys: unknown, rows: SubmissionRow[]) => (selected = rows)\"\n >\n <!-- The pile only offers what can be done to all of it at once; one row's own menu\n keeps the rest. -->\n <template v-if=\"selected.length > 0\" #actions>\n <div class=\"wx-submissions__mass\">\n <wx-text size=\"sm\" weight=\"medium\">\n {{ t('panel.selected', { count: selected.length }) }}\n </wx-text>\n <wx-select\n :model-value=\"null\"\n :options=\"statusOptions\"\n :placeholder=\"t('panel.move-to')\"\n :disabled=\"moving\"\n size=\"sm\"\n style=\"width: 180px\"\n @update:model-value=\"moveTo\"\n />\n <wx-button\n size=\"sm\"\n variant=\"outline\"\n type=\"danger\"\n icon=\"trash\"\n @click=\"remove(selected.map((row) => row.id))\"\n >\n {{ t('panel.delete') }}\n </wx-button>\n </div>\n </template>\n\n <template v-if=\"hasPlacements\" #filters>\n <wx-form-item :label=\"t('panel.meta-placement')\">\n <wx-select\n :model-value=\"query.placement\"\n :options=\"placementOptions\"\n :placeholder=\"t('panel.any-placement')\"\n clearable\n size=\"sm\"\n @update:model-value=\"narrow\"\n />\n </wx-form-item>\n </template>\n\n <template v-if=\"applied.length > 0\" #applied>\n <wx-filter-chips :filters=\"applied\" />\n </template>\n\n <template #cell-status=\"{ row }\">\n <div class=\"wx-submissions__state\">\n <wx-badge v-if=\"row.status\" :type=\"row.status.color\">{{ name(row.status) }}</wx-badge>\n <!-- The assignee is an avatar beside the status rather than a column: at the\n width this pane has, a column of names costs an answer (§11). -->\n <wx-avatar\n v-if=\"row.assignee\"\n :name=\"row.assignee.name\"\n :title=\"row.assignee.name\"\n size=\"xs\"\n tone=\"auto\"\n />\n <wx-tooltip v-if=\"row.files_count > 0\" :content=\"t('panel.attachments')\">\n <wx-icon name=\"file\" size=\"sm\" />\n </wx-tooltip>\n </div>\n </template>\n\n <template #cell-created_at=\"{ row }\">\n <wx-date :value=\"row.created_at\" compact />\n </template>\n\n <template #cell-card=\"{ row }\">\n <wx-entity-card variant=\"plain\" shape=\"circle\" :title=\"answer(row, 0)\">\n <template #subtitle>{{ answer(row, 1) }}</template>\n\n <template #meta>\n <wx-badge v-if=\"row.status\" :type=\"row.status.color\" size=\"sm\">\n {{ name(row.status) }}\n </wx-badge>\n <wx-avatar\n v-if=\"row.assignee\"\n :name=\"row.assignee.name\"\n :title=\"row.assignee.name\"\n size=\"xs\"\n tone=\"auto\"\n />\n <wx-icon v-if=\"row.files_count > 0\" name=\"file\" size=\"sm\" />\n <wx-date :value=\"row.created_at\" />\n </template>\n </wx-entity-card>\n </template>\n\n <template #card-actions=\"{ row }\">\n <wx-row-menu :actions=\"actionsFor(row)\" :label=\"String(row.id)\" />\n </template>\n\n <template #cell-actions=\"{ row }\">\n <wx-row-menu :actions=\"actionsFor(row)\" :label=\"String(row.id)\" />\n </template>\n </wx-table>\n </wx-tabs>\n </div>\n</template>\n\n<style scoped>\n/*\n * One step, and everything in the pane keeps it.\n *\n * The panel's own — 8 on a phone and 16 on a desktop — and not a number of this screen's own.\n * Written as 16 here, the pane kept desktop air on a 375px screen: the head, the tabs and the\n * rows each took a line of nothing between them, and four rows fitted where six do now.\n *\n * It is the pane that holds it, so the name of the form, the tabs, the search box and the rows\n * all begin on the same line down the left. The table used to add a step of its own inside\n * this one — measured on a phone: the head at 17 and the search at 33 — and two insets, one\n * for the words and one for the list they are about, read as two panels stacked rather than as\n * one screen.\n */\n.wx-submissions {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n padding: var(--wx-gap, var(--wx-space-16));\n min-width: 0;\n}\n\n/* The address the form posts to, in the type an address is written in. */\n.wx-submissions__head :deep(.wx-screen-head__subtitle) {\n font-family: var(--wx-font-family-mono);\n}\n\n/*\n * The tabs and the rows they filter are one thing, so they stand closer than two things do.\n * `WxTabs` leaves the panel's step under the strip, which is right where a card follows it;\n * here what follows is the search box of the same table, and a full step between a filter and\n * what it filters reads as a gap between two screens.\n */\n.wx-submissions__views :deep(.wx-tabs__panels) {\n padding-top: var(--wx-space-8);\n}\n\n.wx-submissions__mass {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n flex-wrap: wrap;\n}\n\n/* `:deep()` because the cell is the table's element and the class is ours — a scoped rule\n would be looking for our attribute on somebody else's markup (CLAUDE.md §4). */\n.wx-submissions :deep(.wx-submissions__when) {\n white-space: nowrap;\n}\n\n.wx-submissions__state {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--wx-space-6);\n min-width: 0;\n}\n\n/*\n * What nobody has opened yet, said on the whole row. `:deep()` because the row is the table's\n * element and the class is ours — a scoped rule would be looking for our attribute on somebody\n * else's markup (CLAUDE.md §4).\n */\n.wx-submissions :deep(.is-unread) {\n font-weight: var(--wx-font-weight-medium);\n}\n\n.wx-submissions :deep(.is-unread) td:first-child {\n box-shadow: inset 2px 0 0 0 var(--wx-color-primary);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useLocales, WxLocales, WxRichText, type LocalizedValue } from '@webx-ui/core'\n\n/**\n * Rich text in every language the site publishes in.\n *\n * `WxRichText` holds one string, the way `WxInput` does without `localized`; what a localized\n * field adds is the picker and the map underneath it. This is that, for the one place in this\n * module that needs it — the thank-you, which is printed raw on the site and is therefore\n * written where formatting is possible.\n *\n * With no content languages at all — a panel assembled by hand, a test — the value stays a\n * plain string, which is exactly what `useLocalized` does in the same situation and what the\n * server accepts for a form written before the site had a second language.\n */\nconst model = defineModel<LocalizedValue | string>({ default: '' })\n\nconst props = withDefaults(defineProps<{ placeholder?: string; minHeight?: string }>(), {\n placeholder: undefined,\n minHeight: '160px',\n})\n\nconst locales = useLocales()\n\nconst active = computed(() => {\n const chosen = locales.active.value\n const known = locales.list.value.some((locale) => locale.code === chosen)\n\n return known ? chosen : (locales.list.value[0]?.code ?? '')\n})\n\nconst text = computed({\n get: () => {\n const value = model.value\n\n if (typeof value === 'string') {\n // A string under a localized field belongs to the first language: that is where the\n // words were written, and hiding them would look like losing them.\n return active.value === '' || active.value === locales.list.value[0]?.code ? value : ''\n }\n\n return value[active.value] ?? ''\n },\n set: (next: string) => {\n if (active.value === '') {\n model.value = next\n\n return\n }\n\n const base = typeof model.value === 'string' ? { [active.value]: model.value } : model.value\n\n model.value = { ...base, [active.value]: next }\n },\n})\n</script>\n\n<template>\n <wx-locales v-if=\"locales.list.value.length > 0\">\n <wx-rich-text v-model=\"text\" :placeholder=\"props.placeholder\" :min-height=\"props.minHeight\" />\n </wx-locales>\n\n <wx-rich-text\n v-else\n v-model=\"text\"\n :placeholder=\"props.placeholder\"\n :min-height=\"props.minHeight\"\n />\n</template>\n","import type { LocalizedValue } from '@webx-ui/core'\nimport type { RelationCandidate } from '@webx-ui/module-admin'\n\n/** The kinds of question a form can ask (§4). Mirrors `WebxUi\\Inbox\\Fields\\FieldType`. */\nexport const FIELD_TYPES = [\n 'text',\n 'email',\n 'tel',\n 'textarea',\n 'select',\n 'radio',\n 'checkbox',\n 'consent',\n 'date',\n 'file',\n 'hidden',\n] as const\n\nexport type FieldType = (typeof FIELD_TYPES)[number]\n\n/** Tones of `WxBadge`, which is what a status is coloured with — never a hex value. */\nexport const STATUS_COLORS = ['default', 'primary', 'success', 'warning', 'info', 'danger'] as const\n\nexport type StatusColor = (typeof STATUS_COLORS)[number]\n\n/** One written-down answer of a `select`, `radio` or `checkbox`. */\nexport interface FieldChoice {\n value: string\n label: LocalizedValue | string\n}\n\n/**\n * What a field may be configured with. Which keys mean anything depends on the type (§4), and\n * the server keeps only the ones that do.\n */\nexport interface FieldOptions {\n maxlength?: number\n rows?: number\n pattern?: string\n min?: number | string\n max?: number | string\n choices?: FieldChoice[]\n text?: LocalizedValue | string\n max_size?: number\n extensions?: string[]\n multiple?: boolean\n [key: string]: unknown\n}\n\nexport interface InboxField {\n id: number\n form_id: number\n /** What somebody typed, or null. */\n name: string | null\n /** What the HTML will actually say — `f17` for a field nobody named. */\n key: string\n type: FieldType\n title: LocalizedValue\n placeholder: LocalizedValue\n help: LocalizedValue\n options: FieldOptions\n is_enabled: boolean\n is_required: boolean\n is_fullsize: boolean\n in_table: boolean\n position: number\n /* A table row, so the index signature `WxTable` asks of what it draws. */\n [key: string]: unknown\n}\n\n/** A field as the dialog saves it. */\nexport interface FieldInput {\n name: string | null\n type: FieldType\n title: LocalizedValue\n placeholder?: LocalizedValue\n help?: LocalizedValue\n options?: FieldOptions\n is_enabled: boolean\n is_required: boolean\n is_fullsize: boolean\n in_table: boolean\n}\n\n/** Who a notification goes to: somebody with an account, or an address typed in. */\nexport type Recipient = { admin_id: number } | { email: string }\n\n/** Why a recipient the form names would not get a letter. */\nexport type RecipientProblem = 'admin_deleted' | 'admin_inactive' | 'invalid_email'\n\n/** A recipient as the server reads it today: who it is, and whether a letter would reach it. */\nexport interface RecipientState {\n type: 'admin' | 'email'\n admin_id?: number\n name?: string | null\n email: string | null\n receives: boolean\n problem: RecipientProblem | null\n}\n\n/** The settings of a form (§5). Every key is literal, dots included. */\nexport interface FormOptions {\n 'thank-you.heading'?: LocalizedValue\n 'thank-you.text'?: LocalizedValue\n 'design.submit-text'?: LocalizedValue\n redirect?: string\n recipients?: Recipient[]\n email_field?: string\n /** Channels of the notifications module a submission from the site also goes to (NOTIFICATIONS §15.2). */\n notify_channels?: number[]\n 'antispam.honeypot'?: boolean\n 'antispam.min_seconds'?: number\n 'antispam.throttle'?: number\n 'antispam.captcha'?: 'off' | 'recaptcha' | 'turnstile'\n [key: string]: unknown\n}\n\nexport interface InboxForm {\n id: number\n slug: string\n title: LocalizedValue\n is_enabled: boolean\n options: FormOptions\n /**\n * Who a submission would be written to, read from `options.recipients` as saved. Optional\n * only because a server older than this field does not send it.\n */\n recipients?: RecipientState[]\n /** False when a submission would be written to nobody at all — no letter and no channel. */\n notifies?: boolean\n /** Whether `webx-ui/module-notifications` is installed: \"Notify through\" shows only then. */\n notifications?: boolean\n /** The channels `options.notify_channels` holds, as saved, each with whether it sends. */\n channels?: FormChannel[]\n position: number\n /** Only where the query counted them — null on a form loaded on its own. */\n submissions_count: number | null\n /** Unread and not spam. */\n unread_count: number | null\n /** Only on a form asked for by id, or one just written. */\n fields?: InboxField[]\n /**\n * What the site has for each captcha — the keys and how they are run live in its `.env`,\n * not in the form — so the antispam tab can say which kind of key it expects. Optional\n * because a server older than this field does not send it.\n */\n captcha?: Record<CaptchaProvider, CaptchaSite>\n created_at: string | null\n updated_at: string | null\n}\n\n/** A channel a form notifies through, as the server read it. */\nexport interface FormChannel {\n id: number\n /** Null for a channel deleted for good. */\n name: string | null\n provider: string | null\n enabled: boolean\n deleted: boolean\n /** Switched on, not in the bin, and for this event or any. */\n sends: boolean\n}\n\nexport type CaptchaProvider = 'recaptcha' | 'turnstile'\n\n/** How a provider runs on this site, and whether both halves of its keys are there. */\nexport interface CaptchaSite {\n type: 'checkbox' | 'invisible' | 'v3'\n configured: boolean\n}\n\n/** A form as its editor saves it. */\nexport interface FormInput {\n slug: string\n title: LocalizedValue\n is_enabled: boolean\n options: FormOptions\n}\n\nexport interface InboxStatus {\n id: number\n key: string\n title: LocalizedValue\n color: StatusColor\n is_default: boolean\n is_spam: boolean\n is_closed: boolean\n position: number\n submissions_count: number | null\n}\n\nexport interface StatusInput {\n key: string\n title: LocalizedValue\n color: StatusColor\n is_default: boolean\n is_spam: boolean\n is_closed: boolean\n}\n\n/** Somebody with an account who may read the section, for the recipients list. */\nexport interface InboxRecipient {\n id: number\n name: string\n email: string\n}\n\n/** An administrator as a name beside something else — an assignee, the author of a log line. */\nexport interface InboxAdmin {\n id: number\n name: string\n email: string\n}\n\n/** One column of the list: a field of the form that was marked `in_table`. */\nexport interface SubmissionColumn {\n key: string\n label: string\n type: FieldType\n}\n\n/** What each tab above the list would hold, under the filters that are on. */\nexport interface SubmissionCounts {\n all: number\n unread: number\n /** By the status's key, spam included — its own tab has to say how much is in it. */\n statuses: Record<string, number>\n}\n\n/** A page as Laravel's `->paginate()` serialises it, which is what `WxTable` reads. */\nexport interface InboxPage<T> {\n data: T[]\n current_page: number\n last_page: number\n per_page: number\n total: number\n from: number | null\n to: number | null\n}\n\n/** One line of the list. The answers are keyed by the field's machine name. */\nexport interface SubmissionRow {\n id: number\n values: Record<string, string | null>\n status: InboxStatus | null\n assignee: InboxAdmin | null\n is_read: boolean\n source: string\n /** Where on the site the form stood (`footer`, `article`), or null when the page did not say. */\n placement: string | null\n files_count: number\n created_at: string | null\n /* A table row, so the index signature `WxTable` asks of what it draws. */\n [key: string]: unknown\n}\n\n/**\n * The list, and the two things that travel with it: what its columns are, and what each tab\n * above it would hold.\n */\nexport interface SubmissionsPage extends InboxPage<SubmissionRow> {\n columns: SubmissionColumn[]\n counts: SubmissionCounts\n /**\n * Every place on the site the form has been sent from, `null` for the page that did not say —\n * over the whole form rather than the filter, so the placement filter can always be undone.\n * More than one is what makes that filter worth showing.\n */\n placements: (string | null)[]\n}\n\n/** One answer, with the question as it was asked at the time (§2.2). */\nexport interface SubmissionValue {\n id: number\n field_id: number | null\n name: string\n label: string | null\n type: string\n value: string | null\n payload: unknown\n}\n\nexport interface SubmissionAttachment {\n id: number\n field_id: number | null\n name: string\n size: number\n mime: string | null\n /** Through the panel, behind the same permission as the submission (§8). */\n url: string\n}\n\n/** One line of what has happened to a submission. Never edited, never deleted. */\nexport interface SubmissionEvent {\n id: number\n type:\n | 'created'\n | 'status'\n | 'assignee'\n | 'note'\n | 'notified'\n | 'handled'\n | 'handler_error'\n | 'no_recipients'\n | 'notify_queued'\n | 'notify_failed'\n | 'value'\n | string\n /** The answer a `value` line is about, by machine name; null on every other line. */\n field?: string | null\n from: string | null\n to: string | null\n /** Null is the system — the submission arriving, the notification going out. */\n author: { id: number; name: string | null } | null\n created_at: string | null\n}\n\n/**\n * Whether the letter about a submission left (§9). `queued` is handed to the site's queue and\n * not sent yet — on a site with a queue, sending is a worker's job, and a worker can be missing.\n */\nexport type NotifyState = 'none' | 'queued' | 'delivered' | 'failed'\n\nexport interface SubmissionNotification {\n state: NotifyState\n error: string | null\n queued_at: string | null\n delivered_at: string | null\n /** Empty on a submission from before the letters were watched one by one. */\n recipients: {\n address: string\n state: 'queued' | 'delivered' | 'failed'\n error: string | null\n at: string\n }[]\n}\n\n/** One row of the notifications module's log about a submission (NOTIFICATIONS §15.3). */\nexport interface ChannelDelivery {\n id: number\n channel_id: number | null\n channel: string\n provider: string\n recipient: string\n recipient_label: string | null\n status: 'queued' | 'sent' | 'failed' | 'skipped'\n /** The status and the reason in the notifications module's own words. */\n status_label: string\n reason: string | null\n reason_label: string | null\n error: string | null\n attempts: number\n retryable: boolean\n created_at: string | null\n sent_at: string | null\n}\n\n/** What the intake saw around the submission: the page, the language, the campaign. */\nexport interface SubmissionMeta {\n ip?: string\n user_agent?: string\n page?: string\n referrer?: string\n utm?: Record<string, string>\n locale?: string\n [key: string]: unknown\n}\n\nexport interface InboxSubmission {\n id: number\n form: { id: number; slug: string | null; title: LocalizedValue | null }\n status: InboxStatus | null\n assignee: InboxAdmin | null\n values: SubmissionValue[]\n files: SubmissionAttachment[]\n meta: SubmissionMeta\n events: SubmissionEvent[]\n is_read: boolean\n source: string\n /** Where on the site the form stood (`footer`, `article`), or null when the page did not say. */\n placement: string | null\n notified_at: string | null\n notify_error: string | null\n /** The same two read as a state, with how each letter went. */\n notification: SubmissionNotification\n /**\n * What the form's channels made of it, a row per recipient, newest first; null on a site\n * without the notifications module, absent from a server older than it.\n */\n channels?: ChannelDelivery[] | null\n /** The neighbours in the list this was opened from, so the arrows walk the same pile. */\n previous_id: number | null\n next_id: number | null\n created_at: string | null\n updated_at: string | null\n}\n\n/** Everything the list asks the server for. The tab is `view`, the rest are filters. */\nexport interface SubmissionQuery {\n view?: string\n search?: string\n /** An administrator's id, or `none` — the pile nobody has picked up. */\n assignee?: string | null\n /** A placement, or `none` — the submissions whose page did not say. */\n placement?: string | null\n sort?: string | null\n page?: number\n per_page?: number\n}\n\n/** A submission changed by hand: the status, the assignee, a typo in an answer. */\nexport interface SubmissionInput {\n status_id?: number\n assignee_id?: number | null\n /** Machine name → the corrected text. The snapshot beside it is never rewritten. */\n values?: Record<string, string | null>\n}\n\n/** A pile dealt with at once. */\nexport interface SubmissionMassInput {\n ids: number[]\n action: 'status' | 'read' | 'unread' | 'delete'\n status_id?: number\n}\n\n/**\n * A form as the panel's relation target `inbox-form` describes it, with the slug under its own\n * name — what `wx-inbox-form` keeps (`FormTarget::row()` on the server).\n */\nexport interface FormCandidate extends RelationCandidate {\n slug?: string\n}\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport {\n toast,\n useModal,\n WxAction,\n WxButton,\n WxIcon,\n WxCheckbox,\n WxDialog,\n WxFormItem,\n WxInput,\n WxInputNumber,\n WxSelect,\n WxSpace,\n WxDatePicker,\n WxTagsInput,\n WxText,\n type LocalizedValue,\n} from '@webx-ui/core'\nimport LocalizedRichText from './LocalizedRichText.vue'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport { FIELD_TYPES, type FieldChoice, type FieldOptions, type FieldType } from './types'\nimport type { InboxField, InboxForm } from './types'\n\n/**\n * One question, written.\n *\n * The settings shown are the ones the chosen type has and no others (§4): a `select` has\n * choices, a `textarea` has a height, a `file` has a size and a list of extensions. Changing\n * the type changes what is asked for, and the server keeps only what belongs — a leftover\n * `choices` array on a text field would be a column of empty strings in an export a year from\n * now.\n */\nconst props = defineProps<{ field: InboxField | null; form: InboxForm }>()\n\nconst { resolve, dismiss, open } = useModal<InboxField>()\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\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 saving = ref(false)\nconst errors = ref<Record<string, string[]>>({})\n\nconst name = ref('')\nconst type = ref<FieldType>('text')\nconst title = ref<LocalizedValue>({})\nconst placeholder = ref<LocalizedValue>({})\nconst help = ref<LocalizedValue>({})\nconst options = ref<FieldOptions>({})\nconst isEnabled = ref(true)\nconst isRequired = ref(false)\nconst isFullsize = ref(true)\nconst inTable = ref(false)\n\nwatch(\n () => props.field,\n (field) => {\n name.value = field?.name ?? ''\n type.value = field?.type ?? 'text'\n title.value = { ...(field?.title ?? {}) }\n placeholder.value = { ...(field?.placeholder ?? {}) }\n help.value = { ...(field?.help ?? {}) }\n options.value = { ...(field?.options ?? {}) }\n isEnabled.value = field?.is_enabled ?? true\n isRequired.value = field?.is_required ?? false\n isFullsize.value = field?.is_fullsize ?? true\n inTable.value = field?.in_table ?? false\n errors.value = {}\n },\n { immediate: true },\n)\n\nconst types = computed(() =>\n FIELD_TYPES.map((one) => ({ value: one, label: t(`fields.type-${one}`) })),\n)\n\nconst hasChoices = computed(() => ['select', 'radio', 'checkbox'].includes(type.value))\n\nconst choices = computed<FieldChoice[]>(() =>\n Array.isArray(options.value.choices) ? options.value.choices : [],\n)\n\n/** Extensions are typed as a list of words, which is what they are — not a sentence. */\nconst extensions = computed({\n get: () => (Array.isArray(options.value.extensions) ? options.value.extensions : []),\n set: (value: string[]) =>\n set(\n 'extensions',\n value.map((one) => one.replace(/^\\./, '')),\n ),\n})\n\nfunction set(key: string, value: unknown): void {\n options.value = { ...options.value, [key]: value }\n}\n\nfunction addChoice(): void {\n set('choices', [...choices.value, { value: '', label: {} }])\n}\n\nfunction removeChoice(index: number): void {\n set(\n 'choices',\n choices.value.filter((_, at) => at !== index),\n )\n}\n\nfunction setChoice(index: number, patch: Partial<FieldChoice>): void {\n set(\n 'choices',\n choices.value.map((choice, at) => (at === index ? { ...choice, ...patch } : choice)),\n )\n}\n\nfunction errorOf(field: string): string | undefined {\n return errors.value[field]?.[0]\n}\n\nasync function save(): Promise<void> {\n saving.value = true\n errors.value = {}\n\n const input = {\n name: name.value.trim() === '' ? null : name.value.trim(),\n type: type.value,\n title: title.value,\n placeholder: placeholder.value,\n help: help.value,\n options: options.value,\n is_enabled: isEnabled.value,\n is_required: isRequired.value,\n is_fullsize: isFullsize.value,\n in_table: inTable.value,\n }\n\n try {\n resolve(\n props.field === null\n ? await api.createField(props.form.id, input)\n : await api.saveField(props.field.id, input),\n )\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 <wx-dialog\n v-model:open=\"open\"\n :title=\"field ? t('fields.edit-field') : t('fields.new-field')\"\n :width=\"720\"\n >\n <div class=\"wx-inbox-field-form\">\n <div class=\"wx-inbox-field-form__row\">\n <wx-form-item :label=\"t('fields.type')\">\n <wx-select v-model=\"type\" :options=\"types\" />\n </wx-form-item>\n\n <wx-form-item\n :label=\"t('fields.name')\"\n :help=\"t('fields.name-help')\"\n :error=\"errorOf('name')\"\n >\n <wx-input v-model=\"name\" placeholder=\"email\" />\n </wx-form-item>\n </div>\n\n <wx-form-item :label=\"t('fields.title')\" :error=\"errorOf('title')\" required>\n <wx-input v-model=\"title\" localized />\n </wx-form-item>\n\n <!-- A hidden field has neither: nobody reads a placeholder they cannot see. -->\n <template v-if=\"type !== 'hidden'\">\n <wx-form-item v-if=\"type !== 'consent'\" :label=\"t('fields.placeholder')\">\n <wx-input v-model=\"placeholder\" localized />\n </wx-form-item>\n\n <wx-form-item :label=\"t('fields.help')\">\n <wx-input v-model=\"help\" localized />\n </wx-form-item>\n </template>\n\n <!-- The sentence beside the tick, which is printed raw on the site: it is a sentence\n with a link in it, not a caption. -->\n <wx-form-item\n v-if=\"type === 'consent'\"\n :label=\"t('fields.consent-text')\"\n :help=\"t('fields.consent-text-help')\"\n >\n <localized-rich-text\n :model-value=\"(options.text as LocalizedValue) ?? {}\"\n min-height=\"100px\"\n @update:model-value=\"(value) => set('text', value)\"\n />\n </wx-form-item>\n\n <div v-if=\"hasChoices\" class=\"wx-inbox-choices\">\n <wx-text size=\"sm\" weight=\"medium\">{{ t('fields.choices') }}</wx-text>\n\n <wx-text v-if=\"choices.length === 0\" size=\"sm\" tone=\"placeholder\">\n {{ t('fields.no-choices') }}\n </wx-text>\n\n <div v-for=\"(choice, index) in choices\" :key=\"index\" class=\"wx-inbox-choices__row\">\n <wx-input\n :model-value=\"choice.value\"\n :placeholder=\"t('fields.choice-value')\"\n @update:model-value=\"(value) => setChoice(index, { value: String(value) })\"\n />\n <wx-input\n :model-value=\"choice.label\"\n localized\n :placeholder=\"t('fields.choice-label')\"\n @update:model-value=\"(label) => setChoice(index, { label: label as LocalizedValue })\"\n />\n <wx-action icon=\"trash\" :title=\"t('fields.delete')\" @click=\"removeChoice(index)\" />\n </div>\n\n <wx-button variant=\"outline\" size=\"sm\" @click=\"addChoice\">\n <template #icon><wx-icon name=\"plus\" /></template>\n {{ t('fields.add-choice') }}\n </wx-button>\n\n <!-- A list field with nothing to pick is refused by the server: it could never be sent. -->\n <wx-text v-if=\"errorOf('options.choices')\" size=\"sm\" tone=\"danger\">\n {{ errorOf('options.choices') }}\n </wx-text>\n </div>\n\n <div class=\"wx-inbox-field-form__row\">\n <wx-form-item v-if=\"type === 'textarea'\" :label=\"t('fields.rows')\">\n <wx-input-number\n :model-value=\"(options.rows as number) ?? 5\"\n :min=\"2\"\n :max=\"30\"\n @update:model-value=\"(value) => set('rows', value)\"\n />\n </wx-form-item>\n\n <wx-form-item\n v-if=\"['text', 'email', 'textarea'].includes(type)\"\n :label=\"t('fields.maxlength')\"\n >\n <wx-input-number\n :model-value=\"(options.maxlength as number) ?? null\"\n :min=\"1\"\n :max=\"20000\"\n @update:model-value=\"(value) => set('maxlength', value)\"\n />\n </wx-form-item>\n\n <wx-form-item\n v-if=\"type === 'tel'\"\n :label=\"t('fields.pattern')\"\n :help=\"t('fields.pattern-help')\"\n >\n <wx-input\n :model-value=\"(options.pattern as string) ?? ''\"\n @update:model-value=\"(value) => set('pattern', value)\"\n />\n </wx-form-item>\n\n <template v-if=\"type === 'date'\">\n <wx-form-item :label=\"t('fields.earliest')\">\n <wx-date-picker\n clearable\n :model-value=\"(options.min as string) ?? null\"\n @update:model-value=\"(value) => set('min', value)\"\n />\n </wx-form-item>\n <wx-form-item :label=\"t('fields.latest')\">\n <wx-date-picker\n clearable\n :model-value=\"(options.max as string) ?? null\"\n @update:model-value=\"(value) => set('max', value)\"\n />\n </wx-form-item>\n </template>\n\n <template v-if=\"type === 'checkbox'\">\n <wx-form-item :label=\"t('fields.min-choices')\">\n <wx-input-number\n :model-value=\"(options.min as number) ?? null\"\n :min=\"0\"\n @update:model-value=\"(value) => set('min', value)\"\n />\n </wx-form-item>\n <wx-form-item :label=\"t('fields.max-choices')\">\n <wx-input-number\n :model-value=\"(options.max as number) ?? null\"\n :min=\"0\"\n @update:model-value=\"(value) => set('max', value)\"\n />\n </wx-form-item>\n </template>\n\n <wx-form-item v-if=\"type === 'file'\" :label=\"t('fields.max-size')\">\n <wx-input-number\n :model-value=\"(options.max_size as number) ?? null\"\n :min=\"1\"\n @update:model-value=\"(value) => set('max_size', value)\"\n />\n </wx-form-item>\n </div>\n\n <template v-if=\"type === 'file'\">\n <wx-form-item :label=\"t('fields.extensions')\" :help=\"t('fields.extensions-help')\">\n <wx-tags-input v-model=\"extensions\" />\n </wx-form-item>\n\n <wx-checkbox\n :model-value=\"Boolean(options.multiple)\"\n :label=\"t('fields.multiple')\"\n @update:model-value=\"(value) => set('multiple', value)\"\n />\n </template>\n\n <div class=\"wx-inbox-field-form__checks\">\n <wx-checkbox v-model=\"isEnabled\" :label=\"t('fields.is-enabled')\" />\n <wx-checkbox v-model=\"isRequired\" :label=\"t('fields.is-required')\" />\n <wx-checkbox\n v-if=\"type !== 'hidden'\"\n v-model=\"isFullsize\"\n :label=\"t('fields.is-fullsize')\"\n />\n <wx-checkbox v-model=\"inTable\" :label=\"t('fields.in-table')\" />\n </div>\n </div>\n\n <template #footer>\n <wx-space size=\"sm\">\n <wx-button variant=\"outline\" @click=\"dismiss()\">{{ t('fields.cancel') }}</wx-button>\n <wx-button type=\"primary\" :loading=\"saving\" @click=\"save\">{{ t('fields.save') }}</wx-button>\n </wx-space>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-inbox-field-form {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n.wx-inbox-field-form__row {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-12);\n}\n\n.wx-inbox-field-form__row > * {\n flex: 1 1 200px;\n min-width: 0;\n}\n\n/* Empty when the type has nothing to configure, and then it should take no room at all. */\n.wx-inbox-field-form__row:empty {\n display: none;\n}\n\n.wx-inbox-field-form__checks {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-16);\n}\n\n.wx-inbox-choices {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n align-items: flex-start;\n}\n\n.wx-inbox-choices__row {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n width: 100%;\n}\n\n.wx-inbox-choices__row > :first-child {\n flex: 0 1 180px;\n min-width: 0;\n}\n\n.wx-inbox-choices__row > :nth-child(2) {\n flex: 1 1 auto;\n min-width: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxRowMenu,\n type RowAction,\n} from '@webx-ui/module-admin'\nimport {\n confirm,\n createModal,\n localizedValue,\n toast,\n useLocales,\n WxBadge,\n WxButton,\n WxIcon,\n WxCard,\n WxEmpty,\n WxSortableList,\n WxText,\n} from '@webx-ui/core'\nimport FieldDialog from './FieldDialog.vue'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport type { InboxField, InboxForm } from './types'\n\n/**\n * The questions the form asks, in the order it asks them.\n *\n * A list with a grip rather than a table, because the order is the thing being edited here\n * and a table cannot be dragged. Each question is saved on its own, in its own dialog: a\n * field is a row with an identity that answers point at (§2.1), not a value of the form.\n */\nconst props = defineProps<{ form: InboxForm; canManage: boolean }>()\n\nconst fields = defineModel<InboxField[]>({ required: true })\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\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 edit = createModal<InboxField, { field: InboxField | null; form: InboxForm }>(FieldDialog)\n\nfunction name(field: InboxField): string {\n return localizedValue(field.title, locales.active.value, field.key)\n}\n\n/** What the row says about itself, under its name: the type, then what is true of it. */\nfunction marks(field: InboxField): string[] {\n return [\n t(`fields.type-${field.type}`),\n ...(field.is_required ? [t('fields.is-required')] : []),\n ...(field.in_table ? [t('fields.in-table')] : []),\n ...(field.is_fullsize ? [] : [t('fields.is-fullsize')]),\n ]\n}\n\nconst empty = computed(() => fields.value.length === 0)\n\nasync function open(field: InboxField | null): Promise<void> {\n const saved = await edit({ field, form: props.form })\n\n if (!saved) return\n\n fields.value =\n field === null\n ? [...fields.value, saved]\n : fields.value.map((one) => (one.id === saved.id ? saved : one))\n}\n\nasync function remove(field: InboxField): Promise<void> {\n const agreed = await confirm({\n title: t('fields.delete-title', { field: name(field) }),\n message: t('fields.delete-text'),\n confirmText: t('fields.delete'),\n cancelText: t('fields.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n try {\n await api.removeField(field.id)\n fields.value = fields.value.filter((one) => one.id !== field.id)\n toast.success(t('panel.deleted'))\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nfunction actionsFor(field: InboxField): RowAction[] {\n if (!props.canManage) return []\n\n return [\n { key: 'edit', icon: 'edit', label: t('fields.edit'), run: () => void open(field) },\n {\n key: 'delete',\n icon: 'trash',\n label: t('fields.delete'),\n danger: true,\n run: () => void remove(field),\n },\n ]\n}\n\n/** The whole order, every time — the list is already in it on screen. */\nasync function reorder(): Promise<void> {\n try {\n await api.sortFields(\n props.form.id,\n fields.value.map((field) => field.id),\n )\n } catch (error) {\n toast.danger(message(error, t('panel.reorder-failed')))\n }\n}\n</script>\n\n<template>\n <wx-card :title=\"t('panel.tab-fields')\">\n <template v-if=\"canManage\" #extra>\n <wx-button type=\"primary\" size=\"sm\" @click=\"open(null)\">\n <template #icon><wx-icon name=\"plus\" /></template>\n {{ t('fields.new-field') }}\n </wx-button>\n </template>\n\n <wx-empty\n v-if=\"empty\"\n :title=\"t('fields.no-fields')\"\n :description=\"t('fields.no-fields-help')\"\n />\n\n <wx-sortable-list\n v-else\n v-model=\"fields\"\n plain\n item-key=\"id\"\n :item-label=\"name\"\n :drag-label=\"t('panel.reorder')\"\n :disabled=\"!canManage\"\n :aria-label=\"t('panel.tab-fields')\"\n @move=\"reorder\"\n >\n <template #default=\"{ item }\">\n <div class=\"wx-inbox-field\">\n <div class=\"wx-inbox-field__name\">\n <wx-text weight=\"medium\" truncate>{{ name(item) }}</wx-text>\n <wx-badge v-if=\"!item.is_enabled\" type=\"default\">{{ t('panel.off') }}</wx-badge>\n </div>\n <wx-text size=\"sm\" tone=\"muted\" truncate>\n <code>fields[{{ item.key }}]</code> · {{ marks(item).join(' · ') }}\n </wx-text>\n </div>\n </template>\n\n <template #actions=\"{ item }\">\n <wx-row-menu :actions=\"actionsFor(item)\" :label=\"name(item)\" />\n </template>\n </wx-sortable-list>\n </wx-card>\n</template>\n\n<style scoped>\n.wx-inbox-field {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-2);\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.wx-inbox-field__name {\n display: flex;\n align-items: center;\n gap: var(--wx-space-6);\n min-width: 0;\n}\n</style>\n","import { defineAsyncComponent } from 'vue'\nexport { inbox, type InboxOptions } from './module'\nexport { createInboxApi, type InboxApi } from './api'\nexport { inboxMessages } from './messages'\nexport { option } from './options'\nexport const WxInboxPage = defineAsyncComponent(() => import('./InboxPage.vue'))\nexport const WxInboxFormEditor = defineAsyncComponent(() => import('./FormEditorPage.vue'))\nexport const WxInboxStatusesPage = defineAsyncComponent(() => import('./StatusesPage.vue'))\nexport { default as WxInboxSubmissionList } from './SubmissionList.vue'\nexport const WxInboxSubmissionPage = defineAsyncComponent(() => import('./SubmissionPage.vue'))\nexport { default as WxInboxFieldList } from './FieldList.vue'\nexport { default as WxInboxFormField } from './FormField.vue'\nexport { FIELD_TYPES, STATUS_COLORS } from './types'\nexport type {\n ChannelDelivery,\n FieldChoice,\n FieldInput,\n FieldOptions,\n FieldType,\n FormCandidate,\n FormChannel,\n FormInput,\n FormOptions,\n InboxField,\n InboxForm,\n InboxAdmin,\n InboxPage,\n InboxRecipient,\n InboxStatus,\n InboxSubmission,\n Recipient,\n RecipientProblem,\n RecipientState,\n StatusColor,\n StatusInput,\n SubmissionAttachment,\n SubmissionColumn,\n SubmissionCounts,\n SubmissionEvent,\n SubmissionInput,\n SubmissionMassInput,\n SubmissionMeta,\n SubmissionQuery,\n SubmissionRow,\n SubmissionsPage,\n SubmissionValue,\n} from './types'\n"],"names":["inboxMessages","seeded","useInboxMessages","i18n","useAdmin","useStatusName","panel","inject","i18nKey","locales","useLocales","status","locale","localizedValue","props","__props","value","_useModel","admin","t","useTranslate","api","createRelationsApi","slug","computed","known","ref","missing","candidates","searching","term","remember","rows","next","row","name","wanted","watch","chosen","mark","options","one","part","search","query","found","opened","pick","option","nextTick","clear","placeholder","_openBlock","_createElementBlock","_hoisted_1","_hoisted_2","_createElementVNode","_hoisted_3","_hoisted_4","_toDisplayString","_hoisted_5","_createBlock","_unref","WxBadge","WxAction","_hoisted_6","_hoisted_7","_createVNode","WxAutocomplete","$event","inbox","path","FormField","statusRequests","createInboxApi","base","data","body","nothing","forgetStatuses","result","statuses","list","asked","id","input","ids","formId","listQuery","fields","key","suffix","fallback","resolve","dismiss","open","useModal","context","message","useErrorText","loading","saving","values","errors","field","hasFiles","errorOf","label","text","choices","choice","load","form","error","toast","save","WxDialog","WxSpace","WxButton","WxAlert","WxSkeleton","_Fragment","_renderList","WxFormItem","WxTextarea","WxSelect","WxRadioGroup","WxCheckboxGroup","WxCheckbox","WxDatePicker","WxInput","CARDS","emit","__emit","route","useRoute","router","useRouter","root","useTemplateRef","width","useElementWidth","asCards","cardsBelow","page","selected","moving","canUpdate","add","createModal","SubmissionCreateDialog","view","placementOptions","placement","hasPlacements","applied","narrow","views","counts","items","answer","index","column","columns","answers","rowMenuWidth","emptyText","statusOptions","formName","state","onState","statusList","actionsFor","mass","remove","moveTo","statusId","confirm","action","byHand","made","exportHref","actions","__expose","WxScreenHead","WxTabs","WxTable","_keys","_withCtx","WxAvatar","WxTooltip","WxIcon","WxDate","WxEntityCard","_createTextVNode","WxRowMenu","WxText","_cache","WxFilterChips","model","active","WxLocales","WxRichText","FIELD_TYPES","STATUS_COLORS","type","title","help","isEnabled","isRequired","isFullsize","inTable","types","hasChoices","extensions","set","addChoice","removeChoice","_","at","setChoice","patch","LocalizedRichText","WxInputNumber","WxTagsInput","edit","FieldDialog","marks","empty","saved","reorder","WxCard","WxEmpty","WxSortableList","item","WxInboxPage","defineAsyncComponent","WxInboxFormEditor","WxInboxStatusesPage","WxInboxSubmissionPage"],"mappings":"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"}
|