@conduction/nextcloud-vue 2.78.0 → 2.80.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/bundled-packages.json +0 -2
- package/dist/esm/bundled-packages.json +0 -2
- package/dist/esm/components/CnActionButtons/CnActionButtons.vue2.js.map +1 -1
- package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js +3 -1
- package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js +32 -3
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +115 -104
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +12 -2
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +39 -3
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +158 -0
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +157 -96
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +139 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +140 -92
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +77 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +5 -2
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +62 -4
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +85 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +43 -4
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +11 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +736 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js +238 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnFactsWidget/index.js +30 -0
- package/dist/esm/components/CnFactsWidget/index.js.map +1 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js +10 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js.map +1 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +551 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +183 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnFieldListWidget/index.js +29 -0
- package/dist/esm/components/CnFieldListWidget/index.js.map +1 -0
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +173 -5
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +181 -99
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/filesBrowser.js +29 -11
- package/dist/esm/components/CnFilesBrowser/filesBrowser.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/openRegisterSource.js +252 -0
- package/dist/esm/components/CnFilesBrowser/openRegisterSource.js.map +1 -0
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +66 -18
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +4 -4
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnFormPage/CnFormPage.vue2.js +18 -3
- package/dist/esm/components/CnFormPage/CnFormPage.vue2.js.map +1 -1
- package/dist/esm/components/CnFormPage/CnFormPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +330 -74
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +34 -15
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js +10 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js.map +1 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js +99 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js.map +1 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js +48 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js.map +1 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +100 -3
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +4 -2
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js +29 -1
- package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js +3 -2
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js.map +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +10 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js.map +1 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +387 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +169 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnRecordListWidget/index.js +31 -0
- package/dist/esm/components/CnRecordListWidget/index.js.map +1 -0
- package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue2.js.map +1 -1
- package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js +1 -1
- package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js.map +1 -1
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js +10 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js +351 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js +71 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnSectionsWidget/index.js +35 -0
- package/dist/esm/components/CnSectionsWidget/index.js.map +1 -0
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js +81 -2
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +1 -0
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +152 -8
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +84 -23
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +4 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +13 -0
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js +106 -2
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js +105 -53
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js.map +1 -1
- package/dist/esm/composables/useAppManifest.js +8 -3
- package/dist/esm/composables/useAppManifest.js.map +1 -1
- package/dist/esm/composables/useFormDraft.js +140 -9
- package/dist/esm/composables/useFormDraft.js.map +1 -1
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js +28 -20
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js +9 -0
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/field-inspection.js +21 -0
- package/dist/esm/integrations/builtin/field-inspection.js.map +1 -1
- package/dist/esm/integrations/offline/checklistSubmission.js +141 -0
- package/dist/esm/integrations/offline/checklistSubmission.js.map +1 -0
- package/dist/esm/integrations/offline/fieldCollectionHelpers.js +70 -5
- package/dist/esm/integrations/offline/fieldCollectionHelpers.js.map +1 -1
- package/dist/esm/integrations/offline/index.js +2 -1
- package/dist/esm/integrations/offline/index.js.map +1 -1
- package/dist/esm/integrations/offline/offlineDb.js +6 -1
- package/dist/esm/integrations/offline/offlineDb.js.map +1 -1
- package/dist/esm/integrations/offline/syncReplayService.js +8 -2
- package/dist/esm/integrations/offline/syncReplayService.js.map +1 -1
- package/dist/esm/l10n/en.json.js +72 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +120 -2
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +1314 -74
- package/dist/esm/utils/boardDate.js +193 -0
- package/dist/esm/utils/boardDate.js.map +1 -0
- package/dist/esm/utils/detailActionModel.js +60 -3
- package/dist/esm/utils/detailActionModel.js.map +1 -1
- package/dist/esm/utils/dynamicProperties.js +5 -1
- package/dist/esm/utils/dynamicProperties.js.map +1 -1
- package/dist/esm/utils/fillTemplate.js +114 -0
- package/dist/esm/utils/fillTemplate.js.map +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js +4 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/queryPresets.js +96 -0
- package/dist/esm/utils/queryPresets.js.map +1 -0
- package/dist/esm/utils/resolveFilterTokens.js +11 -0
- package/dist/esm/utils/resolveFilterTokens.js.map +1 -1
- package/dist/esm/utils/schema.js +21 -0
- package/dist/esm/utils/schema.js.map +1 -1
- package/dist/esm/utils/sentinelTokens.js +3 -3
- package/dist/esm/utils/sentinelTokens.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +57 -6
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/widgetDispatch.js +7 -1
- package/dist/esm/utils/widgetDispatch.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +14278 -8169
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +1314 -74
- package/l10n/en.json +72 -1
- package/l10n/nl.json +120 -2
- package/package.json +1 -1
- package/scripts/build-validators.js +26 -0
- package/src/components/CnActionButtons/CnActionButtons.vue +2 -0
- package/src/components/CnActionsBar/CnActionsBar.md +4 -0
- package/src/components/CnActionsBar/CnActionsBar.vue +83 -42
- package/src/components/CnAppRoot/CnAppRoot.vue +12 -2
- package/src/components/CnBannerWidget/CnBannerWidget.vue +39 -3
- package/src/components/CnCellRenderer/CnCellRenderer.vue +306 -2
- package/src/components/CnDashboardPage/CnDashboardPage.vue +219 -4
- package/src/components/CnDataTable/CnDataTable.md +2 -0
- package/src/components/CnDataTable/CnDataTable.vue +82 -2
- package/src/components/CnDetailPage/CnDetailPage.md +1 -1
- package/src/components/CnDetailPage/CnDetailPage.vue +63 -3
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +127 -1
- package/src/components/CnFactsWidget/CnFactsWidget.vue +1050 -0
- package/src/components/CnFactsWidget/index.js +29 -0
- package/src/components/CnFieldListWidget/CnFieldListWidget.vue +746 -0
- package/src/components/CnFieldListWidget/index.js +28 -0
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +232 -11
- package/src/components/CnFilesBrowser/filesBrowser.js +43 -2
- package/src/components/CnFilesBrowser/index.js +1 -0
- package/src/components/CnFilesBrowser/openRegisterSource.js +248 -0
- package/src/components/CnFormDialog/CnFormDialog.md +9 -3
- package/src/components/CnFormDialog/CnFormDialog.vue +70 -22
- package/src/components/CnFormPage/CnFormPage.vue +18 -3
- package/src/components/CnIndexPage/CnIndexPage.vue +281 -9
- package/src/components/CnIndexPage/CnIndexPageWidgets.vue +169 -0
- package/src/components/CnObjectSidebar/CnFilesTab.vue +103 -4
- package/src/components/CnPageRenderer/CnPageRenderer.vue +29 -1
- package/src/components/CnQuickFilterBar/CnQuickFilterBar.vue +3 -2
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +603 -0
- package/src/components/CnRecordListWidget/index.js +30 -0
- package/src/components/CnSavedViewsControl/CnSavedViewsControl.vue +1 -1
- package/src/components/CnSectionsWidget/CnSectionsWidget.vue +489 -0
- package/src/components/CnSectionsWidget/index.js +34 -0
- package/src/components/CnStagesWidget/CnStagesWidget.vue +81 -2
- package/src/components/CnStatWidget/CnStatWidget.vue +1 -1
- package/src/components/CnTabsWidget/CnTabsWidget.vue +214 -9
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +4 -0
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +13 -0
- package/src/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue +188 -4
- package/src/components/index.js +5 -1
- package/src/composables/__tests__/useFormDraft.spec.js +69 -0
- package/src/composables/useAppManifest.js +8 -3
- package/src/composables/useFormDraft.js +139 -8
- package/src/css/form-field.css +14 -0
- package/src/css/index-page.css +71 -0
- package/src/css/kpi-card.css +32 -0
- package/src/css/look-board-detail.css +87 -0
- package/src/css/look-board-index.css +143 -14
- package/src/css/look-board.css +114 -2
- package/src/css/table.css +56 -0
- package/src/index.js +8 -0
- package/src/integrations/builtin/field-inspection/CnFieldInspectionCard.vue +35 -20
- package/src/integrations/builtin/field-inspection.js +21 -0
- package/src/integrations/offline/checklistSubmission.js +137 -0
- package/src/integrations/offline/fieldCollectionHelpers.js +69 -4
- package/src/integrations/offline/index.js +3 -0
- package/src/integrations/offline/offlineDb.js +6 -1
- package/src/integrations/offline/syncReplayService.js +8 -2
- package/src/schemas/app-manifest-v2.schema.json +149 -5
- package/src/utils/boardDate.js +189 -0
- package/src/utils/detailActionModel.js +59 -2
- package/src/utils/dynamicProperties.js +5 -1
- package/src/utils/fillTemplate.js +110 -0
- package/src/utils/libraryWidgetKeys.js +4 -0
- package/src/utils/queryPresets.js +93 -0
- package/src/utils/resolveFilterTokens.js +11 -0
- package/src/utils/schema.js +21 -0
- package/src/utils/sentinelTokens.js +3 -3
- package/src/utils/validateManifestV2.compiled.js +57 -2
- package/src/utils/widgetDispatch.js +7 -1
- package/dist/esm/_virtual/equal.js +0 -4
- package/dist/esm/_virtual/equal.js.map +0 -1
- package/dist/esm/_virtual/ucs2length.js +0 -4
- package/dist/esm/_virtual/ucs2length.js.map +0 -1
- package/dist/esm/node_modules/ajv/dist/runtime/equal.js +0 -9
- package/dist/esm/node_modules/ajv/dist/runtime/equal.js.map +0 -1
- package/dist/esm/node_modules/ajv/dist/runtime/ucs2length.js +0 -25
- package/dist/esm/node_modules/ajv/dist/runtime/ucs2length.js.map +0 -1
- package/dist/esm/node_modules/fast-deep-equal/index.js +0 -47
- package/dist/esm/node_modules/fast-deep-equal/index.js.map +0 -1
|
@@ -107,16 +107,27 @@
|
|
|
107
107
|
margin-inline-start: 0;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
/* The first of Save view
|
|
111
|
-
the
|
|
112
|
-
|
|
110
|
+
/* The first of Save view and the Filter + view switch unit takes the free
|
|
111
|
+
space (the board's `flex: 1` spacer), so they sit at the end of row 1.
|
|
112
|
+
When the line is full the unit wraps as one to the START of the next line
|
|
113
|
+
while Save view stays at the end of row 1 (DqZaken); without Save view the
|
|
114
|
+
unit sits at the end of row 1 (PqTickets, PqLeads, PtPortals). */
|
|
115
|
+
.cn-look-board .cn-actions-bar--board > .cn-actions-bar__row--views > :is(.cn-saved-views__save, .cn-actions-bar__view-controls) {
|
|
113
116
|
margin-inline-start: auto;
|
|
114
117
|
}
|
|
115
118
|
|
|
116
|
-
.cn-look-board .cn-actions-bar--board > .cn-actions-bar__row--views >
|
|
119
|
+
.cn-look-board .cn-actions-bar--board > .cn-actions-bar__row--views > .cn-saved-views__save ~ .cn-actions-bar__view-controls {
|
|
117
120
|
margin-inline-start: 0;
|
|
118
121
|
}
|
|
119
122
|
|
|
123
|
+
.cn-look-board .cn-actions-bar--board .cn-actions-bar__view-controls {
|
|
124
|
+
display: flex;
|
|
125
|
+
flex: 0 0 auto;
|
|
126
|
+
flex-wrap: nowrap;
|
|
127
|
+
align-items: center;
|
|
128
|
+
gap: 8px;
|
|
129
|
+
}
|
|
130
|
+
|
|
120
131
|
/* Row 2: the search field and the active filters on a line of their own. */
|
|
121
132
|
.cn-look-board .cn-actions-bar--board > .cn-actions-bar__row--search {
|
|
122
133
|
display: flex;
|
|
@@ -202,16 +213,39 @@
|
|
|
202
213
|
color: var(--color-primary-element-text);
|
|
203
214
|
}
|
|
204
215
|
|
|
205
|
-
/* Save view: 34px, radius 17, on the light primary
|
|
216
|
+
/* Save view: a ghost button, 34px, radius 17, no border, on the light primary
|
|
217
|
+
tint, a 14px icon 6px before the label, on one line. */
|
|
206
218
|
.cn-look-board .cn-saved-views__save .button-vue {
|
|
207
219
|
min-height: 34px;
|
|
208
220
|
height: 34px;
|
|
209
|
-
padding: 0
|
|
221
|
+
padding: 0 12px;
|
|
222
|
+
border: 0;
|
|
210
223
|
border-radius: 17px;
|
|
211
224
|
background: var(--color-primary-element-light);
|
|
212
225
|
color: var(--color-primary-element-light-text);
|
|
213
226
|
font-size: 13px;
|
|
214
227
|
font-weight: 600;
|
|
228
|
+
white-space: nowrap;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.cn-look-board .cn-saved-views__save .button-vue:hover {
|
|
232
|
+
background: var(--color-primary-element-light-hover);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.cn-look-board .cn-saved-views__save .button-vue .button-vue__wrapper {
|
|
236
|
+
gap: 6px;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.cn-look-board .cn-saved-views__save .button-vue .button-vue__icon {
|
|
240
|
+
width: auto;
|
|
241
|
+
min-width: 0;
|
|
242
|
+
height: auto;
|
|
243
|
+
min-height: 0;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.cn-look-board .cn-saved-views__save .button-vue .button-vue__text {
|
|
247
|
+
margin: 0;
|
|
248
|
+
padding: 0;
|
|
215
249
|
}
|
|
216
250
|
|
|
217
251
|
/* Filter: a labelled secondary button, 36px, radius 8, with the active count. */
|
|
@@ -267,6 +301,15 @@
|
|
|
267
301
|
color: var(--color-main-text);
|
|
268
302
|
}
|
|
269
303
|
|
|
304
|
+
/* A segment the page cannot open: drawn, as the boards do, but faded and inert. */
|
|
305
|
+
.cn-look-board .cn-actions-bar--board .cn-actions-bar__view-toggle .cn-actions-bar__view-toggle-btn--disabled,
|
|
306
|
+
.cn-look-board .cn-actions-bar--board .cn-actions-bar__view-toggle .cn-actions-bar__view-toggle-btn--disabled:hover {
|
|
307
|
+
background: transparent !important;
|
|
308
|
+
color: var(--color-text-maxcontrast);
|
|
309
|
+
opacity: 0.5;
|
|
310
|
+
cursor: not-allowed;
|
|
311
|
+
}
|
|
312
|
+
|
|
270
313
|
/* The search field: 40px, radius 8, not a pill. */
|
|
271
314
|
.cn-look-board .cn-actions-bar--board .cn-actions-bar__search {
|
|
272
315
|
flex: 1 1 260px;
|
|
@@ -414,6 +457,48 @@
|
|
|
414
457
|
border-bottom: 0;
|
|
415
458
|
}
|
|
416
459
|
|
|
460
|
+
/* The table fits its card (screens-index-table-fit-parity). Under the auto
|
|
461
|
+
layout every one-line cell asked for its whole text up to the 22rem cap, so
|
|
462
|
+
seven text columns made a 1500px table in a 1118px card at a 1440px
|
|
463
|
+
viewport: the last columns and the row menus sat past the card's edge. The
|
|
464
|
+
fixed layout shares the card's width: the selection and menu columns keep
|
|
465
|
+
their own width, the first data column takes 18%, the others split the
|
|
466
|
+
rest, and a value that does not fit is cut with an ellipsis (its full text
|
|
467
|
+
stays in the cell's tooltip). A column's own `width` still wins. */
|
|
468
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table {
|
|
469
|
+
table-layout: fixed;
|
|
470
|
+
width: 100%;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table th.cn-table-head--title {
|
|
474
|
+
width: 18%;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/* The board's data cells sit 12px apart (PqTickets), the first one 18px from
|
|
478
|
+
the selection column; the selection and menu columns keep 16px. */
|
|
479
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table th:not(.cn-table-col--checkbox):not(.cn-table-col--actions):not(.cn-table-col--icon),
|
|
480
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table td:not(.cn-table-col--checkbox):not(.cn-table-col--actions):not(.cn-table-col--icon) {
|
|
481
|
+
padding-inline: 12px;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table th.cn-table-head--title,
|
|
485
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table td.cn-table-col--title {
|
|
486
|
+
padding-inline-start: 18px;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table td > .cn-cell-renderer {
|
|
490
|
+
display: block;
|
|
491
|
+
min-width: 0;
|
|
492
|
+
overflow: hidden;
|
|
493
|
+
text-overflow: ellipsis;
|
|
494
|
+
white-space: nowrap;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/* A narrow header cuts its label, not its filter funnel. */
|
|
498
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table th .cn-table-header__sort:has(~ .cn-table-header__filter) {
|
|
499
|
+
max-width: calc(100% - 26px);
|
|
500
|
+
}
|
|
501
|
+
|
|
417
502
|
/* The selection column: 28px, 18px checkboxes. */
|
|
418
503
|
.cn-look-board .cn-table-container--board .cn-data-table .cn-table-col--checkbox {
|
|
419
504
|
box-sizing: content-box;
|
|
@@ -443,6 +528,29 @@
|
|
|
443
528
|
text-decoration: none;
|
|
444
529
|
}
|
|
445
530
|
|
|
531
|
+
/* Only the title is underlined (DqZaken). An underline set on the cell
|
|
532
|
+
reaches every in-flow child whatever its own text-decoration, so the
|
|
533
|
+
secondary lines become inline blocks on a line of their own: an atomic
|
|
534
|
+
inline box is the one thing the underline does not reach. */
|
|
535
|
+
.cn-look-board .cn-table-container--board .cn-data-table td.cn-table-col--title .cn-table-cell__secondary {
|
|
536
|
+
display: inline-block;
|
|
537
|
+
width: 100%;
|
|
538
|
+
vertical-align: top;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/* `rowTitle: "plain"` (PqTickets, OcPublicaties): the title is bold text in
|
|
542
|
+
the main text colour without an underline, the secondary line 13px muted,
|
|
543
|
+
2px under it. The row stays clickable through its stretched row link. */
|
|
544
|
+
.cn-look-board .cn-table-container--board.cn-table-container--title-plain .cn-data-table td.cn-table-col--title {
|
|
545
|
+
font-weight: 700;
|
|
546
|
+
text-decoration: none;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
.cn-look-board .cn-table-container--board.cn-table-container--title-plain .cn-data-table td.cn-table-col--title .cn-table-cell__secondary {
|
|
550
|
+
margin-top: 2px;
|
|
551
|
+
font-size: 13px;
|
|
552
|
+
}
|
|
553
|
+
|
|
446
554
|
/* A status pill: 3px 10px, radius 12, 13px weight 600. The colours stay the
|
|
447
555
|
status colour map's. */
|
|
448
556
|
.cn-look-board .cn-table-container--board .cn-data-table .cn-status-badge {
|
|
@@ -465,15 +573,36 @@
|
|
|
465
573
|
--default-clickable-area: 34px;
|
|
466
574
|
}
|
|
467
575
|
|
|
576
|
+
/* The row menu: a 34px square, three dots, a grey border on the main
|
|
577
|
+
background (DqZaken, PqTickets). A theme that styles every secondary button
|
|
578
|
+
with `!important` (the nldesign theme: a primary border, 8px 16px padding,
|
|
579
|
+
`min-width: max-content`) would otherwise turn it into a 64px wide button
|
|
580
|
+
with a blue border, so the board values are `!important` too. */
|
|
581
|
+
.cn-look-board .cn-row-actions--board .button-vue,
|
|
582
|
+
.cn-look-board .cn-row-actions--board .button-vue:hover,
|
|
583
|
+
.cn-look-board .cn-row-actions--board .button-vue:focus {
|
|
584
|
+
box-sizing: border-box !important;
|
|
585
|
+
width: 34px !important;
|
|
586
|
+
min-width: 34px !important;
|
|
587
|
+
height: 34px !important;
|
|
588
|
+
min-height: 34px !important;
|
|
589
|
+
padding: 0 !important;
|
|
590
|
+
border: 1px solid var(--color-border-dark) !important;
|
|
591
|
+
border-radius: 8px !important;
|
|
592
|
+
color: var(--cn-board-text-soft) !important;
|
|
593
|
+
}
|
|
594
|
+
|
|
468
595
|
.cn-look-board .cn-row-actions--board .button-vue {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
596
|
+
background: var(--color-main-background) !important;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
.cn-look-board .cn-row-actions--board .button-vue:hover {
|
|
600
|
+
background: var(--color-background-hover) !important;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
.cn-look-board .cn-row-actions--board .button-vue:focus-visible {
|
|
604
|
+
outline: 2px solid var(--color-main-text);
|
|
605
|
+
outline-offset: 2px;
|
|
477
606
|
}
|
|
478
607
|
|
|
479
608
|
/* ------------------------------------------------------------------ footer */
|
package/src/css/look-board.css
CHANGED
|
@@ -12,9 +12,14 @@
|
|
|
12
12
|
* counterpart default to one.
|
|
13
13
|
*/
|
|
14
14
|
.cn-look-board {
|
|
15
|
-
/* Page content area: padding, max width, gap between blocks.
|
|
15
|
+
/* Page content area: padding, max width, gap between blocks. The content
|
|
16
|
+
spans the whole content area (screens-one-scroller-parity): grids grow
|
|
17
|
+
with the window and shrink only when the sidebar takes its share. A
|
|
18
|
+
1240px cap left dead space right of the content, and on a dashboard,
|
|
19
|
+
which scrolled itself, put the scrollbar beside the content instead of
|
|
20
|
+
at the window edge. */
|
|
16
21
|
--cn-board-content-padding: 24px 28px;
|
|
17
|
-
--cn-board-content-max-width:
|
|
22
|
+
--cn-board-content-max-width: none;
|
|
18
23
|
--cn-board-section-gap: 20px;
|
|
19
24
|
/* Buttons and inputs. */
|
|
20
25
|
--cn-board-control-height: 40px;
|
|
@@ -54,6 +59,15 @@
|
|
|
54
59
|
gap: var(--cn-board-section-gap);
|
|
55
60
|
}
|
|
56
61
|
|
|
62
|
+
/* One scroller: the content area. CnDashboardPage scrolls itself
|
|
63
|
+
(`height: 100%; overflow-y: auto`), which nested a second scrollbar inside
|
|
64
|
+
NcAppContent's; under the board look the page grows with its widgets and
|
|
65
|
+
NcAppContent, which already spans to the window edge, scrolls it. */
|
|
66
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) {
|
|
67
|
+
height: auto;
|
|
68
|
+
overflow-y: visible;
|
|
69
|
+
}
|
|
70
|
+
|
|
57
71
|
.cn-look-board .cn-index-page:not(.cn-look-nextcloud *) .cn-page-header,
|
|
58
72
|
.cn-look-board .cn-settings-page:not(.cn-look-nextcloud *) .cn-page-header,
|
|
59
73
|
.cn-look-board .cn-index-page:not(.cn-look-nextcloud *) .cn-index-page__below-header,
|
|
@@ -146,6 +160,14 @@
|
|
|
146
160
|
margin-inline-start: -264px;
|
|
147
161
|
}
|
|
148
162
|
|
|
163
|
+
/* The navigation draws the line between it and the content. NcContent draws a
|
|
164
|
+
second one on the content while the navigation is open, which doubled the
|
|
165
|
+
line and put the page 1px further from the navigation than the board's 28px.
|
|
166
|
+
Outranks NcContent's rule (six classes) with seven. */
|
|
167
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"]:not(.app-navigation--closed):not(.app-navigation--close) ~ .app-content.app-content {
|
|
168
|
+
border-inline-start: none;
|
|
169
|
+
}
|
|
170
|
+
|
|
149
171
|
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__content {
|
|
150
172
|
box-sizing: border-box;
|
|
151
173
|
gap: 20px;
|
|
@@ -155,6 +177,52 @@
|
|
|
155
177
|
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__list {
|
|
156
178
|
height: auto;
|
|
157
179
|
flex: 1 1 auto;
|
|
180
|
+
margin: 0;
|
|
181
|
+
gap: 2px;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* No scrollbars inside the navigation (screens-one-scroller-parity).
|
|
185
|
+
NcAppNavigation gives the region above the list `overflow-y: scroll`, an
|
|
186
|
+
always-on track (with arrow buttons on classic scrollbars) beside the
|
|
187
|
+
primary action that has nothing to scroll. It takes its content's height
|
|
188
|
+
instead. A menu taller than the window still scrolls (wheel, touch, focus),
|
|
189
|
+
without drawing a bar of its own; the one visible scrollbar is the page's. */
|
|
190
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__body:not(.app-navigation__body--no-list) {
|
|
191
|
+
flex-shrink: 0;
|
|
192
|
+
overflow: visible;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__list,
|
|
196
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__body--no-list {
|
|
197
|
+
scrollbar-width: none;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__list::-webkit-scrollbar,
|
|
201
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__body--no-list::-webkit-scrollbar {
|
|
202
|
+
display: none;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* The board's vertical rhythm (AppZijbalk): the primary action 20px from the
|
|
206
|
+
top, the list 20px under it, entries 2px apart. An empty search slot is a
|
|
207
|
+
flex child too and pushed everything 20px down, so it goes. */
|
|
208
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__search:empty {
|
|
209
|
+
display: none;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/* A caption is a 12px label with 6px under it, 20px after the group above
|
|
213
|
+
and 2px before its first entry. NcAppNavigationCaption gives its name a
|
|
214
|
+
15px font on a 34px line, which made it 44px high. */
|
|
215
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__list > .app-navigation-caption:not(:first-child) {
|
|
216
|
+
margin-top: 18px;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation-caption .app-navigation-caption__name {
|
|
220
|
+
margin: 0;
|
|
221
|
+
padding: 0;
|
|
222
|
+
font-size: inherit;
|
|
223
|
+
font-weight: inherit;
|
|
224
|
+
line-height: normal;
|
|
225
|
+
color: inherit;
|
|
158
226
|
}
|
|
159
227
|
|
|
160
228
|
.cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation-entry,
|
|
@@ -239,6 +307,43 @@
|
|
|
239
307
|
font-size: 15px;
|
|
240
308
|
}
|
|
241
309
|
|
|
310
|
+
/* The footer of the board: Help and Advanced as two 40px rows at weight 400,
|
|
311
|
+
2px apart. The Help row kept the 42px of a list entry, and the Advanced
|
|
312
|
+
foldout drew a 34px button inside 4px of padding, 20px under Help. */
|
|
313
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .cn-app-nav__footer-list {
|
|
314
|
+
gap: 2px;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .cn-app-nav__footer-list .app-navigation-entry,
|
|
318
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .cn-app-nav__footer-list .app-navigation-entry-link {
|
|
319
|
+
min-height: 40px;
|
|
320
|
+
font-weight: 400;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] [data-testid="cn-nav-settings"] {
|
|
324
|
+
padding: 0;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] .cn-app-nav__footer-list + [data-testid="cn-nav-settings"] {
|
|
328
|
+
margin-top: -18px;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] [data-testid="cn-nav-settings"] > :first-child {
|
|
332
|
+
margin: 0;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.cn-look-board .app-navigation[data-testid="cn-nav"] [data-testid="cn-nav-settings"] > :first-child .button-vue {
|
|
336
|
+
box-sizing: border-box;
|
|
337
|
+
width: 100%;
|
|
338
|
+
height: 40px;
|
|
339
|
+
min-height: 40px;
|
|
340
|
+
padding: 0 10px;
|
|
341
|
+
border-radius: 8px;
|
|
342
|
+
font-size: 15px;
|
|
343
|
+
font-weight: 400;
|
|
344
|
+
justify-content: flex-start;
|
|
345
|
+
}
|
|
346
|
+
|
|
242
347
|
/* The card above the footer, pushed down. */
|
|
243
348
|
.cn-look-board .cn-app-nav__card {
|
|
244
349
|
order: 0;
|
|
@@ -443,3 +548,10 @@
|
|
|
443
548
|
.cn-look-board .cn-status-badge--primary:not(.cn-status-badge--solid):not(.cn-look-nextcloud *) {
|
|
444
549
|
color: var(--color-primary-element-light-text);
|
|
445
550
|
}
|
|
551
|
+
|
|
552
|
+
/* ---- Date and age cells (screens-cell-date-parity) ---------------------- */
|
|
553
|
+
/* The board sets every waiting time ("3 dagen", "4 uur") in weight 600; a
|
|
554
|
+
late one is red through its variant class. */
|
|
555
|
+
.cn-look-board .cn-cell-renderer__age:not(.cn-look-nextcloud *) {
|
|
556
|
+
font-weight: 600;
|
|
557
|
+
}
|
package/src/css/table.css
CHANGED
|
@@ -230,6 +230,53 @@
|
|
|
230
230
|
min-width: 0;
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
+
/* Fit to the container (CnDataTable's `fitWidth`, on in CnWidgetObjectTable).
|
|
234
|
+
|
|
235
|
+
In a narrow tile the auto layout made the table as wide as its one-line
|
|
236
|
+
cells, so it ran past the tile and clipped the trailing column (a date).
|
|
237
|
+
Here every column but one takes the width of its content (`width: 1%` asks
|
|
238
|
+
for as little as the content allows), and the grow column takes what is
|
|
239
|
+
left. `max-width: 0` is what lets that column go below its content's width:
|
|
240
|
+
the table no longer counts its text, so the text is cut with an ellipsis
|
|
241
|
+
instead of widening the table. The full value stays in the cell's tooltip. */
|
|
242
|
+
.cn-data-table--fit {
|
|
243
|
+
width: 100%;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.cn-data-table--fit th,
|
|
247
|
+
.cn-data-table--fit td {
|
|
248
|
+
width: 1%;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.cn-data-table--fit th.cn-table-col--grow,
|
|
252
|
+
.cn-data-table--fit td.cn-table-col--grow {
|
|
253
|
+
width: auto;
|
|
254
|
+
min-width: 0;
|
|
255
|
+
max-width: 0;
|
|
256
|
+
overflow: hidden;
|
|
257
|
+
text-overflow: ellipsis;
|
|
258
|
+
white-space: nowrap;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/* The secondary line of the growing column ("2026-0004" under a case title)
|
|
262
|
+
is a line of its own with its own ellipsis. The cell does not wrap, so in
|
|
263
|
+
the board look, where the secondary line is an inline block (the title
|
|
264
|
+
underline cannot reach an atomic inline box), it stayed on the title's line
|
|
265
|
+
and ran out of the tile. A full-width float is a block (computed `display:
|
|
266
|
+
block`) that always starts under the line before it, and, being out of the
|
|
267
|
+
flow, the cell's underline does not reach it either. The cell is a table
|
|
268
|
+
cell, which contains its floats, so the row grows to hold the line.
|
|
269
|
+
@spec openspec/changes/dashboard-tile-text-fits/specs/dashboard-tile-text-fits/spec.md#requirement-the-secondary-line-of-a-narrow-tables-growing-column-sits-under-the-value */
|
|
270
|
+
.cn-data-table.cn-data-table--fit td.cn-table-col--grow .cn-table-cell__secondary {
|
|
271
|
+
float: inline-start;
|
|
272
|
+
clear: both;
|
|
273
|
+
box-sizing: border-box;
|
|
274
|
+
width: 100%;
|
|
275
|
+
overflow: hidden;
|
|
276
|
+
text-overflow: ellipsis;
|
|
277
|
+
white-space: nowrap;
|
|
278
|
+
}
|
|
279
|
+
|
|
233
280
|
.cn-data-table th {
|
|
234
281
|
background: var(--color-background-dark);
|
|
235
282
|
font-weight: 500;
|
|
@@ -578,6 +625,15 @@
|
|
|
578
625
|
color: var(--color-text-maxcontrast);
|
|
579
626
|
}
|
|
580
627
|
|
|
628
|
+
/* The empty row holds a sentence (the empty text, or why a lens cannot
|
|
629
|
+
answer), not a cell value: it wraps instead of being cut to one line. The
|
|
630
|
+
selector carries the table class so it outranks the one-line cell rule. */
|
|
631
|
+
.cn-data-table .cn-table-empty td {
|
|
632
|
+
max-width: none;
|
|
633
|
+
white-space: normal;
|
|
634
|
+
overflow-wrap: anywhere;
|
|
635
|
+
}
|
|
636
|
+
|
|
581
637
|
/* ========================================
|
|
582
638
|
Backwards compatibility aliases
|
|
583
639
|
(legacy OpenRegister CSS class names)
|
package/src/index.js
CHANGED
|
@@ -112,6 +112,7 @@ export {
|
|
|
112
112
|
CnEnvironmentBanner,
|
|
113
113
|
CnExportWizard,
|
|
114
114
|
CnFacetSidebar,
|
|
115
|
+
CnFactsWidget,
|
|
115
116
|
CnFavouriteToggle,
|
|
116
117
|
CnFeaturesAndRoadmapLink,
|
|
117
118
|
CnFeaturesAndRoadmapPage,
|
|
@@ -120,6 +121,7 @@ export {
|
|
|
120
121
|
CnFeaturesTab,
|
|
121
122
|
CnFederationStatus,
|
|
122
123
|
CnFieldHelper,
|
|
124
|
+
CnFieldListWidget,
|
|
123
125
|
CnFileField,
|
|
124
126
|
CnFileManager,
|
|
125
127
|
CnFilePreview,
|
|
@@ -236,6 +238,7 @@ export {
|
|
|
236
238
|
CnQuickFilterBar,
|
|
237
239
|
CnQuicklinksWidget,
|
|
238
240
|
CnQuicklinksWidgetForm,
|
|
241
|
+
CnRecordListWidget,
|
|
239
242
|
CnReferencePreview,
|
|
240
243
|
CnRegisterMapping,
|
|
241
244
|
CnRegisterSchemaSelect,
|
|
@@ -258,6 +261,7 @@ export {
|
|
|
258
261
|
CnSaveViewDialog,
|
|
259
262
|
CnSchemaFormDialog,
|
|
260
263
|
CnSearchPage,
|
|
264
|
+
CnSectionsWidget,
|
|
261
265
|
CnSettingsCard,
|
|
262
266
|
CnSettingsPage,
|
|
263
267
|
CnSettingsSection,
|
|
@@ -338,6 +342,10 @@ export {
|
|
|
338
342
|
// @deprecated Use `CnBuildiqEditButton`.
|
|
339
343
|
export { CnOpenBuildEditButton } from './components/index.js'
|
|
340
344
|
|
|
345
|
+
// A CnFilesBrowser data source that reads an OpenRegister object's folder
|
|
346
|
+
// through OpenRegister's files API (openspec: files-browser-openregister-source).
|
|
347
|
+
export { createOpenRegisterSource } from './components/index.js'
|
|
348
|
+
|
|
341
349
|
// Workplace dashboard primitives (openspec: workplace-dashboard-primitives):
|
|
342
350
|
// the week strip and stacked bar widgets with their forms, the segmented
|
|
343
351
|
// control, and the brand stripe.
|
|
@@ -134,6 +134,13 @@
|
|
|
134
134
|
(an invalid `ButtonType`, so the visual primary style never applied
|
|
135
135
|
either). See CnFormPage.vue's inline comment for the submit-button
|
|
136
136
|
half of this bug in detail. -->
|
|
137
|
+
<p v-if="saveError"
|
|
138
|
+
class="cn-field-inspection__error"
|
|
139
|
+
role="alert"
|
|
140
|
+
data-testid="cn-fi-save-error">
|
|
141
|
+
{{ saveError }}
|
|
142
|
+
</p>
|
|
143
|
+
|
|
137
144
|
<NcButton type="submit"
|
|
138
145
|
variant="primary"
|
|
139
146
|
data-testid="cn-fi-save"
|
|
@@ -157,7 +164,8 @@ import { NcButton, NcEmptyContent, NcLoadingIcon } from '@nextcloud/vue'
|
|
|
157
164
|
import ClipboardCheckOutline from 'vue-material-design-icons/ClipboardCheckOutline.vue'
|
|
158
165
|
import CnDetailCard from '../../../components/CnDetailCard/CnDetailCard.vue'
|
|
159
166
|
import CnOfflineQueue from '../../../components/CnOfflineQueue/index.js'
|
|
160
|
-
import {
|
|
167
|
+
import { buildChecklistSubmission } from '../../offline/checklistSubmission.js'
|
|
168
|
+
import { checklistProgress, classifyGps, normaliseChecklistTemplate, syncIndicator, validateChecklistAnswers } from '../../offline/fieldCollectionHelpers.js'
|
|
161
169
|
import {
|
|
162
170
|
countPending,
|
|
163
171
|
countStuck,
|
|
@@ -236,6 +244,8 @@ export default {
|
|
|
236
244
|
activeTemplate: null,
|
|
237
245
|
answers: {},
|
|
238
246
|
errors: [],
|
|
247
|
+
/** Why the last save could not be queued, in words. */
|
|
248
|
+
saveError: '',
|
|
239
249
|
}
|
|
240
250
|
},
|
|
241
251
|
|
|
@@ -449,8 +459,13 @@ export default {
|
|
|
449
459
|
this.errors = []
|
|
450
460
|
const cfg = this.config
|
|
451
461
|
const templateRef = item?.[cfg.templateRefField]
|
|
462
|
+
// The app's template shape (sections, its own item keys and type
|
|
463
|
+
// words) is read into the leaf's flat item list here, once.
|
|
452
464
|
this.activeTemplate = templateRef
|
|
453
|
-
?
|
|
465
|
+
? normaliseChecklistTemplate(
|
|
466
|
+
await getCachedObject(this.effectiveRegister, cfg.referenceSchema, 'references', String(templateRef)),
|
|
467
|
+
cfg,
|
|
468
|
+
)
|
|
454
469
|
: null
|
|
455
470
|
const initial = {}
|
|
456
471
|
for (const q of (this.activeTemplate?.items || [])) {
|
|
@@ -464,6 +479,7 @@ export default {
|
|
|
464
479
|
this.activeTemplate = null
|
|
465
480
|
this.answers = {}
|
|
466
481
|
this.errors = []
|
|
482
|
+
this.saveError = ''
|
|
467
483
|
},
|
|
468
484
|
|
|
469
485
|
/**
|
|
@@ -485,7 +501,9 @@ export default {
|
|
|
485
501
|
},
|
|
486
502
|
|
|
487
503
|
/**
|
|
488
|
-
* Validate answers, then queue
|
|
504
|
+
* Validate answers, then queue the run: an object create on
|
|
505
|
+
* `resultSchema`, or, when the config names a `resultEndpoint`, one
|
|
506
|
+
* `submit` to that endpoint.
|
|
489
507
|
*
|
|
490
508
|
* @return {Promise<void>}
|
|
491
509
|
*/
|
|
@@ -499,26 +517,22 @@ export default {
|
|
|
499
517
|
try {
|
|
500
518
|
const cfg = this.config
|
|
501
519
|
const gps = await this.captureGps()
|
|
502
|
-
const
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
})
|
|
511
|
-
const payload = {
|
|
512
|
-
inspectionRef: this.itemId(this.activeItem),
|
|
513
|
-
checklistTemplateRef: this.activeTemplate.id ?? this.activeTemplate['@self']?.id,
|
|
514
|
-
items,
|
|
515
|
-
}
|
|
520
|
+
const submission = buildChecklistSubmission(cfg, {
|
|
521
|
+
plannedItem: this.activeItem,
|
|
522
|
+
template: this.activeTemplate,
|
|
523
|
+
answers: this.answers,
|
|
524
|
+
gps,
|
|
525
|
+
gpsSource: classifyGps(gps).source,
|
|
526
|
+
capturedAt: new Date().toISOString(),
|
|
527
|
+
capturedOffline: this.offline,
|
|
528
|
+
})
|
|
516
529
|
await enqueueMutation({
|
|
517
530
|
deviceId: this.deviceId,
|
|
518
|
-
operationType:
|
|
531
|
+
operationType: submission.operationType,
|
|
519
532
|
register: this.effectiveRegister,
|
|
520
|
-
schema:
|
|
521
|
-
|
|
533
|
+
schema: submission.schema,
|
|
534
|
+
endpoint: submission.endpoint,
|
|
535
|
+
payload: submission.payload,
|
|
522
536
|
})
|
|
523
537
|
this.pendingCount = await countPending(this.deviceId)
|
|
524
538
|
this.stuckCount = await countStuck(this.deviceId)
|
|
@@ -527,6 +541,7 @@ export default {
|
|
|
527
541
|
await this.drain()
|
|
528
542
|
}
|
|
529
543
|
} catch (e) {
|
|
544
|
+
this.saveError = e?.message || t('nextcloud-vue', 'The answers could not be saved on this device.')
|
|
530
545
|
// eslint-disable-next-line no-console
|
|
531
546
|
console.error('[CnFieldInspectionCard] saveChecklist failed', e)
|
|
532
547
|
} finally {
|
|
@@ -56,6 +56,27 @@ export const DEFAULT_FIELD_INSPECTION_CONFIG = {
|
|
|
56
56
|
// Schema holding conflict records. Empty keeps a conflict on the device,
|
|
57
57
|
// and the queue row says so rather than pretending it was filed.
|
|
58
58
|
conflictSchema: '',
|
|
59
|
+
// How a template's items are read (normaliseChecklistTemplate). Empty
|
|
60
|
+
// `sectionsField` reads a flat `items[]`; set it when the items sit inside
|
|
61
|
+
// ordered sections, each with its own `items[]`.
|
|
62
|
+
sectionsField: '',
|
|
63
|
+
itemKeyField: 'questionId',
|
|
64
|
+
itemTextField: 'text',
|
|
65
|
+
itemTypeField: 'type',
|
|
66
|
+
// The app's own item type words onto the leaf's (`yes_no`,
|
|
67
|
+
// `photo_required`; anything else renders as free text).
|
|
68
|
+
itemTypeMap: {},
|
|
69
|
+
// An item whose `photoRequiredField` equals `photoRequiredValue` needs a
|
|
70
|
+
// photo as well as an answer. Empty switches the gate off.
|
|
71
|
+
photoRequiredField: '',
|
|
72
|
+
photoRequiredValue: '',
|
|
73
|
+
// Where a finished run goes (checklistSubmission). Empty queues an object
|
|
74
|
+
// create on `resultSchema`. Set, it is a path under the Nextcloud root with
|
|
75
|
+
// `{field}` placeholders from the planned item, and the run replays as one
|
|
76
|
+
// POST there, naming the template and the planned item under these keys.
|
|
77
|
+
resultEndpoint: '',
|
|
78
|
+
resultTemplateParam: 'templateId',
|
|
79
|
+
resultPlannedItemParam: 'plannedItem',
|
|
59
80
|
}
|
|
60
81
|
|
|
61
82
|
/**
|