@conduction/nextcloud-vue 2.99.0 → 2.101.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/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js +6 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +2 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue.js +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js +22 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js +26 -16
- 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 +51 -7
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +104 -73
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +25 -8
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +5 -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 +11 -8
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +13 -4
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue.js +9 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue2.js +139 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue3.js +76 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +54 -3
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js +16 -2
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +160 -2
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +206 -94
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/filesReview.js +61 -0
- package/dist/esm/components/CnFilesBrowser/filesReview.js.map +1 -0
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue.js +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js +42 -7
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js +121 -57
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue2.js +10 -0
- package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue3.js +2 -1
- package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue3.js.map +1 -1
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue.js +9 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue2.js +279 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue3.js +122 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnGroupedCardsWidget/index.js +29 -0
- package/dist/esm/components/CnGroupedCardsWidget/index.js.map +1 -0
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +387 -78
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +317 -209
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useNamedSource.js +4 -1
- package/dist/esm/components/CnIndexPage/useNamedSource.js.map +1 -1
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue.js +1 -1
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue2.js +15 -0
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +14 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +14 -6
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue.js +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +10 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +6 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue.js +1 -1
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js +91 -4
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js.map +1 -1
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js +63 -38
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +68 -7
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +256 -240
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue.js +9 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue.js.map +1 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue2.js +175 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue3.js +77 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue.js +1 -1
- package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue2.js +38 -9
- package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue2.js.map +1 -1
- package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue3.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue.js +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +51 -4
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +40 -25
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +4 -0
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue.js +1 -1
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js +7 -7
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue3.js.map +1 -1
- package/dist/esm/composables/indexSources.js +167 -20
- package/dist/esm/composables/indexSources.js.map +1 -1
- package/dist/esm/composables/useEndpointSource.js +28 -6
- package/dist/esm/composables/useEndpointSource.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +43 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +41 -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 +1101 -396
- package/dist/esm/utils/languageMapText.js +50 -0
- package/dist/esm/utils/languageMapText.js.map +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js +3 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/mapList.js +71 -0
- package/dist/esm/utils/mapList.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 +9996 -7378
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +1101 -396
- package/l10n/en.json +43 -1
- package/l10n/nl.json +41 -1
- package/package.json +1 -1
- package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +7 -1
- package/src/components/CnChoiceCards/CnChoiceCards.md +39 -0
- package/src/components/CnChoiceCards/CnChoiceCards.vue +93 -16
- package/src/components/CnDashboardPage/CnDashboardPage.vue +89 -20
- package/src/components/CnDetailPage/CnDetailPage.vue +28 -9
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +13 -4
- package/src/components/CnExportsWidget/CnExportsWidget.vue +233 -0
- package/src/components/CnExportsWidget/index.js +7 -0
- package/src/components/CnFactsWidget/CnFactsWidget.vue +65 -3
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +324 -0
- package/src/components/CnFilesBrowser/filesReview.js +57 -0
- package/src/components/CnFlowsPage/CnFlowBoard.vue +77 -2
- package/src/components/CnFlowsPage/CnFlowEditorPage.vue +11 -0
- package/src/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue +433 -0
- package/src/components/CnGroupedCardsWidget/index.js +28 -0
- package/src/components/CnIndexPage/CnIndexPage.vue +376 -11
- package/src/components/CnIndexPage/useNamedSource.js +4 -1
- package/src/components/CnMapWidget/CnMapWidget.vue +37 -0
- package/src/components/CnObjectListWidget/CnObjectListWidget.vue +29 -1
- package/src/components/CnObjectSidebar/CnFilesTab.vue +15 -0
- package/src/components/CnOrderedListField/CnOrderedListField.vue +151 -5
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +114 -7
- package/src/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue +272 -0
- package/src/components/CnSavedViewAlertWidget/index.js +7 -0
- package/src/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue +38 -9
- package/src/components/CnSetupWizard/CnSetupWizard.vue +72 -5
- package/src/components/CnWidgetGrid/builtInWidgets.js +4 -0
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
- package/src/components/CnWizardDialog/CnWizardDialog.vue +7 -7
- package/src/components/index.js +3 -0
- package/src/composables/indexSources.js +166 -19
- package/src/composables/useEndpointSource.js +28 -6
- package/src/css/detail-page.css +15 -0
- package/src/css/dialog.css +48 -0
- package/src/css/index-page.css +117 -0
- package/src/css/look-board.css +127 -1
- package/src/index.js +1 -0
- package/src/schemas/app-manifest-v2.schema.json +55 -1
- package/src/utils/languageMapText.js +46 -0
- package/src/utils/libraryWidgetKeys.js +3 -0
- package/src/utils/mapList.js +67 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
package/src/css/look-board.css
CHANGED
|
@@ -99,6 +99,50 @@
|
|
|
99
99
|
padding-inline-start: 56px;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
/* The dashboard header as the board draws it (DqTermijnen): the actions on
|
|
103
|
+
the title's row, the description and its segmented period under both, at
|
|
104
|
+
the header's full width. As two flex columns the description sat in the
|
|
105
|
+
title's column only, so a long period group wrapped under its text and the
|
|
106
|
+
actions dropped to a line of their own. The title column never shrinks
|
|
107
|
+
below its longest word; the actions wrap their buttons first.
|
|
108
|
+
@spec openspec/changes/dashboard-board-header-row/specs/dashboard-page/spec.md#requirement-the-board-dashboard-header-keeps-its-actions-on-the-title-row */
|
|
109
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-dashboard-page__header {
|
|
110
|
+
display: grid;
|
|
111
|
+
grid-template-columns: minmax(min-content, 1fr) auto;
|
|
112
|
+
align-items: start;
|
|
113
|
+
column-gap: 16px;
|
|
114
|
+
row-gap: 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-dashboard-page__header-left {
|
|
118
|
+
display: contents;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-dashboard-page__title-row {
|
|
122
|
+
grid-column: 1;
|
|
123
|
+
grid-row: 1;
|
|
124
|
+
align-self: center;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-dashboard-page__header-left > :not(.cn-dashboard-page__title-row) {
|
|
128
|
+
grid-column: 1 / -1;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-dashboard-page__header > .cn-dashboard-page__header-actions {
|
|
132
|
+
grid-column: 2;
|
|
133
|
+
grid-row: 1;
|
|
134
|
+
justify-content: flex-end;
|
|
135
|
+
margin-inline-start: 0;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* A stat tile in the board's KPI row carries the board's own 18px 20px inset
|
|
139
|
+
(`cn-kpi-card--board`), so the card-fit cell adds none of its own: with
|
|
140
|
+
both the label sat 29px from the tile's top and 37px from its side, and
|
|
141
|
+
the row stood about 1.4 times the board's height. */
|
|
142
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-dashboard-page__kpi-cell .cn-dashboard-page__card-fit .cn-widget-wrapper__content:has(> .cn-kpi-card--board.cn-kpi-card--stacked) {
|
|
143
|
+
padding: 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
102
146
|
/* ---- The header button ------------------------------------------------- */
|
|
103
147
|
.cn-look-board .cn-index-page__header-buttons:not(.cn-look-nextcloud *),
|
|
104
148
|
.cn-look-board .cn-detail-page__header-actions:not(.cn-look-nextcloud *),
|
|
@@ -302,6 +346,40 @@
|
|
|
302
346
|
color: inherit;
|
|
303
347
|
}
|
|
304
348
|
|
|
349
|
+
/* A caption's edit pencil ("Mijn zaaktypen") sits on the caption's line at
|
|
350
|
+
its end, 4px in: a 28px round muted button with a 16px icon that adds no
|
|
351
|
+
height (DqZijbalk). It is placed absolutely because a theme may force the
|
|
352
|
+
caption to `display: block` at id strength (thematiq's Zuiddrecht sheet),
|
|
353
|
+
which put the pencil on a line of its own. */
|
|
354
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation-caption:has(.app-navigation-caption__actions) {
|
|
355
|
+
position: relative;
|
|
356
|
+
padding-inline-end: 36px;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation-caption .app-navigation-caption__actions {
|
|
360
|
+
--default-clickable-area: 28px;
|
|
361
|
+
position: absolute;
|
|
362
|
+
inset-block-start: -6px;
|
|
363
|
+
inset-inline-end: 4px;
|
|
364
|
+
margin: 0;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation-caption .app-navigation-caption__actions .button-vue {
|
|
368
|
+
--nldesign-color-on-surface: var(--color-text-maxcontrast);
|
|
369
|
+
width: 28px;
|
|
370
|
+
min-width: 28px;
|
|
371
|
+
height: 28px;
|
|
372
|
+
min-height: 28px;
|
|
373
|
+
padding: 0;
|
|
374
|
+
border-radius: 14px;
|
|
375
|
+
color: var(--color-text-maxcontrast);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation-caption .app-navigation-caption__actions .button-vue svg {
|
|
379
|
+
width: 16px;
|
|
380
|
+
height: 16px;
|
|
381
|
+
}
|
|
382
|
+
|
|
305
383
|
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation-entry,
|
|
306
384
|
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation-entry-link {
|
|
307
385
|
min-height: 42px;
|
|
@@ -316,7 +394,15 @@
|
|
|
316
394
|
color: var(--color-main-text);
|
|
317
395
|
}
|
|
318
396
|
|
|
397
|
+
/* The open entry sits on the tonal primary. NcAppNavigationItem paints an
|
|
398
|
+
active entry with a 16% (22% hovered) primary mix at `!important`, so the
|
|
399
|
+
board value needs `!important` too; the selector is the more specific one.
|
|
400
|
+
The link carries the same ground. */
|
|
319
401
|
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation-entry.active,
|
|
402
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation-entry.active:hover {
|
|
403
|
+
background-color: var(--color-primary-element-light) !important;
|
|
404
|
+
}
|
|
405
|
+
|
|
320
406
|
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation-entry.active .app-navigation-entry-link {
|
|
321
407
|
background: var(--color-primary-element-light);
|
|
322
408
|
color: var(--color-primary-element-light-text);
|
|
@@ -362,9 +448,11 @@
|
|
|
362
448
|
font-weight: 700;
|
|
363
449
|
}
|
|
364
450
|
|
|
451
|
+
/* White on the error colour: --color-error-text is the error colour for text on
|
|
452
|
+
a light ground (#8A0000 under thematiq), not the text on an error pill. */
|
|
365
453
|
.cn-look-board .cn-app-nav__count--attention {
|
|
366
454
|
background: var(--color-error);
|
|
367
|
-
color: var(--color-
|
|
455
|
+
color: var(--color-primary-element-text);
|
|
368
456
|
}
|
|
369
457
|
|
|
370
458
|
/* The footer: Help, then Advanced, whatever the declared order. */
|
|
@@ -951,6 +1039,44 @@
|
|
|
951
1039
|
--nldesign-color-on-surface: var(--cn-status-badge-ink);
|
|
952
1040
|
}
|
|
953
1041
|
|
|
1042
|
+
/* ---- Info notes (NcNoteCard type="info") -------------------------------- */
|
|
1043
|
+
/* The board's info note is a light-blue rounded box: no edge bar, 12px 14px
|
|
1044
|
+
of padding, radius 8, an 18px icon 10px before the text, 14px text in the
|
|
1045
|
+
deep primary ink at 1.5, and a bold heading line (DqBesluit and 13 other
|
|
1046
|
+
boards). NcNoteCard paints its ground and ink with `!important`, and a
|
|
1047
|
+
theme forces the body ink onto every p and span (thematiq), so the ground,
|
|
1048
|
+
the ink and the paragraph colour carry `!important` here too, scoped to
|
|
1049
|
+
the board look; the ink also goes to --nldesign-color-on-surface. */
|
|
1050
|
+
.cn-look-board .notecard.notecard--info:not(.cn-look-nextcloud *) {
|
|
1051
|
+
--nldesign-color-on-surface: var(--color-primary-element-light-text);
|
|
1052
|
+
--note-card-icon-size: 18px;
|
|
1053
|
+
--note-theme: var(--color-primary-element-light-text);
|
|
1054
|
+
gap: 10px;
|
|
1055
|
+
padding: 12px 14px;
|
|
1056
|
+
border-inline-start: 0;
|
|
1057
|
+
border-radius: 8px;
|
|
1058
|
+
background-color: var(--color-primary-element-light) !important;
|
|
1059
|
+
color: var(--color-primary-element-light-text) !important;
|
|
1060
|
+
font-size: 14px;
|
|
1061
|
+
line-height: 1.5;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
.cn-look-board .notecard.notecard--info:not(.cn-look-nextcloud *) p {
|
|
1065
|
+
color: var(--color-primary-element-light-text) !important;
|
|
1066
|
+
font-size: inherit;
|
|
1067
|
+
line-height: inherit;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
.cn-look-board .notecard.notecard--info:not(.cn-look-nextcloud *) .notecard__heading {
|
|
1071
|
+
font-size: inherit;
|
|
1072
|
+
font-weight: 700 !important;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
.cn-look-board .notecard.notecard--info:not(.cn-look-nextcloud *) .notecard__icon {
|
|
1076
|
+
padding-top: 1px;
|
|
1077
|
+
color: var(--color-primary-element-light-text);
|
|
1078
|
+
}
|
|
1079
|
+
|
|
954
1080
|
/* ---- Date and age cells (screens-cell-date-parity) ---------------------- */
|
|
955
1081
|
/* The board sets every waiting time ("3 dagen", "4 uur") in weight 600; a
|
|
956
1082
|
late one is red through its variant class. */
|
package/src/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"$id": "https://raw.githubusercontent.com/ConductionNL/nextcloud-vue/main/src/schemas/app-manifest-v2.schema.json",
|
|
4
4
|
"title": "Conduction App Manifest v2",
|
|
5
5
|
"description": "v2 schema for the JSON-driven page and navigation manifest consumed by @conduction/nextcloud-vue. Introduces a uniform widgets[] array on every page type with a per-slot grid coordinate system, a typed actions[] discriminator, and the required $schema field for version detection. v1 manifests continue to validate against app-manifest.schema.json (unchanged).",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.124.0",
|
|
7
7
|
"type": "object",
|
|
8
8
|
"required": ["$schema", "version"],
|
|
9
9
|
"allOf": [
|
|
@@ -97,6 +97,9 @@
|
|
|
97
97
|
"type": { "type": "string", "enum": ["info", "config-fields", "choice", "run-action", "summary", "component"], "description": "Built-in step renderer." },
|
|
98
98
|
"title": { "type": "string" },
|
|
99
99
|
"body": { "type": "string", "description": "info: explanatory copy." },
|
|
100
|
+
"note": { "type": "string", "minLength": 1, "description": "choice: a footnote under the options, translated like body." },
|
|
101
|
+
"visibleWhen": { "description": "Offer the step only when the setup status says so: a dotted path into the setup status document whose value must be truthy, or { path, equals } for an exact value. Hidden while the status loads.", "oneOf": [ { "type": "string", "minLength": 1 }, { "type": "object", "required": ["path"], "additionalProperties": false, "properties": { "path": { "type": "string", "minLength": 1 }, "equals": {} } } ] },
|
|
102
|
+
"footnote": { "type": "string", "minLength": 1, "description": "choice: the same footnote under another name; note wins when both are set." },
|
|
100
103
|
"required": { "type": "boolean", "default": false, "description": "When true the step gates the app until done." },
|
|
101
104
|
"schema": { "description": "config-fields: a JSON Schema ref (string) or inline object rendered via fieldsFromSchema." },
|
|
102
105
|
"configKey": { "type": "string", "description": "choice: app-config key the selection is written to." },
|
|
@@ -4024,6 +4027,14 @@
|
|
|
4024
4027
|
"type": "boolean",
|
|
4025
4028
|
"description": "false removes Request a feature, Report a bug and Documentation, for an app that offers them in its own help menu."
|
|
4026
4029
|
},
|
|
4030
|
+
"showMarkUnread": {
|
|
4031
|
+
"type": "boolean",
|
|
4032
|
+
"description": "false removes the built-in Mark as unread entry."
|
|
4033
|
+
},
|
|
4034
|
+
"showOpenSidebar": {
|
|
4035
|
+
"type": "boolean",
|
|
4036
|
+
"description": "false removes the built-in Open sidebar entry of the board look."
|
|
4037
|
+
},
|
|
4027
4038
|
"label": {
|
|
4028
4039
|
"type": "string",
|
|
4029
4040
|
"minLength": 1,
|
|
@@ -4333,6 +4344,20 @@
|
|
|
4333
4344
|
"minLength": 1,
|
|
4334
4345
|
"description": "type='detail', board look: the meta line on row 2 of the header, after the breadcrumb and a middle dot (screens-detail-page-parity). A field template such as `\"via {channel}\"`: every `{path}` is read from the record, and a line with an empty value is dropped. Maps to CnDetailPage `headerMeta`. type='index' | 'dashboard' | 'settings' (page-header-breadcrumb): the note after the breadcrumb and a middle dot under the title; on an index page `{total}` and `{shown}` are the list's counts."
|
|
4335
4346
|
},
|
|
4347
|
+
"headerMetaCounts": {
|
|
4348
|
+
"type": "object",
|
|
4349
|
+
"description": "type='index': the other lists headerMeta counts, by name. Each is read as one list total and fills `{count:<name>}` in headerMeta (\"{total} contracten bij {count:suppliers} leveranciers\"); while a count loads or when it fails, the note is left out.",
|
|
4350
|
+
"additionalProperties": {
|
|
4351
|
+
"type": "object",
|
|
4352
|
+
"required": ["register", "schema"],
|
|
4353
|
+
"additionalProperties": false,
|
|
4354
|
+
"properties": {
|
|
4355
|
+
"register": { "type": "string", "minLength": 1 },
|
|
4356
|
+
"schema": { "type": "string", "minLength": 1 },
|
|
4357
|
+
"filter": { "type": "object" }
|
|
4358
|
+
}
|
|
4359
|
+
}
|
|
4360
|
+
},
|
|
4336
4361
|
"tabsLabel": {
|
|
4337
4362
|
"type": "string",
|
|
4338
4363
|
"minLength": 1,
|
|
@@ -4348,6 +4373,35 @@
|
|
|
4348
4373
|
"default": true,
|
|
4349
4374
|
"description": "type='dashboard' and type='detail': `false` drops the overflow Actions menu from every widget that does not set `showActions` itself, for a dashboard whose widget headers carry a header link and nothing else (zuiddrecht-pixel-gaps-2), or a record page whose data cards carry none (zuiddrecht-pixel-gaps-3; a card with an Add action keeps it). When the key is not set a detail page keeps the menu, except under the board look, where side cards carry none (screens-detail-page-parity). Maps to CnDashboardPage / CnDetailPage `showWidgetActions`."
|
|
4350
4375
|
},
|
|
4376
|
+
"pageFilters": {
|
|
4377
|
+
"type": "array",
|
|
4378
|
+
"description": "type='dashboard': page-level filter controls in the header. Each selection is written into the page's workspace context, so a widget reads it through a `@page.<key>` / `@workspace.<key>` token (an endpoint widget also in its `responsePath`). Maps to the CnDashboardPage `pageFilters` prop.",
|
|
4379
|
+
"items": {
|
|
4380
|
+
"type": "object",
|
|
4381
|
+
"required": ["key", "options"],
|
|
4382
|
+
"additionalProperties": false,
|
|
4383
|
+
"properties": {
|
|
4384
|
+
"key": { "type": "string", "minLength": 1, "description": "Workspace-context key written on change (the `@page.<key>` / `@workspace.<key>` token name)." },
|
|
4385
|
+
"label": { "type": "string", "description": "Control label (i18n key or plain text)." },
|
|
4386
|
+
"type": { "type": "string", "enum": ["select"], "default": "select", "description": "Control type, carried over from v1." },
|
|
4387
|
+
"control": { "type": "string", "enum": ["select", "segmented"], "default": "select", "description": "How the filter is drawn: a select, or a compact segmented group." },
|
|
4388
|
+
"placement": { "type": "string", "enum": ["row", "description"], "default": "row", "description": "Where the filter sits: in the header's filter row, or (a segmented group) on the description line after the period group (DqProcesanalyse)." },
|
|
4389
|
+
"default": { "type": ["string", "number"], "description": "Initial value seeded into the context on mount; the first option's value when omitted." },
|
|
4390
|
+
"options": {
|
|
4391
|
+
"type": "array",
|
|
4392
|
+
"items": {
|
|
4393
|
+
"type": "object",
|
|
4394
|
+
"required": ["value", "label"],
|
|
4395
|
+
"additionalProperties": false,
|
|
4396
|
+
"properties": {
|
|
4397
|
+
"value": { "type": ["string", "number"], "description": "Value written into the context when picked." },
|
|
4398
|
+
"label": { "type": "string", "description": "Display text (i18n key or plain text)." }
|
|
4399
|
+
}
|
|
4400
|
+
}
|
|
4401
|
+
}
|
|
4402
|
+
}
|
|
4403
|
+
}
|
|
4404
|
+
},
|
|
4351
4405
|
"kpiRow": {
|
|
4352
4406
|
"type": "array",
|
|
4353
4407
|
"items": { "type": "string" },
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
3
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { getLanguage } from '@nextcloud/l10n'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The user's Nextcloud language as a bare code (`nl_NL` reads `nl`), or ''.
|
|
10
|
+
*
|
|
11
|
+
* @return {string} The code.
|
|
12
|
+
*/
|
|
13
|
+
function userLanguage() {
|
|
14
|
+
try {
|
|
15
|
+
return String(getLanguage() || '').split(/[-_]/)[0].toLowerCase()
|
|
16
|
+
} catch {
|
|
17
|
+
return ''
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The text of a value that may be a language map (`{ nl: 'Ontvangst', en:
|
|
23
|
+
* 'Intake' }`), in the user's Nextcloud language, then Dutch, then English,
|
|
24
|
+
* then the first text it holds. A plain value comes back as text; anything
|
|
25
|
+
* else as ''.
|
|
26
|
+
*
|
|
27
|
+
* @param {(string|number|object|null|undefined)} value The value.
|
|
28
|
+
* @return {string} The text.
|
|
29
|
+
* @spec openspec/changes/grouped-cards-widget/specs/grouped-cards-widget/spec.md#requirement-a-widget-draws-groups-of-cards-from-an-endpoint
|
|
30
|
+
*/
|
|
31
|
+
export function languageMapText(value) {
|
|
32
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
33
|
+
return String(value)
|
|
34
|
+
}
|
|
35
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
36
|
+
return ''
|
|
37
|
+
}
|
|
38
|
+
const language = userLanguage()
|
|
39
|
+
for (const key of [language, 'nl', 'en']) {
|
|
40
|
+
if (key && typeof value[key] === 'string' && value[key] !== '') {
|
|
41
|
+
return value[key]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const first = Object.values(value).find((text) => typeof text === 'string' && text !== '')
|
|
45
|
+
return first || ''
|
|
46
|
+
}
|
|
@@ -71,6 +71,8 @@ export const BUILT_IN_WIDGET_KEYS = Object.freeze([
|
|
|
71
71
|
'header',
|
|
72
72
|
'text',
|
|
73
73
|
'divider',
|
|
74
|
+
'saved-view-alert',
|
|
75
|
+
'exports',
|
|
74
76
|
])
|
|
75
77
|
|
|
76
78
|
/**
|
|
@@ -109,6 +111,7 @@ export const DASHBOARD_CATALOG_WIDGET_KEYS = Object.freeze([
|
|
|
109
111
|
'files',
|
|
110
112
|
'flow-runs',
|
|
111
113
|
'gauge',
|
|
114
|
+
'grouped-cards',
|
|
112
115
|
'header',
|
|
113
116
|
'image',
|
|
114
117
|
'interaction-form',
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
3
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
*/
|
|
5
|
+
import { isBadgeVariant } from './badgeVariants.js'
|
|
6
|
+
import { fillTemplate } from './fillTemplate.js'
|
|
7
|
+
import { readPath } from './readPath.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The numbered list beside an index map (DqZakenKaart): one entry per row
|
|
11
|
+
* that has a place on the map, numbered in list order so the number on the
|
|
12
|
+
* pin and the number in the list are the same, and the rows without one.
|
|
13
|
+
*
|
|
14
|
+
* `spec` is `mapConfig.list`: `{ title, sub?, pills?: [{ path?, text?, map?,
|
|
15
|
+
* colorMap? }], due? }`. `title`, `sub` and `due` are field templates
|
|
16
|
+
* (`"{title}"`, `"{address} · {identifier}"`, `"{deadline|date}"`), already
|
|
17
|
+
* translated by the caller; a pill reads `path` (or shows `text`), maps it
|
|
18
|
+
* through `map`, and takes its tone from `colorMap` by the raw value.
|
|
19
|
+
*
|
|
20
|
+
* @param {Array<object>} rows The rows, in display order.
|
|
21
|
+
* @param {object} spec The list declaration.
|
|
22
|
+
* @param {object} options How to read a row.
|
|
23
|
+
* @param {string} options.rowKey The row's key field.
|
|
24
|
+
* @param {Function} options.located Whether a row has a place on the map.
|
|
25
|
+
* @param {Function} [options.translate] The host's translate, for pill labels.
|
|
26
|
+
* @return {{items: Array<{key: string, n: number, row: object, title: string, sub: string, due: string, pills: Array<{label: string, variant: string}>}>, missing: Array<object>}}
|
|
27
|
+
*/
|
|
28
|
+
export function mapListItems(rows, spec, { rowKey, located, translate = (text) => text }) {
|
|
29
|
+
const items = []
|
|
30
|
+
const missing = []
|
|
31
|
+
const list = spec && typeof spec === 'object' ? spec : {}
|
|
32
|
+
for (const row of Array.isArray(rows) ? rows : []) {
|
|
33
|
+
if (!located(row)) {
|
|
34
|
+
missing.push(row)
|
|
35
|
+
continue
|
|
36
|
+
}
|
|
37
|
+
const pills = (Array.isArray(list.pills) ? list.pills : [])
|
|
38
|
+
.map((pill) => {
|
|
39
|
+
if (!pill || typeof pill !== 'object') {
|
|
40
|
+
return null
|
|
41
|
+
}
|
|
42
|
+
const raw = typeof pill.path === 'string' && pill.path !== '' ? readPath(row, pill.path) : undefined
|
|
43
|
+
const mapped = pill.map && (typeof raw === 'string' || typeof raw === 'number') && Object.hasOwn(pill.map, raw) ? pill.map[raw] : undefined
|
|
44
|
+
const text = mapped ?? pill.text ?? raw
|
|
45
|
+
if (typeof text !== 'string' && typeof text !== 'number') {
|
|
46
|
+
return null
|
|
47
|
+
}
|
|
48
|
+
const label = translate(String(text))
|
|
49
|
+
if (label === '') {
|
|
50
|
+
return null
|
|
51
|
+
}
|
|
52
|
+
const tone = pill.colorMap && (typeof raw === 'string' || typeof raw === 'number') ? pill.colorMap[raw] : pill.variant
|
|
53
|
+
return { label, variant: isBadgeVariant(tone) ? tone : 'default' }
|
|
54
|
+
})
|
|
55
|
+
.filter(Boolean)
|
|
56
|
+
items.push({
|
|
57
|
+
key: String(row[rowKey]),
|
|
58
|
+
n: items.length + 1,
|
|
59
|
+
row,
|
|
60
|
+
title: fillTemplate(list.title || '', row),
|
|
61
|
+
sub: fillTemplate(list.sub || '', row),
|
|
62
|
+
due: fillTemplate(list.due || '', row),
|
|
63
|
+
pills,
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
return { items, missing }
|
|
67
|
+
}
|