@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
package/src/components/index.js
CHANGED
|
@@ -216,6 +216,24 @@ export { CnFlowStepOutcomes } from './CnFlowStepOutcomes/index.js'
|
|
|
216
216
|
export { CnFlowRunsWidgetForm } from './CnFlowRunsWidgetForm/index.js'
|
|
217
217
|
export { CnTasksWidget } from './CnTasksWidget/index.js'
|
|
218
218
|
export { CnTasksWidgetForm } from './CnTasksWidgetForm/index.js'
|
|
219
|
+
export { CnSectionsWidget } from './CnSectionsWidget/index.js'
|
|
220
|
+
export { CnFactsWidget } from './CnFactsWidget/index.js'
|
|
221
|
+
export { CnFieldListWidget } from './CnFieldListWidget/index.js'
|
|
222
|
+
export { CnSettingsFormWidget } from './CnSettingsFormWidget/index.js'
|
|
223
|
+
export { CnSwitchRowsWidget } from './CnSwitchRowsWidget/index.js'
|
|
224
|
+
export { CnRadioCardsWidget } from './CnRadioCardsWidget/index.js'
|
|
225
|
+
export { CnChipsFieldWidget } from './CnChipsFieldWidget/index.js'
|
|
226
|
+
export { CnToggleTableWidget } from './CnToggleTableWidget/index.js'
|
|
227
|
+
export { CnChoicePickerWidget } from './CnChoicePickerWidget/index.js'
|
|
228
|
+
export { CnRecordListWidget } from './CnRecordListWidget/index.js'
|
|
229
|
+
export { CnBannerWidget } from './CnBannerWidget/index.js'
|
|
230
|
+
export { default as CnConversationWidget } from './CnConversationThread/CnConversationWidget.vue'
|
|
231
|
+
export { default as CnDocumentReviewWidget } from './CnDocumentReviewList/CnDocumentReviewWidget.vue'
|
|
232
|
+
export { default as CnNextStepWidget } from './CnNextStepCard/CnNextStepWidget.vue'
|
|
233
|
+
export { default as CnAuditTrailWidget } from './CnAuditTrailWidget/CnAuditTrailWidget.vue'
|
|
234
|
+
export { CnKbSearchWidget } from './CnKbSearchWidget/index.js'
|
|
235
|
+
export { CnInteractionFormWidget } from './CnInteractionFormWidget/index.js'
|
|
236
|
+
export { CnWorkspaceFilterWidget } from './CnWorkspaceFilterWidget/index.js'
|
|
219
237
|
export { CnFilePreview } from './CnFilePreview/index.js'
|
|
220
238
|
export { CnTaskFormDialog } from './CnTaskFormDialog/index.js'
|
|
221
239
|
export { CnChildRecordsField } from './CnChildRecordsField/index.js'
|
|
@@ -224,6 +242,7 @@ export { CnMarkdownWidget } from './CnMarkdownWidget/index.js'
|
|
|
224
242
|
export { CnMarkdownWidgetForm } from './CnMarkdownWidgetForm/index.js'
|
|
225
243
|
export { CnObjectListWidget } from './CnObjectListWidget/index.js'
|
|
226
244
|
export { CnObjectListWidgetForm } from './CnObjectListWidgetForm/index.js'
|
|
245
|
+
export { CnSavedViewsWidget } from './CnSavedViewsWidget/index.js'
|
|
227
246
|
export { CnSavedViewWidget } from './CnSavedViewWidget/index.js'
|
|
228
247
|
export { CnSavedViewWidgetForm } from './CnSavedViewWidgetForm/index.js'
|
|
229
248
|
export { CnChartWidgetForm } from './CnChartWidgetForm/index.js'
|
|
@@ -17,11 +17,21 @@
|
|
|
17
17
|
* one, and it would be this library's fault in somebody else's app.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
+
jest.mock('@nextcloud/auth', () => ({
|
|
21
|
+
...jest.requireActual('@nextcloud/auth'),
|
|
22
|
+
getCurrentUser: jest.fn(() => null),
|
|
23
|
+
}))
|
|
24
|
+
|
|
25
|
+
import { getCurrentUser } from '@nextcloud/auth'
|
|
20
26
|
import {
|
|
27
|
+
clearAnonymousDrafts,
|
|
21
28
|
clearDraft,
|
|
22
29
|
DRAFT_MAX_AGE_MS,
|
|
23
30
|
draftKey,
|
|
31
|
+
hasDraftChanges,
|
|
24
32
|
readDraft,
|
|
33
|
+
resolveDraftUserId,
|
|
34
|
+
sameDraftValue,
|
|
25
35
|
writeDraft,
|
|
26
36
|
} from '../useFormDraft.js'
|
|
27
37
|
|
|
@@ -170,3 +180,62 @@ describe('when storage is not available', () => {
|
|
|
170
180
|
expect(() => clearDraft('cn-form-draft:a:s:new:u')).not.toThrow()
|
|
171
181
|
})
|
|
172
182
|
})
|
|
183
|
+
|
|
184
|
+
// @spec openspec/changes/form-draft-on-change-and-help-text-spacing/specs/form-draft-on-change-and-help-text-spacing/spec.md#requirement-a-draft-belongs-to-the-signed-in-user
|
|
185
|
+
describe('resolveDraftUserId', () => {
|
|
186
|
+
afterEach(() => getCurrentUser.mockReturnValue(null))
|
|
187
|
+
|
|
188
|
+
it('prefers the id the host passed', () => {
|
|
189
|
+
getCurrentUser.mockReturnValue({ uid: 'cluade' })
|
|
190
|
+
expect(resolveDraftUserId('anne')).toBe('anne')
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
it('falls back to the signed-in user', () => {
|
|
194
|
+
getCurrentUser.mockReturnValue({ uid: 'cluade' })
|
|
195
|
+
expect(resolveDraftUserId('')).toBe('cluade')
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it('is empty when nobody is signed in, and when the lookup throws', () => {
|
|
199
|
+
expect(resolveDraftUserId()).toBe('')
|
|
200
|
+
getCurrentUser.mockImplementationOnce(() => {
|
|
201
|
+
throw new Error('no head')
|
|
202
|
+
})
|
|
203
|
+
expect(resolveDraftUserId()).toBe('')
|
|
204
|
+
})
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
describe('clearAnonymousDrafts', () => {
|
|
208
|
+
beforeEach(() => window.localStorage.clear())
|
|
209
|
+
|
|
210
|
+
it('removes only drafts stored under anonymous', () => {
|
|
211
|
+
const anon = draftKey({ appId: 'pipelinq', schema: 'crmTask', objectId: 't1' })
|
|
212
|
+
const anne = draftKey({ appId: 'pipelinq', schema: 'crmTask', objectId: 't1', userId: 'anne' })
|
|
213
|
+
writeDraft(anon, { title: 'x' })
|
|
214
|
+
writeDraft(anne, { title: 'y' })
|
|
215
|
+
window.localStorage.setItem('unrelated:anonymous', 'keep')
|
|
216
|
+
|
|
217
|
+
expect(clearAnonymousDrafts()).toBe(1)
|
|
218
|
+
expect(window.localStorage.getItem(anon)).toBeNull()
|
|
219
|
+
expect(window.localStorage.getItem(anne)).not.toBeNull()
|
|
220
|
+
expect(window.localStorage.getItem('unrelated:anonymous')).toBe('keep')
|
|
221
|
+
})
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
// @spec openspec/changes/form-draft-on-change-and-help-text-spacing/specs/form-draft-on-change-and-help-text-spacing/spec.md#requirement-a-draft-is-written-only-after-a-person-changes-a-field
|
|
225
|
+
describe('hasDraftChanges', () => {
|
|
226
|
+
it('treats empty values as equal', () => {
|
|
227
|
+
expect(sameDraftValue(null, '')).toBe(true)
|
|
228
|
+
expect(sameDraftValue(undefined, [])).toBe(true)
|
|
229
|
+
expect(sameDraftValue('a', 'b')).toBe(false)
|
|
230
|
+
expect(sameDraftValue({ a: 1 }, { a: 1 })).toBe(true)
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
it('counts only fields a person edited', () => {
|
|
234
|
+
const baseline = { title: 'Call back', notes: '' }
|
|
235
|
+
// The form changed `notes` by itself; nobody edited it.
|
|
236
|
+
expect(hasDraftChanges({ title: 'Call back', notes: 'filled in' }, baseline, [])).toBe(false)
|
|
237
|
+
// Edited, but back to what it was.
|
|
238
|
+
expect(hasDraftChanges({ title: 'Call back' }, baseline, ['title'])).toBe(false)
|
|
239
|
+
expect(hasDraftChanges({ title: 'Call back tomorrow' }, baseline, ['title'])).toBe(true)
|
|
240
|
+
})
|
|
241
|
+
})
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
* value, and the audit trail is read by people answering "who changed this".
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
+
import { getCurrentUser } from '@nextcloud/auth'
|
|
26
27
|
import { translate as t } from '@nextcloud/l10n'
|
|
27
28
|
|
|
28
29
|
/** How long a draft stays interesting, in milliseconds (7 days). */
|
|
@@ -34,6 +35,9 @@ export const DRAFT_DEBOUNCE_MS = 500
|
|
|
34
35
|
/** The prefix every draft key carries, so a sweep can find them. */
|
|
35
36
|
export const DRAFT_KEY_PREFIX = 'cn-form-draft'
|
|
36
37
|
|
|
38
|
+
/** The user part of a draft key when nobody is signed in. */
|
|
39
|
+
export const DRAFT_ANONYMOUS_USER = 'anonymous'
|
|
40
|
+
|
|
37
41
|
/**
|
|
38
42
|
* The storage key one form's draft lives under.
|
|
39
43
|
*
|
|
@@ -54,10 +58,124 @@ export function draftKey({ appId = '', schema = '', objectId = '', userId = '' }
|
|
|
54
58
|
String(appId || 'app'),
|
|
55
59
|
String(schema || 'schema'),
|
|
56
60
|
String(objectId || 'new'),
|
|
57
|
-
String(userId ||
|
|
61
|
+
String(userId || DRAFT_ANONYMOUS_USER),
|
|
58
62
|
].join(':')
|
|
59
63
|
}
|
|
60
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Who a draft belongs to: the id the host passed, else the signed-in
|
|
67
|
+
* Nextcloud user, else '' (which {@link draftKey} stores as `anonymous`).
|
|
68
|
+
*
|
|
69
|
+
* 🔴 A HOST THAT PASSES NOTHING STILL GETS PER-USER DRAFTS. Leaving the user
|
|
70
|
+
* to every host meant no host passed it, and every draft on a shared device
|
|
71
|
+
* was keyed `anonymous`: the next person at the counter was offered what the
|
|
72
|
+
* last one typed.
|
|
73
|
+
*
|
|
74
|
+
* @param {string} [explicit] The id the host passed (`draftUserId`).
|
|
75
|
+
* @return {string} The user id, or '' when nobody is signed in.
|
|
76
|
+
* @spec openspec/changes/form-draft-on-change-and-help-text-spacing/specs/form-draft-on-change-and-help-text-spacing/spec.md#requirement-a-draft-belongs-to-the-signed-in-user
|
|
77
|
+
*/
|
|
78
|
+
export function resolveDraftUserId(explicit = '') {
|
|
79
|
+
if (explicit) {
|
|
80
|
+
return String(explicit)
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const uid = getCurrentUser()?.uid
|
|
84
|
+
return uid ? String(uid) : ''
|
|
85
|
+
} catch {
|
|
86
|
+
// No Nextcloud page around us (a test, an embed): nobody is signed in.
|
|
87
|
+
return ''
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Remove every draft stored under the anonymous user.
|
|
93
|
+
*
|
|
94
|
+
* Called once a signed-in user is known. Such a draft was written by a page
|
|
95
|
+
* that did not know who was typing, so it may be somebody else's, and it is
|
|
96
|
+
* deleted rather than moved: moving it would hand it to whoever opened the
|
|
97
|
+
* form next.
|
|
98
|
+
*
|
|
99
|
+
* @return {number} How many drafts were removed.
|
|
100
|
+
* @spec openspec/changes/form-draft-on-change-and-help-text-spacing/specs/form-draft-on-change-and-help-text-spacing/spec.md#requirement-a-draft-belongs-to-the-signed-in-user
|
|
101
|
+
*/
|
|
102
|
+
export function clearAnonymousDrafts() {
|
|
103
|
+
let removed = 0
|
|
104
|
+
try {
|
|
105
|
+
const storage = window.localStorage
|
|
106
|
+
const suffix = ':' + DRAFT_ANONYMOUS_USER
|
|
107
|
+
const doomed = []
|
|
108
|
+
for (let i = 0; i < storage.length; i++) {
|
|
109
|
+
const key = storage.key(i)
|
|
110
|
+
if (key && key.startsWith(DRAFT_KEY_PREFIX + ':') && key.endsWith(suffix)) {
|
|
111
|
+
doomed.push(key)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
for (const key of doomed) {
|
|
115
|
+
storage.removeItem(key)
|
|
116
|
+
removed++
|
|
117
|
+
}
|
|
118
|
+
} catch {
|
|
119
|
+
// Blocked storage holds no drafts to leak.
|
|
120
|
+
}
|
|
121
|
+
return removed
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Whether a value counts as empty for a draft: null, undefined, '' and [].
|
|
126
|
+
*
|
|
127
|
+
* @param {unknown} value The value.
|
|
128
|
+
* @return {boolean} True when empty.
|
|
129
|
+
*/
|
|
130
|
+
function isEmptyDraftValue(value) {
|
|
131
|
+
return value === null || value === undefined || value === '' || (Array.isArray(value) && value.length === 0)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Whether two field values are the same for the purpose of a draft.
|
|
136
|
+
*
|
|
137
|
+
* Empty values are equal to each other: an input reports a missing value back
|
|
138
|
+
* as '', and that is the control normalising, not a person typing.
|
|
139
|
+
*
|
|
140
|
+
* @param {unknown} a One value.
|
|
141
|
+
* @param {unknown} b The other.
|
|
142
|
+
* @return {boolean} True when they are the same.
|
|
143
|
+
*/
|
|
144
|
+
export function sameDraftValue(a, b) {
|
|
145
|
+
if (isEmptyDraftValue(a) && isEmptyDraftValue(b)) {
|
|
146
|
+
return true
|
|
147
|
+
}
|
|
148
|
+
if (a === b) {
|
|
149
|
+
return true
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
return JSON.stringify(a) === JSON.stringify(b)
|
|
153
|
+
} catch {
|
|
154
|
+
return false
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Whether a person changed the form: one of the fields they edited holds a
|
|
160
|
+
* value different from the one the form opened with.
|
|
161
|
+
*
|
|
162
|
+
* 🔴 ONLY EDITED FIELDS COUNT. A form fills in values by itself after it
|
|
163
|
+
* opens (defaults, normalised dates, the active organisation, options that
|
|
164
|
+
* arrive later). Counting those wrote a draft and said "Saved just now" on a
|
|
165
|
+
* dialog nobody had touched.
|
|
166
|
+
*
|
|
167
|
+
* @param {object} values The current values.
|
|
168
|
+
* @param {object} baseline The values the form opened with.
|
|
169
|
+
* @param {string[]} editedKeys The fields a person edited.
|
|
170
|
+
* @return {boolean} True when there is something worth keeping.
|
|
171
|
+
* @spec openspec/changes/form-draft-on-change-and-help-text-spacing/specs/form-draft-on-change-and-help-text-spacing/spec.md#requirement-a-draft-is-written-only-after-a-person-changes-a-field
|
|
172
|
+
*/
|
|
173
|
+
export function hasDraftChanges(values, baseline, editedKeys) {
|
|
174
|
+
const now = values || {}
|
|
175
|
+
const base = baseline || {}
|
|
176
|
+
return (editedKeys || []).some((key) => !sameDraftValue(now[key], base[key]))
|
|
177
|
+
}
|
|
178
|
+
|
|
61
179
|
/**
|
|
62
180
|
* Read one draft back, or null when there is nothing usable.
|
|
63
181
|
*
|
|
@@ -218,13 +336,6 @@ export function formDraftMixin() {
|
|
|
218
336
|
draftSavedAt: 0,
|
|
219
337
|
/** Non-reactive handle for the debounce. */
|
|
220
338
|
draftTimeout: null,
|
|
221
|
-
/**
|
|
222
|
-
* Whether the form's own initial population has happened.
|
|
223
|
-
*
|
|
224
|
-
* The first change to the values is the component building
|
|
225
|
-
* them, not a person typing. See the watcher that reads this.
|
|
226
|
-
*/
|
|
227
|
-
draftSeeded: false,
|
|
228
339
|
}
|
|
229
340
|
},
|
|
230
341
|
|
|
@@ -265,6 +376,26 @@ export function formDraftMixin() {
|
|
|
265
376
|
}, DRAFT_DEBOUNCE_MS)
|
|
266
377
|
},
|
|
267
378
|
|
|
379
|
+
/**
|
|
380
|
+
* The form is back to what it opened with: cancel a pending write,
|
|
381
|
+
* remove a draft written earlier and stop announcing anything.
|
|
382
|
+
*
|
|
383
|
+
* @param {string} key The storage key.
|
|
384
|
+
* @return {void}
|
|
385
|
+
* @spec openspec/changes/form-draft-on-change-and-help-text-spacing/specs/form-draft-on-change-and-help-text-spacing/spec.md#requirement-a-draft-is-written-only-after-a-person-changes-a-field
|
|
386
|
+
*/
|
|
387
|
+
settleUnchangedDraft(key) {
|
|
388
|
+
if (this.draftTimeout) {
|
|
389
|
+
clearTimeout(this.draftTimeout)
|
|
390
|
+
this.draftTimeout = null
|
|
391
|
+
}
|
|
392
|
+
if (this.draftState !== 'idle') {
|
|
393
|
+
clearDraft(key)
|
|
394
|
+
this.draftState = 'idle'
|
|
395
|
+
this.draftSavedAt = 0
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
|
|
268
399
|
/**
|
|
269
400
|
* Drop the draft and stop announcing anything about it.
|
|
270
401
|
*
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { computed, isRef, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
2
2
|
import { useObjectStore } from '../store/index.js'
|
|
3
|
+
import { facetFilterParams } from '../utils/facets.js'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Composable for managing list view state with full objectStore integration.
|
|
@@ -163,10 +164,9 @@ export function useListView(objectTypeOrOptions, options) {
|
|
|
163
164
|
}
|
|
164
165
|
|
|
165
166
|
for (const [key, values] of Object.entries(activeFilters.value)) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
167
|
+
// Single-value arrays are unwrapped to scalar params; the
|
|
168
|
+
// missing-value option becomes `<key>_isnull=true`.
|
|
169
|
+
Object.assign(params, facetFilterParams(key, values))
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
// Fixed filters (e.g. a route-param-scoped `pages[].config.filter`) are
|
package/src/css/form-field.css
CHANGED
|
@@ -82,6 +82,20 @@
|
|
|
82
82
|
min-height: var(--cn-field-height);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
/* NcTextField draws its input inside `.input-field__main-wrapper`, which has a
|
|
86
|
+
FIXED height (`--default-clickable-area`, 34px on Nextcloud 34) and a 2px
|
|
87
|
+
padding ring for the focus outline. The min-height above makes the input
|
|
88
|
+
40px, so without this the input overflowed its wrapper by 6px and the help
|
|
89
|
+
line under it, which starts at the wrapper's bottom edge, sat behind the
|
|
90
|
+
input's lower border. NcSelect grows with its content, which is why only
|
|
91
|
+
plain inputs showed it. The wrapper now takes the field height plus its
|
|
92
|
+
padding ring, so the input fits and the help line starts below it.
|
|
93
|
+
@spec openspec/changes/form-draft-on-change-and-help-text-spacing/specs/form-draft-on-change-and-help-text-spacing/spec.md#requirement-help-text-starts-below-every-input */
|
|
94
|
+
.cn-look-board .cn-form-dialog__field .input-field__main-wrapper,
|
|
95
|
+
.cn-look-board .cn-form-page__field .input-field__main-wrapper {
|
|
96
|
+
height: calc(var(--cn-field-height) + 2 * var(--border-width-input-focused, 2px));
|
|
97
|
+
}
|
|
98
|
+
|
|
85
99
|
.cn-look-board .cn-form-dialog__field textarea,
|
|
86
100
|
.cn-look-board .cn-form-page__field textarea {
|
|
87
101
|
padding: 10px 12px;
|
package/src/css/index-page.css
CHANGED
|
@@ -240,3 +240,74 @@
|
|
|
240
240
|
color: var(--color-text-maxcontrast);
|
|
241
241
|
font-size: 0.9em;
|
|
242
242
|
}
|
|
243
|
+
|
|
244
|
+
/* An index page with cards beside its list (`sidePanel`,
|
|
245
|
+
screens-index-stat-row): the header rows span the page, the toolbar and the
|
|
246
|
+
list take the first column and the side panel the second (300px, 20px
|
|
247
|
+
apart), spanning both. Every other child (dialogs, the inline sidebar) sits
|
|
248
|
+
in a zero-height area after them. The list row is the flexible one, so a
|
|
249
|
+
side panel taller than the toolbar never opens a gap under the toolbar.
|
|
250
|
+
Below 1024px the panel moves above the toolbar. */
|
|
251
|
+
.cn-index-page--with-side-panel {
|
|
252
|
+
display: grid;
|
|
253
|
+
grid-template-columns: minmax(0, 1fr) var(--cn-index-side-panel-width, 300px);
|
|
254
|
+
grid-template-rows: auto auto auto auto minmax(0, 1fr) auto;
|
|
255
|
+
grid-template-areas:
|
|
256
|
+
"head head"
|
|
257
|
+
"below below"
|
|
258
|
+
"stats stats"
|
|
259
|
+
"bar side"
|
|
260
|
+
"body side"
|
|
261
|
+
"extra extra";
|
|
262
|
+
column-gap: 20px;
|
|
263
|
+
align-content: start;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.cn-index-page--with-side-panel > * {
|
|
267
|
+
grid-area: extra;
|
|
268
|
+
min-width: 0;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.cn-index-page--with-side-panel > :first-child {
|
|
272
|
+
grid-area: head;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.cn-index-page--with-side-panel > .cn-index-page__below-header {
|
|
276
|
+
grid-area: below;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.cn-index-page--with-side-panel > .cn-index-page__stat-row {
|
|
280
|
+
grid-area: stats;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.cn-index-page--with-side-panel > .cn-actions-bar {
|
|
284
|
+
grid-area: bar;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.cn-index-page--with-side-panel > .cn-index-page__body {
|
|
288
|
+
grid-area: body;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.cn-index-page--with-side-panel > .cn-index-page__side-panel {
|
|
292
|
+
grid-area: side;
|
|
293
|
+
align-self: start;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
@media (max-width: 1024px) {
|
|
297
|
+
.cn-index-page--with-side-panel {
|
|
298
|
+
grid-template-columns: minmax(0, 1fr);
|
|
299
|
+
grid-template-areas:
|
|
300
|
+
"head"
|
|
301
|
+
"below"
|
|
302
|
+
"stats"
|
|
303
|
+
"side"
|
|
304
|
+
"bar"
|
|
305
|
+
"body"
|
|
306
|
+
"extra";
|
|
307
|
+
grid-template-rows: auto auto auto auto auto minmax(0, 1fr) auto;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.cn-index-page--with-side-panel > .cn-index-page__side-panel {
|
|
311
|
+
margin-bottom: 20px;
|
|
312
|
+
}
|
|
313
|
+
}
|
package/src/css/kpi-card.css
CHANGED
|
@@ -450,6 +450,38 @@ a.cn-kpi-card--stacked:focus-visible {
|
|
|
450
450
|
font-weight: 400;
|
|
451
451
|
}
|
|
452
452
|
|
|
453
|
+
/* A caption on a line of its own wraps, up to two lines (DqDashboard: "haalden
|
|
454
|
+
hun termijn, naar doorlooptijd" runs over two lines in a narrow tile). The
|
|
455
|
+
one-line rule of `.cn-kpi-card__label` is for a caption BESIDE the number,
|
|
456
|
+
where a second line would push the tile taller; this line has the width of
|
|
457
|
+
the tile to itself. The clamp is safe here because the element is a plain
|
|
458
|
+
span, not a flex row (compare the title note above).
|
|
459
|
+
@spec openspec/changes/dashboard-tile-text-fits/specs/dashboard-tile-text-fits/spec.md#requirement-a-kpi-tiles-caption-and-board-label-wrap-to-two-lines */
|
|
460
|
+
.cn-kpi-card--stacked .cn-kpi-card__caption-line {
|
|
461
|
+
display: -webkit-box;
|
|
462
|
+
-webkit-box-orient: vertical;
|
|
463
|
+
-webkit-line-clamp: 2;
|
|
464
|
+
line-clamp: 2;
|
|
465
|
+
white-space: normal;
|
|
466
|
+
overflow-wrap: break-word;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/* Board look: the label wraps too, up to two lines, beside its icon badge
|
|
470
|
+
("Afgehandeld deze maand"). The clamp sits on the label's own span
|
|
471
|
+
(`cn-kpi-card__title-text`), not on the title row, which stays the flex row
|
|
472
|
+
that carries the badge or the range select. */
|
|
473
|
+
.cn-kpi-card--board .cn-kpi-card__title-text {
|
|
474
|
+
flex: 1 1 auto;
|
|
475
|
+
min-width: 0;
|
|
476
|
+
display: -webkit-box;
|
|
477
|
+
-webkit-box-orient: vertical;
|
|
478
|
+
-webkit-line-clamp: 2;
|
|
479
|
+
line-clamp: 2;
|
|
480
|
+
overflow: hidden;
|
|
481
|
+
white-space: normal;
|
|
482
|
+
overflow-wrap: break-word;
|
|
483
|
+
}
|
|
484
|
+
|
|
453
485
|
/* The 18px glyph before the label, drawn only on a link tile. */
|
|
454
486
|
.cn-kpi-card--board .cn-kpi-card__title {
|
|
455
487
|
display: flex;
|
|
@@ -87,6 +87,61 @@
|
|
|
87
87
|
margin-bottom: 0;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
/* The breadcrumb is a line of 14px text between the pills and the meta, as
|
|
91
|
+
the boards draw it (screens-detail-header-row-parity). NcBreadcrumbs grows to
|
|
92
|
+
the full row and draws each crumb as a 34px tertiary button, which pushed the
|
|
93
|
+
pills above it and the meta under it. The doubled class outranks its scoped
|
|
94
|
+
rules. */
|
|
95
|
+
.cn-look-board .cn-detail-page__header-row2 .cn-detail-page__breadcrumbs.cn-detail-page__breadcrumbs {
|
|
96
|
+
flex: 0 1 auto;
|
|
97
|
+
height: auto;
|
|
98
|
+
min-height: 0;
|
|
99
|
+
min-width: 0;
|
|
100
|
+
width: auto;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.cn-look-board .cn-detail-page__header-row2 .cn-detail-page__breadcrumbs .breadcrumb__crumbs {
|
|
104
|
+
gap: 8px;
|
|
105
|
+
margin: 0;
|
|
106
|
+
min-height: 0;
|
|
107
|
+
padding: 0;
|
|
108
|
+
vertical-align: middle;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.cn-look-board .cn-detail-page__header-row2 .cn-detail-page__breadcrumbs .vue-crumb.vue-crumb {
|
|
112
|
+
gap: 8px;
|
|
113
|
+
height: auto;
|
|
114
|
+
min-height: 0;
|
|
115
|
+
min-width: 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.cn-look-board .cn-detail-page__header-row2 .cn-detail-page__breadcrumbs .vue-crumb .button-vue.button-vue {
|
|
119
|
+
background: transparent;
|
|
120
|
+
border: 0;
|
|
121
|
+
font-size: 14px;
|
|
122
|
+
font-weight: 400;
|
|
123
|
+
height: auto;
|
|
124
|
+
min-height: 0;
|
|
125
|
+
min-width: 0;
|
|
126
|
+
padding: 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.cn-look-board .cn-detail-page__header-row2 .cn-detail-page__breadcrumbs .vue-crumb .button-vue__text {
|
|
130
|
+
font-weight: inherit;
|
|
131
|
+
line-height: 20px;
|
|
132
|
+
padding: 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* The list is the link; the record's own crumb is plain muted text. */
|
|
136
|
+
.cn-look-board .cn-detail-page__header-row2 .cn-detail-page__breadcrumbs .vue-crumb .button-vue[aria-current='page'] {
|
|
137
|
+
color: var(--color-text-maxcontrast);
|
|
138
|
+
cursor: default;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.cn-look-board .cn-detail-page__header-row2 .cn-detail-page__breadcrumbs .vue-crumb__separator {
|
|
142
|
+
margin: 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
90
145
|
.cn-look-board .cn-detail-page__header-dot,
|
|
91
146
|
.cn-look-board .cn-detail-page__header-meta {
|
|
92
147
|
color: var(--color-text-maxcontrast);
|
|
@@ -147,6 +202,15 @@
|
|
|
147
202
|
gap: 4px;
|
|
148
203
|
}
|
|
149
204
|
|
|
205
|
+
/* No inner scroller: tabs that do not fit the width wrap onto a second row
|
|
206
|
+
instead of scrolling sideways (the library's default strip), so the strip
|
|
207
|
+
has no scrollbar, no clipped tab and no fade or chevron to find the rest. */
|
|
208
|
+
.cn-look-board .cn-tabs--board .cn-tabs__nav {
|
|
209
|
+
flex-wrap: wrap;
|
|
210
|
+
overflow: visible;
|
|
211
|
+
row-gap: 4px;
|
|
212
|
+
}
|
|
213
|
+
|
|
150
214
|
.cn-look-board .cn-tabs--board .cn-tabs__nav-item {
|
|
151
215
|
background-color: var(--color-background-dark);
|
|
152
216
|
border: 1px solid var(--color-border-dark);
|
|
@@ -229,6 +293,22 @@
|
|
|
229
293
|
border-radius: 0;
|
|
230
294
|
}
|
|
231
295
|
|
|
296
|
+
/* A tab that holds a stack (`widgetIds`, screens-relation-pages): the panel
|
|
297
|
+
draws no frame and no padding; each widget is its own card. The first card
|
|
298
|
+
joins the open tab (the first-card rule above), the next ones stand 20px
|
|
299
|
+
apart, as the Overzicht of DqContact and PqOrganisatie draws them. */
|
|
300
|
+
.cn-look-board .cn-tabs--board.cn-tabs-widget__tabs .cn-tabs__content:has(> .cn-tab:not([hidden]) > .cn-tabs-widget__stack) {
|
|
301
|
+
background: transparent;
|
|
302
|
+
border: 0;
|
|
303
|
+
border-radius: 0;
|
|
304
|
+
padding: 0;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/* The stack's next cards are whole cards, not joined to the strip. */
|
|
308
|
+
.cn-look-board .cn-tabs--board .cn-tabs__content .cn-tab .cn-tabs-widget__stack-item .cn-widget-wrapper {
|
|
309
|
+
border-radius: var(--cn-board-card-radius);
|
|
310
|
+
}
|
|
311
|
+
|
|
232
312
|
/* ---- Body cards and side cards ----------------------------------------- */
|
|
233
313
|
|
|
234
314
|
.cn-look-board .cn-detail-page .cn-widget-wrapper,
|
|
@@ -276,12 +356,28 @@
|
|
|
276
356
|
padding: 0 0 10px;
|
|
277
357
|
}
|
|
278
358
|
|
|
279
|
-
|
|
280
|
-
|
|
359
|
+
/* Outranks the component's own `.cn-object-data-widget__label[data-v-...]`
|
|
360
|
+
(weight 500, 0.85em, which has the same specificity as the look's rule and
|
|
361
|
+
wins on source order wherever a bundle, such as a companion app's, loads
|
|
362
|
+
after this stylesheet), through the grid the labels sit in. Measured live:
|
|
363
|
+
the labels read bold and dark where the boards (DqContact, PqKlant, ShKlant)
|
|
364
|
+
draw them 13px, regular weight and light grey.
|
|
365
|
+
|
|
366
|
+
The colour carries `!important`: a theme (nldesign's element overrides) sets
|
|
367
|
+
the ink of every `div` outside the header with a selector that has an id in
|
|
368
|
+
its `:not()`, which no class rule outranks. */
|
|
369
|
+
.cn-look-board .cn-object-data-widget__grid .cn-object-data-widget__label {
|
|
370
|
+
color: var(--color-text-maxcontrast) !important;
|
|
281
371
|
font-size: 13px;
|
|
282
372
|
font-weight: 400;
|
|
283
373
|
}
|
|
284
374
|
|
|
375
|
+
/* The facts card's labels: the same light grey, regular weight. */
|
|
376
|
+
.cn-look-board .cn-facts-widget .cn-facts-widget__label {
|
|
377
|
+
color: var(--color-text-maxcontrast);
|
|
378
|
+
font-weight: 400;
|
|
379
|
+
}
|
|
380
|
+
|
|
285
381
|
.cn-look-board .cn-object-data-widget__value {
|
|
286
382
|
font-weight: 500;
|
|
287
383
|
}
|
|
@@ -308,6 +404,12 @@
|
|
|
308
404
|
display: none;
|
|
309
405
|
}
|
|
310
406
|
|
|
407
|
+
/* A side card whose widget reports a header action (screens-relation-pages:
|
|
408
|
+
the "+ Toevoegen" of Contactkanalen and Relaties) keeps that one button. */
|
|
409
|
+
.cn-look-board .cn-detail-page__side .cn-widget-wrapper__actions:has(.cn-detail-page__catalog-action) {
|
|
410
|
+
display: flex;
|
|
411
|
+
}
|
|
412
|
+
|
|
311
413
|
/* The notice at the top of the side column: radius 12, padding 14px 16px. */
|
|
312
414
|
.cn-look-board .cn-detail-page__side-item--notice .cn-widget-wrapper,
|
|
313
415
|
.cn-look-board .cn-detail-page__side-item--notice .cn-banner-widget,
|
|
@@ -533,3 +635,12 @@
|
|
|
533
635
|
font-size: 13px;
|
|
534
636
|
margin: 2px 0 0;
|
|
535
637
|
}
|
|
638
|
+
|
|
639
|
+
/* The sidebar's own open toggle (NcAppSidebar's `.app-sidebar__toggle`, drawn
|
|
640
|
+
when the sidebar is closed) is positioned over the content's top-right
|
|
641
|
+
corner, which in this look is the header's last button: a stray square icon
|
|
642
|
+
on "More". The board draws none, so it is hidden on a detail page and the
|
|
643
|
+
header menu offers "Open sidebar" instead. */
|
|
644
|
+
.cn-look-board:has(.cn-detail-page) > .app-sidebar__toggle {
|
|
645
|
+
display: none;
|
|
646
|
+
}
|