@conduction/nextcloud-vue 2.79.0 → 2.81.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.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 +13 -11
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +80 -4
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +95 -91
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +179 -13
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js +52 -16
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +96 -4
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +158 -110
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue.js +10 -0
- package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue.js.map +1 -0
- package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue2.js +252 -0
- package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue3.js +140 -0
- package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnChipsFieldWidget/index.js +26 -0
- package/dist/esm/components/CnChipsFieldWidget/index.js.map +1 -0
- package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue.js +10 -0
- package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue.js.map +1 -0
- package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue2.js +354 -0
- package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue3.js +172 -0
- package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnChoicePickerWidget/index.js +27 -0
- package/dist/esm/components/CnChoicePickerWidget/index.js.map +1 -0
- package/dist/esm/components/CnConversationThread/CnConversationWidget.vue2.js +1 -1
- package/dist/esm/components/CnConversationThread/CnConversationWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnConversationThread/CnConversationWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js +2 -2
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +65 -5
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +2 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +19 -11
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +4 -2
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +134 -4
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +21 -4
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +24 -0
- 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/CnDocumentReviewList/CnDocumentReviewWidget.vue2.js +1 -1
- package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.vue2.js +7 -7
- package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.vue2.js.map +1 -1
- package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.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 +867 -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 +626 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +396 -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 +302 -4
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +417 -244
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/filesBrowser.js +101 -1
- package/dist/esm/components/CnFilesBrowser/filesBrowser.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/filesBrowserColumns.js +141 -1
- package/dist/esm/components/CnFilesBrowser/filesBrowserColumns.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +65 -17
- 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 +78 -3
- package/dist/esm/components/CnFormPage/CnFormPage.vue2.js.map +1 -1
- package/dist/esm/components/CnFormPage/CnFormPage.vue3.js +74 -49
- package/dist/esm/components/CnFormPage/CnFormPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +333 -73
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +79 -17
- 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/CnIndexSidebar/CnIndexSidebar.vue2.js +7 -7
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
- package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue2.js +1 -1
- package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +65 -2
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +6 -2
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +63 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +8 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js +14 -0
- package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue3.js +5 -1
- package/dist/esm/components/CnObjectSidebar/CnNotesTab.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/CnRadioCardsWidget/CnRadioCardsWidget.vue.js +10 -0
- package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue2.js +174 -0
- package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue3.js +75 -0
- package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnRadioCardsWidget/index.js +28 -0
- package/dist/esm/components/CnRadioCardsWidget/index.js.map +1 -0
- 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 +411 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +178 -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/CnSavedViewsWidget/CnSavedViewsWidget.vue.js +10 -0
- package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue2.js +222 -0
- package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue3.js +64 -0
- package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnSavedViewsWidget/index.js +30 -0
- package/dist/esm/components/CnSavedViewsWidget/index.js.map +1 -0
- 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/CnSegmentedControl/CnSegmentedControl.vue2.js.map +1 -1
- package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue3.js.map +1 -1
- package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue.js +10 -0
- package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue.js.map +1 -0
- package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue2.js +347 -0
- package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue3.js +184 -0
- package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnSettingsFormWidget/index.js +27 -0
- package/dist/esm/components/CnSettingsFormWidget/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 +87 -6
- 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/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js +84 -1
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js +85 -41
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue.js +10 -0
- package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue2.js +159 -0
- package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue3.js +60 -0
- package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnSwitchRowsWidget/index.js +26 -0
- package/dist/esm/components/CnSwitchRowsWidget/index.js.map +1 -0
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +168 -7
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +86 -23
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js +80 -1
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js +75 -32
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js +10 -0
- package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js.map +1 -0
- package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js +269 -0
- package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js +106 -0
- package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnToggleTableWidget/index.js +27 -0
- package/dist/esm/components/CnToggleTableWidget/index.js.map +1 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +11 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +7 -2
- 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/CnWidgetObjectTable/dashboardRegistration.js +5 -0
- package/dist/esm/components/CnWidgetObjectTable/dashboardRegistration.js.map +1 -1
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js +301 -6
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js +153 -55
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js.map +1 -1
- package/dist/esm/composables/useFormDraft.js +140 -9
- package/dist/esm/composables/useFormDraft.js.map +1 -1
- package/dist/esm/composables/useListView.js +4 -4
- package/dist/esm/composables/useListView.js.map +1 -1
- package/dist/esm/index.js +21 -1
- 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 +20 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +70 -2
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +2192 -222
- package/dist/esm/utils/contentHeaderLink.js +51 -0
- package/dist/esm/utils/contentHeaderLink.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/facets.js +75 -3
- package/dist/esm/utils/facets.js.map +1 -1
- package/dist/esm/utils/fetchFilterCounts.js +40 -5
- package/dist/esm/utils/fetchFilterCounts.js.map +1 -1
- package/dist/esm/utils/fillTemplate.js +120 -0
- package/dist/esm/utils/fillTemplate.js.map +1 -0
- package/dist/esm/utils/initials.js +32 -0
- package/dist/esm/utils/initials.js.map +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js +11 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/objectWrite.js +59 -0
- package/dist/esm/utils/objectWrite.js.map +1 -0
- package/dist/esm/utils/pageControls.js +81 -0
- package/dist/esm/utils/pageControls.js.map +1 -0
- package/dist/esm/utils/personalLenses.js +40 -3
- package/dist/esm/utils/personalLenses.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 +12 -1
- package/dist/esm/utils/resolveFilterTokens.js.map +1 -1
- package/dist/esm/utils/resolveManifestTokens.js +2 -0
- package/dist/esm/utils/resolveManifestTokens.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 +22 -4
- package/dist/esm/utils/sentinelTokens.js.map +1 -1
- package/dist/esm/utils/userGroupsPeek.js +91 -0
- package/dist/esm/utils/userGroupsPeek.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/esm/utils/visibleWhen.js +57 -5
- package/dist/esm/utils/visibleWhen.js.map +1 -1
- package/dist/esm/utils/widgetDispatch.js +7 -1
- package/dist/esm/utils/widgetDispatch.js.map +1 -1
- package/dist/esm/utils/widgetVisibility.js +4 -57
- package/dist/esm/utils/widgetVisibility.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +19708 -9301
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +2192 -222
- package/l10n/en.json +20 -1
- package/l10n/nl.json +70 -2
- package/package.json +2 -1
- package/scripts/check-docs-mdx.mjs +108 -0
- package/src/components/CnActionButtons/CnActionButtons.vue +2 -0
- package/src/components/CnActionsBar/CnActionsBar.md +4 -0
- package/src/components/CnActionsBar/CnActionsBar.vue +48 -11
- package/src/components/CnAppRoot/CnAppRoot.md +4 -2
- package/src/components/CnAppRoot/CnAppRoot.vue +151 -59
- package/src/components/CnBannerWidget/CnBannerWidget.vue +244 -23
- package/src/components/CnCellRenderer/CnCellRenderer.md +2 -0
- package/src/components/CnCellRenderer/CnCellRenderer.vue +235 -5
- package/src/components/CnChipsFieldWidget/CnChipsFieldWidget.vue +433 -0
- package/src/components/CnChipsFieldWidget/index.js +25 -0
- package/src/components/CnChoicePickerWidget/CnChoicePickerWidget.vue +556 -0
- package/src/components/CnChoicePickerWidget/index.js +26 -0
- package/src/components/CnConversationThread/CnConversationWidget.vue +1 -1
- package/src/components/CnDashboardGrid/CnDashboardGrid.vue +2 -2
- package/src/components/CnDashboardPage/CnDashboardPage.vue +78 -5
- package/src/components/CnDataTable/CnDataTable.vue +22 -12
- package/src/components/CnDetailPage/CnDetailPage.md +1 -1
- package/src/components/CnDetailPage/CnDetailPage.vue +152 -6
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +66 -0
- package/src/components/CnDocumentReviewList/CnDocumentReviewWidget.vue +1 -1
- package/src/components/CnFacetSidebar/CnFacetSidebar.vue +7 -7
- package/src/components/CnFactsWidget/CnFactsWidget.vue +1190 -0
- package/src/components/CnFactsWidget/index.js +29 -0
- package/src/components/CnFieldListWidget/CnFieldListWidget.vue +1008 -0
- package/src/components/CnFieldListWidget/index.js +28 -0
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +588 -117
- package/src/components/CnFilesBrowser/filesBrowser.js +100 -0
- package/src/components/CnFilesBrowser/filesBrowserColumns.js +140 -0
- package/src/components/CnFormDialog/CnFormDialog.md +9 -3
- package/src/components/CnFormDialog/CnFormDialog.vue +69 -21
- package/src/components/CnFormPage/CnFormPage.vue +99 -3
- package/src/components/CnIndexPage/CnIndexPage.vue +309 -9
- package/src/components/CnIndexPage/CnIndexPageWidgets.vue +169 -0
- package/src/components/CnIndexSidebar/CnIndexSidebar.vue +7 -7
- package/src/components/CnNextStepCard/CnNextStepWidget.vue +1 -1
- package/src/components/CnObjectListWidget/CnObjectListWidget.vue +69 -2
- package/src/components/CnObjectSidebar/CnFilesTab.vue +70 -1
- package/src/components/CnObjectSidebar/CnNotesTab.vue +16 -0
- package/src/components/CnPageRenderer/CnPageRenderer.vue +29 -1
- package/src/components/CnRadioCardsWidget/CnRadioCardsWidget.vue +313 -0
- package/src/components/CnRadioCardsWidget/index.js +27 -0
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +652 -0
- package/src/components/CnRecordListWidget/index.js +30 -0
- package/src/components/CnSavedViewsWidget/CnSavedViewsWidget.vue +296 -0
- package/src/components/CnSavedViewsWidget/index.js +29 -0
- package/src/components/CnSectionsWidget/CnSectionsWidget.vue +489 -0
- package/src/components/CnSectionsWidget/index.js +34 -0
- package/src/components/CnSegmentedControl/CnSegmentedControl.vue +13 -0
- package/src/components/CnSettingsFormWidget/CnSettingsFormWidget.vue +555 -0
- package/src/components/CnSettingsFormWidget/index.js +26 -0
- package/src/components/CnStagesWidget/CnStagesWidget.vue +81 -2
- package/src/components/CnStatWidget/CnStatWidget.vue +88 -7
- package/src/components/CnStatsBlockWidget/CnStatsBlockWidget.vue +180 -3
- package/src/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue +226 -0
- package/src/components/CnSwitchRowsWidget/index.js +25 -0
- package/src/components/CnTabsWidget/CnTabsWidget.vue +263 -8
- package/src/components/CnTasksWidget/CnTasksWidget.vue +175 -15
- package/src/components/CnToggleTableWidget/CnToggleTableWidget.vue +386 -0
- package/src/components/CnToggleTableWidget/index.js +26 -0
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +11 -0
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +7 -2
- package/src/components/CnWidgetObjectTable/dashboardRegistration.js +5 -0
- package/src/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue +493 -11
- package/src/components/index.js +19 -0
- package/src/composables/__tests__/useFormDraft.spec.js +69 -0
- package/src/composables/useFormDraft.js +139 -8
- package/src/composables/useListView.js +4 -4
- 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 +113 -2
- package/src/css/look-board-index.css +90 -8
- package/src/css/look-board.css +109 -2
- package/src/css/table.css +19 -0
- package/src/index.js +19 -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 +196 -13
- package/src/utils/contentHeaderLink.js +48 -0
- package/src/utils/detailActionModel.js +59 -2
- package/src/utils/facets.js +74 -2
- package/src/utils/fetchFilterCounts.js +39 -4
- package/src/utils/fillTemplate.js +116 -0
- package/src/utils/initials.js +29 -0
- package/src/utils/libraryWidgetKeys.js +11 -0
- package/src/utils/objectWrite.js +55 -0
- package/src/utils/pageControls.js +78 -0
- package/src/utils/personalLenses.js +39 -2
- package/src/utils/queryPresets.js +93 -0
- package/src/utils/resolveFilterTokens.js +14 -1
- package/src/utils/resolveManifestTokens.js +2 -0
- package/src/utils/schema.js +21 -0
- package/src/utils/sentinelTokens.js +22 -4
- package/src/utils/userGroupsPeek.js +87 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
- package/src/utils/visibleWhen.js +56 -4
- package/src/utils/widgetDispatch.js +7 -1
- package/src/utils/widgetVisibility.js +7 -56
|
@@ -249,7 +249,8 @@
|
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
/* Filter: a labelled secondary button, 36px, radius 8, with the active count. */
|
|
252
|
-
.cn-look-board .cn-actions-bar__filter-button.button-vue
|
|
252
|
+
.cn-look-board .cn-actions-bar__filter-button.button-vue,
|
|
253
|
+
.cn-look-board .cn-actions-bar__filter-menu .button-vue {
|
|
253
254
|
min-height: 36px;
|
|
254
255
|
height: 36px;
|
|
255
256
|
border-radius: 8px;
|
|
@@ -301,6 +302,15 @@
|
|
|
301
302
|
color: var(--color-main-text);
|
|
302
303
|
}
|
|
303
304
|
|
|
305
|
+
/* A segment the page cannot open: drawn, as the boards do, but faded and inert. */
|
|
306
|
+
.cn-look-board .cn-actions-bar--board .cn-actions-bar__view-toggle .cn-actions-bar__view-toggle-btn--disabled,
|
|
307
|
+
.cn-look-board .cn-actions-bar--board .cn-actions-bar__view-toggle .cn-actions-bar__view-toggle-btn--disabled:hover {
|
|
308
|
+
background: transparent !important;
|
|
309
|
+
color: var(--color-text-maxcontrast);
|
|
310
|
+
opacity: 0.5;
|
|
311
|
+
cursor: not-allowed;
|
|
312
|
+
}
|
|
313
|
+
|
|
304
314
|
/* The search field: 40px, radius 8, not a pill. */
|
|
305
315
|
.cn-look-board .cn-actions-bar--board .cn-actions-bar__search {
|
|
306
316
|
flex: 1 1 260px;
|
|
@@ -448,11 +458,58 @@
|
|
|
448
458
|
border-bottom: 0;
|
|
449
459
|
}
|
|
450
460
|
|
|
451
|
-
/* The
|
|
461
|
+
/* The table fits its card (screens-index-table-fit-parity). Under the auto
|
|
462
|
+
layout every one-line cell asked for its whole text up to the 22rem cap, so
|
|
463
|
+
seven text columns made a 1500px table in a 1118px card at a 1440px
|
|
464
|
+
viewport: the last columns and the row menus sat past the card's edge. The
|
|
465
|
+
fixed layout shares the card's width: the selection and menu columns keep
|
|
466
|
+
their own width, the first data column takes 18%, the others split the
|
|
467
|
+
rest, and a value that does not fit is cut with an ellipsis (its full text
|
|
468
|
+
stays in the cell's tooltip). A column's own `width` still wins. */
|
|
469
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table {
|
|
470
|
+
table-layout: fixed;
|
|
471
|
+
width: 100%;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table th.cn-table-head--title {
|
|
475
|
+
width: 18%;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/* The board's data cells sit 12px apart (PqTickets), the first one 18px from
|
|
479
|
+
the selection column; the selection and menu columns keep 16px. */
|
|
480
|
+
.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),
|
|
481
|
+
.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) {
|
|
482
|
+
padding-inline: 12px;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table th.cn-table-head--title,
|
|
486
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table td.cn-table-col--title {
|
|
487
|
+
padding-inline-start: 18px;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
.cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table td > .cn-cell-renderer {
|
|
491
|
+
display: block;
|
|
492
|
+
min-width: 0;
|
|
493
|
+
overflow: hidden;
|
|
494
|
+
text-overflow: ellipsis;
|
|
495
|
+
white-space: nowrap;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/* A narrow header cuts its label, not its filter funnel. */
|
|
499
|
+
.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) {
|
|
500
|
+
max-width: calc(100% - 26px);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/* The selection column: 18px checkboxes, 28px of content after 16px of padding.
|
|
504
|
+
The box model is set with `!important` and the widths include the padding:
|
|
505
|
+
Nextcloud's server.css sets `box-sizing: border-box` on everything under
|
|
506
|
+
`#content[class*="app-"]`, an id selector no class rule outranks, so a plain
|
|
507
|
+
`content-box` here was ignored and the cell left 12px for the checkbox (the
|
|
508
|
+
header's checkbox showed as a stray bracket). */
|
|
452
509
|
.cn-look-board .cn-table-container--board .cn-data-table .cn-table-col--checkbox {
|
|
453
|
-
box-sizing:
|
|
454
|
-
width:
|
|
455
|
-
min-width:
|
|
510
|
+
box-sizing: border-box !important;
|
|
511
|
+
width: 44px;
|
|
512
|
+
min-width: 44px;
|
|
456
513
|
padding-inline: 16px 0;
|
|
457
514
|
text-align: start;
|
|
458
515
|
}
|
|
@@ -500,6 +557,29 @@
|
|
|
500
557
|
font-size: 13px;
|
|
501
558
|
}
|
|
502
559
|
|
|
560
|
+
/* An avatar in the title column (PtAccounts): a 32px chip circle, 10px before
|
|
561
|
+
the name, the e-mail under the name beside it. The name keeps the title's
|
|
562
|
+
weight and size, and its underline: an inline-flex box is atomic, so the
|
|
563
|
+
cell's own underline does not reach it. */
|
|
564
|
+
.cn-look-board .cn-table-container--board .cn-data-table .cn-cell-renderer__avatar {
|
|
565
|
+
gap: 10px;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
.cn-look-board .cn-table-container--board .cn-data-table .cn-cell-renderer__avatar-initials {
|
|
569
|
+
background: var(--color-background-dark);
|
|
570
|
+
color: var(--color-main-text);
|
|
571
|
+
font-size: 12px;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
.cn-look-board .cn-table-container--board .cn-data-table td.cn-table-col--title .cn-cell-renderer__avatar-name {
|
|
575
|
+
text-decoration: underline;
|
|
576
|
+
text-underline-offset: 2px;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
.cn-look-board .cn-table-container--board.cn-table-container--title-plain .cn-data-table td.cn-table-col--title .cn-cell-renderer__avatar-name {
|
|
580
|
+
text-decoration: none;
|
|
581
|
+
}
|
|
582
|
+
|
|
503
583
|
/* A status pill: 3px 10px, radius 12, 13px weight 600. The colours stay the
|
|
504
584
|
status colour map's. */
|
|
505
585
|
.cn-look-board .cn-table-container--board .cn-data-table .cn-status-badge {
|
|
@@ -510,10 +590,12 @@
|
|
|
510
590
|
line-height: 1.4;
|
|
511
591
|
}
|
|
512
592
|
|
|
513
|
-
/* The row menu column holds one 34px button
|
|
593
|
+
/* The row menu column holds one 34px button between 16px of padding, so 66px
|
|
594
|
+
border to border (see the selection column for why the box model is forced). */
|
|
514
595
|
.cn-look-board .cn-table-container--board .cn-data-table .cn-table-col--actions {
|
|
515
|
-
|
|
516
|
-
|
|
596
|
+
box-sizing: border-box !important;
|
|
597
|
+
width: 66px;
|
|
598
|
+
min-width: 66px;
|
|
517
599
|
padding-inline: 16px;
|
|
518
600
|
text-align: end;
|
|
519
601
|
}
|
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,
|
|
@@ -167,6 +181,27 @@
|
|
|
167
181
|
gap: 2px;
|
|
168
182
|
}
|
|
169
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
|
+
|
|
170
205
|
/* The board's vertical rhythm (AppZijbalk): the primary action 20px from the
|
|
171
206
|
top, the list 20px under it, entries 2px apart. An empty search slot is a
|
|
172
207
|
flex child too and pushed everything 20px down, so it goes. */
|
|
@@ -520,3 +555,75 @@
|
|
|
520
555
|
.cn-look-board .cn-cell-renderer__age:not(.cn-look-nextcloud *) {
|
|
521
556
|
font-weight: 600;
|
|
522
557
|
}
|
|
558
|
+
|
|
559
|
+
/* ---- Record list on a dashboard card (PtDashboard) ---------------------- */
|
|
560
|
+
/* The dashboard's card body is flush, so the rows carry their own inset: the
|
|
561
|
+
board's card pads 24px at the sides and each row 14px, a soft hairline
|
|
562
|
+
between rows, the title 15px weight 600 and the meta 13px muted. A row is a
|
|
563
|
+
link, but only the hover says so: no underline on any text run, however the
|
|
564
|
+
host styles its links (`!important`, because a host rule such as
|
|
565
|
+
`#content a` outranks any class). The pill and the date sit at the right. */
|
|
566
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list {
|
|
567
|
+
padding: 0 24px 10px;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list--rows .cn-record-list__item + .cn-record-list__item {
|
|
571
|
+
border-top: 1px solid var(--color-border-dark, var(--color-border));
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list__row {
|
|
575
|
+
padding: 14px 0;
|
|
576
|
+
flex-wrap: wrap;
|
|
577
|
+
gap: 8px 16px;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list__row,
|
|
581
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list__row:hover,
|
|
582
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list__row:focus-visible,
|
|
583
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list__row * {
|
|
584
|
+
color: inherit;
|
|
585
|
+
text-decoration: none !important;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list__title {
|
|
589
|
+
color: var(--color-main-text);
|
|
590
|
+
font-size: 15px;
|
|
591
|
+
font-weight: 600;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list__meta {
|
|
595
|
+
color: var(--color-text-maxcontrast);
|
|
596
|
+
font-size: 13px;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list__trailing {
|
|
600
|
+
color: var(--color-text-maxcontrast);
|
|
601
|
+
font-size: 13px;
|
|
602
|
+
font-weight: 600;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/* Hover: the whole row takes the hover ground, 8px beyond the text so the
|
|
606
|
+
text does not move. */
|
|
607
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list__row--link {
|
|
608
|
+
margin-inline: -8px;
|
|
609
|
+
padding-inline: 8px;
|
|
610
|
+
border-radius: 8px;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list__row--link:hover,
|
|
614
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list__row--link:focus-visible {
|
|
615
|
+
background: var(--color-background-hover);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list__row--link:hover .cn-record-list__title {
|
|
619
|
+
text-decoration: none !important;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list__aside {
|
|
623
|
+
margin-inline-start: auto;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/* The board draws no chevron after the pill and date. */
|
|
627
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list__chevron {
|
|
628
|
+
display: none;
|
|
629
|
+
}
|
package/src/css/table.css
CHANGED
|
@@ -258,6 +258,25 @@
|
|
|
258
258
|
white-space: nowrap;
|
|
259
259
|
}
|
|
260
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
|
+
|
|
261
280
|
.cn-data-table th {
|
|
262
281
|
background: var(--color-background-dark);
|
|
263
282
|
font-weight: 500;
|
package/src/index.js
CHANGED
|
@@ -43,6 +43,8 @@ export {
|
|
|
43
43
|
CnAppNav,
|
|
44
44
|
CnAppRoot,
|
|
45
45
|
CnAuditTrailCard,
|
|
46
|
+
CnAuditTrailWidget,
|
|
47
|
+
CnBannerWidget,
|
|
46
48
|
CnBoardView,
|
|
47
49
|
CnBodySections,
|
|
48
50
|
CnBreadcrumbs,
|
|
@@ -58,7 +60,9 @@ export {
|
|
|
58
60
|
CnChartWidgetForm,
|
|
59
61
|
CnChatPage,
|
|
60
62
|
CnChildRecordsField,
|
|
63
|
+
CnChipsFieldWidget,
|
|
61
64
|
CnChoiceCards,
|
|
65
|
+
CnChoicePickerWidget,
|
|
62
66
|
CnColorPicker,
|
|
63
67
|
CnCommandPalette,
|
|
64
68
|
CnConfigurationCard,
|
|
@@ -70,6 +74,7 @@ export {
|
|
|
70
74
|
CnContainerWidgetForm,
|
|
71
75
|
CnContextMenu,
|
|
72
76
|
CnConversationThread,
|
|
77
|
+
CnConversationWidget,
|
|
73
78
|
CnCopyDialog,
|
|
74
79
|
CnCountdownWidget,
|
|
75
80
|
CnCountdownWidgetForm,
|
|
@@ -97,6 +102,7 @@ export {
|
|
|
97
102
|
CnDividerWidget,
|
|
98
103
|
CnDividerWidgetForm,
|
|
99
104
|
CnDocumentReviewList,
|
|
105
|
+
CnDocumentReviewWidget,
|
|
100
106
|
CnDurationField,
|
|
101
107
|
CnEditActionsModal,
|
|
102
108
|
CnEditDataModal,
|
|
@@ -112,6 +118,7 @@ export {
|
|
|
112
118
|
CnEnvironmentBanner,
|
|
113
119
|
CnExportWizard,
|
|
114
120
|
CnFacetSidebar,
|
|
121
|
+
CnFactsWidget,
|
|
115
122
|
CnFavouriteToggle,
|
|
116
123
|
CnFeaturesAndRoadmapLink,
|
|
117
124
|
CnFeaturesAndRoadmapPage,
|
|
@@ -120,6 +127,7 @@ export {
|
|
|
120
127
|
CnFeaturesTab,
|
|
121
128
|
CnFederationStatus,
|
|
122
129
|
CnFieldHelper,
|
|
130
|
+
CnFieldListWidget,
|
|
123
131
|
CnFileField,
|
|
124
132
|
CnFileManager,
|
|
125
133
|
CnFilePreview,
|
|
@@ -162,11 +170,13 @@ export {
|
|
|
162
170
|
CnIntegrationTab,
|
|
163
171
|
CnIntegrationWidget,
|
|
164
172
|
CnIntegrationWidgetGrid,
|
|
173
|
+
CnInteractionFormWidget,
|
|
165
174
|
CnItemCard,
|
|
166
175
|
CnJourney,
|
|
167
176
|
CnJourneyDialog,
|
|
168
177
|
CnJourneyReviewList,
|
|
169
178
|
CnJsonViewer,
|
|
179
|
+
CnKbSearchWidget,
|
|
170
180
|
CnKpiGrid,
|
|
171
181
|
CnLabelWidget,
|
|
172
182
|
CnLabelWidgetForm,
|
|
@@ -198,6 +208,7 @@ export {
|
|
|
198
208
|
CnNcWidgetGridPicker,
|
|
199
209
|
CnNcWidgetWidget,
|
|
200
210
|
CnNextStepCard,
|
|
211
|
+
CnNextStepWidget,
|
|
201
212
|
CnNoteBody,
|
|
202
213
|
CnNoteCard,
|
|
203
214
|
CnNoteComposer,
|
|
@@ -236,6 +247,8 @@ export {
|
|
|
236
247
|
CnQuickFilterBar,
|
|
237
248
|
CnQuicklinksWidget,
|
|
238
249
|
CnQuicklinksWidgetForm,
|
|
250
|
+
CnRadioCardsWidget,
|
|
251
|
+
CnRecordListWidget,
|
|
239
252
|
CnReferencePreview,
|
|
240
253
|
CnRegisterMapping,
|
|
241
254
|
CnRegisterSchemaSelect,
|
|
@@ -253,12 +266,15 @@ export {
|
|
|
253
266
|
CnSavedViewsControl,
|
|
254
267
|
CnSavedViewShareDialog,
|
|
255
268
|
CnSavedViewShareFields,
|
|
269
|
+
CnSavedViewsWidget,
|
|
256
270
|
CnSavedViewWidget,
|
|
257
271
|
CnSavedViewWidgetForm,
|
|
258
272
|
CnSaveViewDialog,
|
|
259
273
|
CnSchemaFormDialog,
|
|
260
274
|
CnSearchPage,
|
|
275
|
+
CnSectionsWidget,
|
|
261
276
|
CnSettingsCard,
|
|
277
|
+
CnSettingsFormWidget,
|
|
262
278
|
CnSettingsPage,
|
|
263
279
|
CnSettingsSection,
|
|
264
280
|
CnSetupWizard,
|
|
@@ -278,6 +294,7 @@ export {
|
|
|
278
294
|
CnSubObjectsField,
|
|
279
295
|
CnSummaryAggregates,
|
|
280
296
|
CnSupportDialog,
|
|
297
|
+
CnSwitchRowsWidget,
|
|
281
298
|
CnTab,
|
|
282
299
|
CnTabbedFormDialog,
|
|
283
300
|
CnTableWidget,
|
|
@@ -298,6 +315,7 @@ export {
|
|
|
298
315
|
CnTimelineStages,
|
|
299
316
|
CnTimelineView,
|
|
300
317
|
CnTimelineWidget,
|
|
318
|
+
CnToggleTableWidget,
|
|
301
319
|
CnTranslatedBadge,
|
|
302
320
|
CnTreeView,
|
|
303
321
|
CnUnreadMarker,
|
|
@@ -320,6 +338,7 @@ export {
|
|
|
320
338
|
CnWidgetVisibilityRulesModal,
|
|
321
339
|
CnWidgetWrapper,
|
|
322
340
|
CnWizardDialog,
|
|
341
|
+
CnWorkspaceFilterWidget,
|
|
323
342
|
DEFAULT_DATE_RANGE_PRESETS,
|
|
324
343
|
defaultPageTypes,
|
|
325
344
|
fetchWebdavFolderTree,
|
|
@@ -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
|
/**
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V. <info@conduction.nl>
|
|
3
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
*
|
|
5
|
+
* What a finished offline checklist run turns into in the queue.
|
|
6
|
+
*
|
|
7
|
+
* Two shapes, chosen by the leaf's `offlineConfig`:
|
|
8
|
+
*
|
|
9
|
+
* - `resultEndpoint` empty: an object create on `resultSchema`, the shape the
|
|
10
|
+
* leaf has always queued (`inspectionRef`, `checklistTemplateRef`,
|
|
11
|
+
* `items[]` with `questionId` / `answer` / `evidenceRefs`).
|
|
12
|
+
* - `resultEndpoint` set: a `submit` operation that replays the run as ONE
|
|
13
|
+
* POST to an app's own endpoint, for an app that stores a run as something
|
|
14
|
+
* other than a plain object (a completed task, say) and checks the run
|
|
15
|
+
* server side before it stores anything. The endpoint is a path under the
|
|
16
|
+
* Nextcloud root with `{field}` placeholders filled from the planned item,
|
|
17
|
+
* e.g. `/apps/myapp/api/cases/{caseRef}/checklist-run`.
|
|
18
|
+
*
|
|
19
|
+
* Pure: no axios, no IndexedDB, no DOM. The card queues what this returns and
|
|
20
|
+
* the replay service sends it.
|
|
21
|
+
*
|
|
22
|
+
* @module integrations/offline/checklistSubmission
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { translate as t } from '@nextcloud/l10n'
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Fill a `{field}` endpoint template from a planned item.
|
|
29
|
+
*
|
|
30
|
+
* Each value is URL-encoded, so a planned item can never steer the request to
|
|
31
|
+
* another path. A placeholder the item does not fill is an error rather than
|
|
32
|
+
* an empty path segment: a run sent to the wrong case is worse than one that
|
|
33
|
+
* waits.
|
|
34
|
+
*
|
|
35
|
+
* @param {string} template The endpoint template.
|
|
36
|
+
* @param {object} plannedItem The planned item the run belongs to.
|
|
37
|
+
*
|
|
38
|
+
* @return {string} The filled path.
|
|
39
|
+
*
|
|
40
|
+
* @throws {Error} When a placeholder has no value on the item.
|
|
41
|
+
*/
|
|
42
|
+
export function fillEndpoint(template, plannedItem) {
|
|
43
|
+
return String(template).replace(/\{([A-Za-z0-9_.]+)\}/g, (match, field) => {
|
|
44
|
+
const value = field.split('.').reduce((node, key) => (node === null || node === undefined ? undefined : node[key]), plannedItem)
|
|
45
|
+
if (value === undefined || value === null || String(value) === '') {
|
|
46
|
+
throw new Error(t('nextcloud-vue', 'This planned item has no {field}, so the answers have nowhere to go.', { field }))
|
|
47
|
+
}
|
|
48
|
+
return encodeURIComponent(String(value))
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The id of an object, wherever OpenRegister carries it.
|
|
54
|
+
*
|
|
55
|
+
* @param {object|null} object The object.
|
|
56
|
+
*
|
|
57
|
+
* @return {string} The id, or an empty string.
|
|
58
|
+
*/
|
|
59
|
+
function idOf(object) {
|
|
60
|
+
return String(object?.id ?? object?.['@self']?.id ?? object?.uuid ?? '')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Build the queue operation for a finished checklist run.
|
|
65
|
+
*
|
|
66
|
+
* @param {object} config The leaf's offline config.
|
|
67
|
+
* @param {object} run The run.
|
|
68
|
+
* @param {object} run.plannedItem The planned item.
|
|
69
|
+
* @param {object} run.template The normalised template (`items[]`).
|
|
70
|
+
* @param {object} run.answers Map of questionId to `{ answer, evidenceRefs }`.
|
|
71
|
+
* @param {object|null} [run.gps] The GPS fix at save, or null.
|
|
72
|
+
* @param {string} [run.gpsSource] `sensor` or `sensorless`.
|
|
73
|
+
* @param {string} [run.capturedAt] ISO time of the save.
|
|
74
|
+
* @param {boolean} [run.capturedOffline] Whether the device was offline at save.
|
|
75
|
+
*
|
|
76
|
+
* @return {{ operationType: string, schema: string, endpoint: (string|null), payload: object }}
|
|
77
|
+
* The operation fields for `enqueueMutation`.
|
|
78
|
+
*
|
|
79
|
+
* @throws {Error} When the endpoint cannot be filled from the planned item.
|
|
80
|
+
*/
|
|
81
|
+
export function buildChecklistSubmission(config, run) {
|
|
82
|
+
const capturedAt = run.capturedAt || new Date().toISOString()
|
|
83
|
+
const gpsAtAnswer = run.gps ? { ...run.gps, source: run.gpsSource || 'sensor' } : { source: 'sensorless' }
|
|
84
|
+
const items = Array.isArray(run.template?.items) ? run.template.items : []
|
|
85
|
+
const answers = run.answers ?? {}
|
|
86
|
+
const plannedItemId = idOf(run.plannedItem)
|
|
87
|
+
const templateId = idOf(run.template)
|
|
88
|
+
|
|
89
|
+
if (!config.resultEndpoint) {
|
|
90
|
+
return {
|
|
91
|
+
operationType: 'create',
|
|
92
|
+
schema: config.resultSchema,
|
|
93
|
+
endpoint: null,
|
|
94
|
+
payload: {
|
|
95
|
+
inspectionRef: plannedItemId,
|
|
96
|
+
checklistTemplateRef: templateId,
|
|
97
|
+
items: items.map((q) => ({
|
|
98
|
+
questionId: q.questionId,
|
|
99
|
+
answer: answers[q.questionId]?.answer,
|
|
100
|
+
evidenceRefs: answers[q.questionId]?.evidenceRefs ?? [],
|
|
101
|
+
answeredAt: capturedAt,
|
|
102
|
+
gpsAtAnswer,
|
|
103
|
+
})),
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const payload = {
|
|
109
|
+
[config.resultTemplateParam || 'templateId']: templateId,
|
|
110
|
+
[config.resultPlannedItemParam || 'plannedItem']: plannedItemId,
|
|
111
|
+
capturedAt,
|
|
112
|
+
capturedOffline: run.capturedOffline === true,
|
|
113
|
+
items: items
|
|
114
|
+
.filter((q) => {
|
|
115
|
+
const entry = answers[q.questionId] ?? {}
|
|
116
|
+
const hasAnswer = entry.answer !== undefined && entry.answer !== null && String(entry.answer).trim() !== ''
|
|
117
|
+
return hasAnswer || (Array.isArray(entry.evidenceRefs) && entry.evidenceRefs.length > 0)
|
|
118
|
+
})
|
|
119
|
+
.map((q) => ({
|
|
120
|
+
itemId: q.questionId,
|
|
121
|
+
value: answers[q.questionId]?.answer ?? '',
|
|
122
|
+
photos: answers[q.questionId]?.evidenceRefs ?? [],
|
|
123
|
+
answeredAt: capturedAt,
|
|
124
|
+
gpsAtAnswer,
|
|
125
|
+
})),
|
|
126
|
+
}
|
|
127
|
+
if (run.gps) {
|
|
128
|
+
payload.location = { ...run.gps, source: run.gpsSource || 'sensor' }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
operationType: 'submit',
|
|
133
|
+
schema: config.resultSchema || '',
|
|
134
|
+
endpoint: fillEndpoint(config.resultEndpoint, run.plannedItem),
|
|
135
|
+
payload,
|
|
136
|
+
}
|
|
137
|
+
}
|