@conduction/nextcloud-vue 2.111.0 → 2.113.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 +4 -6
- package/dist/esm/components/CnActionButtons/CnActionButtons.vue2.js.map +1 -1
- package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js.map +1 -1
- package/dist/esm/components/CnActionDialog/CnActionDialog.vue.js +1 -1
- package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js +3 -2
- package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js +4 -2
- package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue.js +1 -1
- package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js +3 -2
- package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js +2 -1
- package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnBoardView/CnBoardView.vue.js +1 -1
- package/dist/esm/components/CnBoardView/CnBoardView.vue2.js +54 -5
- package/dist/esm/components/CnBoardView/CnBoardView.vue2.js.map +1 -1
- package/dist/esm/components/CnBoardView/CnBoardView.vue3.js +16 -2
- package/dist/esm/components/CnBoardView/CnBoardView.vue3.js.map +1 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue.js +1 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js +10 -0
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js.map +1 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js +2 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue.js +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +22 -2
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +17 -3
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue.js +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +18 -3
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +2 -2
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +52 -13
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +31 -3
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +48 -11
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +160 -97
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue.js +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +2 -2
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +222 -15
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +24 -7
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue.js +1 -1
- package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue2.js +21 -1
- package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue2.js.map +1 -1
- package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue.js +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js +36 -2
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js +44 -5
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js.map +1 -1
- package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue.js +1 -0
- package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue.js.map +1 -1
- package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue2.js +22 -2
- package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue2.js.map +1 -1
- package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue3.js +36 -16
- package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue3.js.map +1 -1
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue.js +1 -1
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue2.js +29 -12
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue2.js.map +1 -1
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue3.js +3 -1
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue3.js.map +1 -1
- package/dist/esm/components/CnSearchSelect/CnSearchSelect.vue.js +1 -1
- package/dist/esm/components/CnSearchSelect/CnSearchSelect.vue2.js.map +1 -1
- package/dist/esm/components/CnSearchSelect/CnSearchSelect.vue3.js.map +1 -1
- package/dist/esm/composables/useRefLabels.js +26 -6
- package/dist/esm/composables/useRefLabels.js.map +1 -1
- package/dist/esm/integrations/registry.js +4 -0
- package/dist/esm/integrations/registry.js.map +1 -1
- package/dist/esm/l10n/en.json.js +3 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +3 -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 +680 -449
- package/dist/esm/store/plugins/liveUpdates.js +3 -1
- package/dist/esm/store/plugins/liveUpdates.js.map +1 -1
- package/dist/esm/store/plugins/logs.js +2 -1
- package/dist/esm/store/plugins/logs.js.map +1 -1
- package/dist/esm/utils/actionLink.js +104 -1
- package/dist/esm/utils/actionLink.js.map +1 -1
- package/dist/esm/utils/detailActionModel.js +28 -1
- package/dist/esm/utils/detailActionModel.js.map +1 -1
- package/dist/esm/utils/fillTemplate.js +13 -5
- package/dist/esm/utils/fillTemplate.js.map +1 -1
- package/dist/esm/utils/headerFieldChips.js +21 -2
- package/dist/esm/utils/headerFieldChips.js.map +1 -1
- package/dist/esm/utils/mapList.js +26 -11
- package/dist/esm/utils/mapList.js.map +1 -1
- package/dist/esm/utils/savedViewMenu.js +12 -5
- package/dist/esm/utils/savedViewMenu.js.map +1 -1
- 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 +2800 -1933
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +680 -449
- package/l10n/en.json +3 -1
- package/l10n/nl.json +3 -1
- package/package.json +1 -1
- package/src/components/CnActionButtons/CnActionButtons.vue +4 -6
- package/src/components/CnActionDialog/CnActionDialog.vue +32 -9
- package/src/components/CnAssignDialog/CnAssignDialog.vue +4 -2
- package/src/components/CnBoardView/CnBoardView.vue +58 -5
- package/src/components/CnCardGrid/CnCardGrid.md +1 -0
- package/src/components/CnCardGrid/CnCardGrid.vue +11 -0
- package/src/components/CnCellRenderer/CnCellRenderer.vue +27 -3
- package/src/components/CnChartWidget/CnChartWidget.vue +6 -0
- package/src/components/CnChoiceCards/CnChoiceCards.vue +0 -3
- package/src/components/CnDashboardPage/CnDashboardPage.vue +20 -5
- package/src/components/CnDetailPage/CnDetailPage.vue +62 -14
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +100 -5
- package/src/components/CnFormDialog/CnFormDialog.vue +1 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +233 -18
- package/src/components/CnNcDashboardList/CnNcDashboardList.vue +21 -1
- package/src/components/CnObjectCard/CnObjectCard.md +1 -0
- package/src/components/CnObjectCard/CnObjectCard.vue +51 -5
- package/src/components/CnPartyPicker/CnPartyPicker.vue +62 -16
- package/src/components/CnReportsPage/CnReportsPage.vue +31 -12
- package/src/components/CnSearchSelect/CnSearchSelect.vue +8 -0
- package/src/composables/useRefLabels.js +25 -5
- package/src/css/badge.css +15 -13
- package/src/css/board.css +0 -1
- package/src/css/dialog.css +53 -3
- package/src/css/index-page.css +26 -1
- package/src/css/look-board-detail.css +36 -15
- package/src/css/look-board-index.css +67 -15
- package/src/css/look-board.css +32 -18
- package/src/integrations/registry.js +4 -0
- package/src/schemas/app-manifest-v2.schema.json +61 -13
- package/src/store/plugins/liveUpdates.js +3 -1
- package/src/store/plugins/logs.js +2 -1
- package/src/utils/actionLink.js +103 -0
- package/src/utils/detailActionModel.js +27 -0
- package/src/utils/fillTemplate.js +13 -5
- package/src/utils/headerFieldChips.js +21 -2
- package/src/utils/mapList.js +26 -11
- package/src/utils/savedViewMenu.js +12 -5
- package/src/utils/validateManifestV2.compiled.js +3 -3
package/l10n/en.json
CHANGED
|
@@ -1912,7 +1912,9 @@
|
|
|
1912
1912
|
"New team": "New team",
|
|
1913
1913
|
"Why it is moving": "Why it is moving",
|
|
1914
1914
|
"Use \"{name}\"": "Use \"{name}\"",
|
|
1915
|
-
"It was not handed over.": "It was not handed over."
|
|
1915
|
+
"It was not handed over.": "It was not handed over.",
|
|
1916
|
+
"This search could not be read.": "This search could not be read.",
|
|
1917
|
+
"{source} could not be searched, so this list may be incomplete.": "{source} could not be searched, so this list may be incomplete."
|
|
1916
1918
|
},
|
|
1917
1919
|
"plurals": {
|
|
1918
1920
|
"{count} member": [
|
package/l10n/nl.json
CHANGED
|
@@ -2124,7 +2124,9 @@
|
|
|
2124
2124
|
"New team": "Nieuw team",
|
|
2125
2125
|
"Why it is moving": "Waarom het overgaat",
|
|
2126
2126
|
"Use \"{name}\"": "\"{name}\" gebruiken",
|
|
2127
|
-
"It was not handed over.": "Het is niet overgedragen."
|
|
2127
|
+
"It was not handed over.": "Het is niet overgedragen.",
|
|
2128
|
+
"This search could not be read.": "Deze zoekopdracht kon niet worden gelezen.",
|
|
2129
|
+
"{source} could not be searched, so this list may be incomplete.": "{source} kon niet worden doorzocht, dus deze lijst is mogelijk niet compleet."
|
|
2128
2130
|
},
|
|
2129
2131
|
"plurals": {
|
|
2130
2132
|
"{count} member": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@conduction/nextcloud-vue",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.113.0",
|
|
4
4
|
"description": "Shared Vue component library for Conduction Nextcloud apps — complements @nextcloud/vue with higher-level components, OpenRegister integration, and NL Design System support",
|
|
5
5
|
"homepage": "https://github.com/ConductionNL/nextcloud-vue#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -329,12 +329,10 @@ export default {
|
|
|
329
329
|
* browser keeps middle-click, "open in new tab" and the link semantics
|
|
330
330
|
* assistive tech announces.
|
|
331
331
|
*
|
|
332
|
-
* `href` is
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
* `type: "navigate"` with an external `target`, which auto-derives the
|
|
337
|
-
* anchor/`window.open` behaviour instead.
|
|
332
|
+
* `href` is used as given, so it must be a finished URL. A manifest
|
|
333
|
+
* `headerActions[]` entry may carry `href` too: the page (CnDetailPage,
|
|
334
|
+
* CnDashboardPage) resolves an instance path through `generateUrl()`
|
|
335
|
+
* and sets `target` before the entry reaches this component.
|
|
338
336
|
*
|
|
339
337
|
* @type {Array<object>}
|
|
340
338
|
*/
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
{{ section.title }}
|
|
32
32
|
</h3>
|
|
33
33
|
<dl class="cn-action-dialog__facts">
|
|
34
|
-
<div v-for="fact in section.facts" :key="fact.label">
|
|
34
|
+
<div v-for="fact in section.facts" :key="fact.label" class="cn-action-dialog__fact">
|
|
35
35
|
<dt>{{ fact.label }}</dt>
|
|
36
36
|
<dd>{{ fact.value }}</dd>
|
|
37
37
|
</div>
|
|
@@ -87,6 +87,7 @@
|
|
|
87
87
|
v-model="reason"
|
|
88
88
|
:label="reasonLabel"
|
|
89
89
|
:labelOutside="false"
|
|
90
|
+
:rows="config.reason.rows || 2"
|
|
90
91
|
resize="vertical"
|
|
91
92
|
data-testid="cn-action-dialog-reason" />
|
|
92
93
|
<span v-if="config.reason.hint" class="cn-action-dialog__muted">{{ text(config.reason.hint) }}</span>
|
|
@@ -176,8 +177,9 @@ let reasonSeq = 0
|
|
|
176
177
|
* required?, options?: [{ value, label, fills? }] }]`: inputs sent beside
|
|
177
178
|
* the reason, required by default; a select option's `fills` sets other
|
|
178
179
|
* fields that are still empty.
|
|
179
|
-
* - `reason`: `{ label?, hint?, required?, field? }`: a text area; required by
|
|
180
|
-
* default; sent as `field` (default `reason`).
|
|
180
|
+
* - `reason`: `{ label?, hint?, required?, field?, rows? }`: a text area; required by
|
|
181
|
+
* default; sent as `field` (default `reason`). `rows` is its height in lines
|
|
182
|
+
* (default 2; board DqBesluit draws 4).
|
|
181
183
|
* - `note`: `{ variant?, title?, text }`: a read-only note.
|
|
182
184
|
* - `confirm`: `{ label, icon?, request?: { method?, url, body? }, action? }`.
|
|
183
185
|
* `request` posts itself (`body` templates filled with the record and
|
|
@@ -604,17 +606,27 @@ export default {
|
|
|
604
606
|
|
|
605
607
|
.cn-action-dialog__title {
|
|
606
608
|
margin: 0 0 8px;
|
|
607
|
-
font-size:
|
|
608
|
-
font-weight:
|
|
609
|
+
font-size: 14px;
|
|
610
|
+
font-weight: 600;
|
|
609
611
|
}
|
|
610
612
|
|
|
613
|
+
/* Facts in columns of at least 200px, each a label over its value above a
|
|
614
|
+
hairline (DqArchiveren "Bewaring volgens het zaaktype"). */
|
|
611
615
|
.cn-action-dialog__facts {
|
|
612
616
|
display: grid;
|
|
613
|
-
grid-template-columns: repeat(auto-fit, minmax(
|
|
614
|
-
gap:
|
|
617
|
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
618
|
+
gap: 12px 24px;
|
|
615
619
|
margin: 0;
|
|
616
620
|
}
|
|
617
621
|
|
|
622
|
+
.cn-action-dialog__fact {
|
|
623
|
+
display: flex;
|
|
624
|
+
flex-direction: column;
|
|
625
|
+
gap: 3px;
|
|
626
|
+
padding-bottom: 10px;
|
|
627
|
+
border-bottom: 1px solid var(--color-border);
|
|
628
|
+
}
|
|
629
|
+
|
|
618
630
|
.cn-action-dialog__facts dt {
|
|
619
631
|
color: var(--color-text-maxcontrast);
|
|
620
632
|
font-size: 13px;
|
|
@@ -622,12 +634,15 @@ export default {
|
|
|
622
634
|
|
|
623
635
|
.cn-action-dialog__facts dd {
|
|
624
636
|
margin: 0;
|
|
637
|
+
font-size: 15px;
|
|
638
|
+
font-weight: 500;
|
|
625
639
|
}
|
|
626
640
|
|
|
641
|
+
/* Checklist rows divided by hairlines, the detail at the row's end
|
|
642
|
+
(DqArchiveren "Klaar om te archiveren"). */
|
|
627
643
|
.cn-action-dialog__checks {
|
|
628
644
|
display: flex;
|
|
629
645
|
flex-direction: column;
|
|
630
|
-
gap: 8px;
|
|
631
646
|
margin: 0;
|
|
632
647
|
padding: 0;
|
|
633
648
|
list-style: none;
|
|
@@ -637,7 +652,15 @@ export default {
|
|
|
637
652
|
display: flex;
|
|
638
653
|
flex-wrap: wrap;
|
|
639
654
|
align-items: center;
|
|
640
|
-
gap:
|
|
655
|
+
gap: 2px 12px;
|
|
656
|
+
padding: 10px 0;
|
|
657
|
+
border-top: 1px solid var(--color-border);
|
|
658
|
+
font-size: 15px;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
.cn-action-dialog__check-label {
|
|
662
|
+
flex: 1 1 auto;
|
|
663
|
+
font-weight: 600;
|
|
641
664
|
}
|
|
642
665
|
|
|
643
666
|
.cn-action-dialog__check-icon {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
v-model="note"
|
|
35
35
|
:label="noteLabel"
|
|
36
36
|
:labelOutside="false"
|
|
37
|
+
:rows="noteConfig.rows || 3"
|
|
37
38
|
resize="vertical"
|
|
38
39
|
data-testid="cn-assign-dialog-note" />
|
|
39
40
|
<span v-if="noteConfig.hint" class="cn-assign-dialog__hint">{{ text(noteConfig.hint) }}</span>
|
|
@@ -139,8 +140,9 @@ export function withTypedAssignee(found, typed, label) {
|
|
|
139
140
|
* by `currentAs`) says so, in place of `hint`; `allowTyped`
|
|
140
141
|
* offers what was typed as a choice; the id is sent as `field` (default
|
|
141
142
|
* `assignee`) and its kind as `kindField` when set.
|
|
142
|
-
* - `note`: `{ label?, hint?, required?, field? }`, required by default and
|
|
143
|
-
* sent as `field` (default `note`); `false` drops it.
|
|
143
|
+
* - `note`: `{ label?, hint?, required?, field?, rows? }`, required by default and
|
|
144
|
+
* sent as `field` (default `note`); `false` drops it. `rows` is the text
|
|
145
|
+
* area's height in lines (default 3, as board DqOverdragen draws it).
|
|
144
146
|
* - `toggles`: `[{ field, label, note? }]`: switches that start off and are
|
|
145
147
|
* sent as booleans.
|
|
146
148
|
* - `confirm`: `{ label?, icon?, request?: { method?, url, body? }, action? }`.
|
|
@@ -228,7 +228,11 @@
|
|
|
228
228
|
class="cn-board-view__pill"
|
|
229
229
|
data-testid="cn-board-card-pill"
|
|
230
230
|
:label="roleText(card, roles.pill)"
|
|
231
|
-
:variant="pillVariant(card)"
|
|
231
|
+
:variant="pillVariant(card)">
|
|
232
|
+
<template v-if="pillIcon(card)" #icon>
|
|
233
|
+
<CnIcon :name="pillIcon(card)" :size="14" />
|
|
234
|
+
</template>
|
|
235
|
+
</CnStatusBadge>
|
|
232
236
|
</span>
|
|
233
237
|
<span
|
|
234
238
|
v-if="dueText(card) !== '' || ownerName(card) !== ''"
|
|
@@ -352,12 +356,14 @@
|
|
|
352
356
|
|
|
353
357
|
<script>
|
|
354
358
|
import { translate as t } from '@nextcloud/l10n'
|
|
359
|
+
import CnIcon from '../CnIcon/CnIcon.vue'
|
|
355
360
|
import CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'
|
|
356
361
|
import { normalizeLook } from '../../composables/useLook.js'
|
|
357
362
|
import { isBadgeVariant } from '../../utils/badgeVariants.js'
|
|
358
363
|
import { buildBoardColumns, normalizeAllowed, resolveStageColor } from '../../utils/boardColumns.js'
|
|
359
364
|
import { buildSwimlanes } from '../../utils/boardSwimlanes.js'
|
|
360
365
|
import { DROP_OUTCOMES, runBoardDrop } from '../../utils/boardTransition.js'
|
|
366
|
+
import { pillLook } from '../../utils/detailActionModel.js'
|
|
361
367
|
import { daysUntil, dueStateForRow } from '../../utils/dueRule.js'
|
|
362
368
|
import { formatMetricValue } from '../../utils/formatMetric.js'
|
|
363
369
|
import { readPath } from '../../utils/readPath.js'
|
|
@@ -393,7 +399,7 @@ import '../../css/board.css'
|
|
|
393
399
|
export default {
|
|
394
400
|
name: 'CnBoardView',
|
|
395
401
|
|
|
396
|
-
components: { CnStatusBadge },
|
|
402
|
+
components: { CnIcon, CnStatusBadge },
|
|
397
403
|
|
|
398
404
|
inject: {
|
|
399
405
|
/**
|
|
@@ -489,9 +495,10 @@ export default {
|
|
|
489
495
|
|
|
490
496
|
/**
|
|
491
497
|
* The board look's card roles (manifest `config.board.card`):
|
|
492
|
-
* `{ title, sub, pill, due, owner, pillColors? }`. `sub` is a
|
|
493
|
-
* a list of fields joined by a middle dot; `pillColors` maps a
|
|
494
|
-
* value to a badge variant
|
|
498
|
+
* `{ title, sub, pill, due, owner, pillColors?, resolve? }`. `sub` is a
|
|
499
|
+
* field or a list of fields joined by a middle dot; `pillColors` maps a
|
|
500
|
+
* pill value to a badge variant; `resolve: { colorField?, iconField? }`
|
|
501
|
+
* takes the pill's tone and icon from the record it points at. Missing, the first of `cardFields` is the
|
|
495
502
|
* title and the rest form the sub line. The Nextcloud look ignores it.
|
|
496
503
|
*
|
|
497
504
|
* @type {{title?: string, sub?: string|Array<string>, pill?: string, due?: string, owner?: string, pillColors?: object}|null}
|
|
@@ -502,6 +509,20 @@ export default {
|
|
|
502
509
|
default: null,
|
|
503
510
|
},
|
|
504
511
|
|
|
512
|
+
/**
|
|
513
|
+
* The referenced records' colour and icon names, by field and id
|
|
514
|
+
* (`{ [field]: { [id]: { color, icon } } }`, CnIndexPage reads them).
|
|
515
|
+
* With `cardRoles.resolve: { colorField?, iconField? }` the card's pill
|
|
516
|
+
* takes its record's tone and icon from here.
|
|
517
|
+
*
|
|
518
|
+
* @type {object}
|
|
519
|
+
* @spec openspec/changes/pill-color-field/specs/pill-color-field/spec.md#requirement-a-card-pill-takes-its-tone-and-icon-from-the-referenced-record
|
|
520
|
+
*/
|
|
521
|
+
pillLooks: {
|
|
522
|
+
type: Object,
|
|
523
|
+
default: () => ({}),
|
|
524
|
+
},
|
|
525
|
+
|
|
505
526
|
/**
|
|
506
527
|
* The field on a column's state that holds its dot colour (manifest
|
|
507
528
|
* `config.board.colorField`). Empty, the lifecycle state's declared
|
|
@@ -1064,11 +1085,43 @@ export default {
|
|
|
1064
1085
|
* @return {string} A CnStatusBadge variant.
|
|
1065
1086
|
*/
|
|
1066
1087
|
pillVariant(card) {
|
|
1088
|
+
const look = this.pillLookOf(card)
|
|
1089
|
+
if (look.variant) {
|
|
1090
|
+
return look.variant
|
|
1091
|
+
}
|
|
1067
1092
|
const raw = this.fieldText(card, this.roles.pill)
|
|
1068
1093
|
const variant = this.roles.pillColors[raw] ?? this.roles.pillColors[raw.toLowerCase()]
|
|
1069
1094
|
return isBadgeVariant(variant) ? variant : 'default'
|
|
1070
1095
|
},
|
|
1071
1096
|
|
|
1097
|
+
/**
|
|
1098
|
+
* The pill's icon, from the record it points at (`cardRoles.resolve`).
|
|
1099
|
+
*
|
|
1100
|
+
* @param {object} card The card's row.
|
|
1101
|
+
* @return {string} An icon name, or ''.
|
|
1102
|
+
* @spec openspec/changes/pill-color-field/specs/pill-color-field/spec.md#requirement-a-card-pill-takes-its-tone-and-icon-from-the-referenced-record
|
|
1103
|
+
*/
|
|
1104
|
+
pillIcon(card) {
|
|
1105
|
+
return this.pillLookOf(card).icon || ''
|
|
1106
|
+
},
|
|
1107
|
+
|
|
1108
|
+
/**
|
|
1109
|
+
* The tone and icon of the record the card's pill points at, when
|
|
1110
|
+
* `cardRoles.resolve` asks for them; empty otherwise.
|
|
1111
|
+
*
|
|
1112
|
+
* @param {object} card The card's row.
|
|
1113
|
+
* @return {{variant?: string, icon?: string}} The look.
|
|
1114
|
+
*/
|
|
1115
|
+
pillLookOf(card) {
|
|
1116
|
+
const given = this.cardRoles && typeof this.cardRoles === 'object' ? this.cardRoles : null
|
|
1117
|
+
if (!given || !given.resolve || !this.roles.pill || !this.pillLooks) {
|
|
1118
|
+
return {}
|
|
1119
|
+
}
|
|
1120
|
+
const raw = readPath(card, this.roles.pill)
|
|
1121
|
+
const looks = this.pillLooks[this.roles.pill]
|
|
1122
|
+
return pillLook(looks && raw !== null && raw !== undefined && typeof raw !== 'object' ? looks[String(raw)] : null)
|
|
1123
|
+
},
|
|
1124
|
+
|
|
1072
1125
|
/**
|
|
1073
1126
|
* The footer's due text: "Due today", "Due 2 Nov", or "Overdue 2 Nov"
|
|
1074
1127
|
* for a date in the past. Words, so the late tone is not colour alone.
|
|
@@ -107,6 +107,7 @@ Custom card slot — replace the default CnObjectCard with your own rendering:
|
|
|
107
107
|
| `selectable` | `Boolean` | `false` | When `true`, each card shows a selection checkbox and the grid emits `select` events |
|
|
108
108
|
| `selectedIds` | `Array` | `[]` | Array of currently selected object IDs (matched against `object[rowKey]`) |
|
|
109
109
|
| `accentOf` | `Function` | `null` | `(object) => { variant, icon?, label? } \| null`, each card's status accent (see CnObjectCard `accent`) |
|
|
110
|
+
| `pillLooks` | `Object` | `{}` | The referenced records' colour and icon names, by field and id (`{ [field]: { [id]: { color, icon } } }`), passed to each CnObjectCard for the record layout's pills that declare `resolve`. |
|
|
110
111
|
|
|
111
112
|
## Board look props
|
|
112
113
|
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
:selected="isSelected(object)"
|
|
39
39
|
:cardFields="cardFields"
|
|
40
40
|
:layout="cardLayout"
|
|
41
|
+
:pillLooks="pillLooks"
|
|
41
42
|
:cardFieldColumns="cardFieldColumns"
|
|
42
43
|
:status="statusOf ? statusOf(object) : null"
|
|
43
44
|
:leading="leadingOf ? leadingOf(object) : null"
|
|
@@ -179,6 +180,16 @@ export default {
|
|
|
179
180
|
default: null,
|
|
180
181
|
},
|
|
181
182
|
|
|
183
|
+
/**
|
|
184
|
+
* The referenced records' colour and icon names, by field and id
|
|
185
|
+
* (`{ [field]: { [id]: { color, icon } } }`), passed through to
|
|
186
|
+
* CnObjectCard for the record layout's pills that declare `resolve`.
|
|
187
|
+
*/
|
|
188
|
+
pillLooks: {
|
|
189
|
+
type: Object,
|
|
190
|
+
default: () => ({}),
|
|
191
|
+
},
|
|
192
|
+
|
|
182
193
|
/** The page's columns by key, passed through to CnObjectCard. */
|
|
183
194
|
cardFieldColumns: {
|
|
184
195
|
type: Object,
|
|
@@ -50,7 +50,11 @@
|
|
|
50
50
|
:label="labelledValue"
|
|
51
51
|
:variant="badgeVariant"
|
|
52
52
|
:colorMap="badgeColorMap"
|
|
53
|
-
:colorKey="badgeColorKey"
|
|
53
|
+
:colorKey="badgeColorKey">
|
|
54
|
+
<template v-if="badgeLook.icon" #icon>
|
|
55
|
+
<CnIcon :name="badgeLook.icon" :size="14" class="cn-cell-renderer__badge-icon" />
|
|
56
|
+
</template>
|
|
57
|
+
</CnStatusBadge>
|
|
54
58
|
<span v-else class="cn-cell-renderer__dash">—</span>
|
|
55
59
|
</template>
|
|
56
60
|
|
|
@@ -376,6 +380,7 @@ import CnGroupNameCell from './CnGroupNameCell.vue'
|
|
|
376
380
|
import { normalizeLook } from '../../composables/useLook.js'
|
|
377
381
|
import { ageInDays, boardDateLocale, formatAge, formatBoardDate, formatRelativeDate, formatTimeOfDay, resolveAgeVariant } from '../../utils/boardDate.js'
|
|
378
382
|
import { parseDateValue, resolveDateVariant } from '../../utils/dateVariant.js'
|
|
383
|
+
import { pillLook } from '../../utils/detailActionModel.js'
|
|
379
384
|
import { resolveDue } from '../../utils/dueText.js'
|
|
380
385
|
import { formatMoney } from '../../utils/formatMetric.js'
|
|
381
386
|
import { objectFieldValue } from '../../utils/objectName.js'
|
|
@@ -1177,9 +1182,25 @@ export default {
|
|
|
1177
1182
|
return Object.keys(map).some((key) => key.toLowerCase() === raw) ? String(this.value) : ''
|
|
1178
1183
|
},
|
|
1179
1184
|
|
|
1180
|
-
/**
|
|
1185
|
+
/**
|
|
1186
|
+
* What the built-in `badge` widget takes from the record its value
|
|
1187
|
+
* points at (`widgetProps.looks`, filled by CnIndexPage from
|
|
1188
|
+
* `widgetProps.resolve`): a tone and an icon, or nothing.
|
|
1189
|
+
*
|
|
1190
|
+
* @return {{variant?: string, colorMap?: null, icon?: string}}
|
|
1191
|
+
* @spec openspec/changes/pill-color-field/specs/pill-color-field/spec.md#requirement-a-badge-cell-takes-its-tone-and-icon-from-the-referenced-record
|
|
1192
|
+
*/
|
|
1193
|
+
badgeLook() {
|
|
1194
|
+
const looks = this.widgetProps && this.widgetProps.looks
|
|
1195
|
+
if (!looks || typeof looks !== 'object' || !this.hasValue || typeof this.value === 'object') {
|
|
1196
|
+
return {}
|
|
1197
|
+
}
|
|
1198
|
+
return pillLook(looks[String(this.value)])
|
|
1199
|
+
},
|
|
1200
|
+
|
|
1201
|
+
/** Variant for the built-in `badge` widget: the referenced record's tone, else `widgetProps.variant`, else `'default'`. */
|
|
1181
1202
|
badgeVariant() {
|
|
1182
|
-
return (this.widgetProps && this.widgetProps.variant) || 'default'
|
|
1203
|
+
return this.badgeLook.variant || (this.widgetProps && this.widgetProps.variant) || 'default'
|
|
1183
1204
|
},
|
|
1184
1205
|
|
|
1185
1206
|
/**
|
|
@@ -1194,6 +1215,9 @@ export default {
|
|
|
1194
1215
|
* @return {object|null}
|
|
1195
1216
|
*/
|
|
1196
1217
|
badgeColorMap() {
|
|
1218
|
+
if (this.badgeLook.variant) {
|
|
1219
|
+
return null
|
|
1220
|
+
}
|
|
1197
1221
|
return (this.widgetProps && this.widgetProps.colorMap) || this.enumColorMap || null
|
|
1198
1222
|
},
|
|
1199
1223
|
|
|
@@ -2830,6 +2830,7 @@ export default {
|
|
|
2830
2830
|
}
|
|
2831
2831
|
|
|
2832
2832
|
.cn-chart-widget__matrix-head {
|
|
2833
|
+
--nldesign-color-on-surface: var(--color-text-maxcontrast);
|
|
2833
2834
|
color: var(--color-text-maxcontrast);
|
|
2834
2835
|
padding: 6px;
|
|
2835
2836
|
}
|
|
@@ -2866,7 +2867,11 @@ export default {
|
|
|
2866
2867
|
outline-offset: -3px;
|
|
2867
2868
|
}
|
|
2868
2869
|
|
|
2870
|
+
/* A cell is a span: its ink also goes to --nldesign-color-on-surface, which a
|
|
2871
|
+
theme that forces the body ink onto every span (thematiq) reads. Level 3
|
|
2872
|
+
leaves the theme's body ink in place: white on its tint is below 4.5:1. */
|
|
2869
2873
|
.cn-chart-widget__matrix-cell--1 {
|
|
2874
|
+
--nldesign-color-on-surface: var(--color-primary-element-light-text);
|
|
2870
2875
|
background: var(--color-primary-element-light);
|
|
2871
2876
|
color: var(--color-primary-element-light-text);
|
|
2872
2877
|
}
|
|
@@ -2882,6 +2887,7 @@ export default {
|
|
|
2882
2887
|
}
|
|
2883
2888
|
|
|
2884
2889
|
.cn-chart-widget__matrix-cell--4 {
|
|
2890
|
+
--nldesign-color-on-surface: var(--color-primary-element-text);
|
|
2885
2891
|
background: var(--color-primary-element);
|
|
2886
2892
|
color: var(--color-primary-element-text);
|
|
2887
2893
|
}
|
|
@@ -522,7 +522,6 @@ export default {
|
|
|
522
522
|
still legible (DqVolgendeStap), not faded. */
|
|
523
523
|
.cn-choice-cards__row--disabled,
|
|
524
524
|
.cn-choice-cards__row--disabled:hover {
|
|
525
|
-
--nldesign-color-on-surface: var(--color-text-maxcontrast);
|
|
526
525
|
border-color: var(--color-border);
|
|
527
526
|
background: var(--color-background-hover);
|
|
528
527
|
color: var(--color-text-maxcontrast);
|
|
@@ -532,7 +531,6 @@ export default {
|
|
|
532
531
|
/* The title takes the muted ink itself: a theme that colours every label
|
|
533
532
|
with `!important` (thematiq) would otherwise hand it the label colour. */
|
|
534
533
|
.cn-choice-cards__row--disabled .cn-choice-cards__row-title {
|
|
535
|
-
--nldesign-color-on-surface: var(--color-text-maxcontrast);
|
|
536
534
|
color: var(--color-text-maxcontrast);
|
|
537
535
|
}
|
|
538
536
|
|
|
@@ -600,7 +598,6 @@ export default {
|
|
|
600
598
|
with `!important` (thematiq) reaches a span that only inherits. */
|
|
601
599
|
.cn-choice-cards__row-description,
|
|
602
600
|
.cn-choice-cards__reason {
|
|
603
|
-
--nldesign-color-on-surface: var(--color-text-maxcontrast);
|
|
604
601
|
font-size: 13px;
|
|
605
602
|
font-weight: 400;
|
|
606
603
|
color: var(--color-text-maxcontrast);
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
<template v-if="!isBoardLook">
|
|
97
97
|
<CnActionButtons
|
|
98
98
|
v-if="headerActions && headerActions.length"
|
|
99
|
-
:actions="
|
|
99
|
+
:actions="linkedHeaderActions"
|
|
100
100
|
data-testid="cn-dashboard-page-header-actions" />
|
|
101
101
|
<!-- @slot header-actions Inline buttons rendered in the dashboard header next to the edit toggle. Used by every existing consumer (decidesk, launchpad, opencatalogi, pipelinq, procest). -->
|
|
102
102
|
<slot name="header-actions" />
|
|
@@ -169,7 +169,7 @@
|
|
|
169
169
|
<CnBuildiqEditButton />
|
|
170
170
|
<CnActionButtons
|
|
171
171
|
v-if="headerActions && headerActions.length"
|
|
172
|
-
:actions="
|
|
172
|
+
:actions="linkedHeaderActions"
|
|
173
173
|
data-testid="cn-dashboard-page-header-actions" />
|
|
174
174
|
<slot name="header-actions" />
|
|
175
175
|
<slot name="actions" />
|
|
@@ -1042,6 +1042,7 @@ import { useIntegrationRegistry } from '../../composables/useIntegrationRegistry
|
|
|
1042
1042
|
import { normalizeLook } from '../../composables/useLook.js'
|
|
1043
1043
|
import { pageViews } from '../../mixins/pageViews.js'
|
|
1044
1044
|
import { mergeUserLayout, resolveUserLayoutApi } from '../../store/plugins/dashboardLayouts.js'
|
|
1045
|
+
import { headerActionAsLink } from '../../utils/actionLink.js'
|
|
1045
1046
|
import { isAppInstalled } from '../../utils/appInstalled.js'
|
|
1046
1047
|
import { contentHeaderLink } from '../../utils/contentHeaderLink.js'
|
|
1047
1048
|
import { pickDeclaredProps } from '../../utils/declaredProps.js'
|
|
@@ -1693,9 +1694,12 @@ export default {
|
|
|
1693
1694
|
* in the dashboard header via CnActionButtons — `open-form` (schema
|
|
1694
1695
|
* create dialog), `api-call` (POST/PUT + toast + refresh), `toggle`
|
|
1695
1696
|
* (two-way state button), `navigate` / `open-modal` / `refresh`, each
|
|
1696
|
-
* with an optional `visibleWhen` predicate.
|
|
1697
|
-
*
|
|
1698
|
-
*
|
|
1697
|
+
* with an optional `visibleWhen` predicate. An entry with `href` is a
|
|
1698
|
+
* link button, never dispatched: an absolute `http(s)`, `mailto:`,
|
|
1699
|
+
* `tel:` or `//host/...` URL as written, an instance path (leading `/`) through
|
|
1700
|
+
* `generateUrl()`, in a new tab with `target: '_blank'`. Empty (the
|
|
1701
|
+
* default) renders nothing; the `#header-actions` slot still works
|
|
1702
|
+
* alongside it for bespoke buttons.
|
|
1699
1703
|
*
|
|
1700
1704
|
* @type {Array<object>}
|
|
1701
1705
|
*/
|
|
@@ -2102,6 +2106,17 @@ export default {
|
|
|
2102
2106
|
return typeof this.cnTranslate === 'function' ? this.cnTranslate : (key) => key
|
|
2103
2107
|
},
|
|
2104
2108
|
|
|
2109
|
+
/**
|
|
2110
|
+
* The header actions handed to CnActionButtons, an entry with `href`
|
|
2111
|
+
* in its link form (resolved URL, anchor target, no handler).
|
|
2112
|
+
*
|
|
2113
|
+
* @spec openspec/changes/header-action-href/specs/header-action-href/spec.md#requirement-a-header-action-with-href-is-a-link-that-runs-and-emits-nothing
|
|
2114
|
+
* @return {Array<object>}
|
|
2115
|
+
*/
|
|
2116
|
+
linkedHeaderActions() {
|
|
2117
|
+
return (this.headerActions || []).map(headerActionAsLink)
|
|
2118
|
+
},
|
|
2119
|
+
|
|
2105
2120
|
/**
|
|
2106
2121
|
* The greeting for the time of day, with the reader's first (or
|
|
2107
2122
|
* full) name when known, or '' when `greeting` is off.
|