@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
|
@@ -151,6 +151,8 @@
|
|
|
151
151
|
:sortKey="localSort.field || null"
|
|
152
152
|
:sortOrder="localSort.dir || 'asc'"
|
|
153
153
|
borderless
|
|
154
|
+
:fitWidth="fitWidthActive"
|
|
155
|
+
:fixedLayout="fixedLayoutActive"
|
|
154
156
|
:hideHeader="content.hideHeader === true"
|
|
155
157
|
@rowClick="onRowClick"
|
|
156
158
|
@rowAuxClick="onRowAuxClick"
|
|
@@ -173,6 +175,8 @@
|
|
|
173
175
|
:sortKey="localSort.field || null"
|
|
174
176
|
:sortOrder="localSort.dir || 'asc'"
|
|
175
177
|
borderless
|
|
178
|
+
:fitWidth="fitWidthActive"
|
|
179
|
+
:fixedLayout="fixedLayoutActive"
|
|
176
180
|
:hideHeader="content.hideHeader === true"
|
|
177
181
|
@rowClick="onRowClick"
|
|
178
182
|
@rowAuxClick="onRowAuxClick"
|
|
@@ -448,6 +452,15 @@ export default {
|
|
|
448
452
|
page: 1,
|
|
449
453
|
/** Rows that fit the host cell; null = unconstrained (dashboards). */
|
|
450
454
|
fitRows: null,
|
|
455
|
+
/**
|
|
456
|
+
* How far the table has been squeezed to the widget's width, so the
|
|
457
|
+
* card never scrolls sideways: 0 = its own auto layout, 1 = one column
|
|
458
|
+
* takes what is left and is cut with an ellipsis while the rest keep
|
|
459
|
+
* their content on one line, 2 = a fixed layout, every column an equal
|
|
460
|
+
* share with its text wrapped. Each step is taken only while the table
|
|
461
|
+
* still scrolls sideways. `content.fitWidth` forces stage 1 on or off.
|
|
462
|
+
*/
|
|
463
|
+
fitStage: 0,
|
|
451
464
|
/** Whether the create dialog is open. */
|
|
452
465
|
showCreate: false,
|
|
453
466
|
/**
|
|
@@ -480,6 +493,27 @@ export default {
|
|
|
480
493
|
},
|
|
481
494
|
|
|
482
495
|
computed: {
|
|
496
|
+
/**
|
|
497
|
+
* Whether the table fits the widget's width (stage 1): `content.fitWidth`
|
|
498
|
+
* when it says, else once the columns were measured not to fit.
|
|
499
|
+
*
|
|
500
|
+
* @return {boolean}
|
|
501
|
+
*/
|
|
502
|
+
fitWidthActive() {
|
|
503
|
+
const forced = this.content?.fitWidth
|
|
504
|
+
return typeof forced === 'boolean' ? forced : this.fitStage === 1
|
|
505
|
+
},
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Whether the table takes a fixed layout, the last resort when even the
|
|
509
|
+
* fitted table is wider than the widget (not with `content.fitWidth` set).
|
|
510
|
+
*
|
|
511
|
+
* @return {boolean}
|
|
512
|
+
*/
|
|
513
|
+
fixedLayoutActive() {
|
|
514
|
+
return typeof this.content?.fitWidth !== 'boolean' && this.fitStage >= 2
|
|
515
|
+
},
|
|
516
|
+
|
|
483
517
|
/**
|
|
484
518
|
* The unwrapped detail-page object context for token resolution, or null
|
|
485
519
|
* on surfaces (dashboards) that don't provide one.
|
|
@@ -619,7 +653,7 @@ export default {
|
|
|
619
653
|
// `secondary` (a second, muted line under the cell) rides
|
|
620
654
|
// along too: the table draws it, and dropping it here took the
|
|
621
655
|
// list rows' second line away (zuiddrecht-pixel-gaps-3).
|
|
622
|
-
for (const k of ['format', 'widget', 'widgetProps', 'formatter', 'align', 'width', 'type', 'enum', 'enumLabels', 'sortable', 'secondary']) {
|
|
656
|
+
for (const k of ['format', 'widget', 'widgetProps', 'formatter', 'align', 'width', 'type', 'enum', 'enumLabels', 'sortable', 'secondary', 'colorMap', 'grow']) {
|
|
623
657
|
if (c[k] !== undefined) {
|
|
624
658
|
out[k] = c[k]
|
|
625
659
|
}
|
|
@@ -1165,6 +1199,12 @@ export default {
|
|
|
1165
1199
|
mounted() {
|
|
1166
1200
|
this.fetchRows()
|
|
1167
1201
|
this.loadHeadingsIfNeeded()
|
|
1202
|
+
// A table wider than the widget fits its columns to the width instead of
|
|
1203
|
+
// scrolling sideways (no inner scrollbars).
|
|
1204
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
1205
|
+
this._widthObserver = new ResizeObserver(() => this.measureWidthFit())
|
|
1206
|
+
this._widthObserver.observe(this.$el)
|
|
1207
|
+
}
|
|
1168
1208
|
// Re-read on a page-level refresh. This list fetches its own rows from
|
|
1169
1209
|
// OpenRegister and subscribed to nothing, so after a write elsewhere on
|
|
1170
1210
|
// the page it went on rendering the result set it fetched on mount —
|
|
@@ -1203,6 +1243,9 @@ export default {
|
|
|
1203
1243
|
if (this._fitObserver) {
|
|
1204
1244
|
this._fitObserver.disconnect()
|
|
1205
1245
|
}
|
|
1246
|
+
if (this._widthObserver) {
|
|
1247
|
+
this._widthObserver.disconnect()
|
|
1248
|
+
}
|
|
1206
1249
|
},
|
|
1207
1250
|
|
|
1208
1251
|
methods: {
|
|
@@ -1277,7 +1320,10 @@ export default {
|
|
|
1277
1320
|
const res = await axios.get(url, { params })
|
|
1278
1321
|
this.rows = (res && res.data && res.data.results) || []
|
|
1279
1322
|
this.total = (res && res.data && typeof res.data.total === 'number') ? res.data.total : this.rows.length
|
|
1280
|
-
this.$nextTick(() =>
|
|
1323
|
+
this.$nextTick(() => {
|
|
1324
|
+
this.measureFit()
|
|
1325
|
+
this.measureWidthFit()
|
|
1326
|
+
})
|
|
1281
1327
|
} catch (e) {
|
|
1282
1328
|
// Keep the raw message OUT of the template — log it for
|
|
1283
1329
|
// debugging, surface only the quiet `loadErrorLabel` line.
|
|
@@ -1291,6 +1337,27 @@ export default {
|
|
|
1291
1337
|
}
|
|
1292
1338
|
},
|
|
1293
1339
|
|
|
1340
|
+
/**
|
|
1341
|
+
* Squeeze the table to the widget's width while it scrolls sideways: its
|
|
1342
|
+
* `.cn-data-table__scroll` wrapper is wider than it is visible. First the
|
|
1343
|
+
* fit (stage 1), then, if that is still too wide, a fixed layout
|
|
1344
|
+
* (stage 2). It never goes back (a squeezed table does not overflow, so
|
|
1345
|
+
* there is nothing to measure to relax it). No-op when `content.fitWidth`
|
|
1346
|
+
* is set.
|
|
1347
|
+
*
|
|
1348
|
+
* @return {void}
|
|
1349
|
+
*/
|
|
1350
|
+
measureWidthFit() {
|
|
1351
|
+
if (this.fitStage >= 2 || typeof this.content?.fitWidth === 'boolean') {
|
|
1352
|
+
return
|
|
1353
|
+
}
|
|
1354
|
+
const scroller = this.$el && this.$el.querySelector ? this.$el.querySelector('.cn-data-table__scroll') : null
|
|
1355
|
+
if (scroller && scroller.scrollWidth > scroller.clientWidth + 1) {
|
|
1356
|
+
this.fitStage += 1
|
|
1357
|
+
this.$nextTick(() => this.measureWidthFit())
|
|
1358
|
+
}
|
|
1359
|
+
},
|
|
1360
|
+
|
|
1294
1361
|
/**
|
|
1295
1362
|
* Fit the visible row count to the host grid cell (ADR-062 — the cell
|
|
1296
1363
|
* is the budget). Measures the cell's remaining height below the table
|
|
@@ -16,6 +16,13 @@
|
|
|
16
16
|
:rowActions="rowActions"
|
|
17
17
|
:newActions="newActions"
|
|
18
18
|
:linkedItems="linkedItems"
|
|
19
|
+
:columns="columns"
|
|
20
|
+
:rowData="rowDataSource"
|
|
21
|
+
:preferenceApp="preferenceApp"
|
|
22
|
+
:preferenceKey="preferenceKey"
|
|
23
|
+
:bulkActions="bulkActions"
|
|
24
|
+
:groupBy="groupBy"
|
|
25
|
+
:facets="facets"
|
|
19
26
|
@changed="onBrowserChanged" />
|
|
20
27
|
<template v-else>
|
|
21
28
|
<!-- Upload error -->
|
|
@@ -240,7 +247,7 @@ import CnFilePreview from '../CnFilePreview/CnFilePreview.vue'
|
|
|
240
247
|
import CnFilesBrowser from '../CnFilesBrowser/CnFilesBrowser.vue'
|
|
241
248
|
import { useFileOpener } from '../../composables/useFileOpener.js'
|
|
242
249
|
import { buildHeaders, prefixUrl } from '../../utils/index.js'
|
|
243
|
-
import { objectDisplayName, resolveObjectFolderInfo } from '../CnFilesBrowser/filesBrowser.js'
|
|
250
|
+
import { indexRowData, objectDisplayName, resolveObjectFolderInfo } from '../CnFilesBrowser/filesBrowser.js'
|
|
244
251
|
import { createOpenRegisterSource } from '../CnFilesBrowser/openRegisterSource.js'
|
|
245
252
|
|
|
246
253
|
/**
|
|
@@ -359,6 +366,47 @@ export default {
|
|
|
359
366
|
* Null fetches nothing.
|
|
360
367
|
*/
|
|
361
368
|
linkedItemsUrl: { type: String, default: null },
|
|
369
|
+
/**
|
|
370
|
+
* Forwarded to CnFilesBrowser: the columns the browser shows, built-in
|
|
371
|
+
* names or declared columns (`{ key, label, source, formatter }`).
|
|
372
|
+
* A `source: 'row'` column reads the host's record for the file from
|
|
373
|
+
* `rowDataUrl`. None keeps name, size and modified.
|
|
374
|
+
*
|
|
375
|
+
* @type {Array<string|object>}
|
|
376
|
+
*/
|
|
377
|
+
columns: { type: Array, default: () => [] },
|
|
378
|
+
/** Forwarded to CnFilesBrowser: the app id the user's column choice is stored under; unset offers no Columns chooser. */
|
|
379
|
+
preferenceApp: { type: String, default: '' },
|
|
380
|
+
/** Forwarded to CnFilesBrowser: the key the column choice is stored under. */
|
|
381
|
+
preferenceKey: { type: String, default: 'files-browser-columns' },
|
|
382
|
+
/**
|
|
383
|
+
* An app endpoint that answers the host's own record per file, for the
|
|
384
|
+
* browser's `source: 'row'` columns. App-relative; `{objectId}` is
|
|
385
|
+
* replaced. Read once per listing. The answer is a list of records
|
|
386
|
+
* (or the list at `rowDataPath`, or under `items` or `results`), each
|
|
387
|
+
* naming its file in `rowDataKey`. Null reads nothing.
|
|
388
|
+
*/
|
|
389
|
+
rowDataUrl: { type: String, default: null },
|
|
390
|
+
/**
|
|
391
|
+
* Forwarded to CnFilesBrowser: the host's actions on a selection of
|
|
392
|
+
* files. With at least one, files get checkboxes and a bulk bar.
|
|
393
|
+
*
|
|
394
|
+
* @type {Array<{id: string, label: string, icon?: string, type?: string, target?: string, props?: object}>}
|
|
395
|
+
*/
|
|
396
|
+
bulkActions: { type: Array, default: () => [] },
|
|
397
|
+
/** Forwarded to CnFilesBrowser: the key of a declared column to group the files on. */
|
|
398
|
+
groupBy: { type: String, default: '' },
|
|
399
|
+
/**
|
|
400
|
+
* Forwarded to CnFilesBrowser: keys of declared columns to filter on,
|
|
401
|
+
* a chip per value in use.
|
|
402
|
+
*
|
|
403
|
+
* @type {string[]}
|
|
404
|
+
*/
|
|
405
|
+
facets: { type: Array, default: () => [] },
|
|
406
|
+
/** A dotted path to the list of records in the `rowDataUrl` answer; empty reads the answer itself. */
|
|
407
|
+
rowDataPath: { type: String, default: '' },
|
|
408
|
+
/** The record field that holds the Nextcloud file id. */
|
|
409
|
+
rowDataKey: { type: String, default: 'fileId' },
|
|
362
410
|
/** Label of the Download action. */
|
|
363
411
|
downloadLabel: { type: String, default: () => t('nextcloud-vue', 'Download') },
|
|
364
412
|
/** Label of the action that opens the Files sidebar on the file. */
|
|
@@ -424,6 +472,27 @@ export default {
|
|
|
424
472
|
},
|
|
425
473
|
|
|
426
474
|
computed: {
|
|
475
|
+
/**
|
|
476
|
+
* The browser's `rowData`: a function that reads the host's records
|
|
477
|
+
* from `rowDataUrl` and keys them by file id, or null without a url.
|
|
478
|
+
* The browser calls it once per listing.
|
|
479
|
+
*
|
|
480
|
+
* @return {(function(): Promise<object>)|null} The row data source.
|
|
481
|
+
* @spec openspec/changes/files-browser-hosts-a-documents-list/specs/files-browser/spec.md
|
|
482
|
+
*/
|
|
483
|
+
rowDataSource() {
|
|
484
|
+
if (!this.rowDataUrl || !this.objectId) {
|
|
485
|
+
return null
|
|
486
|
+
}
|
|
487
|
+
const url = generateUrl(this.rowDataUrl.replace('{objectId}', encodeURIComponent(this.objectId)))
|
|
488
|
+
const path = this.rowDataPath
|
|
489
|
+
const key = this.rowDataKey
|
|
490
|
+
return async () => {
|
|
491
|
+
const { data } = await axios.get(url)
|
|
492
|
+
return indexRowData(data, { path, key })
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
|
|
427
496
|
/**
|
|
428
497
|
* The root crumb: the host's label, else the object's name (its folder
|
|
429
498
|
* on disk is called after its uuid), else the folder's own name.
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
{{ cancelLabel }}
|
|
19
19
|
</NcButton>
|
|
20
20
|
</p>
|
|
21
|
+
<!-- @slot composer-before An app's own control above the composer, e.g. a template picker. Scope: `{ setText, text }`; `setText(text)` fills the composer, `text` is what it holds now. -->
|
|
22
|
+
<slot name="composer-before" :setText="setComposerText" :text="newNoteText" />
|
|
21
23
|
<CnNoteComposer
|
|
22
24
|
class="cn-sidebar-tab__composer"
|
|
23
25
|
:modelValue="newNoteText"
|
|
@@ -481,6 +483,20 @@ export default {
|
|
|
481
483
|
}
|
|
482
484
|
},
|
|
483
485
|
|
|
486
|
+
/**
|
|
487
|
+
* Fill the composer from outside, for the `composer-before` slot.
|
|
488
|
+
*
|
|
489
|
+
* The app decides what goes in (a template body, a quoted line); the
|
|
490
|
+
* composer stays the one place the text lives, so sending, editing and
|
|
491
|
+
* the mention picker all see it exactly as if it had been typed.
|
|
492
|
+
*
|
|
493
|
+
* @param {string} text The text the composer should hold.
|
|
494
|
+
* @return {void}
|
|
495
|
+
*/
|
|
496
|
+
setComposerText(text) {
|
|
497
|
+
this.newNoteText = (text === null || text === undefined) ? '' : String(text)
|
|
498
|
+
},
|
|
499
|
+
|
|
484
500
|
startEdit(note) {
|
|
485
501
|
this.replyTo = null
|
|
486
502
|
this.editingNoteId = note.id
|
|
@@ -305,6 +305,7 @@ import { pageHasSplitView, pageIdForRoute, splitIdForRoute, splitRouteName } fro
|
|
|
305
305
|
import { reportDiagnostic, reportDiagnosticOnce } from '../../utils/diagnostics.js'
|
|
306
306
|
import { openRowTarget } from '../../utils/linkNavigation.js'
|
|
307
307
|
import { listContextFromRoute, listContextToQuery } from '../../utils/listNavigation.js'
|
|
308
|
+
import { applyQueryPreset, matchQueryPreset } from '../../utils/queryPresets.js'
|
|
308
309
|
import { resolveRouteSentinels } from '../../utils/resolveRouteSentinels.js'
|
|
309
310
|
import { parseSortKeys } from '../../utils/routeFilters.js'
|
|
310
311
|
import { buildRouteParams, routePathFor } from '../../utils/routeParams.js'
|
|
@@ -1050,7 +1051,25 @@ export default {
|
|
|
1050
1051
|
return 'none'
|
|
1051
1052
|
}
|
|
1052
1053
|
const cfg = (page.config && typeof page.config === 'object' && !Array.isArray(page.config)) ? page.config : {}
|
|
1053
|
-
|
|
1054
|
+
// A query preset swaps the lenses and columns, so it remounts the
|
|
1055
|
+
// page: the active lens index belongs to the lenses it indexes.
|
|
1056
|
+
const preset = this.activeQueryPresetIndex >= 0 ? `:preset-${this.activeQueryPresetIndex}` : ''
|
|
1057
|
+
return [page.id, cfg.register || '', cfg.schema || ''].join(':') + preset
|
|
1058
|
+
},
|
|
1059
|
+
|
|
1060
|
+
/**
|
|
1061
|
+
* The index of the current index page's query preset that the route
|
|
1062
|
+
* query matches, or -1.
|
|
1063
|
+
*
|
|
1064
|
+
* @return {number}
|
|
1065
|
+
* @spec openspec/changes/screens-index-query-presets/specs/index-query-presets/spec.md#requirement-a-query-preset-overlays-lenses-columns-and-copy
|
|
1066
|
+
*/
|
|
1067
|
+
activeQueryPresetIndex() {
|
|
1068
|
+
const page = this.currentPage
|
|
1069
|
+
if (!page || page.type !== 'index' || !page.config || !Array.isArray(page.config.queryPresets)) {
|
|
1070
|
+
return -1
|
|
1071
|
+
}
|
|
1072
|
+
return matchQueryPreset(page.config.queryPresets, this.$route?.query || {})
|
|
1054
1073
|
},
|
|
1055
1074
|
|
|
1056
1075
|
/**
|
|
@@ -1297,6 +1316,15 @@ export default {
|
|
|
1297
1316
|
// container before forwarding — CnIndexPage has no
|
|
1298
1317
|
// `actionToggles` prop.
|
|
1299
1318
|
const isIndex = page?.type === 'index'
|
|
1319
|
+
// A query preset (`config.queryPresets`): the menu entry's query
|
|
1320
|
+
// brings its own lenses, columns and copy to the same page.
|
|
1321
|
+
if (isIndex && Array.isArray(config.queryPresets)) {
|
|
1322
|
+
const preset = config.queryPresets[this.activeQueryPresetIndex] || null
|
|
1323
|
+
config = applyQueryPreset(config, preset)
|
|
1324
|
+
if (preset && typeof preset.title === 'string' && preset.title !== '') {
|
|
1325
|
+
topLevel.title = preset.title
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1300
1328
|
// When an index page has somewhere to open a row, make a row click
|
|
1301
1329
|
// go there: set `rowClickToView` so the row body emits `row-click`
|
|
1302
1330
|
// (→ onRowOpen navigates) even though the page is selectable.
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
- SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
3
|
+
- SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
<template>
|
|
7
|
+
<fieldset class="cn-radio-cards" data-testid="cn-radio-cards" :aria-busy="busy ? 'true' : 'false'">
|
|
8
|
+
<legend v-if="label" class="cn-radio-cards__legend">
|
|
9
|
+
{{ label }}
|
|
10
|
+
</legend>
|
|
11
|
+
<div class="cn-radio-cards__grid" :class="`cn-radio-cards__grid--${columns}`">
|
|
12
|
+
<label
|
|
13
|
+
v-for="option in options"
|
|
14
|
+
:key="String(option.value)"
|
|
15
|
+
class="cn-radio-cards__card"
|
|
16
|
+
:class="{ 'cn-radio-cards__card--selected': isSelected(option) }"
|
|
17
|
+
:data-testid="`cn-radio-cards-option-${option.value}`">
|
|
18
|
+
<input
|
|
19
|
+
class="cn-radio-cards__input"
|
|
20
|
+
type="radio"
|
|
21
|
+
:name="groupName"
|
|
22
|
+
:value="String(option.value)"
|
|
23
|
+
:checked="isSelected(option)"
|
|
24
|
+
:disabled="readOnly || busy"
|
|
25
|
+
@change="choose(option)">
|
|
26
|
+
<span class="cn-radio-cards__dot" aria-hidden="true" />
|
|
27
|
+
<span class="cn-radio-cards__text">
|
|
28
|
+
<span class="cn-radio-cards__title">{{ option.label }}</span>
|
|
29
|
+
<span v-if="option.description" class="cn-radio-cards__description">{{ option.description }}</span>
|
|
30
|
+
</span>
|
|
31
|
+
</label>
|
|
32
|
+
</div>
|
|
33
|
+
<NcNoteCard v-if="notice" type="error" data-testid="cn-radio-cards-notice">
|
|
34
|
+
{{ notice }}
|
|
35
|
+
</NcNoteCard>
|
|
36
|
+
</fieldset>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<script>
|
|
40
|
+
import { NcNoteCard } from '@nextcloud/vue'
|
|
41
|
+
import { objectUrlOf, patchObject } from '../../utils/objectWrite.js'
|
|
42
|
+
import { readPath } from '../../utils/readPath.js'
|
|
43
|
+
import { serverErrorMessage } from '../../utils/serverErrorMessage.js'
|
|
44
|
+
|
|
45
|
+
let uid = 0
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* CnRadioCardsWidget — the `radio-cards` widget: one choice out of a few cards,
|
|
49
|
+
* each with a title and a description, bound to an enum field of the CURRENT
|
|
50
|
+
* object. Choosing a card saves at once with ONE PATCH of that field; a refused
|
|
51
|
+
* PATCH puts the choice back and shows the server's words. Real radio inputs
|
|
52
|
+
* underneath, so the choice is perceivable without colour and works from the
|
|
53
|
+
* keyboard.
|
|
54
|
+
*
|
|
55
|
+
* @spec openspec/changes/abstract-radio-cards/specs/radio-cards/spec.md
|
|
56
|
+
*/
|
|
57
|
+
export default {
|
|
58
|
+
name: 'CnRadioCardsWidget',
|
|
59
|
+
|
|
60
|
+
components: { NcNoteCard },
|
|
61
|
+
|
|
62
|
+
inject: {
|
|
63
|
+
cnTranslate: { default: () => (key) => key },
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
props: {
|
|
67
|
+
/**
|
|
68
|
+
* The widget configuration.
|
|
69
|
+
*
|
|
70
|
+
* - `field` (required) — the top-level enum field.
|
|
71
|
+
* - `options` (required) — `[{ value, label, description? }]`.
|
|
72
|
+
* - `label` — a legend over the cards (visually shown).
|
|
73
|
+
* - `columns` — 1, 2 or 3 (default 2).
|
|
74
|
+
* - `readOnly`.
|
|
75
|
+
*
|
|
76
|
+
* @type {object}
|
|
77
|
+
*/
|
|
78
|
+
content: {
|
|
79
|
+
type: Object,
|
|
80
|
+
default: () => ({}),
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
/** The current detail-page object. */
|
|
84
|
+
objectData: {
|
|
85
|
+
type: Object,
|
|
86
|
+
default: null,
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
/** The current object id. */
|
|
90
|
+
objectId: {
|
|
91
|
+
type: [String, Number],
|
|
92
|
+
default: '',
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
/** OpenRegister register slug of the surface. */
|
|
96
|
+
register: {
|
|
97
|
+
type: [String, Object],
|
|
98
|
+
default: '',
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
/** OpenRegister schema slug of the surface. */
|
|
102
|
+
schema: {
|
|
103
|
+
type: [String, Object],
|
|
104
|
+
default: '',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
emits: ['saved'],
|
|
109
|
+
|
|
110
|
+
data() {
|
|
111
|
+
uid += 1
|
|
112
|
+
return {
|
|
113
|
+
groupName: `cn-radio-cards-${uid}`,
|
|
114
|
+
saved: '',
|
|
115
|
+
value: '',
|
|
116
|
+
busy: false,
|
|
117
|
+
notice: '',
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
computed: {
|
|
122
|
+
options() {
|
|
123
|
+
const list = Array.isArray(this.content.options) ? this.content.options : []
|
|
124
|
+
return list
|
|
125
|
+
.filter((option) => option !== null && option !== undefined)
|
|
126
|
+
.map((option) => (typeof option === 'object'
|
|
127
|
+
? { value: option.value, label: this.tr(String(option.label ?? option.value)), description: this.tr(option.description || '') }
|
|
128
|
+
: { value: option, label: this.tr(String(option)), description: '' }))
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
label() {
|
|
132
|
+
return this.tr(this.content.label || '')
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
columns() {
|
|
136
|
+
return [1, 3].includes(this.content.columns) ? this.content.columns : 2
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
readOnly() {
|
|
140
|
+
return this.content.readOnly === true
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
objectUrl() {
|
|
144
|
+
return objectUrlOf(this.register, this.schema, this.objectId || (this.objectData && this.objectData.id))
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
watch: {
|
|
149
|
+
objectData() {
|
|
150
|
+
this.adopt()
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
created() {
|
|
155
|
+
this.adopt()
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
methods: {
|
|
159
|
+
tr(text) {
|
|
160
|
+
if (typeof text !== 'string' || text === '') {
|
|
161
|
+
return ''
|
|
162
|
+
}
|
|
163
|
+
return typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
/** Read the choice off the object. */
|
|
167
|
+
adopt() {
|
|
168
|
+
const stored = readPath(this.objectData || {}, this.content.field)
|
|
169
|
+
this.saved = stored === undefined || stored === null ? '' : String(stored)
|
|
170
|
+
this.value = this.saved
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
isSelected(option) {
|
|
174
|
+
return this.value === String(option.value)
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Choose a card and save that one field.
|
|
179
|
+
*
|
|
180
|
+
* @param {object} option The chosen option.
|
|
181
|
+
* @return {Promise<void>}
|
|
182
|
+
* @spec openspec/changes/abstract-radio-cards/specs/radio-cards/spec.md#requirement-choosing-a-card-saves-that-one-field
|
|
183
|
+
*/
|
|
184
|
+
async choose(option) {
|
|
185
|
+
if (!this.objectUrl || !this.content.field) {
|
|
186
|
+
this.notice = this.tr('This choice cannot be saved here.')
|
|
187
|
+
return
|
|
188
|
+
}
|
|
189
|
+
this.notice = ''
|
|
190
|
+
this.busy = true
|
|
191
|
+
this.value = String(option.value)
|
|
192
|
+
try {
|
|
193
|
+
const data = await patchObject(this.objectUrl, { [this.content.field]: option.value })
|
|
194
|
+
const written = readPath(data, this.content.field)
|
|
195
|
+
this.saved = String(written !== undefined && written !== null ? written : option.value)
|
|
196
|
+
this.value = this.saved
|
|
197
|
+
/**
|
|
198
|
+
* @event saved The choice was written.
|
|
199
|
+
* @type {{field: string, value: unknown}}
|
|
200
|
+
*/
|
|
201
|
+
this.$emit('saved', { field: this.content.field, value: option.value })
|
|
202
|
+
} catch (e) {
|
|
203
|
+
this.value = this.saved
|
|
204
|
+
this.notice = serverErrorMessage(e)
|
|
205
|
+
} finally {
|
|
206
|
+
this.busy = false
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
}
|
|
211
|
+
</script>
|
|
212
|
+
|
|
213
|
+
<style scoped>
|
|
214
|
+
.cn-radio-cards {
|
|
215
|
+
display: flex;
|
|
216
|
+
flex-direction: column;
|
|
217
|
+
gap: 8px;
|
|
218
|
+
min-width: 0;
|
|
219
|
+
margin: 0;
|
|
220
|
+
padding: 0;
|
|
221
|
+
border: 0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.cn-radio-cards__legend {
|
|
225
|
+
padding: 0;
|
|
226
|
+
margin-bottom: 6px;
|
|
227
|
+
font-weight: 600;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.cn-radio-cards__grid {
|
|
231
|
+
display: grid;
|
|
232
|
+
gap: 10px;
|
|
233
|
+
grid-template-columns: minmax(0, 1fr);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.cn-radio-cards__grid--2 {
|
|
237
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.cn-radio-cards__grid--3 {
|
|
241
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.cn-radio-cards__card {
|
|
245
|
+
position: relative;
|
|
246
|
+
display: flex;
|
|
247
|
+
align-items: flex-start;
|
|
248
|
+
gap: 10px;
|
|
249
|
+
padding: 12px 14px;
|
|
250
|
+
border: 1px solid var(--color-border-maxcontrast);
|
|
251
|
+
border-radius: var(--cn-board-control-radius, 8px);
|
|
252
|
+
background: var(--color-main-background);
|
|
253
|
+
cursor: pointer;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.cn-radio-cards__card--selected {
|
|
257
|
+
border-color: var(--color-primary-element);
|
|
258
|
+
background: var(--color-primary-element-light);
|
|
259
|
+
box-shadow: 0 0 0 1px var(--color-primary-element);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.cn-radio-cards__card:focus-within {
|
|
263
|
+
outline: 2px solid var(--color-primary-element);
|
|
264
|
+
outline-offset: 2px;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* The real input stays in the DOM and in the accessibility tree; the dot is its picture. */
|
|
268
|
+
.cn-radio-cards__input {
|
|
269
|
+
position: absolute;
|
|
270
|
+
opacity: 0;
|
|
271
|
+
inset: 0;
|
|
272
|
+
margin: 0;
|
|
273
|
+
cursor: pointer;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.cn-radio-cards__dot {
|
|
277
|
+
flex: 0 0 auto;
|
|
278
|
+
width: 14px;
|
|
279
|
+
height: 14px;
|
|
280
|
+
margin-top: 3px;
|
|
281
|
+
box-sizing: border-box;
|
|
282
|
+
border: 1px solid var(--color-border-maxcontrast);
|
|
283
|
+
border-radius: 50%;
|
|
284
|
+
background: var(--color-main-background);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.cn-radio-cards__card--selected .cn-radio-cards__dot {
|
|
288
|
+
border: 4px solid var(--color-primary-element);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.cn-radio-cards__text {
|
|
292
|
+
display: flex;
|
|
293
|
+
flex-direction: column;
|
|
294
|
+
gap: 2px;
|
|
295
|
+
min-width: 0;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.cn-radio-cards__title {
|
|
299
|
+
font-weight: 600;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.cn-radio-cards__description {
|
|
303
|
+
font-size: 12px;
|
|
304
|
+
color: var(--color-text-maxcontrast);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
@media (max-width: 640px) {
|
|
308
|
+
.cn-radio-cards__grid--2,
|
|
309
|
+
.cn-radio-cards__grid--3 {
|
|
310
|
+
grid-template-columns: minmax(0, 1fr);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
</style>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
3
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
*
|
|
5
|
+
* CnRadioCardsWidget — self-registers the `radio-cards` widget type (one
|
|
6
|
+
* choice out of a few cards with a title and a description, bound to an enum
|
|
7
|
+
* field of the current object and saved on selection) into the shared
|
|
8
|
+
* dashboardWidgetRegistry at module load.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import CnRadioCardsWidget from './CnRadioCardsWidget.vue'
|
|
12
|
+
import { registerDashboardWidget } from '../CnWidgetGrid/dashboardWidgetRegistry.js'
|
|
13
|
+
|
|
14
|
+
registerDashboardWidget('radio-cards', {
|
|
15
|
+
renderer: CnRadioCardsWidget,
|
|
16
|
+
form: null,
|
|
17
|
+
defaultContent: {
|
|
18
|
+
field: '',
|
|
19
|
+
options: [],
|
|
20
|
+
},
|
|
21
|
+
displayName: 'Radio cards',
|
|
22
|
+
icon: 'RadioboxMarked',
|
|
23
|
+
surfaces: ['detail-page'],
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
export { CnRadioCardsWidget }
|
|
27
|
+
export default CnRadioCardsWidget
|