@conduction/nextcloud-vue 2.56.0-beta.4 → 2.56.0-beta.5
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/CnActionsBar/CnActionsBar.vue2.js +12 -2
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +1 -2
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue3.js +0 -3
- package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue3.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +1 -2
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
- package/dist/esm/components/CnBoardView/CnBoardView.vue2.js +12 -5
- package/dist/esm/components/CnBoardView/CnBoardView.vue2.js.map +1 -1
- package/dist/esm/components/CnBoardView/CnBoardView.vue3.js +2 -1
- package/dist/esm/components/CnBoardView/CnBoardView.vue3.js.map +1 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js +9 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js.map +1 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js.map +1 -1
- package/dist/esm/components/CnContextMenu/CnContextMenu.vue2.js +6 -1
- package/dist/esm/components/CnContextMenu/CnContextMenu.vue2.js.map +1 -1
- package/dist/esm/components/CnContextMenu/CnContextMenu.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +116 -15
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +27 -14
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDateAxisView/CnDateAxisView.vue2.js +13 -6
- package/dist/esm/components/CnDateAxisView/CnDateAxisView.vue2.js.map +1 -1
- package/dist/esm/components/CnDateAxisView/CnDateAxisView.vue3.js +2 -0
- package/dist/esm/components/CnDateAxisView/CnDateAxisView.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +29 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js.map +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js +1 -2
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +3 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +17 -17
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesWidget/CnFilesWidget.vue2.js +4 -21
- package/dist/esm/components/CnFilesWidget/CnFilesWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesWidget/CnFilesWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue2.js +0 -13
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue3.js +8 -8
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowsPage.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowsPage.vue3.js +3 -2
- package/dist/esm/components/CnFlowsPage/CnFlowsPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +67 -13
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +15 -8
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/manifestActionDispatch.js +31 -11
- package/dist/esm/components/CnIndexPage/manifestActionDispatch.js.map +1 -1
- package/dist/esm/components/CnIntegrationWidget/CnIntegrationWidgetEmpty.vue2.js.map +1 -1
- package/dist/esm/components/CnIntegrationWidget/CnIntegrationWidgetEmpty.vue3.js +1 -2
- package/dist/esm/components/CnIntegrationWidget/CnIntegrationWidgetEmpty.vue3.js.map +1 -1
- package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue3.js +0 -1
- package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnLinkButtonWidget/CnLinkButtonWidget.vue2.js +2 -17
- package/dist/esm/components/CnLinkButtonWidget/CnLinkButtonWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnLinkButtonWidget/CnLinkButtonWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnLogsPage/CnLogsPage.vue2.js +35 -11
- package/dist/esm/components/CnLogsPage/CnLogsPage.vue2.js.map +1 -1
- package/dist/esm/components/CnLogsPage/CnLogsPage.vue3.js +3 -2
- package/dist/esm/components/CnLogsPage/CnLogsPage.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js +23 -5
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectList/CnObjectList.vue2.js +19 -3
- package/dist/esm/components/CnObjectList/CnObjectList.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectList/CnObjectList.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +45 -15
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +4 -2
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue2.js +24 -6
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue3.js +1 -1
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +0 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue3.js +4 -2
- package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnRowActions/CnRowActions.vue2.js +7 -2
- package/dist/esm/components/CnRowActions/CnRowActions.vue2.js.map +1 -1
- package/dist/esm/components/CnRowActions/CnRowActions.vue3.js.map +1 -1
- package/dist/esm/components/CnSpendAnalyticsWidget/CnSpendAnalyticsWidget.vue2.js +5 -3
- package/dist/esm/components/CnSpendAnalyticsWidget/CnSpendAnalyticsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnSpendAnalyticsWidget/CnSpendAnalyticsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTabs/CnTabs.vue2.js.map +1 -1
- package/dist/esm/components/CnTabs/CnTabs.vue3.js.map +1 -1
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js +3 -1
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js +1 -0
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/analytics/CnAnalyticsCard.vue2.js +3 -1
- package/dist/esm/integrations/builtin/analytics/CnAnalyticsCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/analytics/CnAnalyticsCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue2.js +3 -1
- package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue3.js +2 -4
- package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/bookmarks/CnBookmarksCard.vue2.js +6 -0
- package/dist/esm/integrations/builtin/bookmarks/CnBookmarksCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/bookmarks/CnBookmarksCard.vue3.js +68 -53
- package/dist/esm/integrations/builtin/bookmarks/CnBookmarksCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/bookmarks/CnBookmarksTab.vue2.js +17 -0
- package/dist/esm/integrations/builtin/bookmarks/CnBookmarksTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/bookmarks/CnBookmarksTab.vue3.js +21 -19
- package/dist/esm/integrations/builtin/bookmarks/CnBookmarksTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/collectives/CnCollectivesCard.vue2.js +3 -1
- package/dist/esm/integrations/builtin/collectives/CnCollectivesCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/collectives/CnCollectivesCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/collectives/CnCollectivesTab.vue2.js +3 -1
- package/dist/esm/integrations/builtin/collectives/CnCollectivesTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/collectives/CnCollectivesTab.vue3.js +2 -4
- package/dist/esm/integrations/builtin/collectives/CnCollectivesTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/cospend/CnCospendCard.vue2.js +2 -1
- package/dist/esm/integrations/builtin/cospend/CnCospendCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/cospend/CnCospendCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue2.js +2 -1
- package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue3.js +1 -2
- package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/deck/CnDeckCard.vue2.js +2 -1
- package/dist/esm/integrations/builtin/deck/CnDeckCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/deck/CnDeckCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/deck/CnDeckTab.vue2.js +2 -1
- package/dist/esm/integrations/builtin/deck/CnDeckTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/deck/CnDeckTab.vue3.js +1 -2
- package/dist/esm/integrations/builtin/deck/CnDeckTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/email/CnEmailCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/email/CnEmailCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/email/CnEmailTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/email/CnEmailTab.vue3.js +1 -2
- package/dist/esm/integrations/builtin/email/CnEmailTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/flow/CnFlowCard.vue2.js +2 -1
- package/dist/esm/integrations/builtin/flow/CnFlowCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/flow/CnFlowCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/flow/CnFlowTab.vue2.js +2 -1
- package/dist/esm/integrations/builtin/flow/CnFlowTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/flow/CnFlowTab.vue3.js +1 -2
- package/dist/esm/integrations/builtin/flow/CnFlowTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/forms/CnFormsCard.vue2.js +3 -1
- package/dist/esm/integrations/builtin/forms/CnFormsCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/forms/CnFormsCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/forms/CnFormsTab.vue2.js +3 -1
- package/dist/esm/integrations/builtin/forms/CnFormsTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/forms/CnFormsTab.vue3.js +2 -4
- package/dist/esm/integrations/builtin/forms/CnFormsTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/maps/CnMapsCard.vue2.js +3 -1
- package/dist/esm/integrations/builtin/maps/CnMapsCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/maps/CnMapsCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/maps/CnMapsTab.vue2.js +3 -1
- package/dist/esm/integrations/builtin/maps/CnMapsTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/maps/CnMapsTab.vue3.js +2 -4
- package/dist/esm/integrations/builtin/maps/CnMapsTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/openproject/CnOpenprojectCard.vue2.js +3 -1
- package/dist/esm/integrations/builtin/openproject/CnOpenprojectCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/openproject/CnOpenprojectCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/openproject/CnOpenprojectTab.vue2.js +3 -1
- package/dist/esm/integrations/builtin/openproject/CnOpenprojectTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/openproject/CnOpenprojectTab.vue3.js +2 -4
- package/dist/esm/integrations/builtin/openproject/CnOpenprojectTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/photos/CnPhotosCard.vue2.js +2 -1
- package/dist/esm/integrations/builtin/photos/CnPhotosCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/photos/CnPhotosCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue2.js +2 -1
- package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue3.js +1 -2
- package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/polls/CnPollsCard.vue2.js +2 -1
- package/dist/esm/integrations/builtin/polls/CnPollsCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/polls/CnPollsCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/polls/CnPollsTab.vue2.js +2 -1
- package/dist/esm/integrations/builtin/polls/CnPollsTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/polls/CnPollsTab.vue3.js +1 -2
- package/dist/esm/integrations/builtin/polls/CnPollsTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/shares/CnSharesTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/shares/CnSharesTab.vue3.js +3 -6
- package/dist/esm/integrations/builtin/shares/CnSharesTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/talk/CnTalkCard.vue2.js +3 -1
- package/dist/esm/integrations/builtin/talk/CnTalkCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/talk/CnTalkCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/talk/CnTalkTab.vue2.js +3 -1
- package/dist/esm/integrations/builtin/talk/CnTalkTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/talk/CnTalkTab.vue3.js +2 -4
- package/dist/esm/integrations/builtin/talk/CnTalkTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/time-tracker/CnTimeTrackerCard.vue2.js +2 -1
- package/dist/esm/integrations/builtin/time-tracker/CnTimeTrackerCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/time-tracker/CnTimeTrackerCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/time-tracker/CnTimeTrackerTab.vue2.js +2 -1
- package/dist/esm/integrations/builtin/time-tracker/CnTimeTrackerTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/time-tracker/CnTimeTrackerTab.vue3.js +1 -2
- package/dist/esm/integrations/builtin/time-tracker/CnTimeTrackerTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/xwiki/CnXwikiCard.vue2.js +4 -1
- package/dist/esm/integrations/builtin/xwiki/CnXwikiCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/xwiki/CnXwikiCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/xwiki/CnXwikiTab.vue2.js +6 -3
- package/dist/esm/integrations/builtin/xwiki/CnXwikiTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/xwiki/CnXwikiTab.vue3.js +2 -4
- package/dist/esm/integrations/builtin/xwiki/CnXwikiTab.vue3.js.map +1 -1
- package/dist/esm/l10n/en.json.js +1 -0
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +1 -0
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +71 -7
- package/dist/esm/utils/actionLink.js +5 -0
- package/dist/esm/utils/actionLink.js.map +1 -1
- package/dist/esm/utils/actionsDispatcher.js +16 -1
- package/dist/esm/utils/actionsDispatcher.js.map +1 -1
- package/dist/esm/utils/linkNavigation.js +6 -3
- package/dist/esm/utils/linkNavigation.js.map +1 -1
- package/dist/esm/utils/rowAuxClick.js +30 -5
- package/dist/esm/utils/rowAuxClick.js.map +1 -1
- package/dist/esm/utils/safeHref.js +18 -3
- package/dist/esm/utils/safeHref.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +809 -383
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +71 -7
- package/l10n/en.json +1 -0
- package/l10n/nl.json +1 -0
- package/package.json +1 -1
- package/src/components/CnActionsBar/CnActionsBar.vue +14 -5
- package/src/components/CnActionsMenu/CnActionsMenu.vue +0 -3
- package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +1 -2
- package/src/components/CnBoardView/CnBoardView.vue +13 -5
- package/src/components/CnCardGrid/CnCardGrid.vue +9 -1
- package/src/components/CnContextMenu/CnContextMenu.vue +6 -1
- package/src/components/CnDataTable/CnDataTable.md +1 -1
- package/src/components/CnDataTable/CnDataTable.vue +131 -17
- package/src/components/CnDateAxisView/CnDateAxisView.vue +15 -6
- package/src/components/CnDetailPage/CnDetailPage.md +1 -1
- package/src/components/CnDetailPage/CnDetailPage.vue +29 -1
- package/src/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue +1 -2
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +5 -3
- package/src/components/CnFilesWidget/CnFilesWidget.vue +4 -21
- package/src/components/CnFlowRunsWidget/CnFlowRunsWidget.vue +8 -21
- package/src/components/CnFlowsPage/CnFlowsPage.vue +2 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +75 -14
- package/src/components/CnIndexPage/manifestActionDispatch.js +31 -11
- package/src/components/CnIntegrationWidget/CnIntegrationWidgetEmpty.vue +1 -2
- package/src/components/CnInteractionFormWidget/CnInteractionFormWidget.vue +0 -1
- package/src/components/CnLinkButtonWidget/CnLinkButtonWidget.vue +2 -17
- package/src/components/CnLogsPage/CnLogsPage.vue +37 -12
- package/src/components/CnObjectCard/CnObjectCard.vue +24 -6
- package/src/components/CnObjectList/CnObjectList.vue +19 -3
- package/src/components/CnObjectListWidget/CnObjectListWidget.vue +47 -15
- package/src/components/CnObjectRow/CnObjectRow.vue +25 -7
- package/src/components/CnObjectSidebar/CnFilesTab.vue +0 -1
- package/src/components/CnPageRenderer/CnPageRenderer.vue +2 -0
- package/src/components/CnRowActions/CnRowActions.vue +7 -2
- package/src/components/CnSpendAnalyticsWidget/CnSpendAnalyticsWidget.vue +5 -3
- package/src/components/CnTabs/CnTabs.vue +7 -3
- package/src/components/CnTasksWidget/CnTasksWidget.vue +4 -1
- package/src/css/table.css +26 -0
- package/src/integrations/builtin/analytics/CnAnalyticsCard.vue +3 -2
- package/src/integrations/builtin/analytics/CnAnalyticsTab.vue +5 -6
- package/src/integrations/builtin/bookmarks/CnBookmarksCard.vue +12 -1
- package/src/integrations/builtin/bookmarks/CnBookmarksTab.vue +23 -6
- package/src/integrations/builtin/bookmarks/__tests__/CnBookmarksTab.spec.js +7 -2
- package/src/integrations/builtin/collectives/CnCollectivesCard.vue +3 -2
- package/src/integrations/builtin/collectives/CnCollectivesTab.vue +5 -6
- package/src/integrations/builtin/cospend/CnCospendCard.vue +2 -2
- package/src/integrations/builtin/cospend/CnCospendTab.vue +3 -4
- package/src/integrations/builtin/deck/CnDeckCard.vue +2 -2
- package/src/integrations/builtin/deck/CnDeckTab.vue +3 -4
- package/src/integrations/builtin/email/CnEmailCard.vue +6 -2
- package/src/integrations/builtin/email/CnEmailTab.vue +7 -4
- package/src/integrations/builtin/flow/CnFlowCard.vue +2 -2
- package/src/integrations/builtin/flow/CnFlowTab.vue +3 -4
- package/src/integrations/builtin/forms/CnFormsCard.vue +3 -2
- package/src/integrations/builtin/forms/CnFormsTab.vue +5 -6
- package/src/integrations/builtin/maps/CnMapsCard.vue +3 -2
- package/src/integrations/builtin/maps/CnMapsTab.vue +5 -6
- package/src/integrations/builtin/maps/__tests__/CnMapsTab.spec.js +9 -0
- package/src/integrations/builtin/openproject/CnOpenprojectCard.vue +3 -2
- package/src/integrations/builtin/openproject/CnOpenprojectTab.vue +5 -6
- package/src/integrations/builtin/photos/CnPhotosCard.vue +2 -2
- package/src/integrations/builtin/photos/CnPhotosTab.vue +3 -4
- package/src/integrations/builtin/polls/CnPollsCard.vue +2 -2
- package/src/integrations/builtin/polls/CnPollsTab.vue +3 -4
- package/src/integrations/builtin/shares/CnSharesTab.vue +3 -6
- package/src/integrations/builtin/talk/CnTalkCard.vue +3 -2
- package/src/integrations/builtin/talk/CnTalkTab.vue +5 -6
- package/src/integrations/builtin/time-tracker/CnTimeTrackerCard.vue +2 -2
- package/src/integrations/builtin/time-tracker/CnTimeTrackerTab.vue +3 -4
- package/src/integrations/builtin/xwiki/CnXwikiCard.vue +4 -2
- package/src/integrations/builtin/xwiki/CnXwikiTab.vue +7 -7
- package/src/integrations/builtin/xwiki/__tests__/CnXwikiTab.spec.js +9 -0
- package/src/utils/actionLink.js +5 -0
- package/src/utils/actionsDispatcher.js +15 -0
- package/src/utils/linkNavigation.js +6 -3
- package/src/utils/rowAuxClick.js +29 -4
- package/src/utils/safeHref.js +18 -3
|
@@ -2,6 +2,7 @@ import { translate, translatePlural } from '@nextcloud/l10n';
|
|
|
2
2
|
import { NcLoadingIcon } from '@nextcloud/vue';
|
|
3
3
|
import SitemapOutline from 'vue-material-design-icons/SitemapOutline.vue';
|
|
4
4
|
import __sfc_main from '../../../components/CnDetailCard/CnDetailCard.vue.js';
|
|
5
|
+
import { safeHref } from '../../../utils/safeHref.js';
|
|
5
6
|
import { prefixUrl, buildHeaders } from '../../../utils/headers.js';
|
|
6
7
|
|
|
7
8
|
const VALID_SURFACES = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity'];
|
|
@@ -137,7 +138,7 @@ var script = {
|
|
|
137
138
|
},
|
|
138
139
|
|
|
139
140
|
opUrl(op) {
|
|
140
|
-
return op.url
|
|
141
|
+
return op.url && safeHref(op.url) !== '#' ? op.url : this.flowSettingsUrl
|
|
141
142
|
},
|
|
142
143
|
|
|
143
144
|
shortClass(className) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnFlowCard.vue2.js","sources":["../../../../../src/integrations/builtin/flow/CnFlowCard.vue"],"sourcesContent":["<!--\n CnFlowCard — bespoke surface-aware widget for the `flow` (automation)\n integration.\n\n Replaces the generic CnIntegrationCard for the `flow` leaf. Branches\n on `surface` per AD-19:\n - user-dashboard / app-dashboard : headline \"N automations · M\n active\" + most-recent name with its entity binding.\n - detail-page : compact list of linked\n operations with entity / operation type / enabled indicator\n per row.\n - single-entity : chip with operation name + an\n enabled dot (referenceType: 'flow').\n\n Pulls rows from the same OR pluggable-integration sub-resource as\n CnFlowTab; for `single-entity` the optional `value` prop addresses a\n single operation by id (matching CnIntegrationCard's fetchSingle\n contract).\n\n See `openregister/openspec/changes/integration-flow/` for the spec\n delta and ADR-019 (registry mechanism), AD-19 (surface fallback).\n-->\n<template>\n\t<CnDetailCard :title=\"cardTitle\" :icon=\"cardIcon\" :collapsible=\"collapsible\">\n\t\t<NcLoadingIcon v-if=\"loading\" />\n\n\t\t<!-- single-entity surface: chip -->\n\t\t<template v-else-if=\"surface === 'single-entity'\">\n\t\t\t<span v-if=\"entity\" class=\"cn-flow-card__chip\" :title=\"chipSubtitle(entity)\">\n\t\t\t\t<SitemapOutline :size=\"14\" />\n\t\t\t\t<a\n\t\t\t\t\t:href=\"opUrl(entity)\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener\">{{ opTitle(entity) }}</a>\n\t\t\t\t<span\n\t\t\t\t\tclass=\"cn-flow-card__chip-enabled\"\n\t\t\t\t\t:class=\"enabledClass(entity)\" />\n\t\t\t</span>\n\t\t\t<span v-else class=\"cn-flow-card__empty\">{{ emptyLabel }}</span>\n\t\t</template>\n\n\t\t<!-- dashboard surfaces: headline + most-recent -->\n\t\t<template v-else-if=\"surface === 'user-dashboard' || surface === 'app-dashboard'\">\n\t\t\t<div v-if=\"degraded\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"operations.length === 0\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<div v-else class=\"cn-flow-card__headline\">\n\t\t\t\t<div class=\"cn-flow-card__headline-line\">\n\t\t\t\t\t<strong>{{ countHeadline }}</strong>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"mostRecent\" class=\"cn-flow-card__headline-recent\">\n\t\t\t\t\t<SitemapOutline :size=\"14\" />\n\t\t\t\t\t<a\n\t\t\t\t\t\t:href=\"opUrl(mostRecent)\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener\">{{ opTitle(mostRecent) }}</a>\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-if=\"entityLabel(mostRecent)\"\n\t\t\t\t\t\tclass=\"cn-flow-card__headline-entity\">\n\t\t\t\t\t\t· {{ entityLabel(mostRecent) }}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</template>\n\n\t\t<!-- detail-page surface: compact list -->\n\t\t<template v-else>\n\t\t\t<div v-if=\"degraded\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"operations.length === 0\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<ul v-else class=\"cn-flow-card__list\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"op in displayedOperations\"\n\t\t\t\t\t:key=\"opKey(op)\"\n\t\t\t\t\tclass=\"cn-flow-card__row\"\n\t\t\t\t\t:class=\"{ 'cn-flow-card__row--disabled': isDisabled(op) }\">\n\t\t\t\t\t<div class=\"cn-flow-card__row-header\">\n\t\t\t\t\t\t<SitemapOutline :size=\"16\" class=\"cn-flow-card__row-icon\" />\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t:href=\"opUrl(op)\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noopener\"\n\t\t\t\t\t\t\tclass=\"cn-flow-card__title\">{{ opTitle(op) }}</a>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclass=\"cn-flow-card__enabled\"\n\t\t\t\t\t\t\t:class=\"enabledClass(op)\"\n\t\t\t\t\t\t\t:aria-label=\"enabledLabel(op)\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t<span v-if=\"rowMeta(op)\" class=\"cn-flow-card__subtitle\">{{ rowMeta(op) }}</span>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</template>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translatePlural as n, translate as t } from '@nextcloud/l10n'\nimport { NcLoadingIcon } from '@nextcloud/vue'\nimport SitemapOutline from 'vue-material-design-icons/SitemapOutline.vue'\nimport CnDetailCard from '../../../components/CnDetailCard/CnDetailCard.vue'\nimport { buildHeaders, prefixUrl } from '../../../utils/index.js'\n\nconst VALID_SURFACES = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity']\nconst COMPACT_LIMIT = 5\n\n/**\n * CnFlowCard — bespoke surface-aware widget for the `flow` integration.\n *\n * Renders Flow-aware metadata across all four surfaces. See the\n * file-level docblock for surface-by-surface behaviour.\n */\nexport default {\n\tname: 'CnFlowCard',\n\n\tcomponents: { CnDetailCard, NcLoadingIcon, SitemapOutline },\n\n\tprops: {\n\t\t/** Stable integration id (forwarded from the registry — always `'flow'`). */\n\t\tintegrationId: { type: String, default: 'flow' },\n\t\t/** OpenRegister register id (slug or uuid). */\n\t\tregister: { type: String, required: true },\n\t\t/** OpenRegister schema id (slug or uuid). */\n\t\tschema: { type: String, required: true },\n\t\t/** Parent object id. */\n\t\tobjectId: { type: String, required: true },\n\t\t/** Rendering surface (AD-19). */\n\t\tsurface: {\n\t\t\ttype: String,\n\t\t\tdefault: 'detail-page',\n\t\t\tvalidator: (s) => VALID_SURFACES.includes(s),\n\t\t},\n\n\t\t/** Optional single-entity reference (operation id). */\n\t\tvalue: { type: String, default: '' },\n\t\t/** Pre-translated card title. */\n\t\ttitle: { type: String, default: () => t('nextcloud-vue', 'Automation') },\n\t\t/** Optional Material Design Icon component. */\n\t\ticon: { type: Object, default: () => SitemapOutline },\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Whether the card body is collapsible. */\n\t\tcollapsible: { type: Boolean, default: true },\n\t\t/** Pre-translated empty-state label. */\n\t\temptyLabel: { type: String, default: () => t('nextcloud-vue', 'No automations linked yet') },\n\t\t/** Pre-translated unavailable label. */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'NC Flow is currently unavailable.') },\n\t\t/** URL of the NC Flow admin settings page. */\n\t\tflowSettingsUrl: { type: String, default: '/index.php/settings/admin/workflow' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\toperations: [],\n\t\t\tentity: null,\n\t\t\tloading: false,\n\t\t\tdegraded: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tcardTitle() {\n\t\t\treturn this.title || this.integrationId\n\t\t},\n\n\t\tcardIcon() {\n\t\t\treturn this.icon\n\t\t},\n\n\t\tdisplayedOperations() {\n\t\t\tif (this.surface === 'user-dashboard' || this.surface === 'app-dashboard') {\n\t\t\t\treturn this.operations.slice(0, COMPACT_LIMIT)\n\t\t\t}\n\t\t\treturn this.operations\n\t\t},\n\n\t\tactiveCount() {\n\t\t\treturn this.operations.reduce((sum, op) => sum + (this.isDisabled(op) ? 0 : 1), 0)\n\t\t},\n\n\t\tcountHeadline() {\n\t\t\tconst total = this.operations.length\n\t\t\tconst active = this.activeCount\n\t\t\tif (total === 0) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tif (active === total) {\n\t\t\t\treturn n('nextcloud-vue', '{count} automation', '{count} automations', total, { count: total })\n\t\t\t}\n\t\t\tconst totalFragment = n('nextcloud-vue', '{count} automation', '{count} automations', total, { count: total })\n\t\t\tconst activeFragment = n('nextcloud-vue', '{count} active', '{count} active', active, { count: active })\n\t\t\treturn `${totalFragment} · ${activeFragment}`\n\t\t},\n\n\t\tmostRecent() {\n\t\t\tif (this.operations.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\t// NC Flow operations don't carry a stable \"created\" field,\n\t\t\t// so we just use the natural list order — the provider\n\t\t\t// returns admin-scoped operations newest-first via the\n\t\t\t// Manager API.\n\t\t\treturn this.operations[0]\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: { immediate: true, handler() {\n\t\t\tthis.fetch()\n\t\t} },\n\n\t\tsurface() {\n\t\t\tthis.fetch()\n\t\t},\n\n\t\tvalue() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t}\n\t\t},\n\t},\n\n\tmethods: {\n\t\tbaseUrl() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/integrations/${this.integrationId}`\n\t\t},\n\n\t\topKey(op) {\n\t\t\treturn op.id ?? op.title ?? ''\n\t\t},\n\n\t\topTitle(op) {\n\t\t\treturn op.title || op.displayName || op.name || this.shortClass(op.class) || t('nextcloud-vue', 'Untitled automation')\n\t\t},\n\n\t\topUrl(op) {\n\t\t\treturn op.url || this.flowSettingsUrl\n\t\t},\n\n\t\tshortClass(className) {\n\t\t\tif (!className) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst parts = String(className).split('\\\\')\n\t\t\treturn parts[parts.length - 1] || className\n\t\t},\n\n\t\tentityLabel(op) {\n\t\t\tif (!op.entity) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn this.shortClass(op.entity)\n\t\t},\n\n\t\tisDisabled(op) {\n\t\t\tconst v = op.enabled ?? op.data?.enabled\n\t\t\tif (v === undefined || v === null) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn v === false || v === 0 || v === '0'\n\t\t},\n\n\t\tenabledLabel(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? t('nextcloud-vue', 'Disabled')\n\t\t\t\t: t('nextcloud-vue', 'Enabled')\n\t\t},\n\n\t\tenabledClass(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? 'cn-flow-card__enabled--off'\n\t\t\t\t: 'cn-flow-card__enabled--on'\n\t\t},\n\n\t\trowMeta(op) {\n\t\t\tconst parts = []\n\t\t\tconst entity = this.entityLabel(op)\n\t\t\tif (entity !== '') {\n\t\t\t\tparts.push(entity)\n\t\t\t}\n\t\t\tconst operation = op.operation || ''\n\t\t\tif (operation !== '') {\n\t\t\t\tparts.push(operation)\n\t\t\t}\n\t\t\tconst checks = this.checksCount(op)\n\t\t\tif (checks > 0) {\n\t\t\t\tparts.push(t('nextcloud-vue', '{n} conditions', { n: checks }))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\tchecksCount(op) {\n\t\t\tconst raw = op.checks ?? op.data?.checks ?? []\n\t\t\tif (Array.isArray(raw) === true) {\n\t\t\t\treturn raw.length\n\t\t\t}\n\t\t\treturn 0\n\t\t},\n\n\t\tchipSubtitle(op) {\n\t\t\treturn this.entityLabel(op) || this.opTitle(op)\n\t\t},\n\n\t\tfetch() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.fetchList()\n\t\t},\n\n\t\tasync fetchList() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tthis.operations = data.results || data.items || (Array.isArray(data) ? data : []) || []\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else if (response.status === 403) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = t('nextcloud-vue', 'Flow operations are only visible to administrators.')\n\t\t\t\t} else {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowCard] failed to fetch operations', err)\n\t\t\t\tthis.operations = []\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync fetchSingle() {\n\t\t\tif (!this.value || !this.register || !this.schema || !this.objectId) {\n\t\t\t\tthis.entity = null\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.baseUrl()}/${encodeURIComponent(this.value)}`), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tthis.entity = await response.json()\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.entity = null\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.entity = null\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowCard] failed to fetch single operation', err)\n\t\t\t\tthis.entity = null\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-flow-card__empty {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n\tpadding: 8px 0;\n}\n\n.cn-flow-card__headline {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n}\n\n.cn-flow-card__headline-line {\n\tfont-size: 1.1em;\n\tcolor: var(--color-main-text);\n}\n\n.cn-flow-card__headline-recent {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n\tfont-size: 0.9em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-flow-card__headline-recent a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\n.cn-flow-card__headline-recent a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-flow-card__headline-entity {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-card__chip {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 6px;\n\tpadding: 4px 8px;\n\tborder-radius: 12px;\n\tbackground: var(--color-background-hover);\n\tfont-size: 0.9em;\n\tmax-width: 100%;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n/* stylelint-disable-next-line no-descending-specificity */\n.cn-flow-card__chip a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\n.cn-flow-card__chip a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-flow-card__chip-enabled,\n.cn-flow-card__enabled {\n\twidth: 8px;\n\theight: 8px;\n\tborder-radius: 50%;\n\tflex-shrink: 0;\n}\n\n.cn-flow-card__enabled--on {\n\tbackground: var(--color-success, #46ba61);\n}\n\n.cn-flow-card__enabled--off {\n\tbackground: var(--color-text-maxcontrast);\n}\n\n.cn-flow-card__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-flow-card__row {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tpadding: 8px 0;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.cn-flow-card__row:last-child {\n\tborder-bottom: none;\n}\n\n.cn-flow-card__row--disabled {\n\topacity: 0.7;\n}\n\n.cn-flow-card__row-header {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-flow-card__row-icon {\n\tcolor: var(--color-text-maxcontrast);\n\tflex-shrink: 0;\n}\n\n.cn-flow-card__title {\n\tflex: 1;\n\tmin-width: 0;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\na.cn-flow-card__title:hover {\n\ttext-decoration: underline;\n}\n\n.cn-flow-card__subtitle {\n\tfont-size: 0.8em;\n\tcolor: var(--color-text-maxcontrast);\n\tpadding-left: 24px;\n}\n</style>\n"],"names":["CnDetailCard","t","n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnFlowCard.vue2.js","sources":["../../../../../src/integrations/builtin/flow/CnFlowCard.vue"],"sourcesContent":["<!--\n CnFlowCard — bespoke surface-aware widget for the `flow` (automation)\n integration.\n\n Replaces the generic CnIntegrationCard for the `flow` leaf. Branches\n on `surface` per AD-19:\n - user-dashboard / app-dashboard : headline \"N automations · M\n active\" + most-recent name with its entity binding.\n - detail-page : compact list of linked\n operations with entity / operation type / enabled indicator\n per row.\n - single-entity : chip with operation name + an\n enabled dot (referenceType: 'flow').\n\n Pulls rows from the same OR pluggable-integration sub-resource as\n CnFlowTab; for `single-entity` the optional `value` prop addresses a\n single operation by id (matching CnIntegrationCard's fetchSingle\n contract).\n\n See `openregister/openspec/changes/integration-flow/` for the spec\n delta and ADR-019 (registry mechanism), AD-19 (surface fallback).\n-->\n<template>\n\t<CnDetailCard :title=\"cardTitle\" :icon=\"cardIcon\" :collapsible=\"collapsible\">\n\t\t<NcLoadingIcon v-if=\"loading\" />\n\n\t\t<!-- single-entity surface: chip -->\n\t\t<template v-else-if=\"surface === 'single-entity'\">\n\t\t\t<span v-if=\"entity\" class=\"cn-flow-card__chip\" :title=\"chipSubtitle(entity)\">\n\t\t\t\t<SitemapOutline :size=\"14\" />\n\t\t\t\t<a\n\t\t\t\t\t:href=\"opUrl(entity)\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener\">{{ opTitle(entity) }}</a>\n\t\t\t\t<span\n\t\t\t\t\tclass=\"cn-flow-card__chip-enabled\"\n\t\t\t\t\t:class=\"enabledClass(entity)\" />\n\t\t\t</span>\n\t\t\t<span v-else class=\"cn-flow-card__empty\">{{ emptyLabel }}</span>\n\t\t</template>\n\n\t\t<!-- dashboard surfaces: headline + most-recent -->\n\t\t<template v-else-if=\"surface === 'user-dashboard' || surface === 'app-dashboard'\">\n\t\t\t<div v-if=\"degraded\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"operations.length === 0\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<div v-else class=\"cn-flow-card__headline\">\n\t\t\t\t<div class=\"cn-flow-card__headline-line\">\n\t\t\t\t\t<strong>{{ countHeadline }}</strong>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"mostRecent\" class=\"cn-flow-card__headline-recent\">\n\t\t\t\t\t<SitemapOutline :size=\"14\" />\n\t\t\t\t\t<a\n\t\t\t\t\t\t:href=\"opUrl(mostRecent)\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener\">{{ opTitle(mostRecent) }}</a>\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-if=\"entityLabel(mostRecent)\"\n\t\t\t\t\t\tclass=\"cn-flow-card__headline-entity\">\n\t\t\t\t\t\t· {{ entityLabel(mostRecent) }}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</template>\n\n\t\t<!-- detail-page surface: compact list -->\n\t\t<template v-else>\n\t\t\t<div v-if=\"degraded\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"operations.length === 0\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<ul v-else class=\"cn-flow-card__list\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"op in displayedOperations\"\n\t\t\t\t\t:key=\"opKey(op)\"\n\t\t\t\t\tclass=\"cn-flow-card__row\"\n\t\t\t\t\t:class=\"{ 'cn-flow-card__row--disabled': isDisabled(op) }\">\n\t\t\t\t\t<div class=\"cn-flow-card__row-header\">\n\t\t\t\t\t\t<SitemapOutline :size=\"16\" class=\"cn-flow-card__row-icon\" />\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t:href=\"opUrl(op)\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noopener\"\n\t\t\t\t\t\t\tclass=\"cn-flow-card__title\">{{ opTitle(op) }}</a>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclass=\"cn-flow-card__enabled\"\n\t\t\t\t\t\t\t:class=\"enabledClass(op)\"\n\t\t\t\t\t\t\t:aria-label=\"enabledLabel(op)\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t<span v-if=\"rowMeta(op)\" class=\"cn-flow-card__subtitle\">{{ rowMeta(op) }}</span>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</template>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translatePlural as n, translate as t } from '@nextcloud/l10n'\nimport { NcLoadingIcon } from '@nextcloud/vue'\nimport SitemapOutline from 'vue-material-design-icons/SitemapOutline.vue'\nimport CnDetailCard from '../../../components/CnDetailCard/CnDetailCard.vue'\nimport { buildHeaders, prefixUrl, safeHref } from '../../../utils/index.js'\n\nconst VALID_SURFACES = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity']\nconst COMPACT_LIMIT = 5\n\n/**\n * CnFlowCard — bespoke surface-aware widget for the `flow` integration.\n *\n * Renders Flow-aware metadata across all four surfaces. See the\n * file-level docblock for surface-by-surface behaviour.\n */\nexport default {\n\tname: 'CnFlowCard',\n\n\tcomponents: { CnDetailCard, NcLoadingIcon, SitemapOutline },\n\n\tprops: {\n\t\t/** Stable integration id (forwarded from the registry — always `'flow'`). */\n\t\tintegrationId: { type: String, default: 'flow' },\n\t\t/** OpenRegister register id (slug or uuid). */\n\t\tregister: { type: String, required: true },\n\t\t/** OpenRegister schema id (slug or uuid). */\n\t\tschema: { type: String, required: true },\n\t\t/** Parent object id. */\n\t\tobjectId: { type: String, required: true },\n\t\t/** Rendering surface (AD-19). */\n\t\tsurface: {\n\t\t\ttype: String,\n\t\t\tdefault: 'detail-page',\n\t\t\tvalidator: (s) => VALID_SURFACES.includes(s),\n\t\t},\n\n\t\t/** Optional single-entity reference (operation id). */\n\t\tvalue: { type: String, default: '' },\n\t\t/** Pre-translated card title. */\n\t\ttitle: { type: String, default: () => t('nextcloud-vue', 'Automation') },\n\t\t/** Optional Material Design Icon component. */\n\t\ticon: { type: Object, default: () => SitemapOutline },\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Whether the card body is collapsible. */\n\t\tcollapsible: { type: Boolean, default: true },\n\t\t/** Pre-translated empty-state label. */\n\t\temptyLabel: { type: String, default: () => t('nextcloud-vue', 'No automations linked yet') },\n\t\t/** Pre-translated unavailable label. */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'NC Flow is currently unavailable.') },\n\t\t/** URL of the NC Flow admin settings page. */\n\t\tflowSettingsUrl: { type: String, default: '/index.php/settings/admin/workflow' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\toperations: [],\n\t\t\tentity: null,\n\t\t\tloading: false,\n\t\t\tdegraded: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tcardTitle() {\n\t\t\treturn this.title || this.integrationId\n\t\t},\n\n\t\tcardIcon() {\n\t\t\treturn this.icon\n\t\t},\n\n\t\tdisplayedOperations() {\n\t\t\tif (this.surface === 'user-dashboard' || this.surface === 'app-dashboard') {\n\t\t\t\treturn this.operations.slice(0, COMPACT_LIMIT)\n\t\t\t}\n\t\t\treturn this.operations\n\t\t},\n\n\t\tactiveCount() {\n\t\t\treturn this.operations.reduce((sum, op) => sum + (this.isDisabled(op) ? 0 : 1), 0)\n\t\t},\n\n\t\tcountHeadline() {\n\t\t\tconst total = this.operations.length\n\t\t\tconst active = this.activeCount\n\t\t\tif (total === 0) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tif (active === total) {\n\t\t\t\treturn n('nextcloud-vue', '{count} automation', '{count} automations', total, { count: total })\n\t\t\t}\n\t\t\tconst totalFragment = n('nextcloud-vue', '{count} automation', '{count} automations', total, { count: total })\n\t\t\tconst activeFragment = n('nextcloud-vue', '{count} active', '{count} active', active, { count: active })\n\t\t\treturn `${totalFragment} · ${activeFragment}`\n\t\t},\n\n\t\tmostRecent() {\n\t\t\tif (this.operations.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\t// NC Flow operations don't carry a stable \"created\" field,\n\t\t\t// so we just use the natural list order — the provider\n\t\t\t// returns admin-scoped operations newest-first via the\n\t\t\t// Manager API.\n\t\t\treturn this.operations[0]\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: { immediate: true, handler() {\n\t\t\tthis.fetch()\n\t\t} },\n\n\t\tsurface() {\n\t\t\tthis.fetch()\n\t\t},\n\n\t\tvalue() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t}\n\t\t},\n\t},\n\n\tmethods: {\n\t\tbaseUrl() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/integrations/${this.integrationId}`\n\t\t},\n\n\t\topKey(op) {\n\t\t\treturn op.id ?? op.title ?? ''\n\t\t},\n\n\t\topTitle(op) {\n\t\t\treturn op.title || op.displayName || op.name || this.shortClass(op.class) || t('nextcloud-vue', 'Untitled automation')\n\t\t},\n\n\t\topUrl(op) {\n\t\t\treturn op.url && safeHref(op.url) !== '#' ? op.url : this.flowSettingsUrl\n\t\t},\n\n\t\tshortClass(className) {\n\t\t\tif (!className) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst parts = String(className).split('\\\\')\n\t\t\treturn parts[parts.length - 1] || className\n\t\t},\n\n\t\tentityLabel(op) {\n\t\t\tif (!op.entity) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn this.shortClass(op.entity)\n\t\t},\n\n\t\tisDisabled(op) {\n\t\t\tconst v = op.enabled ?? op.data?.enabled\n\t\t\tif (v === undefined || v === null) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn v === false || v === 0 || v === '0'\n\t\t},\n\n\t\tenabledLabel(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? t('nextcloud-vue', 'Disabled')\n\t\t\t\t: t('nextcloud-vue', 'Enabled')\n\t\t},\n\n\t\tenabledClass(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? 'cn-flow-card__enabled--off'\n\t\t\t\t: 'cn-flow-card__enabled--on'\n\t\t},\n\n\t\trowMeta(op) {\n\t\t\tconst parts = []\n\t\t\tconst entity = this.entityLabel(op)\n\t\t\tif (entity !== '') {\n\t\t\t\tparts.push(entity)\n\t\t\t}\n\t\t\tconst operation = op.operation || ''\n\t\t\tif (operation !== '') {\n\t\t\t\tparts.push(operation)\n\t\t\t}\n\t\t\tconst checks = this.checksCount(op)\n\t\t\tif (checks > 0) {\n\t\t\t\tparts.push(t('nextcloud-vue', '{n} conditions', { n: checks }))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\tchecksCount(op) {\n\t\t\tconst raw = op.checks ?? op.data?.checks ?? []\n\t\t\tif (Array.isArray(raw) === true) {\n\t\t\t\treturn raw.length\n\t\t\t}\n\t\t\treturn 0\n\t\t},\n\n\t\tchipSubtitle(op) {\n\t\t\treturn this.entityLabel(op) || this.opTitle(op)\n\t\t},\n\n\t\tfetch() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.fetchList()\n\t\t},\n\n\t\tasync fetchList() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tthis.operations = data.results || data.items || (Array.isArray(data) ? data : []) || []\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else if (response.status === 403) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = t('nextcloud-vue', 'Flow operations are only visible to administrators.')\n\t\t\t\t} else {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowCard] failed to fetch operations', err)\n\t\t\t\tthis.operations = []\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync fetchSingle() {\n\t\t\tif (!this.value || !this.register || !this.schema || !this.objectId) {\n\t\t\t\tthis.entity = null\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.baseUrl()}/${encodeURIComponent(this.value)}`), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tthis.entity = await response.json()\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.entity = null\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.entity = null\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowCard] failed to fetch single operation', err)\n\t\t\t\tthis.entity = null\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-flow-card__empty {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n\tpadding: 8px 0;\n}\n\n.cn-flow-card__headline {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n}\n\n.cn-flow-card__headline-line {\n\tfont-size: 1.1em;\n\tcolor: var(--color-main-text);\n}\n\n.cn-flow-card__headline-recent {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n\tfont-size: 0.9em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-flow-card__headline-recent a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\n.cn-flow-card__headline-recent a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-flow-card__headline-entity {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-card__chip {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 6px;\n\tpadding: 4px 8px;\n\tborder-radius: 12px;\n\tbackground: var(--color-background-hover);\n\tfont-size: 0.9em;\n\tmax-width: 100%;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n/* stylelint-disable-next-line no-descending-specificity */\n.cn-flow-card__chip a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\n.cn-flow-card__chip a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-flow-card__chip-enabled,\n.cn-flow-card__enabled {\n\twidth: 8px;\n\theight: 8px;\n\tborder-radius: 50%;\n\tflex-shrink: 0;\n}\n\n.cn-flow-card__enabled--on {\n\tbackground: var(--color-success, #46ba61);\n}\n\n.cn-flow-card__enabled--off {\n\tbackground: var(--color-text-maxcontrast);\n}\n\n.cn-flow-card__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-flow-card__row {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tpadding: 8px 0;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.cn-flow-card__row:last-child {\n\tborder-bottom: none;\n}\n\n.cn-flow-card__row--disabled {\n\topacity: 0.7;\n}\n\n.cn-flow-card__row-header {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-flow-card__row-icon {\n\tcolor: var(--color-text-maxcontrast);\n\tflex-shrink: 0;\n}\n\n.cn-flow-card__title {\n\tflex: 1;\n\tmin-width: 0;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\na.cn-flow-card__title:hover {\n\ttext-decoration: underline;\n}\n\n.cn-flow-card__subtitle {\n\tfont-size: 0.8em;\n\tcolor: var(--color-text-maxcontrast);\n\tpadding-left: 24px;\n}\n</style>\n"],"names":["CnDetailCard","t","n"],"mappings":";;;;;;;AA4GA,MAAM,cAAe,GAAE,CAAC,gBAAgB,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAA;AACzF,MAAM,gBAAgB,EAAA;;AAEtB;;AAEC;;;;AAID,aAAe;AACd,CAAA,IAAI,EAAE,YAAY;;CAElB,UAAU,EAAE,gBAAEA,UAAY,EAAE,aAAa,EAAE,cAAa,EAAG;;AAE3D,CAAA,KAAK,EAAE;AACN;AACA,EAAA,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ;AAChD;AACA,EAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;AAC1C;AACA,EAAA,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;AACxC;AACA,EAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;AAE1C,EAAA,OAAO,EAAE;GACR,IAAI,EAAE,MAAM;AACZ,GAAA,OAAO,EAAE,aAAa;AACtB,GAAA,SAAS,EAAE,CAAC,CAAC,KAAK,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;GAC5C;;;AAGD,EAAA,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAC,EAAG;;AAEpC,EAAA,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAMC,SAAC,CAAC,eAAe,EAAE,YAAY,GAAG;AACxE;AACA,EAAA,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gBAAgB;AACrD;EACA,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAuB,EAAG;AAC5D;AACA,EAAA,WAAW,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM;AAC7C;AACA,EAAA,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAMA,SAAC,CAAC,eAAe,EAAE,2BAA2B,GAAG;AAC5F;AACA,EAAA,gBAAgB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAMA,SAAC,CAAC,eAAe,EAAE,mCAAmC,GAAG;AAC1G;AACA,EAAA,eAAe,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sCAAsC;EAChF;;AAED,CAAA,IAAI,GAAG;AACN,EAAA,OAAO;GACN,UAAU,EAAE,EAAE;GACd,MAAM,EAAE,IAAI;GACZ,OAAO,EAAE,KAAK;GACd,QAAQ,EAAE,EAAE;AACb,GAAA;EACA;;AAED,CAAA,QAAQ,EAAE;EACT,SAAS,GAAG;AACX,GAAA,OAAO,IAAI,CAAC,KAAM,IAAG,IAAI,CAAC,aAAY;GACtC;;EAED,QAAQ,GAAG;AACV,GAAA,OAAO,IAAI,CAAC,IAAG;GACf;;AAED,EAAA,mBAAmB,GAAG;AACrB,GAAA,IAAI,IAAI,CAAC,OAAQ,KAAI,gBAAiB,IAAG,IAAI,CAAC,YAAY,eAAe,EAAE;AAC1E,IAAA,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAA;AAC9C,IAAA;AACA,GAAA,OAAO,IAAI,CAAC,UAAS;GACrB;;EAED,WAAW,GAAG;AACb,GAAA,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,CAAE,GAAE,CAAE,GAAE,CAAC,CAAC,EAAE,CAAC,CAAA;GACjF;;AAED,EAAA,aAAa,GAAG;AACf,GAAA,MAAM,KAAM,GAAE,IAAI,CAAC,UAAU,CAAC,OAAK;GACnC,MAAM,MAAK,GAAI,IAAI,CAAC,YAAU;GAC9B,IAAI,KAAI,KAAM,CAAC,EAAE;AAChB,IAAA,OAAO,EAAC;AACT,IAAA;AACA,GAAA,IAAI,MAAK,KAAM,KAAK,EAAE;AACrB,IAAA,OAAOC,eAAC,CAAC,eAAe,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,CAAA;AAC/F,IAAA;GACA,MAAM,gBAAgBA,eAAC,CAAC,eAAe,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAI,EAAG,EAAA;AAC7G,GAAA,MAAM,cAAa,GAAIA,eAAC,CAAC,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAA;AACvG,GAAA,OAAO,CAAC,EAAE,aAAa,IAAI,EAAE,cAAc,CAAC,CAAA;GAC5C;;EAED,UAAU,GAAG;AACZ,GAAA,IAAI,IAAI,CAAC,UAAU,CAAC,MAAK,KAAM,CAAC,EAAE;AACjC,IAAA,OAAO,IAAG;AACX,IAAA;;AAEA;;;GAGA,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAA;GACxB;EACD;;AAED,CAAA,KAAK,EAAE;AACN,EAAA,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,GAAG;GACtC,IAAI,CAAC,KAAK,GAAC;AACZ,GAAA,EAAG;;AAEH,EAAA,OAAO,GAAG;GACT,IAAI,CAAC,KAAK,GAAC;GACX;;AAED,EAAA,KAAK,GAAG;AACP,GAAA,IAAI,IAAI,CAAC,YAAY,eAAe,EAAE;AACrC,IAAA,IAAI,CAAC,WAAW,GAAC;AAClB,IAAA;GACA;EACD;;AAED,CAAA,OAAO,EAAE;AACR,EAAA,OAAO,GAAG;GACT,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,IAAI,CAAC,aAAa,CAAC,CAAA;GACnH;;AAED,EAAA,KAAK,CAAC,EAAE,EAAE;GACT,OAAO,EAAE,CAAC,EAAG,IAAG,EAAE,CAAC,KAAI,IAAK,EAAC;GAC7B;;EAED,OAAO,CAAC,EAAE,EAAE;GACX,OAAO,EAAE,CAAC,KAAM,IAAG,EAAE,CAAC,eAAe,EAAE,CAAC,IAAG,IAAK,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAA,IAAKD,SAAC,CAAC,eAAe,EAAE,qBAAqB,CAAA;GACrH;;AAED,EAAA,KAAK,CAAC,EAAE,EAAE;AACT,GAAA,OAAO,EAAE,CAAC,GAAI,IAAG,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAE,KAAI,GAAI,GAAE,EAAE,CAAC,GAAE,GAAI,IAAI,CAAC,eAAc;GACxE;;AAED,EAAA,UAAU,CAAC,SAAS,EAAE;AACrB,GAAA,IAAI,CAAC,SAAS,EAAE;AACf,IAAA,OAAO,EAAC;AACT,IAAA;AACA,GAAA,MAAM,KAAM,GAAE,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,IAAI,EAAA;AAC1C,GAAA,OAAO,KAAK,CAAC,KAAK,CAAC,MAAO,GAAE,CAAC,CAAE,IAAG,SAAQ;GAC1C;;AAED,EAAA,WAAW,CAAC,EAAE,EAAE;AACf,GAAA,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE;AACf,IAAA,OAAO,EAAC;AACT,IAAA;AACA,GAAA,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,MAAM,CAAA;GAChC;;AAED,EAAA,UAAU,CAAC,EAAE,EAAE;AACd,GAAA,MAAM,IAAI,EAAE,CAAC,OAAM,IAAK,EAAE,CAAC,IAAI,EAAE,QAAM;GACvC,IAAI,CAAA,KAAM,SAAQ,IAAK,CAAE,KAAI,IAAI,EAAE;IAClC,OAAO,KAAI;AACZ,IAAA;AACA,GAAA,OAAO,CAAA,KAAM,KAAI,IAAK,CAAE,KAAI,CAAE,IAAG,CAAA,KAAM,GAAE;GACzC;;AAED,EAAA,YAAY,CAAC,EAAE,EAAE;AAChB,GAAA,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,CAAA,KAAM,IAAG;MAC/BA,SAAC,CAAC,eAAe,EAAE,UAAU,CAAA;MAC7BA,SAAC,CAAC,eAAe,EAAE,SAAS,CAAA;GAC/B;;AAED,EAAA,YAAY,CAAC,EAAE,EAAE;AAChB,GAAA,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,CAAA,KAAM,IAAG;MAC/B,4BAA2B;MAC3B,2BAA0B;GAC7B;;EAED,OAAO,CAAC,EAAE,EAAE;GACX,MAAM,KAAM,GAAE,GAAC;AACf,GAAA,MAAM,MAAK,GAAI,IAAI,CAAC,WAAW,CAAC,EAAE,EAAA;AAClC,GAAA,IAAI,MAAK,KAAM,EAAE,EAAE;AAClB,IAAA,KAAK,CAAC,IAAI,CAAC,MAAM,EAAA;AAClB,IAAA;AACA,GAAA,MAAM,SAAU,GAAE,EAAE,CAAC,SAAQ,IAAK,GAAC;AACnC,GAAA,IAAI,cAAc,EAAE,EAAE;AACrB,IAAA,KAAK,CAAC,IAAI,CAAC,SAAS,EAAA;AACrB,IAAA;AACA,GAAA,MAAM,MAAK,GAAI,IAAI,CAAC,WAAW,CAAC,EAAE,EAAA;GAClC,IAAI,MAAK,GAAI,CAAC,EAAE;IACf,KAAK,CAAC,IAAI,CAACA,SAAC,CAAC,eAAe,EAAE,gBAAgB,EAAE,EAAE,CAAC,EAAE,MAAO,EAAC,CAAC,EAAA;AAC/D,IAAA;AACA,GAAA,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAA;GACvB;;AAED,EAAA,WAAW,CAAC,EAAE,EAAE;AACf,GAAA,MAAM,GAAI,GAAE,EAAE,CAAC,MAAO,IAAG,EAAE,CAAC,IAAI,EAAE,MAAO,IAAG,GAAC;GAC7C,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAE,KAAI,IAAI,EAAE;AAChC,IAAA,OAAO,GAAG,CAAC,MAAK;AACjB,IAAA;AACA,GAAA,OAAO,CAAA;GACP;;AAED,EAAA,YAAY,CAAC,EAAE,EAAE;AAChB,GAAA,OAAO,IAAI,CAAC,WAAW,CAAC,EAAE,CAAA,IAAK,IAAI,CAAC,OAAO,CAAC,EAAE,CAAA;GAC9C;;AAED,EAAA,KAAK,GAAG;AACP,GAAA,IAAI,IAAI,CAAC,YAAY,eAAe,EAAE;AACrC,IAAA,IAAI,CAAC,WAAW,GAAC;IACjB,MAAK;AACN,IAAA;AACA,GAAA,IAAI,CAAC,SAAS,GAAC;GACf;;AAED,EAAA,MAAM,SAAS,GAAG;GACjB,IAAI,CAAC,IAAI,CAAC,QAAO,IAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE;IACrD,MAAK;AACN,IAAA;AACA,GAAA,IAAI,CAAC,OAAM,GAAI,KAAG;AAClB,GAAA,IAAI,CAAC,QAAO,GAAI,GAAC;AACjB,GAAA,IAAI;AACH,IAAA,MAAM,QAAO,GAAI,MAAM,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,YAAY,IAAI,EAAA;AACnF,IAAA,IAAI,QAAQ,CAAC,EAAE,EAAE;KAChB,MAAM,IAAK,GAAE,MAAM,QAAQ,CAAC,IAAI,GAAC;AACjC,KAAA,IAAI,CAAC,UAAS,GAAI,IAAI,CAAC,OAAQ,IAAG,IAAI,CAAC,KAAM,KAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAA,GAAI,IAAG,GAAI,EAAE,CAAE,IAAG,GAAC;AACvF,KAAA,MAAO,IAAI,QAAQ,CAAC,MAAK,KAAM,GAAG,EAAE;AACnC,KAAA,IAAI,CAAC,UAAS,GAAI,GAAC;AACnB,KAAA,IAAI,CAAC,QAAS,GAAE,IAAI,CAAC,iBAAe;AACrC,KAAA,MAAO,IAAI,QAAQ,CAAC,MAAK,KAAM,GAAG,EAAE;AACnC,KAAA,IAAI,CAAC,UAAS,GAAI,GAAC;AACnB,KAAA,IAAI,CAAC,QAAS,GAAEA,SAAC,CAAC,eAAe,EAAE,qDAAqD,EAAA;KACvF,MAAK;AACN,KAAA,IAAI,CAAC,UAAS,GAAI,GAAC;AACpB,KAAA;IACC,CAAA,OAAO,GAAG,EAAE;AACb;IACA,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,GAAG,EAAA;AAC5D,IAAA,IAAI,CAAC,UAAS,GAAI,GAAC;AACpB,IAAA,SAAU;AACT,IAAA,IAAI,CAAC,OAAQ,GAAE,MAAI;AACpB,IAAA;GACA;;AAED,EAAA,MAAM,WAAW,GAAG;GACnB,IAAI,CAAC,IAAI,CAAC,KAAI,IAAK,CAAC,IAAI,CAAC,QAAO,IAAK,CAAC,IAAI,CAAC,MAAK,IAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;AACpE,IAAA,IAAI,CAAC,MAAK,GAAI,KAAG;IACjB,MAAK;AACN,IAAA;AACA,GAAA,IAAI,CAAC,OAAM,GAAI,KAAG;AAClB,GAAA,IAAI,CAAC,QAAO,GAAI,GAAC;AACjB,GAAA,IAAI;IACH,MAAM,QAAO,GAAI,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,YAAY,EAAC,EAAG,EAAA;AAC1H,IAAA,IAAI,QAAQ,CAAC,EAAE,EAAE;AAChB,KAAA,IAAI,CAAC,MAAK,GAAI,MAAM,QAAQ,CAAC,IAAI,GAAC;AACnC,KAAA,MAAO,IAAI,QAAQ,CAAC,MAAK,KAAM,GAAG,EAAE;AACnC,KAAA,IAAI,CAAC,MAAK,GAAI,KAAG;AACjB,KAAA,IAAI,CAAC,QAAS,GAAE,IAAI,CAAC,iBAAe;KACnC,MAAK;AACN,KAAA,IAAI,CAAC,MAAK,GAAI,KAAG;AAClB,KAAA;IACC,CAAA,OAAO,GAAG,EAAE;AACb;IACA,OAAO,CAAC,KAAK,CAAC,+CAA+C,EAAE,GAAG,EAAA;AAClE,IAAA,IAAI,CAAC,MAAK,GAAI,KAAG;AAClB,IAAA,SAAU;AACT,IAAA,IAAI,CAAC,OAAQ,GAAE,MAAI;AACpB,IAAA;GACA;EACD;AACF;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnFlowCard.vue3.js","sources":["../../../../../src/integrations/builtin/flow/CnFlowCard.vue?vue&type=template&id=3dfce3f2&lang.js"],"sourcesContent":["<!--\n CnFlowCard — bespoke surface-aware widget for the `flow` (automation)\n integration.\n\n Replaces the generic CnIntegrationCard for the `flow` leaf. Branches\n on `surface` per AD-19:\n - user-dashboard / app-dashboard : headline \"N automations · M\n active\" + most-recent name with its entity binding.\n - detail-page : compact list of linked\n operations with entity / operation type / enabled indicator\n per row.\n - single-entity : chip with operation name + an\n enabled dot (referenceType: 'flow').\n\n Pulls rows from the same OR pluggable-integration sub-resource as\n CnFlowTab; for `single-entity` the optional `value` prop addresses a\n single operation by id (matching CnIntegrationCard's fetchSingle\n contract).\n\n See `openregister/openspec/changes/integration-flow/` for the spec\n delta and ADR-019 (registry mechanism), AD-19 (surface fallback).\n-->\n<template>\n\t<CnDetailCard :title=\"cardTitle\" :icon=\"cardIcon\" :collapsible=\"collapsible\">\n\t\t<NcLoadingIcon v-if=\"loading\" />\n\n\t\t<!-- single-entity surface: chip -->\n\t\t<template v-else-if=\"surface === 'single-entity'\">\n\t\t\t<span v-if=\"entity\" class=\"cn-flow-card__chip\" :title=\"chipSubtitle(entity)\">\n\t\t\t\t<SitemapOutline :size=\"14\" />\n\t\t\t\t<a\n\t\t\t\t\t:href=\"opUrl(entity)\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener\">{{ opTitle(entity) }}</a>\n\t\t\t\t<span\n\t\t\t\t\tclass=\"cn-flow-card__chip-enabled\"\n\t\t\t\t\t:class=\"enabledClass(entity)\" />\n\t\t\t</span>\n\t\t\t<span v-else class=\"cn-flow-card__empty\">{{ emptyLabel }}</span>\n\t\t</template>\n\n\t\t<!-- dashboard surfaces: headline + most-recent -->\n\t\t<template v-else-if=\"surface === 'user-dashboard' || surface === 'app-dashboard'\">\n\t\t\t<div v-if=\"degraded\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"operations.length === 0\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<div v-else class=\"cn-flow-card__headline\">\n\t\t\t\t<div class=\"cn-flow-card__headline-line\">\n\t\t\t\t\t<strong>{{ countHeadline }}</strong>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"mostRecent\" class=\"cn-flow-card__headline-recent\">\n\t\t\t\t\t<SitemapOutline :size=\"14\" />\n\t\t\t\t\t<a\n\t\t\t\t\t\t:href=\"opUrl(mostRecent)\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener\">{{ opTitle(mostRecent) }}</a>\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-if=\"entityLabel(mostRecent)\"\n\t\t\t\t\t\tclass=\"cn-flow-card__headline-entity\">\n\t\t\t\t\t\t· {{ entityLabel(mostRecent) }}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</template>\n\n\t\t<!-- detail-page surface: compact list -->\n\t\t<template v-else>\n\t\t\t<div v-if=\"degraded\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"operations.length === 0\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<ul v-else class=\"cn-flow-card__list\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"op in displayedOperations\"\n\t\t\t\t\t:key=\"opKey(op)\"\n\t\t\t\t\tclass=\"cn-flow-card__row\"\n\t\t\t\t\t:class=\"{ 'cn-flow-card__row--disabled': isDisabled(op) }\">\n\t\t\t\t\t<div class=\"cn-flow-card__row-header\">\n\t\t\t\t\t\t<SitemapOutline :size=\"16\" class=\"cn-flow-card__row-icon\" />\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t:href=\"opUrl(op)\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noopener\"\n\t\t\t\t\t\t\tclass=\"cn-flow-card__title\">{{ opTitle(op) }}</a>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclass=\"cn-flow-card__enabled\"\n\t\t\t\t\t\t\t:class=\"enabledClass(op)\"\n\t\t\t\t\t\t\t:aria-label=\"enabledLabel(op)\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t<span v-if=\"rowMeta(op)\" class=\"cn-flow-card__subtitle\">{{ rowMeta(op) }}</span>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</template>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translatePlural as n, translate as t } from '@nextcloud/l10n'\nimport { NcLoadingIcon } from '@nextcloud/vue'\nimport SitemapOutline from 'vue-material-design-icons/SitemapOutline.vue'\nimport CnDetailCard from '../../../components/CnDetailCard/CnDetailCard.vue'\nimport { buildHeaders, prefixUrl } from '../../../utils/index.js'\n\nconst VALID_SURFACES = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity']\nconst COMPACT_LIMIT = 5\n\n/**\n * CnFlowCard — bespoke surface-aware widget for the `flow` integration.\n *\n * Renders Flow-aware metadata across all four surfaces. See the\n * file-level docblock for surface-by-surface behaviour.\n */\nexport default {\n\tname: 'CnFlowCard',\n\n\tcomponents: { CnDetailCard, NcLoadingIcon, SitemapOutline },\n\n\tprops: {\n\t\t/** Stable integration id (forwarded from the registry — always `'flow'`). */\n\t\tintegrationId: { type: String, default: 'flow' },\n\t\t/** OpenRegister register id (slug or uuid). */\n\t\tregister: { type: String, required: true },\n\t\t/** OpenRegister schema id (slug or uuid). */\n\t\tschema: { type: String, required: true },\n\t\t/** Parent object id. */\n\t\tobjectId: { type: String, required: true },\n\t\t/** Rendering surface (AD-19). */\n\t\tsurface: {\n\t\t\ttype: String,\n\t\t\tdefault: 'detail-page',\n\t\t\tvalidator: (s) => VALID_SURFACES.includes(s),\n\t\t},\n\n\t\t/** Optional single-entity reference (operation id). */\n\t\tvalue: { type: String, default: '' },\n\t\t/** Pre-translated card title. */\n\t\ttitle: { type: String, default: () => t('nextcloud-vue', 'Automation') },\n\t\t/** Optional Material Design Icon component. */\n\t\ticon: { type: Object, default: () => SitemapOutline },\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Whether the card body is collapsible. */\n\t\tcollapsible: { type: Boolean, default: true },\n\t\t/** Pre-translated empty-state label. */\n\t\temptyLabel: { type: String, default: () => t('nextcloud-vue', 'No automations linked yet') },\n\t\t/** Pre-translated unavailable label. */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'NC Flow is currently unavailable.') },\n\t\t/** URL of the NC Flow admin settings page. */\n\t\tflowSettingsUrl: { type: String, default: '/index.php/settings/admin/workflow' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\toperations: [],\n\t\t\tentity: null,\n\t\t\tloading: false,\n\t\t\tdegraded: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tcardTitle() {\n\t\t\treturn this.title || this.integrationId\n\t\t},\n\n\t\tcardIcon() {\n\t\t\treturn this.icon\n\t\t},\n\n\t\tdisplayedOperations() {\n\t\t\tif (this.surface === 'user-dashboard' || this.surface === 'app-dashboard') {\n\t\t\t\treturn this.operations.slice(0, COMPACT_LIMIT)\n\t\t\t}\n\t\t\treturn this.operations\n\t\t},\n\n\t\tactiveCount() {\n\t\t\treturn this.operations.reduce((sum, op) => sum + (this.isDisabled(op) ? 0 : 1), 0)\n\t\t},\n\n\t\tcountHeadline() {\n\t\t\tconst total = this.operations.length\n\t\t\tconst active = this.activeCount\n\t\t\tif (total === 0) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tif (active === total) {\n\t\t\t\treturn n('nextcloud-vue', '{count} automation', '{count} automations', total, { count: total })\n\t\t\t}\n\t\t\tconst totalFragment = n('nextcloud-vue', '{count} automation', '{count} automations', total, { count: total })\n\t\t\tconst activeFragment = n('nextcloud-vue', '{count} active', '{count} active', active, { count: active })\n\t\t\treturn `${totalFragment} · ${activeFragment}`\n\t\t},\n\n\t\tmostRecent() {\n\t\t\tif (this.operations.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\t// NC Flow operations don't carry a stable \"created\" field,\n\t\t\t// so we just use the natural list order — the provider\n\t\t\t// returns admin-scoped operations newest-first via the\n\t\t\t// Manager API.\n\t\t\treturn this.operations[0]\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: { immediate: true, handler() {\n\t\t\tthis.fetch()\n\t\t} },\n\n\t\tsurface() {\n\t\t\tthis.fetch()\n\t\t},\n\n\t\tvalue() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t}\n\t\t},\n\t},\n\n\tmethods: {\n\t\tbaseUrl() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/integrations/${this.integrationId}`\n\t\t},\n\n\t\topKey(op) {\n\t\t\treturn op.id ?? op.title ?? ''\n\t\t},\n\n\t\topTitle(op) {\n\t\t\treturn op.title || op.displayName || op.name || this.shortClass(op.class) || t('nextcloud-vue', 'Untitled automation')\n\t\t},\n\n\t\topUrl(op) {\n\t\t\treturn op.url || this.flowSettingsUrl\n\t\t},\n\n\t\tshortClass(className) {\n\t\t\tif (!className) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst parts = String(className).split('\\\\')\n\t\t\treturn parts[parts.length - 1] || className\n\t\t},\n\n\t\tentityLabel(op) {\n\t\t\tif (!op.entity) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn this.shortClass(op.entity)\n\t\t},\n\n\t\tisDisabled(op) {\n\t\t\tconst v = op.enabled ?? op.data?.enabled\n\t\t\tif (v === undefined || v === null) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn v === false || v === 0 || v === '0'\n\t\t},\n\n\t\tenabledLabel(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? t('nextcloud-vue', 'Disabled')\n\t\t\t\t: t('nextcloud-vue', 'Enabled')\n\t\t},\n\n\t\tenabledClass(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? 'cn-flow-card__enabled--off'\n\t\t\t\t: 'cn-flow-card__enabled--on'\n\t\t},\n\n\t\trowMeta(op) {\n\t\t\tconst parts = []\n\t\t\tconst entity = this.entityLabel(op)\n\t\t\tif (entity !== '') {\n\t\t\t\tparts.push(entity)\n\t\t\t}\n\t\t\tconst operation = op.operation || ''\n\t\t\tif (operation !== '') {\n\t\t\t\tparts.push(operation)\n\t\t\t}\n\t\t\tconst checks = this.checksCount(op)\n\t\t\tif (checks > 0) {\n\t\t\t\tparts.push(t('nextcloud-vue', '{n} conditions', { n: checks }))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\tchecksCount(op) {\n\t\t\tconst raw = op.checks ?? op.data?.checks ?? []\n\t\t\tif (Array.isArray(raw) === true) {\n\t\t\t\treturn raw.length\n\t\t\t}\n\t\t\treturn 0\n\t\t},\n\n\t\tchipSubtitle(op) {\n\t\t\treturn this.entityLabel(op) || this.opTitle(op)\n\t\t},\n\n\t\tfetch() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.fetchList()\n\t\t},\n\n\t\tasync fetchList() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tthis.operations = data.results || data.items || (Array.isArray(data) ? data : []) || []\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else if (response.status === 403) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = t('nextcloud-vue', 'Flow operations are only visible to administrators.')\n\t\t\t\t} else {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowCard] failed to fetch operations', err)\n\t\t\t\tthis.operations = []\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync fetchSingle() {\n\t\t\tif (!this.value || !this.register || !this.schema || !this.objectId) {\n\t\t\t\tthis.entity = null\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.baseUrl()}/${encodeURIComponent(this.value)}`), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tthis.entity = await response.json()\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.entity = null\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.entity = null\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowCard] failed to fetch single operation', err)\n\t\t\t\tthis.entity = null\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-flow-card__empty {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n\tpadding: 8px 0;\n}\n\n.cn-flow-card__headline {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n}\n\n.cn-flow-card__headline-line {\n\tfont-size: 1.1em;\n\tcolor: var(--color-main-text);\n}\n\n.cn-flow-card__headline-recent {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n\tfont-size: 0.9em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-flow-card__headline-recent a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\n.cn-flow-card__headline-recent a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-flow-card__headline-entity {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-card__chip {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 6px;\n\tpadding: 4px 8px;\n\tborder-radius: 12px;\n\tbackground: var(--color-background-hover);\n\tfont-size: 0.9em;\n\tmax-width: 100%;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n/* stylelint-disable-next-line no-descending-specificity */\n.cn-flow-card__chip a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\n.cn-flow-card__chip a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-flow-card__chip-enabled,\n.cn-flow-card__enabled {\n\twidth: 8px;\n\theight: 8px;\n\tborder-radius: 50%;\n\tflex-shrink: 0;\n}\n\n.cn-flow-card__enabled--on {\n\tbackground: var(--color-success, #46ba61);\n}\n\n.cn-flow-card__enabled--off {\n\tbackground: var(--color-text-maxcontrast);\n}\n\n.cn-flow-card__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-flow-card__row {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tpadding: 8px 0;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.cn-flow-card__row:last-child {\n\tborder-bottom: none;\n}\n\n.cn-flow-card__row--disabled {\n\topacity: 0.7;\n}\n\n.cn-flow-card__row-header {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-flow-card__row-icon {\n\tcolor: var(--color-text-maxcontrast);\n\tflex-shrink: 0;\n}\n\n.cn-flow-card__title {\n\tflex: 1;\n\tmin-width: 0;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\na.cn-flow-card__title:hover {\n\ttext-decoration: underline;\n}\n\n.cn-flow-card__subtitle {\n\tfont-size: 0.8em;\n\tcolor: var(--color-text-maxcontrast);\n\tpadding-left: 24px;\n}\n</style>\n"],"names":["_createBlock","_createElementBlock","_Fragment","_createVNode","_createElementVNode","_toDisplayString","_normalizeClass","_openBlock"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnFlowCard.vue3.js","sources":["../../../../../src/integrations/builtin/flow/CnFlowCard.vue?vue&type=template&id=3dfce3f2&lang.js"],"sourcesContent":["<!--\n CnFlowCard — bespoke surface-aware widget for the `flow` (automation)\n integration.\n\n Replaces the generic CnIntegrationCard for the `flow` leaf. Branches\n on `surface` per AD-19:\n - user-dashboard / app-dashboard : headline \"N automations · M\n active\" + most-recent name with its entity binding.\n - detail-page : compact list of linked\n operations with entity / operation type / enabled indicator\n per row.\n - single-entity : chip with operation name + an\n enabled dot (referenceType: 'flow').\n\n Pulls rows from the same OR pluggable-integration sub-resource as\n CnFlowTab; for `single-entity` the optional `value` prop addresses a\n single operation by id (matching CnIntegrationCard's fetchSingle\n contract).\n\n See `openregister/openspec/changes/integration-flow/` for the spec\n delta and ADR-019 (registry mechanism), AD-19 (surface fallback).\n-->\n<template>\n\t<CnDetailCard :title=\"cardTitle\" :icon=\"cardIcon\" :collapsible=\"collapsible\">\n\t\t<NcLoadingIcon v-if=\"loading\" />\n\n\t\t<!-- single-entity surface: chip -->\n\t\t<template v-else-if=\"surface === 'single-entity'\">\n\t\t\t<span v-if=\"entity\" class=\"cn-flow-card__chip\" :title=\"chipSubtitle(entity)\">\n\t\t\t\t<SitemapOutline :size=\"14\" />\n\t\t\t\t<a\n\t\t\t\t\t:href=\"opUrl(entity)\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener\">{{ opTitle(entity) }}</a>\n\t\t\t\t<span\n\t\t\t\t\tclass=\"cn-flow-card__chip-enabled\"\n\t\t\t\t\t:class=\"enabledClass(entity)\" />\n\t\t\t</span>\n\t\t\t<span v-else class=\"cn-flow-card__empty\">{{ emptyLabel }}</span>\n\t\t</template>\n\n\t\t<!-- dashboard surfaces: headline + most-recent -->\n\t\t<template v-else-if=\"surface === 'user-dashboard' || surface === 'app-dashboard'\">\n\t\t\t<div v-if=\"degraded\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"operations.length === 0\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<div v-else class=\"cn-flow-card__headline\">\n\t\t\t\t<div class=\"cn-flow-card__headline-line\">\n\t\t\t\t\t<strong>{{ countHeadline }}</strong>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"mostRecent\" class=\"cn-flow-card__headline-recent\">\n\t\t\t\t\t<SitemapOutline :size=\"14\" />\n\t\t\t\t\t<a\n\t\t\t\t\t\t:href=\"opUrl(mostRecent)\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener\">{{ opTitle(mostRecent) }}</a>\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-if=\"entityLabel(mostRecent)\"\n\t\t\t\t\t\tclass=\"cn-flow-card__headline-entity\">\n\t\t\t\t\t\t· {{ entityLabel(mostRecent) }}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</template>\n\n\t\t<!-- detail-page surface: compact list -->\n\t\t<template v-else>\n\t\t\t<div v-if=\"degraded\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"operations.length === 0\" class=\"cn-flow-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<ul v-else class=\"cn-flow-card__list\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"op in displayedOperations\"\n\t\t\t\t\t:key=\"opKey(op)\"\n\t\t\t\t\tclass=\"cn-flow-card__row\"\n\t\t\t\t\t:class=\"{ 'cn-flow-card__row--disabled': isDisabled(op) }\">\n\t\t\t\t\t<div class=\"cn-flow-card__row-header\">\n\t\t\t\t\t\t<SitemapOutline :size=\"16\" class=\"cn-flow-card__row-icon\" />\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t:href=\"opUrl(op)\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noopener\"\n\t\t\t\t\t\t\tclass=\"cn-flow-card__title\">{{ opTitle(op) }}</a>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclass=\"cn-flow-card__enabled\"\n\t\t\t\t\t\t\t:class=\"enabledClass(op)\"\n\t\t\t\t\t\t\t:aria-label=\"enabledLabel(op)\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t<span v-if=\"rowMeta(op)\" class=\"cn-flow-card__subtitle\">{{ rowMeta(op) }}</span>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</template>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translatePlural as n, translate as t } from '@nextcloud/l10n'\nimport { NcLoadingIcon } from '@nextcloud/vue'\nimport SitemapOutline from 'vue-material-design-icons/SitemapOutline.vue'\nimport CnDetailCard from '../../../components/CnDetailCard/CnDetailCard.vue'\nimport { buildHeaders, prefixUrl, safeHref } from '../../../utils/index.js'\n\nconst VALID_SURFACES = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity']\nconst COMPACT_LIMIT = 5\n\n/**\n * CnFlowCard — bespoke surface-aware widget for the `flow` integration.\n *\n * Renders Flow-aware metadata across all four surfaces. See the\n * file-level docblock for surface-by-surface behaviour.\n */\nexport default {\n\tname: 'CnFlowCard',\n\n\tcomponents: { CnDetailCard, NcLoadingIcon, SitemapOutline },\n\n\tprops: {\n\t\t/** Stable integration id (forwarded from the registry — always `'flow'`). */\n\t\tintegrationId: { type: String, default: 'flow' },\n\t\t/** OpenRegister register id (slug or uuid). */\n\t\tregister: { type: String, required: true },\n\t\t/** OpenRegister schema id (slug or uuid). */\n\t\tschema: { type: String, required: true },\n\t\t/** Parent object id. */\n\t\tobjectId: { type: String, required: true },\n\t\t/** Rendering surface (AD-19). */\n\t\tsurface: {\n\t\t\ttype: String,\n\t\t\tdefault: 'detail-page',\n\t\t\tvalidator: (s) => VALID_SURFACES.includes(s),\n\t\t},\n\n\t\t/** Optional single-entity reference (operation id). */\n\t\tvalue: { type: String, default: '' },\n\t\t/** Pre-translated card title. */\n\t\ttitle: { type: String, default: () => t('nextcloud-vue', 'Automation') },\n\t\t/** Optional Material Design Icon component. */\n\t\ticon: { type: Object, default: () => SitemapOutline },\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Whether the card body is collapsible. */\n\t\tcollapsible: { type: Boolean, default: true },\n\t\t/** Pre-translated empty-state label. */\n\t\temptyLabel: { type: String, default: () => t('nextcloud-vue', 'No automations linked yet') },\n\t\t/** Pre-translated unavailable label. */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'NC Flow is currently unavailable.') },\n\t\t/** URL of the NC Flow admin settings page. */\n\t\tflowSettingsUrl: { type: String, default: '/index.php/settings/admin/workflow' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\toperations: [],\n\t\t\tentity: null,\n\t\t\tloading: false,\n\t\t\tdegraded: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tcardTitle() {\n\t\t\treturn this.title || this.integrationId\n\t\t},\n\n\t\tcardIcon() {\n\t\t\treturn this.icon\n\t\t},\n\n\t\tdisplayedOperations() {\n\t\t\tif (this.surface === 'user-dashboard' || this.surface === 'app-dashboard') {\n\t\t\t\treturn this.operations.slice(0, COMPACT_LIMIT)\n\t\t\t}\n\t\t\treturn this.operations\n\t\t},\n\n\t\tactiveCount() {\n\t\t\treturn this.operations.reduce((sum, op) => sum + (this.isDisabled(op) ? 0 : 1), 0)\n\t\t},\n\n\t\tcountHeadline() {\n\t\t\tconst total = this.operations.length\n\t\t\tconst active = this.activeCount\n\t\t\tif (total === 0) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tif (active === total) {\n\t\t\t\treturn n('nextcloud-vue', '{count} automation', '{count} automations', total, { count: total })\n\t\t\t}\n\t\t\tconst totalFragment = n('nextcloud-vue', '{count} automation', '{count} automations', total, { count: total })\n\t\t\tconst activeFragment = n('nextcloud-vue', '{count} active', '{count} active', active, { count: active })\n\t\t\treturn `${totalFragment} · ${activeFragment}`\n\t\t},\n\n\t\tmostRecent() {\n\t\t\tif (this.operations.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\t// NC Flow operations don't carry a stable \"created\" field,\n\t\t\t// so we just use the natural list order — the provider\n\t\t\t// returns admin-scoped operations newest-first via the\n\t\t\t// Manager API.\n\t\t\treturn this.operations[0]\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: { immediate: true, handler() {\n\t\t\tthis.fetch()\n\t\t} },\n\n\t\tsurface() {\n\t\t\tthis.fetch()\n\t\t},\n\n\t\tvalue() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t}\n\t\t},\n\t},\n\n\tmethods: {\n\t\tbaseUrl() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/integrations/${this.integrationId}`\n\t\t},\n\n\t\topKey(op) {\n\t\t\treturn op.id ?? op.title ?? ''\n\t\t},\n\n\t\topTitle(op) {\n\t\t\treturn op.title || op.displayName || op.name || this.shortClass(op.class) || t('nextcloud-vue', 'Untitled automation')\n\t\t},\n\n\t\topUrl(op) {\n\t\t\treturn op.url && safeHref(op.url) !== '#' ? op.url : this.flowSettingsUrl\n\t\t},\n\n\t\tshortClass(className) {\n\t\t\tif (!className) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst parts = String(className).split('\\\\')\n\t\t\treturn parts[parts.length - 1] || className\n\t\t},\n\n\t\tentityLabel(op) {\n\t\t\tif (!op.entity) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn this.shortClass(op.entity)\n\t\t},\n\n\t\tisDisabled(op) {\n\t\t\tconst v = op.enabled ?? op.data?.enabled\n\t\t\tif (v === undefined || v === null) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn v === false || v === 0 || v === '0'\n\t\t},\n\n\t\tenabledLabel(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? t('nextcloud-vue', 'Disabled')\n\t\t\t\t: t('nextcloud-vue', 'Enabled')\n\t\t},\n\n\t\tenabledClass(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? 'cn-flow-card__enabled--off'\n\t\t\t\t: 'cn-flow-card__enabled--on'\n\t\t},\n\n\t\trowMeta(op) {\n\t\t\tconst parts = []\n\t\t\tconst entity = this.entityLabel(op)\n\t\t\tif (entity !== '') {\n\t\t\t\tparts.push(entity)\n\t\t\t}\n\t\t\tconst operation = op.operation || ''\n\t\t\tif (operation !== '') {\n\t\t\t\tparts.push(operation)\n\t\t\t}\n\t\t\tconst checks = this.checksCount(op)\n\t\t\tif (checks > 0) {\n\t\t\t\tparts.push(t('nextcloud-vue', '{n} conditions', { n: checks }))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\tchecksCount(op) {\n\t\t\tconst raw = op.checks ?? op.data?.checks ?? []\n\t\t\tif (Array.isArray(raw) === true) {\n\t\t\t\treturn raw.length\n\t\t\t}\n\t\t\treturn 0\n\t\t},\n\n\t\tchipSubtitle(op) {\n\t\t\treturn this.entityLabel(op) || this.opTitle(op)\n\t\t},\n\n\t\tfetch() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.fetchList()\n\t\t},\n\n\t\tasync fetchList() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tthis.operations = data.results || data.items || (Array.isArray(data) ? data : []) || []\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else if (response.status === 403) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = t('nextcloud-vue', 'Flow operations are only visible to administrators.')\n\t\t\t\t} else {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowCard] failed to fetch operations', err)\n\t\t\t\tthis.operations = []\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync fetchSingle() {\n\t\t\tif (!this.value || !this.register || !this.schema || !this.objectId) {\n\t\t\t\tthis.entity = null\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.baseUrl()}/${encodeURIComponent(this.value)}`), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tthis.entity = await response.json()\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.entity = null\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.entity = null\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowCard] failed to fetch single operation', err)\n\t\t\t\tthis.entity = null\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-flow-card__empty {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n\tpadding: 8px 0;\n}\n\n.cn-flow-card__headline {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n}\n\n.cn-flow-card__headline-line {\n\tfont-size: 1.1em;\n\tcolor: var(--color-main-text);\n}\n\n.cn-flow-card__headline-recent {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n\tfont-size: 0.9em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-flow-card__headline-recent a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\n.cn-flow-card__headline-recent a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-flow-card__headline-entity {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-card__chip {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 6px;\n\tpadding: 4px 8px;\n\tborder-radius: 12px;\n\tbackground: var(--color-background-hover);\n\tfont-size: 0.9em;\n\tmax-width: 100%;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n/* stylelint-disable-next-line no-descending-specificity */\n.cn-flow-card__chip a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\n.cn-flow-card__chip a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-flow-card__chip-enabled,\n.cn-flow-card__enabled {\n\twidth: 8px;\n\theight: 8px;\n\tborder-radius: 50%;\n\tflex-shrink: 0;\n}\n\n.cn-flow-card__enabled--on {\n\tbackground: var(--color-success, #46ba61);\n}\n\n.cn-flow-card__enabled--off {\n\tbackground: var(--color-text-maxcontrast);\n}\n\n.cn-flow-card__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-flow-card__row {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tpadding: 8px 0;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.cn-flow-card__row:last-child {\n\tborder-bottom: none;\n}\n\n.cn-flow-card__row--disabled {\n\topacity: 0.7;\n}\n\n.cn-flow-card__row-header {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-flow-card__row-icon {\n\tcolor: var(--color-text-maxcontrast);\n\tflex-shrink: 0;\n}\n\n.cn-flow-card__title {\n\tflex: 1;\n\tmin-width: 0;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\na.cn-flow-card__title:hover {\n\ttext-decoration: underline;\n}\n\n.cn-flow-card__subtitle {\n\tfont-size: 0.8em;\n\tcolor: var(--color-text-maxcontrast);\n\tpadding-left: 24px;\n}\n</style>\n"],"names":["_createBlock","_createElementBlock","_Fragment","_createVNode","_createElementVNode","_toDisplayString","_normalizeClass","_openBlock"],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ import Plus from 'vue-material-design-icons/Plus.vue';
|
|
|
6
6
|
import SitemapOutline from 'vue-material-design-icons/SitemapOutline.vue';
|
|
7
7
|
import __sfc_main from '../../../components/CnFlowOperationPicker/CnFlowOperationPicker.vue.js';
|
|
8
8
|
import __sfc_main$1 from '../../../components/CnStatusBadge/CnStatusBadge.vue.js';
|
|
9
|
+
import { safeHref } from '../../../utils/safeHref.js';
|
|
9
10
|
import { prefixUrl, buildHeaders } from '../../../utils/headers.js';
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -85,7 +86,7 @@ var script = {
|
|
|
85
86
|
},
|
|
86
87
|
|
|
87
88
|
opUrl(op) {
|
|
88
|
-
return op.url
|
|
89
|
+
return op.url && safeHref(op.url) !== '#' ? op.url : this.flowSettingsUrl
|
|
89
90
|
},
|
|
90
91
|
|
|
91
92
|
shortClass(className) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnFlowTab.vue2.js","sources":["../../../../../src/integrations/builtin/flow/CnFlowTab.vue"],"sourcesContent":["<!--\n CnFlowTab — bespoke sidebar tab for the `flow` (automation) integration.\n\n Renders a list of NC Flow (workflowengine) operations bound to the\n parent OR object via the Tier-2 `openregister_flow_links` table.\n Each row surfaces the operation name, the target entity class\n (short form), the operation type, a chips set of trigger events, a\n checks-count, and a (display-only) enabled toggle. A trailing\n \"Open in Flow settings\" deep-link points to\n `/index.php/settings/admin/workflow` (NC Flow is admin-gated, so\n edits happen in the admin settings, not in the sidebar tab).\n\n Talks to the Tier-2 link-table endpoints:\n GET /api/objects/{r}/{s}/{id}/flow (read, all users)\n POST /api/objects/{r}/{s}/{id}/flow (link, admin-only)\n DELETE /api/objects/{r}/{s}/{id}/flow/{operationId} (unlink, admin-only)\n\n Payload contract (per FlowProvider + FlowLinkService):\n { operationId, operationName, operationClass, entityType,\n enabled, url, linkId, events, checks, operation }\n + envelope `{ results, total, isAdmin }`\n\n Surface behaviour:\n - Admins see: \"Link existing automation\" button → CnFlowOperationPicker\n + per-row unlink action.\n - Non-admins see: read-only list, no link/unlink controls. The\n \"Open Flow settings\" deep-link is still surfaced so the user\n knows where automations live.\n - Loading + 503 \"currently unavailable\" + generic error states\n match CnIntegrationTab's behaviour for AD-23 graceful degradation.\n\n See `openregister/openspec/changes/integration-flow/` for the spec\n delta and ADR-019 (registry mechanism) / ADR-023 (action authorisation).\n-->\n<template>\n\t<div class=\"cn-sidebar-tab cn-flow-tab\">\n\t\t<div v-if=\"degraded\" class=\"cn-flow-tab__banner\" role=\"alert\">\n\t\t\t<AlertCircleOutline :size=\"18\" />\n\t\t\t<span>{{ degraded }}</span>\n\t\t</div>\n\n\t\t<div v-if=\"isAdmin && !loading && !error\" class=\"cn-flow-tab__actions\">\n\t\t\t<NcButton variant=\"secondary\" data-testid=\"cn-flow-tab-link\" @click=\"openPicker\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Plus :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('nextcloud-vue', 'Link existing automation') }}\n\t\t\t</NcButton>\n\t\t</div>\n\n\t\t<NcLoadingIcon v-if=\"loading\" />\n\t\t<div v-else-if=\"error\" class=\"cn-flow-tab__error\" role=\"alert\">\n\t\t\t{{ error }}\n\t\t</div>\n\t\t<div v-else-if=\"operations.length === 0\" class=\"cn-sidebar-tab__empty cn-flow-tab__empty\">\n\t\t\t<SitemapOutline :size=\"32\" class=\"cn-flow-tab__empty-icon\" />\n\t\t\t<p>{{ emptyLabel }}</p>\n\t\t\t<NcButton\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:href=\"flowSettingsUrl\"\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\trel=\"noopener noreferrer\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<SitemapOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ openSettingsLabel }}\n\t\t\t</NcButton>\n\t\t</div>\n\t\t<ul v-else class=\"cn-flow-tab__list\">\n\t\t\t<NcListItem\n\t\t\t\tv-for=\"op in operations\"\n\t\t\t\t:key=\"opKey(op)\"\n\t\t\t\tclass=\"cn-flow-tab__row\"\n\t\t\t\t:class=\"{ 'cn-flow-tab__row--disabled': isDisabled(op) }\"\n\t\t\t\t:name=\"opTitle(op)\"\n\t\t\t\t:href=\"opUrl(op)\"\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\t:bold=\"true\"\n\t\t\t\t:forceDisplayActions=\"isAdmin\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<span class=\"cn-flow-tab__avatar\" :class=\"enabledClass(op)\" :aria-hidden=\"true\">\n\t\t\t\t\t\t<SitemapOutline :size=\"20\" />\n\t\t\t\t\t</span>\n\t\t\t\t</template>\n\t\t\t\t<template #subname>\n\t\t\t\t\t<span v-if=\"opSummary(op)\" class=\"cn-flow-tab__summary\">{{ opSummary(op) }}</span>\n\t\t\t\t</template>\n\t\t\t\t<template #indicator>\n\t\t\t\t\t<CnStatusBadge\n\t\t\t\t\t\tclass=\"cn-flow-tab__enabled\"\n\t\t\t\t\t\t:class=\"enabledClass(op)\"\n\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t:variant=\"enabledVariant(op)\"\n\t\t\t\t\t\t:label=\"enabledLabel(op)\"\n\t\t\t\t\t\t:aria-label=\"enabledAriaLabel(op)\" />\n\t\t\t\t</template>\n\t\t\t\t<template v-if=\"events(op).length > 0 || opMeta(op)\" #details>\n\t\t\t\t\t<span class=\"cn-flow-tab__details\">\n\t\t\t\t\t\t<span v-if=\"events(op).length > 0\" class=\"cn-flow-tab__events\">\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tv-for=\"evt in events(op)\"\n\t\t\t\t\t\t\t\t:key=\"evt\"\n\t\t\t\t\t\t\t\tclass=\"cn-flow-tab__chip\">{{ shortEvent(evt) }}</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span v-if=\"opMeta(op)\" class=\"cn-flow-tab__meta\">{{ opMeta(op) }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t</template>\n\t\t\t\t<template v-if=\"isAdmin\" #actions>\n\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\tclass=\"cn-flow-tab__unlink\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Unlink automation')\"\n\t\t\t\t\t\tdata-testid=\"cn-flow-tab-unlink\"\n\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t@click=\"confirmUnlink(op)\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<Close :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t{{ t('nextcloud-vue', 'Unlink automation') }}\n\t\t\t\t\t</NcActionButton>\n\t\t\t\t</template>\n\t\t\t</NcListItem>\n\t\t</ul>\n\n\t\t<CnFlowOperationPicker\n\t\t\tv-if=\"pickerOpen\"\n\t\t\t:apiBase=\"apiBase\"\n\t\t\t:flowSettingsUrl=\"flowSettingsUrl\"\n\t\t\t@close=\"pickerOpen = false\"\n\t\t\t@link=\"onLink\" />\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcActionButton, NcButton, NcListItem, NcLoadingIcon } from '@nextcloud/vue'\nimport AlertCircleOutline from 'vue-material-design-icons/AlertCircleOutline.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\nimport Plus from 'vue-material-design-icons/Plus.vue'\nimport SitemapOutline from 'vue-material-design-icons/SitemapOutline.vue'\nimport CnFlowOperationPicker from '../../../components/CnFlowOperationPicker/CnFlowOperationPicker.vue'\nimport CnStatusBadge from '../../../components/CnStatusBadge/CnStatusBadge.vue'\nimport { buildHeaders, prefixUrl } from '../../../utils/index.js'\n\n/**\n * CnFlowTab — bespoke automation-rule list for the `flow` integration.\n *\n * Admins can link/unlink operations via the picker; non-admins see\n * a read-only list with a deep-link to NC Workflow Settings.\n */\nexport default {\n\tname: 'CnFlowTab',\n\n\tcomponents: { NcActionButton, NcButton, NcListItem, NcLoadingIcon, AlertCircleOutline, Close, Plus, SitemapOutline, CnFlowOperationPicker, CnStatusBadge },\n\n\tprops: {\n\t\t/* eslint-disable vue/no-unused-properties -- the integration dispatch binds integrationId on every integration component (see CnIntegrationWidgetGrid), so declaring it keeps it out of $attrs */\n\t\t/** Stable integration id (forwarded from the registry — always `'flow'`). */\n\t\tintegrationId: { type: String, default: 'flow' },\n\t\t/* eslint-enable vue/no-unused-properties */\n\t\t/** Parent object id. */\n\t\tobjectId: { type: String, required: true },\n\t\t/** OpenRegister register id (slug or uuid). */\n\t\tregister: { type: String, default: '' },\n\t\t/** OpenRegister schema id (slug or uuid). */\n\t\tschema: { type: String, default: '' },\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Pre-translated empty-state label. */\n\t\temptyLabel: { type: String, default: () => t('nextcloud-vue', 'No automations linked yet') },\n\t\t/** Pre-translated label for the \"Open Flow settings\" CTA. */\n\t\topenSettingsLabel: { type: String, default: () => t('nextcloud-vue', 'Open Workflow settings') },\n\t\t/** Pre-translated banner when Flow is unavailable. */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'NC Flow is currently unavailable.') },\n\t\t/** URL of the NC Flow admin settings page. */\n\t\tflowSettingsUrl: { type: String, default: '/index.php/settings/admin/workflow' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\toperations: [],\n\t\t\tloading: false,\n\t\t\terror: '',\n\t\t\tdegraded: '',\n\t\t\tisAdmin: false,\n\t\t\tpickerOpen: false,\n\t\t}\n\t},\n\n\twatch: {\n\t\tobjectId: { immediate: true, handler(id) {\n\t\t\tif (id) {\n\t\t\t\tthis.fetchOperations()\n\t\t\t}\n\t\t} },\n\n\t\tregister() {\n\t\t\tthis.fetchOperations()\n\t\t},\n\n\t\tschema() {\n\t\t\tthis.fetchOperations()\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\tbaseUrl() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/flow`\n\t\t},\n\n\t\topKey(op) {\n\t\t\treturn op.operationId ?? op.id ?? op.title ?? ''\n\t\t},\n\n\t\topTitle(op) {\n\t\t\treturn op.operationName || op.title || op.name || this.shortClass(op.operationClass) || t('nextcloud-vue', 'Untitled automation')\n\t\t},\n\n\t\topUrl(op) {\n\t\t\treturn op.url || this.flowSettingsUrl\n\t\t},\n\n\t\tshortClass(className) {\n\t\t\tif (!className) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst parts = String(className).split('\\\\')\n\t\t\treturn parts[parts.length - 1] || className\n\t\t},\n\n\t\tentityLabel(op) {\n\t\t\tconst entity = op.entityType || op.entity\n\t\t\tif (!entity) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn this.shortClass(entity)\n\t\t},\n\n\t\toperationLabel(op) {\n\t\t\treturn op.operation || ''\n\t\t},\n\n\t\topSummary(op) {\n\t\t\tconst parts = []\n\t\t\tconst entity = this.entityLabel(op)\n\t\t\tif (entity !== '') {\n\t\t\t\tparts.push(t('nextcloud-vue', 'Entity: {entity}', { entity }))\n\t\t\t}\n\t\t\tconst opLabel = this.operationLabel(op)\n\t\t\tif (opLabel !== '') {\n\t\t\t\tparts.push(t('nextcloud-vue', 'Operation: {op}', { op: opLabel }))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\tevents(op) {\n\t\t\tconst raw = op.events ?? op.data?.events ?? []\n\t\t\tif (Array.isArray(raw) === true) {\n\t\t\t\treturn raw.filter((e) => typeof e === 'string' && e !== '')\n\t\t\t}\n\t\t\treturn []\n\t\t},\n\n\t\tshortEvent(evt) {\n\t\t\tconst colon = String(evt).lastIndexOf(':')\n\t\t\tif (colon === -1) {\n\t\t\t\treturn String(evt)\n\t\t\t}\n\t\t\treturn String(evt).slice(colon + 1) || String(evt)\n\t\t},\n\n\t\tchecksCount(op) {\n\t\t\tconst raw = op.checks ?? op.data?.checks ?? []\n\t\t\tif (Array.isArray(raw) === true) {\n\t\t\t\treturn raw.length\n\t\t\t}\n\t\t\tif (typeof raw === 'string' && raw.startsWith('[') === true) {\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(raw)\n\t\t\t\t\treturn Array.isArray(parsed) === true ? parsed.length : 0\n\t\t\t\t} catch {\n\t\t\t\t\treturn 0\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn 0\n\t\t},\n\n\t\topMeta(op) {\n\t\t\tconst parts = []\n\t\t\tconst checks = this.checksCount(op)\n\t\t\tif (checks > 0) {\n\t\t\t\tparts.push(t('nextcloud-vue', '{n} conditions', { n: checks }))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\tisDisabled(op) {\n\t\t\tconst v = op.enabled ?? op.data?.enabled\n\t\t\tif (v === undefined || v === null) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn v === false || v === 0 || v === '0'\n\t\t},\n\n\t\tenabledLabel(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? t('nextcloud-vue', 'Disabled')\n\t\t\t\t: t('nextcloud-vue', 'Enabled')\n\t\t},\n\n\t\tenabledClass(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? 'cn-flow-tab__enabled--off'\n\t\t\t\t: 'cn-flow-tab__enabled--on'\n\t\t},\n\n\t\tenabledVariant(op) {\n\t\t\treturn this.isDisabled(op) === true ? 'default' : 'success'\n\t\t},\n\n\t\tenabledAriaLabel(op) {\n\t\t\treturn this.enabledLabel(op)\n\t\t},\n\n\t\topenPicker() {\n\t\t\tthis.pickerOpen = true\n\t\t},\n\n\t\tasync fetchOperations() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.error = ''\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tconst rows = data.results || data.items || (Array.isArray(data) ? data : []) || []\n\t\t\t\t\tthis.operations = rows\n\t\t\t\t\tthis.isAdmin = Boolean(data.isAdmin)\n\t\t\t\t} else if (response.status === 501) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = t('nextcloud-vue', 'NC Workflow Engine is not installed.')\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not load automations.')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowTab] failed to fetch operations', err)\n\t\t\t\tthis.operations = []\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not load automations.')\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync onLink({ operationId }) {\n\t\t\tthis.pickerOpen = false\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { ...buildHeaders(), 'Content-Type': 'application/json' },\n\t\t\t\t\tbody: JSON.stringify({ operationId }),\n\t\t\t\t})\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tawait this.fetchOperations()\n\t\t\t\t} else if (response.status === 403) {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Only administrators can link automations.')\n\t\t\t\t} else if (response.status === 409) {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Automation is already linked.')\n\t\t\t\t} else {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not link automation.')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowTab] link failed', err)\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not link automation.')\n\t\t\t}\n\t\t},\n\n\t\tasync confirmUnlink(op) {\n\t\t\tconst opId = op.operationId ?? op.id\n\t\t\tif (!opId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (typeof window !== 'undefined' && typeof window.confirm === 'function') {\n\t\t\t\tconst ok = window.confirm(t('nextcloud-vue', 'Remove this automation link?'))\n\t\t\t\tif (!ok) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.baseUrl()}/${encodeURIComponent(opId)}`), {\n\t\t\t\t\tmethod: 'DELETE',\n\t\t\t\t\theaders: buildHeaders(),\n\t\t\t\t})\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tawait this.fetchOperations()\n\t\t\t\t} else if (response.status === 403) {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Only administrators can unlink automations.')\n\t\t\t\t} else {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not unlink automation.')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowTab] unlink failed', err)\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not unlink automation.')\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-flow-tab__banner {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 8px 10px;\n\tmargin-bottom: 10px;\n\tborder-radius: var(--border-radius);\n\tbackground: var(--color-warning, #e9a40f);\n\tcolor: var(--color-main-background);\n\tfont-size: 0.9em;\n}\n\n.cn-flow-tab__actions {\n\tmargin-bottom: 8px;\n}\n\n.cn-flow-tab__error {\n\tcolor: var(--color-error);\n\tfont-size: 0.9em;\n\tmargin: 4px 0 8px;\n}\n\n.cn-flow-tab__empty {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 16px 8px;\n\tcolor: var(--color-text-maxcontrast);\n\ttext-align: center;\n}\n\n.cn-flow-tab__empty-icon {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-tab__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n/* Mirror NC Flow's rule rows: a round robot avatar, the bold rule\n name, a trigger/condition subline, and an enabled/disabled chip. */\n.cn-flow-tab__row--disabled {\n\topacity: 0.7;\n}\n\n.cn-flow-tab__avatar {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 36px;\n\theight: 36px;\n\tborder-radius: 50%;\n\tbackground: var(--color-background-dark);\n\tcolor: var(--color-text-maxcontrast);\n\tflex-shrink: 0;\n}\n\n.cn-flow-tab__avatar.cn-flow-tab__enabled--on {\n\tbackground: var(--color-primary-element-light, var(--color-background-dark));\n\tcolor: var(--color-primary-element, #0082c9);\n}\n\n.cn-flow-tab__avatar.cn-flow-tab__enabled--off {\n\tbackground: var(--color-background-dark);\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-tab__summary {\n\tfont-size: 0.85em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-flow-tab__meta {\n\tfont-size: 0.8em;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-tab__details {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tflex-wrap: wrap;\n\tgap: 6px;\n}\n\n.cn-flow-tab__events {\n\tdisplay: inline-flex;\n\tflex-wrap: wrap;\n\tgap: 4px;\n}\n\n.cn-flow-tab__chip {\n\tdisplay: inline-block;\n\tpadding: 1px 8px;\n\tborder-radius: 10px;\n\tbackground: var(--color-background-hover);\n\tcolor: var(--color-main-text);\n\tfont-size: 0.75em;\n}\n</style>\n"],"names":["CnFlowOperationPicker","CnStatusBadge","t"],"mappings":";;;;;;;;;;AA+IA;;AAEC;;;;AAID,aAAe;AACd,CAAA,IAAI,EAAE,WAAW;;AAEjB,CAAA,UAAU,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,kBAAkB,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,yBAAEA,UAAqB,iBAAEC,cAAe;;AAE1J,CAAA,KAAK,EAAE;AACN;AACA;AACA,EAAA,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ;AAChD;AACA;AACA,EAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;AAC1C;AACA,EAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI;AACvC;AACA,EAAA,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI;AACrC;EACA,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAuB,EAAG;AAC5D;AACA,EAAA,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAMC,SAAC,CAAC,eAAe,EAAE,2BAA2B,GAAG;;AAE5F,EAAA,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAMA,SAAC,CAAC,eAAe,EAAE,wBAAwB,GAAG;;AAEhG,EAAA,gBAAgB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAMA,SAAC,CAAC,eAAe,EAAE,mCAAmC,GAAG;AAC1G;AACA,EAAA,eAAe,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sCAAsC;EAChF;;AAED,CAAA,IAAI,GAAG;AACN,EAAA,OAAO;GACN,UAAU,EAAE,EAAE;GACd,OAAO,EAAE,KAAK;AACd,GAAA,KAAK,EAAE,EAAE;GACT,QAAQ,EAAE,EAAE;GACZ,OAAO,EAAE,KAAK;AACd,GAAA,UAAU,EAAE,KAAK;AAClB,GAAA;EACA;;AAED,CAAA,KAAK,EAAE;AACN,EAAA,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE;AACxC,GAAA,IAAI,EAAE,EAAE;AACP,IAAA,IAAI,CAAC,eAAe,GAAC;AACtB,IAAA;AACD,GAAA,EAAG;;EAEH,QAAQ,GAAG;AACV,GAAA,IAAI,CAAC,eAAe,GAAC;GACrB;;AAED,EAAA,MAAM,GAAG;AACR,GAAA,IAAI,CAAC,eAAe,GAAC;GACrB;EACD;;AAED,CAAA,OAAO,EAAE;KACRA,SAAC;;AAED,EAAA,OAAO,GAAG;AACT,GAAA,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAA;GACrF;;AAED,EAAA,KAAK,CAAC,EAAE,EAAE;AACT,GAAA,OAAO,EAAE,CAAC,WAAU,IAAK,EAAE,CAAC,EAAC,IAAK,EAAE,CAAC,KAAM,IAAG,EAAC;GAC/C;;EAED,OAAO,CAAC,EAAE,EAAE;GACX,OAAO,EAAE,CAAC,aAAY,IAAK,EAAE,CAAC,KAAM,IAAG,EAAE,CAAC,IAAG,IAAK,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,cAAc,CAAE,IAAGA,SAAC,CAAC,eAAe,EAAE,qBAAqB,CAAA;GAChI;;AAED,EAAA,KAAK,CAAC,EAAE,EAAE;AACT,GAAA,OAAO,EAAE,CAAC,GAAI,IAAG,IAAI,CAAC,eAAc;GACpC;;AAED,EAAA,UAAU,CAAC,SAAS,EAAE;AACrB,GAAA,IAAI,CAAC,SAAS,EAAE;AACf,IAAA,OAAO,EAAC;AACT,IAAA;AACA,GAAA,MAAM,KAAM,GAAE,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,IAAI,EAAA;AAC1C,GAAA,OAAO,KAAK,CAAC,KAAK,CAAC,MAAO,GAAE,CAAC,CAAE,IAAG,SAAQ;GAC1C;;AAED,EAAA,WAAW,CAAC,EAAE,EAAE;AACf,GAAA,MAAM,MAAO,GAAE,EAAE,CAAC,UAAW,IAAG,EAAE,CAAC,OAAK;GACxC,IAAI,CAAC,MAAM,EAAE;AACZ,IAAA,OAAO,EAAC;AACT,IAAA;GACA,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAA;GAC7B;;AAED,EAAA,cAAc,CAAC,EAAE,EAAE;AAClB,GAAA,OAAO,EAAE,CAAC,SAAU,IAAG,EAAC;GACxB;;EAED,SAAS,CAAC,EAAE,EAAE;GACb,MAAM,KAAM,GAAE,GAAC;AACf,GAAA,MAAM,MAAK,GAAI,IAAI,CAAC,WAAW,CAAC,EAAE,EAAA;AAClC,GAAA,IAAI,MAAK,KAAM,EAAE,EAAE;IAClB,KAAK,CAAC,IAAI,CAACA,SAAC,CAAC,eAAe,EAAE,kBAAkB,EAAE,EAAE,MAAO,EAAC,CAAC,EAAA;AAC9D,IAAA;AACA,GAAA,MAAM,OAAM,GAAI,IAAI,CAAC,cAAc,CAAC,EAAE,EAAA;AACtC,GAAA,IAAI,OAAM,KAAM,EAAE,EAAE;IACnB,KAAK,CAAC,IAAI,CAACA,SAAC,CAAC,eAAe,EAAE,iBAAiB,EAAE,EAAE,EAAE,EAAE,OAAQ,EAAC,CAAC,EAAA;AAClE,IAAA;AACA,GAAA,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAA;GACvB;;EAED,MAAM,CAAC,EAAE,EAAE;AACV,GAAA,MAAM,GAAI,GAAE,EAAE,CAAC,MAAO,IAAG,EAAE,CAAC,IAAI,EAAE,MAAO,IAAG,GAAC;GAC7C,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAE,KAAI,IAAI,EAAE;IAChC,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,OAAO,CAAE,KAAI,YAAY,MAAM,EAAE,CAAA;AAC3D,IAAA;AACA,GAAA,OAAO,EAAC;GACR;;AAED,EAAA,UAAU,CAAC,GAAG,EAAE;AACf,GAAA,MAAM,KAAM,GAAE,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,EAAA;AACzC,GAAA,IAAI,KAAM,KAAI,CAAC,CAAC,EAAE;AACjB,IAAA,OAAO,MAAM,CAAC,GAAG,CAAA;AAClB,IAAA;AACA,GAAA,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,KAAM,GAAE,CAAC,CAAE,IAAG,MAAM,CAAC,GAAG,CAAA;GACjD;;AAED,EAAA,WAAW,CAAC,EAAE,EAAE;AACf,GAAA,MAAM,GAAI,GAAE,EAAE,CAAC,MAAO,IAAG,EAAE,CAAC,IAAI,EAAE,MAAO,IAAG,GAAC;GAC7C,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAE,KAAI,IAAI,EAAE;AAChC,IAAA,OAAO,GAAG,CAAC,MAAK;AACjB,IAAA;GACA,IAAI,OAAO,GAAE,KAAM,QAAS,IAAG,GAAG,CAAC,UAAU,CAAC,GAAG,CAAA,KAAM,IAAI,EAAE;AAC5D,IAAA,IAAI;KACH,MAAM,MAAK,GAAI,IAAI,CAAC,KAAK,CAAC,GAAG,EAAA;KAC7B,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAA,KAAM,IAAK,GAAE,MAAM,CAAC,MAAK,GAAI,CAAA;AACzD,KAAA,CAAE,MAAM;AACP,KAAA,OAAO,CAAA;AACR,KAAA;AACD,IAAA;AACA,GAAA,OAAO,CAAA;GACP;;EAED,MAAM,CAAC,EAAE,EAAE;GACV,MAAM,KAAM,GAAE,GAAC;AACf,GAAA,MAAM,MAAK,GAAI,IAAI,CAAC,WAAW,CAAC,EAAE,EAAA;GAClC,IAAI,MAAK,GAAI,CAAC,EAAE;IACf,KAAK,CAAC,IAAI,CAACA,SAAC,CAAC,eAAe,EAAE,gBAAgB,EAAE,EAAE,CAAC,EAAE,MAAO,EAAC,CAAC,EAAA;AAC/D,IAAA;AACA,GAAA,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAA;GACvB;;AAED,EAAA,UAAU,CAAC,EAAE,EAAE;AACd,GAAA,MAAM,IAAI,EAAE,CAAC,OAAM,IAAK,EAAE,CAAC,IAAI,EAAE,QAAM;GACvC,IAAI,CAAA,KAAM,SAAQ,IAAK,CAAE,KAAI,IAAI,EAAE;IAClC,OAAO,KAAI;AACZ,IAAA;AACA,GAAA,OAAO,CAAA,KAAM,KAAI,IAAK,CAAE,KAAI,CAAE,IAAG,CAAA,KAAM,GAAE;GACzC;;AAED,EAAA,YAAY,CAAC,EAAE,EAAE;AAChB,GAAA,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,CAAA,KAAM,IAAG;MAC/BA,SAAC,CAAC,eAAe,EAAE,UAAU,CAAA;MAC7BA,SAAC,CAAC,eAAe,EAAE,SAAS,CAAA;GAC/B;;AAED,EAAA,YAAY,CAAC,EAAE,EAAE;AAChB,GAAA,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,CAAA,KAAM,IAAG;MAC/B,2BAA0B;MAC1B,0BAAyB;GAC5B;;AAED,EAAA,cAAc,CAAC,EAAE,EAAE;GAClB,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,CAAA,KAAM,OAAO,SAAU,GAAE,SAAQ;GAC1D;;AAED,EAAA,gBAAgB,CAAC,EAAE,EAAE;GACpB,OAAO,IAAI,CAAC,YAAY,CAAC,EAAE,CAAA;GAC3B;;EAED,UAAU,GAAG;AACZ,GAAA,IAAI,CAAC,aAAa,KAAG;GACrB;;EAED,MAAM,eAAe,GAAG;GACvB,IAAI,CAAC,IAAI,CAAC,QAAO,IAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE;IACrD,MAAK;AACN,IAAA;AACA,GAAA,IAAI,CAAC,OAAM,GAAI,KAAG;GAClB,IAAI,CAAC,KAAM,GAAE,GAAC;AACd,GAAA,IAAI,CAAC,QAAO,GAAI,GAAC;AACjB,GAAA,IAAI;AACH,IAAA,MAAM,QAAO,GAAI,MAAM,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,YAAY,IAAI,EAAA;AACnF,IAAA,IAAI,QAAQ,CAAC,EAAE,EAAE;KAChB,MAAM,IAAK,GAAE,MAAM,QAAQ,CAAC,IAAI,GAAC;AACjC,KAAA,MAAM,IAAG,GAAI,IAAI,CAAC,OAAM,IAAK,IAAI,CAAC,KAAI,KAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAE,GAAE,IAAK,GAAE,EAAE,CAAE,IAAG,GAAC;AACjF,KAAA,IAAI,CAAC,aAAa,KAAG;AACrB,KAAA,IAAI,CAAC,OAAQ,GAAE,OAAO,CAAC,IAAI,CAAC,OAAO,EAAA;AACpC,KAAA,MAAO,IAAI,QAAQ,CAAC,MAAK,KAAM,GAAG,EAAE;AACnC,KAAA,IAAI,CAAC,UAAS,GAAI,GAAC;AACnB,KAAA,IAAI,CAAC,QAAO,GAAIA,SAAC,CAAC,eAAe,EAAE,sCAAsC,EAAA;AAC1E,KAAA,MAAO,IAAI,QAAQ,CAAC,MAAK,KAAM,GAAG,EAAE;AACnC,KAAA,IAAI,CAAC,UAAS,GAAI,GAAC;AACnB,KAAA,IAAI,CAAC,QAAS,GAAE,IAAI,CAAC,iBAAe;KACnC,MAAK;AACN,KAAA,IAAI,CAAC,UAAS,GAAI,GAAC;KACnB,IAAI,CAAC,KAAM,GAAEA,SAAC,CAAC,eAAe,EAAE,6BAA6B,EAAA;AAC9D,KAAA;IACC,CAAA,OAAO,GAAG,EAAE;AACb;IACA,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,GAAG,EAAA;AAC3D,IAAA,IAAI,CAAC,UAAS,GAAI,GAAC;IACnB,IAAI,CAAC,KAAM,GAAEA,SAAC,CAAC,eAAe,EAAE,6BAA6B,EAAA;AAC9D,IAAA,SAAU;AACT,IAAA,IAAI,CAAC,OAAQ,GAAE,MAAI;AACpB,IAAA;GACA;;EAED,MAAM,MAAM,CAAC,EAAE,WAAY,EAAC,EAAE;AAC7B,GAAA,IAAI,CAAC,UAAS,GAAI,MAAI;AACtB,GAAA,IAAI;IACH,MAAM,WAAW,MAAM,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE;KACvD,MAAM,EAAE,MAAM;KACd,OAAO,EAAE,EAAE,GAAG,YAAY,EAAE,EAAE,cAAc,EAAE,kBAAiB,EAAG;AAClE,KAAA,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,WAAU,EAAG,CAAC;KACrC,EAAA;AACD,IAAA,IAAI,QAAQ,CAAC,EAAE,EAAE;KAChB,MAAM,IAAI,CAAC,eAAe,GAAC;AAC5B,KAAA,MAAO,IAAI,QAAQ,CAAC,MAAK,KAAM,GAAG,EAAE;AACnC,KAAA,IAAI,CAAC,KAAM,GAAEA,SAAC,CAAC,eAAe,EAAE,2CAA2C,EAAA;AAC5E,KAAA,MAAO,IAAI,QAAQ,CAAC,MAAK,KAAM,GAAG,EAAE;KACnC,IAAI,CAAC,KAAM,GAAEA,SAAC,CAAC,eAAe,EAAE,+BAA+B,EAAA;KAC9D,MAAK;KACN,IAAI,CAAC,KAAM,GAAEA,SAAC,CAAC,eAAe,EAAE,4BAA4B,EAAA;AAC7D,KAAA;IACC,CAAA,OAAO,GAAG,EAAE;AACb;AACA,IAAA,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,GAAG,EAAA;IAC5C,IAAI,CAAC,KAAM,GAAEA,SAAC,CAAC,eAAe,EAAE,4BAA4B,EAAA;AAC7D,IAAA;GACA;;EAED,MAAM,aAAa,CAAC,EAAE,EAAE;AACvB,GAAA,MAAM,IAAG,GAAI,EAAE,CAAC,WAAY,IAAG,EAAE,CAAC,GAAC;AACnC,GAAA,IAAI,CAAC,IAAI,EAAE;IACV,MAAK;AACN,IAAA;AACA,GAAA,IAAI,OAAO,MAAK,KAAM,WAAU,IAAK,OAAO,MAAM,CAAC,OAAM,KAAM,UAAU,EAAE;AAC1E,IAAA,MAAM,EAAC,GAAI,MAAM,CAAC,OAAO,CAACA,SAAC,CAAC,eAAe,EAAE,8BAA8B,CAAC,EAAA;AAC5E,IAAA,IAAI,CAAC,EAAE,EAAE;KACR,MAAK;AACN,KAAA;AACD,IAAA;AACA,GAAA,IAAI;AACH,IAAA,MAAM,QAAS,GAAE,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;AACxF,KAAA,MAAM,EAAE,QAAQ;KAChB,OAAO,EAAE,YAAY,EAAE;KACvB,EAAA;AACD,IAAA,IAAI,QAAQ,CAAC,EAAE,EAAE;KAChB,MAAM,IAAI,CAAC,eAAe,GAAC;AAC5B,KAAA,MAAO,IAAI,QAAQ,CAAC,MAAK,KAAM,GAAG,EAAE;AACnC,KAAA,IAAI,CAAC,KAAI,GAAIA,SAAC,CAAC,eAAe,EAAE,6CAA6C,EAAA;KAC5E,MAAK;KACN,IAAI,CAAC,KAAM,GAAEA,SAAC,CAAC,eAAe,EAAE,8BAA8B,EAAA;AAC/D,KAAA;IACC,CAAA,OAAO,GAAG,EAAE;AACb;AACA,IAAA,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,EAAA;IAC9C,IAAI,CAAC,KAAM,GAAEA,SAAC,CAAC,eAAe,EAAE,8BAA8B,EAAA;AAC/D,IAAA;GACA;EACD;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"CnFlowTab.vue2.js","sources":["../../../../../src/integrations/builtin/flow/CnFlowTab.vue"],"sourcesContent":["<!--\n CnFlowTab — bespoke sidebar tab for the `flow` (automation) integration.\n\n Renders a list of NC Flow (workflowengine) operations bound to the\n parent OR object via the Tier-2 `openregister_flow_links` table.\n Each row surfaces the operation name, the target entity class\n (short form), the operation type, a chips set of trigger events, a\n checks-count, and a (display-only) enabled toggle. A trailing\n \"Open in Flow settings\" deep-link points to\n `/index.php/settings/admin/workflow` (NC Flow is admin-gated, so\n edits happen in the admin settings, not in the sidebar tab).\n\n Talks to the Tier-2 link-table endpoints:\n GET /api/objects/{r}/{s}/{id}/flow (read, all users)\n POST /api/objects/{r}/{s}/{id}/flow (link, admin-only)\n DELETE /api/objects/{r}/{s}/{id}/flow/{operationId} (unlink, admin-only)\n\n Payload contract (per FlowProvider + FlowLinkService):\n { operationId, operationName, operationClass, entityType,\n enabled, url, linkId, events, checks, operation }\n + envelope `{ results, total, isAdmin }`\n\n Surface behaviour:\n - Admins see: \"Link existing automation\" button → CnFlowOperationPicker\n + per-row unlink action.\n - Non-admins see: read-only list, no link/unlink controls. The\n \"Open Flow settings\" deep-link is still surfaced so the user\n knows where automations live.\n - Loading + 503 \"currently unavailable\" + generic error states\n match CnIntegrationTab's behaviour for AD-23 graceful degradation.\n\n See `openregister/openspec/changes/integration-flow/` for the spec\n delta and ADR-019 (registry mechanism) / ADR-023 (action authorisation).\n-->\n<template>\n\t<div class=\"cn-sidebar-tab cn-flow-tab\">\n\t\t<div v-if=\"degraded\" class=\"cn-flow-tab__banner\" role=\"alert\">\n\t\t\t<AlertCircleOutline :size=\"18\" />\n\t\t\t<span>{{ degraded }}</span>\n\t\t</div>\n\n\t\t<div v-if=\"isAdmin && !loading && !error\" class=\"cn-flow-tab__actions\">\n\t\t\t<NcButton variant=\"secondary\" data-testid=\"cn-flow-tab-link\" @click=\"openPicker\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Plus :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('nextcloud-vue', 'Link existing automation') }}\n\t\t\t</NcButton>\n\t\t</div>\n\n\t\t<NcLoadingIcon v-if=\"loading\" />\n\t\t<div v-else-if=\"error\" class=\"cn-flow-tab__error\" role=\"alert\">\n\t\t\t{{ error }}\n\t\t</div>\n\t\t<div v-else-if=\"operations.length === 0\" class=\"cn-sidebar-tab__empty cn-flow-tab__empty\">\n\t\t\t<SitemapOutline :size=\"32\" class=\"cn-flow-tab__empty-icon\" />\n\t\t\t<p>{{ emptyLabel }}</p>\n\t\t\t<NcButton\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:href=\"flowSettingsUrl\"\n\t\t\t\ttarget=\"_blank\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<SitemapOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ openSettingsLabel }}\n\t\t\t</NcButton>\n\t\t</div>\n\t\t<ul v-else class=\"cn-flow-tab__list\">\n\t\t\t<NcListItem\n\t\t\t\tv-for=\"op in operations\"\n\t\t\t\t:key=\"opKey(op)\"\n\t\t\t\tclass=\"cn-flow-tab__row\"\n\t\t\t\t:class=\"{ 'cn-flow-tab__row--disabled': isDisabled(op) }\"\n\t\t\t\t:name=\"opTitle(op)\"\n\t\t\t\t:href=\"opUrl(op)\"\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\t:bold=\"true\"\n\t\t\t\t:forceDisplayActions=\"isAdmin\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<span class=\"cn-flow-tab__avatar\" :class=\"enabledClass(op)\" :aria-hidden=\"true\">\n\t\t\t\t\t\t<SitemapOutline :size=\"20\" />\n\t\t\t\t\t</span>\n\t\t\t\t</template>\n\t\t\t\t<template #subname>\n\t\t\t\t\t<span v-if=\"opSummary(op)\" class=\"cn-flow-tab__summary\">{{ opSummary(op) }}</span>\n\t\t\t\t</template>\n\t\t\t\t<template #indicator>\n\t\t\t\t\t<CnStatusBadge\n\t\t\t\t\t\tclass=\"cn-flow-tab__enabled\"\n\t\t\t\t\t\t:class=\"enabledClass(op)\"\n\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t:variant=\"enabledVariant(op)\"\n\t\t\t\t\t\t:label=\"enabledLabel(op)\"\n\t\t\t\t\t\t:aria-label=\"enabledAriaLabel(op)\" />\n\t\t\t\t</template>\n\t\t\t\t<template v-if=\"events(op).length > 0 || opMeta(op)\" #details>\n\t\t\t\t\t<span class=\"cn-flow-tab__details\">\n\t\t\t\t\t\t<span v-if=\"events(op).length > 0\" class=\"cn-flow-tab__events\">\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tv-for=\"evt in events(op)\"\n\t\t\t\t\t\t\t\t:key=\"evt\"\n\t\t\t\t\t\t\t\tclass=\"cn-flow-tab__chip\">{{ shortEvent(evt) }}</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span v-if=\"opMeta(op)\" class=\"cn-flow-tab__meta\">{{ opMeta(op) }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t</template>\n\t\t\t\t<template v-if=\"isAdmin\" #actions>\n\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\tclass=\"cn-flow-tab__unlink\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Unlink automation')\"\n\t\t\t\t\t\tdata-testid=\"cn-flow-tab-unlink\"\n\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t@click=\"confirmUnlink(op)\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<Close :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t{{ t('nextcloud-vue', 'Unlink automation') }}\n\t\t\t\t\t</NcActionButton>\n\t\t\t\t</template>\n\t\t\t</NcListItem>\n\t\t</ul>\n\n\t\t<CnFlowOperationPicker\n\t\t\tv-if=\"pickerOpen\"\n\t\t\t:apiBase=\"apiBase\"\n\t\t\t:flowSettingsUrl=\"flowSettingsUrl\"\n\t\t\t@close=\"pickerOpen = false\"\n\t\t\t@link=\"onLink\" />\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcActionButton, NcButton, NcListItem, NcLoadingIcon } from '@nextcloud/vue'\nimport AlertCircleOutline from 'vue-material-design-icons/AlertCircleOutline.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\nimport Plus from 'vue-material-design-icons/Plus.vue'\nimport SitemapOutline from 'vue-material-design-icons/SitemapOutline.vue'\nimport CnFlowOperationPicker from '../../../components/CnFlowOperationPicker/CnFlowOperationPicker.vue'\nimport CnStatusBadge from '../../../components/CnStatusBadge/CnStatusBadge.vue'\nimport { buildHeaders, prefixUrl, safeHref } from '../../../utils/index.js'\n\n/**\n * CnFlowTab — bespoke automation-rule list for the `flow` integration.\n *\n * Admins can link/unlink operations via the picker; non-admins see\n * a read-only list with a deep-link to NC Workflow Settings.\n */\nexport default {\n\tname: 'CnFlowTab',\n\n\tcomponents: { NcActionButton, NcButton, NcListItem, NcLoadingIcon, AlertCircleOutline, Close, Plus, SitemapOutline, CnFlowOperationPicker, CnStatusBadge },\n\n\tprops: {\n\t\t/* eslint-disable vue/no-unused-properties -- the integration dispatch binds integrationId on every integration component (see CnIntegrationWidgetGrid), so declaring it keeps it out of $attrs */\n\t\t/** Stable integration id (forwarded from the registry — always `'flow'`). */\n\t\tintegrationId: { type: String, default: 'flow' },\n\t\t/* eslint-enable vue/no-unused-properties */\n\t\t/** Parent object id. */\n\t\tobjectId: { type: String, required: true },\n\t\t/** OpenRegister register id (slug or uuid). */\n\t\tregister: { type: String, default: '' },\n\t\t/** OpenRegister schema id (slug or uuid). */\n\t\tschema: { type: String, default: '' },\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Pre-translated empty-state label. */\n\t\temptyLabel: { type: String, default: () => t('nextcloud-vue', 'No automations linked yet') },\n\t\t/** Pre-translated label for the \"Open Flow settings\" CTA. */\n\t\topenSettingsLabel: { type: String, default: () => t('nextcloud-vue', 'Open Workflow settings') },\n\t\t/** Pre-translated banner when Flow is unavailable. */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'NC Flow is currently unavailable.') },\n\t\t/** URL of the NC Flow admin settings page. */\n\t\tflowSettingsUrl: { type: String, default: '/index.php/settings/admin/workflow' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\toperations: [],\n\t\t\tloading: false,\n\t\t\terror: '',\n\t\t\tdegraded: '',\n\t\t\tisAdmin: false,\n\t\t\tpickerOpen: false,\n\t\t}\n\t},\n\n\twatch: {\n\t\tobjectId: { immediate: true, handler(id) {\n\t\t\tif (id) {\n\t\t\t\tthis.fetchOperations()\n\t\t\t}\n\t\t} },\n\n\t\tregister() {\n\t\t\tthis.fetchOperations()\n\t\t},\n\n\t\tschema() {\n\t\t\tthis.fetchOperations()\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\tbaseUrl() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/flow`\n\t\t},\n\n\t\topKey(op) {\n\t\t\treturn op.operationId ?? op.id ?? op.title ?? ''\n\t\t},\n\n\t\topTitle(op) {\n\t\t\treturn op.operationName || op.title || op.name || this.shortClass(op.operationClass) || t('nextcloud-vue', 'Untitled automation')\n\t\t},\n\n\t\topUrl(op) {\n\t\t\treturn op.url && safeHref(op.url) !== '#' ? op.url : this.flowSettingsUrl\n\t\t},\n\n\t\tshortClass(className) {\n\t\t\tif (!className) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst parts = String(className).split('\\\\')\n\t\t\treturn parts[parts.length - 1] || className\n\t\t},\n\n\t\tentityLabel(op) {\n\t\t\tconst entity = op.entityType || op.entity\n\t\t\tif (!entity) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn this.shortClass(entity)\n\t\t},\n\n\t\toperationLabel(op) {\n\t\t\treturn op.operation || ''\n\t\t},\n\n\t\topSummary(op) {\n\t\t\tconst parts = []\n\t\t\tconst entity = this.entityLabel(op)\n\t\t\tif (entity !== '') {\n\t\t\t\tparts.push(t('nextcloud-vue', 'Entity: {entity}', { entity }))\n\t\t\t}\n\t\t\tconst opLabel = this.operationLabel(op)\n\t\t\tif (opLabel !== '') {\n\t\t\t\tparts.push(t('nextcloud-vue', 'Operation: {op}', { op: opLabel }))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\tevents(op) {\n\t\t\tconst raw = op.events ?? op.data?.events ?? []\n\t\t\tif (Array.isArray(raw) === true) {\n\t\t\t\treturn raw.filter((e) => typeof e === 'string' && e !== '')\n\t\t\t}\n\t\t\treturn []\n\t\t},\n\n\t\tshortEvent(evt) {\n\t\t\tconst colon = String(evt).lastIndexOf(':')\n\t\t\tif (colon === -1) {\n\t\t\t\treturn String(evt)\n\t\t\t}\n\t\t\treturn String(evt).slice(colon + 1) || String(evt)\n\t\t},\n\n\t\tchecksCount(op) {\n\t\t\tconst raw = op.checks ?? op.data?.checks ?? []\n\t\t\tif (Array.isArray(raw) === true) {\n\t\t\t\treturn raw.length\n\t\t\t}\n\t\t\tif (typeof raw === 'string' && raw.startsWith('[') === true) {\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(raw)\n\t\t\t\t\treturn Array.isArray(parsed) === true ? parsed.length : 0\n\t\t\t\t} catch {\n\t\t\t\t\treturn 0\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn 0\n\t\t},\n\n\t\topMeta(op) {\n\t\t\tconst parts = []\n\t\t\tconst checks = this.checksCount(op)\n\t\t\tif (checks > 0) {\n\t\t\t\tparts.push(t('nextcloud-vue', '{n} conditions', { n: checks }))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\tisDisabled(op) {\n\t\t\tconst v = op.enabled ?? op.data?.enabled\n\t\t\tif (v === undefined || v === null) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn v === false || v === 0 || v === '0'\n\t\t},\n\n\t\tenabledLabel(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? t('nextcloud-vue', 'Disabled')\n\t\t\t\t: t('nextcloud-vue', 'Enabled')\n\t\t},\n\n\t\tenabledClass(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? 'cn-flow-tab__enabled--off'\n\t\t\t\t: 'cn-flow-tab__enabled--on'\n\t\t},\n\n\t\tenabledVariant(op) {\n\t\t\treturn this.isDisabled(op) === true ? 'default' : 'success'\n\t\t},\n\n\t\tenabledAriaLabel(op) {\n\t\t\treturn this.enabledLabel(op)\n\t\t},\n\n\t\topenPicker() {\n\t\t\tthis.pickerOpen = true\n\t\t},\n\n\t\tasync fetchOperations() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.error = ''\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tconst rows = data.results || data.items || (Array.isArray(data) ? data : []) || []\n\t\t\t\t\tthis.operations = rows\n\t\t\t\t\tthis.isAdmin = Boolean(data.isAdmin)\n\t\t\t\t} else if (response.status === 501) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = t('nextcloud-vue', 'NC Workflow Engine is not installed.')\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not load automations.')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowTab] failed to fetch operations', err)\n\t\t\t\tthis.operations = []\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not load automations.')\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync onLink({ operationId }) {\n\t\t\tthis.pickerOpen = false\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { ...buildHeaders(), 'Content-Type': 'application/json' },\n\t\t\t\t\tbody: JSON.stringify({ operationId }),\n\t\t\t\t})\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tawait this.fetchOperations()\n\t\t\t\t} else if (response.status === 403) {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Only administrators can link automations.')\n\t\t\t\t} else if (response.status === 409) {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Automation is already linked.')\n\t\t\t\t} else {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not link automation.')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowTab] link failed', err)\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not link automation.')\n\t\t\t}\n\t\t},\n\n\t\tasync confirmUnlink(op) {\n\t\t\tconst opId = op.operationId ?? op.id\n\t\t\tif (!opId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (typeof window !== 'undefined' && typeof window.confirm === 'function') {\n\t\t\t\tconst ok = window.confirm(t('nextcloud-vue', 'Remove this automation link?'))\n\t\t\t\tif (!ok) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.baseUrl()}/${encodeURIComponent(opId)}`), {\n\t\t\t\t\tmethod: 'DELETE',\n\t\t\t\t\theaders: buildHeaders(),\n\t\t\t\t})\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tawait this.fetchOperations()\n\t\t\t\t} else if (response.status === 403) {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Only administrators can unlink automations.')\n\t\t\t\t} else {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not unlink automation.')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowTab] unlink failed', err)\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not unlink automation.')\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-flow-tab__banner {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 8px 10px;\n\tmargin-bottom: 10px;\n\tborder-radius: var(--border-radius);\n\tbackground: var(--color-warning, #e9a40f);\n\tcolor: var(--color-main-background);\n\tfont-size: 0.9em;\n}\n\n.cn-flow-tab__actions {\n\tmargin-bottom: 8px;\n}\n\n.cn-flow-tab__error {\n\tcolor: var(--color-error);\n\tfont-size: 0.9em;\n\tmargin: 4px 0 8px;\n}\n\n.cn-flow-tab__empty {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 16px 8px;\n\tcolor: var(--color-text-maxcontrast);\n\ttext-align: center;\n}\n\n.cn-flow-tab__empty-icon {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-tab__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n/* Mirror NC Flow's rule rows: a round robot avatar, the bold rule\n name, a trigger/condition subline, and an enabled/disabled chip. */\n.cn-flow-tab__row--disabled {\n\topacity: 0.7;\n}\n\n.cn-flow-tab__avatar {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 36px;\n\theight: 36px;\n\tborder-radius: 50%;\n\tbackground: var(--color-background-dark);\n\tcolor: var(--color-text-maxcontrast);\n\tflex-shrink: 0;\n}\n\n.cn-flow-tab__avatar.cn-flow-tab__enabled--on {\n\tbackground: var(--color-primary-element-light, var(--color-background-dark));\n\tcolor: var(--color-primary-element, #0082c9);\n}\n\n.cn-flow-tab__avatar.cn-flow-tab__enabled--off {\n\tbackground: var(--color-background-dark);\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-tab__summary {\n\tfont-size: 0.85em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-flow-tab__meta {\n\tfont-size: 0.8em;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-tab__details {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tflex-wrap: wrap;\n\tgap: 6px;\n}\n\n.cn-flow-tab__events {\n\tdisplay: inline-flex;\n\tflex-wrap: wrap;\n\tgap: 4px;\n}\n\n.cn-flow-tab__chip {\n\tdisplay: inline-block;\n\tpadding: 1px 8px;\n\tborder-radius: 10px;\n\tbackground: var(--color-background-hover);\n\tcolor: var(--color-main-text);\n\tfont-size: 0.75em;\n}\n</style>\n"],"names":["CnFlowOperationPicker","CnStatusBadge","t"],"mappings":"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"}
|
|
@@ -87,8 +87,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
87
87
|
createVNode(_component_NcButton, {
|
|
88
88
|
variant: "primary",
|
|
89
89
|
href: $props.flowSettingsUrl,
|
|
90
|
-
target: "_blank"
|
|
91
|
-
rel: "noopener noreferrer"
|
|
90
|
+
target: "_blank"
|
|
92
91
|
}, {
|
|
93
92
|
icon: withCtx(() => [
|
|
94
93
|
createVNode(_component_SitemapOutline, { size: 20 })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnFlowTab.vue3.js","sources":["../../../../../src/integrations/builtin/flow/CnFlowTab.vue?vue&type=template&id=15f62f6e&lang.js"],"sourcesContent":["<!--\n CnFlowTab — bespoke sidebar tab for the `flow` (automation) integration.\n\n Renders a list of NC Flow (workflowengine) operations bound to the\n parent OR object via the Tier-2 `openregister_flow_links` table.\n Each row surfaces the operation name, the target entity class\n (short form), the operation type, a chips set of trigger events, a\n checks-count, and a (display-only) enabled toggle. A trailing\n \"Open in Flow settings\" deep-link points to\n `/index.php/settings/admin/workflow` (NC Flow is admin-gated, so\n edits happen in the admin settings, not in the sidebar tab).\n\n Talks to the Tier-2 link-table endpoints:\n GET /api/objects/{r}/{s}/{id}/flow (read, all users)\n POST /api/objects/{r}/{s}/{id}/flow (link, admin-only)\n DELETE /api/objects/{r}/{s}/{id}/flow/{operationId} (unlink, admin-only)\n\n Payload contract (per FlowProvider + FlowLinkService):\n { operationId, operationName, operationClass, entityType,\n enabled, url, linkId, events, checks, operation }\n + envelope `{ results, total, isAdmin }`\n\n Surface behaviour:\n - Admins see: \"Link existing automation\" button → CnFlowOperationPicker\n + per-row unlink action.\n - Non-admins see: read-only list, no link/unlink controls. The\n \"Open Flow settings\" deep-link is still surfaced so the user\n knows where automations live.\n - Loading + 503 \"currently unavailable\" + generic error states\n match CnIntegrationTab's behaviour for AD-23 graceful degradation.\n\n See `openregister/openspec/changes/integration-flow/` for the spec\n delta and ADR-019 (registry mechanism) / ADR-023 (action authorisation).\n-->\n<template>\n\t<div class=\"cn-sidebar-tab cn-flow-tab\">\n\t\t<div v-if=\"degraded\" class=\"cn-flow-tab__banner\" role=\"alert\">\n\t\t\t<AlertCircleOutline :size=\"18\" />\n\t\t\t<span>{{ degraded }}</span>\n\t\t</div>\n\n\t\t<div v-if=\"isAdmin && !loading && !error\" class=\"cn-flow-tab__actions\">\n\t\t\t<NcButton variant=\"secondary\" data-testid=\"cn-flow-tab-link\" @click=\"openPicker\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Plus :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('nextcloud-vue', 'Link existing automation') }}\n\t\t\t</NcButton>\n\t\t</div>\n\n\t\t<NcLoadingIcon v-if=\"loading\" />\n\t\t<div v-else-if=\"error\" class=\"cn-flow-tab__error\" role=\"alert\">\n\t\t\t{{ error }}\n\t\t</div>\n\t\t<div v-else-if=\"operations.length === 0\" class=\"cn-sidebar-tab__empty cn-flow-tab__empty\">\n\t\t\t<SitemapOutline :size=\"32\" class=\"cn-flow-tab__empty-icon\" />\n\t\t\t<p>{{ emptyLabel }}</p>\n\t\t\t<NcButton\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:href=\"flowSettingsUrl\"\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\trel=\"noopener noreferrer\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<SitemapOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ openSettingsLabel }}\n\t\t\t</NcButton>\n\t\t</div>\n\t\t<ul v-else class=\"cn-flow-tab__list\">\n\t\t\t<NcListItem\n\t\t\t\tv-for=\"op in operations\"\n\t\t\t\t:key=\"opKey(op)\"\n\t\t\t\tclass=\"cn-flow-tab__row\"\n\t\t\t\t:class=\"{ 'cn-flow-tab__row--disabled': isDisabled(op) }\"\n\t\t\t\t:name=\"opTitle(op)\"\n\t\t\t\t:href=\"opUrl(op)\"\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\t:bold=\"true\"\n\t\t\t\t:forceDisplayActions=\"isAdmin\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<span class=\"cn-flow-tab__avatar\" :class=\"enabledClass(op)\" :aria-hidden=\"true\">\n\t\t\t\t\t\t<SitemapOutline :size=\"20\" />\n\t\t\t\t\t</span>\n\t\t\t\t</template>\n\t\t\t\t<template #subname>\n\t\t\t\t\t<span v-if=\"opSummary(op)\" class=\"cn-flow-tab__summary\">{{ opSummary(op) }}</span>\n\t\t\t\t</template>\n\t\t\t\t<template #indicator>\n\t\t\t\t\t<CnStatusBadge\n\t\t\t\t\t\tclass=\"cn-flow-tab__enabled\"\n\t\t\t\t\t\t:class=\"enabledClass(op)\"\n\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t:variant=\"enabledVariant(op)\"\n\t\t\t\t\t\t:label=\"enabledLabel(op)\"\n\t\t\t\t\t\t:aria-label=\"enabledAriaLabel(op)\" />\n\t\t\t\t</template>\n\t\t\t\t<template v-if=\"events(op).length > 0 || opMeta(op)\" #details>\n\t\t\t\t\t<span class=\"cn-flow-tab__details\">\n\t\t\t\t\t\t<span v-if=\"events(op).length > 0\" class=\"cn-flow-tab__events\">\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tv-for=\"evt in events(op)\"\n\t\t\t\t\t\t\t\t:key=\"evt\"\n\t\t\t\t\t\t\t\tclass=\"cn-flow-tab__chip\">{{ shortEvent(evt) }}</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span v-if=\"opMeta(op)\" class=\"cn-flow-tab__meta\">{{ opMeta(op) }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t</template>\n\t\t\t\t<template v-if=\"isAdmin\" #actions>\n\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\tclass=\"cn-flow-tab__unlink\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Unlink automation')\"\n\t\t\t\t\t\tdata-testid=\"cn-flow-tab-unlink\"\n\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t@click=\"confirmUnlink(op)\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<Close :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t{{ t('nextcloud-vue', 'Unlink automation') }}\n\t\t\t\t\t</NcActionButton>\n\t\t\t\t</template>\n\t\t\t</NcListItem>\n\t\t</ul>\n\n\t\t<CnFlowOperationPicker\n\t\t\tv-if=\"pickerOpen\"\n\t\t\t:apiBase=\"apiBase\"\n\t\t\t:flowSettingsUrl=\"flowSettingsUrl\"\n\t\t\t@close=\"pickerOpen = false\"\n\t\t\t@link=\"onLink\" />\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcActionButton, NcButton, NcListItem, NcLoadingIcon } from '@nextcloud/vue'\nimport AlertCircleOutline from 'vue-material-design-icons/AlertCircleOutline.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\nimport Plus from 'vue-material-design-icons/Plus.vue'\nimport SitemapOutline from 'vue-material-design-icons/SitemapOutline.vue'\nimport CnFlowOperationPicker from '../../../components/CnFlowOperationPicker/CnFlowOperationPicker.vue'\nimport CnStatusBadge from '../../../components/CnStatusBadge/CnStatusBadge.vue'\nimport { buildHeaders, prefixUrl } from '../../../utils/index.js'\n\n/**\n * CnFlowTab — bespoke automation-rule list for the `flow` integration.\n *\n * Admins can link/unlink operations via the picker; non-admins see\n * a read-only list with a deep-link to NC Workflow Settings.\n */\nexport default {\n\tname: 'CnFlowTab',\n\n\tcomponents: { NcActionButton, NcButton, NcListItem, NcLoadingIcon, AlertCircleOutline, Close, Plus, SitemapOutline, CnFlowOperationPicker, CnStatusBadge },\n\n\tprops: {\n\t\t/* eslint-disable vue/no-unused-properties -- the integration dispatch binds integrationId on every integration component (see CnIntegrationWidgetGrid), so declaring it keeps it out of $attrs */\n\t\t/** Stable integration id (forwarded from the registry — always `'flow'`). */\n\t\tintegrationId: { type: String, default: 'flow' },\n\t\t/* eslint-enable vue/no-unused-properties */\n\t\t/** Parent object id. */\n\t\tobjectId: { type: String, required: true },\n\t\t/** OpenRegister register id (slug or uuid). */\n\t\tregister: { type: String, default: '' },\n\t\t/** OpenRegister schema id (slug or uuid). */\n\t\tschema: { type: String, default: '' },\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Pre-translated empty-state label. */\n\t\temptyLabel: { type: String, default: () => t('nextcloud-vue', 'No automations linked yet') },\n\t\t/** Pre-translated label for the \"Open Flow settings\" CTA. */\n\t\topenSettingsLabel: { type: String, default: () => t('nextcloud-vue', 'Open Workflow settings') },\n\t\t/** Pre-translated banner when Flow is unavailable. */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'NC Flow is currently unavailable.') },\n\t\t/** URL of the NC Flow admin settings page. */\n\t\tflowSettingsUrl: { type: String, default: '/index.php/settings/admin/workflow' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\toperations: [],\n\t\t\tloading: false,\n\t\t\terror: '',\n\t\t\tdegraded: '',\n\t\t\tisAdmin: false,\n\t\t\tpickerOpen: false,\n\t\t}\n\t},\n\n\twatch: {\n\t\tobjectId: { immediate: true, handler(id) {\n\t\t\tif (id) {\n\t\t\t\tthis.fetchOperations()\n\t\t\t}\n\t\t} },\n\n\t\tregister() {\n\t\t\tthis.fetchOperations()\n\t\t},\n\n\t\tschema() {\n\t\t\tthis.fetchOperations()\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\tbaseUrl() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/flow`\n\t\t},\n\n\t\topKey(op) {\n\t\t\treturn op.operationId ?? op.id ?? op.title ?? ''\n\t\t},\n\n\t\topTitle(op) {\n\t\t\treturn op.operationName || op.title || op.name || this.shortClass(op.operationClass) || t('nextcloud-vue', 'Untitled automation')\n\t\t},\n\n\t\topUrl(op) {\n\t\t\treturn op.url || this.flowSettingsUrl\n\t\t},\n\n\t\tshortClass(className) {\n\t\t\tif (!className) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst parts = String(className).split('\\\\')\n\t\t\treturn parts[parts.length - 1] || className\n\t\t},\n\n\t\tentityLabel(op) {\n\t\t\tconst entity = op.entityType || op.entity\n\t\t\tif (!entity) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn this.shortClass(entity)\n\t\t},\n\n\t\toperationLabel(op) {\n\t\t\treturn op.operation || ''\n\t\t},\n\n\t\topSummary(op) {\n\t\t\tconst parts = []\n\t\t\tconst entity = this.entityLabel(op)\n\t\t\tif (entity !== '') {\n\t\t\t\tparts.push(t('nextcloud-vue', 'Entity: {entity}', { entity }))\n\t\t\t}\n\t\t\tconst opLabel = this.operationLabel(op)\n\t\t\tif (opLabel !== '') {\n\t\t\t\tparts.push(t('nextcloud-vue', 'Operation: {op}', { op: opLabel }))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\tevents(op) {\n\t\t\tconst raw = op.events ?? op.data?.events ?? []\n\t\t\tif (Array.isArray(raw) === true) {\n\t\t\t\treturn raw.filter((e) => typeof e === 'string' && e !== '')\n\t\t\t}\n\t\t\treturn []\n\t\t},\n\n\t\tshortEvent(evt) {\n\t\t\tconst colon = String(evt).lastIndexOf(':')\n\t\t\tif (colon === -1) {\n\t\t\t\treturn String(evt)\n\t\t\t}\n\t\t\treturn String(evt).slice(colon + 1) || String(evt)\n\t\t},\n\n\t\tchecksCount(op) {\n\t\t\tconst raw = op.checks ?? op.data?.checks ?? []\n\t\t\tif (Array.isArray(raw) === true) {\n\t\t\t\treturn raw.length\n\t\t\t}\n\t\t\tif (typeof raw === 'string' && raw.startsWith('[') === true) {\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(raw)\n\t\t\t\t\treturn Array.isArray(parsed) === true ? parsed.length : 0\n\t\t\t\t} catch {\n\t\t\t\t\treturn 0\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn 0\n\t\t},\n\n\t\topMeta(op) {\n\t\t\tconst parts = []\n\t\t\tconst checks = this.checksCount(op)\n\t\t\tif (checks > 0) {\n\t\t\t\tparts.push(t('nextcloud-vue', '{n} conditions', { n: checks }))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\tisDisabled(op) {\n\t\t\tconst v = op.enabled ?? op.data?.enabled\n\t\t\tif (v === undefined || v === null) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn v === false || v === 0 || v === '0'\n\t\t},\n\n\t\tenabledLabel(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? t('nextcloud-vue', 'Disabled')\n\t\t\t\t: t('nextcloud-vue', 'Enabled')\n\t\t},\n\n\t\tenabledClass(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? 'cn-flow-tab__enabled--off'\n\t\t\t\t: 'cn-flow-tab__enabled--on'\n\t\t},\n\n\t\tenabledVariant(op) {\n\t\t\treturn this.isDisabled(op) === true ? 'default' : 'success'\n\t\t},\n\n\t\tenabledAriaLabel(op) {\n\t\t\treturn this.enabledLabel(op)\n\t\t},\n\n\t\topenPicker() {\n\t\t\tthis.pickerOpen = true\n\t\t},\n\n\t\tasync fetchOperations() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.error = ''\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tconst rows = data.results || data.items || (Array.isArray(data) ? data : []) || []\n\t\t\t\t\tthis.operations = rows\n\t\t\t\t\tthis.isAdmin = Boolean(data.isAdmin)\n\t\t\t\t} else if (response.status === 501) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = t('nextcloud-vue', 'NC Workflow Engine is not installed.')\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not load automations.')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowTab] failed to fetch operations', err)\n\t\t\t\tthis.operations = []\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not load automations.')\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync onLink({ operationId }) {\n\t\t\tthis.pickerOpen = false\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { ...buildHeaders(), 'Content-Type': 'application/json' },\n\t\t\t\t\tbody: JSON.stringify({ operationId }),\n\t\t\t\t})\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tawait this.fetchOperations()\n\t\t\t\t} else if (response.status === 403) {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Only administrators can link automations.')\n\t\t\t\t} else if (response.status === 409) {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Automation is already linked.')\n\t\t\t\t} else {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not link automation.')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowTab] link failed', err)\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not link automation.')\n\t\t\t}\n\t\t},\n\n\t\tasync confirmUnlink(op) {\n\t\t\tconst opId = op.operationId ?? op.id\n\t\t\tif (!opId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (typeof window !== 'undefined' && typeof window.confirm === 'function') {\n\t\t\t\tconst ok = window.confirm(t('nextcloud-vue', 'Remove this automation link?'))\n\t\t\t\tif (!ok) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.baseUrl()}/${encodeURIComponent(opId)}`), {\n\t\t\t\t\tmethod: 'DELETE',\n\t\t\t\t\theaders: buildHeaders(),\n\t\t\t\t})\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tawait this.fetchOperations()\n\t\t\t\t} else if (response.status === 403) {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Only administrators can unlink automations.')\n\t\t\t\t} else {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not unlink automation.')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowTab] unlink failed', err)\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not unlink automation.')\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-flow-tab__banner {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 8px 10px;\n\tmargin-bottom: 10px;\n\tborder-radius: var(--border-radius);\n\tbackground: var(--color-warning, #e9a40f);\n\tcolor: var(--color-main-background);\n\tfont-size: 0.9em;\n}\n\n.cn-flow-tab__actions {\n\tmargin-bottom: 8px;\n}\n\n.cn-flow-tab__error {\n\tcolor: var(--color-error);\n\tfont-size: 0.9em;\n\tmargin: 4px 0 8px;\n}\n\n.cn-flow-tab__empty {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 16px 8px;\n\tcolor: var(--color-text-maxcontrast);\n\ttext-align: center;\n}\n\n.cn-flow-tab__empty-icon {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-tab__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n/* Mirror NC Flow's rule rows: a round robot avatar, the bold rule\n name, a trigger/condition subline, and an enabled/disabled chip. */\n.cn-flow-tab__row--disabled {\n\topacity: 0.7;\n}\n\n.cn-flow-tab__avatar {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 36px;\n\theight: 36px;\n\tborder-radius: 50%;\n\tbackground: var(--color-background-dark);\n\tcolor: var(--color-text-maxcontrast);\n\tflex-shrink: 0;\n}\n\n.cn-flow-tab__avatar.cn-flow-tab__enabled--on {\n\tbackground: var(--color-primary-element-light, var(--color-background-dark));\n\tcolor: var(--color-primary-element, #0082c9);\n}\n\n.cn-flow-tab__avatar.cn-flow-tab__enabled--off {\n\tbackground: var(--color-background-dark);\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-tab__summary {\n\tfont-size: 0.85em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-flow-tab__meta {\n\tfont-size: 0.8em;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-tab__details {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tflex-wrap: wrap;\n\tgap: 6px;\n}\n\n.cn-flow-tab__events {\n\tdisplay: inline-flex;\n\tflex-wrap: wrap;\n\tgap: 4px;\n}\n\n.cn-flow-tab__chip {\n\tdisplay: inline-block;\n\tpadding: 1px 8px;\n\tborder-radius: 10px;\n\tbackground: var(--color-background-hover);\n\tcolor: var(--color-main-text);\n\tfont-size: 0.75em;\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_createVNode","_createTextVNode","_createBlock","_toDisplayString","_normalizeClass","_createElementVNode"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnFlowTab.vue3.js","sources":["../../../../../src/integrations/builtin/flow/CnFlowTab.vue?vue&type=template&id=15f62f6e&lang.js"],"sourcesContent":["<!--\n CnFlowTab — bespoke sidebar tab for the `flow` (automation) integration.\n\n Renders a list of NC Flow (workflowengine) operations bound to the\n parent OR object via the Tier-2 `openregister_flow_links` table.\n Each row surfaces the operation name, the target entity class\n (short form), the operation type, a chips set of trigger events, a\n checks-count, and a (display-only) enabled toggle. A trailing\n \"Open in Flow settings\" deep-link points to\n `/index.php/settings/admin/workflow` (NC Flow is admin-gated, so\n edits happen in the admin settings, not in the sidebar tab).\n\n Talks to the Tier-2 link-table endpoints:\n GET /api/objects/{r}/{s}/{id}/flow (read, all users)\n POST /api/objects/{r}/{s}/{id}/flow (link, admin-only)\n DELETE /api/objects/{r}/{s}/{id}/flow/{operationId} (unlink, admin-only)\n\n Payload contract (per FlowProvider + FlowLinkService):\n { operationId, operationName, operationClass, entityType,\n enabled, url, linkId, events, checks, operation }\n + envelope `{ results, total, isAdmin }`\n\n Surface behaviour:\n - Admins see: \"Link existing automation\" button → CnFlowOperationPicker\n + per-row unlink action.\n - Non-admins see: read-only list, no link/unlink controls. The\n \"Open Flow settings\" deep-link is still surfaced so the user\n knows where automations live.\n - Loading + 503 \"currently unavailable\" + generic error states\n match CnIntegrationTab's behaviour for AD-23 graceful degradation.\n\n See `openregister/openspec/changes/integration-flow/` for the spec\n delta and ADR-019 (registry mechanism) / ADR-023 (action authorisation).\n-->\n<template>\n\t<div class=\"cn-sidebar-tab cn-flow-tab\">\n\t\t<div v-if=\"degraded\" class=\"cn-flow-tab__banner\" role=\"alert\">\n\t\t\t<AlertCircleOutline :size=\"18\" />\n\t\t\t<span>{{ degraded }}</span>\n\t\t</div>\n\n\t\t<div v-if=\"isAdmin && !loading && !error\" class=\"cn-flow-tab__actions\">\n\t\t\t<NcButton variant=\"secondary\" data-testid=\"cn-flow-tab-link\" @click=\"openPicker\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Plus :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('nextcloud-vue', 'Link existing automation') }}\n\t\t\t</NcButton>\n\t\t</div>\n\n\t\t<NcLoadingIcon v-if=\"loading\" />\n\t\t<div v-else-if=\"error\" class=\"cn-flow-tab__error\" role=\"alert\">\n\t\t\t{{ error }}\n\t\t</div>\n\t\t<div v-else-if=\"operations.length === 0\" class=\"cn-sidebar-tab__empty cn-flow-tab__empty\">\n\t\t\t<SitemapOutline :size=\"32\" class=\"cn-flow-tab__empty-icon\" />\n\t\t\t<p>{{ emptyLabel }}</p>\n\t\t\t<NcButton\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:href=\"flowSettingsUrl\"\n\t\t\t\ttarget=\"_blank\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<SitemapOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ openSettingsLabel }}\n\t\t\t</NcButton>\n\t\t</div>\n\t\t<ul v-else class=\"cn-flow-tab__list\">\n\t\t\t<NcListItem\n\t\t\t\tv-for=\"op in operations\"\n\t\t\t\t:key=\"opKey(op)\"\n\t\t\t\tclass=\"cn-flow-tab__row\"\n\t\t\t\t:class=\"{ 'cn-flow-tab__row--disabled': isDisabled(op) }\"\n\t\t\t\t:name=\"opTitle(op)\"\n\t\t\t\t:href=\"opUrl(op)\"\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\t:bold=\"true\"\n\t\t\t\t:forceDisplayActions=\"isAdmin\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<span class=\"cn-flow-tab__avatar\" :class=\"enabledClass(op)\" :aria-hidden=\"true\">\n\t\t\t\t\t\t<SitemapOutline :size=\"20\" />\n\t\t\t\t\t</span>\n\t\t\t\t</template>\n\t\t\t\t<template #subname>\n\t\t\t\t\t<span v-if=\"opSummary(op)\" class=\"cn-flow-tab__summary\">{{ opSummary(op) }}</span>\n\t\t\t\t</template>\n\t\t\t\t<template #indicator>\n\t\t\t\t\t<CnStatusBadge\n\t\t\t\t\t\tclass=\"cn-flow-tab__enabled\"\n\t\t\t\t\t\t:class=\"enabledClass(op)\"\n\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t:variant=\"enabledVariant(op)\"\n\t\t\t\t\t\t:label=\"enabledLabel(op)\"\n\t\t\t\t\t\t:aria-label=\"enabledAriaLabel(op)\" />\n\t\t\t\t</template>\n\t\t\t\t<template v-if=\"events(op).length > 0 || opMeta(op)\" #details>\n\t\t\t\t\t<span class=\"cn-flow-tab__details\">\n\t\t\t\t\t\t<span v-if=\"events(op).length > 0\" class=\"cn-flow-tab__events\">\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tv-for=\"evt in events(op)\"\n\t\t\t\t\t\t\t\t:key=\"evt\"\n\t\t\t\t\t\t\t\tclass=\"cn-flow-tab__chip\">{{ shortEvent(evt) }}</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span v-if=\"opMeta(op)\" class=\"cn-flow-tab__meta\">{{ opMeta(op) }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t</template>\n\t\t\t\t<template v-if=\"isAdmin\" #actions>\n\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\tclass=\"cn-flow-tab__unlink\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Unlink automation')\"\n\t\t\t\t\t\tdata-testid=\"cn-flow-tab-unlink\"\n\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t@click=\"confirmUnlink(op)\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<Close :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t{{ t('nextcloud-vue', 'Unlink automation') }}\n\t\t\t\t\t</NcActionButton>\n\t\t\t\t</template>\n\t\t\t</NcListItem>\n\t\t</ul>\n\n\t\t<CnFlowOperationPicker\n\t\t\tv-if=\"pickerOpen\"\n\t\t\t:apiBase=\"apiBase\"\n\t\t\t:flowSettingsUrl=\"flowSettingsUrl\"\n\t\t\t@close=\"pickerOpen = false\"\n\t\t\t@link=\"onLink\" />\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcActionButton, NcButton, NcListItem, NcLoadingIcon } from '@nextcloud/vue'\nimport AlertCircleOutline from 'vue-material-design-icons/AlertCircleOutline.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\nimport Plus from 'vue-material-design-icons/Plus.vue'\nimport SitemapOutline from 'vue-material-design-icons/SitemapOutline.vue'\nimport CnFlowOperationPicker from '../../../components/CnFlowOperationPicker/CnFlowOperationPicker.vue'\nimport CnStatusBadge from '../../../components/CnStatusBadge/CnStatusBadge.vue'\nimport { buildHeaders, prefixUrl, safeHref } from '../../../utils/index.js'\n\n/**\n * CnFlowTab — bespoke automation-rule list for the `flow` integration.\n *\n * Admins can link/unlink operations via the picker; non-admins see\n * a read-only list with a deep-link to NC Workflow Settings.\n */\nexport default {\n\tname: 'CnFlowTab',\n\n\tcomponents: { NcActionButton, NcButton, NcListItem, NcLoadingIcon, AlertCircleOutline, Close, Plus, SitemapOutline, CnFlowOperationPicker, CnStatusBadge },\n\n\tprops: {\n\t\t/* eslint-disable vue/no-unused-properties -- the integration dispatch binds integrationId on every integration component (see CnIntegrationWidgetGrid), so declaring it keeps it out of $attrs */\n\t\t/** Stable integration id (forwarded from the registry — always `'flow'`). */\n\t\tintegrationId: { type: String, default: 'flow' },\n\t\t/* eslint-enable vue/no-unused-properties */\n\t\t/** Parent object id. */\n\t\tobjectId: { type: String, required: true },\n\t\t/** OpenRegister register id (slug or uuid). */\n\t\tregister: { type: String, default: '' },\n\t\t/** OpenRegister schema id (slug or uuid). */\n\t\tschema: { type: String, default: '' },\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Pre-translated empty-state label. */\n\t\temptyLabel: { type: String, default: () => t('nextcloud-vue', 'No automations linked yet') },\n\t\t/** Pre-translated label for the \"Open Flow settings\" CTA. */\n\t\topenSettingsLabel: { type: String, default: () => t('nextcloud-vue', 'Open Workflow settings') },\n\t\t/** Pre-translated banner when Flow is unavailable. */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'NC Flow is currently unavailable.') },\n\t\t/** URL of the NC Flow admin settings page. */\n\t\tflowSettingsUrl: { type: String, default: '/index.php/settings/admin/workflow' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\toperations: [],\n\t\t\tloading: false,\n\t\t\terror: '',\n\t\t\tdegraded: '',\n\t\t\tisAdmin: false,\n\t\t\tpickerOpen: false,\n\t\t}\n\t},\n\n\twatch: {\n\t\tobjectId: { immediate: true, handler(id) {\n\t\t\tif (id) {\n\t\t\t\tthis.fetchOperations()\n\t\t\t}\n\t\t} },\n\n\t\tregister() {\n\t\t\tthis.fetchOperations()\n\t\t},\n\n\t\tschema() {\n\t\t\tthis.fetchOperations()\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\tbaseUrl() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/flow`\n\t\t},\n\n\t\topKey(op) {\n\t\t\treturn op.operationId ?? op.id ?? op.title ?? ''\n\t\t},\n\n\t\topTitle(op) {\n\t\t\treturn op.operationName || op.title || op.name || this.shortClass(op.operationClass) || t('nextcloud-vue', 'Untitled automation')\n\t\t},\n\n\t\topUrl(op) {\n\t\t\treturn op.url && safeHref(op.url) !== '#' ? op.url : this.flowSettingsUrl\n\t\t},\n\n\t\tshortClass(className) {\n\t\t\tif (!className) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst parts = String(className).split('\\\\')\n\t\t\treturn parts[parts.length - 1] || className\n\t\t},\n\n\t\tentityLabel(op) {\n\t\t\tconst entity = op.entityType || op.entity\n\t\t\tif (!entity) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn this.shortClass(entity)\n\t\t},\n\n\t\toperationLabel(op) {\n\t\t\treturn op.operation || ''\n\t\t},\n\n\t\topSummary(op) {\n\t\t\tconst parts = []\n\t\t\tconst entity = this.entityLabel(op)\n\t\t\tif (entity !== '') {\n\t\t\t\tparts.push(t('nextcloud-vue', 'Entity: {entity}', { entity }))\n\t\t\t}\n\t\t\tconst opLabel = this.operationLabel(op)\n\t\t\tif (opLabel !== '') {\n\t\t\t\tparts.push(t('nextcloud-vue', 'Operation: {op}', { op: opLabel }))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\tevents(op) {\n\t\t\tconst raw = op.events ?? op.data?.events ?? []\n\t\t\tif (Array.isArray(raw) === true) {\n\t\t\t\treturn raw.filter((e) => typeof e === 'string' && e !== '')\n\t\t\t}\n\t\t\treturn []\n\t\t},\n\n\t\tshortEvent(evt) {\n\t\t\tconst colon = String(evt).lastIndexOf(':')\n\t\t\tif (colon === -1) {\n\t\t\t\treturn String(evt)\n\t\t\t}\n\t\t\treturn String(evt).slice(colon + 1) || String(evt)\n\t\t},\n\n\t\tchecksCount(op) {\n\t\t\tconst raw = op.checks ?? op.data?.checks ?? []\n\t\t\tif (Array.isArray(raw) === true) {\n\t\t\t\treturn raw.length\n\t\t\t}\n\t\t\tif (typeof raw === 'string' && raw.startsWith('[') === true) {\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(raw)\n\t\t\t\t\treturn Array.isArray(parsed) === true ? parsed.length : 0\n\t\t\t\t} catch {\n\t\t\t\t\treturn 0\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn 0\n\t\t},\n\n\t\topMeta(op) {\n\t\t\tconst parts = []\n\t\t\tconst checks = this.checksCount(op)\n\t\t\tif (checks > 0) {\n\t\t\t\tparts.push(t('nextcloud-vue', '{n} conditions', { n: checks }))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\tisDisabled(op) {\n\t\t\tconst v = op.enabled ?? op.data?.enabled\n\t\t\tif (v === undefined || v === null) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn v === false || v === 0 || v === '0'\n\t\t},\n\n\t\tenabledLabel(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? t('nextcloud-vue', 'Disabled')\n\t\t\t\t: t('nextcloud-vue', 'Enabled')\n\t\t},\n\n\t\tenabledClass(op) {\n\t\t\treturn this.isDisabled(op) === true\n\t\t\t\t? 'cn-flow-tab__enabled--off'\n\t\t\t\t: 'cn-flow-tab__enabled--on'\n\t\t},\n\n\t\tenabledVariant(op) {\n\t\t\treturn this.isDisabled(op) === true ? 'default' : 'success'\n\t\t},\n\n\t\tenabledAriaLabel(op) {\n\t\t\treturn this.enabledLabel(op)\n\t\t},\n\n\t\topenPicker() {\n\t\t\tthis.pickerOpen = true\n\t\t},\n\n\t\tasync fetchOperations() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.error = ''\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tconst rows = data.results || data.items || (Array.isArray(data) ? data : []) || []\n\t\t\t\t\tthis.operations = rows\n\t\t\t\t\tthis.isAdmin = Boolean(data.isAdmin)\n\t\t\t\t} else if (response.status === 501) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = t('nextcloud-vue', 'NC Workflow Engine is not installed.')\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.operations = []\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not load automations.')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowTab] failed to fetch operations', err)\n\t\t\t\tthis.operations = []\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not load automations.')\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync onLink({ operationId }) {\n\t\t\tthis.pickerOpen = false\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { ...buildHeaders(), 'Content-Type': 'application/json' },\n\t\t\t\t\tbody: JSON.stringify({ operationId }),\n\t\t\t\t})\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tawait this.fetchOperations()\n\t\t\t\t} else if (response.status === 403) {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Only administrators can link automations.')\n\t\t\t\t} else if (response.status === 409) {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Automation is already linked.')\n\t\t\t\t} else {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not link automation.')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowTab] link failed', err)\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not link automation.')\n\t\t\t}\n\t\t},\n\n\t\tasync confirmUnlink(op) {\n\t\t\tconst opId = op.operationId ?? op.id\n\t\t\tif (!opId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (typeof window !== 'undefined' && typeof window.confirm === 'function') {\n\t\t\t\tconst ok = window.confirm(t('nextcloud-vue', 'Remove this automation link?'))\n\t\t\t\tif (!ok) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.baseUrl()}/${encodeURIComponent(opId)}`), {\n\t\t\t\t\tmethod: 'DELETE',\n\t\t\t\t\theaders: buildHeaders(),\n\t\t\t\t})\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tawait this.fetchOperations()\n\t\t\t\t} else if (response.status === 403) {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Only administrators can unlink automations.')\n\t\t\t\t} else {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not unlink automation.')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnFlowTab] unlink failed', err)\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not unlink automation.')\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-flow-tab__banner {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 8px 10px;\n\tmargin-bottom: 10px;\n\tborder-radius: var(--border-radius);\n\tbackground: var(--color-warning, #e9a40f);\n\tcolor: var(--color-main-background);\n\tfont-size: 0.9em;\n}\n\n.cn-flow-tab__actions {\n\tmargin-bottom: 8px;\n}\n\n.cn-flow-tab__error {\n\tcolor: var(--color-error);\n\tfont-size: 0.9em;\n\tmargin: 4px 0 8px;\n}\n\n.cn-flow-tab__empty {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 16px 8px;\n\tcolor: var(--color-text-maxcontrast);\n\ttext-align: center;\n}\n\n.cn-flow-tab__empty-icon {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-tab__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n/* Mirror NC Flow's rule rows: a round robot avatar, the bold rule\n name, a trigger/condition subline, and an enabled/disabled chip. */\n.cn-flow-tab__row--disabled {\n\topacity: 0.7;\n}\n\n.cn-flow-tab__avatar {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 36px;\n\theight: 36px;\n\tborder-radius: 50%;\n\tbackground: var(--color-background-dark);\n\tcolor: var(--color-text-maxcontrast);\n\tflex-shrink: 0;\n}\n\n.cn-flow-tab__avatar.cn-flow-tab__enabled--on {\n\tbackground: var(--color-primary-element-light, var(--color-background-dark));\n\tcolor: var(--color-primary-element, #0082c9);\n}\n\n.cn-flow-tab__avatar.cn-flow-tab__enabled--off {\n\tbackground: var(--color-background-dark);\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-tab__summary {\n\tfont-size: 0.85em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-flow-tab__meta {\n\tfont-size: 0.8em;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-tab__details {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tflex-wrap: wrap;\n\tgap: 6px;\n}\n\n.cn-flow-tab__events {\n\tdisplay: inline-flex;\n\tflex-wrap: wrap;\n\tgap: 4px;\n}\n\n.cn-flow-tab__chip {\n\tdisplay: inline-block;\n\tpadding: 1px 8px;\n\tborder-radius: 10px;\n\tbackground: var(--color-background-hover);\n\tcolor: var(--color-main-text);\n\tfont-size: 0.75em;\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_createVNode","_createTextVNode","_createBlock","_toDisplayString","_normalizeClass","_createElementVNode"],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { translate, translatePlural } from '@nextcloud/l10n';
|
|
|
2
2
|
import { NcLoadingIcon } from '@nextcloud/vue';
|
|
3
3
|
import ClipboardText from 'vue-material-design-icons/ClipboardText.vue';
|
|
4
4
|
import __sfc_main from '../../../components/CnDetailCard/CnDetailCard.vue.js';
|
|
5
|
+
import { safeHref } from '../../../utils/safeHref.js';
|
|
5
6
|
import { prefixUrl, buildHeaders } from '../../../utils/headers.js';
|
|
6
7
|
|
|
7
8
|
const VALID_SURFACES = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity'];
|
|
@@ -191,8 +192,9 @@ var script = {
|
|
|
191
192
|
return form.title || form.id || translate('nextcloud-vue', 'Untitled form')
|
|
192
193
|
},
|
|
193
194
|
|
|
195
|
+
// A provider URL is used only when it is a safe scheme; else the app link.
|
|
194
196
|
formUrl(form) {
|
|
195
|
-
if (form.url) {
|
|
197
|
+
if (form.url && safeHref(form.url) !== '#') {
|
|
196
198
|
return form.url
|
|
197
199
|
}
|
|
198
200
|
if (form.hash) {
|