@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
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { translate } from '@nextcloud/l10n';
|
|
2
2
|
import { NcNoteCard } from '@nextcloud/vue';
|
|
3
|
+
import __sfc_main from '../CnIcon/CnIcon.vue.js';
|
|
4
|
+
import { normalizeLook } from '../../composables/useLook.js';
|
|
5
|
+
import { fillTemplate } from '../../utils/fillTemplate.js';
|
|
3
6
|
import { resolveHref, followLinkClick } from '../../utils/linkNavigation.js';
|
|
7
|
+
import { readPath } from '../../utils/readPath.js';
|
|
4
8
|
import { safeHref } from '../../utils/safeHref.js';
|
|
5
9
|
import { nextUid } from '../../utils/uid.js';
|
|
6
10
|
import { readVisibleWhenValue, compareVisibleWhen } from '../../utils/visibleWhen.js';
|
|
@@ -14,6 +18,12 @@ const LAYOUTS = ['banner', 'attention'];
|
|
|
14
18
|
/** An attention card offers a primary and a secondary action, no more. */
|
|
15
19
|
const MAX_ACTIONS = 2;
|
|
16
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Under the board look the card takes what the boards draw: DqMijnWerk's
|
|
23
|
+
* "Vandaag eerst" has three secondary actions and the primary one.
|
|
24
|
+
*/
|
|
25
|
+
const MAX_ACTIONS_BOARD = 4;
|
|
26
|
+
|
|
17
27
|
/**
|
|
18
28
|
* CnBannerWidget — declarative notice banner for dashboards and v2 pages
|
|
19
29
|
* (`banner` widget type, Wave 1 of nextcloud-vue#91).
|
|
@@ -76,7 +86,7 @@ const MAX_ACTIONS = 2;
|
|
|
76
86
|
var script = {
|
|
77
87
|
name: 'CnBannerWidget',
|
|
78
88
|
|
|
79
|
-
components: { NcNoteCard },
|
|
89
|
+
components: { CnIcon: __sfc_main, NcNoteCard },
|
|
80
90
|
|
|
81
91
|
inject: {
|
|
82
92
|
/**
|
|
@@ -84,6 +94,8 @@ var script = {
|
|
|
84
94
|
* label that is not a key renders as written.
|
|
85
95
|
*/
|
|
86
96
|
cnTranslate: { default: () => (key) => key },
|
|
97
|
+
/** The app's look, provided by CnAppRoot or CnPageRenderer (`nextcloud` or `board`). */
|
|
98
|
+
cnLook: { default: 'nextcloud' },
|
|
87
99
|
},
|
|
88
100
|
|
|
89
101
|
props: {
|
|
@@ -104,6 +116,27 @@ var script = {
|
|
|
104
116
|
default: '',
|
|
105
117
|
},
|
|
106
118
|
|
|
119
|
+
/**
|
|
120
|
+
* A bold lead in front of the text ("2 aanmeldingen wachten op
|
|
121
|
+
* goedkeuring." before the rest of the sentence). `{value}` is replaced
|
|
122
|
+
* like in `text`, and it goes through the app's translate. Empty falls
|
|
123
|
+
* back to the `content` blob.
|
|
124
|
+
*/
|
|
125
|
+
lead: {
|
|
126
|
+
type: String,
|
|
127
|
+
default: '',
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* A named icon (`AccountPlus`, `AlertOutline`, ...) drawn before the
|
|
132
|
+
* text instead of the variant's own glyph. Empty falls back to the
|
|
133
|
+
* `content` blob, then to the variant glyph.
|
|
134
|
+
*/
|
|
135
|
+
icon: {
|
|
136
|
+
type: String,
|
|
137
|
+
default: '',
|
|
138
|
+
},
|
|
139
|
+
|
|
107
140
|
/**
|
|
108
141
|
* Optional visibility condition. Shape:
|
|
109
142
|
* `{ endpoint?, source?, field?, op?, value }` — exactly one of
|
|
@@ -168,7 +201,8 @@ var script = {
|
|
|
168
201
|
},
|
|
169
202
|
|
|
170
203
|
/**
|
|
171
|
-
* Attention card: at most
|
|
204
|
+
* Attention card: its actions, two at most (four under the board look,
|
|
205
|
+
* or `maxActions`). Each is `{ label, route?,
|
|
172
206
|
* href?, primary?, id? }`: `route` is a route name or location,
|
|
173
207
|
* `href` an URL. An action with neither renders a button that emits
|
|
174
208
|
* `action`. The first action is the primary one unless one sets
|
|
@@ -181,6 +215,29 @@ var script = {
|
|
|
181
215
|
default: null,
|
|
182
216
|
},
|
|
183
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Attention card: how many actions it shows at most. Null takes the
|
|
220
|
+
* default: two, four under the board look.
|
|
221
|
+
*
|
|
222
|
+
* @spec openspec/changes/screens-banner-actions-parity/specs/banner-actions/spec.md#requirement-the-board-attention-card-shows-the-boards-actions
|
|
223
|
+
*/
|
|
224
|
+
maxActions: {
|
|
225
|
+
type: Number,
|
|
226
|
+
default: null,
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Attention card: stack the actions under the text instead of beside it,
|
|
231
|
+
* the "Begin hier" card of PqMijnWerk (16px title, the action under the
|
|
232
|
+
* reason). Falls back to the `content` blob.
|
|
233
|
+
*
|
|
234
|
+
* @spec openspec/changes/screens-start-here-banner/specs/start-here-banner/spec.md#requirement-a-card-can-stack-its-action-under-the-text
|
|
235
|
+
*/
|
|
236
|
+
stacked: {
|
|
237
|
+
type: Boolean,
|
|
238
|
+
default: false,
|
|
239
|
+
},
|
|
240
|
+
|
|
184
241
|
/**
|
|
185
242
|
* Stored content blob (CnDashboardPage registry branch) carrying the
|
|
186
243
|
* same keys as the flat props: `{ variant, text, visibleWhen, route,
|
|
@@ -241,6 +298,12 @@ var script = {
|
|
|
241
298
|
* the text wherever it says `{value}`.
|
|
242
299
|
*/
|
|
243
300
|
conditionValue: null,
|
|
301
|
+
/**
|
|
302
|
+
* The first row of the `visibleWhen` source query (its `order`
|
|
303
|
+
* applied), the card's subject: `{subject.<field>}` in the texts
|
|
304
|
+
* and `@subject.<field>` in an action route read it.
|
|
305
|
+
*/
|
|
306
|
+
conditionRow: null,
|
|
244
307
|
/** Whether the visibleWhen request itself failed (not: answered "no"). */
|
|
245
308
|
conditionFailed: false,
|
|
246
309
|
/** Why it failed, as the request reported it. */
|
|
@@ -255,9 +318,38 @@ var script = {
|
|
|
255
318
|
return VARIANTS.includes(v) ? v : 'info'
|
|
256
319
|
},
|
|
257
320
|
|
|
258
|
-
/** The effective banner text (prop → content → ''). */
|
|
321
|
+
/** The effective banner text (prop → content → ''), through the app's translate. */
|
|
259
322
|
resolvedText() {
|
|
260
|
-
|
|
323
|
+
const text = this.text || (this.content && this.content.text) || '';
|
|
324
|
+
return text ? this.tl(text) : ''
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
/** The effective bold lead (prop → content → ''), through the app's translate. */
|
|
328
|
+
resolvedLead() {
|
|
329
|
+
const lead = this.lead || (this.content && this.content.lead) || '';
|
|
330
|
+
return lead ? this.tl(lead) : ''
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
/** The lead with `{value}` filled in. */
|
|
334
|
+
displayLead() {
|
|
335
|
+
return this.fillValue(this.resolvedLead)
|
|
336
|
+
},
|
|
337
|
+
|
|
338
|
+
/** The effective icon name (prop → content → ''). */
|
|
339
|
+
resolvedIcon() {
|
|
340
|
+
return this.icon || (this.content && this.content.icon) || ''
|
|
341
|
+
},
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* The note card's actions as links, under the board look only: the
|
|
345
|
+
* first resolved action of `actions`, as the board draws "Beleid
|
|
346
|
+
* wijzigen" at the end of the line. Without the look the note card
|
|
347
|
+
* ignores `actions`, as it always did.
|
|
348
|
+
*
|
|
349
|
+
* @return {Array<object>} The resolved actions (at most one).
|
|
350
|
+
*/
|
|
351
|
+
noteActions() {
|
|
352
|
+
return normalizeLook(this.cnLook) === 'board' ? this.resolvedActions.slice(0, 1) : []
|
|
261
353
|
},
|
|
262
354
|
|
|
263
355
|
/** The effective visibleWhen condition (prop → content → null). */
|
|
@@ -298,6 +390,15 @@ var script = {
|
|
|
298
390
|
return (this.layout || (this.content && this.content.layout) || 'banner') === 'attention'
|
|
299
391
|
},
|
|
300
392
|
|
|
393
|
+
/**
|
|
394
|
+
* Whether the actions sit under the text.
|
|
395
|
+
*
|
|
396
|
+
* @return {boolean}
|
|
397
|
+
*/
|
|
398
|
+
isStacked() {
|
|
399
|
+
return this.stacked || Boolean(this.content && this.content.stacked)
|
|
400
|
+
},
|
|
401
|
+
|
|
301
402
|
/**
|
|
302
403
|
* The attention card's kicker (prop, else content).
|
|
303
404
|
*
|
|
@@ -306,7 +407,7 @@ var script = {
|
|
|
306
407
|
*/
|
|
307
408
|
resolvedKicker() {
|
|
308
409
|
const kicker = this.kicker || (this.content && this.content.kicker) || '';
|
|
309
|
-
return kicker ? this.tl(kicker) : ''
|
|
410
|
+
return kicker ? this.fillValue(this.tl(kicker)) : ''
|
|
310
411
|
},
|
|
311
412
|
|
|
312
413
|
/**
|
|
@@ -339,12 +440,27 @@ var script = {
|
|
|
339
440
|
},
|
|
340
441
|
|
|
341
442
|
/**
|
|
342
|
-
* The attention card's actions: the first
|
|
443
|
+
* The attention card's actions: the first `actionCap` that have a label, each
|
|
343
444
|
* with its href and whether it is the primary one.
|
|
344
445
|
*
|
|
345
446
|
* @return {Array<{key: string, id: (string|undefined), label: string, href: string, target: (object|null), primary: boolean, index: number}>}
|
|
346
447
|
* @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card
|
|
347
448
|
*/
|
|
449
|
+
/**
|
|
450
|
+
* How many actions the attention card shows: `maxActions` (prop, then
|
|
451
|
+
* content), else four under the board look and two without it.
|
|
452
|
+
*
|
|
453
|
+
* @return {number} The cap.
|
|
454
|
+
* @spec openspec/changes/screens-banner-actions-parity/specs/banner-actions/spec.md#requirement-the-board-attention-card-shows-the-boards-actions
|
|
455
|
+
*/
|
|
456
|
+
actionCap() {
|
|
457
|
+
const explicit = this.maxActions ?? (this.content ? this.content.maxActions : undefined);
|
|
458
|
+
if (Number.isInteger(explicit) && explicit > 0) {
|
|
459
|
+
return explicit
|
|
460
|
+
}
|
|
461
|
+
return normalizeLook(this.cnLook) === 'board' ? MAX_ACTIONS_BOARD : MAX_ACTIONS
|
|
462
|
+
},
|
|
463
|
+
|
|
348
464
|
resolvedActions() {
|
|
349
465
|
const raw = this.actions || (this.content && this.content.actions) || [];
|
|
350
466
|
if (!Array.isArray(raw)) {
|
|
@@ -352,14 +468,14 @@ var script = {
|
|
|
352
468
|
}
|
|
353
469
|
const usable = raw
|
|
354
470
|
.filter((action) => action && typeof action === 'object' && typeof action.label === 'string' && action.label !== '')
|
|
355
|
-
.slice(0,
|
|
471
|
+
.slice(0, this.actionCap);
|
|
356
472
|
const declaredPrimary = usable.findIndex((action) => action.primary === true);
|
|
357
473
|
const primaryIndex = declaredPrimary === -1 ? 0 : declaredPrimary;
|
|
358
474
|
return usable.map((action, index) => {
|
|
359
475
|
let target = null;
|
|
360
476
|
let href = '';
|
|
361
477
|
if (action.route) {
|
|
362
|
-
target = typeof action.route === 'string' ? { name: action.route } : action.route;
|
|
478
|
+
target = typeof action.route === 'string' ? { name: action.route } : this.resolveSubject(action.route);
|
|
363
479
|
href = resolveHref(target, this.$router);
|
|
364
480
|
} else if (typeof action.href === 'string' && action.href !== '') {
|
|
365
481
|
const safe = safeHref(action.href);
|
|
@@ -384,7 +500,7 @@ var script = {
|
|
|
384
500
|
*/
|
|
385
501
|
visible() {
|
|
386
502
|
const title = this.title || (this.content && this.content.title) || '';
|
|
387
|
-
if (this.resolvedText === '' && !(this.isAttention && title !== '')) {
|
|
503
|
+
if (this.resolvedText === '' && this.resolvedLead === '' && !(this.isAttention && title !== '')) {
|
|
388
504
|
return false
|
|
389
505
|
}
|
|
390
506
|
if (!this.resolvedVisibleWhen) {
|
|
@@ -418,7 +534,7 @@ var script = {
|
|
|
418
534
|
*/
|
|
419
535
|
uncheckedText() {
|
|
420
536
|
const title = this.title || (this.content && this.content.title) || this.resolvedText;
|
|
421
|
-
if (!title || title.includes('{value}')) {
|
|
537
|
+
if (!title || title.includes('{value}') || title.includes('{subject.')) {
|
|
422
538
|
return translate('nextcloud-vue', 'Could not check')
|
|
423
539
|
}
|
|
424
540
|
// `escape: false`: the result is rendered through `{{ }}`, which escapes.
|
|
@@ -490,10 +606,55 @@ var script = {
|
|
|
490
606
|
* @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card
|
|
491
607
|
*/
|
|
492
608
|
fillValue(text) {
|
|
493
|
-
|
|
609
|
+
let out = text;
|
|
610
|
+
if (this.conditionValue !== null && out.includes('{value}')) {
|
|
611
|
+
out = out.replaceAll('{value}', String(this.conditionValue));
|
|
612
|
+
}
|
|
613
|
+
return this.fillSubject(out)
|
|
614
|
+
},
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Fill `{subject.<field>}` (and `{subject.<field>|date}`, `|days`) from
|
|
618
|
+
* the card's subject row. A token with no value empties the whole text,
|
|
619
|
+
* as in a record list. Text without a subject token is untouched.
|
|
620
|
+
*
|
|
621
|
+
* @param {string} text The text.
|
|
622
|
+
* @return {string} The filled text.
|
|
623
|
+
* @spec openspec/changes/screens-start-here-banner/specs/start-here-banner/spec.md#requirement-a-banner-can-name-the-first-row-of-a-query
|
|
624
|
+
*/
|
|
625
|
+
fillSubject(text) {
|
|
626
|
+
if (typeof text !== 'string' || !text.includes('{subject.')) {
|
|
494
627
|
return text
|
|
495
628
|
}
|
|
496
|
-
|
|
629
|
+
// `{value}` is not a subject token: keep it out of the template fill.
|
|
630
|
+
const guard = '\u0000value\u0000';
|
|
631
|
+
const filled = fillTemplate(text.replaceAll('{value}', guard), { subject: this.conditionRow || {} });
|
|
632
|
+
return filled.replaceAll(guard, '{value}')
|
|
633
|
+
},
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* Replace `@subject.<field>` strings anywhere in an action route
|
|
637
|
+
* (params, query) by the subject's value.
|
|
638
|
+
*
|
|
639
|
+
* @param {unknown} node A route name, location or any nested part of one.
|
|
640
|
+
* @return {unknown} The same shape with the tokens resolved.
|
|
641
|
+
* @spec openspec/changes/screens-start-here-banner/specs/start-here-banner/spec.md#requirement-a-banner-can-name-the-first-row-of-a-query
|
|
642
|
+
*/
|
|
643
|
+
resolveSubject(node) {
|
|
644
|
+
if (typeof node === 'string') {
|
|
645
|
+
if (!node.startsWith('@subject.')) {
|
|
646
|
+
return node
|
|
647
|
+
}
|
|
648
|
+
const value = this.conditionRow ? readPath(this.conditionRow, node.slice('@subject.'.length)) : undefined;
|
|
649
|
+
return value === undefined || value === null ? '' : String(value)
|
|
650
|
+
}
|
|
651
|
+
if (Array.isArray(node)) {
|
|
652
|
+
return node.map((item) => this.resolveSubject(item))
|
|
653
|
+
}
|
|
654
|
+
if (node && typeof node === 'object') {
|
|
655
|
+
return Object.fromEntries(Object.entries(node).map(([key, value]) => [key, this.resolveSubject(value)]))
|
|
656
|
+
}
|
|
657
|
+
return node
|
|
497
658
|
},
|
|
498
659
|
|
|
499
660
|
/**
|
|
@@ -536,6 +697,7 @@ var script = {
|
|
|
536
697
|
if (outcome) {
|
|
537
698
|
this.conditionMet = outcome.met === true;
|
|
538
699
|
this.conditionValue = outcome.value !== undefined ? outcome.value : null;
|
|
700
|
+
this.conditionRow = outcome.row && typeof outcome.row === 'object' ? outcome.row : null;
|
|
539
701
|
this.conditionFailed = outcome.failed === true;
|
|
540
702
|
this.conditionFailureReason = outcome.failed === true && typeof outcome.reason === 'string' ? outcome.reason : '';
|
|
541
703
|
return
|
|
@@ -544,12 +706,15 @@ var script = {
|
|
|
544
706
|
if (!cond) {
|
|
545
707
|
this.conditionMet = null;
|
|
546
708
|
this.conditionValue = null;
|
|
709
|
+
this.conditionRow = null;
|
|
547
710
|
this.conditionFailed = false;
|
|
548
711
|
this.conditionFailureReason = '';
|
|
549
712
|
return
|
|
550
713
|
}
|
|
551
714
|
try {
|
|
552
|
-
const
|
|
715
|
+
const sink = {};
|
|
716
|
+
const value = await readVisibleWhenValue(cond, undefined, sink);
|
|
717
|
+
this.conditionRow = sink.row || null;
|
|
553
718
|
this.conditionValue = value;
|
|
554
719
|
this.conditionMet = compareVisibleWhen(value, cond.op || 'eq', cond.value);
|
|
555
720
|
this.conditionFailed = false;
|
|
@@ -562,6 +727,7 @@ var script = {
|
|
|
562
727
|
console.warn('[CnBannerWidget] visibleWhen could not be evaluated, banner hidden:', error?.message || error);
|
|
563
728
|
this.conditionMet = false;
|
|
564
729
|
this.conditionValue = null;
|
|
730
|
+
this.conditionRow = null;
|
|
565
731
|
this.conditionFailed = true;
|
|
566
732
|
this.conditionFailureReason = typeof error?.message === 'string' ? error.message : String(error ?? '');
|
|
567
733
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnBannerWidget.vue2.js","sources":["../../../../src/components/CnBannerWidget/CnBannerWidget.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<section\n\t\tv-if=\"visible && isAttention\"\n\t\tclass=\"cn-banner-widget cn-banner-widget--attention\"\n\t\t:class=\"'cn-banner-widget--' + resolvedVariant\"\n\t\t:aria-labelledby=\"headingId\"\n\t\tdata-testid=\"cn-banner-widget-attention\">\n\t\t<div class=\"cn-banner-widget__body\">\n\t\t\t<p v-if=\"resolvedKicker\" class=\"cn-banner-widget__kicker\">\n\t\t\t\t{{ resolvedKicker }}\n\t\t\t</p>\n\t\t\t<h3 :id=\"headingId\" class=\"cn-banner-widget__title\">\n\t\t\t\t{{ displayTitle }}\n\t\t\t</h3>\n\t\t\t<p v-if=\"displayReason\" class=\"cn-banner-widget__reason\">\n\t\t\t\t{{ displayReason }}\n\t\t\t</p>\n\t\t</div>\n\t\t<div v-if=\"resolvedActions.length > 0\" class=\"cn-banner-widget__actions\">\n\t\t\t<component\n\t\t\t\t:is=\"action.href ? 'a' : 'button'\"\n\t\t\t\tv-for=\"action in resolvedActions\"\n\t\t\t\t:key=\"action.key\"\n\t\t\t\tclass=\"cn-banner-widget__action\"\n\t\t\t\t:class=\"action.primary ? 'cn-banner-widget__action--primary' : 'cn-banner-widget__action--secondary'\"\n\t\t\t\t:href=\"action.href || null\"\n\t\t\t\t:type=\"action.href ? null : 'button'\"\n\t\t\t\tdata-testid=\"cn-banner-widget-action\"\n\t\t\t\t@click=\"onActionClick($event, action)\">\n\t\t\t\t{{ action.label }}\n\t\t\t</component>\n\t\t</div>\n\t</section>\n\t<!-- The count could not be read. One quiet line, not the card and not an\n\t alarm: hidden would read as \"nothing to report\", which is not known. -->\n\t<p\n\t\tv-else-if=\"checkFailed\"\n\t\tclass=\"cn-banner-widget cn-banner-widget--unchecked\"\n\t\t:title=\"failureTooltip\"\n\t\tdata-testid=\"cn-banner-widget-unchecked\">\n\t\t<span class=\"cn-banner-widget__unchecked-text\">{{ uncheckedText }}</span>\n\t\t<span class=\"cn-banner-widget__unchecked-reason\">{{ failureTooltip }}</span>\n\t</p>\n\t<div v-else-if=\"visible\" class=\"cn-banner-widget\">\n\t\t<NcNoteCard :type=\"resolvedVariant\" class=\"cn-banner-widget__card\">\n\t\t\t<component\n\t\t\t\t:is=\"clickable ? 'a' : 'span'\"\n\t\t\t\tclass=\"cn-banner-widget__text\"\n\t\t\t\t:class=\"{ 'cn-banner-widget__text--clickable': clickable }\"\n\t\t\t\t:href=\"clickable ? routeHref : null\"\n\t\t\t\tdata-testid=\"cn-banner-widget-text\"\n\t\t\t\t@click=\"onClick\">\n\t\t\t\t{{ displayText }}\n\t\t\t</component>\n\t\t</NcNoteCard>\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcNoteCard } from '@nextcloud/vue'\nimport { followLinkClick, resolveHref } from '../../utils/linkNavigation.js'\nimport { safeHref } from '../../utils/safeHref.js'\nimport { nextUid } from '../../utils/uid.js'\nimport { compareVisibleWhen, readVisibleWhenValue } from '../../utils/visibleWhen.js'\n\n/** Variants understood by NcNoteCard. */\nconst VARIANTS = ['info', 'warning', 'error', 'success']\n\n/** Layouts: the note card (default) or the attention card. */\nconst LAYOUTS = ['banner', 'attention']\n\n/** An attention card offers a primary and a secondary action, no more. */\nconst MAX_ACTIONS = 2\n\n/**\n * CnBannerWidget — declarative notice banner for dashboards and v2 pages\n * (`banner` widget type, Wave 1 of nextcloud-vue#91).\n *\n * Renders a themed NcNoteCard with a variant (`info | warning | error`),\n * a text, an optional click-through route, and an optional `visibleWhen`\n * condition: a simple `{ field, op, value }` predicate evaluated against\n * an endpoint response or an OpenRegister source (the doriath\n * migration-banner case — \"show while `pending > 0`\").\n *\n * Config arrives either as flat props (v2 grid spreads `props`) or as a\n * stored `content` blob (CnDashboardPage's registry branch) — explicit\n * flat props win on collision.\n *\n * ```json\n * {\n * \"widgetKey\": \"banner\",\n * \"props\": {\n * \"variant\": \"warning\",\n * \"text\": \"Migrations pending — open the migration overview.\",\n * \"visibleWhen\": { \"endpoint\": \"/apps/doriath/api/migrations/status\", \"field\": \"pending\", \"op\": \"gt\", \"value\": 0 },\n * \"route\": \"migrations\"\n * }\n * }\n * ```\n *\n * Fail-safe: with a `visibleWhen`, the banner stays HIDDEN until the\n * condition evaluates true — a failed fetch never breaks (or spams) a\n * dashboard.\n *\n * An attention card (`layout: \"attention\"`) whose `visibleWhen` request\n * FAILS renders one quiet line instead, \"Could not check\", with the reason as\n * a tooltip. A hidden card reads as \"nothing needs attention\", and a failed\n * count does not know that. A request that succeeds with a value that does\n * not meet the condition still renders nothing.\n *\n * `layout: \"attention\"` turns the banner into an attention card: a card with\n * a coloured edge by severity, a `kicker` label, a `title`, a `reason` line\n * and up to two `actions` (the first is the primary one unless an action says\n * `primary` itself). `visibleWhen` works the same way. Without `layout` the\n * note card above renders, as it always did.\n *\n * ```json\n * {\n * \"widgetKey\": \"banner\",\n * \"props\": {\n * \"layout\": \"attention\",\n * \"variant\": \"error\",\n * \"kicker\": \"First today\",\n * \"title\": \"Parking permits city centre\",\n * \"reason\": \"The deadline ends today.\",\n * \"actions\": [\n * { \"label\": \"Open case\", \"route\": { \"name\": \"CaseDetail\", \"params\": { \"id\": \"2026-0061\" } } },\n * { \"label\": \"Suspend deadline\", \"route\": \"CaseSuspend\" }\n * ]\n * }\n * }\n * ```\n */\nexport default {\n\tname: 'CnBannerWidget',\n\n\tcomponents: { NcNoteCard },\n\n\tinject: {\n\t\t/**\n\t\t * The host's label lookup (CnAppRoot provides it); identity without one, so a\n\t\t * label that is not a key renders as written.\n\t\t */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * Banner severity variant: `info | warning | error` (plus `success`\n\t\t * for completeness — NcNoteCard's set). Empty falls back to the\n\t\t * `content` blob, then `info`.\n\t\t */\n\t\tvariant: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t\tvalidator: (v) => v === '' || VARIANTS.includes(v),\n\t\t},\n\n\t\t/** Pre-translated banner text. Empty falls back to the `content` blob. */\n\t\ttext: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Optional visibility condition. Shape:\n\t\t * `{ endpoint?, source?, field?, op?, value }` — exactly one of\n\t\t * `endpoint` (a same-origin URL returning JSON) or `source`\n\t\t * (`{ register, schema, filter? }`, an OpenRegister object query whose\n\t\t * `filter` supports the shared @-token grammar). `field` is a\n\t\t * dot-path into the response (for a `source`, into the first result;\n\t\t * omit it — or use `@total` — to compare the collection total).\n\t\t * `op` is `eq | neq | gt | gte | lt | lte` (default `eq`); `value` is\n\t\t * the literal right-hand side. `null` (the default) shows the banner\n\t\t * unconditionally.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tvisibleWhen: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Optional click-through route: a vue-router route NAME (string) or\n\t\t * a full location object. When set, the banner text is a link to that\n\t\t * route. `null` renders static text.\n\t\t *\n\t\t * @type {string|object|null}\n\t\t */\n\t\troute: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * How the banner renders: `banner` (the note card, default) or\n\t\t * `attention` (a card with a severity edge, kicker, title, reason and\n\t\t * up to two actions). Empty falls back to the `content` blob, then\n\t\t * `banner`.\n\t\t *\n\t\t * @type {''|'banner'|'attention'}\n\t\t */\n\t\tlayout: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t\tvalidator: (v) => v === '' || LAYOUTS.includes(v),\n\t\t},\n\n\t\t/** Attention card: the small label above the title (\"First today\"). */\n\t\tkicker: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Attention card: the title. Falls back to `text` when empty. */\n\t\ttitle: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Attention card: the line under the title that says why this needs attention. `{value}` is replaced like in `text`. */\n\t\treason: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Attention card: at most two actions. Each is `{ label, route?,\n\t\t * href?, primary?, id? }`: `route` is a route name or location,\n\t\t * `href` an URL. An action with neither renders a button that emits\n\t\t * `action`. The first action is the primary one unless one sets\n\t\t * `primary: true`.\n\t\t *\n\t\t * @type {Array<{label: string, route?: (string|object), href?: string, primary?: boolean, id?: string}>|null}\n\t\t */\n\t\tactions: {\n\t\t\ttype: Array,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Stored content blob (CnDashboardPage registry branch) carrying the\n\t\t * same keys as the flat props: `{ variant, text, visibleWhen, route,\n\t\t * layout, kicker, title, reason, actions }`. Explicit flat props win\n\t\t * on collision.\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/**\n\t\t * Pre-evaluated `visibleWhen` outcome `{ met, value }`, injected by a\n\t\t * host that already ran the predicate (CnDashboardPage evaluates it\n\t\t * to know whether to collapse the banner's grid cell). When present,\n\t\t * the banner renders from this verdict instead of fetching again —\n\t\t * no duplicate request and no hidden-until-self-evaluated flash —\n\t\t * and `value` feeds the `{value}` text placeholder. `null` (the\n\t\t * default) keeps the banner self-evaluating. A host whose request\n\t\t * failed passes `{ met: false, value: null, failed: true, reason }`,\n\t\t * and an attention card then says it could not check.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tconditionOutcome: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: [\n\t\t/**\n\t\t * Emitted when an attention-card action without a `route` or `href`\n\t\t * is clicked, so the host can run it.\n\t\t *\n\t\t * @event action\n\t\t * @type {{id: (string|undefined), label: string, index: number}}\n\t\t */\n\t\t'action',\n\t],\n\n\t/**\n\t * The banner's own state: the evaluated condition, the value it read,\n\t * and whether the request for it failed.\n\t *\n\t * @return {object} The state.\n\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-an-attention-card-says-when-it-could-not-check\n\t */\n\tdata() {\n\t\treturn {\n\t\t\t/** Id that ties the attention card's region to its title. */\n\t\t\theadingId: `cn-banner-title-${nextUid()}`,\n\t\t\t/** Evaluated visibleWhen outcome (null = not yet evaluated). */\n\t\t\tconditionMet: null,\n\t\t\t/**\n\t\t\t * The raw field value the predicate read (from the injected\n\t\t\t * outcome or the banner's own evaluation) — interpolated into\n\t\t\t * the text wherever it says `{value}`.\n\t\t\t */\n\t\t\tconditionValue: null,\n\t\t\t/** Whether the visibleWhen request itself failed (not: answered \"no\"). */\n\t\t\tconditionFailed: false,\n\t\t\t/** Why it failed, as the request reported it. */\n\t\t\tconditionFailureReason: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** The effective variant (prop → content → 'info'). */\n\t\tresolvedVariant() {\n\t\t\tconst v = this.variant || (this.content && this.content.variant) || 'info'\n\t\t\treturn VARIANTS.includes(v) ? v : 'info'\n\t\t},\n\n\t\t/** The effective banner text (prop → content → ''). */\n\t\tresolvedText() {\n\t\t\treturn this.text || (this.content && this.content.text) || ''\n\t\t},\n\n\t\t/** The effective visibleWhen condition (prop → content → null). */\n\t\tresolvedVisibleWhen() {\n\t\t\treturn this.visibleWhen || (this.content && this.content.visibleWhen) || null\n\t\t},\n\n\t\t/** The effective injected outcome (prop → content → null). */\n\t\tresolvedConditionOutcome() {\n\t\t\treturn this.conditionOutcome || (this.content && this.content.conditionOutcome) || null\n\t\t},\n\n\t\t/**\n\t\t * The rendered text: `resolvedText` with `{value}` replaced by the\n\t\t * predicate's field value once one is known. Without a known value\n\t\t * the text renders as written — a `{value}` placeholder only makes\n\t\t * sense on a conditional banner, which stays hidden until its\n\t\t * predicate (and therefore its value) resolves.\n\t\t *\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tdisplayText() {\n\t\t\treturn this.fillValue(this.resolvedText)\n\t\t},\n\n\t\t/** The effective click-through route (prop → content → null). */\n\t\tresolvedRoute() {\n\t\t\treturn this.route || (this.content && this.content.route) || null\n\t\t},\n\n\t\t/**\n\t\t * Whether the attention card renders instead of the note card.\n\t\t *\n\t\t * @return {boolean}\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tisAttention() {\n\t\t\treturn (this.layout || (this.content && this.content.layout) || 'banner') === 'attention'\n\t\t},\n\n\t\t/**\n\t\t * The attention card's kicker (prop, else content).\n\t\t *\n\t\t * @return {string}\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tresolvedKicker() {\n\t\t\tconst kicker = this.kicker || (this.content && this.content.kicker) || ''\n\t\t\treturn kicker ? this.tl(kicker) : ''\n\t\t},\n\n\t\t/**\n\t\t * The attention card's title: `title`, else `text`, with `{value}` filled in.\n\t\t *\n\t\t * @return {string}\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tdisplayTitle() {\n\t\t\tconst title = this.title || (this.content && this.content.title) || ''\n\t\t\treturn title ? this.fillValue(this.tl(title)) : this.displayText\n\t\t},\n\n\t\t/**\n\t\t * The attention card's reason line. When the title already used\n\t\t * `text`, the text is not repeated here.\n\t\t *\n\t\t * @return {string}\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tdisplayReason() {\n\t\t\tconst reason = this.reason || (this.content && this.content.reason) || ''\n\t\t\tif (reason) {\n\t\t\t\treturn this.fillValue(this.tl(reason))\n\t\t\t}\n\t\t\tconst title = this.title || (this.content && this.content.title) || ''\n\t\t\t// A card that sets `text` to the same words as its `title` says\n\t\t\t// them once.\n\t\t\treturn title && this.displayText !== this.displayTitle ? this.displayText : ''\n\t\t},\n\n\t\t/**\n\t\t * The attention card's actions: the first two that have a label, each\n\t\t * with its href and whether it is the primary one.\n\t\t *\n\t\t * @return {Array<{key: string, id: (string|undefined), label: string, href: string, target: (object|null), primary: boolean, index: number}>}\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tresolvedActions() {\n\t\t\tconst raw = this.actions || (this.content && this.content.actions) || []\n\t\t\tif (!Array.isArray(raw)) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\tconst usable = raw\n\t\t\t\t.filter((action) => action && typeof action === 'object' && typeof action.label === 'string' && action.label !== '')\n\t\t\t\t.slice(0, MAX_ACTIONS)\n\t\t\tconst declaredPrimary = usable.findIndex((action) => action.primary === true)\n\t\t\tconst primaryIndex = declaredPrimary === -1 ? 0 : declaredPrimary\n\t\t\treturn usable.map((action, index) => {\n\t\t\t\tlet target = null\n\t\t\t\tlet href = ''\n\t\t\t\tif (action.route) {\n\t\t\t\t\ttarget = typeof action.route === 'string' ? { name: action.route } : action.route\n\t\t\t\t\thref = resolveHref(target, this.$router)\n\t\t\t\t} else if (typeof action.href === 'string' && action.href !== '') {\n\t\t\t\t\tconst safe = safeHref(action.href)\n\t\t\t\t\thref = safe === '#' ? '' : safe\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tkey: `${index}-${action.id || action.label}`,\n\t\t\t\t\tid: action.id,\n\t\t\t\t\tlabel: this.tl(action.label),\n\t\t\t\t\thref,\n\t\t\t\t\ttarget,\n\t\t\t\t\tprimary: index === primaryIndex,\n\t\t\t\t\tindex,\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Whether the banner renders: no condition = always; else the evaluated outcome.\n\t\t *\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tvisible() {\n\t\t\tconst title = this.title || (this.content && this.content.title) || ''\n\t\t\tif (this.resolvedText === '' && !(this.isAttention && title !== '')) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif (!this.resolvedVisibleWhen) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn this.conditionMet === true\n\t\t},\n\n\t\t/**\n\t\t * Whether to say the check failed: an attention card, with words to\n\t\t * show, whose `visibleWhen` request failed. A plain banner stays\n\t\t * hidden on failure, as it always did.\n\t\t *\n\t\t * @return {boolean}\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-an-attention-card-says-when-it-could-not-check\n\t\t */\n\t\tcheckFailed() {\n\t\t\tconst title = this.title || (this.content && this.content.title) || ''\n\t\t\treturn this.isAttention\n\t\t\t\t&& !!this.resolvedVisibleWhen\n\t\t\t\t&& this.conditionFailed\n\t\t\t\t&& (title !== '' || this.resolvedText !== '')\n\t\t},\n\n\t\t/**\n\t\t * The one line shown when the check failed. It names the card by its\n\t\t * title, unless the title needs the value that could not be read.\n\t\t *\n\t\t * @return {string}\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-an-attention-card-says-when-it-could-not-check\n\t\t */\n\t\tuncheckedText() {\n\t\t\tconst title = this.title || (this.content && this.content.title) || this.resolvedText\n\t\t\tif (!title || title.includes('{value}')) {\n\t\t\t\treturn t('nextcloud-vue', 'Could not check')\n\t\t\t}\n\t\t\t// `escape: false`: the result is rendered through `{{ }}`, which escapes.\n\t\t\treturn t('nextcloud-vue', 'Could not check: {subject}', { subject: title }, undefined, { escape: false })\n\t\t},\n\n\t\t/**\n\t\t * The reason the check failed, for the tooltip and for assistive\n\t\t * technology.\n\t\t *\n\t\t * @return {string}\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-an-attention-card-says-when-it-could-not-check\n\t\t */\n\t\tfailureTooltip() {\n\t\t\tif (!this.conditionFailureReason) {\n\t\t\t\treturn t('nextcloud-vue', 'The check failed.')\n\t\t\t}\n\t\t\treturn t('nextcloud-vue', 'The check failed: {reason}', { reason: this.conditionFailureReason }, undefined, { escape: false })\n\t\t},\n\n\t\t/** Whether the banner navigates on click (route set + router present). */\n\t\tclickable() {\n\t\t\treturn !!this.resolvedRoute && !!this.$router\n\t\t},\n\n\t\t/** The click-through route as a router location (a string is a route name). */\n\t\trouteLocation() {\n\t\t\tconst route = this.resolvedRoute\n\t\t\treturn typeof route === 'string' ? { name: route } : route\n\t\t},\n\n\t\t/** The href of the click-through link. */\n\t\trouteHref() {\n\t\t\treturn resolveHref(this.routeLocation, this.$router)\n\t\t},\n\t},\n\n\twatch: {\n\t\tresolvedVisibleWhen: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tthis.evaluateCondition()\n\t\t\t},\n\t\t},\n\n\t\tresolvedConditionOutcome() {\n\t\t\tthis.evaluateCondition()\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * A manifest string through the host's label lookup (`cnTranslate`), so a key\n\t\t * such as \"Mine\" reads in the user's language.\n\t\t *\n\t\t * @param {string} text The text as written in the manifest.\n\t\t * @return {string} The translated text.\n\t\t */\n\t\ttl(text) {\n\t\t\treturn typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\t/**\n\t\t * Replace `{value}` in a text by the value the predicate read, once\n\t\t * one is known.\n\t\t *\n\t\t * @param {string} text The text.\n\t\t * @return {string} The text with the value filled in.\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tfillValue(text) {\n\t\t\tif (this.conditionValue === null || !text.includes('{value}')) {\n\t\t\t\treturn text\n\t\t\t}\n\t\t\treturn text.replaceAll('{value}', String(this.conditionValue))\n\t\t},\n\n\t\t/**\n\t\t * Run an attention-card action: route an in-app link, leave an\n\t\t * external link to the browser, and emit `action` for a button.\n\t\t *\n\t\t * @param {MouseEvent} event The click.\n\t\t * @param {object} action The resolved action.\n\t\t * @return {void}\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tonActionClick(event, action) {\n\t\t\tif (action.target) {\n\t\t\t\tfollowLinkClick(event, action.target, this.$router)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!action.href) {\n\t\t\t\tthis.$emit('action', { id: action.id, label: action.label, index: action.index })\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Resolve the `visibleWhen` verdict. A host-injected\n\t\t * `conditionOutcome` wins outright — the host already ran the\n\t\t * predicate, so re-fetching would double the request and flash the\n\t\t * banner hidden until its own copy resolved. Otherwise evaluate\n\t\t * through the shared util primitives (endpoint / OpenRegister-source\n\t\t * modes — the Wave-1 banner shape is the canonical one, extracted to\n\t\t * `utils/visibleWhen.js` in Wave 3 so manifest actions reuse it),\n\t\t * keeping the read VALUE for the `{value}` text placeholder.\n\t\t * Fail-safe: any fetch/shape error leaves the banner hidden. The\n\t\t * failure is kept (`conditionFailed`, with its reason) so an\n\t\t * attention card can say it could not check.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-an-attention-card-says-when-it-could-not-check\n\t\t */\n\t\tasync evaluateCondition() {\n\t\t\tconst outcome = this.resolvedConditionOutcome\n\t\t\tif (outcome) {\n\t\t\t\tthis.conditionMet = outcome.met === true\n\t\t\t\tthis.conditionValue = outcome.value !== undefined ? outcome.value : null\n\t\t\t\tthis.conditionFailed = outcome.failed === true\n\t\t\t\tthis.conditionFailureReason = outcome.failed === true && typeof outcome.reason === 'string' ? outcome.reason : ''\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst cond = this.resolvedVisibleWhen\n\t\t\tif (!cond) {\n\t\t\t\tthis.conditionMet = null\n\t\t\t\tthis.conditionValue = null\n\t\t\t\tthis.conditionFailed = false\n\t\t\t\tthis.conditionFailureReason = ''\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst value = await readVisibleWhenValue(cond)\n\t\t\t\tthis.conditionValue = value\n\t\t\t\tthis.conditionMet = compareVisibleWhen(value, cond.op || 'eq', cond.value)\n\t\t\t\tthis.conditionFailed = false\n\t\t\t\tthis.conditionFailureReason = ''\n\t\t\t} catch (error) {\n\t\t\t\t// Still hidden: a banner that cannot tell whether it applies\n\t\t\t\t// should not claim attention. But not silently, because a\n\t\t\t\t// failed count and \"nothing to report\" look the same on screen.\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[CnBannerWidget] visibleWhen could not be evaluated, banner hidden:', error?.message || error)\n\t\t\t\tthis.conditionMet = false\n\t\t\t\tthis.conditionValue = null\n\t\t\t\tthis.conditionFailed = true\n\t\t\t\tthis.conditionFailureReason = typeof error?.message === 'string' ? error.message : String(error ?? '')\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Route a plain click on the link; a modified click opens the href\n\t\t * in the browser.\n\t\t *\n\t\t * @param {MouseEvent} event The click event.\n\t\t * @return {void}\n\t\t */\n\t\tonClick(event) {\n\t\t\tif (!this.clickable) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tfollowLinkClick(event, this.routeLocation, this.$router)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-banner-widget {\n\twidth: 100%;\n}\n\n.cn-banner-widget__card {\n\tmargin: 0;\n}\n\n.cn-banner-widget__text--clickable {\n\tcursor: pointer;\n\ttext-decoration: underline;\n\tcolor: inherit;\n}\n\n/* The check failed. Muted text, no fill, no severity colour: it is a note\n that something is not known, not a warning. */\n.cn-banner-widget--unchecked {\n\tbox-sizing: border-box;\n\tmargin: 0;\n\tpadding: 8px 12px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n\tcursor: help;\n}\n\n/* The reason, for assistive technology; sighted readers get the tooltip. */\n.cn-banner-widget__unchecked-reason {\n\tposition: absolute;\n\twidth: 1px;\n\theight: 1px;\n\tmargin: -1px;\n\tpadding: 0;\n\toverflow: hidden;\n\tclip-path: inset(50%);\n\twhite-space: nowrap;\n\tborder: 0;\n}\n\n/* Attention card. The severity edge is an inset shadow, so it takes no width. */\n.cn-banner-widget--attention {\n\t--cn-banner-accent: var(--color-primary-element);\n\t--cn-banner-accent-text: var(--color-primary-element);\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 16px 24px;\n\tbox-sizing: border-box;\n\tpadding: 20px 24px 20px 28px;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-container, var(--border-radius-large, 12px));\n\tbackground: var(--color-main-background);\n\tbox-shadow: inset 4px 0 0 0 var(--cn-banner-accent);\n}\n\n.cn-banner-widget--attention.cn-banner-widget--warning {\n\t--cn-banner-accent: var(--color-element-warning, var(--color-warning));\n\t--cn-banner-accent-text: var(--color-text-warning, var(--color-warning-text, var(--color-main-text)));\n}\n\n.cn-banner-widget--attention.cn-banner-widget--error {\n\t--cn-banner-accent: var(--color-element-error, var(--color-error));\n\t--cn-banner-accent-text: var(--color-text-error, var(--color-error-text));\n}\n\n.cn-banner-widget--attention.cn-banner-widget--success {\n\t--cn-banner-accent: var(--color-element-success, var(--color-success));\n\t--cn-banner-accent-text: var(--color-text-success, var(--color-success-text));\n}\n\n.cn-banner-widget__body {\n\tdisplay: flex;\n\tflex: 1 1 320px;\n\tflex-direction: column;\n\tgap: 6px;\n\tmin-width: 0;\n}\n\n.cn-banner-widget__kicker {\n\tmargin: 0;\n\tfont-size: 0.85em;\n\tfont-weight: 700;\n\tletter-spacing: 0.06em;\n\ttext-transform: uppercase;\n\tcolor: var(--cn-banner-accent-text);\n}\n\n.cn-banner-widget__title {\n\tmargin: 0;\n\tfont-size: 1.3em;\n\tfont-weight: 700;\n\tline-height: 1.3;\n\tcolor: var(--color-main-text);\n}\n\n.cn-banner-widget__reason {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-banner-widget__actions {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 10px;\n}\n\n.cn-banner-widget__action {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tbox-sizing: border-box;\n\tmin-height: var(--default-clickable-area, 40px);\n\tmargin: 0;\n\tpadding: 0 16px;\n\tborder: 1px solid var(--color-border-maxcontrast);\n\tborder-radius: var(--border-radius-element, var(--border-radius-large, 8px));\n\tfont: inherit;\n\tfont-weight: 600;\n\ttext-decoration: none;\n\tcursor: pointer;\n}\n\n.cn-banner-widget__action--secondary {\n\tbackground: var(--color-main-background);\n\tcolor: var(--color-main-text);\n}\n\n.cn-banner-widget__action--secondary:hover {\n\tbackground: var(--color-background-hover);\n}\n\n.cn-banner-widget__action--primary {\n\tborder-color: var(--color-primary-element);\n\tbackground: var(--color-primary-element);\n\tcolor: var(--color-primary-element-text);\n}\n\n.cn-banner-widget__action--primary:hover {\n\tborder-color: var(--color-primary-element-hover);\n\tbackground: var(--color-primary-element-hover);\n}\n\n.cn-banner-widget__action:focus-visible {\n\toutline: 2px solid var(--color-main-text);\n\toutline-offset: 2px;\n}\n</style>\n"],"names":["t"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnBannerWidget.vue2.js","sources":["../../../../src/components/CnBannerWidget/CnBannerWidget.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<section\n\t\tv-if=\"visible && isAttention\"\n\t\tclass=\"cn-banner-widget cn-banner-widget--attention\"\n\t\t:class=\"['cn-banner-widget--' + resolvedVariant, { 'cn-banner-widget--stacked': isStacked }]\"\n\t\t:aria-labelledby=\"headingId\"\n\t\tdata-testid=\"cn-banner-widget-attention\">\n\t\t<div class=\"cn-banner-widget__body\">\n\t\t\t<p v-if=\"resolvedKicker\" class=\"cn-banner-widget__kicker\">\n\t\t\t\t{{ resolvedKicker }}\n\t\t\t</p>\n\t\t\t<h3 :id=\"headingId\" class=\"cn-banner-widget__title\">\n\t\t\t\t{{ displayTitle }}\n\t\t\t</h3>\n\t\t\t<p v-if=\"displayReason\" class=\"cn-banner-widget__reason\">\n\t\t\t\t{{ displayReason }}\n\t\t\t</p>\n\t\t</div>\n\t\t<div v-if=\"resolvedActions.length > 0\" class=\"cn-banner-widget__actions\">\n\t\t\t<component\n\t\t\t\t:is=\"action.href ? 'a' : 'button'\"\n\t\t\t\tv-for=\"action in resolvedActions\"\n\t\t\t\t:key=\"action.key\"\n\t\t\t\tclass=\"cn-banner-widget__action\"\n\t\t\t\t:class=\"action.primary ? 'cn-banner-widget__action--primary' : 'cn-banner-widget__action--secondary'\"\n\t\t\t\t:href=\"action.href || null\"\n\t\t\t\t:type=\"action.href ? null : 'button'\"\n\t\t\t\tdata-testid=\"cn-banner-widget-action\"\n\t\t\t\t@click=\"onActionClick($event, action)\">\n\t\t\t\t{{ action.label }}\n\t\t\t</component>\n\t\t</div>\n\t</section>\n\t<!-- The count could not be read. One quiet line, not the card and not an\n\t alarm: hidden would read as \"nothing to report\", which is not known. -->\n\t<p\n\t\tv-else-if=\"checkFailed\"\n\t\tclass=\"cn-banner-widget cn-banner-widget--unchecked\"\n\t\t:title=\"failureTooltip\"\n\t\tdata-testid=\"cn-banner-widget-unchecked\">\n\t\t<span class=\"cn-banner-widget__unchecked-text\">{{ uncheckedText }}</span>\n\t\t<span class=\"cn-banner-widget__unchecked-reason\">{{ failureTooltip }}</span>\n\t</p>\n\t<div v-else-if=\"visible\" class=\"cn-banner-widget\">\n\t\t<NcNoteCard :type=\"resolvedVariant\" class=\"cn-banner-widget__card\">\n\t\t\t<!-- A named icon replaces the variant's own glyph. -->\n\t\t\t<template v-if=\"resolvedIcon\" #icon>\n\t\t\t\t<CnIcon :name=\"resolvedIcon\" :size=\"22\" data-testid=\"cn-banner-widget-icon\" />\n\t\t\t</template>\n\t\t\t<span class=\"cn-banner-widget__line\">\n\t\t\t\t<component\n\t\t\t\t\t:is=\"clickable ? 'a' : 'span'\"\n\t\t\t\t\tclass=\"cn-banner-widget__text\"\n\t\t\t\t\t:class=\"{ 'cn-banner-widget__text--clickable': clickable }\"\n\t\t\t\t\t:href=\"clickable ? routeHref : null\"\n\t\t\t\t\tdata-testid=\"cn-banner-widget-text\"\n\t\t\t\t\t@click=\"onClick\"><strong v-if=\"displayLead\" class=\"cn-banner-widget__lead\" data-testid=\"cn-banner-widget-lead\">{{ displayLead }}</strong>{{ displayLead && displayText ? ' ' : '' }}{{ displayText }}</component>\n\t\t\t\t<!-- Board look: the actions as links at the end of the line. -->\n\t\t\t\t<a\n\t\t\t\t\tv-for=\"action in noteActions\"\n\t\t\t\t\t:key=\"action.key\"\n\t\t\t\t\tclass=\"cn-banner-widget__link\"\n\t\t\t\t\t:href=\"action.href || null\"\n\t\t\t\t\tdata-testid=\"cn-banner-widget-link\"\n\t\t\t\t\t@click=\"onActionClick($event, action)\">{{ action.label }}</a>\n\t\t\t</span>\n\t\t</NcNoteCard>\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcNoteCard } from '@nextcloud/vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\nimport { normalizeLook } from '../../composables/useLook.js'\nimport { fillTemplate } from '../../utils/fillTemplate.js'\nimport { followLinkClick, resolveHref } from '../../utils/linkNavigation.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { safeHref } from '../../utils/safeHref.js'\nimport { nextUid } from '../../utils/uid.js'\nimport { compareVisibleWhen, readVisibleWhenValue } from '../../utils/visibleWhen.js'\n\n/** Variants understood by NcNoteCard. */\nconst VARIANTS = ['info', 'warning', 'error', 'success']\n\n/** Layouts: the note card (default) or the attention card. */\nconst LAYOUTS = ['banner', 'attention']\n\n/** An attention card offers a primary and a secondary action, no more. */\nconst MAX_ACTIONS = 2\n\n/**\n * Under the board look the card takes what the boards draw: DqMijnWerk's\n * \"Vandaag eerst\" has three secondary actions and the primary one.\n */\nconst MAX_ACTIONS_BOARD = 4\n\n/**\n * CnBannerWidget — declarative notice banner for dashboards and v2 pages\n * (`banner` widget type, Wave 1 of nextcloud-vue#91).\n *\n * Renders a themed NcNoteCard with a variant (`info | warning | error`),\n * a text, an optional click-through route, and an optional `visibleWhen`\n * condition: a simple `{ field, op, value }` predicate evaluated against\n * an endpoint response or an OpenRegister source (the doriath\n * migration-banner case — \"show while `pending > 0`\").\n *\n * Config arrives either as flat props (v2 grid spreads `props`) or as a\n * stored `content` blob (CnDashboardPage's registry branch) — explicit\n * flat props win on collision.\n *\n * ```json\n * {\n * \"widgetKey\": \"banner\",\n * \"props\": {\n * \"variant\": \"warning\",\n * \"text\": \"Migrations pending — open the migration overview.\",\n * \"visibleWhen\": { \"endpoint\": \"/apps/doriath/api/migrations/status\", \"field\": \"pending\", \"op\": \"gt\", \"value\": 0 },\n * \"route\": \"migrations\"\n * }\n * }\n * ```\n *\n * Fail-safe: with a `visibleWhen`, the banner stays HIDDEN until the\n * condition evaluates true — a failed fetch never breaks (or spams) a\n * dashboard.\n *\n * An attention card (`layout: \"attention\"`) whose `visibleWhen` request\n * FAILS renders one quiet line instead, \"Could not check\", with the reason as\n * a tooltip. A hidden card reads as \"nothing needs attention\", and a failed\n * count does not know that. A request that succeeds with a value that does\n * not meet the condition still renders nothing.\n *\n * `layout: \"attention\"` turns the banner into an attention card: a card with\n * a coloured edge by severity, a `kicker` label, a `title`, a `reason` line\n * and up to two `actions` (the first is the primary one unless an action says\n * `primary` itself). `visibleWhen` works the same way. Without `layout` the\n * note card above renders, as it always did.\n *\n * ```json\n * {\n * \"widgetKey\": \"banner\",\n * \"props\": {\n * \"layout\": \"attention\",\n * \"variant\": \"error\",\n * \"kicker\": \"First today\",\n * \"title\": \"Parking permits city centre\",\n * \"reason\": \"The deadline ends today.\",\n * \"actions\": [\n * { \"label\": \"Open case\", \"route\": { \"name\": \"CaseDetail\", \"params\": { \"id\": \"2026-0061\" } } },\n * { \"label\": \"Suspend deadline\", \"route\": \"CaseSuspend\" }\n * ]\n * }\n * }\n * ```\n */\nexport default {\n\tname: 'CnBannerWidget',\n\n\tcomponents: { CnIcon, NcNoteCard },\n\n\tinject: {\n\t\t/**\n\t\t * The host's label lookup (CnAppRoot provides it); identity without one, so a\n\t\t * label that is not a key renders as written.\n\t\t */\n\t\tcnTranslate: { default: () => (key) => key },\n\t\t/** The app's look, provided by CnAppRoot or CnPageRenderer (`nextcloud` or `board`). */\n\t\tcnLook: { default: 'nextcloud' },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * Banner severity variant: `info | warning | error` (plus `success`\n\t\t * for completeness — NcNoteCard's set). Empty falls back to the\n\t\t * `content` blob, then `info`.\n\t\t */\n\t\tvariant: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t\tvalidator: (v) => v === '' || VARIANTS.includes(v),\n\t\t},\n\n\t\t/** Pre-translated banner text. Empty falls back to the `content` blob. */\n\t\ttext: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * A bold lead in front of the text (\"2 aanmeldingen wachten op\n\t\t * goedkeuring.\" before the rest of the sentence). `{value}` is replaced\n\t\t * like in `text`, and it goes through the app's translate. Empty falls\n\t\t * back to the `content` blob.\n\t\t */\n\t\tlead: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * A named icon (`AccountPlus`, `AlertOutline`, ...) drawn before the\n\t\t * text instead of the variant's own glyph. Empty falls back to the\n\t\t * `content` blob, then to the variant glyph.\n\t\t */\n\t\ticon: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Optional visibility condition. Shape:\n\t\t * `{ endpoint?, source?, field?, op?, value }` — exactly one of\n\t\t * `endpoint` (a same-origin URL returning JSON) or `source`\n\t\t * (`{ register, schema, filter? }`, an OpenRegister object query whose\n\t\t * `filter` supports the shared @-token grammar). `field` is a\n\t\t * dot-path into the response (for a `source`, into the first result;\n\t\t * omit it — or use `@total` — to compare the collection total).\n\t\t * `op` is `eq | neq | gt | gte | lt | lte` (default `eq`); `value` is\n\t\t * the literal right-hand side. `null` (the default) shows the banner\n\t\t * unconditionally.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tvisibleWhen: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Optional click-through route: a vue-router route NAME (string) or\n\t\t * a full location object. When set, the banner text is a link to that\n\t\t * route. `null` renders static text.\n\t\t *\n\t\t * @type {string|object|null}\n\t\t */\n\t\troute: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * How the banner renders: `banner` (the note card, default) or\n\t\t * `attention` (a card with a severity edge, kicker, title, reason and\n\t\t * up to two actions). Empty falls back to the `content` blob, then\n\t\t * `banner`.\n\t\t *\n\t\t * @type {''|'banner'|'attention'}\n\t\t */\n\t\tlayout: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t\tvalidator: (v) => v === '' || LAYOUTS.includes(v),\n\t\t},\n\n\t\t/** Attention card: the small label above the title (\"First today\"). */\n\t\tkicker: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Attention card: the title. Falls back to `text` when empty. */\n\t\ttitle: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Attention card: the line under the title that says why this needs attention. `{value}` is replaced like in `text`. */\n\t\treason: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Attention card: its actions, two at most (four under the board look,\n\t\t * or `maxActions`). Each is `{ label, route?,\n\t\t * href?, primary?, id? }`: `route` is a route name or location,\n\t\t * `href` an URL. An action with neither renders a button that emits\n\t\t * `action`. The first action is the primary one unless one sets\n\t\t * `primary: true`.\n\t\t *\n\t\t * @type {Array<{label: string, route?: (string|object), href?: string, primary?: boolean, id?: string}>|null}\n\t\t */\n\t\tactions: {\n\t\t\ttype: Array,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Attention card: how many actions it shows at most. Null takes the\n\t\t * default: two, four under the board look.\n\t\t *\n\t\t * @spec openspec/changes/screens-banner-actions-parity/specs/banner-actions/spec.md#requirement-the-board-attention-card-shows-the-boards-actions\n\t\t */\n\t\tmaxActions: {\n\t\t\ttype: Number,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Attention card: stack the actions under the text instead of beside it,\n\t\t * the \"Begin hier\" card of PqMijnWerk (16px title, the action under the\n\t\t * reason). Falls back to the `content` blob.\n\t\t *\n\t\t * @spec openspec/changes/screens-start-here-banner/specs/start-here-banner/spec.md#requirement-a-card-can-stack-its-action-under-the-text\n\t\t */\n\t\tstacked: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Stored content blob (CnDashboardPage registry branch) carrying the\n\t\t * same keys as the flat props: `{ variant, text, visibleWhen, route,\n\t\t * layout, kicker, title, reason, actions }`. Explicit flat props win\n\t\t * on collision.\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/**\n\t\t * Pre-evaluated `visibleWhen` outcome `{ met, value }`, injected by a\n\t\t * host that already ran the predicate (CnDashboardPage evaluates it\n\t\t * to know whether to collapse the banner's grid cell). When present,\n\t\t * the banner renders from this verdict instead of fetching again —\n\t\t * no duplicate request and no hidden-until-self-evaluated flash —\n\t\t * and `value` feeds the `{value}` text placeholder. `null` (the\n\t\t * default) keeps the banner self-evaluating. A host whose request\n\t\t * failed passes `{ met: false, value: null, failed: true, reason }`,\n\t\t * and an attention card then says it could not check.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tconditionOutcome: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: [\n\t\t/**\n\t\t * Emitted when an attention-card action without a `route` or `href`\n\t\t * is clicked, so the host can run it.\n\t\t *\n\t\t * @event action\n\t\t * @type {{id: (string|undefined), label: string, index: number}}\n\t\t */\n\t\t'action',\n\t],\n\n\t/**\n\t * The banner's own state: the evaluated condition, the value it read,\n\t * and whether the request for it failed.\n\t *\n\t * @return {object} The state.\n\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-an-attention-card-says-when-it-could-not-check\n\t */\n\tdata() {\n\t\treturn {\n\t\t\t/** Id that ties the attention card's region to its title. */\n\t\t\theadingId: `cn-banner-title-${nextUid()}`,\n\t\t\t/** Evaluated visibleWhen outcome (null = not yet evaluated). */\n\t\t\tconditionMet: null,\n\t\t\t/**\n\t\t\t * The raw field value the predicate read (from the injected\n\t\t\t * outcome or the banner's own evaluation) — interpolated into\n\t\t\t * the text wherever it says `{value}`.\n\t\t\t */\n\t\t\tconditionValue: null,\n\t\t\t/**\n\t\t\t * The first row of the `visibleWhen` source query (its `order`\n\t\t\t * applied), the card's subject: `{subject.<field>}` in the texts\n\t\t\t * and `@subject.<field>` in an action route read it.\n\t\t\t */\n\t\t\tconditionRow: null,\n\t\t\t/** Whether the visibleWhen request itself failed (not: answered \"no\"). */\n\t\t\tconditionFailed: false,\n\t\t\t/** Why it failed, as the request reported it. */\n\t\t\tconditionFailureReason: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** The effective variant (prop → content → 'info'). */\n\t\tresolvedVariant() {\n\t\t\tconst v = this.variant || (this.content && this.content.variant) || 'info'\n\t\t\treturn VARIANTS.includes(v) ? v : 'info'\n\t\t},\n\n\t\t/** The effective banner text (prop → content → ''), through the app's translate. */\n\t\tresolvedText() {\n\t\t\tconst text = this.text || (this.content && this.content.text) || ''\n\t\t\treturn text ? this.tl(text) : ''\n\t\t},\n\n\t\t/** The effective bold lead (prop → content → ''), through the app's translate. */\n\t\tresolvedLead() {\n\t\t\tconst lead = this.lead || (this.content && this.content.lead) || ''\n\t\t\treturn lead ? this.tl(lead) : ''\n\t\t},\n\n\t\t/** The lead with `{value}` filled in. */\n\t\tdisplayLead() {\n\t\t\treturn this.fillValue(this.resolvedLead)\n\t\t},\n\n\t\t/** The effective icon name (prop → content → ''). */\n\t\tresolvedIcon() {\n\t\t\treturn this.icon || (this.content && this.content.icon) || ''\n\t\t},\n\n\t\t/**\n\t\t * The note card's actions as links, under the board look only: the\n\t\t * first resolved action of `actions`, as the board draws \"Beleid\n\t\t * wijzigen\" at the end of the line. Without the look the note card\n\t\t * ignores `actions`, as it always did.\n\t\t *\n\t\t * @return {Array<object>} The resolved actions (at most one).\n\t\t */\n\t\tnoteActions() {\n\t\t\treturn normalizeLook(this.cnLook) === 'board' ? this.resolvedActions.slice(0, 1) : []\n\t\t},\n\n\t\t/** The effective visibleWhen condition (prop → content → null). */\n\t\tresolvedVisibleWhen() {\n\t\t\treturn this.visibleWhen || (this.content && this.content.visibleWhen) || null\n\t\t},\n\n\t\t/** The effective injected outcome (prop → content → null). */\n\t\tresolvedConditionOutcome() {\n\t\t\treturn this.conditionOutcome || (this.content && this.content.conditionOutcome) || null\n\t\t},\n\n\t\t/**\n\t\t * The rendered text: `resolvedText` with `{value}` replaced by the\n\t\t * predicate's field value once one is known. Without a known value\n\t\t * the text renders as written — a `{value}` placeholder only makes\n\t\t * sense on a conditional banner, which stays hidden until its\n\t\t * predicate (and therefore its value) resolves.\n\t\t *\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tdisplayText() {\n\t\t\treturn this.fillValue(this.resolvedText)\n\t\t},\n\n\t\t/** The effective click-through route (prop → content → null). */\n\t\tresolvedRoute() {\n\t\t\treturn this.route || (this.content && this.content.route) || null\n\t\t},\n\n\t\t/**\n\t\t * Whether the attention card renders instead of the note card.\n\t\t *\n\t\t * @return {boolean}\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tisAttention() {\n\t\t\treturn (this.layout || (this.content && this.content.layout) || 'banner') === 'attention'\n\t\t},\n\n\t\t/**\n\t\t * Whether the actions sit under the text.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tisStacked() {\n\t\t\treturn this.stacked || Boolean(this.content && this.content.stacked)\n\t\t},\n\n\t\t/**\n\t\t * The attention card's kicker (prop, else content).\n\t\t *\n\t\t * @return {string}\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tresolvedKicker() {\n\t\t\tconst kicker = this.kicker || (this.content && this.content.kicker) || ''\n\t\t\treturn kicker ? this.fillValue(this.tl(kicker)) : ''\n\t\t},\n\n\t\t/**\n\t\t * The attention card's title: `title`, else `text`, with `{value}` filled in.\n\t\t *\n\t\t * @return {string}\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tdisplayTitle() {\n\t\t\tconst title = this.title || (this.content && this.content.title) || ''\n\t\t\treturn title ? this.fillValue(this.tl(title)) : this.displayText\n\t\t},\n\n\t\t/**\n\t\t * The attention card's reason line. When the title already used\n\t\t * `text`, the text is not repeated here.\n\t\t *\n\t\t * @return {string}\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tdisplayReason() {\n\t\t\tconst reason = this.reason || (this.content && this.content.reason) || ''\n\t\t\tif (reason) {\n\t\t\t\treturn this.fillValue(this.tl(reason))\n\t\t\t}\n\t\t\tconst title = this.title || (this.content && this.content.title) || ''\n\t\t\t// A card that sets `text` to the same words as its `title` says\n\t\t\t// them once.\n\t\t\treturn title && this.displayText !== this.displayTitle ? this.displayText : ''\n\t\t},\n\n\t\t/**\n\t\t * The attention card's actions: the first `actionCap` that have a label, each\n\t\t * with its href and whether it is the primary one.\n\t\t *\n\t\t * @return {Array<{key: string, id: (string|undefined), label: string, href: string, target: (object|null), primary: boolean, index: number}>}\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\t/**\n\t\t * How many actions the attention card shows: `maxActions` (prop, then\n\t\t * content), else four under the board look and two without it.\n\t\t *\n\t\t * @return {number} The cap.\n\t\t * @spec openspec/changes/screens-banner-actions-parity/specs/banner-actions/spec.md#requirement-the-board-attention-card-shows-the-boards-actions\n\t\t */\n\t\tactionCap() {\n\t\t\tconst explicit = this.maxActions ?? (this.content ? this.content.maxActions : undefined)\n\t\t\tif (Number.isInteger(explicit) && explicit > 0) {\n\t\t\t\treturn explicit\n\t\t\t}\n\t\t\treturn normalizeLook(this.cnLook) === 'board' ? MAX_ACTIONS_BOARD : MAX_ACTIONS\n\t\t},\n\n\t\tresolvedActions() {\n\t\t\tconst raw = this.actions || (this.content && this.content.actions) || []\n\t\t\tif (!Array.isArray(raw)) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\tconst usable = raw\n\t\t\t\t.filter((action) => action && typeof action === 'object' && typeof action.label === 'string' && action.label !== '')\n\t\t\t\t.slice(0, this.actionCap)\n\t\t\tconst declaredPrimary = usable.findIndex((action) => action.primary === true)\n\t\t\tconst primaryIndex = declaredPrimary === -1 ? 0 : declaredPrimary\n\t\t\treturn usable.map((action, index) => {\n\t\t\t\tlet target = null\n\t\t\t\tlet href = ''\n\t\t\t\tif (action.route) {\n\t\t\t\t\ttarget = typeof action.route === 'string' ? { name: action.route } : this.resolveSubject(action.route)\n\t\t\t\t\thref = resolveHref(target, this.$router)\n\t\t\t\t} else if (typeof action.href === 'string' && action.href !== '') {\n\t\t\t\t\tconst safe = safeHref(action.href)\n\t\t\t\t\thref = safe === '#' ? '' : safe\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tkey: `${index}-${action.id || action.label}`,\n\t\t\t\t\tid: action.id,\n\t\t\t\t\tlabel: this.tl(action.label),\n\t\t\t\t\thref,\n\t\t\t\t\ttarget,\n\t\t\t\t\tprimary: index === primaryIndex,\n\t\t\t\t\tindex,\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Whether the banner renders: no condition = always; else the evaluated outcome.\n\t\t *\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tvisible() {\n\t\t\tconst title = this.title || (this.content && this.content.title) || ''\n\t\t\tif (this.resolvedText === '' && this.resolvedLead === '' && !(this.isAttention && title !== '')) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif (!this.resolvedVisibleWhen) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn this.conditionMet === true\n\t\t},\n\n\t\t/**\n\t\t * Whether to say the check failed: an attention card, with words to\n\t\t * show, whose `visibleWhen` request failed. A plain banner stays\n\t\t * hidden on failure, as it always did.\n\t\t *\n\t\t * @return {boolean}\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-an-attention-card-says-when-it-could-not-check\n\t\t */\n\t\tcheckFailed() {\n\t\t\tconst title = this.title || (this.content && this.content.title) || ''\n\t\t\treturn this.isAttention\n\t\t\t\t&& !!this.resolvedVisibleWhen\n\t\t\t\t&& this.conditionFailed\n\t\t\t\t&& (title !== '' || this.resolvedText !== '')\n\t\t},\n\n\t\t/**\n\t\t * The one line shown when the check failed. It names the card by its\n\t\t * title, unless the title needs the value that could not be read.\n\t\t *\n\t\t * @return {string}\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-an-attention-card-says-when-it-could-not-check\n\t\t */\n\t\tuncheckedText() {\n\t\t\tconst title = this.title || (this.content && this.content.title) || this.resolvedText\n\t\t\tif (!title || title.includes('{value}') || title.includes('{subject.')) {\n\t\t\t\treturn t('nextcloud-vue', 'Could not check')\n\t\t\t}\n\t\t\t// `escape: false`: the result is rendered through `{{ }}`, which escapes.\n\t\t\treturn t('nextcloud-vue', 'Could not check: {subject}', { subject: title }, undefined, { escape: false })\n\t\t},\n\n\t\t/**\n\t\t * The reason the check failed, for the tooltip and for assistive\n\t\t * technology.\n\t\t *\n\t\t * @return {string}\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-an-attention-card-says-when-it-could-not-check\n\t\t */\n\t\tfailureTooltip() {\n\t\t\tif (!this.conditionFailureReason) {\n\t\t\t\treturn t('nextcloud-vue', 'The check failed.')\n\t\t\t}\n\t\t\treturn t('nextcloud-vue', 'The check failed: {reason}', { reason: this.conditionFailureReason }, undefined, { escape: false })\n\t\t},\n\n\t\t/** Whether the banner navigates on click (route set + router present). */\n\t\tclickable() {\n\t\t\treturn !!this.resolvedRoute && !!this.$router\n\t\t},\n\n\t\t/** The click-through route as a router location (a string is a route name). */\n\t\trouteLocation() {\n\t\t\tconst route = this.resolvedRoute\n\t\t\treturn typeof route === 'string' ? { name: route } : route\n\t\t},\n\n\t\t/** The href of the click-through link. */\n\t\trouteHref() {\n\t\t\treturn resolveHref(this.routeLocation, this.$router)\n\t\t},\n\t},\n\n\twatch: {\n\t\tresolvedVisibleWhen: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tthis.evaluateCondition()\n\t\t\t},\n\t\t},\n\n\t\tresolvedConditionOutcome() {\n\t\t\tthis.evaluateCondition()\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * A manifest string through the host's label lookup (`cnTranslate`), so a key\n\t\t * such as \"Mine\" reads in the user's language.\n\t\t *\n\t\t * @param {string} text The text as written in the manifest.\n\t\t * @return {string} The translated text.\n\t\t */\n\t\ttl(text) {\n\t\t\treturn typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\t/**\n\t\t * Replace `{value}` in a text by the value the predicate read, once\n\t\t * one is known.\n\t\t *\n\t\t * @param {string} text The text.\n\t\t * @return {string} The text with the value filled in.\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tfillValue(text) {\n\t\t\tlet out = text\n\t\t\tif (this.conditionValue !== null && out.includes('{value}')) {\n\t\t\t\tout = out.replaceAll('{value}', String(this.conditionValue))\n\t\t\t}\n\t\t\treturn this.fillSubject(out)\n\t\t},\n\n\t\t/**\n\t\t * Fill `{subject.<field>}` (and `{subject.<field>|date}`, `|days`) from\n\t\t * the card's subject row. A token with no value empties the whole text,\n\t\t * as in a record list. Text without a subject token is untouched.\n\t\t *\n\t\t * @param {string} text The text.\n\t\t * @return {string} The filled text.\n\t\t * @spec openspec/changes/screens-start-here-banner/specs/start-here-banner/spec.md#requirement-a-banner-can-name-the-first-row-of-a-query\n\t\t */\n\t\tfillSubject(text) {\n\t\t\tif (typeof text !== 'string' || !text.includes('{subject.')) {\n\t\t\t\treturn text\n\t\t\t}\n\t\t\t// `{value}` is not a subject token: keep it out of the template fill.\n\t\t\tconst guard = '\\u0000value\\u0000'\n\t\t\tconst filled = fillTemplate(text.replaceAll('{value}', guard), { subject: this.conditionRow || {} })\n\t\t\treturn filled.replaceAll(guard, '{value}')\n\t\t},\n\n\t\t/**\n\t\t * Replace `@subject.<field>` strings anywhere in an action route\n\t\t * (params, query) by the subject's value.\n\t\t *\n\t\t * @param {unknown} node A route name, location or any nested part of one.\n\t\t * @return {unknown} The same shape with the tokens resolved.\n\t\t * @spec openspec/changes/screens-start-here-banner/specs/start-here-banner/spec.md#requirement-a-banner-can-name-the-first-row-of-a-query\n\t\t */\n\t\tresolveSubject(node) {\n\t\t\tif (typeof node === 'string') {\n\t\t\t\tif (!node.startsWith('@subject.')) {\n\t\t\t\t\treturn node\n\t\t\t\t}\n\t\t\t\tconst value = this.conditionRow ? readPath(this.conditionRow, node.slice('@subject.'.length)) : undefined\n\t\t\t\treturn value === undefined || value === null ? '' : String(value)\n\t\t\t}\n\t\t\tif (Array.isArray(node)) {\n\t\t\t\treturn node.map((item) => this.resolveSubject(item))\n\t\t\t}\n\t\t\tif (node && typeof node === 'object') {\n\t\t\t\treturn Object.fromEntries(Object.entries(node).map(([key, value]) => [key, this.resolveSubject(value)]))\n\t\t\t}\n\t\t\treturn node\n\t\t},\n\n\t\t/**\n\t\t * Run an attention-card action: route an in-app link, leave an\n\t\t * external link to the browser, and emit `action` for a button.\n\t\t *\n\t\t * @param {MouseEvent} event The click.\n\t\t * @param {object} action The resolved action.\n\t\t * @return {void}\n\t\t * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-attention-card\n\t\t */\n\t\tonActionClick(event, action) {\n\t\t\tif (action.target) {\n\t\t\t\tfollowLinkClick(event, action.target, this.$router)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!action.href) {\n\t\t\t\tthis.$emit('action', { id: action.id, label: action.label, index: action.index })\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Resolve the `visibleWhen` verdict. A host-injected\n\t\t * `conditionOutcome` wins outright — the host already ran the\n\t\t * predicate, so re-fetching would double the request and flash the\n\t\t * banner hidden until its own copy resolved. Otherwise evaluate\n\t\t * through the shared util primitives (endpoint / OpenRegister-source\n\t\t * modes — the Wave-1 banner shape is the canonical one, extracted to\n\t\t * `utils/visibleWhen.js` in Wave 3 so manifest actions reuse it),\n\t\t * keeping the read VALUE for the `{value}` text placeholder.\n\t\t * Fail-safe: any fetch/shape error leaves the banner hidden. The\n\t\t * failure is kept (`conditionFailed`, with its reason) so an\n\t\t * attention card can say it could not check.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-an-attention-card-says-when-it-could-not-check\n\t\t */\n\t\tasync evaluateCondition() {\n\t\t\tconst outcome = this.resolvedConditionOutcome\n\t\t\tif (outcome) {\n\t\t\t\tthis.conditionMet = outcome.met === true\n\t\t\t\tthis.conditionValue = outcome.value !== undefined ? outcome.value : null\n\t\t\t\tthis.conditionRow = outcome.row && typeof outcome.row === 'object' ? outcome.row : null\n\t\t\t\tthis.conditionFailed = outcome.failed === true\n\t\t\t\tthis.conditionFailureReason = outcome.failed === true && typeof outcome.reason === 'string' ? outcome.reason : ''\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst cond = this.resolvedVisibleWhen\n\t\t\tif (!cond) {\n\t\t\t\tthis.conditionMet = null\n\t\t\t\tthis.conditionValue = null\n\t\t\t\tthis.conditionRow = null\n\t\t\t\tthis.conditionFailed = false\n\t\t\t\tthis.conditionFailureReason = ''\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst sink = {}\n\t\t\t\tconst value = await readVisibleWhenValue(cond, undefined, sink)\n\t\t\t\tthis.conditionRow = sink.row || null\n\t\t\t\tthis.conditionValue = value\n\t\t\t\tthis.conditionMet = compareVisibleWhen(value, cond.op || 'eq', cond.value)\n\t\t\t\tthis.conditionFailed = false\n\t\t\t\tthis.conditionFailureReason = ''\n\t\t\t} catch (error) {\n\t\t\t\t// Still hidden: a banner that cannot tell whether it applies\n\t\t\t\t// should not claim attention. But not silently, because a\n\t\t\t\t// failed count and \"nothing to report\" look the same on screen.\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[CnBannerWidget] visibleWhen could not be evaluated, banner hidden:', error?.message || error)\n\t\t\t\tthis.conditionMet = false\n\t\t\t\tthis.conditionValue = null\n\t\t\t\tthis.conditionRow = null\n\t\t\t\tthis.conditionFailed = true\n\t\t\t\tthis.conditionFailureReason = typeof error?.message === 'string' ? error.message : String(error ?? '')\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Route a plain click on the link; a modified click opens the href\n\t\t * in the browser.\n\t\t *\n\t\t * @param {MouseEvent} event The click event.\n\t\t * @return {void}\n\t\t */\n\t\tonClick(event) {\n\t\t\tif (!this.clickable) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tfollowLinkClick(event, this.routeLocation, this.$router)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-banner-widget {\n\twidth: 100%;\n}\n\n.cn-banner-widget__card {\n\tmargin: 0;\n}\n\n.cn-banner-widget__line {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: baseline;\n\tgap: 4px 20px;\n}\n\n.cn-banner-widget__lead {\n\tfont-weight: 700;\n}\n\n.cn-banner-widget__link {\n\tmargin-inline-start: auto;\n\tfont-size: 14px;\n\tfont-weight: 600;\n}\n\n.cn-banner-widget__text--clickable {\n\tcursor: pointer;\n\ttext-decoration: underline;\n\tcolor: inherit;\n}\n\n/* The check failed. Muted text, no fill, no severity colour: it is a note\n that something is not known, not a warning. */\n.cn-banner-widget--unchecked {\n\tbox-sizing: border-box;\n\tmargin: 0;\n\tpadding: 8px 12px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n\tcursor: help;\n}\n\n/* The reason, for assistive technology; sighted readers get the tooltip. */\n.cn-banner-widget__unchecked-reason {\n\tposition: absolute;\n\twidth: 1px;\n\theight: 1px;\n\tmargin: -1px;\n\tpadding: 0;\n\toverflow: hidden;\n\tclip-path: inset(50%);\n\twhite-space: nowrap;\n\tborder: 0;\n}\n\n/* Attention card. The severity edge is an inset shadow, so it takes no width. */\n.cn-banner-widget--attention {\n\t--cn-banner-accent: var(--color-primary-element);\n\t--cn-banner-accent-text: var(--color-primary-element);\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 16px 24px;\n\tbox-sizing: border-box;\n\tpadding: 20px 24px 20px 28px;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-container, var(--border-radius-large, 12px));\n\tbackground: var(--color-main-background);\n\tbox-shadow: inset 4px 0 0 0 var(--cn-banner-accent);\n}\n\n.cn-banner-widget--attention.cn-banner-widget--warning {\n\t--cn-banner-accent: var(--color-element-warning, var(--color-warning));\n\t--cn-banner-accent-text: var(--color-text-warning, var(--color-warning-text, var(--color-main-text)));\n}\n\n.cn-banner-widget--attention.cn-banner-widget--error {\n\t--cn-banner-accent: var(--color-element-error, var(--color-error));\n\t--cn-banner-accent-text: var(--color-text-error, var(--color-error-text));\n}\n\n.cn-banner-widget--attention.cn-banner-widget--success {\n\t--cn-banner-accent: var(--color-element-success, var(--color-success));\n\t--cn-banner-accent-text: var(--color-text-success, var(--color-success-text));\n}\n\n.cn-banner-widget__body {\n\tdisplay: flex;\n\tflex: 1 1 320px;\n\tflex-direction: column;\n\tgap: 6px;\n\tmin-width: 0;\n}\n\n.cn-banner-widget__kicker {\n\tmargin: 0;\n\tfont-size: 0.85em;\n\tfont-weight: 700;\n\tletter-spacing: 0.06em;\n\ttext-transform: uppercase;\n\tcolor: var(--cn-banner-accent-text);\n}\n\n.cn-banner-widget__title {\n\tmargin: 0;\n\tfont-size: 1.3em;\n\tfont-weight: 700;\n\tline-height: 1.3;\n\tcolor: var(--color-main-text);\n}\n\n.cn-banner-widget__reason {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n/* Stacked (PqMijnWerk \"Begin hier\"): the text, then the action under it. */\n.cn-banner-widget--stacked {\n\tflex-direction: column;\n\talign-items: flex-start;\n\tgap: 10px;\n}\n\n.cn-banner-widget--stacked .cn-banner-widget__body {\n\tflex: 0 0 auto;\n\tgap: 10px;\n}\n\n.cn-banner-widget--stacked .cn-banner-widget__title {\n\tfont-size: 16px;\n\tline-height: 1.4;\n}\n\n.cn-banner-widget--stacked .cn-banner-widget__reason {\n\tfont-size: 14px;\n}\n\n.cn-banner-widget--stacked .cn-banner-widget__action {\n\tmin-height: var(--cn-board-control-height, 40px);\n\tfont-size: 14px;\n}\n\n.cn-banner-widget__actions {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 10px;\n}\n\n.cn-banner-widget__action {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tbox-sizing: border-box;\n\tmin-height: var(--default-clickable-area, 40px);\n\tmargin: 0;\n\tpadding: 0 16px;\n\tborder: 1px solid var(--color-border-maxcontrast);\n\tborder-radius: var(--border-radius-element, var(--border-radius-large, 8px));\n\tfont: inherit;\n\tfont-weight: 600;\n\ttext-decoration: none;\n\tcursor: pointer;\n}\n\n.cn-banner-widget__action--secondary {\n\tbackground: var(--color-main-background);\n\tcolor: var(--color-main-text);\n}\n\n.cn-banner-widget__action--secondary:hover {\n\tbackground: var(--color-background-hover);\n}\n\n.cn-banner-widget__action--primary {\n\tborder-color: var(--color-primary-element);\n\tbackground: var(--color-primary-element);\n\tcolor: var(--color-primary-element-text);\n}\n\n.cn-banner-widget__action--primary:hover {\n\tborder-color: var(--color-primary-element-hover);\n\tbackground: var(--color-primary-element-hover);\n}\n\n.cn-banner-widget__action:focus-visible {\n\toutline: 2px solid var(--color-main-text);\n\toutline-offset: 2px;\n}\n</style>\n"],"names":["CnIcon","t"],"mappings":"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"}
|