@webx-ui/module-inbox 0.1.0 → 0.2.0
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/LICENSE +21 -0
- package/dist/FormEditorPage.d.ts +1 -1
- package/dist/index.js +1456 -1425
- package/dist/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +9 -9
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/LocalizedRichText.vue","../src/api.ts","../src/messages.ts","../src/i18n.ts","../src/types.ts","../src/FieldDialog.vue","../src/FieldList.vue","../src/options.ts","../src/FormAntispam.vue","../src/FormEmbed.vue","../src/FormGeneral.vue","../src/FormNotifications.vue","../src/FormEditorPage.vue","../src/FormCreateDialog.vue","../src/SubmissionCreateDialog.vue","../src/SubmissionList.vue","../src/InboxPage.vue","../src/StatusDialog.vue","../src/StatusesPage.vue","../src/SubmissionPage.vue","../src/module.ts"],"sourcesContent":["<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 { 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 /** 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/** 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\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: () => admin.http.get<{ data: InboxStatus[] }>(`${base}/statuses`).then(data),\n createStatus: (input) =>\n admin.http.post<{ data: InboxStatus }>(`${base}/statuses`, input).then(data),\n saveStatus: (id, input) =>\n admin.http.put<{ data: InboxStatus }>(`${base}/statuses/${id}`, input).then(data),\n removeStatus: (id) => admin.http.delete(`${base}/statuses/${id}`).then(nothing),\n sortStatuses: (ids) => admin.http.post(`${base}/statuses/sorting`, { ids }).then(nothing),\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'>\n columns: SubmissionsPage['columns']\n counts: SubmissionsPage['counts']\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 })),\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 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 sort: query.sort ?? undefined,\n page: query.page,\n per_page: query.per_page,\n }\n}\n","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 'choose-form': 'Choose a form to see what has come in.',\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 '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 '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 '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-help': 'The keys belong to the site and are set in its settings, not here.',\n 'captcha-off': 'Off',\n 'captcha-recaptcha': 'reCAPTCHA',\n 'captcha-turnstile': 'Turnstile',\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-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': 'Add by hand',\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-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 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 },\n\n fields: {\n field: 'Field',\n 'new-field': 'New field',\n 'edit-field': 'Field',\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","import { useAdmin } from '@webx-ui/module-admin'\nimport { inboxMessages } from './messages'\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","import type { LocalizedValue } from '@webx-ui/core'\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/** 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 '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 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 created_at: string | null\n updated_at: string | null\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 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\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: 'created' | 'status' | 'assignee' | 'note' | 'notified' | string\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/** 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 notified_at: string | null\n notify_error: string | 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 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","<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 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\" icon=\"plus\" @click=\"addChoice\">\n {{ t('fields.add-choice') }}\n </wx-button>\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 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-field'), 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\" icon=\"plus\" @click=\"open(null)\">\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 :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 { 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 } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxCard, WxFormItem, WxInputNumber, WxSelect, WxSwitch } from '@webx-ui/core'\nimport { option } from './options'\nimport type { FormOptions } from './types'\n\n/**\n * The four layers in front of the door (§7), as the three anybody would want to change.\n *\n * The origin check is not here: it is not a dial, it is a fact about where the site is served\n * from, and it lives in the configuration with the rest of the deployment. The captcha keys\n * are not here either — they are the site's, one pair for every form, and a secret repeated\n * in each form's settings is a secret scattered over rows (§5).\n */\nconst options = defineModel<FormOptions>({ required: true })\n\nconst t = useTranslate('webx-inbox')\n\nconst honeypot = option<boolean>(options, 'antispam.honeypot', true)\nconst seconds = option<number>(options, 'antispam.min_seconds', 3)\nconst throttle = option<number>(options, 'antispam.throttle', 5)\nconst captcha = option<string>(options, 'antispam.captcha', 'off')\n\nconst captchas = computed(() => [\n { value: 'off', label: t('panel.captcha-off') },\n { value: 'recaptcha', label: t('panel.captcha-recaptcha') },\n { value: 'turnstile', label: t('panel.captcha-turnstile') },\n])\n</script>\n\n<template>\n <wx-card>\n <wx-form-item :label=\"t('panel.honeypot')\" :help=\"t('panel.honeypot-help')\">\n <wx-switch v-model=\"honeypot\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.min-seconds')\" :help=\"t('panel.min-seconds-help')\">\n <wx-input-number v-model=\"seconds\" :min=\"0\" :max=\"120\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.throttle')\" :help=\"t('panel.throttle-help')\">\n <wx-input-number v-model=\"throttle\" :min=\"0\" :max=\"120\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.captcha')\" :help=\"t('panel.captcha-help')\">\n <wx-select v-model=\"captcha\" :options=\"captchas\" />\n </wx-form-item>\n </wx-card>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { toast, WxAction, WxCard, WxTable, WxText, type TableColumn } from '@webx-ui/core'\nimport { useInboxMessages } from './i18n'\nimport type { InboxField, InboxForm } from './types'\n\n/**\n * How the form gets onto a page.\n *\n * Two answers and both are one line, because the module's whole public half is one tag (§10):\n * a template prints it, and a block type prints the same thing so that an editor never opens\n * a template at all.\n *\n * Under them, the names. A hidden field is filled in by the page it stands on — the address\n * somebody wrote from, the product they were looking at, the campaign that brought them — and\n * the only way to fill one in is to know what it is called (§2.6).\n */\nconst props = defineProps<{ form: InboxForm; slug: string; fields: InboxField[] }>()\n\nuseInboxMessages()\nconst t = useTranslate('webx-inbox')\n\nconst blade = computed(() => `<x-webx-form slug=\"${props.slug}\" />`)\n\nconst block = computed(\n () => `{{-- resources/views/blocks/contact.blade.php --}}\\n<x-webx-form slug=\"${props.slug}\" />`,\n)\n\nconst columns = computed<TableColumn<InboxField>[]>(() => [\n { key: 'key', label: t('fields.name') },\n { key: 'title', label: t('fields.title') },\n { key: 'type', label: t('fields.type'), hideBelow: 520 },\n])\n\n/** Only the ones a page can actually fill in or a visitor can actually answer. */\nconst listed = computed(() => props.fields.filter((field) => field.is_enabled))\n\nasync function copy(text: string): Promise<void> {\n try {\n await navigator.clipboard.writeText(text)\n toast.success(t('panel.copied'))\n } catch {\n // A browser that refuses the clipboard — an insecure origin, a denied permission — still\n // shows the line, and selecting it by hand is what anybody does next anyway.\n }\n}\n</script>\n\n<template>\n <div class=\"wx-inbox-embed\">\n <wx-card :title=\"t('panel.embed-blade')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.embed-blade-help') }}</wx-text>\n\n <div class=\"wx-inbox-embed__snippet\">\n <code>{{ blade }}</code>\n <wx-action icon=\"copy\" :title=\"t('panel.copy')\" @click=\"copy(blade)\" />\n </div>\n </wx-card>\n\n <wx-card :title=\"t('panel.embed-block')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.embed-block-help') }}</wx-text>\n\n <div class=\"wx-inbox-embed__snippet\">\n <code>{{ block }}</code>\n <wx-action icon=\"copy\" :title=\"t('panel.copy')\" @click=\"copy(block)\" />\n </div>\n </wx-card>\n\n <wx-card :title=\"t('panel.embed-names')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.embed-names-help') }}</wx-text>\n\n <wx-table\n :data=\"listed\"\n :columns=\"columns\"\n row-key=\"id\"\n flush\n :empty-text=\"t('fields.no-fields')\"\n >\n <template #cell-key=\"{ row }\">\n <wx-text mono size=\"sm\">fields[{{ row.key }}]</wx-text>\n </template>\n\n <template #cell-title=\"{ row }\">\n {{ Object.values(row.title)[0] ?? row.key }}\n </template>\n\n <template #cell-type=\"{ row }\">\n {{ t(`fields.type-${row.type}`) }}\n </template>\n </wx-table>\n </wx-card>\n </div>\n</template>\n\n<style scoped>\n.wx-inbox-embed {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n}\n\n.wx-inbox-embed__snippet {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n margin-top: var(--wx-space-12);\n padding: var(--wx-space-10) var(--wx-space-12);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-subtle);\n}\n\n.wx-inbox-embed__snippet code {\n flex: 1 1 auto;\n min-width: 0;\n overflow-x: auto;\n white-space: pre;\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-sm);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxCard, WxFormItem, WxInput, WxSwitch, type LocalizedValue } from '@webx-ui/core'\nimport LocalizedRichText from './LocalizedRichText.vue'\nimport { option } from './options'\nimport type { FormOptions } from './types'\n\n/**\n * What the form is, and what it says once it has been sent.\n *\n * The two halves are on two cards because they are read at two different times: the first is\n * set up once, the second is the sentence a visitor sees and is rewritten whenever the\n * marketing does.\n */\ndefineProps<{ errors: Record<string, string[]> }>()\n\nconst settings = defineModel<{ slug: string; title: LocalizedValue; is_enabled: boolean }>(\n 'settings',\n { required: true },\n)\n\nconst options = defineModel<FormOptions>('options', { required: true })\n\nconst t = useTranslate('webx-inbox')\n\nconst heading = option<LocalizedValue>(options, 'thank-you.heading', {})\nconst text = option<LocalizedValue>(options, 'thank-you.text', {})\nconst submit = option<LocalizedValue>(options, 'design.submit-text', {})\nconst redirect = option<string>(options, 'redirect', '')\n</script>\n\n<template>\n <div class=\"wx-inbox-general\">\n <wx-card>\n <wx-form-item :label=\"t('panel.title')\" :error=\"errors.title?.[0]\" required>\n <wx-input v-model=\"settings.title\" localized />\n </wx-form-item>\n\n <wx-form-item\n :label=\"t('panel.slug')\"\n :help=\"t('panel.slug-help')\"\n :error=\"errors.slug?.[0]\"\n required\n >\n <wx-input v-model=\"settings.slug\" placeholder=\"contact\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.is-enabled')\" :help=\"t('panel.is-enabled-help')\">\n <wx-switch v-model=\"settings.is_enabled\" />\n </wx-form-item>\n </wx-card>\n\n <wx-card :title=\"t('panel.after-sending')\">\n <wx-form-item :label=\"t('panel.submit-text')\">\n <wx-input v-model=\"submit\" localized />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.thank-you-heading')\">\n <wx-input v-model=\"heading\" localized />\n </wx-form-item>\n\n <!-- Printed raw on the site, which is why it is written where formatting is possible. -->\n <wx-form-item :label=\"t('panel.thank-you-text')\">\n <localized-rich-text v-model=\"text\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.redirect')\" :help=\"t('panel.redirect-help')\">\n <wx-input v-model=\"redirect\" placeholder=\"/thank-you\" />\n </wx-form-item>\n </wx-card>\n </div>\n</template>\n\n<style scoped>\n.wx-inbox-general {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref } from 'vue'\nimport { useAdmin, useTranslate } from '@webx-ui/module-admin'\nimport {\n WxAction,\n WxAlert,\n WxButton,\n WxCard,\n WxFormItem,\n WxInput,\n WxSelect,\n WxSpace,\n WxText,\n} from '@webx-ui/core'\nimport { createInboxApi } from './api'\nimport { option } from './options'\nimport type { FormOptions, InboxField, InboxRecipient, Recipient } from './types'\n\n/**\n * Who hears that something arrived (§9).\n *\n * Two kinds of recipient and they are not interchangeable. An administrator is written to at\n * the address on their account and in the language they keep the panel in, so changing either\n * changes it everywhere; a typed address is written to in the language the submission came in.\n * The list offered is not every administrator but the ones who may open a submission — a\n * notification is a link, and sending one to somebody who gets a 403 looks like the panel is\n * broken rather than like the form is.\n */\nconst props = defineProps<{ fields: InboxField[]; errors: Record<string, string[]> }>()\n\nconst options = defineModel<FormOptions>({ required: true })\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\nconst t = useTranslate('webx-inbox')\n\nconst admins = ref<InboxRecipient[]>([])\n\nconst recipients = option<Recipient[]>(options, 'recipients', [])\nconst emailField = option<string>(options, 'email_field', '')\n\nonMounted(async () => {\n try {\n admins.value = await api.recipients()\n } catch {\n // Only the shortcut is gone: an address can still be typed, and that is the half of this\n // that has to work.\n }\n})\n\nconst adminOptions = computed(() =>\n admins.value.map((admin) => ({ value: admin.id, label: `${admin.name} · ${admin.email}` })),\n)\n\n/** The fields that could hold the sender's address, plus the option of naming none. */\nconst emailOptions = computed(() => [\n { value: '', label: t('panel.no-email-field') },\n ...props.fields\n .filter((field) => field.type === 'email')\n .map((field) => ({ value: field.key, label: field.key })),\n])\n\nfunction isAdmin(recipient: Recipient): recipient is { admin_id: number } {\n return 'admin_id' in recipient\n}\n\nfunction add(recipient: Recipient): void {\n recipients.value = [...recipients.value, recipient]\n}\n\nfunction remove(index: number): void {\n recipients.value = recipients.value.filter((_, at) => at !== index)\n}\n\nfunction setAdmin(index: number, id: number): void {\n recipients.value = recipients.value.map((one, at) => (at === index ? { admin_id: id } : one))\n}\n\nfunction setEmail(index: number, email: string): void {\n recipients.value = recipients.value.map((one, at) => (at === index ? { email } : one))\n}\n</script>\n\n<template>\n <wx-card :title=\"t('panel.recipients')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.recipients-help') }}</wx-text>\n\n <wx-alert\n v-if=\"errors['options.recipients']\"\n type=\"danger\"\n variant=\"soft\"\n :description=\"errors['options.recipients']?.[0]\"\n />\n\n <div class=\"wx-inbox-recipients\">\n <wx-text v-if=\"recipients.length === 0\" size=\"sm\" tone=\"placeholder\">\n {{ t('panel.no-recipients') }}\n </wx-text>\n\n <div v-for=\"(recipient, index) in recipients\" :key=\"index\" class=\"wx-inbox-recipients__row\">\n <wx-select\n v-if=\"isAdmin(recipient)\"\n :model-value=\"recipient.admin_id\"\n :options=\"adminOptions\"\n @update:model-value=\"(id) => setAdmin(index, Number(id))\"\n />\n <wx-input\n v-else\n :model-value=\"recipient.email\"\n type=\"email\"\n placeholder=\"sales@example.com\"\n @update:model-value=\"(email) => setEmail(index, String(email))\"\n />\n\n <wx-action icon=\"trash\" :title=\"t('panel.remove')\" @click=\"remove(index)\" />\n </div>\n </div>\n\n <wx-space size=\"sm\">\n <wx-button\n variant=\"outline\"\n icon=\"user\"\n :disabled=\"adminOptions.length === 0\"\n @click=\"add({ admin_id: Number(adminOptions[0]?.value) })\"\n >\n {{ t('panel.add-admin') }}\n </wx-button>\n <wx-button variant=\"outline\" icon=\"mail\" @click=\"add({ email: '' })\">\n {{ t('panel.add-email') }}\n </wx-button>\n </wx-space>\n\n <wx-form-item :label=\"t('panel.email-field')\" :help=\"t('panel.email-field-help')\">\n <wx-select v-model=\"emailField\" :options=\"emailOptions\" />\n </wx-form-item>\n </wx-card>\n</template>\n\n<style scoped>\n.wx-inbox-recipients {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n margin-block: var(--wx-space-12);\n}\n\n.wx-inbox-recipients__row {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n}\n\n.wx-inbox-recipients__row > :first-child {\n flex: 1 1 auto;\n min-width: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, reactive, ref, watch } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport { useAdmin, useErrorText, useTranslate, WxBackButton } from '@webx-ui/module-admin'\nimport {\n localizedValue,\n toast,\n useLocales,\n WxActionBar,\n WxBadge,\n WxButton,\n WxSkeleton,\n WxTab,\n WxTabs,\n WxText,\n type LocalizedValue,\n} from '@webx-ui/core'\nimport FieldList from './FieldList.vue'\nimport FormAntispam from './FormAntispam.vue'\nimport FormEmbed from './FormEmbed.vue'\nimport FormGeneral from './FormGeneral.vue'\nimport FormNotifications from './FormNotifications.vue'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport type { FormOptions, InboxField, InboxForm } from './types'\n\n/**\n * One form: what it is called, what it asks, who hears about it, and how it is put on a page.\n *\n * Five tabs and one save. The fields are the exception — a question is written in its own\n * dialog and saved on its own, because it is a row with an identity (§2.1) and because a\n * dragged order that waited for a save button would be an order nobody trusts.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/inbox' })\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\nconst route = useRoute()\nconst router = useRouter()\nconst locales = useLocales()\nuseInboxMessages()\n\nconst t = useTranslate('webx-inbox')\n/* Not the server's `message`: the panel says how a request failed in its own words. */\nconst message = useErrorText()\n\nconst form = ref<InboxForm | null>(null)\nconst fields = ref<InboxField[]>([])\nconst loading = ref(true)\nconst saving = ref(false)\nconst errors = ref<Record<string, string[]>>({})\n\nconst settings = reactive<{ slug: string; title: LocalizedValue; is_enabled: boolean }>({\n slug: '',\n title: {},\n is_enabled: true,\n})\n\nconst options = ref<FormOptions>({})\n\nconst canManage = computed(() => context.can('inbox.manage'))\n\nconst id = computed(() => Number(route.params.id))\n\nconst name = computed(() =>\n form.value === null ? '' : localizedValue(settings.title, locales.active.value, settings.slug),\n)\n\n/** Where a submission would come back to: the section, with this form already chosen. */\nconst backTo = computed(() => `${props.base}?form=${id.value}`)\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n const loaded = await api.form(id.value)\n\n form.value = loaded\n fields.value = loaded.fields ?? []\n settings.slug = loaded.slug\n settings.title = { ...loaded.title }\n settings.is_enabled = loaded.is_enabled\n options.value = { ...loaded.options }\n } catch (error) {\n toast.danger(message(error))\n void router.replace(props.base)\n } finally {\n loading.value = false\n }\n}\n\nwatch(id, () => void load(), { immediate: true })\n\nasync function save(): Promise<void> {\n saving.value = true\n errors.value = {}\n\n try {\n const saved = await api.saveForm(id.value, {\n slug: settings.slug.trim(),\n title: settings.title,\n is_enabled: settings.is_enabled,\n options: options.value,\n })\n\n form.value = saved\n toast.success(t('panel.saved'))\n } catch (error) {\n const body = (error as { body?: { errors?: Record<string, string[]> } }).body\n\n if (body?.errors) {\n errors.value = body.errors\n toast.danger(t('panel.failed'))\n } else {\n toast.danger(message(error))\n }\n } finally {\n saving.value = false\n }\n}\n</script>\n\n<template>\n <div class=\"wx-inbox-editor\" data-wx-fill>\n <wx-skeleton v-if=\"loading\" title :rows=\"8\" />\n\n <template v-else-if=\"form\">\n <div class=\"wx-inbox-editor__head\">\n <wx-back-button :to=\"backTo\" :label=\"t('panel.forms')\" />\n\n <div class=\"wx-inbox-editor__id\">\n <h1 class=\"wx-inbox-editor__title\">{{ name }}</h1>\n <wx-text size=\"sm\" tone=\"muted\" mono>{{ form.slug }}</wx-text>\n </div>\n\n <wx-badge v-if=\"!settings.is_enabled\" type=\"default\">{{ t('panel.off') }}</wx-badge>\n </div>\n\n <!--\n Every tab is mounted at once and the hidden ones keep their state: somebody who wrote\n a thank-you, went to look at the fields and came back should find it still written.\n -->\n <wx-tabs class=\"wx-inbox-editor__tabs\" keep-alive>\n <wx-tab value=\"general\" :label=\"t('panel.tab-general')\">\n <form-general v-model:settings=\"settings\" v-model:options=\"options\" :errors=\"errors\" />\n </wx-tab>\n\n <wx-tab value=\"fields\" :label=\"t('panel.tab-fields')\">\n <field-list v-model=\"fields\" :form=\"form\" :can-manage=\"canManage\" />\n </wx-tab>\n\n <wx-tab value=\"notifications\" :label=\"t('panel.tab-notifications')\">\n <form-notifications v-model=\"options\" :fields=\"fields\" :errors=\"errors\" />\n </wx-tab>\n\n <wx-tab value=\"antispam\" :label=\"t('panel.tab-antispam')\">\n <form-antispam v-model=\"options\" />\n </wx-tab>\n\n <wx-tab value=\"embed\" :label=\"t('panel.tab-embed')\">\n <form-embed :form=\"form\" :slug=\"settings.slug\" :fields=\"fields\" />\n </wx-tab>\n </wx-tabs>\n\n <wx-action-bar v-if=\"canManage\">\n <wx-button type=\"primary\" :loading=\"saving\" @click=\"save\">{{ t('panel.save') }}</wx-button>\n </wx-action-bar>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-inbox-editor {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n min-height: 0;\n}\n\n.wx-inbox-editor__head {\n display: flex;\n align-items: center;\n gap: var(--wx-space-12);\n flex-wrap: wrap;\n}\n\n.wx-inbox-editor__id {\n min-width: 0;\n}\n\n.wx-inbox-editor__title {\n margin: 0;\n font-size: var(--wx-font-size-xl);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n/* The tabs take what is left, and what scrolls is inside them. */\n.wx-inbox-editor__tabs {\n flex: 1 1 auto;\n min-height: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport {\n toast,\n useModal,\n WxButton,\n WxDialog,\n WxFormItem,\n WxInput,\n WxSpace,\n type LocalizedValue,\n} from '@webx-ui/core'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport type { InboxForm } from './types'\n\n/**\n * A form, started.\n *\n * Two fields, because a form has nothing else until it has questions: what it is called and\n * where it answers. Everything else — who is written to, what happens after sending, the\n * antispam — belongs to the editor, and asking for it before the form exists would be a\n * dialog longer than the screen it leads to.\n *\n * The address is typed rather than made out of the title. A page's address is a sentence\n * transliterated; a form's is a short word somebody chooses once and then writes into a\n * template by hand, and guessing `svyazhites-s-nami` for them helps nobody.\n */\nconst { resolve, dismiss, open } = useModal<InboxForm>()\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 title = ref<LocalizedValue>({})\nconst slug = ref('')\nconst saving = ref(false)\nconst errors = ref<Record<string, string[]>>({})\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 try {\n resolve(\n await api.createForm({\n title: title.value,\n slug: slug.value.trim(),\n is_enabled: true,\n options: {},\n }),\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 v-model:open=\"open\" :title=\"t('panel.new-form-title')\" :width=\"520\">\n <div class=\"wx-inbox-create\">\n <wx-form-item :label=\"t('panel.title')\" :error=\"errorOf('title')\" required>\n <wx-input v-model=\"title\" localized autofocus />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.slug')\" :help=\"t('panel.slug-help')\" :error=\"errorOf('slug')\">\n <wx-input v-model=\"slug\" placeholder=\"contact\" />\n </wx-form-item>\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\" @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-create {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n</style>\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, watch } from 'vue'\nimport { useRoute, useRouter, type LocationQueryRaw } from 'vue-router'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxDate,\n WxRowMenu,\n type RowAction,\n} from '@webx-ui/module-admin'\nimport {\n confirm,\n createModal,\n localizedValue,\n toast,\n useLocales,\n WxAction,\n WxAvatar,\n WxBadge,\n WxButton,\n WxHeading,\n WxIcon,\n WxSelect,\n WxTable,\n WxTabs,\n WxText,\n WxTooltip,\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 } 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 /** Whether the pane is beside the list of forms or is the whole screen. */\n inline?: boolean\n }>(),\n { base: '/inbox', inline: true },\n)\n\nconst emit = defineEmits<{\n /** The pane wants out — only ever on a phone, where it is the screen. */\n back: []\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\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 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'))\nconst canManage = computed(() => context.can('inbox.manage'))\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 sort: typeof route.query.sort === 'string' ? route.query.sort : null,\n page: Number(route.query.page ?? 1) || 1,\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\nconst columns = computed<TableColumn<SubmissionRow>[]>(() => {\n const answers = page.value?.columns ?? []\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: 150,\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: 56, 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' && query.value.search === '' && query.value.assignee === 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\nfunction name(status: InboxStatus): string {\n return localizedValue(status.title, locales.active.value, status.key)\n}\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 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. */\nwatch(\n () => [props.form.id, view.value, query.value.assignee] as const,\n () => {\n selected.value = []\n void load()\n },\n)\n\nvoid load()\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 sort: query.value.sort,\n }),\n)\n\nfunction settings(): void {\n void router.push(`${props.base}/forms/${props.form.id}`)\n}\n</script>\n\n<template>\n <div class=\"wx-submissions\">\n <div class=\"wx-submissions__head\">\n <!-- On a phone the pane is a screen of its own and the drawer carries no close of its\n own, so the way back has to be here. Beside the list there is nothing to go back to. -->\n <wx-action v-if=\"!inline\" icon=\"arrow-left\" :title=\"t('panel.forms')\" @click=\"emit('back')\" />\n\n <div class=\"wx-submissions__who\">\n <wx-heading :level=\"3\" truncate>{{ formName() }}</wx-heading>\n <wx-text size=\"sm\" tone=\"muted\" mono truncate>{{ form.slug }}</wx-text>\n </div>\n\n <wx-button v-if=\"canUpdate\" variant=\"outline\" icon=\"plus\" size=\"sm\" @click=\"byHand\">{{\n t('panel.new-submission')\n }}</wx-button>\n <wx-button variant=\"outline\" icon=\"download\" size=\"sm\" :href=\"exportHref\">\n {{ t('panel.export') }}\n </wx-button>\n <wx-button v-if=\"canManage\" variant=\"outline\" icon=\"settings\" size=\"sm\" @click=\"settings\">\n {{ t('panel.settings') }}\n </wx-button>\n </div>\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 :selectable=\"canUpdate\"\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=\"640\"\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 #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\" />\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.wx-submissions {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n padding: var(--wx-space-16);\n min-width: 0;\n height: 100%;\n min-height: 0;\n}\n\n.wx-submissions__head {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n flex-wrap: wrap;\n}\n\n/* The name takes the middle, so the way back stays at the start of the line and the buttons\n stay at its end. */\n.wx-submissions__who {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.wx-submissions__views {\n flex: 1 1 auto;\n min-height: 0;\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, ref, watch } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxListScreen,\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 WxCard,\n WxEmpty,\n WxListDetail,\n WxSkeleton,\n WxSortableList,\n WxText,\n} from '@webx-ui/core'\nimport FormCreateDialog from './FormCreateDialog.vue'\nimport SubmissionList from './SubmissionList.vue'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport type { InboxForm } from './types'\n\n/**\n * The section: the forms of the site on the left, what came in through one of them on the\n * right (§11, §2.12).\n *\n * One screen rather than two, and that is the decision this is built around. The columns of\n * the list are the fields of the chosen form, so a list of everything would have no columns\n * to speak of; and the two questions somebody opens this section to ask — \"what is new\" and\n * \"what does this form ask\" — are one click apart instead of one screen apart.\n *\n * The right-hand side is the submissions, and it arrives with them. What is here is the\n * column: the forms, in the order somebody dragged them, with what is waiting in each.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/inbox' })\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\nconst route = useRoute()\nconst router = useRouter()\nconst locales = useLocales()\nuseInboxMessages()\n\nconst t = useTranslate('webx-inbox')\n/* Not the server's `message`: the panel says how a request failed in its own words. */\nconst message = useErrorText()\n\nconst forms = ref<InboxForm[]>([])\nconst loading = ref(true)\nconst open = ref(false)\n\nconst canManage = computed(() => context.can('inbox.manage'))\n\nconst create = createModal<InboxForm, Record<string, never>>(FormCreateDialog)\n\nconst title = computed(\n () =>\n context.state.manifest?.modules.find((module) => module.id === 'inbox')?.title ??\n t('module.title'),\n)\n\n/**\n * Which form is open, kept in the address.\n *\n * So that coming back from a submission lands on the form it belonged to (§11) — and so that\n * a link to \"the callback form\" is a link somebody can send.\n */\nconst current = computed<number | null>(() => {\n const asked = route.query.form\n\n return typeof asked === 'string' && asked !== '' ? Number(asked) : null\n})\n\nconst chosen = computed(() => forms.value.find((form) => form.id === current.value) ?? null)\n\nfunction name(form: InboxForm): string {\n return localizedValue(form.title, locales.active.value, form.slug)\n}\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n forms.value = await api.forms()\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n}\n\nvoid load()\n\n/* A form chosen while the list was still loading is still chosen once it arrives. */\nwatch(chosen, (form) => {\n if (form !== null) open.value = true\n})\n\nfunction choose(form: InboxForm): void {\n void router.replace({ query: { ...route.query, form: String(form.id) } })\n open.value = true\n}\n\nfunction edit(form: InboxForm): void {\n void router.push(`${props.base}/forms/${form.id}`)\n}\n\nfunction actionsFor(form: InboxForm): RowAction[] {\n if (!canManage.value) return []\n\n return [\n { key: 'settings', icon: 'settings', label: t('panel.settings'), run: () => edit(form) },\n { key: 'duplicate', icon: 'copy', label: t('panel.duplicate'), run: () => duplicate(form) },\n // A form that has taken submissions is switched off, never deleted (§2.4). The line is\n // left out rather than greyed: a menu is a list of what is possible.\n ...(form.submissions_count === 0\n ? [\n {\n key: 'delete',\n icon: 'trash' as const,\n label: t('panel.delete'),\n danger: true,\n run: () => remove(form),\n },\n ]\n : []),\n ]\n}\n\nasync function add(): Promise<void> {\n const made = await create({})\n\n if (made) {\n await load()\n edit(made)\n }\n}\n\nasync function duplicate(form: InboxForm): Promise<void> {\n try {\n const copy = await api.duplicateForm(form.id)\n toast.success(t('panel.duplicated'))\n await load()\n edit(copy)\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nasync function remove(form: InboxForm): Promise<void> {\n const agreed = await confirm({\n title: t('panel.delete-form-title', { form: name(form) }),\n message: t('panel.delete-form-text'),\n confirmText: t('panel.delete'),\n cancelText: t('panel.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n try {\n await api.removeForm(form.id)\n toast.success(t('panel.deleted'))\n\n if (current.value === form.id) {\n const rest = { ...route.query }\n delete rest.form\n void router.replace({ query: rest })\n open.value = false\n }\n\n await load()\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\n/**\n * The whole order, every time.\n *\n * The list is already in its new order on screen — `WxSortableList` reorders the model before\n * it says anything — so this only has to agree with what is there, and a failure has to put\n * the list back rather than leave the screen disagreeing with the database.\n */\nasync function reorder(): Promise<void> {\n try {\n await api.sortForms(forms.value.map((form) => form.id))\n } catch (error) {\n toast.danger(message(error, t('panel.reorder-failed')))\n await load()\n }\n}\n</script>\n\n<template>\n <wx-list-screen :title=\"title\" :card=\"false\" fill>\n <template #actions>\n <wx-button\n v-if=\"canManage\"\n variant=\"outline\"\n icon=\"tag\"\n @click=\"router.push(`${props.base}/statuses`)\"\n >\n {{ t('panel.statuses') }}\n </wx-button>\n <wx-button v-if=\"canManage\" type=\"primary\" icon=\"plus\" @click=\"add\">\n {{ t('panel.new-form') }}\n </wx-button>\n </template>\n\n <wx-card class=\"wx-inbox\" padding=\"none\">\n <wx-list-detail\n v-model:open=\"open\"\n class=\"wx-inbox__panes\"\n :list-width=\"270\"\n :detail-min=\"420\"\n :detail-label=\"chosen ? name(chosen) : t('panel.forms')\"\n >\n <template #list>\n <wx-skeleton v-if=\"loading\" class=\"wx-inbox__loading\" :rows=\"5\" />\n\n <wx-empty\n v-else-if=\"forms.length === 0\"\n :title=\"t('panel.no-forms')\"\n :description=\"t('panel.no-forms-help')\"\n />\n\n <!--\n A grip and not the whole row: the row is what opens a form, and a list whose rows\n both open and drag is a list where one of the two happens by accident.\n -->\n <wx-sortable-list\n v-else\n v-model=\"forms\"\n class=\"wx-inbox__forms\"\n plain\n size=\"sm\"\n item-key=\"id\"\n :item-label=\"name\"\n :disabled=\"!canManage\"\n :title=\"t('panel.forms')\"\n @move=\"reorder\"\n >\n <template #default=\"{ item }\">\n <button\n type=\"button\"\n class=\"wx-inbox-form\"\n :class=\"{ 'is-current': item.id === current }\"\n @click=\"choose(item)\"\n >\n <span class=\"wx-inbox-form__name\">\n <wx-text truncate weight=\"medium\">{{ name(item) }}</wx-text>\n <wx-badge v-if=\"!item.is_enabled\" type=\"default\">{{ t('panel.off') }}</wx-badge>\n </span>\n <wx-text size=\"sm\" tone=\"muted\" truncate>{{ item.slug }}</wx-text>\n </button>\n\n <!-- Unread first and in colour; the total behind it, quietly, because it is\n context rather than work. -->\n <wx-badge\n v-if=\"item.unread_count\"\n type=\"primary\"\n class=\"wx-inbox-form__count\"\n :title=\"t('panel.unread')\"\n >\n {{ item.unread_count }}\n </wx-badge>\n <wx-text\n v-else-if=\"item.submissions_count\"\n size=\"sm\"\n tone=\"muted\"\n :title=\"t('panel.submissions')\"\n >\n {{ item.submissions_count }}\n </wx-text>\n </template>\n\n <template #actions=\"{ item }\">\n <wx-row-menu :actions=\"actionsFor(item)\" :label=\"name(item)\" />\n </template>\n </wx-sortable-list>\n </template>\n\n <template #empty>\n <wx-empty :description=\"t('panel.choose-form')\" />\n </template>\n\n <!--\n The submissions of the chosen form. The pane is the list's, head and all: what is\n above the rows — which form this is, the way back on a phone, the way into what it\n asks — belongs beside the tabs and not above the drawer.\n -->\n <template #detail=\"{ inline, back }\">\n <submission-list\n v-if=\"chosen\"\n :key=\"chosen.id\"\n :form=\"chosen\"\n :base=\"props.base\"\n :inline=\"inline\"\n @back=\"back\"\n @changed=\"load\"\n />\n </template>\n </wx-list-detail>\n </wx-card>\n </wx-list-screen>\n</template>\n\n<style>\n.wx-inbox {\n height: 100%;\n min-height: 0;\n}\n\n/* The card is the screen: what scrolls is inside it, not the page behind it. */\n.wx-inbox > .wx-card__body {\n height: 100%;\n min-height: 0;\n display: flex;\n flex-direction: column;\n}\n\n.wx-inbox__panes {\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.wx-inbox__loading {\n padding: var(--wx-space-16);\n}\n\n.wx-inbox__forms {\n padding: var(--wx-space-8);\n}\n\n.wx-inbox-form {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-2);\n align-items: flex-start;\n /* The row is the target, so it takes the row: a name of four letters should not leave\n three quarters of the line dead. */\n flex: 1 1 auto;\n min-width: 0;\n padding: 0;\n border: 0;\n background: none;\n font: inherit;\n color: inherit;\n text-align: start;\n cursor: pointer;\n}\n\n.wx-inbox-form__name {\n display: flex;\n align-items: center;\n gap: var(--wx-space-6);\n min-width: 0;\n max-width: 100%;\n}\n\n/*\n * The chosen form, marked on the whole row rather than on the name inside it: the row is what\n * was clicked, and a colour on the words alone leaves the grip and the menu looking like they\n * belong to something else. `:has()` because the row is the list's element and the class is\n * ours — the slot cannot reach the element it is drawn into.\n */\n.wx-inbox__forms .wx-sortable-list__row:has(.wx-inbox-form.is-current) {\n background: var(--wx-bg-subtle);\n border-radius: var(--wx-radius-sm);\n}\n\n.wx-inbox-form.is-current {\n color: var(--wx-color-primary);\n}\n\n.wx-inbox-form__count {\n flex: 0 0 auto;\n}\n</style>\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 WxButton,\n WxCheckbox,\n WxDialog,\n WxFormItem,\n WxInput,\n WxSelect,\n WxSpace,\n type LocalizedValue,\n} from '@webx-ui/core'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport { STATUS_COLORS, type InboxStatus, type StatusColor } from './types'\n\n/**\n * One state, written.\n *\n * The colour is a tone rather than a swatch: the panel has a light theme and a dark one, and\n * a colour picked in one of them is unreadable in the other.\n *\n * Nothing here refuses a second default — the server clears the flag on whoever had it, which\n * is what somebody moving the default from one status to another means, and refusing the save\n * would be the other reading of the same click.\n */\nconst props = defineProps<{ status: InboxStatus | null }>()\n\nconst { resolve, dismiss, open } = useModal<InboxStatus>()\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 key = ref('')\nconst title = ref<LocalizedValue>({})\nconst color = ref<StatusColor>('default')\nconst isDefault = ref(false)\nconst isSpam = ref(false)\nconst isClosed = ref(false)\nconst saving = ref(false)\nconst errors = ref<Record<string, string[]>>({})\n\nwatch(\n () => props.status,\n (status) => {\n key.value = status?.key ?? ''\n title.value = { ...(status?.title ?? {}) }\n color.value = status?.color ?? 'default'\n isDefault.value = status?.is_default ?? false\n isSpam.value = status?.is_spam ?? false\n isClosed.value = status?.is_closed ?? false\n errors.value = {}\n },\n { immediate: true },\n)\n\nconst colors = computed(() =>\n STATUS_COLORS.map((one) => ({ value: one, label: t(`panel.color-${one}`) })),\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 key: key.value.trim(),\n title: title.value,\n color: color.value,\n is_default: isDefault.value,\n is_spam: isSpam.value,\n is_closed: isClosed.value,\n }\n\n try {\n resolve(\n props.status === null\n ? await api.createStatus(input)\n : await api.saveStatus(props.status.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=\"status ? t('panel.settings') : t('panel.new-status')\"\n :width=\"520\"\n >\n <div class=\"wx-inbox-status-form\">\n <wx-form-item :label=\"t('panel.title')\" :error=\"errorOf('title')\" required>\n <wx-input v-model=\"title\" localized />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.status-key')\" :error=\"errorOf('key')\" required>\n <wx-input v-model=\"key\" placeholder=\"in-progress\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.status-color')\" :error=\"errorOf('color')\">\n <wx-select v-model=\"color\" :options=\"colors\" />\n </wx-form-item>\n\n <div class=\"wx-inbox-status-form__checks\">\n <wx-checkbox v-model=\"isDefault\" :label=\"t('panel.status-default')\" />\n <wx-checkbox v-model=\"isSpam\" :label=\"t('panel.status-spam')\" />\n <wx-checkbox v-model=\"isClosed\" :disabled=\"isSpam\" :label=\"t('panel.status-closed')\" />\n </div>\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\" @click=\"save\">{{ t('panel.save') }}</wx-button>\n </wx-space>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-inbox-status-form {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n.wx-inbox-status-form__checks {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-16);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxBackButton,\n WxListScreen,\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 WxEmpty,\n WxSortableList,\n WxText,\n} from '@webx-ui/core'\nimport StatusDialog from './StatusDialog.vue'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport type { InboxStatus } from './types'\n\n/**\n * The states a submission can be in (§2.11).\n *\n * Rows rather than an enum, because every panel ends up wanting its own words — and the flags\n * are what the section reads, not the keys, so renaming \"New\" to whatever this client calls\n * it keeps it the status a new submission gets.\n *\n * Their order is the order of the tabs over the list of submissions, which is why it is\n * dragged rather than typed.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/inbox' })\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 statuses = ref<InboxStatus[]>([])\nconst loading = ref(true)\n\nconst canManage = context.can('inbox.manage')\n\nconst edit = createModal<InboxStatus, { status: InboxStatus | null }>(StatusDialog)\n\nfunction name(status: InboxStatus): string {\n return localizedValue(status.title, locales.active.value, status.key)\n}\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n statuses.value = await api.statuses()\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n}\n\nvoid load()\n\nasync function open(status: InboxStatus | null): Promise<void> {\n if (await edit({ status })) await load()\n}\n\nasync function remove(status: InboxStatus): Promise<void> {\n const agreed = await confirm({\n title: t('panel.delete-status-title', { status: name(status) }),\n message: t('panel.delete-status-text'),\n confirmText: t('panel.delete'),\n cancelText: t('panel.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n try {\n await api.removeStatus(status.id)\n toast.success(t('panel.deleted'))\n await load()\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nfunction actionsFor(status: InboxStatus): RowAction[] {\n if (!canManage) return []\n\n return [\n { key: 'edit', icon: 'edit', label: t('panel.settings'), run: () => void open(status) },\n // A status with submissions in them cannot go: they would have nothing to be in. The\n // line is left out rather than greyed, the way every list of the panel does it.\n ...(status.submissions_count === 0\n ? [\n {\n key: 'delete',\n icon: 'trash' as const,\n label: t('panel.delete'),\n danger: true,\n run: () => void remove(status),\n },\n ]\n : []),\n ]\n}\n\nasync function reorder(): Promise<void> {\n try {\n await api.sortStatuses(statuses.value.map((status) => status.id))\n } catch (error) {\n toast.danger(message(error, t('panel.reorder-failed')))\n await load()\n }\n}\n</script>\n\n<template>\n <div class=\"wx-inbox-statuses\">\n <!-- Above the heading, where the way out of a screen is on every other one: beside the\n primary action it reads as a second thing to do rather than as a way back. -->\n <wx-back-button :to=\"props.base\" :label=\"t('panel.forms')\" />\n\n <wx-list-screen :title=\"t('panel.statuses')\">\n <template #actions>\n <wx-button v-if=\"canManage\" type=\"primary\" icon=\"plus\" @click=\"open(null)\">\n {{ t('panel.new-status') }}\n </wx-button>\n </template>\n\n <wx-empty v-if=\"!loading && statuses.length === 0\" :title=\"t('panel.no-statuses')\" />\n\n <wx-sortable-list\n v-else\n v-model=\"statuses\"\n plain\n item-key=\"id\"\n :item-label=\"name\"\n :disabled=\"!canManage\"\n :aria-label=\"t('panel.statuses')\"\n @move=\"reorder\"\n >\n <template #default=\"{ item }\">\n <div class=\"wx-inbox-status\">\n <wx-badge :type=\"item.color\">{{ name(item) }}</wx-badge>\n\n <wx-text size=\"sm\" tone=\"muted\" truncate>\n <code>{{ item.key }}</code>\n <template v-if=\"item.is_default\"> · {{ t('panel.status-default') }}</template>\n <template v-if=\"item.is_spam\"> · {{ t('panel.status-spam') }}</template>\n <template v-else-if=\"item.is_closed\"> · {{ t('panel.status-closed') }}</template>\n <template v-if=\"item.submissions_count\">\n · {{ t('panel.in-use') }} ({{ item.submissions_count }})\n </template>\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-list-screen>\n </div>\n</template>\n\n<style scoped>\n.wx-inbox-statuses {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--wx-space-12);\n}\n\n.wx-inbox-statuses > .wx-list-screen {\n align-self: stretch;\n}\n\n.wx-inbox-status {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n flex: 1 1 auto;\n min-width: 0;\n flex-wrap: wrap;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxBackButton,\n WxDate,\n WxNotes,\n WxRowMenu,\n type RowAction,\n} from '@webx-ui/module-admin'\nimport {\n confirm,\n localizedValue,\n toast,\n useLocales,\n WxAction,\n WxAlert,\n WxBadge,\n WxButton,\n WxCard,\n WxDescriptions,\n WxDescriptionsItem,\n WxEmpty,\n WxFileCard,\n WxHeading,\n WxSelect,\n WxSkeleton,\n WxText,\n WxTimeline,\n WxTimelineItem,\n} from '@webx-ui/core'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport type { InboxRecipient, InboxStatus, InboxSubmission, SubmissionEvent } from './types'\n\n/**\n * One submission, on a screen of its own (§11).\n *\n * A dialog over the list would have kept the filters under the reader's hand, and it was\n * rejected for one reason: a submission needs an address somebody can send. It goes into the\n * mail to whoever deals with it, it gets pasted into a chat, an agent links to it. What the\n * dialog would have given back is paid for here instead — the list's whole state travels in\n * the address, so the way out lands exactly where the reader was, and the arrows walk the same\n * filtered pile.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/inbox' })\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\nconst route = useRoute()\nconst router = useRouter()\nconst locales = useLocales()\nuseInboxMessages()\n\nconst t = useTranslate('webx-inbox')\n/* Not the server's `message`: the panel says how a request failed in its own words. */\nconst message = useErrorText()\n\nconst submission = ref<InboxSubmission | null>(null)\nconst statuses = ref<InboxStatus[]>([])\nconst admins = ref<InboxRecipient[]>([])\nconst loading = ref(true)\n\nconst canUpdate = computed(() => context.can('inbox.update'))\n\nconst id = computed(() => Number(route.params.id))\n\n/** Everything the list was looking at, carried along so the arrows walk the same pile. */\nconst filter = computed(() => ({\n view: typeof route.query.view === 'string' ? route.query.view : undefined,\n search: typeof route.query.search === 'string' ? route.query.search : undefined,\n assignee: typeof route.query.assignee === 'string' ? route.query.assignee : undefined,\n}))\n\n/** Back to the list, on the form, the tab and the page it was left at. */\nconst backTo = computed(() => ({ path: props.base, query: { ...route.query } }))\n\nconst statusOptions = computed(() =>\n statuses.value.map((status) => ({ value: status.id, label: name(status) })),\n)\n\n/* Nobody is not an option in the list but the empty state of the control: a select whose\n first line means \"none\" is one somebody picks by accident, and `clearable` already says\n it. */\nconst assigneeOptions = computed(() =>\n admins.value.map((admin) => ({ value: admin.id, label: admin.name })),\n)\n\nfunction name(status: InboxStatus): string {\n return localizedValue(status.title, locales.active.value, status.key)\n}\n\nconst heading = computed(() => t('panel.submission', { id: String(id.value) }))\n\nconst formTitle = computed(() => {\n const form = submission.value?.form\n\n return form === undefined\n ? ''\n : localizedValue(form.title ?? {}, locales.active.value, form.slug ?? '')\n})\n\n/**\n * Where a reply goes.\n *\n * The form says which field holds the sender's address (`email_field`); without one, the first\n * answer that was asked as an e-mail is the honest guess, and where there is none the button\n * is simply not there — a `mailto:` with nothing after it opens an empty window.\n */\nconst replyTo = computed(() => {\n const values = submission.value?.values ?? []\n const answer = values.find((value) => value.type === 'email' && (value.value ?? '') !== '')\n\n return answer?.value ?? null\n})\n\nconst mailto = computed(() => {\n if (replyTo.value === null) return null\n\n const subject = encodeURIComponent(`${formTitle.value} — ${heading.value}`)\n\n return `mailto:${replyTo.value}?subject=${subject}`\n})\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n submission.value = await api.submission(id.value, filter.value)\n } catch (error) {\n toast.danger(message(error))\n void router.replace(backTo.value)\n } finally {\n loading.value = false\n }\n}\n\nasync function lists(): Promise<void> {\n try {\n statuses.value = await api.statuses()\n\n // Only where there is something to do with them: assigning is `inbox.update`, and the\n // list of administrators is not a reader's business.\n if (canUpdate.value) {\n admins.value = await api.recipients()\n }\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\n/* The arrows change the address without leaving the screen, so the record has to follow it. */\nwatch(id, () => void load(), { immediate: true })\n\nvoid lists()\n\nasync function save(input: { status_id?: number; assignee_id?: number | null }): Promise<void> {\n try {\n submission.value = await api.saveSubmission(id.value, input)\n toast.success(t('panel.saved'))\n } catch (error) {\n toast.danger(message(error))\n await load()\n }\n}\n\nfunction onStatus(value: unknown): void {\n if (typeof value === 'number') void save({ status_id: value })\n}\n\nfunction onAssignee(value: unknown): void {\n void save({ assignee_id: typeof value === 'number' ? value : null })\n}\n\nconst actions = computed<RowAction[]>(() => {\n if (!canUpdate.value || submission.value === null) return []\n\n return [\n {\n key: 'unread',\n icon: 'eye-off',\n label: t('panel.mark-unread'),\n run: () => void unread(),\n },\n {\n key: 'delete',\n icon: 'trash',\n label: t('panel.delete'),\n danger: true,\n run: () => void remove(),\n },\n ]\n})\n\nasync function unread(): Promise<void> {\n try {\n await api.massSubmissions({ ids: [id.value], action: 'unread' })\n // Straight back to the list: a submission marked unread and then left open is one the\n // next request would mark read again.\n void router.push(backTo.value)\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nasync function remove(): Promise<void> {\n const agreed = await confirm({\n title: t('panel.delete-submission-title'),\n message: t('panel.delete-submission-text'),\n confirmText: t('panel.delete'),\n cancelText: t('panel.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n try {\n await api.removeSubmission(id.value)\n toast.success(t('panel.deleted'))\n void router.push(backTo.value)\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nfunction go(to: number | null): void {\n if (to === null) return\n\n void router.push({ path: `${props.base}/submissions/${to}`, query: { ...route.query } })\n}\n\n/**\n * A status the log names, in the words the panel calls it by.\n *\n * The log stores the key on purpose — read months later, the row it pointed at may have been\n * renamed or deleted, and history must not be rewritten by either. So the key is translated\n * where the panel still has that status, and shown as it stands where it does not: `spam` is\n * a poorer line than \"Спам\", and an invented one would be worse than both.\n */\nfunction statusName(key: string): string {\n const status = statuses.value.find((one) => one.key === key)\n\n return status === undefined ? key : name(status)\n}\n\n/** One line of the log, in words rather than as a pair of columns. */\nfunction line(event: SubmissionEvent): string {\n switch (event.type) {\n case 'created':\n return t('panel.event-created')\n case 'status':\n return t('panel.event-status', { to: statusName(event.to ?? '') })\n case 'assignee':\n return event.to === null || event.to === ''\n ? t('panel.event-unassigned')\n : t('panel.event-assignee', { to: event.to })\n case 'note':\n return t('panel.event-note')\n case 'notified':\n return t('panel.event-notified')\n default:\n return event.type\n }\n}\n\nfunction kilobytes(size: number): string {\n return `${Math.max(1, Math.round(size / 1024))} KB`\n}\n\n/** The metadata worth showing, in the order somebody reads it, with the empty ones left out. */\nconst details = computed(() => {\n const meta = submission.value?.meta ?? {}\n\n const rows: { label: string; value: string; link?: boolean }[] = []\n\n if (typeof meta.page === 'string' && meta.page !== '') {\n rows.push({ label: t('panel.meta-page'), value: meta.page, link: true })\n }\n\n if (typeof meta.referrer === 'string' && meta.referrer !== '') {\n rows.push({ label: t('panel.meta-referrer'), value: meta.referrer, link: true })\n }\n\n for (const [key, value] of Object.entries(meta.utm ?? {})) {\n rows.push({ label: key, value: String(value) })\n }\n\n if (typeof meta.locale === 'string' && meta.locale !== '') {\n rows.push({ label: t('panel.meta-locale'), value: meta.locale })\n }\n\n if (typeof meta.ip === 'string' && meta.ip !== '') {\n rows.push({ label: t('panel.meta-ip'), value: meta.ip })\n }\n\n if (typeof meta.user_agent === 'string' && meta.user_agent !== '') {\n rows.push({ label: t('panel.meta-agent'), value: meta.user_agent })\n }\n\n return rows\n})\n</script>\n\n<template>\n <div class=\"wx-submission\">\n <div class=\"wx-submission__head\">\n <wx-back-button :to=\"backTo\" />\n\n <div class=\"wx-submission__who\">\n <wx-heading :level=\"2\" truncate>{{ heading }}</wx-heading>\n <wx-text size=\"sm\" tone=\"muted\" truncate>{{ formTitle }}</wx-text>\n </div>\n\n <!-- The same pile the reader was looking at, one step at a time. An arrow with nowhere\n to go is disabled rather than hidden: the pair is a control, and a control that\n changes shape at the ends is one that moves under the hand. -->\n <wx-action\n icon=\"chevron-left\"\n :title=\"t('panel.previous')\"\n :disabled=\"!submission?.previous_id\"\n @click=\"go(submission?.previous_id ?? null)\"\n />\n <wx-action\n icon=\"chevron-right\"\n :title=\"t('panel.next')\"\n :disabled=\"!submission?.next_id\"\n @click=\"go(submission?.next_id ?? null)\"\n />\n\n <wx-button v-if=\"mailto\" variant=\"outline\" icon=\"mail\" :href=\"mailto\">\n {{ t('panel.reply') }}\n </wx-button>\n\n <wx-row-menu :actions=\"actions\" :label=\"heading\" />\n </div>\n\n <wx-skeleton v-if=\"loading\" :rows=\"6\" />\n\n <div v-else-if=\"submission\" class=\"wx-submission__panes\">\n <div class=\"wx-submission__main\">\n <wx-card :title=\"t('panel.answers')\">\n <wx-empty\n v-if=\"submission.values.length === 0\"\n size=\"sm\"\n :description=\"t('panel.no-answers')\"\n />\n <!-- The labels are the snapshot written when it arrived, never the field's current\n words: a submission from a year ago has to read as it did (§2.2). -->\n <wx-descriptions v-else :columns=\"1\" layout=\"vertical\">\n <wx-descriptions-item\n v-for=\"value in submission.values\"\n :key=\"value.id\"\n :label=\"value.label ?? value.name\"\n >\n <p class=\"wx-submission__value\">{{ value.value || '—' }}</p>\n </wx-descriptions-item>\n </wx-descriptions>\n </wx-card>\n\n <wx-card v-if=\"submission.files.length > 0\" :title=\"t('panel.attachments')\">\n <div class=\"wx-submission__files\">\n <!-- Through the panel and not from the disk: the bytes are behind the same\n permission as the submission, for as long as the reader has it (§8). -->\n <wx-file-card\n v-for=\"file in submission.files\"\n :key=\"file.id\"\n :name=\"file.name\"\n :type=\"file.mime ?? undefined\"\n :download-url=\"file.url\"\n :download-label=\"t('panel.download')\"\n size=\"sm\"\n >\n <template #meta>{{ kilobytes(file.size) }}</template>\n </wx-file-card>\n </div>\n </wx-card>\n\n <!-- The feed is the panel's own, not this module's: the same one will hang off an\n order and a client (§2.17). It carries its own heading. -->\n <wx-card>\n <wx-notes :id=\"submission.id\" type=\"inbox_submission\" :can=\"canUpdate\" @change=\"load\" />\n </wx-card>\n </div>\n\n <aside class=\"wx-submission__aside\">\n <wx-card>\n <div class=\"wx-submission__fields\">\n <label class=\"wx-submission__field\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.status') }}</wx-text>\n <wx-select\n :model-value=\"submission.status?.id ?? null\"\n :options=\"statusOptions\"\n :disabled=\"!canUpdate\"\n @update:model-value=\"onStatus\"\n />\n </label>\n\n <label class=\"wx-submission__field\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.assignee') }}</wx-text>\n <wx-select\n :model-value=\"submission.assignee?.id ?? null\"\n :options=\"assigneeOptions\"\n :disabled=\"!canUpdate\"\n clearable\n :placeholder=\"t('panel.unassigned')\"\n @update:model-value=\"onAssignee\"\n />\n </label>\n </div>\n </wx-card>\n\n <wx-card :title=\"t('panel.details')\">\n <div class=\"wx-submission__fields\">\n <wx-descriptions :columns=\"1\" layout=\"vertical\" size=\"sm\">\n <wx-descriptions-item :label=\"t('panel.received')\">\n <wx-date :value=\"submission.created_at\" tone=\"default\" />\n </wx-descriptions-item>\n <wx-descriptions-item :label=\"t('panel.meta-source')\">\n <wx-badge :type=\"submission.source === 'panel' ? 'info' : 'default'\">\n {{\n submission.source === 'panel' ? t('panel.source-panel') : t('panel.source-web')\n }}\n </wx-badge>\n </wx-descriptions-item>\n <wx-descriptions-item v-for=\"row in details\" :key=\"row.label\" :label=\"row.label\">\n <a v-if=\"row.link\" :href=\"row.value\" target=\"_blank\" rel=\"noreferrer\">{{\n row.value\n }}</a>\n <span v-else class=\"wx-submission__detail\">{{ row.value }}</span>\n </wx-descriptions-item>\n </wx-descriptions>\n\n <!-- An unsent notification is a mark on the submission, not a lost one (§2.10),\n and the only place it is ever said out loud is here. -->\n <wx-alert v-if=\"submission.notify_error\" type=\"warning\" :closable=\"false\">\n {{ t('panel.notify-failed') }}\n </wx-alert>\n <wx-text v-else-if=\"submission.notified_at\" size=\"sm\" tone=\"muted\">\n {{ t('panel.notified') }}\n </wx-text>\n <wx-text v-else size=\"sm\" tone=\"muted\">{{ t('panel.not-notified') }}</wx-text>\n </div>\n </wx-card>\n\n <wx-card :title=\"t('panel.log')\">\n <wx-timeline size=\"sm\">\n <wx-timeline-item v-for=\"event in submission.events\" :key=\"event.id\">\n <!-- What happened on one line and who did it when on the next: three inline\n pieces in a row run into each other, and a log is read down. -->\n <wx-text size=\"sm\" as=\"p\" class=\"wx-submission__event\">{{ line(event) }}</wx-text>\n <p class=\"wx-submission__by\">\n <wx-text size=\"sm\" tone=\"muted\">\n {{ event.author?.name ?? t('panel.system') }}\n </wx-text>\n <wx-date :value=\"event.created_at\" />\n </p>\n </wx-timeline-item>\n </wx-timeline>\n </wx-card>\n </aside>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-submission {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n min-width: 0;\n /* The panes below decide their own layout from the width of the screen rather than of the\n window: the panel has a sidebar, and the window knows nothing about it. */\n container-type: inline-size;\n}\n\n.wx-submission__head {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n flex-wrap: wrap;\n}\n\n.wx-submission__who {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.wx-submission__panes {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n min-width: 0;\n}\n\n.wx-submission__main,\n.wx-submission__aside {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n min-width: 0;\n}\n\n/* The answers are what the screen is for, so they take the room; everything about the\n submission rather than in it stands beside them. */\n@container (min-width: 900px) {\n .wx-submission__panes {\n flex-direction: row;\n align-items: flex-start;\n }\n\n .wx-submission__main {\n flex: 1 1 auto;\n }\n\n .wx-submission__aside {\n flex: 0 0 320px;\n max-width: 320px;\n }\n}\n\n.wx-submission__value {\n margin: 0;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n.wx-submission__detail {\n overflow-wrap: anywhere;\n}\n\n.wx-submission__event {\n margin: 0;\n}\n\n.wx-submission__by {\n display: flex;\n align-items: baseline;\n gap: var(--wx-space-6);\n flex-wrap: wrap;\n margin: 0;\n}\n\n.wx-submission__files {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-8);\n}\n\n.wx-submission__fields {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n.wx-submission__field {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n}\n</style>\n","import type { AdminModule } from '@webx-ui/module-admin'\nimport FormEditorPage from './FormEditorPage.vue'\nimport InboxPage from './InboxPage.vue'\nimport StatusesPage from './StatusesPage.vue'\nimport SubmissionPage from './SubmissionPage.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 { path, name: 'webx.inbox', component: InboxPage, props: { base: path } },\n {\n path: `${path}/statuses`,\n name: 'webx.inbox.statuses',\n component: StatusesPage,\n props: { base: path },\n },\n {\n path: `${path}/forms/:id(\\\\d+)`,\n name: 'webx.inbox.form',\n component: FormEditorPage,\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: SubmissionPage,\n props: { base: path },\n },\n ],\n }\n}\n"],"names":["model","_useModel","__props","props","locales","useLocales","active","computed","chosen","locale","text","value","next","base","_unref","_createBlock","WxLocales","_createVNode","WxRichText","$event","createInboxApi","admin","data","body","nothing","id","input","ids","formId","query","listQuery","fields","search","key","suffix","inboxMessages","seeded","useInboxMessages","i18n","useAdmin","FIELD_TYPES","STATUS_COLORS","resolve","dismiss","open","useModal","context","api","t","useTranslate","message","useErrorText","saving","ref","errors","name","type","title","placeholder","help","options","isEnabled","isRequired","isFullsize","inTable","watch","field","types","one","hasChoices","choices","extensions","set","addChoice","removeChoice","index","_","at","setChoice","patch","choice","errorOf","save","error","toast","WxDialog","WxSpace","WxButton","_createElementVNode","_hoisted_1","_hoisted_2","WxFormItem","WxSelect","WxInput","_createElementBlock","_Fragment","LocalizedRichText","_cache","_openBlock","_hoisted_3","WxText","_renderList","label","WxAction","_hoisted_4","WxInputNumber","WxDatePicker","WxTagsInput","WxCheckbox","_hoisted_5","edit","createModal","FieldDialog","localizedValue","marks","empty","saved","remove","confirm","actionsFor","reorder","WxCard","WxEmpty","WxSortableList","_withCtx","item","_createTextVNode","_toDisplayString","WxBadge","WxRowMenu","option","fallback","honeypot","seconds","throttle","captcha","captchas","WxSwitch","blade","block","columns","listed","copy","WxTable","row","settings","heading","submit","redirect","admins","recipients","emailField","onMounted","adminOptions","emailOptions","isAdmin","recipient","add","setAdmin","setEmail","email","WxAlert","route","useRoute","router","useRouter","form","loading","reactive","canManage","backTo","load","loaded","WxSkeleton","WxBackButton","WxTabs","WxTab","FormGeneral","FieldList","FormNotifications","FormAntispam","FormEmbed","WxActionBar","slug","values","asked","hasFiles","WxTextarea","WxRadioGroup","WxCheckboxGroup","emit","__emit","page","statuses","selected","moving","canUpdate","SubmissionCreateDialog","view","views","counts","items","status","column","emptyText","statusOptions","formName","state","onState","wanted","statusList","mass","moveTo","statusId","action","byHand","made","exportHref","WxHeading","_keys","rows","WxAvatar","WxTooltip","WxIcon","WxDate","forms","create","FormCreateDialog","module","current","choose","duplicate","rest","WxListScreen","WxListDetail","inline","back","SubmissionList","color","isDefault","isSpam","isClosed","colors","StatusDialog","submission","filter","assigneeOptions","formTitle","replyTo","mailto","subject","lists","onStatus","onAssignee","actions","unread","go","to","statusName","line","event","kilobytes","size","details","meta","WxDescriptions","WxDescriptionsItem","_hoisted_6","_hoisted_7","file","WxFileCard","WxNotes","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_14","WxTimeline","WxTimelineItem","_hoisted_15","inbox","path","InboxPage","StatusesPage","FormEditorPage","SubmissionPage"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/LocalizedRichText.vue","../src/api.ts","../src/messages.ts","../src/i18n.ts","../src/types.ts","../src/FieldDialog.vue","../src/FieldList.vue","../src/options.ts","../src/FormAntispam.vue","../src/FormEmbed.vue","../src/FormGeneral.vue","../src/FormNotifications.vue","../src/FormEditorPage.vue","../src/FormCreateDialog.vue","../src/SubmissionCreateDialog.vue","../src/SubmissionList.vue","../src/InboxPage.vue","../src/StatusDialog.vue","../src/StatusesPage.vue","../src/SubmissionPage.vue","../src/module.ts"],"sourcesContent":["<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 { 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 /** 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/** 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\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: () => admin.http.get<{ data: InboxStatus[] }>(`${base}/statuses`).then(data),\n createStatus: (input) =>\n admin.http.post<{ data: InboxStatus }>(`${base}/statuses`, input).then(data),\n saveStatus: (id, input) =>\n admin.http.put<{ data: InboxStatus }>(`${base}/statuses/${id}`, input).then(data),\n removeStatus: (id) => admin.http.delete(`${base}/statuses/${id}`).then(nothing),\n sortStatuses: (ids) => admin.http.post(`${base}/statuses/sorting`, { ids }).then(nothing),\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'>\n columns: SubmissionsPage['columns']\n counts: SubmissionsPage['counts']\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 })),\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 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 sort: query.sort ?? undefined,\n page: query.page,\n per_page: query.per_page,\n }\n}\n","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 'choose-form': 'Choose a form to see what has come in.',\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 '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 '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-help': 'The keys belong to the site and are set in its settings, not here.',\n 'captcha-off': 'Off',\n 'captcha-recaptcha': 'reCAPTCHA',\n 'captcha-turnstile': 'Turnstile',\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-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': 'Add by hand',\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-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 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 },\n\n fields: {\n field: 'Field',\n 'new-field': 'New field',\n 'edit-field': 'Field',\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","import { useAdmin } from '@webx-ui/module-admin'\nimport { inboxMessages } from './messages'\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","import type { LocalizedValue } from '@webx-ui/core'\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/** 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 '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 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 created_at: string | null\n updated_at: string | null\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 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\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: 'created' | 'status' | 'assignee' | 'note' | 'notified' | string\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/** 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 notified_at: string | null\n notify_error: string | 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 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","<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 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\" icon=\"plus\" @click=\"addChoice\">\n {{ t('fields.add-choice') }}\n </wx-button>\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 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-field'), 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\" icon=\"plus\" @click=\"open(null)\">\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 :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 { 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 } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxCard, WxFormItem, WxInputNumber, WxSelect, WxSwitch } from '@webx-ui/core'\nimport { option } from './options'\nimport type { FormOptions } from './types'\n\n/**\n * The four layers in front of the door (§7), as the three anybody would want to change.\n *\n * The origin check is not here: it is not a dial, it is a fact about where the site is served\n * from, and it lives in the configuration with the rest of the deployment. The captcha keys\n * are not here either — they are the site's, one pair for every form, and a secret repeated\n * in each form's settings is a secret scattered over rows (§5).\n */\nconst options = defineModel<FormOptions>({ required: true })\n\nconst t = useTranslate('webx-inbox')\n\nconst honeypot = option<boolean>(options, 'antispam.honeypot', true)\nconst seconds = option<number>(options, 'antispam.min_seconds', 3)\nconst throttle = option<number>(options, 'antispam.throttle', 5)\nconst captcha = option<string>(options, 'antispam.captcha', 'off')\n\nconst captchas = computed(() => [\n { value: 'off', label: t('panel.captcha-off') },\n { value: 'recaptcha', label: t('panel.captcha-recaptcha') },\n { value: 'turnstile', label: t('panel.captcha-turnstile') },\n])\n</script>\n\n<template>\n <wx-card>\n <wx-form-item :label=\"t('panel.honeypot')\" :help=\"t('panel.honeypot-help')\">\n <wx-switch v-model=\"honeypot\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.min-seconds')\" :help=\"t('panel.min-seconds-help')\">\n <wx-input-number v-model=\"seconds\" :min=\"0\" :max=\"120\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.throttle')\" :help=\"t('panel.throttle-help')\">\n <wx-input-number v-model=\"throttle\" :min=\"0\" :max=\"120\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.captcha')\" :help=\"t('panel.captcha-help')\">\n <wx-select v-model=\"captcha\" :options=\"captchas\" />\n </wx-form-item>\n </wx-card>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { toast, WxAction, WxCard, WxTable, WxText, type TableColumn } from '@webx-ui/core'\nimport { useInboxMessages } from './i18n'\nimport type { InboxField, InboxForm } from './types'\n\n/**\n * How the form gets onto a page.\n *\n * Two answers and both are one line, because the module's whole public half is one tag (§10):\n * a template prints it, and a block type prints the same thing so that an editor never opens\n * a template at all.\n *\n * Under them, the names. A hidden field is filled in by the page it stands on — the address\n * somebody wrote from, the product they were looking at, the campaign that brought them — and\n * the only way to fill one in is to know what it is called (§2.6).\n */\nconst props = defineProps<{ form: InboxForm; slug: string; fields: InboxField[] }>()\n\nuseInboxMessages()\nconst t = useTranslate('webx-inbox')\n\nconst blade = computed(() => `<x-webx-form slug=\"${props.slug}\" />`)\n\nconst block = computed(\n () => `{{-- resources/views/blocks/contact.blade.php --}}\\n<x-webx-form slug=\"${props.slug}\" />`,\n)\n\nconst columns = computed<TableColumn<InboxField>[]>(() => [\n { key: 'key', label: t('fields.name') },\n { key: 'title', label: t('fields.title') },\n { key: 'type', label: t('fields.type'), hideBelow: 520 },\n])\n\n/** Only the ones a page can actually fill in or a visitor can actually answer. */\nconst listed = computed(() => props.fields.filter((field) => field.is_enabled))\n\nasync function copy(text: string): Promise<void> {\n try {\n await navigator.clipboard.writeText(text)\n toast.success(t('panel.copied'))\n } catch {\n // A browser that refuses the clipboard — an insecure origin, a denied permission — still\n // shows the line, and selecting it by hand is what anybody does next anyway.\n }\n}\n</script>\n\n<template>\n <div class=\"wx-inbox-embed\">\n <wx-card :title=\"t('panel.embed-blade')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.embed-blade-help') }}</wx-text>\n\n <div class=\"wx-inbox-embed__snippet\">\n <code>{{ blade }}</code>\n <wx-action icon=\"copy\" :title=\"t('panel.copy')\" @click=\"copy(blade)\" />\n </div>\n </wx-card>\n\n <wx-card :title=\"t('panel.embed-block')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.embed-block-help') }}</wx-text>\n\n <div class=\"wx-inbox-embed__snippet\">\n <code>{{ block }}</code>\n <wx-action icon=\"copy\" :title=\"t('panel.copy')\" @click=\"copy(block)\" />\n </div>\n </wx-card>\n\n <wx-card :title=\"t('panel.embed-names')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.embed-names-help') }}</wx-text>\n\n <wx-table\n :data=\"listed\"\n :columns=\"columns\"\n row-key=\"id\"\n flush\n :empty-text=\"t('fields.no-fields')\"\n >\n <template #cell-key=\"{ row }\">\n <wx-text mono size=\"sm\">fields[{{ row.key }}]</wx-text>\n </template>\n\n <template #cell-title=\"{ row }\">\n {{ Object.values(row.title)[0] ?? row.key }}\n </template>\n\n <template #cell-type=\"{ row }\">\n {{ t(`fields.type-${row.type}`) }}\n </template>\n </wx-table>\n </wx-card>\n </div>\n</template>\n\n<style scoped>\n.wx-inbox-embed {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n}\n\n.wx-inbox-embed__snippet {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n margin-top: var(--wx-space-12);\n padding: var(--wx-space-10) var(--wx-space-12);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-subtle);\n}\n\n.wx-inbox-embed__snippet code {\n flex: 1 1 auto;\n min-width: 0;\n overflow-x: auto;\n white-space: pre;\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-sm);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxCard, WxFormItem, WxInput, WxSwitch, type LocalizedValue } from '@webx-ui/core'\nimport LocalizedRichText from './LocalizedRichText.vue'\nimport { option } from './options'\nimport type { FormOptions } from './types'\n\n/**\n * What the form is, and what it says once it has been sent.\n *\n * The two halves are on two cards because they are read at two different times: the first is\n * set up once, the second is the sentence a visitor sees and is rewritten whenever the\n * marketing does.\n */\ndefineProps<{ errors: Record<string, string[]> }>()\n\nconst settings = defineModel<{ slug: string; title: LocalizedValue; is_enabled: boolean }>(\n 'settings',\n { required: true },\n)\n\nconst options = defineModel<FormOptions>('options', { required: true })\n\nconst t = useTranslate('webx-inbox')\n\nconst heading = option<LocalizedValue>(options, 'thank-you.heading', {})\nconst text = option<LocalizedValue>(options, 'thank-you.text', {})\nconst submit = option<LocalizedValue>(options, 'design.submit-text', {})\nconst redirect = option<string>(options, 'redirect', '')\n</script>\n\n<template>\n <div class=\"wx-inbox-general\">\n <wx-card>\n <wx-form-item :label=\"t('panel.title')\" :error=\"errors.title?.[0]\" required>\n <wx-input v-model=\"settings.title\" localized />\n </wx-form-item>\n\n <wx-form-item\n :label=\"t('panel.slug')\"\n :help=\"t('panel.slug-help')\"\n :error=\"errors.slug?.[0]\"\n required\n >\n <wx-input v-model=\"settings.slug\" placeholder=\"contact\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.is-enabled')\" :help=\"t('panel.is-enabled-help')\">\n <wx-switch v-model=\"settings.is_enabled\" />\n </wx-form-item>\n </wx-card>\n\n <wx-card :title=\"t('panel.after-sending')\">\n <wx-form-item :label=\"t('panel.submit-text')\">\n <wx-input v-model=\"submit\" localized />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.thank-you-heading')\">\n <wx-input v-model=\"heading\" localized />\n </wx-form-item>\n\n <!-- Printed raw on the site, which is why it is written where formatting is possible. -->\n <wx-form-item :label=\"t('panel.thank-you-text')\">\n <localized-rich-text v-model=\"text\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.redirect')\" :help=\"t('panel.redirect-help')\">\n <wx-input v-model=\"redirect\" placeholder=\"/thank-you\" />\n </wx-form-item>\n </wx-card>\n </div>\n</template>\n\n<style scoped>\n.wx-inbox-general {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref } from 'vue'\nimport { useAdmin, useTranslate } from '@webx-ui/module-admin'\nimport {\n confirm,\n WxAction,\n WxAlert,\n WxButton,\n WxCard,\n WxFormItem,\n WxInput,\n WxSelect,\n WxSpace,\n WxText,\n} from '@webx-ui/core'\nimport { createInboxApi } from './api'\nimport { option } from './options'\nimport type { FormOptions, InboxField, InboxRecipient, Recipient } from './types'\n\n/**\n * Who hears that something arrived (§9).\n *\n * Two kinds of recipient and they are not interchangeable. An administrator is written to at\n * the address on their account and in the language they keep the panel in, so changing either\n * changes it everywhere; a typed address is written to in the language the submission came in.\n * The list offered is not every administrator but the ones who may open a submission — a\n * notification is a link, and sending one to somebody who gets a 403 looks like the panel is\n * broken rather than like the form is.\n */\nconst props = defineProps<{ fields: InboxField[]; errors: Record<string, string[]> }>()\n\nconst options = defineModel<FormOptions>({ required: true })\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\nconst t = useTranslate('webx-inbox')\n\nconst admins = ref<InboxRecipient[]>([])\n\nconst recipients = option<Recipient[]>(options, 'recipients', [])\nconst emailField = option<string>(options, 'email_field', '')\n\nonMounted(async () => {\n try {\n admins.value = await api.recipients()\n } catch {\n // Only the shortcut is gone: an address can still be typed, and that is the half of this\n // that has to work.\n }\n})\n\nconst adminOptions = computed(() =>\n admins.value.map((admin) => ({ value: admin.id, label: `${admin.name} · ${admin.email}` })),\n)\n\n/** The fields that could hold the sender's address, plus the option of naming none. */\nconst emailOptions = computed(() => [\n { value: '', label: t('panel.no-email-field') },\n ...props.fields\n .filter((field) => field.type === 'email')\n .map((field) => ({ value: field.key, label: field.key })),\n])\n\nfunction isAdmin(recipient: Recipient): recipient is { admin_id: number } {\n return 'admin_id' in recipient\n}\n\nfunction add(recipient: Recipient): void {\n recipients.value = [...recipients.value, recipient]\n}\n\n/**\n * A recipient goes behind a question, unless there is nothing there to lose.\n *\n * The row that was just added and never filled in is a blank line, and asking about a blank\n * line teaches the reader to click through the question without reading it — which is the\n * one thing a confirmation must not do.\n */\nasync function remove(index: number): Promise<void> {\n const recipient = recipients.value[index]\n const written =\n recipient !== undefined && (isAdmin(recipient) || (recipient.email ?? '').trim() !== '')\n\n if (written) {\n const agreed = await confirm({\n title: t('panel.remove-recipient-title'),\n message: t('panel.remove-recipient-text'),\n confirmText: t('panel.remove'),\n cancelText: t('panel.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n }\n\n recipients.value = recipients.value.filter((_, at) => at !== index)\n}\n\nfunction setAdmin(index: number, id: number): void {\n recipients.value = recipients.value.map((one, at) => (at === index ? { admin_id: id } : one))\n}\n\nfunction setEmail(index: number, email: string): void {\n recipients.value = recipients.value.map((one, at) => (at === index ? { email } : one))\n}\n</script>\n\n<template>\n <wx-card :title=\"t('panel.recipients')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.recipients-help') }}</wx-text>\n\n <wx-alert\n v-if=\"errors['options.recipients']\"\n type=\"danger\"\n variant=\"soft\"\n :description=\"errors['options.recipients']?.[0]\"\n />\n\n <div class=\"wx-inbox-recipients\">\n <wx-text v-if=\"recipients.length === 0\" size=\"sm\" tone=\"placeholder\">\n {{ t('panel.no-recipients') }}\n </wx-text>\n\n <div v-for=\"(recipient, index) in recipients\" :key=\"index\" class=\"wx-inbox-recipients__row\">\n <wx-select\n v-if=\"isAdmin(recipient)\"\n :model-value=\"recipient.admin_id\"\n :options=\"adminOptions\"\n @update:model-value=\"(id) => setAdmin(index, Number(id))\"\n />\n <wx-input\n v-else\n :model-value=\"recipient.email\"\n type=\"email\"\n placeholder=\"sales@example.com\"\n @update:model-value=\"(email) => setEmail(index, String(email))\"\n />\n\n <!-- Red, like every other way of taking something away in the panel: the colour is\n what tells the two buttons of a row apart before either is read. -->\n <wx-action icon=\"trash\" tone=\"danger\" :title=\"t('panel.remove')\" @click=\"remove(index)\" />\n </div>\n </div>\n\n <wx-space size=\"sm\">\n <wx-button\n variant=\"outline\"\n icon=\"user\"\n :disabled=\"adminOptions.length === 0\"\n @click=\"add({ admin_id: Number(adminOptions[0]?.value) })\"\n >\n {{ t('panel.add-admin') }}\n </wx-button>\n <wx-button variant=\"outline\" icon=\"mail\" @click=\"add({ email: '' })\">\n {{ t('panel.add-email') }}\n </wx-button>\n </wx-space>\n\n <wx-form-item :label=\"t('panel.email-field')\" :help=\"t('panel.email-field-help')\">\n <wx-select v-model=\"emailField\" :options=\"emailOptions\" />\n </wx-form-item>\n </wx-card>\n</template>\n\n<style scoped>\n/*\n * As wide as a field, because that is what each row is: an address is typed into it and read\n * back off it. The rows are not form items — one of them is a select, the next an input, and\n * both carry a bin — so the cap that a form item applies has to be said here.\n */\n.wx-inbox-recipients {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n margin-block: var(--wx-space-12);\n max-width: var(--wx-field-max-width, 640px);\n}\n\n.wx-inbox-recipients__row {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n}\n\n.wx-inbox-recipients__row > :first-child {\n flex: 1 1 auto;\n min-width: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, reactive, ref, watch } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport { useAdmin, useErrorText, useTranslate, WxBackButton } from '@webx-ui/module-admin'\nimport {\n localizedValue,\n toast,\n useLocales,\n WxActionBar,\n WxBadge,\n WxButton,\n WxCard,\n WxSkeleton,\n WxTab,\n WxTabs,\n WxText,\n type LocalizedValue,\n} from '@webx-ui/core'\nimport FieldList from './FieldList.vue'\nimport FormAntispam from './FormAntispam.vue'\nimport FormEmbed from './FormEmbed.vue'\nimport FormGeneral from './FormGeneral.vue'\nimport FormNotifications from './FormNotifications.vue'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport type { FormOptions, InboxField, InboxForm } from './types'\n\n/**\n * One form: what it is called, what it asks, who hears about it, and how it is put on a page.\n *\n * Five tabs and one save. The fields are the exception — a question is written in its own\n * dialog and saved on its own, because it is a row with an identity (§2.1) and because a\n * dragged order that waited for a save button would be an order nobody trusts.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/inbox' })\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\nconst route = useRoute()\nconst router = useRouter()\nconst locales = useLocales()\nuseInboxMessages()\n\nconst t = useTranslate('webx-inbox')\n/* Not the server's `message`: the panel says how a request failed in its own words. */\nconst message = useErrorText()\n\nconst form = ref<InboxForm | null>(null)\nconst fields = ref<InboxField[]>([])\nconst loading = ref(true)\nconst saving = ref(false)\nconst errors = ref<Record<string, string[]>>({})\n\nconst settings = reactive<{ slug: string; title: LocalizedValue; is_enabled: boolean }>({\n slug: '',\n title: {},\n is_enabled: true,\n})\n\nconst options = ref<FormOptions>({})\n\nconst canManage = computed(() => context.can('inbox.manage'))\n\nconst id = computed(() => Number(route.params.id))\n\nconst name = computed(() =>\n form.value === null ? '' : localizedValue(settings.title, locales.active.value, settings.slug),\n)\n\n/** Where a submission would come back to: the section, with this form already chosen. */\nconst backTo = computed(() => `${props.base}?form=${id.value}`)\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n const loaded = await api.form(id.value)\n\n form.value = loaded\n fields.value = loaded.fields ?? []\n settings.slug = loaded.slug\n settings.title = { ...loaded.title }\n settings.is_enabled = loaded.is_enabled\n options.value = { ...loaded.options }\n } catch (error) {\n toast.danger(message(error))\n void router.replace(props.base)\n } finally {\n loading.value = false\n }\n}\n\nwatch(id, () => void load(), { immediate: true })\n\nasync function save(): Promise<void> {\n saving.value = true\n errors.value = {}\n\n try {\n const saved = await api.saveForm(id.value, {\n slug: settings.slug.trim(),\n title: settings.title,\n is_enabled: settings.is_enabled,\n options: options.value,\n })\n\n form.value = saved\n toast.success(t('panel.saved'))\n } catch (error) {\n const body = (error as { body?: { errors?: Record<string, string[]> } }).body\n\n if (body?.errors) {\n errors.value = body.errors\n toast.danger(t('panel.failed'))\n } else {\n toast.danger(message(error))\n }\n } finally {\n saving.value = false\n }\n}\n</script>\n\n<template>\n <!--\n Not a screen that fills its column, whatever the first draft said. `data-wx-fill` makes the\n screen exactly as tall as the window, and nothing inside these tabs scrolls on its own — so\n a form longer than the window grew straight through the box, and the save bar, which is the\n next thing in the column, was drawn across the middle of it with fields still going on\n underneath. What this screen wants is the ordinary thing: the page scrolls, the bar sticks\n to the bottom of it, and `WxMain` gives the screen a floor to push that bar down to.\n -->\n <div class=\"wx-inbox-editor\">\n <!-- On a card, like everything else on this screen: a bare skeleton flush against the\n page is a shape the form that follows it never takes, so the screen jumps twice —\n once when the card appears around it, once when the fields land inside. -->\n <wx-card v-if=\"loading\">\n <wx-skeleton title :rows=\"8\" />\n </wx-card>\n\n <template v-else-if=\"form\">\n <div class=\"wx-inbox-editor__head\">\n <wx-back-button :to=\"backTo\" :label=\"t('panel.forms')\" />\n\n <div class=\"wx-inbox-editor__id\">\n <h1 class=\"wx-inbox-editor__title\">{{ name }}</h1>\n <wx-text size=\"sm\" tone=\"muted\" mono>{{ form.slug }}</wx-text>\n </div>\n\n <wx-badge v-if=\"!settings.is_enabled\" type=\"default\">{{ t('panel.off') }}</wx-badge>\n </div>\n\n <!--\n Every tab is mounted at once and the hidden ones keep their state: somebody who wrote\n a thank-you, went to look at the fields and came back should find it still written.\n -->\n <wx-tabs class=\"wx-inbox-editor__tabs\" keep-alive>\n <wx-tab value=\"general\" :label=\"t('panel.tab-general')\">\n <form-general v-model:settings=\"settings\" v-model:options=\"options\" :errors=\"errors\" />\n </wx-tab>\n\n <wx-tab value=\"fields\" :label=\"t('panel.tab-fields')\">\n <field-list v-model=\"fields\" :form=\"form\" :can-manage=\"canManage\" />\n </wx-tab>\n\n <wx-tab value=\"notifications\" :label=\"t('panel.tab-notifications')\">\n <form-notifications v-model=\"options\" :fields=\"fields\" :errors=\"errors\" />\n </wx-tab>\n\n <wx-tab value=\"antispam\" :label=\"t('panel.tab-antispam')\">\n <form-antispam v-model=\"options\" />\n </wx-tab>\n\n <wx-tab value=\"embed\" :label=\"t('panel.tab-embed')\">\n <form-embed :form=\"form\" :slug=\"settings.slug\" :fields=\"fields\" />\n </wx-tab>\n </wx-tabs>\n\n <wx-action-bar v-if=\"canManage\">\n <wx-button type=\"primary\" :loading=\"saving\" @click=\"save\">{{ t('panel.save') }}</wx-button>\n </wx-action-bar>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-inbox-editor {\n display: flex;\n flex-direction: column;\n /* The panel's own step, which is smaller on a phone than on a desktop. */\n gap: var(--wx-gap, var(--wx-space-16));\n}\n\n/*\n * The way out lines up with the name, not with the pair of lines under it.\n *\n * The block beside it is two lines — the name and the address it posts to — so centring the\n * row put the arrow halfway down, level with the gap between them: it read as belonging to\n * the slug rather than to the screen. Aligned to the top and nudged by the difference between\n * the line it stands next to and its own height, it sits on the name.\n */\n.wx-inbox-editor__head {\n display: flex;\n align-items: flex-start;\n gap: var(--wx-space-12);\n flex-wrap: wrap;\n}\n\n/*\n * The button (30px) is taller than the line it stands beside (25px), so aligning their boxes\n * leaves its centre low; half the difference back up puts the two centres together. `:deep()`\n * because the class is ours but the element it rides is `WxAction`'s, and a scoped rule would\n * be looking for our attribute on somebody else's markup (CLAUDE.md §4).\n */\n.wx-inbox-editor__head > :deep(.wx-back-button) {\n margin-block-start: -2px;\n}\n\n.wx-inbox-editor__id {\n min-width: 0;\n}\n\n.wx-inbox-editor__title {\n margin: 0;\n font-size: var(--wx-font-size-xl);\n font-weight: var(--wx-font-weight-semibold);\n line-height: var(--wx-font-line-height-tight);\n}\n\n/* The tabs take what is left of the column, so the save bar under them is at its bottom\n rather than under the last field. Nothing inside them scrolls on its own — the page does. */\n.wx-inbox-editor__tabs {\n flex: 1 1 auto;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport {\n toast,\n useModal,\n WxButton,\n WxDialog,\n WxFormItem,\n WxInput,\n WxSpace,\n type LocalizedValue,\n} from '@webx-ui/core'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport type { InboxForm } from './types'\n\n/**\n * A form, started.\n *\n * Two fields, because a form has nothing else until it has questions: what it is called and\n * where it answers. Everything else — who is written to, what happens after sending, the\n * antispam — belongs to the editor, and asking for it before the form exists would be a\n * dialog longer than the screen it leads to.\n *\n * The address is typed rather than made out of the title. A page's address is a sentence\n * transliterated; a form's is a short word somebody chooses once and then writes into a\n * template by hand, and guessing `svyazhites-s-nami` for them helps nobody.\n */\nconst { resolve, dismiss, open } = useModal<InboxForm>()\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 title = ref<LocalizedValue>({})\nconst slug = ref('')\nconst saving = ref(false)\nconst errors = ref<Record<string, string[]>>({})\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 try {\n resolve(\n await api.createForm({\n title: title.value,\n slug: slug.value.trim(),\n is_enabled: true,\n options: {},\n }),\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 v-model:open=\"open\" :title=\"t('panel.new-form-title')\" :width=\"520\">\n <div class=\"wx-inbox-create\">\n <wx-form-item :label=\"t('panel.title')\" :error=\"errorOf('title')\" required>\n <wx-input v-model=\"title\" localized autofocus />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.slug')\" :help=\"t('panel.slug-help')\" :error=\"errorOf('slug')\">\n <wx-input v-model=\"slug\" placeholder=\"contact\" />\n </wx-form-item>\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\" @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-create {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n</style>\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, watch } from 'vue'\nimport { useRoute, useRouter, type LocationQueryRaw } from 'vue-router'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxDate,\n WxRowMenu,\n type RowAction,\n} from '@webx-ui/module-admin'\nimport {\n confirm,\n createModal,\n localizedValue,\n toast,\n useLocales,\n WxAction,\n WxAvatar,\n WxBadge,\n WxButton,\n WxHeading,\n WxIcon,\n WxSelect,\n WxTable,\n WxTabs,\n WxText,\n WxTooltip,\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 } 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 /** Whether the pane is beside the list of forms or is the whole screen. */\n inline?: boolean\n }>(),\n { base: '/inbox', inline: true },\n)\n\nconst emit = defineEmits<{\n /** The pane wants out — only ever on a phone, where it is the screen. */\n back: []\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\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 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'))\nconst canManage = computed(() => context.can('inbox.manage'))\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 sort: typeof route.query.sort === 'string' ? route.query.sort : null,\n page: Number(route.query.page ?? 1) || 1,\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\nconst columns = computed<TableColumn<SubmissionRow>[]>(() => {\n const answers = page.value?.columns ?? []\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: 150,\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: 56, 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' && query.value.search === '' && query.value.assignee === 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\nfunction name(status: InboxStatus): string {\n return localizedValue(status.title, locales.active.value, status.key)\n}\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 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. */\nwatch(\n () => [props.form.id, view.value, query.value.assignee] as const,\n () => {\n selected.value = []\n void load()\n },\n)\n\nvoid load()\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 sort: query.value.sort,\n }),\n)\n\nfunction settings(): void {\n void router.push(`${props.base}/forms/${props.form.id}`)\n}\n</script>\n\n<template>\n <div class=\"wx-submissions\" :class=\"{ 'is-pane': inline }\">\n <div class=\"wx-submissions__head\">\n <!-- On a phone the pane is a screen of its own and the drawer carries no close of its\n own, so the way back has to be here. Beside the list there is nothing to go back to. -->\n <wx-action\n v-if=\"!inline\"\n class=\"wx-submissions__back\"\n icon=\"arrow-left\"\n :title=\"t('panel.forms')\"\n @click=\"emit('back')\"\n />\n\n <div class=\"wx-submissions__who\">\n <wx-heading :level=\"3\" truncate>{{ formName() }}</wx-heading>\n <wx-text size=\"sm\" tone=\"muted\" mono truncate>{{ form.slug }}</wx-text>\n </div>\n\n <wx-button v-if=\"canUpdate\" variant=\"outline\" icon=\"plus\" size=\"sm\" @click=\"byHand\">{{\n t('panel.new-submission')\n }}</wx-button>\n <wx-button variant=\"outline\" icon=\"download\" size=\"sm\" :href=\"exportHref\">\n {{ t('panel.export') }}\n </wx-button>\n <wx-button v-if=\"canManage\" variant=\"outline\" icon=\"settings\" size=\"sm\" @click=\"settings\">\n {{ t('panel.settings') }}\n </wx-button>\n </div>\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 :selectable=\"canUpdate\"\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=\"640\"\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 #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\" />\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 * The panel's own step, which is 8 on a phone and 16 on a desktop — not a number of this\n * screen's own. Written as 16 here, the pane kept desktop air inside a 375px drawer: the head,\n * the tabs and the rows each took a line of nothing between them, and four rows fitted where\n * six do now.\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 height: 100%;\n min-height: 0;\n}\n\n/*\n * The way back lines up with the name, not with the pair of lines under it: what stands beside\n * it is the form's name and the address it posts to, and a centred row put the arrow level with\n * the gap between the two.\n */\n.wx-submissions__head {\n display: flex;\n align-items: flex-start;\n gap: var(--wx-space-8);\n flex-wrap: wrap;\n}\n\n/* The button is taller than the line it stands beside, so aligning their boxes leaves its\n centre low; half the difference back up puts the two centres together. `:deep()` because\n the class is ours and the element it rides is `WxAction`'s (CLAUDE.md §4). */\n.wx-submissions__head > :deep(.wx-submissions__back) {\n margin-block-start: -2px;\n}\n\n/* The name takes the middle, so the way back stays at the start of the line and the buttons\n stay at its end. */\n.wx-submissions__who {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.wx-submissions__views {\n flex: 1 1 auto;\n min-height: 0;\n}\n\n/*\n * Beside the forms, the cards stand a step further in than the pane's own padding.\n *\n * There the pane is a column of a card — a rule down its left side, the card's frame on its\n * right — and a list of boxes that begins where the column begins reads as glued to both. As a\n * sheet the same list has the edge of the screen for a boundary and wants nothing extra, which\n * is why this belongs to the pane and not to the table: only the pane knows which one it is.\n * Rows want neither, and do not get it — they are the table's own width by design.\n */\n.wx-submissions.is-pane :deep(.wx-table--cards) {\n padding-inline: var(--wx-table-padding-x);\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, ref, watch } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxListScreen,\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 WxCard,\n WxEmpty,\n WxIndicator,\n WxListDetail,\n WxSkeleton,\n WxSortableList,\n WxText,\n} from '@webx-ui/core'\nimport FormCreateDialog from './FormCreateDialog.vue'\nimport SubmissionList from './SubmissionList.vue'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport type { InboxForm } from './types'\n\n/**\n * The section: the forms of the site on the left, what came in through one of them on the\n * right (§11, §2.12).\n *\n * One screen rather than two, and that is the decision this is built around. The columns of\n * the list are the fields of the chosen form, so a list of everything would have no columns\n * to speak of; and the two questions somebody opens this section to ask — \"what is new\" and\n * \"what does this form ask\" — are one click apart instead of one screen apart.\n *\n * The right-hand side is the submissions, and it arrives with them. What is here is the\n * column: the forms, in the order somebody dragged them, with what is waiting in each.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/inbox' })\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\nconst route = useRoute()\nconst router = useRouter()\nconst locales = useLocales()\nuseInboxMessages()\n\nconst t = useTranslate('webx-inbox')\n/* Not the server's `message`: the panel says how a request failed in its own words. */\nconst message = useErrorText()\n\nconst forms = ref<InboxForm[]>([])\nconst loading = ref(true)\nconst open = ref(false)\n\nconst canManage = computed(() => context.can('inbox.manage'))\n\nconst create = createModal<InboxForm, Record<string, never>>(FormCreateDialog)\n\nconst title = computed(\n () =>\n context.state.manifest?.modules.find((module) => module.id === 'inbox')?.title ??\n t('module.title'),\n)\n\n/**\n * Which form is open, kept in the address.\n *\n * So that coming back from a submission lands on the form it belonged to (§11) — and so that\n * a link to \"the callback form\" is a link somebody can send.\n */\nconst current = computed<number | null>(() => {\n const asked = route.query.form\n\n return typeof asked === 'string' && asked !== '' ? Number(asked) : null\n})\n\nconst chosen = computed(() => forms.value.find((form) => form.id === current.value) ?? null)\n\nfunction name(form: InboxForm): string {\n return localizedValue(form.title, locales.active.value, form.slug)\n}\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n forms.value = await api.forms()\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n}\n\nvoid load()\n\n/* A form chosen while the list was still loading is still chosen once it arrives. */\nwatch(chosen, (form) => {\n if (form !== null) open.value = true\n})\n\nfunction choose(form: InboxForm): void {\n void router.replace({ query: { ...route.query, form: String(form.id) } })\n open.value = true\n}\n\nfunction edit(form: InboxForm): void {\n void router.push(`${props.base}/forms/${form.id}`)\n}\n\nfunction actionsFor(form: InboxForm): RowAction[] {\n if (!canManage.value) return []\n\n return [\n { key: 'settings', icon: 'settings', label: t('panel.settings'), run: () => edit(form) },\n { key: 'duplicate', icon: 'copy', label: t('panel.duplicate'), run: () => duplicate(form) },\n // A form that has taken submissions is switched off, never deleted (§2.4). The line is\n // left out rather than greyed: a menu is a list of what is possible.\n ...(form.submissions_count === 0\n ? [\n {\n key: 'delete',\n icon: 'trash' as const,\n label: t('panel.delete'),\n danger: true,\n run: () => remove(form),\n },\n ]\n : []),\n ]\n}\n\nasync function add(): Promise<void> {\n const made = await create({})\n\n if (made) {\n await load()\n edit(made)\n }\n}\n\nasync function duplicate(form: InboxForm): Promise<void> {\n try {\n const copy = await api.duplicateForm(form.id)\n toast.success(t('panel.duplicated'))\n await load()\n edit(copy)\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nasync function remove(form: InboxForm): Promise<void> {\n const agreed = await confirm({\n title: t('panel.delete-form-title', { form: name(form) }),\n message: t('panel.delete-form-text'),\n confirmText: t('panel.delete'),\n cancelText: t('panel.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n try {\n await api.removeForm(form.id)\n toast.success(t('panel.deleted'))\n\n if (current.value === form.id) {\n const rest = { ...route.query }\n delete rest.form\n void router.replace({ query: rest })\n open.value = false\n }\n\n await load()\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\n/**\n * The whole order, every time.\n *\n * The list is already in its new order on screen — `WxSortableList` reorders the model before\n * it says anything — so this only has to agree with what is there, and a failure has to put\n * the list back rather than leave the screen disagreeing with the database.\n */\nasync function reorder(): Promise<void> {\n try {\n await api.sortForms(forms.value.map((form) => form.id))\n } catch (error) {\n toast.danger(message(error, t('panel.reorder-failed')))\n await load()\n }\n}\n</script>\n\n<template>\n <wx-list-screen :title=\"title\" :card=\"false\" fill>\n <template #actions>\n <wx-button\n v-if=\"canManage\"\n variant=\"outline\"\n icon=\"tag\"\n @click=\"router.push(`${props.base}/statuses`)\"\n >\n {{ t('panel.statuses') }}\n </wx-button>\n <wx-button v-if=\"canManage\" type=\"primary\" icon=\"plus\" @click=\"add\">\n {{ t('panel.new-form') }}\n </wx-button>\n </template>\n\n <wx-card class=\"wx-inbox\" padding=\"none\">\n <wx-list-detail\n v-model:open=\"open\"\n class=\"wx-inbox__panes\"\n :list-width=\"270\"\n :detail-min=\"420\"\n :detail-label=\"chosen ? name(chosen) : t('panel.forms')\"\n >\n <template #list>\n <wx-skeleton v-if=\"loading\" class=\"wx-inbox__loading\" :rows=\"5\" />\n\n <wx-empty\n v-else-if=\"forms.length === 0\"\n :title=\"t('panel.no-forms')\"\n :description=\"t('panel.no-forms-help')\"\n />\n\n <!--\n A grip and not the whole row: the row is what opens a form, and a list whose rows\n both open and drag is a list where one of the two happens by accident.\n -->\n <wx-sortable-list\n v-else\n v-model=\"forms\"\n class=\"wx-inbox__forms\"\n plain\n size=\"sm\"\n item-key=\"id\"\n :item-label=\"name\"\n :disabled=\"!canManage\"\n :title=\"t('panel.forms')\"\n @move=\"reorder\"\n >\n <template #default=\"{ item }\">\n <button\n type=\"button\"\n class=\"wx-inbox-form\"\n :class=\"{ 'is-current': item.id === current }\"\n @click=\"choose(item)\"\n >\n <span class=\"wx-inbox-form__name\">\n <wx-text truncate weight=\"medium\">{{ name(item) }}</wx-text>\n <wx-badge v-if=\"!item.is_enabled\" type=\"default\">{{ t('panel.off') }}</wx-badge>\n\n <!--\n On the name's line, not under it. The list stacks what the slot hands it, so\n a count standing beside the form was a third line under the address — the\n row grew by a line to say a single digit. Unread first and in colour; the\n total behind it, quietly, because it is context rather than work.\n -->\n <wx-indicator\n v-if=\"item.unread_count\"\n class=\"wx-inbox-form__count\"\n type=\"primary\"\n :value=\"item.unread_count\"\n :label=\"t('panel.unread')\"\n />\n <wx-indicator\n v-else-if=\"item.submissions_count\"\n class=\"wx-inbox-form__count\"\n type=\"neutral\"\n :value=\"item.submissions_count\"\n :label=\"t('panel.submissions')\"\n />\n </span>\n <wx-text size=\"sm\" tone=\"muted\" truncate>{{ item.slug }}</wx-text>\n </button>\n </template>\n\n <template #actions=\"{ item }\">\n <wx-row-menu :actions=\"actionsFor(item)\" :label=\"name(item)\" />\n </template>\n </wx-sortable-list>\n </template>\n\n <template #empty>\n <wx-empty :description=\"t('panel.choose-form')\" />\n </template>\n\n <!--\n The submissions of the chosen form. The pane is the list's, head and all: what is\n above the rows — which form this is, the way back on a phone, the way into what it\n asks — belongs beside the tabs and not above the drawer.\n -->\n <template #detail=\"{ inline, back }\">\n <submission-list\n v-if=\"chosen\"\n :key=\"chosen.id\"\n :form=\"chosen\"\n :base=\"props.base\"\n :inline=\"inline\"\n @back=\"back\"\n @changed=\"load\"\n />\n </template>\n </wx-list-detail>\n </wx-card>\n </wx-list-screen>\n</template>\n\n<style>\n.wx-inbox {\n height: 100%;\n min-height: 0;\n}\n\n/*\n * The card is the screen: what scrolls is inside it, not the page behind it.\n *\n * And the card's corners are the screen's corners. The two panes inside are square and paint\n * their own background right up to the edge, so without the clip they covered the rounding —\n * four white notches poking out of the card, most visible where the column divider and the\n * bottom rule of the list meet it.\n */\n.wx-inbox > .wx-card__body {\n height: 100%;\n min-height: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n border-radius: inherit;\n}\n\n.wx-inbox__panes {\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.wx-inbox__loading {\n padding: var(--wx-space-16);\n}\n\n.wx-inbox__forms {\n padding: var(--wx-space-8) var(--wx-space-12);\n}\n\n/*\n * A plain list draws its rows edge to edge, which is right until one of them is tinted: the\n * highlight then starts exactly at the first letter and ends exactly at the `···`, so the\n * chosen form reads as a stain rather than as a row, and it sits flush against the rule that\n * divides the two columns. The padding is inside the tint, not around it.\n */\n.wx-inbox__forms.is-plain .wx-sortable-list__row {\n padding-inline: var(--wx-space-8);\n}\n\n/*\n * Air under the rule that carries the column's name.\n *\n * The first row started exactly where the line ended, and the first row here is usually the\n * tinted one — so the chosen form read as hanging off the heading rather than as the first of\n * a list. Visible in the dark theme first, where the tint is a shape of its own.\n */\n.wx-inbox__forms.is-plain .wx-sortable-list__head {\n margin-block-end: var(--wx-space-6);\n}\n\n.wx-inbox-form {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-2);\n align-items: flex-start;\n /* The row is the target, so it takes the row: a name of four letters should not leave\n three quarters of the line dead. */\n flex: 1 1 auto;\n min-width: 0;\n padding: 0;\n border: 0;\n background: none;\n font: inherit;\n color: inherit;\n text-align: start;\n cursor: pointer;\n}\n\n.wx-inbox-form__name {\n display: flex;\n align-items: center;\n gap: var(--wx-space-6);\n min-width: 0;\n max-width: 100%;\n}\n\n/*\n * The chosen form, marked on the whole row rather than on the name inside it: the row is what\n * was clicked, and a colour on the words alone leaves the grip and the menu looking like they\n * belong to something else. `:has()` because the row is the list's element and the class is\n * ours — the slot cannot reach the element it is drawn into.\n */\n.wx-inbox__forms .wx-sortable-list__row:has(.wx-inbox-form.is-current) {\n background: var(--wx-bg-subtle);\n border-radius: var(--wx-radius-sm);\n}\n\n.wx-inbox-form.is-current {\n color: var(--wx-color-primary);\n}\n\n.wx-inbox-form__count {\n flex: 0 0 auto;\n}\n</style>\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 WxButton,\n WxCheckbox,\n WxDialog,\n WxFormItem,\n WxInput,\n WxSelect,\n WxSpace,\n type LocalizedValue,\n} from '@webx-ui/core'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport { STATUS_COLORS, type InboxStatus, type StatusColor } from './types'\n\n/**\n * One state, written.\n *\n * The colour is a tone rather than a swatch: the panel has a light theme and a dark one, and\n * a colour picked in one of them is unreadable in the other.\n *\n * Nothing here refuses a second default — the server clears the flag on whoever had it, which\n * is what somebody moving the default from one status to another means, and refusing the save\n * would be the other reading of the same click.\n */\nconst props = defineProps<{ status: InboxStatus | null }>()\n\nconst { resolve, dismiss, open } = useModal<InboxStatus>()\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 key = ref('')\nconst title = ref<LocalizedValue>({})\nconst color = ref<StatusColor>('default')\nconst isDefault = ref(false)\nconst isSpam = ref(false)\nconst isClosed = ref(false)\nconst saving = ref(false)\nconst errors = ref<Record<string, string[]>>({})\n\nwatch(\n () => props.status,\n (status) => {\n key.value = status?.key ?? ''\n title.value = { ...(status?.title ?? {}) }\n color.value = status?.color ?? 'default'\n isDefault.value = status?.is_default ?? false\n isSpam.value = status?.is_spam ?? false\n isClosed.value = status?.is_closed ?? false\n errors.value = {}\n },\n { immediate: true },\n)\n\nconst colors = computed(() =>\n STATUS_COLORS.map((one) => ({ value: one, label: t(`panel.color-${one}`) })),\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 key: key.value.trim(),\n title: title.value,\n color: color.value,\n is_default: isDefault.value,\n is_spam: isSpam.value,\n is_closed: isClosed.value,\n }\n\n try {\n resolve(\n props.status === null\n ? await api.createStatus(input)\n : await api.saveStatus(props.status.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=\"status ? t('panel.settings') : t('panel.new-status')\"\n :width=\"520\"\n >\n <div class=\"wx-inbox-status-form\">\n <wx-form-item :label=\"t('panel.title')\" :error=\"errorOf('title')\" required>\n <wx-input v-model=\"title\" localized />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.status-key')\" :error=\"errorOf('key')\" required>\n <wx-input v-model=\"key\" placeholder=\"in-progress\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.status-color')\" :error=\"errorOf('color')\">\n <wx-select v-model=\"color\" :options=\"colors\" />\n </wx-form-item>\n\n <div class=\"wx-inbox-status-form__checks\">\n <wx-checkbox v-model=\"isDefault\" :label=\"t('panel.status-default')\" />\n <wx-checkbox v-model=\"isSpam\" :label=\"t('panel.status-spam')\" />\n <wx-checkbox v-model=\"isClosed\" :disabled=\"isSpam\" :label=\"t('panel.status-closed')\" />\n </div>\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\" @click=\"save\">{{ t('panel.save') }}</wx-button>\n </wx-space>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-inbox-status-form {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n.wx-inbox-status-form__checks {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-16);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxBackButton,\n WxListScreen,\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 WxEmpty,\n WxSortableList,\n WxText,\n} from '@webx-ui/core'\nimport StatusDialog from './StatusDialog.vue'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport type { InboxStatus } from './types'\n\n/**\n * The states a submission can be in (§2.11).\n *\n * Rows rather than an enum, because every panel ends up wanting its own words — and the flags\n * are what the section reads, not the keys, so renaming \"New\" to whatever this client calls\n * it keeps it the status a new submission gets.\n *\n * Their order is the order of the tabs over the list of submissions, which is why it is\n * dragged rather than typed.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/inbox' })\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 statuses = ref<InboxStatus[]>([])\nconst loading = ref(true)\n\nconst canManage = context.can('inbox.manage')\n\nconst edit = createModal<InboxStatus, { status: InboxStatus | null }>(StatusDialog)\n\nfunction name(status: InboxStatus): string {\n return localizedValue(status.title, locales.active.value, status.key)\n}\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n statuses.value = await api.statuses()\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n}\n\nvoid load()\n\nasync function open(status: InboxStatus | null): Promise<void> {\n if (await edit({ status })) await load()\n}\n\nasync function remove(status: InboxStatus): Promise<void> {\n const agreed = await confirm({\n title: t('panel.delete-status-title', { status: name(status) }),\n message: t('panel.delete-status-text'),\n confirmText: t('panel.delete'),\n cancelText: t('panel.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n try {\n await api.removeStatus(status.id)\n toast.success(t('panel.deleted'))\n await load()\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nfunction actionsFor(status: InboxStatus): RowAction[] {\n if (!canManage) return []\n\n return [\n { key: 'edit', icon: 'edit', label: t('panel.settings'), run: () => void open(status) },\n // A status with submissions in them cannot go: they would have nothing to be in. The\n // line is left out rather than greyed, the way every list of the panel does it.\n ...(status.submissions_count === 0\n ? [\n {\n key: 'delete',\n icon: 'trash' as const,\n label: t('panel.delete'),\n danger: true,\n run: () => void remove(status),\n },\n ]\n : []),\n ]\n}\n\nasync function reorder(): Promise<void> {\n try {\n await api.sortStatuses(statuses.value.map((status) => status.id))\n } catch (error) {\n toast.danger(message(error, t('panel.reorder-failed')))\n await load()\n }\n}\n</script>\n\n<template>\n <div class=\"wx-inbox-statuses\">\n <!-- Above the heading, where the way out of a screen is on every other one: beside the\n primary action it reads as a second thing to do rather than as a way back. -->\n <wx-back-button :to=\"props.base\" :label=\"t('panel.forms')\" />\n\n <wx-list-screen :title=\"t('panel.statuses')\">\n <template #actions>\n <wx-button v-if=\"canManage\" type=\"primary\" icon=\"plus\" @click=\"open(null)\">\n {{ t('panel.new-status') }}\n </wx-button>\n </template>\n\n <wx-empty v-if=\"!loading && statuses.length === 0\" :title=\"t('panel.no-statuses')\" />\n\n <wx-sortable-list\n v-else\n v-model=\"statuses\"\n plain\n item-key=\"id\"\n :item-label=\"name\"\n :disabled=\"!canManage\"\n :aria-label=\"t('panel.statuses')\"\n @move=\"reorder\"\n >\n <template #default=\"{ item }\">\n <div class=\"wx-inbox-status\">\n <wx-badge :type=\"item.color\">{{ name(item) }}</wx-badge>\n\n <wx-text size=\"sm\" tone=\"muted\" truncate>\n <code>{{ item.key }}</code>\n <template v-if=\"item.is_default\"> · {{ t('panel.status-default') }}</template>\n <template v-if=\"item.is_spam\"> · {{ t('panel.status-spam') }}</template>\n <template v-else-if=\"item.is_closed\"> · {{ t('panel.status-closed') }}</template>\n <template v-if=\"item.submissions_count\">\n · {{ t('panel.in-use') }} ({{ item.submissions_count }})\n </template>\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-list-screen>\n </div>\n</template>\n\n<style scoped>\n.wx-inbox-statuses {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--wx-space-12);\n}\n\n.wx-inbox-statuses > .wx-list-screen {\n align-self: stretch;\n}\n\n.wx-inbox-status {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n flex: 1 1 auto;\n min-width: 0;\n flex-wrap: wrap;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxBackButton,\n WxDate,\n WxNotes,\n WxRowMenu,\n type RowAction,\n} from '@webx-ui/module-admin'\nimport {\n confirm,\n localizedValue,\n toast,\n useLocales,\n WxAction,\n WxAlert,\n WxBadge,\n WxButton,\n WxCard,\n WxDescriptions,\n WxDescriptionsItem,\n WxEmpty,\n WxFileCard,\n WxHeading,\n WxSelect,\n WxSkeleton,\n WxTab,\n WxTabs,\n WxText,\n WxTimeline,\n WxTimelineItem,\n} from '@webx-ui/core'\nimport { createInboxApi } from './api'\nimport { useInboxMessages } from './i18n'\nimport type { InboxRecipient, InboxStatus, InboxSubmission, SubmissionEvent } from './types'\n\n/**\n * One submission, on a screen of its own (§11).\n *\n * A dialog over the list would have kept the filters under the reader's hand, and it was\n * rejected for one reason: a submission needs an address somebody can send. It goes into the\n * mail to whoever deals with it, it gets pasted into a chat, an agent links to it. What the\n * dialog would have given back is paid for here instead — the list's whole state travels in\n * the address, so the way out lands exactly where the reader was, and the arrows walk the same\n * filtered pile.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/inbox' })\n\nconst context = useAdmin()\nconst api = createInboxApi(context)\nconst route = useRoute()\nconst router = useRouter()\nconst locales = useLocales()\nuseInboxMessages()\n\nconst t = useTranslate('webx-inbox')\n/* The notes feed is the panel's own, and so is the word for it: a second \"Notes\" in this\n module's dictionary would be the same line translated twice. */\nconst panel = useTranslate('webx-admin')\n/* Not the server's `message`: the panel says how a request failed in its own words. */\nconst message = useErrorText()\n\nconst submission = ref<InboxSubmission | null>(null)\nconst statuses = ref<InboxStatus[]>([])\nconst admins = ref<InboxRecipient[]>([])\nconst loading = ref(true)\n\nconst canUpdate = computed(() => context.can('inbox.update'))\n\nconst id = computed(() => Number(route.params.id))\n\n/** Everything the list was looking at, carried along so the arrows walk the same pile. */\nconst filter = computed(() => ({\n view: typeof route.query.view === 'string' ? route.query.view : undefined,\n search: typeof route.query.search === 'string' ? route.query.search : undefined,\n assignee: typeof route.query.assignee === 'string' ? route.query.assignee : undefined,\n}))\n\n/** Back to the list, on the form, the tab and the page it was left at. */\nconst backTo = computed(() => ({ path: props.base, query: { ...route.query } }))\n\nconst statusOptions = computed(() =>\n statuses.value.map((status) => ({ value: status.id, label: name(status) })),\n)\n\n/* Nobody is not an option in the list but the empty state of the control: a select whose\n first line means \"none\" is one somebody picks by accident, and `clearable` already says\n it. */\nconst assigneeOptions = computed(() =>\n admins.value.map((admin) => ({ value: admin.id, label: admin.name })),\n)\n\nfunction name(status: InboxStatus): string {\n return localizedValue(status.title, locales.active.value, status.key)\n}\n\nconst heading = computed(() => t('panel.submission', { id: String(id.value) }))\n\nconst formTitle = computed(() => {\n const form = submission.value?.form\n\n return form === undefined\n ? ''\n : localizedValue(form.title ?? {}, locales.active.value, form.slug ?? '')\n})\n\n/**\n * Where a reply goes.\n *\n * The form says which field holds the sender's address (`email_field`); without one, the first\n * answer that was asked as an e-mail is the honest guess, and where there is none the button\n * is simply not there — a `mailto:` with nothing after it opens an empty window.\n */\nconst replyTo = computed(() => {\n const values = submission.value?.values ?? []\n const answer = values.find((value) => value.type === 'email' && (value.value ?? '') !== '')\n\n return answer?.value ?? null\n})\n\nconst mailto = computed(() => {\n if (replyTo.value === null) return null\n\n const subject = encodeURIComponent(`${formTitle.value} — ${heading.value}`)\n\n return `mailto:${replyTo.value}?subject=${subject}`\n})\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n submission.value = await api.submission(id.value, filter.value)\n } catch (error) {\n toast.danger(message(error))\n void router.replace(backTo.value)\n } finally {\n loading.value = false\n }\n}\n\nasync function lists(): Promise<void> {\n try {\n statuses.value = await api.statuses()\n\n // Only where there is something to do with them: assigning is `inbox.update`, and the\n // list of administrators is not a reader's business.\n if (canUpdate.value) {\n admins.value = await api.recipients()\n }\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\n/* The arrows change the address without leaving the screen, so the record has to follow it. */\nwatch(id, () => void load(), { immediate: true })\n\nvoid lists()\n\nasync function save(input: { status_id?: number; assignee_id?: number | null }): Promise<void> {\n try {\n submission.value = await api.saveSubmission(id.value, input)\n toast.success(t('panel.saved'))\n } catch (error) {\n toast.danger(message(error))\n await load()\n }\n}\n\nfunction onStatus(value: unknown): void {\n if (typeof value === 'number') void save({ status_id: value })\n}\n\nfunction onAssignee(value: unknown): void {\n void save({ assignee_id: typeof value === 'number' ? value : null })\n}\n\nconst actions = computed<RowAction[]>(() => {\n if (!canUpdate.value || submission.value === null) return []\n\n return [\n {\n key: 'unread',\n icon: 'eye-off',\n label: t('panel.mark-unread'),\n run: () => void unread(),\n },\n {\n key: 'delete',\n icon: 'trash',\n label: t('panel.delete'),\n danger: true,\n run: () => void remove(),\n },\n ]\n})\n\nasync function unread(): Promise<void> {\n try {\n await api.massSubmissions({ ids: [id.value], action: 'unread' })\n // Straight back to the list: a submission marked unread and then left open is one the\n // next request would mark read again.\n void router.push(backTo.value)\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nasync function remove(): Promise<void> {\n const agreed = await confirm({\n title: t('panel.delete-submission-title'),\n message: t('panel.delete-submission-text'),\n confirmText: t('panel.delete'),\n cancelText: t('panel.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n try {\n await api.removeSubmission(id.value)\n toast.success(t('panel.deleted'))\n void router.push(backTo.value)\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nfunction go(to: number | null): void {\n if (to === null) return\n\n void router.push({ path: `${props.base}/submissions/${to}`, query: { ...route.query } })\n}\n\n/**\n * A status the log names, in the words the panel calls it by.\n *\n * The log stores the key on purpose — read months later, the row it pointed at may have been\n * renamed or deleted, and history must not be rewritten by either. So the key is translated\n * where the panel still has that status, and shown as it stands where it does not: `spam` is\n * a poorer line than \"Спам\", and an invented one would be worse than both.\n */\nfunction statusName(key: string): string {\n const status = statuses.value.find((one) => one.key === key)\n\n return status === undefined ? key : name(status)\n}\n\n/** One line of the log, in words rather than as a pair of columns. */\nfunction line(event: SubmissionEvent): string {\n switch (event.type) {\n case 'created':\n return t('panel.event-created')\n case 'status':\n return t('panel.event-status', { to: statusName(event.to ?? '') })\n case 'assignee':\n return event.to === null || event.to === ''\n ? t('panel.event-unassigned')\n : t('panel.event-assignee', { to: event.to })\n case 'note':\n return t('panel.event-note')\n case 'notified':\n return t('panel.event-notified')\n default:\n return event.type\n }\n}\n\nfunction kilobytes(size: number): string {\n return `${Math.max(1, Math.round(size / 1024))} KB`\n}\n\n/** The metadata worth showing, in the order somebody reads it, with the empty ones left out. */\nconst details = computed(() => {\n const meta = submission.value?.meta ?? {}\n\n const rows: { label: string; value: string; link?: boolean }[] = []\n\n if (typeof meta.page === 'string' && meta.page !== '') {\n rows.push({ label: t('panel.meta-page'), value: meta.page, link: true })\n }\n\n if (typeof meta.referrer === 'string' && meta.referrer !== '') {\n rows.push({ label: t('panel.meta-referrer'), value: meta.referrer, link: true })\n }\n\n for (const [key, value] of Object.entries(meta.utm ?? {})) {\n rows.push({ label: key, value: String(value) })\n }\n\n if (typeof meta.locale === 'string' && meta.locale !== '') {\n rows.push({ label: t('panel.meta-locale'), value: meta.locale })\n }\n\n if (typeof meta.ip === 'string' && meta.ip !== '') {\n rows.push({ label: t('panel.meta-ip'), value: meta.ip })\n }\n\n if (typeof meta.user_agent === 'string' && meta.user_agent !== '') {\n rows.push({ label: t('panel.meta-agent'), value: meta.user_agent })\n }\n\n return rows\n})\n</script>\n\n<template>\n <div class=\"wx-submission\">\n <div class=\"wx-submission__head\">\n <!-- The way back keeps its own size: it belongs to the heading beside it, not to the row\n of actions at the other end of the line. -->\n <wx-back-button :to=\"backTo\" />\n\n <div class=\"wx-submission__who\">\n <wx-heading :level=\"2\" truncate>{{ heading }}</wx-heading>\n <wx-text size=\"sm\" tone=\"muted\" truncate>{{ formTitle }}</wx-text>\n </div>\n\n <!--\n One height for everything on this line, and the button with a word on it is what sets\n it: an icon button at `lg` is 42px, which is what a `md` button measures. Left to their\n defaults they came out four different sizes — 30 for the way back, 36 for the arrows,\n 42 for the reply, 30 for the menu — and a row of controls that each picked their own\n reads as four unrelated things rather than as one set.\n\n The same pile the reader was looking at, one step at a time. An arrow with nowhere to\n go is disabled rather than hidden: the pair is a control, and a control that changes\n shape at the ends is one that moves under the hand.\n\n One group and not four items in the head's row, so that on a narrow screen they go to\n the next line together instead of breaking wherever the wrap happens to fall — which\n left the arrows up by the name and the reply and the menu alone underneath.\n -->\n <div class=\"wx-submission__tools\">\n <wx-action\n icon=\"chevron-left\"\n size=\"lg\"\n :title=\"t('panel.previous')\"\n :disabled=\"!submission?.previous_id\"\n @click=\"go(submission?.previous_id ?? null)\"\n />\n <wx-action\n icon=\"chevron-right\"\n size=\"lg\"\n :title=\"t('panel.next')\"\n :disabled=\"!submission?.next_id\"\n @click=\"go(submission?.next_id ?? null)\"\n />\n\n <wx-button\n v-if=\"mailto\"\n class=\"wx-submission__reply\"\n variant=\"outline\"\n icon=\"mail\"\n :href=\"mailto\"\n >\n {{ t('panel.reply') }}\n </wx-button>\n\n <wx-row-menu :actions=\"actions\" size=\"lg\" :label=\"heading\" />\n </div>\n </div>\n\n <wx-skeleton v-if=\"loading\" :rows=\"6\" />\n\n <div v-else-if=\"submission\" class=\"wx-submission__panes\">\n <div class=\"wx-submission__main\">\n <wx-card :title=\"t('panel.answers')\">\n <wx-empty\n v-if=\"submission.values.length === 0\"\n size=\"sm\"\n :description=\"t('panel.no-answers')\"\n />\n <!-- The labels are the snapshot written when it arrived, never the field's current\n words: a submission from a year ago has to read as it did (§2.2). -->\n <wx-descriptions v-else :columns=\"1\" layout=\"vertical\">\n <wx-descriptions-item\n v-for=\"value in submission.values\"\n :key=\"value.id\"\n :label=\"value.label ?? value.name\"\n >\n <p class=\"wx-submission__value\">{{ value.value || '—' }}</p>\n </wx-descriptions-item>\n </wx-descriptions>\n </wx-card>\n\n <wx-card v-if=\"submission.files.length > 0\" :title=\"t('panel.attachments')\">\n <div class=\"wx-submission__files\">\n <!-- Through the panel and not from the disk: the bytes are behind the same\n permission as the submission, for as long as the reader has it (§8). -->\n <wx-file-card\n v-for=\"file in submission.files\"\n :key=\"file.id\"\n :name=\"file.name\"\n :type=\"file.mime ?? undefined\"\n :download-url=\"file.url\"\n :download-label=\"t('panel.download')\"\n size=\"sm\"\n >\n <template #meta>{{ kilobytes(file.size) }}</template>\n </wx-file-card>\n </div>\n </wx-card>\n\n <!--\n Everything about the submission rather than in it, behind one strip.\n\n Three cards stacked down a column is three headings to read past before the eye gets\n to the one that was wanted, and on a phone it is three screens of scrolling. They are\n not read together — a note is written while replying, the log is opened when\n something looks wrong, the metadata once — so only one of them is ever the answer.\n Pills rather than a line, and inside the card rather than over it: this is one card\n changing its contents, not a place in the panel that can be navigated to. The strip is\n the card's heading — which is why there is no other one.\n -->\n <wx-card class=\"wx-submission__more\">\n <wx-tabs variant=\"pill\" :aria-label=\"heading\">\n <wx-tab value=\"notes\" :label=\"panel('notes.title')\">\n <!-- The feed is the panel's own, not this module's: the same one will hang off\n an order and a client (§2.17). Its heading is the tab. -->\n <wx-notes\n :id=\"submission.id\"\n type=\"inbox_submission\"\n title=\"\"\n :can=\"canUpdate\"\n @change=\"load\"\n />\n </wx-tab>\n\n <wx-tab value=\"log\" :label=\"t('panel.log')\">\n <wx-timeline size=\"sm\">\n <wx-timeline-item v-for=\"event in submission.events\" :key=\"event.id\">\n <!-- What happened on one line and who did it when on the next: three inline\n pieces in a row run into each other, and a log is read down. -->\n <wx-text size=\"sm\" as=\"p\" class=\"wx-submission__event\">{{ line(event) }}</wx-text>\n <p class=\"wx-submission__by\">\n <wx-text size=\"sm\" tone=\"muted\">\n {{ event.author?.name ?? t('panel.system') }}\n </wx-text>\n <wx-date :value=\"event.created_at\" />\n </p>\n </wx-timeline-item>\n </wx-timeline>\n </wx-tab>\n\n <wx-tab value=\"details\" :label=\"t('panel.details')\">\n <div class=\"wx-submission__fields\">\n <wx-descriptions :columns=\"1\" layout=\"vertical\" size=\"sm\">\n <wx-descriptions-item :label=\"t('panel.received')\">\n <wx-date :value=\"submission.created_at\" tone=\"default\" />\n </wx-descriptions-item>\n <wx-descriptions-item :label=\"t('panel.meta-source')\">\n <wx-badge :type=\"submission.source === 'panel' ? 'info' : 'default'\">\n {{\n submission.source === 'panel'\n ? t('panel.source-panel')\n : t('panel.source-web')\n }}\n </wx-badge>\n </wx-descriptions-item>\n <wx-descriptions-item v-for=\"row in details\" :key=\"row.label\" :label=\"row.label\">\n <a v-if=\"row.link\" :href=\"row.value\" target=\"_blank\" rel=\"noreferrer\">{{\n row.value\n }}</a>\n <span v-else class=\"wx-submission__detail\">{{ row.value }}</span>\n </wx-descriptions-item>\n </wx-descriptions>\n\n <!-- An unsent notification is a mark on the submission, not a lost one\n (§2.10), and the only place it is ever said out loud is here. -->\n <wx-alert v-if=\"submission.notify_error\" type=\"warning\" :closable=\"false\">\n {{ t('panel.notify-failed') }}\n </wx-alert>\n <wx-text v-else-if=\"submission.notified_at\" size=\"sm\" tone=\"muted\">\n {{ t('panel.notified') }}\n </wx-text>\n <wx-text v-else size=\"sm\" tone=\"muted\">{{ t('panel.not-notified') }}</wx-text>\n </div>\n </wx-tab>\n </wx-tabs>\n </wx-card>\n </div>\n\n <aside class=\"wx-submission__aside\">\n <wx-card>\n <div class=\"wx-submission__fields\">\n <label class=\"wx-submission__field\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.status') }}</wx-text>\n <wx-select\n :model-value=\"submission.status?.id ?? null\"\n :options=\"statusOptions\"\n :disabled=\"!canUpdate\"\n @update:model-value=\"onStatus\"\n />\n </label>\n\n <label class=\"wx-submission__field\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.assignee') }}</wx-text>\n <wx-select\n :model-value=\"submission.assignee?.id ?? null\"\n :options=\"assigneeOptions\"\n :disabled=\"!canUpdate\"\n clearable\n :placeholder=\"t('panel.unassigned')\"\n @update:model-value=\"onAssignee\"\n />\n </label>\n </div>\n </wx-card>\n </aside>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-submission {\n display: flex;\n flex-direction: column;\n /* The panel says how far apart things stand, and it says something different on a phone\n than on a desktop (8, 12, 16). Writing the desktop number here is what made this screen\n the one place in the panel with desktop air on a 375px screen. */\n gap: var(--wx-gap, var(--wx-space-16));\n min-width: 0;\n /* The panes below decide their own layout from the width of the screen rather than of the\n window: the panel has a sidebar, and the window knows nothing about it. */\n container-type: inline-size;\n}\n\n/*\n * The way out lines up with the heading, not with the pair of lines under it: what stands\n * beside it is two lines — which submission this is and which form it came through — and a\n * centred row put the arrow level with the gap between them.\n */\n.wx-submission__head {\n display: flex;\n align-items: flex-start;\n gap: var(--wx-space-8);\n flex-wrap: wrap;\n}\n\n.wx-submission__who {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.wx-submission__tools {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n/*\n * On a phone the whole group is the size of the way back — 30.\n *\n * Every control on this line is one of two things: an icon, or a word that does what an icon\n * cannot say. The arrow at the start of the line is the same kind of thing as the arrows in\n * the middle of it, so they are all one size, and the button with the word takes that size\n * too. The height of a button is read off `--wx-size-control-md` and never declared on the\n * button itself, so handing the group a different value is enough (CLAUDE.md §4). Keyed off\n * the shell's own class rather than a width, because that is what the panel keys its icons\n * off: a narrow screen inside a desktop panel is still a desktop.\n */\n.wx-admin--drawer .wx-submission__tools {\n --wx-size-control-md: 30px;\n}\n\n/*\n * The icons and the `···` come down with it. A size class declares `--wx-action-size` on its\n * own element, so the value has to be set there rather than inherited (CLAUDE.md §4) — and\n * `WxActions` grows its menu to 44 on a touch screen, which is the rule for a table row, where\n * that menu is the only control and a finger has nothing else to aim at.\n */\n.wx-admin--drawer .wx-submission__tools :deep(.wx-action),\n.wx-admin--drawer .wx-submission__tools :deep(.wx-actions__menu .wx-action) {\n --wx-action-size: 30px;\n}\n\n/*\n * On a phone the group takes the line under the name, whole, and the one control with a word\n * on it takes what the icons leave — a button that says \"reply by mail\" in the middle of a\n * row of empty space is a button that looks like it did not fit.\n */\n@container (max-width: 560px) {\n .wx-submission__tools {\n flex: 1 1 100%;\n }\n\n /* `:deep()` because the class is ours and the element it rides is `WxButton`'s. */\n .wx-submission__tools > :deep(.wx-submission__reply) {\n flex: 1 1 auto;\n }\n}\n\n.wx-submission__panes {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n min-width: 0;\n}\n\n.wx-submission__main,\n.wx-submission__aside {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n min-width: 0;\n}\n\n/* The answers are what the screen is for, so they take the room; everything about the\n submission rather than in it stands beside them. */\n@container (min-width: 900px) {\n .wx-submission__panes {\n flex-direction: row;\n align-items: flex-start;\n }\n\n .wx-submission__main {\n flex: 1 1 auto;\n }\n\n .wx-submission__aside {\n flex: 0 0 320px;\n max-width: 320px;\n }\n}\n\n.wx-submission__value {\n margin: 0;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n.wx-submission__detail {\n overflow-wrap: anywhere;\n}\n\n.wx-submission__event {\n margin: 0;\n}\n\n.wx-submission__by {\n display: flex;\n align-items: baseline;\n gap: var(--wx-space-6);\n flex-wrap: wrap;\n margin: 0;\n}\n\n.wx-submission__files {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-8);\n}\n\n.wx-submission__fields {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n.wx-submission__field {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n}\n</style>\n","import type { AdminModule } from '@webx-ui/module-admin'\nimport FormEditorPage from './FormEditorPage.vue'\nimport InboxPage from './InboxPage.vue'\nimport StatusesPage from './StatusesPage.vue'\nimport SubmissionPage from './SubmissionPage.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 { path, name: 'webx.inbox', component: InboxPage, props: { base: path } },\n {\n path: `${path}/statuses`,\n name: 'webx.inbox.statuses',\n component: StatusesPage,\n props: { base: path },\n },\n {\n path: `${path}/forms/:id(\\\\d+)`,\n name: 'webx.inbox.form',\n component: FormEditorPage,\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: SubmissionPage,\n props: { base: path },\n },\n ],\n }\n}\n"],"names":["model","_useModel","__props","props","locales","useLocales","active","computed","chosen","locale","text","value","next","base","_unref","_createBlock","WxLocales","_createVNode","WxRichText","$event","createInboxApi","admin","data","body","nothing","id","input","ids","formId","query","listQuery","fields","search","key","suffix","inboxMessages","seeded","useInboxMessages","i18n","useAdmin","FIELD_TYPES","STATUS_COLORS","resolve","dismiss","open","useModal","context","api","t","useTranslate","message","useErrorText","saving","ref","errors","name","type","title","placeholder","help","options","isEnabled","isRequired","isFullsize","inTable","watch","field","types","one","hasChoices","choices","extensions","set","addChoice","removeChoice","index","_","at","setChoice","patch","choice","errorOf","save","error","toast","WxDialog","WxSpace","WxButton","_createElementVNode","_hoisted_1","_hoisted_2","WxFormItem","WxSelect","WxInput","_createElementBlock","_Fragment","LocalizedRichText","_cache","_openBlock","_hoisted_3","WxText","_renderList","label","WxAction","_hoisted_4","WxInputNumber","WxDatePicker","WxTagsInput","WxCheckbox","_hoisted_5","edit","createModal","FieldDialog","localizedValue","marks","empty","saved","remove","confirm","actionsFor","reorder","WxCard","WxEmpty","WxSortableList","_withCtx","item","_createTextVNode","_toDisplayString","WxBadge","WxRowMenu","option","fallback","honeypot","seconds","throttle","captcha","captchas","WxSwitch","blade","block","columns","listed","copy","WxTable","row","settings","heading","submit","redirect","admins","recipients","emailField","onMounted","adminOptions","emailOptions","isAdmin","recipient","add","setAdmin","setEmail","email","WxAlert","route","useRoute","router","useRouter","form","loading","reactive","canManage","backTo","load","loaded","WxSkeleton","WxBackButton","WxTabs","WxTab","FormGeneral","FieldList","FormNotifications","FormAntispam","FormEmbed","WxActionBar","slug","values","asked","hasFiles","WxTextarea","WxRadioGroup","WxCheckboxGroup","emit","__emit","page","statuses","selected","moving","canUpdate","SubmissionCreateDialog","view","views","counts","items","status","column","emptyText","statusOptions","formName","state","onState","wanted","statusList","mass","moveTo","statusId","action","byHand","made","exportHref","_normalizeClass","WxHeading","_keys","rows","WxAvatar","WxTooltip","WxIcon","WxDate","forms","create","FormCreateDialog","module","current","choose","duplicate","rest","WxListScreen","WxListDetail","WxIndicator","inline","back","SubmissionList","color","isDefault","isSpam","isClosed","colors","StatusDialog","panel","submission","filter","assigneeOptions","formTitle","replyTo","mailto","subject","lists","onStatus","onAssignee","actions","unread","go","to","statusName","line","event","kilobytes","size","details","meta","_hoisted_6","WxDescriptions","WxDescriptionsItem","_hoisted_7","_hoisted_8","file","WxFileCard","WxNotes","WxTimeline","WxTimelineItem","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","inbox","path","InboxPage","StatusesPage","FormEditorPage","SubmissionPage"],"mappings":"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"}
|