feat(12.2-04): add the fileupload field with deferred uploads on the form session key
- sessionKey.ts: one 32-byte base64url key per form mount, sent only in headers - api/files.ts: FileRoutes over the record and child file routes, XHR upload with progress, 401 refresh and retry - FileuploadField and FileCaptionModal per UI-SPEC section 3: dropzone, image grid, rows, per-item states, client pre-checks, reorder, protected previews - FormView provides FORM_SESSION, counts pending changes as dirty and sends X-Session-Key on create and update - fileupload lang keys in en and pl, admin-spa docs note, deferred smoke test, rebuilt dist
This commit is contained in:
@@ -6,9 +6,13 @@
|
||||
// Phase 10.1 adds the plugin extension types: a widget mounts a plugin custom
|
||||
// element (D-04, D-09) and a partial renders a server template (D-17). They
|
||||
// hold no form value either, but they render on create and update.
|
||||
// Phase 12.2 adds the fileupload control: it edits its files through the file
|
||||
// routes against the form's session key (D-02, D-03), so it holds no form
|
||||
// value either and renders on create and update.
|
||||
import type { Component } from 'vue'
|
||||
import CheckboxField from './fields/CheckboxField.vue'
|
||||
import DropdownField from './fields/DropdownField.vue'
|
||||
import FileuploadField from './fields/FileuploadField.vue'
|
||||
import NumberField from './fields/NumberField.vue'
|
||||
import PartialField from './fields/PartialField.vue'
|
||||
import RelationManager from '../relation/RelationManager.vue'
|
||||
@@ -39,6 +43,7 @@ const renderers = new Map<string, Component>([
|
||||
[RELATION_MANAGER, RelationManager],
|
||||
['widget', WidgetField],
|
||||
['partial', PartialField],
|
||||
['fileupload', FileuploadField],
|
||||
])
|
||||
|
||||
/** Types whose control shows the label itself (toggle cards, relation manager). */
|
||||
@@ -51,13 +56,13 @@ const selfLabelled = new Set<string>(['switch', 'checkbox', RELATION_MANAGER])
|
||||
const recordBound = new Set<string>([RELATION_MANAGER])
|
||||
|
||||
/** Types that hold no form value: never part of the save body (D-09). */
|
||||
const valueless = new Set<string>([RELATION_MANAGER, 'widget', 'partial'])
|
||||
const valueless = new Set<string>([RELATION_MANAGER, 'widget', 'partial', 'fileupload'])
|
||||
|
||||
/**
|
||||
* Types whose control is a group rather than one focusable element: the
|
||||
* visible label is a span the group points at, not a label for an input.
|
||||
*/
|
||||
const groupLabelledTypes = new Set<string>(['widget', 'partial'])
|
||||
const groupLabelledTypes = new Set<string>(['widget', 'partial', 'fileupload'])
|
||||
|
||||
export function rendererFor(type: string): Component {
|
||||
return renderers.get(type) ?? UnsupportedField
|
||||
|
||||
Reference in New Issue
Block a user