@conduction/nextcloud-vue 2.132.0 → 2.134.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/dist/esm/components/CnActionButtons/CnActionButtons.vue.js +1 -1
- package/dist/esm/components/CnActionButtons/CnActionButtons.vue2.js +14 -0
- package/dist/esm/components/CnActionButtons/CnActionButtons.vue2.js.map +1 -1
- package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js +5 -4
- package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js.map +1 -1
- package/dist/esm/components/CnConditionListEditor/CnConditionListEditor.vue.js +9 -0
- package/dist/esm/components/CnConditionListEditor/CnConditionListEditor.vue.js.map +1 -0
- package/dist/esm/components/CnConditionListEditor/CnConditionListEditor.vue2.js +237 -0
- package/dist/esm/components/CnConditionListEditor/CnConditionListEditor.vue2.js.map +1 -0
- package/dist/esm/components/CnConditionListEditor/CnConditionListEditor.vue3.js +103 -0
- package/dist/esm/components/CnConditionListEditor/CnConditionListEditor.vue3.js.map +1 -0
- package/dist/esm/components/CnConditionListEditor/conditionOperators.js +121 -0
- package/dist/esm/components/CnConditionListEditor/conditionOperators.js.map +1 -0
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +12 -0
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +85 -10
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +60 -36
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +8 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIntegrationWidget/CnIntegrationWidget.vue.js +1 -1
- package/dist/esm/components/CnIntegrationWidget/CnIntegrationWidget.vue2.js +10 -0
- package/dist/esm/components/CnIntegrationWidget/CnIntegrationWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnIntegrationWidget/CnIntegrationWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue.js +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue2.js +46 -7
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue3.js +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue2.js +258 -6
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue3.js +283 -131
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +42 -2
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/dialogs/CnPartyAddDialog.vue.js +9 -0
- package/dist/esm/dialogs/CnPartyAddDialog.vue.js.map +1 -0
- package/dist/esm/dialogs/CnPartyAddDialog.vue2.js +184 -0
- package/dist/esm/dialogs/CnPartyAddDialog.vue2.js.map +1 -0
- package/dist/esm/dialogs/CnPartyAddDialog.vue3.js +168 -0
- package/dist/esm/dialogs/CnPartyAddDialog.vue3.js.map +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +27 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +27 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +353 -217
- package/dist/esm/store/plugins/liveUpdates.js +13 -4
- package/dist/esm/store/plugins/liveUpdates.js.map +1 -1
- package/dist/esm/store/useObjectStore.js +28 -5
- package/dist/esm/store/useObjectStore.js.map +1 -1
- package/dist/esm/utils/detailActionModel.js +6 -0
- package/dist/esm/utils/detailActionModel.js.map +1 -1
- package/dist/esm/utils/listLenses.js +20 -1
- package/dist/esm/utils/listLenses.js.map +1 -1
- package/dist/esm/utils/objectParties.js +79 -1
- package/dist/esm/utils/objectParties.js.map +1 -1
- package/dist/esm/utils/objectRows.js +59 -0
- package/dist/esm/utils/objectRows.js.map +1 -0
- package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +7460 -5803
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +353 -217
- package/l10n/en.json +27 -1
- package/l10n/nl.json +27 -1
- package/package.json +1 -1
- package/src/components/CnActionButtons/CnActionButtons.vue +15 -0
- package/src/components/CnConditionListEditor/CnConditionListEditor.vue +346 -0
- package/src/components/CnConditionListEditor/conditionOperators.js +126 -0
- package/src/components/CnConditionListEditor/index.js +17 -0
- package/src/components/CnDetailPage/CnDetailPage.md +1 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +13 -1
- package/src/components/CnFieldListWidget/CnFieldListWidget.vue +105 -12
- package/src/components/CnIndexPage/CnIndexPage.vue +8 -1
- package/src/components/CnIntegrationWidget/CnIntegrationWidget.vue +10 -0
- package/src/components/CnNcWidgetWidget/CnNcWidgetWidget.vue +47 -8
- package/src/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue +401 -3
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +42 -2
- package/src/components/CnTabsWidget/CnTabsWidget.vue +1 -1
- package/src/components/index.js +1 -0
- package/src/css/look-board-index.css +6 -0
- package/src/css/look-board.css +35 -7
- package/src/dialogs/CnPartyAddDialog.vue +309 -0
- package/src/index.js +2 -0
- package/src/schemas/app-manifest-v2.schema.json +17 -1
- package/src/store/plugins/liveUpdates.js +13 -4
- package/src/store/useObjectStore.js +28 -5
- package/src/utils/detailActionModel.js +6 -0
- package/src/utils/listLenses.js +20 -1
- package/src/utils/objectParties.js +78 -0
- package/src/utils/objectRows.js +55 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detailActionModel.js","sources":["../../../src/utils/detailActionModel.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * detailActionModel: the rules behind a detail page's four action levels and\n * the case surfaces that read the record's stage.\n *\n * 1. the next step: one primary button, chosen by the record's stage,\n * 2. quick actions: at most three always visible buttons,\n * 3. the overflow menu: the rest, in named groups,\n * 4. admin actions: the last group, for admins only.\n *\n * Pure functions, no Vue and no fetch, so CnDetailPage, the widgets and the\n * tests all read one implementation.\n *\n * @module utils/detailActionModel\n */\n\nimport { variantForColor } from './headerFieldChips.js'\nimport { readPath } from './readPath.js'\nimport { evaluateVisibleWhenLocal } from './visibleWhen.js'\n\n/** The most quick actions a page shows. Later entries are dropped. */\nexport const MAX_QUICK_ACTIONS = 3\n\n/**\n * The record's stage, as the string a stage map is keyed on.\n *\n * @param {object|null} object The record.\n * @param {string} [stageField] Dot-path to the stage. Defaults to `status`.\n * @return {string} The stage, or '' when the record has none.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-primary-action-follows-the-stage\n */\nexport function stageOf(object, stageField = 'status') {\n\tif (!object || typeof object !== 'object') {\n\t\treturn ''\n\t}\n\tconst value = readPath(object, stageField || 'status')\n\tif (value === null || value === undefined || typeof value === 'object') {\n\t\treturn ''\n\t}\n\treturn String(value)\n}\n\n/**\n * Look a stage up in a stage-keyed map. An exact key wins; otherwise the\n * match ignores case, because a status is stored as `in_behandeling` in one\n * register and `In_Behandeling` in the next.\n *\n * @param {object|null} map The stage-keyed map.\n * @param {string} stage The stage.\n * @return {unknown} The entry, or undefined.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-primary-action-follows-the-stage\n */\nexport function stageEntry(map, stage) {\n\tif (!map || typeof map !== 'object' || Array.isArray(map) || stage === '') {\n\t\treturn undefined\n\t}\n\tif (Object.hasOwn(map, stage)) {\n\t\treturn map[stage]\n\t}\n\tconst wanted = stage.toLowerCase()\n\tconst key = Object.keys(map).find((candidate) => candidate.toLowerCase() === wanted)\n\treturn key === undefined ? undefined : map[key]\n}\n\n/**\n * Turn a pinned action entry into a descriptor the page can dispatch.\n *\n * An entry is the id of a declared header action, or an action object of its\n * own. An object without an id gets `fallbackId`, since every dispatched\n * action is addressed by id. `{ id, tabs?, notTabs? }` without a label names\n * a declared action and says beside which body tabs it shows (see `onTab`).\n *\n * @param {string|object|null} entry The entry.\n * @param {string} fallbackId Id for an inline action that names none.\n * @return {{id: string, inline: object|null, tabs?: Array<string>, notTabs?: Array<string>}|null} The id, plus the inline definition when the entry carried one.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-quick-actions\n * @spec openspec/changes/detail-actions-per-tab/specs/detail-page/spec.md#requirement-quick-actions-and-the-next-step-card-can-follow-the-open-tab\n */\nexport function normalisePinnedAction(entry, fallbackId) {\n\tif (typeof entry === 'string') {\n\t\treturn entry === '' ? null : { id: entry, inline: null }\n\t}\n\tif (!entry || typeof entry !== 'object' || Array.isArray(entry)) {\n\t\treturn null\n\t}\n\tconst scoped = Array.isArray(entry.tabs) || Array.isArray(entry.notTabs)\n\tif (typeof entry.label !== 'string' || entry.label === '') {\n\t\tif (!scoped || typeof entry.id !== 'string' || entry.id === '') {\n\t\t\treturn null\n\t\t}\n\t\treturn { id: entry.id, inline: null, tabs: entry.tabs, notTabs: entry.notTabs }\n\t}\n\tconst id = typeof entry.id === 'string' && entry.id !== '' ? entry.id : fallbackId\n\tconst { tabs, notTabs, ...action } = entry\n\tconst pinned = { id, inline: { ...action, id } }\n\treturn scoped ? { ...pinned, tabs, notTabs } : pinned\n}\n\n/**\n * Whether an entry belongs beside the open body tab: one with `tabs` shows\n * only while one of them is open, one with `notTabs` stands aside while one\n * of those is open, one with neither shows beside every tab.\n *\n * @param {object|null} entry The entry, carrying `tabs` / `notTabs`.\n * @param {string} activeTab The open body tab's id.\n * @return {boolean}\n * @spec openspec/changes/detail-actions-per-tab/specs/detail-page/spec.md#requirement-quick-actions-and-the-next-step-card-can-follow-the-open-tab\n */\nexport function onTab(entry, activeTab) {\n\tif (!entry) {\n\t\treturn true\n\t}\n\tif (Array.isArray(entry.notTabs) && entry.notTabs.map((id) => String(id)).includes(activeTab)) {\n\t\treturn false\n\t}\n\tif (!Array.isArray(entry.tabs) || entry.tabs.length === 0) {\n\t\treturn true\n\t}\n\treturn entry.tabs.map((id) => String(id)).includes(activeTab)\n}\n\n/**\n * Split menu entries into the groups the overflow menu draws.\n *\n * Ungrouped entries come first, under no caption. Named groups follow in the\n * order they first appear. Admin only entries are dropped for everyone else\n * and form the last group for admins, whatever `group` they also name.\n *\n * `adminOnly` hides a control. It is never an authorization decision: the\n * endpoint behind the action decides who may call it.\n *\n * @param {Array<object>} entries Menu-ready entries, each with an `id`.\n * @param {object} actionsById The declared actions by id, carrying `group` / `adminOnly`.\n * @param {{isAdmin?: boolean, adminLabel?: string}} [options] Who is looking, and what the admin group is called.\n * @return {Array<{key: string, label: string, entries: Array<object>}>} The non-empty groups, in render order.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-grouped-and-admin-only-menu-actions\n */\nexport function groupMenuEntries(entries, actionsById = {}, options = {}) {\n\tconst isAdmin = options.isAdmin === true\n\tconst plain = { key: '', label: '', entries: [] }\n\tconst named = []\n\tconst admin = { key: 'cn-admin', label: options.adminLabel || '', entries: [] }\n\tfor (const entry of Array.isArray(entries) ? entries : []) {\n\t\tconst declared = (entry && actionsById[entry.id]) || {}\n\t\tif (declared.adminOnly === true) {\n\t\t\tif (isAdmin) {\n\t\t\t\tadmin.entries.push(entry)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tconst label = typeof declared.group === 'string' ? declared.group.trim() : ''\n\t\tif (label === '') {\n\t\t\tplain.entries.push(entry)\n\t\t\tcontinue\n\t\t}\n\t\tlet group = named.find((candidate) => candidate.label === label)\n\t\tif (!group) {\n\t\t\tgroup = { key: `cn-group-${named.length}`, label, entries: [] }\n\t\t\tnamed.push(group)\n\t\t}\n\t\tgroup.entries.push(entry)\n\t}\n\treturn [plain, ...named, admin].filter((group) => group.entries.length > 0)\n}\n\n/**\n * Whether one checklist item is done for this record.\n *\n * `done` (a literal) wins, then `doneWhen` (a local visibleWhen condition),\n * then `doneField` (truthy, and for a list: not empty).\n *\n * @param {object} item The checklist item.\n * @param {object|null} object The record.\n * @return {boolean} True when the item is done.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-next-step-card\n */\nexport function isChecklistItemDone(item, object) {\n\tif (!item || typeof item !== 'object') {\n\t\treturn false\n\t}\n\tif (typeof item.done === 'boolean') {\n\t\treturn item.done\n\t}\n\tconst data = object && typeof object === 'object' ? object : {}\n\tif (item.doneWhen && typeof item.doneWhen === 'object') {\n\t\treturn evaluateVisibleWhenLocal(item.doneWhen, data)\n\t}\n\tif (typeof item.doneField === 'string' && item.doneField !== '') {\n\t\tconst value = readPath(data, item.doneField)\n\t\treturn Array.isArray(value) ? value.length > 0 : Boolean(value)\n\t}\n\treturn false\n}\n\n/**\n * A text or its candidates: a string, or a list of strings to fill in order.\n *\n * @param {unknown} value The configured value.\n * @return {string|string[]|null} The text or the candidates, or null.\n */\nfunction templateOf(value) {\n\tif (typeof value === 'string' && value !== '') {\n\t\treturn value\n\t}\n\tif (Array.isArray(value)) {\n\t\tconst list = value.filter((item) => typeof item === 'string' && item !== '')\n\t\treturn list.length > 0 ? list : null\n\t}\n\treturn null\n}\n\n/**\n * Resolve the \"what now\" card for the record's stage.\n *\n * The title and `after` may name record fields as `{path}` tokens, and may be\n * a list of candidates: the page fills the first whose fields all have a value\n * (`[\"What now? Step 2: {statusPublicLabel|lower}\", \"What now? Handle the case\"]`).\n *\n * @param {{stages?: object, title?: (string|string[])}|null} config The `nextStep` config.\n * @param {object|null} object The record.\n * @param {string} [stageField] Dot-path to the stage.\n * @return {{stage: string, title: (string|string[]), items: Array<{label: string, done: boolean, hint: string}>, after: (string|string[])}|null} The card, or null when this stage declares no checklist.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-next-step-card\n */\nexport function resolveNextStep(config, object, stageField = 'status') {\n\tif (!config || typeof config !== 'object') {\n\t\treturn null\n\t}\n\tconst stage = stageOf(object, config.field || stageField)\n\tconst declared = stageEntry(config.stages, stage)\n\tif (!declared || typeof declared !== 'object' || !Array.isArray(declared.checklist)) {\n\t\treturn null\n\t}\n\tconst items = declared.checklist\n\t\t.filter((item) => item && typeof item === 'object' && typeof item.label === 'string' && item.label !== '')\n\t\t.map((item) => ({\n\t\t\tlabel: item.label,\n\t\t\tdone: isChecklistItemDone(item, object),\n\t\t\thint: typeof item.hint === 'string' ? item.hint : '',\n\t\t}))\n\tif (items.length === 0) {\n\t\treturn null\n\t}\n\treturn {\n\t\tstage,\n\t\ttitle: templateOf(declared.title) || templateOf(config.title) || '',\n\t\titems,\n\t\tafter: templateOf(declared.after) || '',\n\t}\n}\n\n/**\n * Resolve a header pill from the record.\n *\n * A pill with `field` reads it off the record; one without `field` and with\n * `text` is a constant. A count pill (`countFrom`) is resolved by\n * {@link resolveCountPill} once its count is known. `values` limits a field\n * pill to those raw values: a priority pill drawn only for high and urgent.\n *\n * @param {{field?: string, text?: string, colorMap?: object, labels?: object, variant?: string, values?: Array<string>}|null} config The pill config.\n * @param {object|null} object The record.\n * @return {{label: string, colorKey: string, colorMap: object|null, variant: string}|null} What CnStatusBadge needs, or null when the field is empty.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-header-pills\n */\nexport function resolvePill(config, object) {\n\tif (!config || typeof config !== 'object') {\n\t\treturn null\n\t}\n\t// A constant pill (`text`): \"Inwoner\", \"Klant\" (screens-relation-pages).\n\tif ((typeof config.field !== 'string' || config.field === '') && typeof config.text === 'string' && config.text !== '') {\n\t\treturn {\n\t\t\tlabel: config.text,\n\t\t\tcolorKey: config.text,\n\t\t\tcolorMap: config.colorMap && typeof config.colorMap === 'object' ? config.colorMap : null,\n\t\t\tvariant: typeof config.variant === 'string' && config.variant !== '' ? config.variant : 'default',\n\t\t}\n\t}\n\tif (typeof config.field !== 'string' || config.field === '') {\n\t\treturn null\n\t}\n\tconst raw = stageOf(object, config.field)\n\tif (raw === '') {\n\t\treturn null\n\t}\n\tif (Array.isArray(config.values) && !config.values.map(String).includes(raw)) {\n\t\treturn null\n\t}\n\tconst mapped = stageEntry(config.labels, raw)\n\treturn {\n\t\tlabel: typeof mapped === 'string' && mapped !== '' ? mapped : raw,\n\t\tcolorKey: raw,\n\t\tcolorMap: config.colorMap && typeof config.colorMap === 'object' ? config.colorMap : null,\n\t\tvariant: typeof config.variant === 'string' && config.variant !== '' ? config.variant : 'default',\n\t}\n}\n\n/**\n * What a pill takes from the record its `resolve` points at\n * (`resolve.colorField`, `resolve.iconField`): the tone its colour name maps\n * onto (an NL Design System hue or a badge role, see `variantForColor`), which\n * replaces the pill's own `variant` and `colorMap`, and an icon name. An empty\n * colour or icon leaves the pill as declared.\n *\n * @param {{color?: string|null, icon?: string|null}|null|undefined} look The names read off the record.\n * @return {{variant?: string, colorMap?: null, icon?: string}} The keys to lay over the pill.\n * @spec openspec/changes/pill-color-field/specs/pill-color-field/spec.md#requirement-a-pill-takes-its-tone-and-icon-from-the-referenced-record\n */\nexport function pillLook(look) {\n\tconst out = {}\n\tif (!look || typeof look !== 'object') {\n\t\treturn out\n\t}\n\tif (typeof look.color === 'string' && look.color !== '') {\n\t\tout.variant = variantForColor(look.color)\n\t\tout.colorMap = null\n\t}\n\tif (typeof look.icon === 'string' && look.icon !== '') {\n\t\tout.icon = look.icon\n\t}\n\treturn out\n}\n\n/**\n * Resolve a tab's count.\n *\n * `count` (a number) wins. Otherwise `countField` is read off the record: a\n * list counts its items, a number is taken as is. A tab that declares neither\n * takes what is new on it from `@self.unreadCounts[<unreadKey>]` (the key\n * defaults to the tab's `id`, else its `widgetId`) when that is above 0;\n * absent or 0 is no count.\n *\n * @param {{count?: number, countField?: string, unreadKey?: string, id?: string, widgetId?: string}|null} tab The tab declaration.\n * @param {object|null} object The record.\n * @return {number|null} The count, or null when the tab declares none.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-tab-counts-and-overflow\n */\nexport function resolveTabCount(tab, object) {\n\tif (!tab || typeof tab !== 'object') {\n\t\treturn null\n\t}\n\tif (typeof tab.count === 'number' && Number.isFinite(tab.count)) {\n\t\treturn tab.count\n\t}\n\tif (typeof tab.countField !== 'string' || tab.countField === '') {\n\t\tconst counts = object && typeof object === 'object' && object['@self'] && object['@self'].unreadCounts\n\t\tconst key = tab.unreadKey || tab.id || tab.widgetId\n\t\tconst unread = counts && typeof counts === 'object' && typeof key === 'string' ? Number(counts[key]) : 0\n\t\treturn Number.isFinite(unread) && unread > 0 ? unread : null\n\t}\n\tconst value = readPath(object && typeof object === 'object' ? object : {}, tab.countField)\n\tif (Array.isArray(value)) {\n\t\treturn value.length\n\t}\n\tif (value === null || value === undefined || value === '') {\n\t\treturn 0\n\t}\n\tconst number = Number(value)\n\treturn Number.isFinite(number) ? number : null\n}\n\n/**\n * The list a count pill counts (`countFrom`), or null for any other pill.\n *\n * @param {object|null} config The pill config.\n * @return {{register: string, schema: string, filter: object}|null} The list.\n * @spec openspec/changes/screens-relation-pages/specs/relation-pages/spec.md#requirement-a-header-pill-can-be-a-constant-or-a-count\n */\nexport function pillCountSource(config) {\n\tconst from = config && typeof config === 'object' && !config.field ? config.countFrom : null\n\tif (!from || typeof from !== 'object' || typeof from.register !== 'string' || from.register === '' || typeof from.schema !== 'string' || from.schema === '') {\n\t\treturn null\n\t}\n\tconst filter = from.filter && typeof from.filter === 'object' && !Array.isArray(from.filter) ? from.filter : {}\n\treturn { register: from.register, schema: from.schema, filter }\n}\n\n/**\n * A count pill once its count is known: \"1 lopende zaak\", \"2 lopende zaken\".\n * Nothing for a count of 0, an unknown count or a failed one.\n *\n * @param {{countLabel?: {one?: string, other?: string}, colorMap?: object, variant?: string}|null} config The pill config.\n * @param {number|null|undefined} count The count.\n * @param {(text: string) => string} [translate] Applied to the label before `{count}` is filled.\n * @return {{label: string, colorKey: string, colorMap: object|null, variant: string}|null} What CnStatusBadge needs, or null.\n * @spec openspec/changes/screens-relation-pages/specs/relation-pages/spec.md#requirement-a-header-pill-can-be-a-constant-or-a-count\n */\nexport function resolveCountPill(config, count, translate = (text) => text) {\n\tif (!pillCountSource(config) || typeof count !== 'number' || !Number.isFinite(count) || count <= 0) {\n\t\treturn null\n\t}\n\tconst labels = config.countLabel && typeof config.countLabel === 'object' ? config.countLabel : {}\n\tconst template = (count === 1 ? labels.one : labels.other) || labels.other || labels.one || '{count}'\n\tconst label = translate(template).replace(/\\{count\\}/g, String(count))\n\treturn {\n\t\tlabel,\n\t\tcolorKey: '',\n\t\tcolorMap: config.colorMap && typeof config.colorMap === 'object' ? config.colorMap : null,\n\t\tvariant: typeof config.variant === 'string' && config.variant !== '' ? config.variant : 'default',\n\t}\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"detailActionModel.js","sources":["../../../src/utils/detailActionModel.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * detailActionModel: the rules behind a detail page's four action levels and\n * the case surfaces that read the record's stage.\n *\n * 1. the next step: one primary button, chosen by the record's stage,\n * 2. quick actions: at most three always visible buttons,\n * 3. the overflow menu: the rest, in named groups,\n * 4. admin actions: the last group, for admins only.\n *\n * Pure functions, no Vue and no fetch, so CnDetailPage, the widgets and the\n * tests all read one implementation.\n *\n * @module utils/detailActionModel\n */\n\nimport { variantForColor } from './headerFieldChips.js'\nimport { isObjectRowsSpec, objectRowsOf } from './objectRows.js'\nimport { readPath } from './readPath.js'\nimport { evaluateVisibleWhenLocal } from './visibleWhen.js'\n\n/** The most quick actions a page shows. Later entries are dropped. */\nexport const MAX_QUICK_ACTIONS = 3\n\n/**\n * The record's stage, as the string a stage map is keyed on.\n *\n * @param {object|null} object The record.\n * @param {string} [stageField] Dot-path to the stage. Defaults to `status`.\n * @return {string} The stage, or '' when the record has none.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-primary-action-follows-the-stage\n */\nexport function stageOf(object, stageField = 'status') {\n\tif (!object || typeof object !== 'object') {\n\t\treturn ''\n\t}\n\tconst value = readPath(object, stageField || 'status')\n\tif (value === null || value === undefined || typeof value === 'object') {\n\t\treturn ''\n\t}\n\treturn String(value)\n}\n\n/**\n * Look a stage up in a stage-keyed map. An exact key wins; otherwise the\n * match ignores case, because a status is stored as `in_behandeling` in one\n * register and `In_Behandeling` in the next.\n *\n * @param {object|null} map The stage-keyed map.\n * @param {string} stage The stage.\n * @return {unknown} The entry, or undefined.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-primary-action-follows-the-stage\n */\nexport function stageEntry(map, stage) {\n\tif (!map || typeof map !== 'object' || Array.isArray(map) || stage === '') {\n\t\treturn undefined\n\t}\n\tif (Object.hasOwn(map, stage)) {\n\t\treturn map[stage]\n\t}\n\tconst wanted = stage.toLowerCase()\n\tconst key = Object.keys(map).find((candidate) => candidate.toLowerCase() === wanted)\n\treturn key === undefined ? undefined : map[key]\n}\n\n/**\n * Turn a pinned action entry into a descriptor the page can dispatch.\n *\n * An entry is the id of a declared header action, or an action object of its\n * own. An object without an id gets `fallbackId`, since every dispatched\n * action is addressed by id. `{ id, tabs?, notTabs? }` without a label names\n * a declared action and says beside which body tabs it shows (see `onTab`).\n *\n * @param {string|object|null} entry The entry.\n * @param {string} fallbackId Id for an inline action that names none.\n * @return {{id: string, inline: object|null, tabs?: Array<string>, notTabs?: Array<string>}|null} The id, plus the inline definition when the entry carried one.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-quick-actions\n * @spec openspec/changes/detail-actions-per-tab/specs/detail-page/spec.md#requirement-quick-actions-and-the-next-step-card-can-follow-the-open-tab\n */\nexport function normalisePinnedAction(entry, fallbackId) {\n\tif (typeof entry === 'string') {\n\t\treturn entry === '' ? null : { id: entry, inline: null }\n\t}\n\tif (!entry || typeof entry !== 'object' || Array.isArray(entry)) {\n\t\treturn null\n\t}\n\tconst scoped = Array.isArray(entry.tabs) || Array.isArray(entry.notTabs)\n\tif (typeof entry.label !== 'string' || entry.label === '') {\n\t\tif (!scoped || typeof entry.id !== 'string' || entry.id === '') {\n\t\t\treturn null\n\t\t}\n\t\treturn { id: entry.id, inline: null, tabs: entry.tabs, notTabs: entry.notTabs }\n\t}\n\tconst id = typeof entry.id === 'string' && entry.id !== '' ? entry.id : fallbackId\n\tconst { tabs, notTabs, ...action } = entry\n\tconst pinned = { id, inline: { ...action, id } }\n\treturn scoped ? { ...pinned, tabs, notTabs } : pinned\n}\n\n/**\n * Whether an entry belongs beside the open body tab: one with `tabs` shows\n * only while one of them is open, one with `notTabs` stands aside while one\n * of those is open, one with neither shows beside every tab.\n *\n * @param {object|null} entry The entry, carrying `tabs` / `notTabs`.\n * @param {string} activeTab The open body tab's id.\n * @return {boolean}\n * @spec openspec/changes/detail-actions-per-tab/specs/detail-page/spec.md#requirement-quick-actions-and-the-next-step-card-can-follow-the-open-tab\n */\nexport function onTab(entry, activeTab) {\n\tif (!entry) {\n\t\treturn true\n\t}\n\tif (Array.isArray(entry.notTabs) && entry.notTabs.map((id) => String(id)).includes(activeTab)) {\n\t\treturn false\n\t}\n\tif (!Array.isArray(entry.tabs) || entry.tabs.length === 0) {\n\t\treturn true\n\t}\n\treturn entry.tabs.map((id) => String(id)).includes(activeTab)\n}\n\n/**\n * Split menu entries into the groups the overflow menu draws.\n *\n * Ungrouped entries come first, under no caption. Named groups follow in the\n * order they first appear. Admin only entries are dropped for everyone else\n * and form the last group for admins, whatever `group` they also name.\n *\n * `adminOnly` hides a control. It is never an authorization decision: the\n * endpoint behind the action decides who may call it.\n *\n * @param {Array<object>} entries Menu-ready entries, each with an `id`.\n * @param {object} actionsById The declared actions by id, carrying `group` / `adminOnly`.\n * @param {{isAdmin?: boolean, adminLabel?: string}} [options] Who is looking, and what the admin group is called.\n * @return {Array<{key: string, label: string, entries: Array<object>}>} The non-empty groups, in render order.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-grouped-and-admin-only-menu-actions\n */\nexport function groupMenuEntries(entries, actionsById = {}, options = {}) {\n\tconst isAdmin = options.isAdmin === true\n\tconst plain = { key: '', label: '', entries: [] }\n\tconst named = []\n\tconst admin = { key: 'cn-admin', label: options.adminLabel || '', entries: [] }\n\tfor (const entry of Array.isArray(entries) ? entries : []) {\n\t\tconst declared = (entry && actionsById[entry.id]) || {}\n\t\tif (declared.adminOnly === true) {\n\t\t\tif (isAdmin) {\n\t\t\t\tadmin.entries.push(entry)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tconst label = typeof declared.group === 'string' ? declared.group.trim() : ''\n\t\tif (label === '') {\n\t\t\tplain.entries.push(entry)\n\t\t\tcontinue\n\t\t}\n\t\tlet group = named.find((candidate) => candidate.label === label)\n\t\tif (!group) {\n\t\t\tgroup = { key: `cn-group-${named.length}`, label, entries: [] }\n\t\t\tnamed.push(group)\n\t\t}\n\t\tgroup.entries.push(entry)\n\t}\n\treturn [plain, ...named, admin].filter((group) => group.entries.length > 0)\n}\n\n/**\n * Whether one checklist item is done for this record.\n *\n * `done` (a literal) wins, then `doneWhen` (a local visibleWhen condition),\n * then `doneField` (truthy, and for a list: not empty).\n *\n * @param {object} item The checklist item.\n * @param {object|null} object The record.\n * @return {boolean} True when the item is done.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-next-step-card\n */\nexport function isChecklistItemDone(item, object) {\n\tif (!item || typeof item !== 'object') {\n\t\treturn false\n\t}\n\tif (typeof item.done === 'boolean') {\n\t\treturn item.done\n\t}\n\tconst data = object && typeof object === 'object' ? object : {}\n\tif (item.doneWhen && typeof item.doneWhen === 'object') {\n\t\treturn evaluateVisibleWhenLocal(item.doneWhen, data)\n\t}\n\tif (typeof item.doneField === 'string' && item.doneField !== '') {\n\t\tconst value = readPath(data, item.doneField)\n\t\treturn Array.isArray(value) ? value.length > 0 : Boolean(value)\n\t}\n\treturn false\n}\n\n/**\n * A text or its candidates: a string, or a list of strings to fill in order.\n *\n * @param {unknown} value The configured value.\n * @return {string|string[]|null} The text or the candidates, or null.\n */\nfunction templateOf(value) {\n\tif (typeof value === 'string' && value !== '') {\n\t\treturn value\n\t}\n\tif (Array.isArray(value)) {\n\t\tconst list = value.filter((item) => typeof item === 'string' && item !== '')\n\t\treturn list.length > 0 ? list : null\n\t}\n\treturn null\n}\n\n/**\n * Resolve the \"what now\" card for the record's stage.\n *\n * The title and `after` may name record fields as `{path}` tokens, and may be\n * a list of candidates: the page fills the first whose fields all have a value\n * (`[\"What now? Step 2: {statusPublicLabel|lower}\", \"What now? Handle the case\"]`).\n *\n * @param {{stages?: object, title?: (string|string[])}|null} config The `nextStep` config.\n * @param {object|null} object The record.\n * @param {string} [stageField] Dot-path to the stage.\n * @return {{stage: string, title: (string|string[]), items: Array<{label: string, done: boolean, hint: string}>, after: (string|string[])}|null} The card, or null when this stage declares no checklist.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-next-step-card\n */\nexport function resolveNextStep(config, object, stageField = 'status') {\n\tif (!config || typeof config !== 'object') {\n\t\treturn null\n\t}\n\tconst stage = stageOf(object, config.field || stageField)\n\tconst declared = stageEntry(config.stages, stage)\n\tif (!declared || typeof declared !== 'object' || !Array.isArray(declared.checklist)) {\n\t\treturn null\n\t}\n\tconst items = declared.checklist\n\t\t.filter((item) => item && typeof item === 'object' && typeof item.label === 'string' && item.label !== '')\n\t\t.map((item) => ({\n\t\t\tlabel: item.label,\n\t\t\tdone: isChecklistItemDone(item, object),\n\t\t\thint: typeof item.hint === 'string' ? item.hint : '',\n\t\t}))\n\tif (items.length === 0) {\n\t\treturn null\n\t}\n\treturn {\n\t\tstage,\n\t\ttitle: templateOf(declared.title) || templateOf(config.title) || '',\n\t\titems,\n\t\tafter: templateOf(declared.after) || '',\n\t}\n}\n\n/**\n * Resolve a header pill from the record.\n *\n * A pill with `field` reads it off the record; one without `field` and with\n * `text` is a constant. A count pill (`countFrom`) is resolved by\n * {@link resolveCountPill} once its count is known. `values` limits a field\n * pill to those raw values: a priority pill drawn only for high and urgent.\n *\n * @param {{field?: string, text?: string, colorMap?: object, labels?: object, variant?: string, values?: Array<string>}|null} config The pill config.\n * @param {object|null} object The record.\n * @return {{label: string, colorKey: string, colorMap: object|null, variant: string}|null} What CnStatusBadge needs, or null when the field is empty.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-header-pills\n */\nexport function resolvePill(config, object) {\n\tif (!config || typeof config !== 'object') {\n\t\treturn null\n\t}\n\t// A constant pill (`text`): \"Inwoner\", \"Klant\" (screens-relation-pages).\n\tif ((typeof config.field !== 'string' || config.field === '') && typeof config.text === 'string' && config.text !== '') {\n\t\treturn {\n\t\t\tlabel: config.text,\n\t\t\tcolorKey: config.text,\n\t\t\tcolorMap: config.colorMap && typeof config.colorMap === 'object' ? config.colorMap : null,\n\t\t\tvariant: typeof config.variant === 'string' && config.variant !== '' ? config.variant : 'default',\n\t\t}\n\t}\n\tif (typeof config.field !== 'string' || config.field === '') {\n\t\treturn null\n\t}\n\tconst raw = stageOf(object, config.field)\n\tif (raw === '') {\n\t\treturn null\n\t}\n\tif (Array.isArray(config.values) && !config.values.map(String).includes(raw)) {\n\t\treturn null\n\t}\n\tconst mapped = stageEntry(config.labels, raw)\n\treturn {\n\t\tlabel: typeof mapped === 'string' && mapped !== '' ? mapped : raw,\n\t\tcolorKey: raw,\n\t\tcolorMap: config.colorMap && typeof config.colorMap === 'object' ? config.colorMap : null,\n\t\tvariant: typeof config.variant === 'string' && config.variant !== '' ? config.variant : 'default',\n\t}\n}\n\n/**\n * What a pill takes from the record its `resolve` points at\n * (`resolve.colorField`, `resolve.iconField`): the tone its colour name maps\n * onto (an NL Design System hue or a badge role, see `variantForColor`), which\n * replaces the pill's own `variant` and `colorMap`, and an icon name. An empty\n * colour or icon leaves the pill as declared.\n *\n * @param {{color?: string|null, icon?: string|null}|null|undefined} look The names read off the record.\n * @return {{variant?: string, colorMap?: null, icon?: string}} The keys to lay over the pill.\n * @spec openspec/changes/pill-color-field/specs/pill-color-field/spec.md#requirement-a-pill-takes-its-tone-and-icon-from-the-referenced-record\n */\nexport function pillLook(look) {\n\tconst out = {}\n\tif (!look || typeof look !== 'object') {\n\t\treturn out\n\t}\n\tif (typeof look.color === 'string' && look.color !== '') {\n\t\tout.variant = variantForColor(look.color)\n\t\tout.colorMap = null\n\t}\n\tif (typeof look.icon === 'string' && look.icon !== '') {\n\t\tout.icon = look.icon\n\t}\n\treturn out\n}\n\n/**\n * Resolve a tab's count.\n *\n * `count` (a number) wins. Otherwise `countField` is read off the record: a\n * list counts its items, a number is taken as is. A tab that declares neither\n * takes what is new on it from `@self.unreadCounts[<unreadKey>]` (the key\n * defaults to the tab's `id`, else its `widgetId`) when that is above 0;\n * absent or 0 is no count.\n *\n * @param {{count?: number, countField?: string, unreadKey?: string, id?: string, widgetId?: string}|null} tab The tab declaration.\n * @param {object|null} object The record.\n * @return {number|null} The count, or null when the tab declares none.\n * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-tab-counts-and-overflow\n * @spec openspec/changes/record-list-object-rows/specs/record-list/spec.md#requirement-a-tab-can-count-the-rows-its-record-holds\n */\nexport function resolveTabCount(tab, object) {\n\tif (!tab || typeof tab !== 'object') {\n\t\treturn null\n\t}\n\tif (typeof tab.count === 'number' && Number.isFinite(tab.count)) {\n\t\treturn tab.count\n\t}\n\t// `countObjectRows`: the rows the record holds where it points, as a record list's `objectRows`.\n\tif (isObjectRowsSpec(tab.countObjectRows)) {\n\t\treturn objectRowsOf(object, tab.countObjectRows).length\n\t}\n\tif (typeof tab.countField !== 'string' || tab.countField === '') {\n\t\tconst counts = object && typeof object === 'object' && object['@self'] && object['@self'].unreadCounts\n\t\tconst key = tab.unreadKey || tab.id || tab.widgetId\n\t\tconst unread = counts && typeof counts === 'object' && typeof key === 'string' ? Number(counts[key]) : 0\n\t\treturn Number.isFinite(unread) && unread > 0 ? unread : null\n\t}\n\tconst value = readPath(object && typeof object === 'object' ? object : {}, tab.countField)\n\tif (Array.isArray(value)) {\n\t\treturn value.length\n\t}\n\tif (value === null || value === undefined || value === '') {\n\t\treturn 0\n\t}\n\tconst number = Number(value)\n\treturn Number.isFinite(number) ? number : null\n}\n\n/**\n * The list a count pill counts (`countFrom`), or null for any other pill.\n *\n * @param {object|null} config The pill config.\n * @return {{register: string, schema: string, filter: object}|null} The list.\n * @spec openspec/changes/screens-relation-pages/specs/relation-pages/spec.md#requirement-a-header-pill-can-be-a-constant-or-a-count\n */\nexport function pillCountSource(config) {\n\tconst from = config && typeof config === 'object' && !config.field ? config.countFrom : null\n\tif (!from || typeof from !== 'object' || typeof from.register !== 'string' || from.register === '' || typeof from.schema !== 'string' || from.schema === '') {\n\t\treturn null\n\t}\n\tconst filter = from.filter && typeof from.filter === 'object' && !Array.isArray(from.filter) ? from.filter : {}\n\treturn { register: from.register, schema: from.schema, filter }\n}\n\n/**\n * A count pill once its count is known: \"1 lopende zaak\", \"2 lopende zaken\".\n * Nothing for a count of 0, an unknown count or a failed one.\n *\n * @param {{countLabel?: {one?: string, other?: string}, colorMap?: object, variant?: string}|null} config The pill config.\n * @param {number|null|undefined} count The count.\n * @param {(text: string) => string} [translate] Applied to the label before `{count}` is filled.\n * @return {{label: string, colorKey: string, colorMap: object|null, variant: string}|null} What CnStatusBadge needs, or null.\n * @spec openspec/changes/screens-relation-pages/specs/relation-pages/spec.md#requirement-a-header-pill-can-be-a-constant-or-a-count\n */\nexport function resolveCountPill(config, count, translate = (text) => text) {\n\tif (!pillCountSource(config) || typeof count !== 'number' || !Number.isFinite(count) || count <= 0) {\n\t\treturn null\n\t}\n\tconst labels = config.countLabel && typeof config.countLabel === 'object' ? config.countLabel : {}\n\tconst template = (count === 1 ? labels.one : labels.other) || labels.other || labels.one || '{count}'\n\tconst label = translate(template).replace(/\\{count\\}/g, String(count))\n\treturn {\n\t\tlabel,\n\t\tcolorKey: '',\n\t\tcolorMap: config.colorMap && typeof config.colorMap === 'object' ? config.colorMap : null,\n\t\tvariant: typeof config.variant === 'string' && config.variant !== '' ? config.variant : 'default',\n\t}\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -74,6 +74,12 @@ function splitViewsIntoTabs(views, tabIds) {
|
|
|
74
74
|
* One saved view as a tab for CnQuickFilterBar, so a lens renders through the
|
|
75
75
|
* tab strip the page already has rather than a second one beside it.
|
|
76
76
|
*
|
|
77
|
+
* Its filter is the view's own `filters`/`filter`, else what an OpenRegister
|
|
78
|
+
* view (and a default view) keeps in its query: `query.filters` with the
|
|
79
|
+
* locked conditions of `query.overrides.lockedFilters` under them. Reading
|
|
80
|
+
* only the first left a stored view with no filter, so every view in the
|
|
81
|
+
* side panel counted the whole list.
|
|
82
|
+
*
|
|
77
83
|
* @param {object} view A saved view.
|
|
78
84
|
* @return {{id: string, label: string, filter: object}}
|
|
79
85
|
*/
|
|
@@ -81,10 +87,23 @@ function viewAsTab(view) {
|
|
|
81
87
|
return {
|
|
82
88
|
id: viewIdOf(view),
|
|
83
89
|
label: (view && (view.title || view.name)) || viewIdOf(view),
|
|
84
|
-
filter: (view && (view.filters || view.filter)) ||
|
|
90
|
+
filter: (view && (view.filters || view.filter)) || queryFilterOf(view),
|
|
85
91
|
}
|
|
86
92
|
}
|
|
87
93
|
|
|
94
|
+
/**
|
|
95
|
+
* The conditions a stored view's query applies: its locked filters, then its filters.
|
|
96
|
+
*
|
|
97
|
+
* @param {object} view A saved view.
|
|
98
|
+
* @return {object}
|
|
99
|
+
*/
|
|
100
|
+
function queryFilterOf(view) {
|
|
101
|
+
const query = view && view.query && typeof view.query === 'object' ? view.query : {};
|
|
102
|
+
const plain = (value) => (value && typeof value === 'object' && !Array.isArray(value) ? value : {});
|
|
103
|
+
const locked = plain(query.overrides && query.overrides.lockedFilters);
|
|
104
|
+
return { ...locked, ...plain(query.filters) }
|
|
105
|
+
}
|
|
106
|
+
|
|
88
107
|
/**
|
|
89
108
|
* The teams this person is treated as having claimed.
|
|
90
109
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listLenses.js","sources":["../../../src/utils/listLenses.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V. <info@conduction.nl>\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\n/**\n * The filter token a lens uses to mean \"the teams this person claimed\".\n *\n * @type {string}\n */\nexport const MY_TEAMS_TOKEN = '@myTeams'\n\n/**\n * The filter token a lens uses to mean \"the subjects this person claimed\".\n *\n * @type {string}\n */\nexport const MY_SUBJECTS_TOKEN = '@mySubjects'\n\n/**\n * The id of a saved view, in either spelling OpenRegister answers with.\n *\n * @param {object} view A saved view.\n * @return {string} The id, or ''.\n */\nexport function viewIdOf(view) {\n\tif (!view || typeof view !== 'object') {\n\t\treturn ''\n\t}\n\tif (view.id !== undefined && view.id !== null && view.id !== '') {\n\t\treturn String(view.id)\n\t}\n\treturn view.uuid !== undefined && view.uuid !== null ? String(view.uuid) : ''\n}\n\n/**\n * Split a page's saved views into the ones it named as tabs and the ones that\n * stay in the views control.\n *\n * Which side wins on what:\n *\n * - The VIEWS decide membership. A tab exists only because a view exists; a\n * `tabIds` entry naming a view that is gone produces no tab, rather than a\n * tab that opens nothing.\n * - The PAGE decides presentation. `tabIds` is the tab order, and a view named\n * there is removed from the control, so the same lens is never offered in\n * two places at once. Opening one of two entries that do the same thing is\n * how a person learns a page is lying to them about what it has.\n *\n * @param {Array<object>} views The page's saved views.\n * @param {Array<string>} tabIds The view ids the page names as tabs, in order.\n * @return {{tabs: Array<object>, control: Array<object>}}\n */\nexport function splitViewsIntoTabs(views, tabIds) {\n\tconst all = Array.isArray(views) ? views : []\n\tconst wanted = Array.isArray(tabIds) ? tabIds.map(String) : []\n\tif (wanted.length === 0) {\n\t\treturn { tabs: [], control: all }\n\t}\n\tconst byId = new Map(all.map((view) => [viewIdOf(view), view]))\n\tconst tabs = []\n\tconst claimed = new Set()\n\twanted.forEach((id) => {\n\t\tconst view = byId.get(id)\n\t\tif (view && !claimed.has(id)) {\n\t\t\ttabs.push(view)\n\t\t\tclaimed.add(id)\n\t\t}\n\t})\n\treturn { tabs, control: all.filter((view) => !claimed.has(viewIdOf(view))) }\n}\n\n/**\n * One saved view as a tab for CnQuickFilterBar, so a lens renders through the\n * tab strip the page already has rather than a second one beside it.\n *\n * @param {object} view A saved view.\n * @return {{id: string, label: string, filter: object}}\n */\nexport function viewAsTab(view) {\n\treturn {\n\t\tid: viewIdOf(view),\n\t\tlabel: (view && (view.title || view.name)) || viewIdOf(view),\n\t\tfilter: (view && (view.filters || view.filter)) || {},\n\t}\n}\n\n/**\n * The teams this person is treated as having claimed.\n *\n * The instance decides membership: `offered` is the set of teams this person\n * may claim at all. The person decides which of those they claim, and their\n * stored answer is read by walking `offered`, so a team they claimed before it\n * was taken away from them is passed over rather than honoured. A preference\n * is a choice among what exists; it is not a second place a membership can be\n * granted.\n *\n * A stored value that is not a list is someone who has never chosen, which\n * claims nothing.\n *\n * @param {Array<string|object>} offered The teams this person may claim.\n * @param {(Array<string>|null|undefined)} stored The teams they stored.\n * @return {string[]} The claimed team ids, in the offered order.\n */\nexport function resolveClaimedTeams(offered, stored) {\n\tconst available = (Array.isArray(offered) ? offered : [])\n\t\t.map((team) => (typeof team === 'string' ? team : (team && team.id !== undefined ? String(team.id) : '')))\n\t\t.filter((id) => id !== '')\n\tif (!Array.isArray(stored)) {\n\t\treturn []\n\t}\n\tconst wanted = new Set(stored.map(String))\n\treturn available.filter((id) => wanted.has(id))\n}\n\n/**\n * Resolve the claimed-teams and claimed-subjects tokens inside a lens filter.\n *\n * A lens that says \"my teams\" and then shows every team would be a label\n * stating one rule while the fetch ran another. So an unresolved token narrows\n * to nothing and says so through `narrowsToNothing`, and the page can tell the\n * person they have claimed no teams rather than hand them the whole list under\n * a heading that says otherwise.\n *\n * @param {object} filter The lens filter.\n * @param {object} claims The person's claims.\n * @param {string[]} [claims.teams] The claimed team ids.\n * @param {string[]} [claims.subjects] The claimed subject ids.\n * @return {{filter: object, narrowsToNothing: boolean, tokens: string[]}}\n */\nexport function resolveClaimTokens(filter, { teams = [], subjects = [] } = {}) {\n\tconst source = filter && typeof filter === 'object' ? filter : {}\n\tconst out = {}\n\tconst tokens = []\n\tlet narrowsToNothing = false\n\tObject.entries(source).forEach(([key, value]) => {\n\t\tif (value === MY_TEAMS_TOKEN || value === MY_SUBJECTS_TOKEN) {\n\t\t\tconst claimed = value === MY_TEAMS_TOKEN ? teams : subjects\n\t\t\ttokens.push(value)\n\t\t\tout[key] = [...claimed]\n\t\t\tif (claimed.length === 0) {\n\t\t\t\tnarrowsToNothing = true\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tout[key] = value\n\t})\n\treturn { filter: out, narrowsToNothing, tokens }\n}\n\n/**\n * A navigation entry per record type, with the count the list confirmed.\n *\n * A count nobody confirmed is left off the entry rather than shown as the last\n * one anybody saw. A stale number beside a list is worse than no number: it is\n * read as fact and acted on, and nothing on the screen says how old it is.\n *\n * @param {Array<object>} types The declared record types: `{ id, label, page }`.\n * @param {object} counts The counts by type id. A type absent from this map, or\n * carrying a value that is not a finite number, gets no count.\n * @return {Array<{id: string, label: string, page: string, count: (number|null)}>}\n */\nexport function recordTypeNavEntries(types, counts = {}) {\n\tconst declared = Array.isArray(types) ? types : []\n\tconst confirmed = counts && typeof counts === 'object' ? counts : {}\n\treturn declared\n\t\t.filter((type) => type && typeof type.id === 'string' && type.id !== '')\n\t\t.map((type) => {\n\t\t\tconst raw = confirmed[type.id]\n\t\t\tconst count = typeof raw === 'number' && Number.isFinite(raw) ? raw : null\n\t\t\treturn {\n\t\t\t\tid: type.id,\n\t\t\t\tlabel: type.label || type.id,\n\t\t\t\tpage: type.page || type.id,\n\t\t\t\tcount,\n\t\t\t}\n\t\t})\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"listLenses.js","sources":["../../../src/utils/listLenses.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V. <info@conduction.nl>\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\n/**\n * The filter token a lens uses to mean \"the teams this person claimed\".\n *\n * @type {string}\n */\nexport const MY_TEAMS_TOKEN = '@myTeams'\n\n/**\n * The filter token a lens uses to mean \"the subjects this person claimed\".\n *\n * @type {string}\n */\nexport const MY_SUBJECTS_TOKEN = '@mySubjects'\n\n/**\n * The id of a saved view, in either spelling OpenRegister answers with.\n *\n * @param {object} view A saved view.\n * @return {string} The id, or ''.\n */\nexport function viewIdOf(view) {\n\tif (!view || typeof view !== 'object') {\n\t\treturn ''\n\t}\n\tif (view.id !== undefined && view.id !== null && view.id !== '') {\n\t\treturn String(view.id)\n\t}\n\treturn view.uuid !== undefined && view.uuid !== null ? String(view.uuid) : ''\n}\n\n/**\n * Split a page's saved views into the ones it named as tabs and the ones that\n * stay in the views control.\n *\n * Which side wins on what:\n *\n * - The VIEWS decide membership. A tab exists only because a view exists; a\n * `tabIds` entry naming a view that is gone produces no tab, rather than a\n * tab that opens nothing.\n * - The PAGE decides presentation. `tabIds` is the tab order, and a view named\n * there is removed from the control, so the same lens is never offered in\n * two places at once. Opening one of two entries that do the same thing is\n * how a person learns a page is lying to them about what it has.\n *\n * @param {Array<object>} views The page's saved views.\n * @param {Array<string>} tabIds The view ids the page names as tabs, in order.\n * @return {{tabs: Array<object>, control: Array<object>}}\n */\nexport function splitViewsIntoTabs(views, tabIds) {\n\tconst all = Array.isArray(views) ? views : []\n\tconst wanted = Array.isArray(tabIds) ? tabIds.map(String) : []\n\tif (wanted.length === 0) {\n\t\treturn { tabs: [], control: all }\n\t}\n\tconst byId = new Map(all.map((view) => [viewIdOf(view), view]))\n\tconst tabs = []\n\tconst claimed = new Set()\n\twanted.forEach((id) => {\n\t\tconst view = byId.get(id)\n\t\tif (view && !claimed.has(id)) {\n\t\t\ttabs.push(view)\n\t\t\tclaimed.add(id)\n\t\t}\n\t})\n\treturn { tabs, control: all.filter((view) => !claimed.has(viewIdOf(view))) }\n}\n\n/**\n * One saved view as a tab for CnQuickFilterBar, so a lens renders through the\n * tab strip the page already has rather than a second one beside it.\n *\n * Its filter is the view's own `filters`/`filter`, else what an OpenRegister\n * view (and a default view) keeps in its query: `query.filters` with the\n * locked conditions of `query.overrides.lockedFilters` under them. Reading\n * only the first left a stored view with no filter, so every view in the\n * side panel counted the whole list.\n *\n * @param {object} view A saved view.\n * @return {{id: string, label: string, filter: object}}\n */\nexport function viewAsTab(view) {\n\treturn {\n\t\tid: viewIdOf(view),\n\t\tlabel: (view && (view.title || view.name)) || viewIdOf(view),\n\t\tfilter: (view && (view.filters || view.filter)) || queryFilterOf(view),\n\t}\n}\n\n/**\n * The conditions a stored view's query applies: its locked filters, then its filters.\n *\n * @param {object} view A saved view.\n * @return {object}\n */\nfunction queryFilterOf(view) {\n\tconst query = view && view.query && typeof view.query === 'object' ? view.query : {}\n\tconst plain = (value) => (value && typeof value === 'object' && !Array.isArray(value) ? value : {})\n\tconst locked = plain(query.overrides && query.overrides.lockedFilters)\n\treturn { ...locked, ...plain(query.filters) }\n}\n\n/**\n * The teams this person is treated as having claimed.\n *\n * The instance decides membership: `offered` is the set of teams this person\n * may claim at all. The person decides which of those they claim, and their\n * stored answer is read by walking `offered`, so a team they claimed before it\n * was taken away from them is passed over rather than honoured. A preference\n * is a choice among what exists; it is not a second place a membership can be\n * granted.\n *\n * A stored value that is not a list is someone who has never chosen, which\n * claims nothing.\n *\n * @param {Array<string|object>} offered The teams this person may claim.\n * @param {(Array<string>|null|undefined)} stored The teams they stored.\n * @return {string[]} The claimed team ids, in the offered order.\n */\nexport function resolveClaimedTeams(offered, stored) {\n\tconst available = (Array.isArray(offered) ? offered : [])\n\t\t.map((team) => (typeof team === 'string' ? team : (team && team.id !== undefined ? String(team.id) : '')))\n\t\t.filter((id) => id !== '')\n\tif (!Array.isArray(stored)) {\n\t\treturn []\n\t}\n\tconst wanted = new Set(stored.map(String))\n\treturn available.filter((id) => wanted.has(id))\n}\n\n/**\n * Resolve the claimed-teams and claimed-subjects tokens inside a lens filter.\n *\n * A lens that says \"my teams\" and then shows every team would be a label\n * stating one rule while the fetch ran another. So an unresolved token narrows\n * to nothing and says so through `narrowsToNothing`, and the page can tell the\n * person they have claimed no teams rather than hand them the whole list under\n * a heading that says otherwise.\n *\n * @param {object} filter The lens filter.\n * @param {object} claims The person's claims.\n * @param {string[]} [claims.teams] The claimed team ids.\n * @param {string[]} [claims.subjects] The claimed subject ids.\n * @return {{filter: object, narrowsToNothing: boolean, tokens: string[]}}\n */\nexport function resolveClaimTokens(filter, { teams = [], subjects = [] } = {}) {\n\tconst source = filter && typeof filter === 'object' ? filter : {}\n\tconst out = {}\n\tconst tokens = []\n\tlet narrowsToNothing = false\n\tObject.entries(source).forEach(([key, value]) => {\n\t\tif (value === MY_TEAMS_TOKEN || value === MY_SUBJECTS_TOKEN) {\n\t\t\tconst claimed = value === MY_TEAMS_TOKEN ? teams : subjects\n\t\t\ttokens.push(value)\n\t\t\tout[key] = [...claimed]\n\t\t\tif (claimed.length === 0) {\n\t\t\t\tnarrowsToNothing = true\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tout[key] = value\n\t})\n\treturn { filter: out, narrowsToNothing, tokens }\n}\n\n/**\n * A navigation entry per record type, with the count the list confirmed.\n *\n * A count nobody confirmed is left off the entry rather than shown as the last\n * one anybody saw. A stale number beside a list is worse than no number: it is\n * read as fact and acted on, and nothing on the screen says how old it is.\n *\n * @param {Array<object>} types The declared record types: `{ id, label, page }`.\n * @param {object} counts The counts by type id. A type absent from this map, or\n * carrying a value that is not a finite number, gets no count.\n * @return {Array<{id: string, label: string, page: string, count: (number|null)}>}\n */\nexport function recordTypeNavEntries(types, counts = {}) {\n\tconst declared = Array.isArray(types) ? types : []\n\tconst confirmed = counts && typeof counts === 'object' ? counts : {}\n\treturn declared\n\t\t.filter((type) => type && typeof type.id === 'string' && type.id !== '')\n\t\t.map((type) => {\n\t\t\tconst raw = confirmed[type.id]\n\t\t\tconst count = typeof raw === 'number' && Number.isFinite(raw) ? raw : null\n\t\t\treturn {\n\t\t\t\tid: type.id,\n\t\t\t\tlabel: type.label || type.id,\n\t\t\t\tpage: type.page || type.id,\n\t\t\t\tcount,\n\t\t\t}\n\t\t})\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { translate } from '@nextcloud/l10n';
|
|
2
|
+
import { readPath } from './readPath.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
@@ -176,5 +177,82 @@ function kindCode(kind) {
|
|
|
176
177
|
return String(kind?.code || kind?.key || '')
|
|
177
178
|
}
|
|
178
179
|
|
|
179
|
-
|
|
180
|
+
/**
|
|
181
|
+
* Write a value at a dotted path, creating the objects on the way.
|
|
182
|
+
*
|
|
183
|
+
* @param {object} target The object written into.
|
|
184
|
+
* @param {string} path The dotted path (`name.surname`).
|
|
185
|
+
* @param {unknown} value The value.
|
|
186
|
+
* @return {void}
|
|
187
|
+
*/
|
|
188
|
+
function writePath(target, path, value) {
|
|
189
|
+
const keys = String(path).split('.').filter((key) => key !== '');
|
|
190
|
+
let node = target;
|
|
191
|
+
keys.slice(0, -1).forEach((key) => {
|
|
192
|
+
if (!node[key] || typeof node[key] !== 'object') {
|
|
193
|
+
node[key] = {};
|
|
194
|
+
}
|
|
195
|
+
node = node[key];
|
|
196
|
+
});
|
|
197
|
+
if (keys.length > 0) {
|
|
198
|
+
node[keys[keys.length - 1]] = value;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* The record a new party is saved as, from the fields a host declares.
|
|
204
|
+
*
|
|
205
|
+
* Each field `{ key, path?, address? }` writes its trimmed value at `path`
|
|
206
|
+
* (default `key`); a field with `address: { path, kind, type }` instead adds
|
|
207
|
+
* `{ kind, type, value }` to the list at that path, the shape OpenRegister's
|
|
208
|
+
* party model reads as the party's addresses. `compose` names the paths a
|
|
209
|
+
* derived field joins with a space, skipping the empty ones
|
|
210
|
+
* (`{ displayName: ["name.givenNames", "name.namePrefix", "name.surname"] }`).
|
|
211
|
+
* A field of `type: "integer"` is saved as a number when it reads as one.
|
|
212
|
+
* An empty value is left out.
|
|
213
|
+
*
|
|
214
|
+
* @param {{fields?: Array<object>, compose?: Record<string, Array<string>>}} create The declaration.
|
|
215
|
+
* @param {Record<string, string>} values The values by field key.
|
|
216
|
+
* @return {object} The record.
|
|
217
|
+
* @spec openspec/changes/object-parties-manage/specs/record-widgets/spec.md#requirement-the-parties-widget-can-add-and-remove-parties
|
|
218
|
+
*/
|
|
219
|
+
function newPartyRecord(create, values) {
|
|
220
|
+
const record = {};
|
|
221
|
+
for (const field of Array.isArray(create?.fields) ? create.fields : []) {
|
|
222
|
+
const value = String(values?.[field?.key] ?? '').trim();
|
|
223
|
+
if (!field || !field.key || value === '') {
|
|
224
|
+
continue
|
|
225
|
+
}
|
|
226
|
+
if (field.address && field.address.path) {
|
|
227
|
+
const list = readPath(record, field.address.path);
|
|
228
|
+
const entry = { kind: field.address.kind || 'correspondence', type: field.address.type || 'email', value };
|
|
229
|
+
writePath(record, field.address.path, [...(Array.isArray(list) ? list : []), entry]);
|
|
230
|
+
continue
|
|
231
|
+
}
|
|
232
|
+
writePath(record, field.path || field.key, field.type === 'integer' && /^-?\d+$/.test(value) ? Number(value) : value);
|
|
233
|
+
}
|
|
234
|
+
for (const [target, paths] of Object.entries(create?.compose && typeof create.compose === 'object' ? create.compose : {})) {
|
|
235
|
+
const joined = (Array.isArray(paths) ? paths : [])
|
|
236
|
+
.map((path) => String(readPath(record, path) ?? '').trim())
|
|
237
|
+
.filter((part) => part !== '')
|
|
238
|
+
.join(' ');
|
|
239
|
+
if (joined !== '') {
|
|
240
|
+
writePath(record, target, joined);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return record
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* The uuid a create answered with: `id`, `uuid` or `@self.id`.
|
|
248
|
+
*
|
|
249
|
+
* @param {object} saved The saved object.
|
|
250
|
+
* @return {string} The uuid, or ''.
|
|
251
|
+
* @spec openspec/changes/object-parties-manage/specs/record-widgets/spec.md#requirement-the-parties-widget-can-add-and-remove-parties
|
|
252
|
+
*/
|
|
253
|
+
function savedUuid(saved) {
|
|
254
|
+
return String(saved?.['@self']?.id || saved?.uuid || saved?.id || '')
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export { documentsOfParty, indicatorVerdict, indicatorsOf, kindCode, newPartyRecord, partiesInOrder, representedByMap, roleLabel, rolesInOrder, savedUuid };
|
|
180
258
|
//# sourceMappingURL=objectParties.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"objectParties.js","sources":["../../../src/utils/objectParties.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * objectParties — reading the parties of a record as OpenRegister's party\n * model answers them (`GET .../objects/{register}/{schema}/{id}/parties`:\n * `{ primary, roles, kinds, byRole, results }`, and `GET .../parties/{uuid}`\n * for one party with its indicators).\n *\n * Pure functions, so CnObjectPartiesWidget and its tests read one shape.\n *\n * @module utils/objectParties\n */\n\nimport { translate as t } from '@nextcloud/l10n'\n\n/**\n * What a role is called: the app's own word (`roleLabels`), else the label\n * the listing declares, else the key. `other` is a party with no role.\n *\n * @param {string} key The role key.\n * @param {Array<{key: string, label?: string}>} roles The roles the listing declares.\n * @param {Record<string, string>} [roleLabels] The app's words, by key.\n * @return {string} The label.\n * @spec openspec/changes/dq-abstract-record-widgets/specs/record-widgets/spec.md#requirement-a-record-shows-its-parties-by-role\n */\nexport function roleLabel(key, roles, roleLabels = {}) {\n\tif (roleLabels && typeof roleLabels[key] === 'string' && roleLabels[key] !== '') {\n\t\treturn roleLabels[key]\n\t}\n\tconst declared = (roles || []).find((role) => role && role.key === key)\n\tif (declared && declared.label) {\n\t\treturn declared.label\n\t}\n\treturn key === 'other' ? t('nextcloud-vue', 'No role') : key\n}\n\n/**\n * The parties of one role, the primary party first.\n *\n * @param {Array<object>} parties The role's rows.\n * @param {string|null} primary The primary party's uuid.\n * @return {Array<object>} The rows.\n * @spec openspec/changes/dq-abstract-record-widgets/specs/record-widgets/spec.md#requirement-a-record-shows-its-parties-by-role\n */\nexport function partiesInOrder(parties, primary) {\n\tconst rows = Array.isArray(parties) ? parties.filter(Boolean) : []\n\tif (!primary) {\n\t\treturn rows\n\t}\n\treturn [\n\t\t...rows.filter((row) => row.partyUuid === primary),\n\t\t...rows.filter((row) => row.partyUuid !== primary),\n\t]\n}\n\n/**\n * The roles of a listing as groups, the group holding the primary party first.\n *\n * @param {object|null} listing The `/parties` answer.\n * @param {Record<string, string>} [roleLabels] The app's words for the roles.\n * @return {Array<{key: string, label: string, parties: Array<object>}>} The groups.\n * @spec openspec/changes/dq-abstract-record-widgets/specs/record-widgets/spec.md#requirement-a-record-shows-its-parties-by-role\n */\nexport function rolesInOrder(listing, roleLabels = {}) {\n\tif (!listing || typeof listing !== 'object') {\n\t\treturn []\n\t}\n\tconst byRole = listing.byRole && typeof listing.byRole === 'object' ? listing.byRole : {}\n\tconst primary = listing.primary || null\n\tconst groups = Object.keys(byRole).map((key) => ({\n\t\tkey,\n\t\tlabel: roleLabel(key, listing.roles, roleLabels),\n\t\tparties: partiesInOrder(byRole[key], primary),\n\t}))\n\tconst holdsPrimary = (group) => !!primary && group.parties.some((party) => party.partyUuid === primary)\n\treturn [...groups.filter(holdsPrimary), ...groups.filter((group) => !holdsPrimary(group))]\n}\n\n/**\n * What an indicator means for what may be done: an indicator always carries\n * its verdict, never a bare chip. `refuse-publication` and `refuse-send` are\n * blocking (`error`); anything else asks to be read first (`warning`).\n *\n * @param {object} indicator The indicator (`{ key, label, effect }`).\n * @param {object} [labels] The app's words: `verdictPublication`, `verdictSend`, `verdictWarn`.\n * @return {{effect: string, severity: string, label: string, verdict: string}} The verdict.\n * @spec openspec/changes/dq-abstract-record-widgets/specs/record-widgets/spec.md#requirement-a-record-shows-its-parties-by-role\n */\nexport function indicatorVerdict(indicator, labels = {}) {\n\tconst effect = String(indicator?.effect || '').trim()\n\tconst label = String(indicator?.label || indicator?.key || '').trim()\n\tif (effect === 'refuse-publication') {\n\t\treturn { effect, severity: 'error', label, verdict: labels.verdictPublication || t('nextcloud-vue', 'Publishing a file on this record is refused') }\n\t}\n\tif (effect === 'refuse-send') {\n\t\treturn { effect, severity: 'error', label, verdict: labels.verdictSend || t('nextcloud-vue', 'A message to this party is refused') }\n\t}\n\treturn { effect: effect === '' ? 'warn' : effect, severity: 'warning', label, verdict: labels.verdictWarn || t('nextcloud-vue', 'Read this before acting on the record') }\n}\n\n/**\n * Every indicator on a set of parties, each knowing whose it is.\n *\n * @param {Array<object>} parties The party records.\n * @return {Array<object>} The indicators with `party` and `partyName`.\n * @spec openspec/changes/dq-abstract-record-widgets/specs/record-widgets/spec.md#requirement-a-record-shows-its-parties-by-role\n */\nexport function indicatorsOf(parties) {\n\tconst found = []\n\tfor (const party of parties || []) {\n\t\tif (!party) {\n\t\t\tcontinue\n\t\t}\n\t\tfor (const indicator of Array.isArray(party.indicators) ? party.indicators : []) {\n\t\t\tif (indicator) {\n\t\t\t\tfound.push({ ...indicator, party: party.id || party.uuid || '', partyName: party.name || party.displayName || '' })\n\t\t\t}\n\t\t}\n\t}\n\treturn found\n}\n\n/**\n * Who represents whom: participant uuid to the uuid of the party it acts for,\n * read from role rows (`{ participant, representedParty }`).\n *\n * @param {Array<object>|null} rows The role rows.\n * @return {Record<string, string>} The map.\n * @spec openspec/changes/dq-abstract-record-widgets/specs/record-widgets/spec.md#requirement-a-record-shows-its-parties-by-role\n */\nexport function representedByMap(rows) {\n\tconst map = {}\n\tfor (const row of Array.isArray(rows) ? rows : []) {\n\t\tconst participant = String(row?.participant || '').trim()\n\t\tconst represented = String(row?.representedParty?.id || row?.representedParty || '').trim()\n\t\tif (participant !== '' && represented !== '') {\n\t\t\tmap[participant] = represented\n\t\t}\n\t}\n\treturn map\n}\n\n/**\n * The documents a party sent and received: sender is the party, or the party\n * is among the recipients.\n *\n * @param {Array<object>} documents The documents.\n * @param {string} identifier The party's uuid.\n * @param {{senderField?: string, recipientsField?: string}} [fields] Where a document names them.\n * @return {{sent: Array<object>, received: Array<object>}} The two lists.\n * @spec openspec/changes/dq-abstract-record-widgets/specs/record-widgets/spec.md#requirement-a-record-shows-its-parties-by-role\n */\nexport function documentsOfParty(documents, identifier, fields = {}) {\n\tconst id = String(identifier || '').trim()\n\tconst rows = Array.isArray(documents) ? documents : []\n\tif (id === '') {\n\t\treturn { sent: [], received: [] }\n\t}\n\tconst sender = fields.senderField || 'sender'\n\tconst recipients = fields.recipientsField || 'recipients'\n\treturn {\n\t\tsent: rows.filter((row) => String(row?.[sender] || '').trim() === id),\n\t\treceived: rows.filter((row) => (Array.isArray(row?.[recipients]) ? row[recipients] : []).map((entry) => String(entry || '').trim()).includes(id)),\n\t}\n}\n\n/**\n * The code of a party kind (`code`, else `key`).\n *\n * @param {object} kind The kind.\n * @return {string} The code.\n */\nexport function kindCode(kind) {\n\treturn String(kind?.code || kind?.key || '')\n}\n"],"names":["t"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"objectParties.js","sources":["../../../src/utils/objectParties.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * objectParties — reading the parties of a record as OpenRegister's party\n * model answers them (`GET .../objects/{register}/{schema}/{id}/parties`:\n * `{ primary, roles, kinds, byRole, results }`, and `GET .../parties/{uuid}`\n * for one party with its indicators).\n *\n * Pure functions, so CnObjectPartiesWidget and its tests read one shape.\n *\n * @module utils/objectParties\n */\n\nimport { translate as t } from '@nextcloud/l10n'\nimport { readPath } from './readPath.js'\n\n/**\n * What a role is called: the app's own word (`roleLabels`), else the label\n * the listing declares, else the key. `other` is a party with no role.\n *\n * @param {string} key The role key.\n * @param {Array<{key: string, label?: string}>} roles The roles the listing declares.\n * @param {Record<string, string>} [roleLabels] The app's words, by key.\n * @return {string} The label.\n * @spec openspec/changes/dq-abstract-record-widgets/specs/record-widgets/spec.md#requirement-a-record-shows-its-parties-by-role\n */\nexport function roleLabel(key, roles, roleLabels = {}) {\n\tif (roleLabels && typeof roleLabels[key] === 'string' && roleLabels[key] !== '') {\n\t\treturn roleLabels[key]\n\t}\n\tconst declared = (roles || []).find((role) => role && role.key === key)\n\tif (declared && declared.label) {\n\t\treturn declared.label\n\t}\n\treturn key === 'other' ? t('nextcloud-vue', 'No role') : key\n}\n\n/**\n * The parties of one role, the primary party first.\n *\n * @param {Array<object>} parties The role's rows.\n * @param {string|null} primary The primary party's uuid.\n * @return {Array<object>} The rows.\n * @spec openspec/changes/dq-abstract-record-widgets/specs/record-widgets/spec.md#requirement-a-record-shows-its-parties-by-role\n */\nexport function partiesInOrder(parties, primary) {\n\tconst rows = Array.isArray(parties) ? parties.filter(Boolean) : []\n\tif (!primary) {\n\t\treturn rows\n\t}\n\treturn [\n\t\t...rows.filter((row) => row.partyUuid === primary),\n\t\t...rows.filter((row) => row.partyUuid !== primary),\n\t]\n}\n\n/**\n * The roles of a listing as groups, the group holding the primary party first.\n *\n * @param {object|null} listing The `/parties` answer.\n * @param {Record<string, string>} [roleLabels] The app's words for the roles.\n * @return {Array<{key: string, label: string, parties: Array<object>}>} The groups.\n * @spec openspec/changes/dq-abstract-record-widgets/specs/record-widgets/spec.md#requirement-a-record-shows-its-parties-by-role\n */\nexport function rolesInOrder(listing, roleLabels = {}) {\n\tif (!listing || typeof listing !== 'object') {\n\t\treturn []\n\t}\n\tconst byRole = listing.byRole && typeof listing.byRole === 'object' ? listing.byRole : {}\n\tconst primary = listing.primary || null\n\tconst groups = Object.keys(byRole).map((key) => ({\n\t\tkey,\n\t\tlabel: roleLabel(key, listing.roles, roleLabels),\n\t\tparties: partiesInOrder(byRole[key], primary),\n\t}))\n\tconst holdsPrimary = (group) => !!primary && group.parties.some((party) => party.partyUuid === primary)\n\treturn [...groups.filter(holdsPrimary), ...groups.filter((group) => !holdsPrimary(group))]\n}\n\n/**\n * What an indicator means for what may be done: an indicator always carries\n * its verdict, never a bare chip. `refuse-publication` and `refuse-send` are\n * blocking (`error`); anything else asks to be read first (`warning`).\n *\n * @param {object} indicator The indicator (`{ key, label, effect }`).\n * @param {object} [labels] The app's words: `verdictPublication`, `verdictSend`, `verdictWarn`.\n * @return {{effect: string, severity: string, label: string, verdict: string}} The verdict.\n * @spec openspec/changes/dq-abstract-record-widgets/specs/record-widgets/spec.md#requirement-a-record-shows-its-parties-by-role\n */\nexport function indicatorVerdict(indicator, labels = {}) {\n\tconst effect = String(indicator?.effect || '').trim()\n\tconst label = String(indicator?.label || indicator?.key || '').trim()\n\tif (effect === 'refuse-publication') {\n\t\treturn { effect, severity: 'error', label, verdict: labels.verdictPublication || t('nextcloud-vue', 'Publishing a file on this record is refused') }\n\t}\n\tif (effect === 'refuse-send') {\n\t\treturn { effect, severity: 'error', label, verdict: labels.verdictSend || t('nextcloud-vue', 'A message to this party is refused') }\n\t}\n\treturn { effect: effect === '' ? 'warn' : effect, severity: 'warning', label, verdict: labels.verdictWarn || t('nextcloud-vue', 'Read this before acting on the record') }\n}\n\n/**\n * Every indicator on a set of parties, each knowing whose it is.\n *\n * @param {Array<object>} parties The party records.\n * @return {Array<object>} The indicators with `party` and `partyName`.\n * @spec openspec/changes/dq-abstract-record-widgets/specs/record-widgets/spec.md#requirement-a-record-shows-its-parties-by-role\n */\nexport function indicatorsOf(parties) {\n\tconst found = []\n\tfor (const party of parties || []) {\n\t\tif (!party) {\n\t\t\tcontinue\n\t\t}\n\t\tfor (const indicator of Array.isArray(party.indicators) ? party.indicators : []) {\n\t\t\tif (indicator) {\n\t\t\t\tfound.push({ ...indicator, party: party.id || party.uuid || '', partyName: party.name || party.displayName || '' })\n\t\t\t}\n\t\t}\n\t}\n\treturn found\n}\n\n/**\n * Who represents whom: participant uuid to the uuid of the party it acts for,\n * read from role rows (`{ participant, representedParty }`).\n *\n * @param {Array<object>|null} rows The role rows.\n * @return {Record<string, string>} The map.\n * @spec openspec/changes/dq-abstract-record-widgets/specs/record-widgets/spec.md#requirement-a-record-shows-its-parties-by-role\n */\nexport function representedByMap(rows) {\n\tconst map = {}\n\tfor (const row of Array.isArray(rows) ? rows : []) {\n\t\tconst participant = String(row?.participant || '').trim()\n\t\tconst represented = String(row?.representedParty?.id || row?.representedParty || '').trim()\n\t\tif (participant !== '' && represented !== '') {\n\t\t\tmap[participant] = represented\n\t\t}\n\t}\n\treturn map\n}\n\n/**\n * The documents a party sent and received: sender is the party, or the party\n * is among the recipients.\n *\n * @param {Array<object>} documents The documents.\n * @param {string} identifier The party's uuid.\n * @param {{senderField?: string, recipientsField?: string}} [fields] Where a document names them.\n * @return {{sent: Array<object>, received: Array<object>}} The two lists.\n * @spec openspec/changes/dq-abstract-record-widgets/specs/record-widgets/spec.md#requirement-a-record-shows-its-parties-by-role\n */\nexport function documentsOfParty(documents, identifier, fields = {}) {\n\tconst id = String(identifier || '').trim()\n\tconst rows = Array.isArray(documents) ? documents : []\n\tif (id === '') {\n\t\treturn { sent: [], received: [] }\n\t}\n\tconst sender = fields.senderField || 'sender'\n\tconst recipients = fields.recipientsField || 'recipients'\n\treturn {\n\t\tsent: rows.filter((row) => String(row?.[sender] || '').trim() === id),\n\t\treceived: rows.filter((row) => (Array.isArray(row?.[recipients]) ? row[recipients] : []).map((entry) => String(entry || '').trim()).includes(id)),\n\t}\n}\n\n/**\n * The code of a party kind (`code`, else `key`).\n *\n * @param {object} kind The kind.\n * @return {string} The code.\n */\nexport function kindCode(kind) {\n\treturn String(kind?.code || kind?.key || '')\n}\n\n/**\n * Write a value at a dotted path, creating the objects on the way.\n *\n * @param {object} target The object written into.\n * @param {string} path The dotted path (`name.surname`).\n * @param {unknown} value The value.\n * @return {void}\n */\nfunction writePath(target, path, value) {\n\tconst keys = String(path).split('.').filter((key) => key !== '')\n\tlet node = target\n\tkeys.slice(0, -1).forEach((key) => {\n\t\tif (!node[key] || typeof node[key] !== 'object') {\n\t\t\tnode[key] = {}\n\t\t}\n\t\tnode = node[key]\n\t})\n\tif (keys.length > 0) {\n\t\tnode[keys[keys.length - 1]] = value\n\t}\n}\n\n/**\n * The record a new party is saved as, from the fields a host declares.\n *\n * Each field `{ key, path?, address? }` writes its trimmed value at `path`\n * (default `key`); a field with `address: { path, kind, type }` instead adds\n * `{ kind, type, value }` to the list at that path, the shape OpenRegister's\n * party model reads as the party's addresses. `compose` names the paths a\n * derived field joins with a space, skipping the empty ones\n * (`{ displayName: [\"name.givenNames\", \"name.namePrefix\", \"name.surname\"] }`).\n * A field of `type: \"integer\"` is saved as a number when it reads as one.\n * An empty value is left out.\n *\n * @param {{fields?: Array<object>, compose?: Record<string, Array<string>>}} create The declaration.\n * @param {Record<string, string>} values The values by field key.\n * @return {object} The record.\n * @spec openspec/changes/object-parties-manage/specs/record-widgets/spec.md#requirement-the-parties-widget-can-add-and-remove-parties\n */\nexport function newPartyRecord(create, values) {\n\tconst record = {}\n\tfor (const field of Array.isArray(create?.fields) ? create.fields : []) {\n\t\tconst value = String(values?.[field?.key] ?? '').trim()\n\t\tif (!field || !field.key || value === '') {\n\t\t\tcontinue\n\t\t}\n\t\tif (field.address && field.address.path) {\n\t\t\tconst list = readPath(record, field.address.path)\n\t\t\tconst entry = { kind: field.address.kind || 'correspondence', type: field.address.type || 'email', value }\n\t\t\twritePath(record, field.address.path, [...(Array.isArray(list) ? list : []), entry])\n\t\t\tcontinue\n\t\t}\n\t\twritePath(record, field.path || field.key, field.type === 'integer' && /^-?\\d+$/.test(value) ? Number(value) : value)\n\t}\n\tfor (const [target, paths] of Object.entries(create?.compose && typeof create.compose === 'object' ? create.compose : {})) {\n\t\tconst joined = (Array.isArray(paths) ? paths : [])\n\t\t\t.map((path) => String(readPath(record, path) ?? '').trim())\n\t\t\t.filter((part) => part !== '')\n\t\t\t.join(' ')\n\t\tif (joined !== '') {\n\t\t\twritePath(record, target, joined)\n\t\t}\n\t}\n\treturn record\n}\n\n/**\n * The uuid a create answered with: `id`, `uuid` or `@self.id`.\n *\n * @param {object} saved The saved object.\n * @return {string} The uuid, or ''.\n * @spec openspec/changes/object-parties-manage/specs/record-widgets/spec.md#requirement-the-parties-widget-can-add-and-remove-parties\n */\nexport function savedUuid(saved) {\n\treturn String(saved?.['@self']?.id || saved?.uuid || saved?.id || '')\n}\n"],"names":["t"],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { readPath } from './readPath.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
5
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
6
|
+
*
|
|
7
|
+
* The rows a record holds in one of its fields, as `objectRows` names them:
|
|
8
|
+
* `{ path, where?, valuePath? }`. The list at `path`, narrowed to the entry
|
|
9
|
+
* matching `where` when set (`{ name: "onderzoeksstappen" }` in a case's
|
|
10
|
+
* answers), its `valuePath` taken; a JSON string is decoded. Anything that is
|
|
11
|
+
* not a list of objects is no rows. The record is read as the page read it, so
|
|
12
|
+
* its own read rules already decided what is in it.
|
|
13
|
+
*
|
|
14
|
+
* @spec openspec/changes/record-list-object-rows/specs/record-list/spec.md#requirement-a-record-list-can-list-rows-the-page-record-holds
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Whether a declaration names rows on a record.
|
|
19
|
+
*
|
|
20
|
+
* @param {unknown} spec The declaration.
|
|
21
|
+
* @return {boolean}
|
|
22
|
+
*/
|
|
23
|
+
function isObjectRowsSpec(spec) {
|
|
24
|
+
return Boolean(spec && typeof spec === 'object' && typeof spec.path === 'string' && spec.path !== '')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The rows a record holds where `spec` points.
|
|
29
|
+
*
|
|
30
|
+
* @param {object|null} object The record.
|
|
31
|
+
* @param {{path: string, where?: object, valuePath?: string}} spec The declaration.
|
|
32
|
+
* @return {Array<object>} The rows.
|
|
33
|
+
*/
|
|
34
|
+
function objectRowsOf(object, spec) {
|
|
35
|
+
if (!object || typeof object !== 'object' || !isObjectRowsSpec(spec)) {
|
|
36
|
+
return []
|
|
37
|
+
}
|
|
38
|
+
const valuePath = typeof spec.valuePath === 'string' && spec.valuePath !== '' ? spec.valuePath : '';
|
|
39
|
+
let value = readPath(object, spec.path);
|
|
40
|
+
if (spec.where && typeof spec.where === 'object') {
|
|
41
|
+
const entries = Array.isArray(value) ? value : [];
|
|
42
|
+
const match = entries.find((entry) => entry && typeof entry === 'object'
|
|
43
|
+
&& Object.entries(spec.where).every(([key, wanted]) => entry[key] === wanted));
|
|
44
|
+
value = match && valuePath ? readPath(match, valuePath) : match;
|
|
45
|
+
} else if (valuePath) {
|
|
46
|
+
value = readPath(value, valuePath);
|
|
47
|
+
}
|
|
48
|
+
if (typeof value === 'string') {
|
|
49
|
+
try {
|
|
50
|
+
value = JSON.parse(value);
|
|
51
|
+
} catch {
|
|
52
|
+
value = undefined;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return Array.isArray(value) ? value.filter((row) => row && typeof row === 'object' && !Array.isArray(row)) : []
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { isObjectRowsSpec, objectRowsOf };
|
|
59
|
+
//# sourceMappingURL=objectRows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"objectRows.js","sources":["../../../src/utils/objectRows.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * The rows a record holds in one of its fields, as `objectRows` names them:\n * `{ path, where?, valuePath? }`. The list at `path`, narrowed to the entry\n * matching `where` when set (`{ name: \"onderzoeksstappen\" }` in a case's\n * answers), its `valuePath` taken; a JSON string is decoded. Anything that is\n * not a list of objects is no rows. The record is read as the page read it, so\n * its own read rules already decided what is in it.\n *\n * @spec openspec/changes/record-list-object-rows/specs/record-list/spec.md#requirement-a-record-list-can-list-rows-the-page-record-holds\n */\nimport { readPath } from './readPath.js'\n\n/**\n * Whether a declaration names rows on a record.\n *\n * @param {unknown} spec The declaration.\n * @return {boolean}\n */\nexport function isObjectRowsSpec(spec) {\n\treturn Boolean(spec && typeof spec === 'object' && typeof spec.path === 'string' && spec.path !== '')\n}\n\n/**\n * The rows a record holds where `spec` points.\n *\n * @param {object|null} object The record.\n * @param {{path: string, where?: object, valuePath?: string}} spec The declaration.\n * @return {Array<object>} The rows.\n */\nexport function objectRowsOf(object, spec) {\n\tif (!object || typeof object !== 'object' || !isObjectRowsSpec(spec)) {\n\t\treturn []\n\t}\n\tconst valuePath = typeof spec.valuePath === 'string' && spec.valuePath !== '' ? spec.valuePath : ''\n\tlet value = readPath(object, spec.path)\n\tif (spec.where && typeof spec.where === 'object') {\n\t\tconst entries = Array.isArray(value) ? value : []\n\t\tconst match = entries.find((entry) => entry && typeof entry === 'object'\n\t\t\t&& Object.entries(spec.where).every(([key, wanted]) => entry[key] === wanted))\n\t\tvalue = match && valuePath ? readPath(match, valuePath) : match\n\t} else if (valuePath) {\n\t\tvalue = readPath(value, valuePath)\n\t}\n\tif (typeof value === 'string') {\n\t\ttry {\n\t\t\tvalue = JSON.parse(value)\n\t\t} catch {\n\t\t\tvalue = undefined\n\t\t}\n\t}\n\treturn Array.isArray(value) ? value.filter((row) => row && typeof row === 'object' && !Array.isArray(row)) : []\n}\n"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,gBAAgB,CAAC,IAAI,EAAE;AACvC,CAAC,OAAO,OAAO,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;AACtG,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE;AAC3C,CAAC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE;AACvE,EAAE,OAAO,EAAE;AACX,EAAE;AACF,CAAC,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ,IAAI,IAAI,CAAC,SAAS,KAAK,EAAE,GAAG,IAAI,CAAC,SAAS,GAAG,GAAE;AACpG,CAAC,IAAI,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAC;AACxC,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE;AACnD,EAAE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,GAAE;AACnD,EAAE,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;AAC1E,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,EAAC;AACjF,EAAE,KAAK,GAAG,KAAK,IAAI,SAAS,GAAG,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,MAAK;AACjE,EAAE,MAAM,IAAI,SAAS,EAAE;AACvB,EAAE,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAC;AACpC,EAAE;AACF,CAAC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAChC,EAAE,IAAI;AACN,GAAG,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAC;AAC5B,GAAG,CAAC,MAAM;AACV,GAAG,KAAK,GAAG,UAAS;AACpB,GAAG;AACH,EAAE;AACF,CAAC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE;AAChH;;;;"}
|