@elytracms/forms 0.0.104 → 0.0.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/studio/inbox.d.ts
CHANGED
|
@@ -32,7 +32,11 @@ export interface FormsInboxConfig<V> {
|
|
|
32
32
|
export declare const INBOX_CAPABILITIES: CollectionViewCapabilities;
|
|
33
33
|
/** The issues-tray finding: how many submissions' mail did not (fully) go out. */
|
|
34
34
|
declare function failedDeliveryIssues(count: number): NavIssue[];
|
|
35
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* The inbox's deep link: `[]` the list, `[submissionId]` one submission. The segment arrives
|
|
37
|
+
* decoded by the router (the `parsePath` contract), so it IS the id (EC-768: decoding it again
|
|
38
|
+
* threw on `50%` and read `a%41` as `aA`).
|
|
39
|
+
*/
|
|
36
40
|
declare function parseInboxPath(segments: string[]): Record<string, string | null> | null;
|
|
37
41
|
/** The forms inbox as a rail entry (see the module header). */
|
|
38
42
|
export declare function formsInbox<V>(config: FormsInboxConfig<V>): import("@elytracms/studio/addon").SidebarViewNode;
|
package/dist/studio/inbox.js
CHANGED
|
@@ -192,12 +192,16 @@ function FormsInbox({ ctx, config, id }) {
|
|
|
192
192
|
function InboxMessage({ text }) {
|
|
193
193
|
return (_jsx(Text, { tone: "muted", className: "p-6", "data-testid": "forms-inbox-message", children: text }));
|
|
194
194
|
}
|
|
195
|
-
/**
|
|
195
|
+
/**
|
|
196
|
+
* The inbox's deep link: `[]` the list, `[submissionId]` one submission. The segment arrives
|
|
197
|
+
* decoded by the router (the `parsePath` contract), so it IS the id (EC-768: decoding it again
|
|
198
|
+
* threw on `50%` and read `a%41` as `aA`).
|
|
199
|
+
*/
|
|
196
200
|
function parseInboxPath(segments) {
|
|
197
201
|
if (segments.length === 0)
|
|
198
202
|
return {};
|
|
199
203
|
if (segments.length === 1)
|
|
200
|
-
return { submissionId:
|
|
204
|
+
return { submissionId: segments[0] };
|
|
201
205
|
return null;
|
|
202
206
|
}
|
|
203
207
|
/** The forms inbox as a rail entry (see the module header). */
|
package/dist/studio/inbox.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inbox.js","sourceRoot":"","sources":["../../src/studio/inbox.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useMemo, useState } from 'react'\nimport { Inbox } from 'lucide-react'\nimport {\n PortableDetailEditor,\n CollectionViewSurface,\n nav,\n normalizeOkResult,\n recordListKey,\n useRecordList,\n useRailViewSource,\n} from '@elytracms/studio/addon'\nimport type {\n AppViewContext,\n CollectionViewCapabilities,\n NavIssue,\n NavPermission,\n NoticeLocation,\n OkResult,\n} from '@elytracms/studio/addon'\nimport { createCollectionRegistry, parseLocaleConfig, validateDocument } from '@elytracms/core/cms-core'\nimport type { CmsDocument, CmsValidationIssue, DocumentRef, Locale, LocalizedString } from '@elytracms/core/cms-core'\nimport { Text } from '@elytracms/studio/ui'\nimport { DELIVERY_STATES, submissionRecordKind } from '../shared/kind'\nimport type { SubmissionRecord } from '../shared/kind'\nimport { deliveryNeedsAttention } from '../shared/delivery'\nimport { labelPayload } from '../shared/mail'\nimport type { FormDocument, FormSource } from '../shared/source'\nimport {\n formOf,\n inboxIssueCount,\n inboxSaveWrite,\n submissionLens,\n submissionSender,\n submissionToLensDocument,\n} from './lens'\nimport type { InboxForms } from './lens'\nimport { SubmissionAppendix } from './appendix'\n\n/**\n * EC-613 — the forms INBOX: the submission kind on the studio's portable list/edit surfaces\n * (AD-19, EC-616's scaffold for a source of one's own), one entry in the project's rail:\n *\n * ```tsx\n * // studio/studio.config.tsx\n * import { formsInbox } from '@elytracms/forms/studio'\n * import { contactForms } from '../cms/forms'\n * export default defineStudio({ sidebar: [ …, formsInbox({ source: contactForms }) ] })\n * ```\n *\n * The list shows every submission, newest first; one opens in the portable edit shell, where\n * the editor sets the status, the assignee and notes (the inbox lifecycle) and reads — below\n * the fields — what was sent, the files and the mail delivery per recipient, with a retry for\n * a failed mail. A failed or partly failed delivery is an issue on the row AND at the rail\n * foot, from any surface. Reads and writes go through the operations client\n * (`operations.records(submissionRecordKind)`) and the one query cache (AD-17).\n */\n\nexport interface FormsInboxConfig<V> {\n /** How the inbox reads your form documents (labels, titles) — the same declaration the site's delivery route reads. */\n source: FormSource<V>\n /** The route segment (default `submissions`). */\n id?: string\n /** The rail label (default `Submissions`). */\n label?: string\n /** OPTIONAL, default-open nav permission (AD-18). */\n visible?: NavPermission\n}\n\n/** The inbox's capabilities: no \"New\" (submissions come from the site), delete and bulk delete. */\nexport const INBOX_CAPABILITIES: CollectionViewCapabilities = {\n publish: false,\n versions: false,\n locales: false,\n inlineEdit: false,\n create: false,\n duplicate: false,\n remove: true,\n bulk: true,\n liveUrl: false,\n hierarchy: false,\n importExport: false,\n adminOnly: false,\n}\n\nconst LENS_LOCALE: Locale = 'en'\nconst LENS_LOCALE_CONFIG = parseLocaleConfig({ default: LENS_LOCALE, locales: [LENS_LOCALE] })\n\nconst DELIVERY_STATE_LABELS: Record<(typeof DELIVERY_STATES)[number], LocalizedString> = {\n pending: { en: 'Sending', de: 'Wird gesendet' },\n sent: { en: 'Sent', de: 'Gesendet' },\n partial: { en: 'Partly failed', de: 'Teilweise fehlgeschlagen' },\n failed: { en: 'Failed', de: 'Fehlgeschlagen' },\n skipped: { en: 'Not sent', de: 'Nicht gesendet' },\n}\n\n/**\n * EC-690 — where the finding is: the inbox, by the record kind it lists (the view declares\n * `recordKind`), so the studio's issues tray offers \"Go to\" the inbox and shows the finding to\n * whoever can open the inbox — not to every role.\n */\nconst INBOX_LOCATION: NoticeLocation = { kind: 'record', recordKind: submissionRecordKind.kind }\n\n/** The issues-tray finding: how many submissions' mail did not (fully) go out. */\nfunction failedDeliveryIssues(count: number): NavIssue[] {\n return count === 0\n ? []\n : [\n {\n key: 'forms-delivery-failed',\n message: `${count} form submission${count === 1 ? '' : 's'}: the mail was not delivered — open the inbox to retry.`,\n severity: 'error',\n location: INBOX_LOCATION,\n },\n ]\n}\n\n/** The always-on findings hook for the issues tray (it reads the inbox's own cached list). */\nfunction useInboxIssues({ projectId }: { projectId: string }): readonly NavIssue[] {\n const list = useRecordList(submissionRecordKind, projectId)\n const count = inboxIssueCount(list.data ?? [])\n return useMemo(() => failedDeliveryIssues(count), [count])\n}\n\n/** The form documents of the source's collection, through the operations client. */\nfunction useInboxForms<V>(ctx: AppViewContext, source: FormSource<V>): InboxForms<V> | undefined {\n const forms = ctx.query.useOperationQuery<FormDocument<V>[]>({\n queryKey: ['forms-inbox', 'forms', ctx.projectId, source.collection],\n loader: async (operations) => {\n const result = await operations.documents.list({ projectId: ctx.projectId, collection: source.collection })\n if (!result.ok) throw new Error(result.error.message)\n return result.value.map((record) => ({ id: record.document.id, values: record.document.values as V }))\n },\n })\n return useMemo(() => (forms.data ? { source, documents: forms.data } : undefined), [forms.data, source])\n}\n\n/** A failed delivery as a warning on the row's own Issues pane (never blocks a save). */\nfunction deliveryIssues(record: SubmissionRecord | undefined): CmsValidationIssue[] {\n if (!record || !deliveryNeedsAttention(record.deliveryState)) return []\n const failed = (record.deliveryLog ?? []).filter((entry) => !entry.ok)\n const last = failed.at(-1)\n return [\n {\n code: 'custom-validation',\n severity: 'warning',\n message: `The mail was not delivered${last?.to ? ` to ${last.to}` : ''}${last?.error ? `: ${last.error}` : ''}.`,\n path: ['deliveryState'],\n collectionId: submissionRecordKind.kind,\n documentId: record.id,\n },\n ]\n}\n\nfunction FormsInbox<V>({ ctx, config, id }: { ctx: AppViewContext; config: FormsInboxConfig<V>; id: string }) {\n const { projectId } = ctx\n const recordId = ctx.deepLink['submissionId'] ?? null\n const list = useRecordList(submissionRecordKind, projectId)\n const cache = ctx.query.useOperationCache()\n const forms = useInboxForms(ctx, config.source)\n const [retrying, setRetrying] = useState(false)\n const [retryError, setRetryError] = useState<string | null>(null)\n\n // Newest first — the inbox order.\n const records = useMemo(\n () => [...(list.data ?? [])].sort((a, b) => (a.submittedAt < b.submittedAt ? 1 : a.submittedAt > b.submittedAt ? -1 : 0)),\n [list.data],\n )\n const byId = useMemo(() => new Map(records.map((record) => [record.id, record])), [records])\n\n const schema = useMemo(() => submissionLens({ detail: recordId !== null }), [recordId])\n const registry = useMemo(() => createCollectionRegistry([schema]), [schema])\n\n const documents = useCallback(() => records.map((record) => submissionToLensDocument(record, forms)), [records, forms])\n const get = useCallback(\n (ref: DocumentRef) => {\n const record = byId.get(ref.id)\n return record ? submissionToLensDocument(record, forms) : undefined\n },\n [byId, forms],\n )\n const titleOf = useCallback(\n (ref: DocumentRef) => {\n const record = byId.get(ref.id)\n return record ? submissionSender(forms, record) || record.form : ref.id\n },\n [byId, forms],\n )\n const validate = useCallback(\n (doc: CmsDocument) => [\n ...validateDocument(registry, doc, { localeConfig: LENS_LOCALE_CONFIG }),\n ...deliveryIssues(byId.get(doc.id)),\n ],\n [registry, byId],\n )\n\n /** Write through the operations client and place the answer in the one cached list. */\n const write = useCallback(\n async (input: { id: string } & Record<string, unknown>): Promise<OkResult> => {\n const operations = await ctx.operations()\n const result = await operations.records(submissionRecordKind).save({ projectId, ...input } as never)\n if (!result.ok) return { ok: false, message: result.error.message }\n const saved = result.value as SubmissionRecord\n cache.patch<SubmissionRecord[]>(recordListKey(submissionRecordKind, projectId), (prev) => [\n ...(prev ?? []).filter((record) => record.id !== saved.id),\n saved,\n ])\n return { ok: true }\n },\n [ctx, projectId, cache],\n )\n\n const save = useCallback(\n async (doc: CmsDocument, base?: CmsDocument): Promise<OkResult> => {\n const stored = byId.get(doc.id)\n if (!stored) return { ok: false, message: `Submission “${doc.id}” is not loaded.` }\n // Against the record as the editor OPENED it (`base`, EC-616) — never the cache, which may\n // already hold another editor's change to a column this editor did not touch.\n const change = inboxSaveWrite(doc, base, stored, forms)\n // Nothing the editor owns changed: nothing to write (the displayed columns are never sent).\n if (Object.keys(change).length === 1) return { ok: true }\n return write(change)\n },\n [byId, write, forms],\n )\n const remove = useCallback(\n async (ref: DocumentRef): Promise<OkResult> => {\n const operations = await ctx.operations()\n const result = await operations.records(submissionRecordKind).remove({ projectId, id: ref.id })\n if (!result.ok) return { ok: false, message: result.error.message }\n cache.patch<SubmissionRecord[]>(recordListKey(submissionRecordKind, projectId), (prev) =>\n (prev ?? []).filter((record) => record.id !== ref.id),\n )\n return { ok: true }\n },\n [ctx, projectId, cache],\n )\n const create = useCallback((): DocumentRef => {\n throw new Error('Submissions come from the site — the inbox creates none.')\n }, [])\n\n const source = useRailViewSource({\n projectId,\n schema,\n capabilities: INBOX_CAPABILITIES,\n localeConfig: LENS_LOCALE_CONFIG,\n documents,\n get,\n titleOf,\n detailPath: (submissionId: string) => `${id}/${submissionId}`,\n listPath: id,\n validate,\n create,\n save,\n remove,\n normalizeSaveResult: normalizeOkResult,\n normalizeRemoveResult: normalizeOkResult,\n })\n\n const retry = useCallback(async () => {\n if (!recordId) return\n setRetrying(true)\n setRetryError(null)\n // Moving the row INTO `pending` is the retry: the deployment schedules the delivery.\n const result = await write({ id: recordId, deliveryState: 'pending' })\n if (!result.ok) setRetryError(result.message)\n setRetrying(false)\n }, [recordId, write])\n\n if (list.status === 'pending') return <InboxMessage text=\"Loading submissions…\" />\n if (list.status === 'error') return <InboxMessage text={`Submissions could not be loaded: ${list.error?.message ?? 'unknown error'}`} />\n if (recordId === null) return <CollectionViewSurface source={source} projectId={projectId} />\n\n const record = byId.get(recordId)\n const form = record ? formOf(forms, record) : undefined\n const fields = record ? labelPayload(record.payload, form ? (config.source.fields?.(form.values) ?? []) : []) : []\n return (\n <PortableDetailEditor\n source={source}\n projectId={projectId}\n documentId={recordId}\n formAppendix={\n record ? (\n <>\n <SubmissionAppendix\n record={record}\n fields={fields}\n stateLabel={DELIVERY_STATE_LABELS[record.deliveryState]}\n onRetry={() => void retry()}\n retrying={retrying}\n />\n {retryError ? <InboxMessage text={retryError} /> : null}\n </>\n ) : null\n }\n />\n )\n}\n\nfunction InboxMessage({ text }: { text: string }) {\n return (\n <Text tone=\"muted\" className=\"p-6\" data-testid=\"forms-inbox-message\">\n {text}\n </Text>\n )\n}\n\n/** The inbox's deep link: `[]` the list, `[submissionId]` one submission. */\nfunction parseInboxPath(segments: string[]): Record<string, string | null> | null {\n if (segments.length === 0) return {}\n if (segments.length === 1) return { submissionId: decodeURIComponent(segments[0]!) }\n return null\n}\n\n/** The forms inbox as a rail entry (see the module header). */\nexport function formsInbox<V>(config: FormsInboxConfig<V>) {\n const id = config.id ?? 'submissions'\n return nav.view({\n id,\n label: config.label ?? 'Submissions',\n description: 'Form submissions from the site, with their mail delivery.',\n icon: Inbox,\n parsePath: parseInboxPath,\n useIssues: useInboxIssues,\n // EC-690: the record kind this view lists — a submission-located finding opens here.\n recordKind: submissionRecordKind.kind,\n ...(config.visible ? { visible: config.visible } : {}),\n render: (ctx) => <FormsInbox ctx={ctx} config={config} id={id} />,\n })\n}\n\nexport { failedDeliveryIssues, parseInboxPath }\n"]}
|
|
1
|
+
{"version":3,"file":"inbox.js","sourceRoot":"","sources":["../../src/studio/inbox.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useMemo, useState } from 'react'\nimport { Inbox } from 'lucide-react'\nimport {\n PortableDetailEditor,\n CollectionViewSurface,\n nav,\n normalizeOkResult,\n recordListKey,\n useRecordList,\n useRailViewSource,\n} from '@elytracms/studio/addon'\nimport type {\n AppViewContext,\n CollectionViewCapabilities,\n NavIssue,\n NavPermission,\n NoticeLocation,\n OkResult,\n} from '@elytracms/studio/addon'\nimport { createCollectionRegistry, parseLocaleConfig, validateDocument } from '@elytracms/core/cms-core'\nimport type { CmsDocument, CmsValidationIssue, DocumentRef, Locale, LocalizedString } from '@elytracms/core/cms-core'\nimport { Text } from '@elytracms/studio/ui'\nimport { DELIVERY_STATES, submissionRecordKind } from '../shared/kind'\nimport type { SubmissionRecord } from '../shared/kind'\nimport { deliveryNeedsAttention } from '../shared/delivery'\nimport { labelPayload } from '../shared/mail'\nimport type { FormDocument, FormSource } from '../shared/source'\nimport {\n formOf,\n inboxIssueCount,\n inboxSaveWrite,\n submissionLens,\n submissionSender,\n submissionToLensDocument,\n} from './lens'\nimport type { InboxForms } from './lens'\nimport { SubmissionAppendix } from './appendix'\n\n/**\n * EC-613 — the forms INBOX: the submission kind on the studio's portable list/edit surfaces\n * (AD-19, EC-616's scaffold for a source of one's own), one entry in the project's rail:\n *\n * ```tsx\n * // studio/studio.config.tsx\n * import { formsInbox } from '@elytracms/forms/studio'\n * import { contactForms } from '../cms/forms'\n * export default defineStudio({ sidebar: [ …, formsInbox({ source: contactForms }) ] })\n * ```\n *\n * The list shows every submission, newest first; one opens in the portable edit shell, where\n * the editor sets the status, the assignee and notes (the inbox lifecycle) and reads — below\n * the fields — what was sent, the files and the mail delivery per recipient, with a retry for\n * a failed mail. A failed or partly failed delivery is an issue on the row AND at the rail\n * foot, from any surface. Reads and writes go through the operations client\n * (`operations.records(submissionRecordKind)`) and the one query cache (AD-17).\n */\n\nexport interface FormsInboxConfig<V> {\n /** How the inbox reads your form documents (labels, titles) — the same declaration the site's delivery route reads. */\n source: FormSource<V>\n /** The route segment (default `submissions`). */\n id?: string\n /** The rail label (default `Submissions`). */\n label?: string\n /** OPTIONAL, default-open nav permission (AD-18). */\n visible?: NavPermission\n}\n\n/** The inbox's capabilities: no \"New\" (submissions come from the site), delete and bulk delete. */\nexport const INBOX_CAPABILITIES: CollectionViewCapabilities = {\n publish: false,\n versions: false,\n locales: false,\n inlineEdit: false,\n create: false,\n duplicate: false,\n remove: true,\n bulk: true,\n liveUrl: false,\n hierarchy: false,\n importExport: false,\n adminOnly: false,\n}\n\nconst LENS_LOCALE: Locale = 'en'\nconst LENS_LOCALE_CONFIG = parseLocaleConfig({ default: LENS_LOCALE, locales: [LENS_LOCALE] })\n\nconst DELIVERY_STATE_LABELS: Record<(typeof DELIVERY_STATES)[number], LocalizedString> = {\n pending: { en: 'Sending', de: 'Wird gesendet' },\n sent: { en: 'Sent', de: 'Gesendet' },\n partial: { en: 'Partly failed', de: 'Teilweise fehlgeschlagen' },\n failed: { en: 'Failed', de: 'Fehlgeschlagen' },\n skipped: { en: 'Not sent', de: 'Nicht gesendet' },\n}\n\n/**\n * EC-690 — where the finding is: the inbox, by the record kind it lists (the view declares\n * `recordKind`), so the studio's issues tray offers \"Go to\" the inbox and shows the finding to\n * whoever can open the inbox — not to every role.\n */\nconst INBOX_LOCATION: NoticeLocation = { kind: 'record', recordKind: submissionRecordKind.kind }\n\n/** The issues-tray finding: how many submissions' mail did not (fully) go out. */\nfunction failedDeliveryIssues(count: number): NavIssue[] {\n return count === 0\n ? []\n : [\n {\n key: 'forms-delivery-failed',\n message: `${count} form submission${count === 1 ? '' : 's'}: the mail was not delivered — open the inbox to retry.`,\n severity: 'error',\n location: INBOX_LOCATION,\n },\n ]\n}\n\n/** The always-on findings hook for the issues tray (it reads the inbox's own cached list). */\nfunction useInboxIssues({ projectId }: { projectId: string }): readonly NavIssue[] {\n const list = useRecordList(submissionRecordKind, projectId)\n const count = inboxIssueCount(list.data ?? [])\n return useMemo(() => failedDeliveryIssues(count), [count])\n}\n\n/** The form documents of the source's collection, through the operations client. */\nfunction useInboxForms<V>(ctx: AppViewContext, source: FormSource<V>): InboxForms<V> | undefined {\n const forms = ctx.query.useOperationQuery<FormDocument<V>[]>({\n queryKey: ['forms-inbox', 'forms', ctx.projectId, source.collection],\n loader: async (operations) => {\n const result = await operations.documents.list({ projectId: ctx.projectId, collection: source.collection })\n if (!result.ok) throw new Error(result.error.message)\n return result.value.map((record) => ({ id: record.document.id, values: record.document.values as V }))\n },\n })\n return useMemo(() => (forms.data ? { source, documents: forms.data } : undefined), [forms.data, source])\n}\n\n/** A failed delivery as a warning on the row's own Issues pane (never blocks a save). */\nfunction deliveryIssues(record: SubmissionRecord | undefined): CmsValidationIssue[] {\n if (!record || !deliveryNeedsAttention(record.deliveryState)) return []\n const failed = (record.deliveryLog ?? []).filter((entry) => !entry.ok)\n const last = failed.at(-1)\n return [\n {\n code: 'custom-validation',\n severity: 'warning',\n message: `The mail was not delivered${last?.to ? ` to ${last.to}` : ''}${last?.error ? `: ${last.error}` : ''}.`,\n path: ['deliveryState'],\n collectionId: submissionRecordKind.kind,\n documentId: record.id,\n },\n ]\n}\n\nfunction FormsInbox<V>({ ctx, config, id }: { ctx: AppViewContext; config: FormsInboxConfig<V>; id: string }) {\n const { projectId } = ctx\n const recordId = ctx.deepLink['submissionId'] ?? null\n const list = useRecordList(submissionRecordKind, projectId)\n const cache = ctx.query.useOperationCache()\n const forms = useInboxForms(ctx, config.source)\n const [retrying, setRetrying] = useState(false)\n const [retryError, setRetryError] = useState<string | null>(null)\n\n // Newest first — the inbox order.\n const records = useMemo(\n () => [...(list.data ?? [])].sort((a, b) => (a.submittedAt < b.submittedAt ? 1 : a.submittedAt > b.submittedAt ? -1 : 0)),\n [list.data],\n )\n const byId = useMemo(() => new Map(records.map((record) => [record.id, record])), [records])\n\n const schema = useMemo(() => submissionLens({ detail: recordId !== null }), [recordId])\n const registry = useMemo(() => createCollectionRegistry([schema]), [schema])\n\n const documents = useCallback(() => records.map((record) => submissionToLensDocument(record, forms)), [records, forms])\n const get = useCallback(\n (ref: DocumentRef) => {\n const record = byId.get(ref.id)\n return record ? submissionToLensDocument(record, forms) : undefined\n },\n [byId, forms],\n )\n const titleOf = useCallback(\n (ref: DocumentRef) => {\n const record = byId.get(ref.id)\n return record ? submissionSender(forms, record) || record.form : ref.id\n },\n [byId, forms],\n )\n const validate = useCallback(\n (doc: CmsDocument) => [\n ...validateDocument(registry, doc, { localeConfig: LENS_LOCALE_CONFIG }),\n ...deliveryIssues(byId.get(doc.id)),\n ],\n [registry, byId],\n )\n\n /** Write through the operations client and place the answer in the one cached list. */\n const write = useCallback(\n async (input: { id: string } & Record<string, unknown>): Promise<OkResult> => {\n const operations = await ctx.operations()\n const result = await operations.records(submissionRecordKind).save({ projectId, ...input } as never)\n if (!result.ok) return { ok: false, message: result.error.message }\n const saved = result.value as SubmissionRecord\n cache.patch<SubmissionRecord[]>(recordListKey(submissionRecordKind, projectId), (prev) => [\n ...(prev ?? []).filter((record) => record.id !== saved.id),\n saved,\n ])\n return { ok: true }\n },\n [ctx, projectId, cache],\n )\n\n const save = useCallback(\n async (doc: CmsDocument, base?: CmsDocument): Promise<OkResult> => {\n const stored = byId.get(doc.id)\n if (!stored) return { ok: false, message: `Submission “${doc.id}” is not loaded.` }\n // Against the record as the editor OPENED it (`base`, EC-616) — never the cache, which may\n // already hold another editor's change to a column this editor did not touch.\n const change = inboxSaveWrite(doc, base, stored, forms)\n // Nothing the editor owns changed: nothing to write (the displayed columns are never sent).\n if (Object.keys(change).length === 1) return { ok: true }\n return write(change)\n },\n [byId, write, forms],\n )\n const remove = useCallback(\n async (ref: DocumentRef): Promise<OkResult> => {\n const operations = await ctx.operations()\n const result = await operations.records(submissionRecordKind).remove({ projectId, id: ref.id })\n if (!result.ok) return { ok: false, message: result.error.message }\n cache.patch<SubmissionRecord[]>(recordListKey(submissionRecordKind, projectId), (prev) =>\n (prev ?? []).filter((record) => record.id !== ref.id),\n )\n return { ok: true }\n },\n [ctx, projectId, cache],\n )\n const create = useCallback((): DocumentRef => {\n throw new Error('Submissions come from the site — the inbox creates none.')\n }, [])\n\n const source = useRailViewSource({\n projectId,\n schema,\n capabilities: INBOX_CAPABILITIES,\n localeConfig: LENS_LOCALE_CONFIG,\n documents,\n get,\n titleOf,\n detailPath: (submissionId: string) => `${id}/${submissionId}`,\n listPath: id,\n validate,\n create,\n save,\n remove,\n normalizeSaveResult: normalizeOkResult,\n normalizeRemoveResult: normalizeOkResult,\n })\n\n const retry = useCallback(async () => {\n if (!recordId) return\n setRetrying(true)\n setRetryError(null)\n // Moving the row INTO `pending` is the retry: the deployment schedules the delivery.\n const result = await write({ id: recordId, deliveryState: 'pending' })\n if (!result.ok) setRetryError(result.message)\n setRetrying(false)\n }, [recordId, write])\n\n if (list.status === 'pending') return <InboxMessage text=\"Loading submissions…\" />\n if (list.status === 'error') return <InboxMessage text={`Submissions could not be loaded: ${list.error?.message ?? 'unknown error'}`} />\n if (recordId === null) return <CollectionViewSurface source={source} projectId={projectId} />\n\n const record = byId.get(recordId)\n const form = record ? formOf(forms, record) : undefined\n const fields = record ? labelPayload(record.payload, form ? (config.source.fields?.(form.values) ?? []) : []) : []\n return (\n <PortableDetailEditor\n source={source}\n projectId={projectId}\n documentId={recordId}\n formAppendix={\n record ? (\n <>\n <SubmissionAppendix\n record={record}\n fields={fields}\n stateLabel={DELIVERY_STATE_LABELS[record.deliveryState]}\n onRetry={() => void retry()}\n retrying={retrying}\n />\n {retryError ? <InboxMessage text={retryError} /> : null}\n </>\n ) : null\n }\n />\n )\n}\n\nfunction InboxMessage({ text }: { text: string }) {\n return (\n <Text tone=\"muted\" className=\"p-6\" data-testid=\"forms-inbox-message\">\n {text}\n </Text>\n )\n}\n\n/**\n * The inbox's deep link: `[]` the list, `[submissionId]` one submission. The segment arrives\n * decoded by the router (the `parsePath` contract), so it IS the id (EC-768: decoding it again\n * threw on `50%` and read `a%41` as `aA`).\n */\nfunction parseInboxPath(segments: string[]): Record<string, string | null> | null {\n if (segments.length === 0) return {}\n if (segments.length === 1) return { submissionId: segments[0]! }\n return null\n}\n\n/** The forms inbox as a rail entry (see the module header). */\nexport function formsInbox<V>(config: FormsInboxConfig<V>) {\n const id = config.id ?? 'submissions'\n return nav.view({\n id,\n label: config.label ?? 'Submissions',\n description: 'Form submissions from the site, with their mail delivery.',\n icon: Inbox,\n parsePath: parseInboxPath,\n useIssues: useInboxIssues,\n // EC-690: the record kind this view lists — a submission-located finding opens here.\n recordKind: submissionRecordKind.kind,\n ...(config.visible ? { visible: config.visible } : {}),\n render: (ctx) => <FormsInbox ctx={ctx} config={config} id={id} />,\n })\n}\n\nexport { failedDeliveryIssues, parseInboxPath }\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elytracms/forms",
|
|
3
3
|
"author": "finaldream <hi@finaldream.de>",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.105",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.18.0"
|
|
7
7
|
},
|
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"lucide-react": "^1.23.0",
|
|
30
30
|
"zod": "^4.4.3",
|
|
31
|
-
"@elytracms/core": "^0.0.
|
|
31
|
+
"@elytracms/core": "^0.0.105"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"convex": "^1.42.1",
|
|
35
35
|
"react": "^19.0.0",
|
|
36
|
-
"@elytracms/next": "^0.0.
|
|
37
|
-
"@elytracms/studio": "^0.0.
|
|
36
|
+
"@elytracms/next": "^0.0.105",
|
|
37
|
+
"@elytracms/studio": "^0.0.105"
|
|
38
38
|
},
|
|
39
39
|
"peerDependenciesMeta": {
|
|
40
40
|
"@elytracms/next": {
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
"react": "^19.2.7",
|
|
60
60
|
"react-dom": "^19.2.7",
|
|
61
61
|
"typescript": "^6.0.3",
|
|
62
|
-
"@elytracms/next": "^0.0.
|
|
63
|
-
"@elytracms/studio": "^0.0.
|
|
62
|
+
"@elytracms/next": "^0.0.105",
|
|
63
|
+
"@elytracms/studio": "^0.0.105"
|
|
64
64
|
},
|
|
65
65
|
"files": [
|
|
66
66
|
"dist",
|