@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
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { resolveComponent, openBlock, createElementBlock, withModifiers, createElementVNode, normalizeClass, Fragment, renderList, createBlock, withCtx, createTextVNode, toDisplayString, createCommentVNode, withDirectives, vModelSelect, vModelText, vModelDynamic, createVNode } from 'vue';
|
|
2
|
+
|
|
3
|
+
const _hoisted_1 = ["data-testid"];
|
|
4
|
+
const _hoisted_2 = ["for"];
|
|
5
|
+
const _hoisted_3 = ["data-testid"];
|
|
6
|
+
const _hoisted_4 = ["id"];
|
|
7
|
+
const _hoisted_5 = ["id", "onUpdate:modelValue", "disabled"];
|
|
8
|
+
const _hoisted_6 = ["value"];
|
|
9
|
+
const _hoisted_7 = ["id", "onUpdate:modelValue", "rows", "placeholder", "readonly"];
|
|
10
|
+
const _hoisted_8 = ["id", "onUpdate:modelValue", "type", "min", "max", "placeholder", "readonly", "aria-invalid"];
|
|
11
|
+
const _hoisted_9 = {
|
|
12
|
+
key: 2,
|
|
13
|
+
class: "cn-settings-form__error",
|
|
14
|
+
role: "alert"
|
|
15
|
+
};
|
|
16
|
+
const _hoisted_10 = {
|
|
17
|
+
key: 3,
|
|
18
|
+
class: "cn-settings-form__hint"
|
|
19
|
+
};
|
|
20
|
+
const _hoisted_11 = {
|
|
21
|
+
key: 1,
|
|
22
|
+
class: "cn-settings-form__actions"
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
26
|
+
const _component_NcCheckboxRadioSwitch = resolveComponent("NcCheckboxRadioSwitch");
|
|
27
|
+
const _component_NcButton = resolveComponent("NcButton");
|
|
28
|
+
const _component_NcNoteCard = resolveComponent("NcNoteCard");
|
|
29
|
+
|
|
30
|
+
return (openBlock(), createElementBlock("form", {
|
|
31
|
+
class: "cn-settings-form",
|
|
32
|
+
"data-testid": "cn-settings-form",
|
|
33
|
+
novalidate: "",
|
|
34
|
+
onSubmit: _cache[0] || (_cache[0] = withModifiers((...args) => ($options.save && $options.save(...args)), ["prevent"]))
|
|
35
|
+
}, [
|
|
36
|
+
createElementVNode("div", {
|
|
37
|
+
class: normalizeClass(["cn-settings-form__grid", `cn-settings-form__grid--${$options.columns}`])
|
|
38
|
+
}, [
|
|
39
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.fields, (field) => {
|
|
40
|
+
return (openBlock(), createElementBlock("div", {
|
|
41
|
+
key: field.key,
|
|
42
|
+
class: normalizeClass(["cn-settings-form__field", { 'cn-settings-form__field--wide': field.wide }]),
|
|
43
|
+
"data-testid": `cn-settings-form-field-${field.key}`
|
|
44
|
+
}, [
|
|
45
|
+
(field.type === 'switch')
|
|
46
|
+
? (openBlock(), createBlock(_component_NcCheckboxRadioSwitch, {
|
|
47
|
+
key: 0,
|
|
48
|
+
modelValue: $data.form[field.key],
|
|
49
|
+
"onUpdate:modelValue": $event => (($data.form[field.key]) = $event),
|
|
50
|
+
type: "switch",
|
|
51
|
+
disabled: field.readOnly
|
|
52
|
+
}, {
|
|
53
|
+
default: withCtx(() => [
|
|
54
|
+
createTextVNode(toDisplayString(field.label), 1 /* TEXT */)
|
|
55
|
+
]),
|
|
56
|
+
_: 2 /* DYNAMIC */
|
|
57
|
+
}, 1032 /* PROPS, DYNAMIC_SLOTS */, ["modelValue", "onUpdate:modelValue", "disabled"]))
|
|
58
|
+
: (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
59
|
+
createElementVNode("label", {
|
|
60
|
+
class: "cn-settings-form__label",
|
|
61
|
+
for: $options.inputId(field)
|
|
62
|
+
}, toDisplayString(field.label), 9 /* TEXT, PROPS */, _hoisted_2),
|
|
63
|
+
(field.type === 'file')
|
|
64
|
+
? (openBlock(), createElementBlock("div", {
|
|
65
|
+
key: 0,
|
|
66
|
+
class: "cn-settings-form__file",
|
|
67
|
+
"data-testid": `cn-settings-form-file-${field.key}`
|
|
68
|
+
}, [
|
|
69
|
+
createElementVNode("span", {
|
|
70
|
+
id: $options.inputId(field),
|
|
71
|
+
class: normalizeClass(["cn-settings-form__control cn-settings-form__control--file", { 'cn-settings-form__control--placeholder': !$data.form[field.key] }])
|
|
72
|
+
}, toDisplayString($data.form[field.key] ? $options.fileName($data.form[field.key]) : field.placeholder), 11 /* TEXT, CLASS, PROPS */, _hoisted_4),
|
|
73
|
+
(!field.readOnly)
|
|
74
|
+
? (openBlock(), createBlock(_component_NcButton, {
|
|
75
|
+
key: 0,
|
|
76
|
+
variant: "secondary",
|
|
77
|
+
"aria-describedby": $options.inputId(field),
|
|
78
|
+
"data-testid": `cn-settings-form-choose-${field.key}`,
|
|
79
|
+
onClick: $event => ($options.chooseFile(field))
|
|
80
|
+
}, {
|
|
81
|
+
default: withCtx(() => [
|
|
82
|
+
createTextVNode(toDisplayString(field.chooseLabel), 1 /* TEXT */)
|
|
83
|
+
]),
|
|
84
|
+
_: 2 /* DYNAMIC */
|
|
85
|
+
}, 1032 /* PROPS, DYNAMIC_SLOTS */, ["aria-describedby", "data-testid", "onClick"]))
|
|
86
|
+
: createCommentVNode("v-if", true),
|
|
87
|
+
(!field.readOnly && $data.form[field.key])
|
|
88
|
+
? (openBlock(), createBlock(_component_NcButton, {
|
|
89
|
+
key: 1,
|
|
90
|
+
variant: "tertiary",
|
|
91
|
+
"data-testid": `cn-settings-form-clear-${field.key}`,
|
|
92
|
+
onClick: $event => ($data.form[field.key] = '')
|
|
93
|
+
}, {
|
|
94
|
+
default: withCtx(() => [
|
|
95
|
+
createTextVNode(toDisplayString(field.clearLabel), 1 /* TEXT */)
|
|
96
|
+
]),
|
|
97
|
+
_: 2 /* DYNAMIC */
|
|
98
|
+
}, 1032 /* PROPS, DYNAMIC_SLOTS */, ["data-testid", "onClick"]))
|
|
99
|
+
: createCommentVNode("v-if", true)
|
|
100
|
+
], 8 /* PROPS */, _hoisted_3))
|
|
101
|
+
: (field.type === 'select')
|
|
102
|
+
? withDirectives((openBlock(), createElementBlock("select", {
|
|
103
|
+
key: 1,
|
|
104
|
+
id: $options.inputId(field),
|
|
105
|
+
"onUpdate:modelValue": $event => (($data.form[field.key]) = $event),
|
|
106
|
+
class: "cn-settings-form__control",
|
|
107
|
+
disabled: field.readOnly
|
|
108
|
+
}, [
|
|
109
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(field.options, (option) => {
|
|
110
|
+
return (openBlock(), createElementBlock("option", {
|
|
111
|
+
key: String(option.value),
|
|
112
|
+
value: option.value
|
|
113
|
+
}, toDisplayString(option.label), 9 /* TEXT, PROPS */, _hoisted_6))
|
|
114
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
115
|
+
], 8 /* PROPS */, _hoisted_5)), [
|
|
116
|
+
[vModelSelect, $data.form[field.key]]
|
|
117
|
+
])
|
|
118
|
+
: (field.type === 'textarea')
|
|
119
|
+
? withDirectives((openBlock(), createElementBlock("textarea", {
|
|
120
|
+
key: 2,
|
|
121
|
+
id: $options.inputId(field),
|
|
122
|
+
"onUpdate:modelValue": $event => (($data.form[field.key]) = $event),
|
|
123
|
+
class: "cn-settings-form__control cn-settings-form__control--area",
|
|
124
|
+
rows: field.rows,
|
|
125
|
+
placeholder: field.placeholder,
|
|
126
|
+
readonly: field.readOnly
|
|
127
|
+
}, null, 8 /* PROPS */, _hoisted_7)), [
|
|
128
|
+
[vModelText, $data.form[field.key]]
|
|
129
|
+
])
|
|
130
|
+
: withDirectives((openBlock(), createElementBlock("input", {
|
|
131
|
+
key: 3,
|
|
132
|
+
id: $options.inputId(field),
|
|
133
|
+
"onUpdate:modelValue": $event => (($data.form[field.key]) = $event),
|
|
134
|
+
class: "cn-settings-form__control",
|
|
135
|
+
type: field.type === 'number' ? 'number' : 'text',
|
|
136
|
+
min: field.min,
|
|
137
|
+
max: field.max,
|
|
138
|
+
placeholder: field.placeholder,
|
|
139
|
+
readonly: field.readOnly,
|
|
140
|
+
"aria-invalid": $data.errors[field.key] ? 'true' : null
|
|
141
|
+
}, null, 8 /* PROPS */, _hoisted_8)), [
|
|
142
|
+
[vModelDynamic, $data.form[field.key]]
|
|
143
|
+
])
|
|
144
|
+
], 64 /* STABLE_FRAGMENT */)),
|
|
145
|
+
($data.errors[field.key])
|
|
146
|
+
? (openBlock(), createElementBlock("p", _hoisted_9, toDisplayString($data.errors[field.key]), 1 /* TEXT */))
|
|
147
|
+
: (field.hint)
|
|
148
|
+
? (openBlock(), createElementBlock("p", _hoisted_10, toDisplayString(field.hint), 1 /* TEXT */))
|
|
149
|
+
: createCommentVNode("v-if", true)
|
|
150
|
+
], 10 /* CLASS, PROPS */, _hoisted_1))
|
|
151
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
152
|
+
], 2 /* CLASS */),
|
|
153
|
+
($data.notice)
|
|
154
|
+
? (openBlock(), createBlock(_component_NcNoteCard, {
|
|
155
|
+
key: 0,
|
|
156
|
+
type: $data.noticeType,
|
|
157
|
+
"data-testid": "cn-settings-form-notice"
|
|
158
|
+
}, {
|
|
159
|
+
default: withCtx(() => [
|
|
160
|
+
createTextVNode(toDisplayString($data.notice), 1 /* TEXT */)
|
|
161
|
+
]),
|
|
162
|
+
_: 1 /* STABLE */
|
|
163
|
+
}, 8 /* PROPS */, ["type"]))
|
|
164
|
+
: createCommentVNode("v-if", true),
|
|
165
|
+
(!$options.readOnly)
|
|
166
|
+
? (openBlock(), createElementBlock("div", _hoisted_11, [
|
|
167
|
+
createVNode(_component_NcButton, {
|
|
168
|
+
variant: "primary",
|
|
169
|
+
type: "submit",
|
|
170
|
+
disabled: $data.saving,
|
|
171
|
+
"data-testid": "cn-settings-form-save"
|
|
172
|
+
}, {
|
|
173
|
+
default: withCtx(() => [
|
|
174
|
+
createTextVNode(toDisplayString($options.saveLabel), 1 /* TEXT */)
|
|
175
|
+
]),
|
|
176
|
+
_: 1 /* STABLE */
|
|
177
|
+
}, 8 /* PROPS */, ["disabled"])
|
|
178
|
+
]))
|
|
179
|
+
: createCommentVNode("v-if", true)
|
|
180
|
+
], 32 /* NEED_HYDRATION */))
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export { render };
|
|
184
|
+
//# sourceMappingURL=CnSettingsFormWidget.vue3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CnSettingsFormWidget.vue3.js","sources":["../../../../src/components/CnSettingsFormWidget/CnSettingsFormWidget.vue?vue&type=template&id=731c450f&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<form class=\"cn-settings-form\"\n\t\tdata-testid=\"cn-settings-form\"\n\t\tnovalidate\n\t\t@submit.prevent=\"save\">\n\t\t<div class=\"cn-settings-form__grid\" :class=\"`cn-settings-form__grid--${columns}`\">\n\t\t\t<div\n\t\t\t\tv-for=\"field in fields\"\n\t\t\t\t:key=\"field.key\"\n\t\t\t\tclass=\"cn-settings-form__field\"\n\t\t\t\t:class=\"{ 'cn-settings-form__field--wide': field.wide }\"\n\t\t\t\t:data-testid=\"`cn-settings-form-field-${field.key}`\">\n\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\tv-if=\"field.type === 'switch'\"\n\t\t\t\t\tv-model=\"form[field.key]\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\t:disabled=\"field.readOnly\">\n\t\t\t\t\t{{ field.label }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t<template v-else>\n\t\t\t\t\t<label class=\"cn-settings-form__label\" :for=\"inputId(field)\">{{ field.label }}</label>\n\t\t\t\t\t<div v-if=\"field.type === 'file'\" class=\"cn-settings-form__file\" :data-testid=\"`cn-settings-form-file-${field.key}`\">\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t:id=\"inputId(field)\"\n\t\t\t\t\t\t\tclass=\"cn-settings-form__control cn-settings-form__control--file\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-settings-form__control--placeholder': !form[field.key] }\">\n\t\t\t\t\t\t\t{{ form[field.key] ? fileName(form[field.key]) : field.placeholder }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"!field.readOnly\"\n\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\t:aria-describedby=\"inputId(field)\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-settings-form-choose-${field.key}`\"\n\t\t\t\t\t\t\t@click=\"chooseFile(field)\">\n\t\t\t\t\t\t\t{{ field.chooseLabel }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"!field.readOnly && form[field.key]\"\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-settings-form-clear-${field.key}`\"\n\t\t\t\t\t\t\t@click=\"form[field.key] = ''\">\n\t\t\t\t\t\t\t{{ field.clearLabel }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</div>\n\t\t\t\t\t<select\n\t\t\t\t\t\tv-else-if=\"field.type === 'select'\"\n\t\t\t\t\t\t:id=\"inputId(field)\"\n\t\t\t\t\t\tv-model=\"form[field.key]\"\n\t\t\t\t\t\tclass=\"cn-settings-form__control\"\n\t\t\t\t\t\t:disabled=\"field.readOnly\">\n\t\t\t\t\t\t<option v-for=\"option in field.options\" :key=\"String(option.value)\" :value=\"option.value\">\n\t\t\t\t\t\t\t{{ option.label }}\n\t\t\t\t\t\t</option>\n\t\t\t\t\t</select>\n\t\t\t\t\t<textarea\n\t\t\t\t\t\tv-else-if=\"field.type === 'textarea'\"\n\t\t\t\t\t\t:id=\"inputId(field)\"\n\t\t\t\t\t\tv-model=\"form[field.key]\"\n\t\t\t\t\t\tclass=\"cn-settings-form__control cn-settings-form__control--area\"\n\t\t\t\t\t\t:rows=\"field.rows\"\n\t\t\t\t\t\t:placeholder=\"field.placeholder\"\n\t\t\t\t\t\t:readonly=\"field.readOnly\" />\n\t\t\t\t\t<input\n\t\t\t\t\t\tv-else\n\t\t\t\t\t\t:id=\"inputId(field)\"\n\t\t\t\t\t\tv-model=\"form[field.key]\"\n\t\t\t\t\t\tclass=\"cn-settings-form__control\"\n\t\t\t\t\t\t:type=\"field.type === 'number' ? 'number' : 'text'\"\n\t\t\t\t\t\t:min=\"field.min\"\n\t\t\t\t\t\t:max=\"field.max\"\n\t\t\t\t\t\t:placeholder=\"field.placeholder\"\n\t\t\t\t\t\t:readonly=\"field.readOnly\"\n\t\t\t\t\t\t:aria-invalid=\"errors[field.key] ? 'true' : null\">\n\t\t\t\t</template>\n\t\t\t\t<p v-if=\"errors[field.key]\" class=\"cn-settings-form__error\" role=\"alert\">\n\t\t\t\t\t{{ errors[field.key] }}\n\t\t\t\t</p>\n\t\t\t\t<p v-else-if=\"field.hint\" class=\"cn-settings-form__hint\">\n\t\t\t\t\t{{ field.hint }}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<NcNoteCard v-if=\"notice\" :type=\"noticeType\" data-testid=\"cn-settings-form-notice\">\n\t\t\t{{ notice }}\n\t\t</NcNoteCard>\n\n\t\t<div v-if=\"!readOnly\" class=\"cn-settings-form__actions\">\n\t\t\t<NcButton\n\t\t\t\tvariant=\"primary\"\n\t\t\t\ttype=\"submit\"\n\t\t\t\t:disabled=\"saving\"\n\t\t\t\tdata-testid=\"cn-settings-form-save\">\n\t\t\t\t{{ saveLabel }}\n\t\t\t</NcButton>\n\t\t</div>\n\t</form>\n</template>\n\n<script>\nimport { FilePickerClosed, getFilePickerBuilder } from '@nextcloud/dialogs'\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcNoteCard } from '@nextcloud/vue'\nimport { changedFields, objectUrlOf, patchObject } from '../../utils/objectWrite.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { serverErrorMessage } from '../../utils/serverErrorMessage.js'\n\n// The native file-picker modal ships its chrome styles here; without this the\n// spawned picker renders unstyled. Rules are scoped to the picker/dialog classes.\nimport '@nextcloud/dialogs/style.css'\n\nconst TYPES = ['text', 'textarea', 'select', 'switch', 'number', 'file']\n\nlet uid = 0\n\n/**\n * CnSettingsFormWidget — the `settings-form` widget: fields of the CURRENT\n * object as a one- or two-column grid of framed inputs with light labels and\n * hints, saved by ONE PATCH of the fields that changed since the last save.\n *\n * \"Last save\" is the baseline this widget keeps: a save moves it forward, so\n * editing a field back to the value the page loaded with, after a save, still\n * counts as a change (comparing against the loaded object skipped that PATCH).\n *\n * @spec openspec/changes/abstract-settings-form/specs/settings-form/spec.md\n */\nexport default {\n\tname: 'CnSettingsFormWidget',\n\n\tcomponents: { NcButton, NcCheckboxRadioSwitch, NcNoteCard },\n\n\tinject: {\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The widget configuration.\n\t\t *\n\t\t * - `fields` (required) — `[{ key, label, type?: 'text'|'textarea'|'select'|'switch'|'number'|'file', picker?: { title?, mimeTypes?, startAt?, valueTemplate? }, chooseLabel?, clearLabel?, hint?, placeholder?, options?: [{ value, label }], required?, pattern?, patternMessage?, min?, max?, rows?, wide?, readOnly? }]`; `key` is a top-level field of the object.\n\t\t * - `columns` — 1 or 2 (default 2).\n\t\t * - `saveLabel`, `savedText`, `readOnly`.\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** The current detail-page object. */\n\t\tobjectData: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** The current object id. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister register slug of the surface. */\n\t\tregister: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema slug of the surface. */\n\t\tschema: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['saved'],\n\n\tdata() {\n\t\tuid += 1\n\t\treturn {\n\t\t\tuid,\n\t\t\tform: {},\n\t\t\tbaseline: {},\n\t\t\terrors: {},\n\t\t\tsaving: false,\n\t\t\tnotice: '',\n\t\t\tnoticeType: 'success',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The configured fields, normalised and translated.\n\t\t *\n\t\t * @return {Array<object>}\n\t\t */\n\t\tfields() {\n\t\t\tconst list = Array.isArray(this.content.fields) ? this.content.fields : []\n\t\t\treturn list\n\t\t\t\t.filter((field) => field && field.key)\n\t\t\t\t.map((field) => ({\n\t\t\t\t\t...field,\n\t\t\t\t\ttype: TYPES.includes(field.type) ? field.type : 'text',\n\t\t\t\t\tlabel: this.tr(field.label || field.key),\n\t\t\t\t\thint: this.tr(field.hint || ''),\n\t\t\t\t\tplaceholder: this.tr(field.placeholder || ''),\n\t\t\t\t\tchooseLabel: this.tr(field.chooseLabel || 'Choose a file'),\n\t\t\t\t\tclearLabel: this.tr(field.clearLabel || 'Remove'),\n\t\t\t\t\trows: field.rows || 3,\n\t\t\t\t\twide: field.wide === true || field.type === 'textarea',\n\t\t\t\t\treadOnly: this.readOnly || field.readOnly === true,\n\t\t\t\t\toptions: (Array.isArray(field.options) ? field.options : []).map((option) => (\n\t\t\t\t\t\ttypeof option === 'object' && option !== null\n\t\t\t\t\t\t\t? { value: option.value, label: this.tr(String(option.label ?? option.value)) }\n\t\t\t\t\t\t\t: { value: option, label: this.tr(String(option)) }\n\t\t\t\t\t)),\n\t\t\t\t}))\n\t\t},\n\n\t\tcolumns() {\n\t\t\treturn this.content.columns === 1 ? 1 : 2\n\t\t},\n\n\t\treadOnly() {\n\t\t\treturn this.content.readOnly === true\n\t\t},\n\n\t\tsaveLabel() {\n\t\t\treturn this.tr(this.content.saveLabel || 'Save')\n\t\t},\n\n\t\t/** The object URL the form is saved to, or '' when it is not known. */\n\t\tobjectUrl() {\n\t\t\treturn objectUrlOf(this.register, this.schema, this.objectId || (this.objectData && this.objectData.id))\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectData() {\n\t\t\tthis.adopt()\n\t\t},\n\t},\n\n\tcreated() {\n\t\tthis.adopt(true)\n\t},\n\n\tmethods: {\n\t\ttr(text) {\n\t\t\tif (typeof text !== 'string' || text === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\tinputId(field) {\n\t\t\treturn `cn-settings-form-${this.uid}-${field.key}`\n\t\t},\n\n\t\t/**\n\t\t * The name shown for a stored file value: its last path segment.\n\t\t *\n\t\t * @param {string} value The stored value.\n\t\t * @return {string}\n\t\t */\n\t\tfileName(value) {\n\t\t\tconst text = String(value)\n\t\t\treturn text.split('/').filter(Boolean).pop() || text\n\t\t},\n\n\t\t/**\n\t\t * Open the Nextcloud file picker and take the chosen file as the value.\n\t\t * `field.picker` = `{ title?, mimeTypes?, startAt?, valueTemplate? }`; the\n\t\t * template's `{path}`, `{fileid}` and `{name}` are filled from the chosen\n\t\t * node (default `{path}`).\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/abstract-settings-form-file/specs/settings-form/spec.md#requirement-a-file-field-takes-a-file-from-the-nextcloud-picker\n\t\t */\n\t\tasync chooseFile(field) {\n\t\t\tconst picker = field.picker || {}\n\t\t\tlet builder = getFilePickerBuilder(this.tr(picker.title || field.label))\n\t\t\t\t.setMultiSelect(false)\n\t\t\t\t.allowDirectories(false)\n\t\t\t\t.startAt(picker.startAt || '/')\n\t\t\t\t.addButton({ label: t('nextcloud-vue', 'Choose'), type: 'primary', callback: () => {} })\n\t\t\tif (Array.isArray(picker.mimeTypes) && picker.mimeTypes.length > 0) {\n\t\t\t\tbuilder = builder.setMimeTypeFilter(picker.mimeTypes)\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst nodes = await builder.build().pickNodes()\n\t\t\t\tconst node = Array.isArray(nodes) ? nodes[0] : nodes\n\t\t\t\tif (!node) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthis.form[field.key] = String(picker.valueTemplate || '{path}').replace(/\\{(path|fileid|name)\\}/g, (match, part) => {\n\t\t\t\t\tconst value = part === 'name' ? (node.basename || this.fileName(node.path)) : node[part]\n\t\t\t\t\treturn value === undefined || value === null ? '' : String(value)\n\t\t\t\t})\n\t\t\t} catch (e) {\n\t\t\t\tif (e instanceof FilePickerClosed) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthis.noticeType = 'error'\n\t\t\t\tthis.notice = this.tr('The file picker could not be opened.')\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The stored value of a field as the input holds it.\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {unknown}\n\t\t */\n\t\tstored(field) {\n\t\t\tconst value = readPath(this.objectData || {}, field.key)\n\t\t\tif (field.type === 'switch') {\n\t\t\t\treturn value === true\n\t\t\t}\n\t\t\treturn value === undefined || value === null ? '' : value\n\t\t},\n\n\t\t/**\n\t\t * Take the object's values as the new baseline; a field the person has\n\t\t * not touched follows it, a touched one keeps the typed value.\n\t\t *\n\t\t * @param {boolean} [first] Whether this is the first read.\n\t\t */\n\t\tadopt(first = false) {\n\t\t\tconst baseline = {}\n\t\t\tconst form = {}\n\t\t\tfor (const field of this.fields) {\n\t\t\t\tbaseline[field.key] = this.stored(field)\n\t\t\t\tconst untouched = first || JSON.stringify(this.form[field.key]) === JSON.stringify(this.baseline[field.key])\n\t\t\t\tform[field.key] = untouched ? baseline[field.key] : this.form[field.key]\n\t\t\t}\n\t\t\tthis.baseline = baseline\n\t\t\tthis.form = form\n\t\t},\n\n\t\t/**\n\t\t * The value to send for a field: numbers as numbers, an empty value as null.\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {unknown}\n\t\t */\n\t\toutgoing(field) {\n\t\t\tconst value = this.form[field.key]\n\t\t\tif (field.type === 'number') {\n\t\t\t\treturn value === '' || value === null || value === undefined ? null : Number(value)\n\t\t\t}\n\t\t\tif (field.type === 'switch') {\n\t\t\t\treturn value === true\n\t\t\t}\n\t\t\tif (typeof value === 'string') {\n\t\t\t\treturn value.trim() === '' ? null : value.trim()\n\t\t\t}\n\t\t\treturn value\n\t\t},\n\n\t\t/**\n\t\t * Check required, number range and pattern before any write.\n\t\t *\n\t\t * @return {object} Error text by field key.\n\t\t */\n\t\tvalidate() {\n\t\t\tconst errors = {}\n\t\t\tfor (const field of this.fields) {\n\t\t\t\tif (field.type === 'switch' || field.readOnly) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst value = this.outgoing(field)\n\t\t\t\tconst empty = value === null || value === undefined || value === ''\n\t\t\t\tif (empty) {\n\t\t\t\t\tif (field.required) {\n\t\t\t\t\t\terrors[field.key] = this.tr('Fill this in.')\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (field.type === 'number') {\n\t\t\t\t\tif (Number.isNaN(value) || (field.min !== undefined && value < field.min) || (field.max !== undefined && value > field.max)) {\n\t\t\t\t\t\terrors[field.key] = this.tr('This number is not valid.')\n\t\t\t\t\t}\n\t\t\t\t} else if (field.pattern && !new RegExp(field.pattern).test(String(value))) {\n\t\t\t\t\terrors[field.key] = this.tr(field.patternMessage || 'This value is not valid.')\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn errors\n\t\t},\n\n\t\t/**\n\t\t * Save: PATCH the fields that differ from the last saved values.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/abstract-settings-form/specs/settings-form/spec.md#requirement-a-settings-form-saves-only-what-changed\n\t\t */\n\t\tasync save() {\n\t\t\tthis.errors = this.validate()\n\t\t\tthis.notice = ''\n\t\t\tif (Object.keys(this.errors).length > 0) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!this.objectUrl) {\n\t\t\t\tthis.noticeType = 'error'\n\t\t\t\tthis.notice = this.tr('This form cannot be saved here.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst next = {}\n\t\t\tconst compare = {}\n\t\t\tfor (const field of this.fields) {\n\t\t\t\tif (!field.readOnly) {\n\t\t\t\t\tnext[field.key] = this.outgoing(field)\n\t\t\t\t\tcompare[field.key] = this.baseline[field.key] === '' ? null : this.baseline[field.key]\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst patch = changedFields(compare, next)\n\t\t\tthis.saving = true\n\t\t\ttry {\n\t\t\t\tif (Object.keys(patch).length > 0) {\n\t\t\t\t\tconst data = await patchObject(this.objectUrl, patch)\n\t\t\t\t\tconst baseline = { ...this.baseline }\n\t\t\t\t\tconst form = { ...this.form }\n\t\t\t\t\tfor (const key of Object.keys(patch)) {\n\t\t\t\t\t\tconst field = this.fields.find((candidate) => candidate.key === key)\n\t\t\t\t\t\tconst written = data[key] !== undefined ? data[key] : patch[key]\n\t\t\t\t\t\tbaseline[key] = field.type === 'switch' ? written === true : (written === null ? '' : written)\n\t\t\t\t\t\tform[key] = baseline[key]\n\t\t\t\t\t}\n\t\t\t\t\tthis.baseline = baseline\n\t\t\t\t\tthis.form = form\n\t\t\t\t}\n\t\t\t\tthis.noticeType = 'success'\n\t\t\t\tthis.notice = this.tr(this.content.savedText || 'Saved.')\n\t\t\t\t/**\n\t\t\t\t * @event saved The changed fields were written.\n\t\t\t\t * @type {{patch: object}}\n\t\t\t\t */\n\t\t\t\tthis.$emit('saved', { patch })\n\t\t\t} catch (e) {\n\t\t\t\tthis.noticeType = 'error'\n\t\t\t\tthis.notice = serverErrorMessage(e)\n\t\t\t} finally {\n\t\t\t\tthis.saving = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-settings-form {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 14px;\n\tmin-width: 0;\n}\n\n.cn-settings-form__grid {\n\tdisplay: grid;\n\tgap: 14px 16px;\n\tgrid-template-columns: minmax(0, 1fr);\n}\n\n.cn-settings-form__grid--2 {\n\tgrid-template-columns: repeat(2, minmax(0, 1fr));\n}\n\n.cn-settings-form__field {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tmin-width: 0;\n}\n\n.cn-settings-form__field--wide {\n\tgrid-column: 1 / -1;\n}\n\n.cn-settings-form__label {\n\tfont-size: 13px;\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n}\n\n.cn-settings-form__control {\n\twidth: 100%;\n\tbox-sizing: border-box;\n\theight: var(--cn-board-control-height, 40px);\n\tpadding: 0 12px;\n\tborder: 1px solid var(--color-border-maxcontrast);\n\tborder-radius: var(--cn-board-control-radius, 8px);\n\tbackground: var(--color-main-background);\n\tcolor: var(--color-main-text);\n\tfont: inherit;\n}\n\n.cn-settings-form__file {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-settings-form__control--file {\n\tdisplay: inline-flex;\n\talign-items: center;\n\twidth: auto;\n\tmin-width: 120px;\n\tflex: 0 1 auto;\n\toverflow-wrap: anywhere;\n}\n\n.cn-settings-form__control--placeholder {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-settings-form__control--area {\n\theight: auto;\n\tpadding: 10px 12px;\n\tresize: vertical;\n}\n\n.cn-settings-form__control:focus-visible {\n\toutline: 2px solid var(--color-primary-element);\n\toutline-offset: 1px;\n}\n\n.cn-settings-form__hint,\n.cn-settings-form__error {\n\tmargin: 0;\n\tfont-size: 12px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-settings-form__error {\n\tcolor: var(--color-error-text);\n}\n\n.cn-settings-form__actions {\n\tdisplay: flex;\n\tjustify-content: flex-start;\n}\n\n@media (max-width: 640px) {\n\t.cn-settings-form__grid--2 {\n\t\tgrid-template-columns: minmax(0, 1fr);\n\t}\n}\n</style>\n"],"names":["_createElementBlock","_normalizeClass","_Fragment","_renderList","_createBlock","_createTextVNode","_toDisplayString","_createElementVNode","_openBlock"],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import __sfc_main from './CnSettingsFormWidget.vue.js';
|
|
2
|
+
import { registerDashboardWidget } from '../CnWidgetGrid/dashboardWidgetRegistry.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
6
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
7
|
+
*
|
|
8
|
+
* CnSettingsFormWidget — self-registers the `settings-form` widget type (framed
|
|
9
|
+
* inputs for fields of the current object, saved by PATCH of the changed
|
|
10
|
+
* fields) into the shared dashboardWidgetRegistry at module load.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
registerDashboardWidget('settings-form', {
|
|
15
|
+
renderer: __sfc_main,
|
|
16
|
+
form: null,
|
|
17
|
+
defaultContent: {
|
|
18
|
+
fields: [],
|
|
19
|
+
columns: 2,
|
|
20
|
+
},
|
|
21
|
+
displayName: 'Settings form',
|
|
22
|
+
icon: 'FormTextbox',
|
|
23
|
+
surfaces: ['detail-page'],
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export { __sfc_main as CnSettingsFormWidget, __sfc_main as default };
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/CnSettingsFormWidget/index.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * CnSettingsFormWidget — self-registers the `settings-form` widget type (framed\n * inputs for fields of the current object, saved by PATCH of the changed\n * fields) into the shared dashboardWidgetRegistry at module load.\n */\n\nimport CnSettingsFormWidget from './CnSettingsFormWidget.vue'\nimport { registerDashboardWidget } from '../CnWidgetGrid/dashboardWidgetRegistry.js'\n\nregisterDashboardWidget('settings-form', {\n\trenderer: CnSettingsFormWidget,\n\tform: null,\n\tdefaultContent: {\n\t\tfields: [],\n\t\tcolumns: 2,\n\t},\n\tdisplayName: 'Settings form',\n\ticon: 'FormTextbox',\n\tsurfaces: ['detail-page'],\n})\n\nexport { CnSettingsFormWidget }\nexport default CnSettingsFormWidget\n"],"names":["CnSettingsFormWidget"],"mappings":";;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA,uBAAuB,CAAC,eAAe,EAAE;AACzC,CAAC,QAAQ,EAAEA,UAAoB;AAC/B,CAAC,IAAI,EAAE,IAAI;AACX,CAAC,cAAc,EAAE;AACjB,EAAE,MAAM,EAAE,EAAE;AACZ,EAAE,OAAO,EAAE,CAAC;AACZ,EAAE;AACF,CAAC,WAAW,EAAE,eAAe;AAC7B,CAAC,IAAI,EAAE,aAAa;AACpB,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC;AAC1B,CAAC;;;;"}
|
|
@@ -6,8 +6,10 @@ import __sfc_main$1 from '../../dialogs/CnTransitionInputDialog.vue.js';
|
|
|
6
6
|
import __sfc_main from '../CnTimelineStages/CnTimelineStages.vue.js';
|
|
7
7
|
import { useEndpointSource, getByPath } from '../../composables/useEndpointSource.js';
|
|
8
8
|
import { actionsByTarget, isBlockedAction, actionNote, declaresInputs, performTransition, transitionError, readAvailableActions } from '../../composables/useLifecycleTransitions.js';
|
|
9
|
+
import { normalizeLook } from '../../composables/useLook.js';
|
|
9
10
|
import { useObjectStore } from '../../store/useObjectStore.js';
|
|
10
11
|
import { resolveObjectOpType } from '../../utils/actionsDispatcher.js';
|
|
12
|
+
import { formatBoardDate } from '../../utils/boardDate.js';
|
|
11
13
|
import { resolveObjectTokenContext } from '../../utils/detailObjectContext.js';
|
|
12
14
|
import { resolveFilterTokens, dropOptionalUnresolved, hasUnresolvedTokens } from '../../utils/resolveFilterTokens.js';
|
|
13
15
|
import { normalizeStages, stageSavePayload } from './stagesModel.js';
|
|
@@ -83,6 +85,14 @@ function userError(message) {
|
|
|
83
85
|
* labelField?, descriptionField?, finalField?, limit? }`, an OpenRegister
|
|
84
86
|
* query whose filter takes the same tokens.
|
|
85
87
|
*
|
|
88
|
+
* `datesSource`: `{ url, method?, params?, path?, idField?, dateField? }`, an
|
|
89
|
+
* endpoint (same token grammar) answering the date the record reached each
|
|
90
|
+
* stage, when the stage list does not carry it: the case type's statuses list
|
|
91
|
+
* the steps, `/blueprint?case=@objectId` says when this case reached them.
|
|
92
|
+
* Read once, merged into the steps by `idField` (default `id`) with the value
|
|
93
|
+
* at `dateField` (default `reachedAt`); a date it does not give falls back to
|
|
94
|
+
* the stage list's own `dateField`. The bars variant draws it.
|
|
95
|
+
*
|
|
86
96
|
* `finalField` marks the stages that close the record, which the timeline
|
|
87
97
|
* draws differently. It grants nothing either.
|
|
88
98
|
*
|
|
@@ -175,7 +185,7 @@ var script = {
|
|
|
175
185
|
* `label`, the placement's own title, so a titled card does not have to
|
|
176
186
|
* repeat itself, and then to "Stages".
|
|
177
187
|
*
|
|
178
|
-
* @type {{currentField?: string, stagesEndpoint?: object, stagesSource?: object, transition?: object, unreachableReason?: string, orientation?: ('horizontal'|'vertical'), size?: ('medium'|'small'), ariaLabel?: string, label?: string, variant?: ('dots'|'bars')}}
|
|
188
|
+
* @type {{currentField?: string, stagesEndpoint?: object, stagesSource?: object, transition?: object, unreachableReason?: string, orientation?: ('horizontal'|'vertical'), size?: ('medium'|'small'), ariaLabel?: string, label?: string, variant?: ('dots'|'bars'), datesSource?: {url: string, method?: string, params?: object, path?: string, idField?: string, dateField?: string}}}
|
|
179
189
|
*/
|
|
180
190
|
content: {
|
|
181
191
|
type: Object,
|
|
@@ -256,6 +266,8 @@ var script = {
|
|
|
256
266
|
const workspaceRaw = inject('cnWorkspaceContext', ref({}));
|
|
257
267
|
const appConfigRaw = inject('cnAppConfig', ref({}));
|
|
258
268
|
const cnTranslate = inject('cnTranslate', (key) => key);
|
|
269
|
+
// The app's look (`nextcloud` or `board`), provided by CnAppRoot or CnPageRenderer.
|
|
270
|
+
const cnLook = inject('cnLook', 'nextcloud');
|
|
259
271
|
|
|
260
272
|
/**
|
|
261
273
|
* The token context: the bound record, its id, and the page context.
|
|
@@ -281,15 +293,24 @@ var script = {
|
|
|
281
293
|
return (cfg && cfg.url) ? { url: cfg.url, method: cfg.method, params: cfg.params } : null
|
|
282
294
|
}, { ctx: tokenCtx });
|
|
283
295
|
|
|
296
|
+
// The dates the record reached each stage, when they live apart from
|
|
297
|
+
// the stage list (`datesSource`): one read, merged into the steps by id.
|
|
298
|
+
const datesRead = useEndpointSource(() => {
|
|
299
|
+
const cfg = props.content?.datesSource;
|
|
300
|
+
return (cfg && cfg.url) ? { url: cfg.url, method: cfg.method, params: cfg.params } : null
|
|
301
|
+
}, { ctx: tokenCtx });
|
|
302
|
+
|
|
284
303
|
return {
|
|
285
304
|
detailCtxRaw,
|
|
286
305
|
objectCtxRaw,
|
|
287
306
|
cnTranslate,
|
|
307
|
+
cnLook,
|
|
288
308
|
tokenCtx,
|
|
289
309
|
stagesBody: stagesRead.data,
|
|
290
310
|
stagesBodyLoading: stagesRead.loading,
|
|
291
311
|
stagesBodyError: stagesRead.error,
|
|
292
312
|
stagesBodyBlocked: stagesRead.blocked,
|
|
313
|
+
datesBody: datesRead.data,
|
|
293
314
|
}
|
|
294
315
|
},
|
|
295
316
|
|
|
@@ -433,6 +454,42 @@ var script = {
|
|
|
433
454
|
return normalizeStages(rows, { ...cfg, orderField })
|
|
434
455
|
},
|
|
435
456
|
|
|
457
|
+
/**
|
|
458
|
+
* The reached dates by stage id, from `datesSource`: the rows at its
|
|
459
|
+
* `path` (or the response itself when it is a list), keyed by
|
|
460
|
+
* `idField` (default `id`), the value at `dateField` (default
|
|
461
|
+
* `reachedAt`). Empty without the option, while it loads, or when it
|
|
462
|
+
* failed: the steps then show the stage list's own dates.
|
|
463
|
+
*
|
|
464
|
+
* @return {{[id: string]: string}} Date by stage id.
|
|
465
|
+
* @spec openspec/changes/screens-stage-dates-source/specs/stage-dates-source/spec.md#requirement-the-reached-dates-can-come-from-their-own-endpoint
|
|
466
|
+
*/
|
|
467
|
+
stageDates() {
|
|
468
|
+
const cfg = this.content.datesSource;
|
|
469
|
+
const body = this.datesBody;
|
|
470
|
+
if (!cfg || !cfg.url || body === null || body === undefined) {
|
|
471
|
+
return {}
|
|
472
|
+
}
|
|
473
|
+
const rows = Array.isArray(body) ? body : getByPath(body, cfg.path || '');
|
|
474
|
+
if (!Array.isArray(rows)) {
|
|
475
|
+
return {}
|
|
476
|
+
}
|
|
477
|
+
const idField = cfg.idField || 'id';
|
|
478
|
+
const dateField = cfg.dateField || 'reachedAt';
|
|
479
|
+
const out = {};
|
|
480
|
+
for (const row of rows) {
|
|
481
|
+
if (!row || typeof row !== 'object') {
|
|
482
|
+
continue
|
|
483
|
+
}
|
|
484
|
+
const id = getByPath(row, idField);
|
|
485
|
+
const date = getByPath(row, dateField);
|
|
486
|
+
if (id !== null && id !== undefined && id !== '' && typeof date === 'string' && date !== '') {
|
|
487
|
+
out[String(id)] = date;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return out
|
|
491
|
+
},
|
|
492
|
+
|
|
436
493
|
/**
|
|
437
494
|
* Whether the stage list is still on its way.
|
|
438
495
|
*
|
|
@@ -614,7 +671,7 @@ var script = {
|
|
|
614
671
|
}
|
|
615
672
|
return {
|
|
616
673
|
...stage,
|
|
617
|
-
date: this.stages[index]?.date || '',
|
|
674
|
+
date: this.barDate(this.stageDates[stage.id] || this.stages[index]?.date || '', state),
|
|
618
675
|
state,
|
|
619
676
|
clickable: this.interactive && state !== 'current',
|
|
620
677
|
}
|
|
@@ -710,6 +767,28 @@ var script = {
|
|
|
710
767
|
},
|
|
711
768
|
|
|
712
769
|
methods: {
|
|
770
|
+
/**
|
|
771
|
+
* A bar's date line. Under the board look a date value reads in the
|
|
772
|
+
* board's short form ("3 okt"), and the current step's reads "sinds
|
|
773
|
+
* 4 okt", as DqZaak draws it. Any other value, and every value outside
|
|
774
|
+
* the board look, shows as written.
|
|
775
|
+
*
|
|
776
|
+
* @param {string} value The `dateField` value of the stage row.
|
|
777
|
+
* @param {string} state The bar state (`done`, `current`, `todo`).
|
|
778
|
+
* @return {string} The date line, or ''.
|
|
779
|
+
* @spec openspec/changes/screens-stage-bar-dates-parity/specs/stage-bar-dates/spec.md#requirement-a-bar-date-reads-as-the-board-draws-it
|
|
780
|
+
*/
|
|
781
|
+
barDate(value, state) {
|
|
782
|
+
if (!value || normalizeLook(this.cnLook) !== 'board') {
|
|
783
|
+
return value
|
|
784
|
+
}
|
|
785
|
+
const short = formatBoardDate(value);
|
|
786
|
+
if (short === '') {
|
|
787
|
+
return value
|
|
788
|
+
}
|
|
789
|
+
return state === 'current' ? translate('nextcloud-vue', 'since {date}', { date: short }) : short
|
|
790
|
+
},
|
|
791
|
+
|
|
713
792
|
/**
|
|
714
793
|
* Translate a library string.
|
|
715
794
|
*
|