@conduction/nextcloud-vue 2.56.0-beta.36 → 2.56.0-beta.38
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/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js +131 -3
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +54 -18
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
- package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue.js +1 -1
- package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue2.js +3 -2
- package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue2.js.map +1 -1
- package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue3.js.map +1 -1
- package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue.js +1 -1
- package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue2.js +5 -4
- package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue2.js.map +1 -1
- package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue3.js.map +1 -1
- package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue.js +1 -1
- package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue2.js +2 -1
- package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue2.js.map +1 -1
- package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue3.js.map +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue.js +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js +2 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js.map +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue3.js.map +1 -1
- package/dist/esm/components/CnBoardView/CnBoardView.vue.js +1 -1
- package/dist/esm/components/CnBoardView/CnBoardView.vue2.js +376 -6
- package/dist/esm/components/CnBoardView/CnBoardView.vue2.js.map +1 -1
- package/dist/esm/components/CnBoardView/CnBoardView.vue3.js +146 -71
- package/dist/esm/components/CnBoardView/CnBoardView.vue3.js.map +1 -1
- package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue.js +1 -1
- package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue2.js +2 -1
- package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue2.js.map +1 -1
- package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue3.js.map +1 -1
- package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue.js +1 -1
- package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue2.js +2 -1
- package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +6 -5
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue.js +1 -1
- package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue2.js +2 -1
- package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue2.js.map +1 -1
- package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue3.js.map +1 -1
- package/dist/esm/components/CnConversationThread/CnConversationThread.vue.js +1 -1
- package/dist/esm/components/CnConversationThread/CnConversationThread.vue2.js +2 -1
- package/dist/esm/components/CnConversationThread/CnConversationThread.vue2.js.map +1 -1
- package/dist/esm/components/CnConversationThread/CnConversationThread.vue3.js.map +1 -1
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue.js +1 -1
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js +2 -1
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +47 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +22 -12
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue.js +1 -1
- package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue2.js +3 -1
- package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue2.js.map +1 -1
- package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailHeaderChips.vue2.js +2 -1
- package/dist/esm/components/CnDetailPage/CnDetailHeaderChips.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailHeaderChips.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +23 -4
- 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/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +3 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue.js +1 -1
- package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue2.js +2 -1
- package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue2.js.map +1 -1
- package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue3.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +18 -5
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue.js +1 -1
- package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue2.js +3 -1
- package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue2.js.map +1 -1
- package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue3.js.map +1 -1
- package/dist/esm/components/CnFileManager/CnFileManager.vue.js +1 -1
- package/dist/esm/components/CnFileManager/CnFileManager.vue2.js +3 -1
- package/dist/esm/components/CnFileManager/CnFileManager.vue2.js.map +1 -1
- package/dist/esm/components/CnFileManager/CnFileManager.vue3.js.map +1 -1
- package/dist/esm/components/CnFilePreview/CnFilePreview.vue.js +1 -1
- package/dist/esm/components/CnFilePreview/CnFilePreview.vue2.js +2 -1
- package/dist/esm/components/CnFilePreview/CnFilePreview.vue2.js.map +1 -1
- package/dist/esm/components/CnFilePreview/CnFilePreview.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +49 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +3 -3
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue.js +1 -1
- package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js +2 -1
- package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js.map +1 -1
- package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +571 -77
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +191 -82
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js +11 -2
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue.js +1 -1
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue2.js +2 -1
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue2.js.map +1 -1
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue.js +1 -1
- package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue2.js +3 -2
- package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js +28 -0
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js +82 -75
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue2.js +5 -4
- package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue.js +1 -1
- package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue2.js +2 -1
- package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue.js +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue2.js +2 -1
- package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue.js +1 -1
- package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js +2 -1
- package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue.js +1 -1
- package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue2.js +2 -1
- package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue3.js.map +1 -1
- package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue.js +1 -1
- package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue2.js +2 -1
- package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue2.js.map +1 -1
- package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +70 -2
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue.js +1 -1
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue2.js +67 -5
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue2.js.map +1 -1
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue3.js +181 -124
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue3.js.map +1 -1
- package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue.js +1 -1
- package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue2.js +2 -1
- package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue2.js.map +1 -1
- package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue3.js.map +1 -1
- package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue2.js +2 -0
- package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue3.js +2 -2
- package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue.js +1 -1
- package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js +5 -1
- package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js.map +1 -1
- package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue.js +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +134 -10
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +6 -2
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue.js +1 -1
- package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js +2 -1
- package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js.map +1 -1
- package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue3.js.map +1 -1
- package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue.js +1 -1
- package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue2.js +2 -1
- package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue2.js.map +1 -1
- package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +6 -3
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTasksCard/CnTasksCard.vue.js +1 -1
- package/dist/esm/components/CnTasksCard/CnTasksCard.vue2.js +2 -1
- package/dist/esm/components/CnTasksCard/CnTasksCard.vue2.js.map +1 -1
- package/dist/esm/components/CnTasksCard/CnTasksCard.vue3.js.map +1 -1
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js +1 -1
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js +2 -1
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js +1 -1
- package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js +140 -7
- package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTranslatedBadge/CnTranslatedBadge.vue.js +1 -1
- package/dist/esm/components/CnTranslatedBadge/CnTranslatedBadge.vue2.js +2 -1
- package/dist/esm/components/CnTranslatedBadge/CnTranslatedBadge.vue2.js.map +1 -1
- package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue.js +1 -1
- package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue2.js +2 -1
- package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue2.js.map +1 -1
- package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue3.js.map +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue.js +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js +37 -9
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js.map +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js +6 -5
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue2.js +53 -1
- package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue3.js +3 -2
- package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +135 -0
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue.js +1 -1
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js +19 -0
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js +37 -19
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js.map +1 -1
- package/dist/esm/composables/useListView.js +21 -0
- package/dist/esm/composables/useListView.js.map +1 -1
- package/dist/esm/dialogs/CnNoteHistoryDialog.vue.js +1 -1
- package/dist/esm/dialogs/CnNoteHistoryDialog.vue2.js +2 -1
- package/dist/esm/dialogs/CnNoteHistoryDialog.vue2.js.map +1 -1
- package/dist/esm/dialogs/CnNoteHistoryDialog.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/activity/CnActivityCard.vue.js +1 -1
- package/dist/esm/integrations/builtin/activity/CnActivityCard.vue2.js +3 -2
- package/dist/esm/integrations/builtin/activity/CnActivityCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/activity/CnActivityCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/activity/CnActivityTab.vue.js +1 -1
- package/dist/esm/integrations/builtin/activity/CnActivityTab.vue2.js +4 -3
- package/dist/esm/integrations/builtin/activity/CnActivityTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/activity/CnActivityTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue.js +1 -1
- package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue2.js +3 -2
- package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue.js +1 -1
- package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue2.js +2 -1
- package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue.js +1 -1
- package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue2.js +6 -5
- package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue.js +1 -1
- package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue2.js +2 -1
- package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue.js +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.map +1 -1
- package/dist/esm/integrations/builtin/deck/CnDeckTab.vue.js +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.map +1 -1
- package/dist/esm/integrations/builtin/email/CnEmailCard.vue.js +1 -1
- package/dist/esm/integrations/builtin/email/CnEmailCard.vue2.js +2 -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/field-inspection/CnFieldInspectionCard.vue.js +1 -1
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js +2 -1
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue.js +1 -1
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue2.js +2 -1
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue.js +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.map +1 -1
- package/dist/esm/l10n/en.json.js +57 -2
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +78 -2
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +1541 -1166
- package/dist/esm/store/useObjectStore.js +23 -4
- package/dist/esm/store/useObjectStore.js.map +1 -1
- package/dist/esm/utils/boardColumns.js +58 -2
- package/dist/esm/utils/boardColumns.js.map +1 -1
- package/dist/esm/utils/boardReferenceColumns.js +330 -0
- package/dist/esm/utils/boardReferenceColumns.js.map +1 -0
- package/dist/esm/utils/buildManifest.js +4 -1
- package/dist/esm/utils/buildManifest.js.map +1 -1
- package/dist/esm/utils/schema.js +5 -4
- package/dist/esm/utils/schema.js.map +1 -1
- package/dist/esm/utils/userLocale.js +30 -0
- package/dist/esm/utils/userLocale.js.map +1 -0
- package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/widgetDispatch.js +8 -2
- package/dist/esm/utils/widgetDispatch.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +30291 -27618
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +1541 -1166
- package/l10n/en.json +57 -2
- package/l10n/nl.json +78 -2
- package/package.json +1 -1
- package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +160 -8
- package/src/components/CnAdvancedFormDialog/CnMetadataTab.vue +3 -2
- package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +5 -4
- package/src/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue +2 -1
- package/src/components/CnAuditTrailCard/CnAuditTrailCard.vue +2 -1
- package/src/components/CnBoardView/CnBoardView.vue +433 -12
- package/src/components/CnCalendarEventPicker/CnCalendarEventPicker.vue +2 -1
- package/src/components/CnCalendarWidget/CnCalendarWidget.vue +2 -1
- package/src/components/CnChartWidget/CnChartWidget.vue +6 -5
- package/src/components/CnCollectivePagePicker/CnCollectivePagePicker.vue +2 -1
- package/src/components/CnConversationThread/CnConversationThread.vue +2 -1
- package/src/components/CnCountdownWidget/CnCountdownWidget.vue +2 -1
- package/src/components/CnDashboardPage/CnDashboardPage.vue +59 -3
- package/src/components/CnDataMatrix/CnDataMatrix.vue +2 -1
- package/src/components/CnDetailPage/CnDetailHeaderChips.vue +2 -1
- package/src/components/CnDetailPage/CnDetailPage.md +1 -1
- package/src/components/CnDetailPage/CnDetailPage.vue +23 -4
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +3 -1
- package/src/components/CnEmailPicker/CnEmailPicker.vue +2 -1
- package/src/components/CnFactsWidget/CnFactsWidget.vue +18 -5
- package/src/components/CnFederationStatus/CnFederationStatus.vue +3 -1
- package/src/components/CnFileManager/CnFileManager.vue +2 -1
- package/src/components/CnFilePreview/CnFilePreview.vue +2 -1
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +54 -6
- package/src/components/CnFollowToggle/CnFollowToggle.vue +2 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +610 -25
- package/src/components/CnIndexPage/useSelfFetchList.js +10 -1
- package/src/components/CnNotesCard/CnNotesCard.vue +2 -1
- package/src/components/CnObjectCalendar/CnObjectCalendar.vue +3 -2
- package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +36 -0
- package/src/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue +5 -4
- package/src/components/CnObjectSidebar/CnAuditTrailTab.vue +2 -1
- package/src/components/CnObjectSidebar/CnFlowTasksPanel.vue +2 -1
- package/src/components/CnObjectSidebar/CnNotesTab.vue +2 -1
- package/src/components/CnObjectSidebar/CnTasksTab.vue +2 -1
- package/src/components/CnPropertySourceField/CnPropertySourceField.vue +2 -1
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +70 -2
- package/src/components/CnRegisterMapping/CnRegisterMapping.md +5 -0
- package/src/components/CnRegisterMapping/CnRegisterMapping.vue +231 -96
- package/src/components/CnRoadmapItem/CnRoadmapItem.vue +2 -1
- package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +4 -2
- package/src/components/CnSettingsPage/CnSettingsPage.vue +5 -1
- package/src/components/CnStatWidget/CnStatWidget.vue +136 -11
- package/src/components/CnStatsBlock/CnStatsBlock.vue +2 -1
- package/src/components/CnSummaryAggregates/CnSummaryAggregates.vue +2 -1
- package/src/components/CnTabsWidget/CnTabsWidget.vue +6 -3
- package/src/components/CnTasksCard/CnTasksCard.vue +2 -1
- package/src/components/CnTimelineWidget/CnTimelineWidget.vue +2 -1
- package/src/components/CnToggleTableWidget/CnToggleTableWidget.vue +140 -7
- package/src/components/CnTranslatedBadge/CnTranslatedBadge.vue +2 -1
- package/src/components/CnVersionHistory/CnVersionHistory.vue +2 -1
- package/src/components/CnVersionInfoCard/CnVersionInfoCard.md +2 -1
- package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +42 -13
- package/src/components/CnWidgetCardGrid/CnWidgetCardGrid.vue +55 -2
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +135 -0
- package/src/components/CnWidgetWrapper/CnWidgetWrapper.md +10 -0
- package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +44 -1
- package/src/composables/useListView.js +21 -0
- package/src/css/board.css +105 -4
- package/src/css/dialog.css +4 -2
- package/src/css/index-page.css +49 -0
- package/src/css/look-board.css +77 -7
- package/src/dialogs/CnNoteHistoryDialog.vue +2 -1
- package/src/integrations/builtin/activity/CnActivityCard.vue +3 -2
- package/src/integrations/builtin/activity/CnActivityTab.vue +4 -3
- package/src/integrations/builtin/analytics/CnAnalyticsTab.vue +3 -2
- package/src/integrations/builtin/calendar/CnCalendarCard.vue +2 -1
- package/src/integrations/builtin/calendar/CnCalendarTab.vue +6 -5
- package/src/integrations/builtin/contactmoment/CnContactmomentCard.vue +2 -1
- package/src/integrations/builtin/cospend/CnCospendTab.vue +2 -1
- package/src/integrations/builtin/deck/CnDeckTab.vue +2 -1
- package/src/integrations/builtin/email/CnEmailCard.vue +2 -1
- package/src/integrations/builtin/field-inspection/CnFieldInspectionCard.vue +2 -1
- package/src/integrations/builtin/field-inspection/CnFieldInspectionTab.vue +2 -1
- package/src/integrations/builtin/photos/CnPhotosTab.vue +2 -1
- package/src/schemas/app-manifest-v2.schema.json +116 -5
- package/src/store/useObjectStore.js +23 -4
- package/src/utils/boardColumns.js +57 -1
- package/src/utils/boardReferenceColumns.js +326 -0
- package/src/utils/buildManifest.js +4 -1
- package/src/utils/schema.js +5 -4
- package/src/utils/userLocale.js +26 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
- package/src/utils/widgetDispatch.js +8 -2
|
@@ -23,6 +23,15 @@ function resolveInitialQuickFilterIndex(quickFilters) {
|
|
|
23
23
|
* @param {Array<object>} filterMaps Already route-resolved filter maps.
|
|
24
24
|
* @return {object} The merged filter (scalar when a key has one value, array when many).
|
|
25
25
|
*/
|
|
26
|
+
/**
|
|
27
|
+
* Rows one board fetch asks for. A board shows every matching row at once,
|
|
28
|
+
* so it loads far more than a table page (OpenRegister serves up to 1000);
|
|
29
|
+
* past this the board offers "Load more".
|
|
30
|
+
*
|
|
31
|
+
* @type {number}
|
|
32
|
+
*/
|
|
33
|
+
const BOARD_PAGE_SIZE = 500;
|
|
34
|
+
|
|
26
35
|
/**
|
|
27
36
|
* The sort a quick filter sets while it is active (`sort: { key, order }`, or a
|
|
28
37
|
* list of those for a multi-column order), as sort keys, or null when it sets
|
|
@@ -233,7 +242,7 @@ function useSelfFetchList(props, instance, inject, extras = {}) {
|
|
|
233
242
|
defaultSortKeys: initialSortKeys,
|
|
234
243
|
defaultActiveFilters: initialActiveFilters,
|
|
235
244
|
defaultSearchTerm: initialSearchTerm,
|
|
236
|
-
defaultPageSize: (props.pagination && props.pagination.limit) || undefined,
|
|
245
|
+
defaultPageSize: props.viewMode === 'board' ? BOARD_PAGE_SIZE : ((props.pagination && props.pagination.limit) || undefined),
|
|
237
246
|
defaultVisibleColumns: configuredColumnKeys.length ? configuredColumnKeys : null,
|
|
238
247
|
// `pages[].config.extend` → OpenRegister's repeated `_extend[]`. A
|
|
239
248
|
// getter so a reactive change re-scopes the next fetch, matching how
|
|
@@ -337,5 +346,5 @@ function useSelfFetchList(props, instance, inject, extras = {}) {
|
|
|
337
346
|
}
|
|
338
347
|
}
|
|
339
348
|
|
|
340
|
-
export { quickFilterSortKeys, useSelfFetchList };
|
|
349
|
+
export { BOARD_PAGE_SIZE, quickFilterSortKeys, useSelfFetchList };
|
|
341
350
|
//# sourceMappingURL=useSelfFetchList.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSelfFetchList.js","sources":["../../../../src/components/CnIndexPage/useSelfFetchList.js"],"sourcesContent":["import { computed, ref, watch } from 'vue'\nimport { useListView } from '../../composables/index.js'\nimport { useObjectSubscription } from '../../composables/useObjectSubscription.js'\nimport { useObjectStore } from '../../store/index.js'\n// Both filter resolvers live in `utils/routeFilters.js` so CnLogsPage applies\n// the same two grammars (route-param interpolation + `?key=value` deep links)\n// without pulling in this composable's index-only sidebar/subscription wiring.\nimport { withPersonalLenses } from '../../utils/personalLenses.js'\nimport { parseSortKeysFromQuery, resolveFilterMap, resolveQueryFilters } from '../../utils/routeFilters.js'\n\nfunction resolveInitialQuickFilterIndex(quickFilters) {\n\tconst tabs = Array.isArray(quickFilters) ? quickFilters : null\n\tif (!tabs || tabs.length === 0) {\n\t\treturn null\n\t}\n\tconst di = tabs.findIndex((t) => t && t.default === true)\n\treturn di >= 0 ? di : 0\n}\n\n/**\n * OR-merge several quick-filter maps into one fetch filter. Values for the\n * same key collapse to an array (deduped) when more than one tab contributes\n * it — `buildQueryString` serialises an array as `key[]=a&key[]=b`, which the\n * OpenRegister API interprets as an IN / OR match.\n *\n * @param {Array<object>} filterMaps Already route-resolved filter maps.\n * @return {object} The merged filter (scalar when a key has one value, array when many).\n */\n/**\n * The sort a quick filter sets while it is active (`sort: { key, order }`, or a\n * list of those for a multi-column order), as sort keys, or null when it sets\n * none.\n *\n * @param {object|undefined} tab A quick filter.\n * @return {Array<{key: string, order: string}>|null} The sort keys.\n * @spec openspec/changes/screens-quick-filter-sort/specs/index-page/spec.md\n */\nexport function quickFilterSortKeys(tab) {\n\tconst sort = tab && tab.sort\n\tif (!sort) {\n\t\treturn null\n\t}\n\tconst keys = (Array.isArray(sort) ? sort : [sort])\n\t\t.filter((entry) => entry && typeof entry.key === 'string' && entry.key !== '')\n\t\t.map((entry) => ({ key: entry.key, order: entry.order === 'desc' ? 'desc' : 'asc' }))\n\treturn keys.length > 0 ? keys : null\n}\n\nfunction unionFilterMaps(filterMaps) {\n\tconst grouped = {}\n\tfor (const map of filterMaps) {\n\t\tif (!map || typeof map !== 'object') {\n\t\t\tcontinue\n\t\t}\n\t\tfor (const [k, v] of Object.entries(map)) {\n\t\t\tif (v === undefined || v === null || v === '') {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (!grouped[k]) {\n\t\t\t\tgrouped[k] = []\n\t\t\t}\n\t\t\tfor (const item of (Array.isArray(v) ? v : [v])) {\n\t\t\t\tif (!grouped[k].includes(item)) {\n\t\t\t\t\tgrouped[k].push(item)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tconst out = {}\n\tfor (const [k, arr] of Object.entries(grouped)) {\n\t\tout[k] = arr.length === 1 ? arr[0] : arr\n\t}\n\treturn out\n}\n\n/**\n * Self-fetch mode for CnIndexPage: when register+schema are set but no\n * `objects` prop was passed (manifest-driven pages), drive the list ourselves.\n *\n * @param {object} props CnIndexPage props.\n * @param {import('vue').ComponentInternalInstance|null} instance Pass `getCurrentInstance()`.\n * @param {typeof import('vue').inject} inject Pass Vue's `inject`.\n * @param {{activeFolderSchema?: import('vue').Ref<?{schema: string, register?: string}>}} [extras] `activeFolderSchema`: a ref the page sets to the selected folder's `{ schema, register? }`, switching the loaded object type while it is non-null.\n * @return {object} { isSelfFetch, list, selfObjectStore, selfObjectType, activeQuickFilterIndex }\n */\nexport function useSelfFetchList(props, instance, inject, extras = {}) {\n\tconst objectsProvided = !!(\n\t\tinstance && instance.proxy && instance.proxy.$options && instance.proxy.$options.propsData\n\t\t&& Object.hasOwn(instance.proxy.$options.propsData, 'objects')\n\t)\n\t// A named source wins over register/schema. Without this the page would\n\t// fire an OpenRegister request whose rows it then discards in favour of the\n\t// source's — wasted, but worse than wasted if the manifest names both by\n\t// mistake, because the request succeeds and nothing says the two disagree.\n\tconst isSelfFetch = !!(props.register && props.schema) && !objectsProvided && !props.entitySource\n\n\t// \"Also search inside files\" switch, seeded from `?contentSearch=1` so a\n\t// shared link reproduces the list. Only meaningful when `searchInFiles` is on.\n\tconst routeAtSetup = instance && instance.proxy && instance.proxy.$route\n\tconst contentSearch = ref(props.searchInFiles === true && String(routeAtSetup?.query?.contentSearch) === '1')\n\n\tconst activeQuickFilterIndex = ref(resolveInitialQuickFilterIndex(withPersonalLenses(props.quickFilters, props.personalLenses)))\n\tconst selectedQuickFilterIndices = ref([])\n\tconst isMultiQuickFilter = props.quickFilterMultiple === true\n\n\tif (!isSelfFetch) {\n\t\treturn {\n\t\t\tisSelfFetch: false,\n\t\t\tlist: null,\n\t\t\tselfObjectStore: null,\n\t\t\tselfObjectType: '',\n\t\t\tactiveQuickFilterIndex,\n\t\t\tselectedQuickFilterIndices,\n\t\t\tcontentSearch,\n\t\t\tselfFetchTokenCtx: null,\n\t\t\tinitialQueryFilterKeys: [],\n\t\t}\n\t}\n\n\t// The object type follows the selected folder's own schema when it declares\n\t// one; otherwise the page's register and schema.\n\tconst activeFolderSchema = extras.activeFolderSchema || null\n\tconst resolvedTarget = computed(() => {\n\t\tconst folder = activeFolderSchema && activeFolderSchema.value\n\t\tif (folder && folder.schema) {\n\t\t\tconst register = folder.register || props.register\n\t\t\treturn { register, schema: folder.schema, type: `${register}-${folder.schema}` }\n\t\t}\n\t\t// A collection endpoint gets its own type key, so a plain registration of\n\t\t// the same pair elsewhere never resets it.\n\t\tconst collectionUrl = props.collectionUrl || ''\n\t\tconst type = `${props.register}-${props.schema}` + (collectionUrl ? `@${collectionUrl}` : '')\n\t\treturn { register: props.register, schema: props.schema, type, collectionUrl }\n\t})\n\tconst objectType = computed(() => resolvedTarget.value.type)\n\tconst sidebarState = inject('sidebarState', null) ?? inject('objectSidebarState', null)\n\tconst objectStore = useObjectStore()\n\n\t// Token-resolution context for `@workspace.<key>` / `@config.<key>` /\n\t// `@objectId` / `@object.<field>` inside `props.filter` / quick-filter\n\t// tab filters. Same injects + unwrap shape as CnObjectListWidget's\n\t// `objectCtx`/`workspaceCtx`/`tokenCtx` computeds (and CnDeltaWidget) —\n\t// `cnWorkspaceContext` is the reactive bag a dashboard/workspace-root\n\t// (e.g. hrmq's App.vue for multi-administratie) provides; `cnObjectContext`\n\t// is a detail-page's object context (rare on an index page, but harmless\n\t// to support); `cnAppConfig` is the page-level app config bag. All three\n\t// default to null/absent so an app that never provides them is unaffected.\n\tconst objectCtxRaw = inject('cnObjectContext', null)\n\tconst workspaceCtxRaw = inject('cnWorkspaceContext', null)\n\tconst appConfigRaw = inject('cnAppConfig', null)\n\tconst unwrapCtx = (v) => ((v && typeof v === 'object' && 'value' in v) ? v.value : v)\n\n\t/**\n\t * Build the current token-resolution ctx `{ objectId?, object?, workspace, config }`\n\t * from the injected bags, unwrapping Vue refs. Called fresh on every fetch\n\t * so it always reflects the latest workspace/config state.\n\t *\n\t * @return {object} The token ctx.\n\t */\n\tfunction tokenCtx() {\n\t\tconst objCtx = unwrapCtx(objectCtxRaw)\n\t\tconst base = (objCtx && typeof objCtx === 'object') ? { ...objCtx } : {}\n\t\tbase.workspace = unwrapCtx(workspaceCtxRaw) || {}\n\t\tbase.config = unwrapCtx(appConfigRaw) || {}\n\t\treturn base\n\t}\n\n\t// Reactive signature of the workspace/config bags so a change (e.g. the\n\t// administration switcher writing `activeAdministrationId`) triggers a\n\t// re-fetch below — `fixedFilters` is a plain getter called at fetch time\n\t// (see useListView.resolveFixedFilters), it is NOT auto-tracked by Vue,\n\t// so without this the list would resolve the token once on mount and\n\t// never again. Stringified (like CnDeltaWidget's `sourceKey`) so the\n\t// watcher fires on real content changes only, not object identity.\n\tconst workspaceSignature = computed(() => JSON.stringify(unwrapCtx(workspaceCtxRaw) || {}))\n\tconst appConfigSignature = computed(() => JSON.stringify(unwrapCtx(appConfigRaw) || {}))\n\n\t// Pass register/schema in their positional id slots (not as a {register, schema} object as\n\t// second arg) — that previously made fetch URLs go to `/api/objects/undefined/[object Object]`.\n\t// Runs (sync, ahead of the list's own watcher) again whenever the type switches.\n\tfunction registerTarget() {\n\t\tconst { register, schema, type, collectionUrl } = resolvedTarget.value\n\t\tif (typeof objectStore.registerObjectType === 'function') {\n\t\t\tobjectStore.registerObjectType(type, schema, register, {\n\t\t\t\tregisterSlug: register,\n\t\t\t\tschemaSlug: schema,\n\t\t\t\t...(collectionUrl ? { collectionUrl } : {}),\n\t\t\t})\n\t\t}\n\t\t// A mixed list tells its own rows apart by `@self.register`, an id, so a slug register needs resolving.\n\t\tif (collectionUrl && !/^\\d+$/.test(String(register)) && typeof objectStore.fetchRegister === 'function') {\n\t\t\tobjectStore.fetchRegister(type)\n\t\t}\n\t}\n\tregisterTarget()\n\twatch(objectType, registerTarget, { flush: 'sync' })\n\n\t// Seed the visible-column set from the configured columns so the sidebar's\n\t// Columns tab reflects the curated default; null when none are configured\n\t// (schema-driven table — every column starts visible).\n\t// A column marked `hidden: true` is declared but starts outside the set,\n\t// so it is off until the person turns it on in the Columns tab.\n\tconst configuredColumnKeys = (props.columns || [])\n\t\t.filter((c) => !(c && typeof c === 'object' && c.hidden === true))\n\t\t.map((c) => (typeof c === 'string' ? c : c && c.key))\n\t\t.filter(Boolean)\n\n\t// Restore a persisted multi-column sort from the route query first (deep\n\t// link / reload); fall back to a host-passed `sortKeys` prop, then the\n\t// legacy single-key `sortKey`/`sortOrder` props.\n\tconst initialRoute = instance && instance.proxy && instance.proxy.$route\n\t// The page's own order, which a lens without a `sort` goes back to.\n\tconst pageSortKeys = (Array.isArray(props.sortKeys) && props.sortKeys.length > 0)\n\t\t? props.sortKeys\n\t\t: (props.sortKey ? [{ key: props.sortKey, order: props.sortOrder || 'asc' }] : [])\n\t// The lens that is active on mount may set its own order.\n\tconst initialTabs = withPersonalLenses(props.quickFilters, props.personalLenses)\n\tconst initialTabSort = (!isMultiQuickFilter && Array.isArray(initialTabs))\n\t\t? quickFilterSortKeys(initialTabs[activeQuickFilterIndex.value])\n\t\t: null\n\tconst initialSortKeys = parseSortKeysFromQuery(initialRoute)\n\t\t|| initialTabSort\n\t\t|| (Array.isArray(props.sortKeys) && props.sortKeys.length > 0 ? props.sortKeys : undefined)\n\t// Same deep-link restore for facet filters and search, so opening a\n\t// shared/bookmarked URL reproduces the same view (CnIndexPage persists\n\t// both back to the route on change).\n\tconst initialActiveFilters = resolveQueryFilters(initialRoute && initialRoute.query, tokenCtx())\n\tconst initialSearchTerm = (initialRoute && typeof initialRoute.query?._search === 'string') ? initialRoute.query._search : ''\n\n\t// Set right after useListView returns; the fixed-filters getter reads it lazily.\n\tlet listHandle = null\n\tconst list = useListView(() => objectType.value, {\n\t\tobjectStore,\n\t\tsidebarState,\n\t\tdefaultSort: props.sortKey ? { key: props.sortKey, order: props.sortOrder || 'asc' } : undefined,\n\t\tdefaultSortKeys: initialSortKeys,\n\t\tdefaultActiveFilters: initialActiveFilters,\n\t\tdefaultSearchTerm: initialSearchTerm,\n\t\tdefaultPageSize: (props.pagination && props.pagination.limit) || undefined,\n\t\tdefaultVisibleColumns: configuredColumnKeys.length ? configuredColumnKeys : null,\n\t\t// `pages[].config.extend` → OpenRegister's repeated `_extend[]`. A\n\t\t// getter so a reactive change re-scopes the next fetch, matching how\n\t\t// `fixedFilters` is read.\n\t\textend: () => (Array.isArray(props.extend) ? props.extend : []),\n\t\tfixedFilters: () => {\n\t\t\tconst route = instance && instance.proxy && instance.proxy.$route\n\t\t\tconst params = (route && route.params) || {}\n\t\t\tconst ctx = tokenCtx()\n\t\t\tconst queryFilters = resolveQueryFilters(route && route.query, ctx)\n\t\t\tconst base = resolveFilterMap(props.filter, params, ctx)\n\t\t\t// A folder-sidebar scope declaring `searchFields` narrows what the\n\t\t\t// search box searches over while that scope is active. Read off the\n\t\t\t// instance, like `$route` above, because the active scope is the\n\t\t\t// component's own state rather than a prop — and read through the\n\t\t\t// one fixed-filter getter rather than a second search path.\n\t\t\tconst scopeSearchFields = (instance && instance.proxy && instance.proxy.activeScopeSearchFields) || []\n\t\t\tconst scopeBase = scopeSearchFields.length > 0 ? { _searchFields: scopeSearchFields } : {}\n\t\t\t// File-content search widens a text search, so it rides only with a term.\n\t\t\tconst widen = props.searchInFiles === true && contentSearch.value && !!(listHandle && listHandle.searchTerm.value)\n\t\t\t// The visible calendar month, only while the page is in calendar mode.\n\t\t\tconst month = (instance && instance.proxy && instance.proxy.calendarRangeFilter) || {}\n\t\t\tconst scope = { ...(widen ? { ...scopeBase, _content_search: 'true' } : scopeBase), ...month }\n\t\t\tconst lensed = withPersonalLenses(props.quickFilters, props.personalLenses)\n\t\t\tconst tabs = Array.isArray(lensed) ? lensed : null\n\t\t\tif (!tabs) {\n\t\t\t\treturn { ...queryFilters, ...scope, ...base }\n\t\t\t}\n\n\t\t\t// Multiple mode: OR the selected tabs' filters together (union).\n\t\t\tif (isMultiQuickFilter) {\n\t\t\t\tconst maps = selectedQuickFilterIndices.value\n\t\t\t\t\t.map((i) => resolveFilterMap(tabs[i]?.filter, params, ctx))\n\t\t\t\treturn { ...queryFilters, ...scope, ...base, ...unionFilterMaps(maps) }\n\t\t\t}\n\n\t\t\t// Single mode: the active tab's filter spread last so it wins\n\t\t\t// over a colliding props.filter entry.\n\t\t\tconst activeIdx = activeQuickFilterIndex.value\n\t\t\tconst tabFilter = (activeIdx !== null && activeIdx !== undefined) ? tabs[activeIdx]?.filter : null\n\t\t\treturn { ...queryFilters, ...scope, ...base, ...resolveFilterMap(tabFilter, params, ctx) }\n\t\t},\n\t})\n\n\tlistHandle = list\n\n\t// Re-fetch when the quick-filter selection changes (pre-existing), OR\n\t// when the workspace/app-config bag content changes (e.g. the\n\t// administration switcher writes a new `activeAdministrationId`) — a\n\t// `@workspace.<key>`/`@config.<key>` token in `props.filter` must re-scope\n\t// the list without a manual reload. A change to `props.filter` itself (a\n\t// host toggling a filter checkbox) re-fetches the same way.\n\tconst filterSignature = computed(() => JSON.stringify(props.filter ?? null))\n\twatch([activeQuickFilterIndex, selectedQuickFilterIndices, contentSearch, workspaceSignature, appConfigSignature, filterSignature], (now, before) => {\n\t\t// Switching lens: a lens with a `sort` sets that order; leaving one\n\t\t// for a lens without goes back to the page's own order. A column the\n\t\t// person sorts by afterwards still wins until the next switch.\n\t\tif (!isMultiQuickFilter && before && now[0] !== before[0]) {\n\t\t\tconst tabs = withPersonalLenses(props.quickFilters, props.personalLenses) || []\n\t\t\tconst keys = quickFilterSortKeys(tabs[now[0]]) || (quickFilterSortKeys(tabs[before[0]]) ? pageSortKeys : null)\n\t\t\tif (keys && list.sortKeys) {\n\t\t\t\tlist.sortKeys.value = keys\n\t\t\t\tlist.sortKey.value = keys[0]?.key ?? null\n\t\t\t\tlist.sortOrder.value = keys[0]?.order ?? 'asc'\n\t\t\t}\n\t\t}\n\t\tif (list && typeof list.refresh === 'function') {\n\t\t\tlist.refresh(1)\n\t\t}\n\t})\n\n\t// Live collection updates (manifest-live-updates): subscribe to the\n\t// page's `or-collection-{register}-{schema}` scope so another user's\n\t// create/update/delete refreshes this list without a manual reload.\n\t// The subscription lifecycle (mount/unmount, in-flight dedupe, epoch\n\t// guard against stale async resolution) lives in useObjectSubscription;\n\t// the refetch-on-event (with the last fetch params, burst-coalesced)\n\t// lives in liveUpdatesPlugin. The `subscribe` prop (default true; from\n\t// a manifest: `config.subscribe: false`) is the opt-out, read through\n\t// a reactive getter so a runtime flip attaches/detaches accordingly.\n\t// Stores without live-updates support (no `subscribe` action) are a\n\t// silent no-op inside the composable, keeping this fully inert.\n\tuseObjectSubscription(objectStore, () => objectType.value, null, {\n\t\tenabled: () => props.subscribe !== false,\n\t})\n\n\treturn {\n\t\tisSelfFetch: true,\n\t\tlist,\n\t\tselfObjectStore: objectStore,\n\t\tselfObjectType: objectType,\n\t\tactiveQuickFilterIndex,\n\t\tselectedQuickFilterIndices,\n\t\tcontentSearch,\n\t\t// The page persists the view state back into the query, and needs both\n\t\t// to do it without trampling the rest of it: the keys it adopted from\n\t\t// the query on load (the only non-`_` ones it may clear), and the ctx\n\t\t// those keys' `@`-tokens resolve against.\n\t\tselfFetchTokenCtx: tokenCtx,\n\t\tinitialQueryFilterKeys: Object.keys(initialActiveFilters),\n\t}\n}\n"],"names":[],"mappings":";;;;;;;AAUA,SAAS,8BAA8B,CAAC,YAAY,EAAE;AACtD,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,GAAG,KAAI;AAC/D,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;AACjC,EAAE,OAAO,IAAI;AACb,EAAE;AACF,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,EAAC;AAC1D,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC;AACxB,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,mBAAmB,CAAC,GAAG,EAAE;AACzC,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,GAAG,CAAC,KAAI;AAC7B,CAAC,IAAI,CAAC,IAAI,EAAE;AACZ,EAAE,OAAO,IAAI;AACb,EAAE;AACF,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC;AAClD,GAAG,MAAM,CAAC,CAAC,KAAK,KAAK,KAAK,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC;AAChF,GAAG,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,KAAK,MAAM,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC,EAAC;AACvF,CAAC,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI;AACrC,CAAC;AACD;AACA,SAAS,eAAe,CAAC,UAAU,EAAE;AACrC,CAAC,MAAM,OAAO,GAAG,GAAE;AACnB,CAAC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE;AAC/B,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;AACvC,GAAG,QAAQ;AACX,GAAG;AACH,EAAE,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;AAC5C,GAAG,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,EAAE;AAClD,IAAI,QAAQ;AACZ,IAAI;AACJ,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;AACpB,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,GAAE;AACnB,IAAI;AACJ,GAAG,KAAK,MAAM,IAAI,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;AACpD,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;AACpC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAC;AAC1B,KAAK;AACL,IAAI;AACJ,GAAG;AACH,EAAE;AACF,CAAC,MAAM,GAAG,GAAG,GAAE;AACf,CAAC,KAAK,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;AACjD,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,IAAG;AAC1C,EAAE;AACF,CAAC,OAAO,GAAG;AACX,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,EAAE,EAAE;AACvE,CAAC,MAAM,eAAe,GAAG,CAAC;AAC1B,EAAE,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS;AAC5F,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;AAChE,GAAE;AACF;AACA;AACA;AACA;AACA,CAAC,MAAM,WAAW,GAAG,CAAC,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,KAAK,CAAC,aAAY;AAClG;AACA;AACA;AACA,CAAC,MAAM,YAAY,GAAG,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAM;AACzE,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,KAAK,IAAI,IAAI,MAAM,CAAC,YAAY,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,GAAG,EAAC;AAC9G;AACA,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC,8BAA8B,CAAC,kBAAkB,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC,EAAC;AACjI,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC,EAAE,EAAC;AAC3C,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC,mBAAmB,KAAK,KAAI;AAC9D;AACA,CAAC,IAAI,CAAC,WAAW,EAAE;AACnB,EAAE,OAAO;AACT,GAAG,WAAW,EAAE,KAAK;AACrB,GAAG,IAAI,EAAE,IAAI;AACb,GAAG,eAAe,EAAE,IAAI;AACxB,GAAG,cAAc,EAAE,EAAE;AACrB,GAAG,sBAAsB;AACzB,GAAG,0BAA0B;AAC7B,GAAG,aAAa;AAChB,GAAG,iBAAiB,EAAE,IAAI;AAC1B,GAAG,sBAAsB,EAAE,EAAE;AAC7B,GAAG;AACH,EAAE;AACF;AACA;AACA;AACA,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,kBAAkB,IAAI,KAAI;AAC7D,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM;AACvC,EAAE,MAAM,MAAM,GAAG,kBAAkB,IAAI,kBAAkB,CAAC,MAAK;AAC/D,EAAE,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE;AAC/B,GAAG,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,KAAK,CAAC,SAAQ;AACrD,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE;AACnF,GAAG;AACH;AACA;AACA,EAAE,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,IAAI,GAAE;AACjD,EAAE,MAAM,IAAI,GAAG,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,aAAa,GAAG,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,GAAG,EAAE,EAAC;AAC/F,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE;AAChF,EAAE,EAAC;AACH,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,cAAc,CAAC,KAAK,CAAC,IAAI,EAAC;AAC7D,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,cAAc,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,oBAAoB,EAAE,IAAI,EAAC;AACxF,CAAC,MAAM,WAAW,GAAG,cAAc,GAAE;AACrC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,iBAAiB,EAAE,IAAI,EAAC;AACrD,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,oBAAoB,EAAE,IAAI,EAAC;AAC3D,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,aAAa,EAAE,IAAI,EAAC;AACjD,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,EAAC;AACtF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,SAAS,QAAQ,GAAG;AACrB,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,EAAC;AACxC,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,EAAE,GAAG,MAAM,EAAE,GAAG,GAAE;AAC1E,EAAE,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,eAAe,CAAC,IAAI,GAAE;AACnD,EAAE,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,IAAI,GAAE;AAC7C,EAAE,OAAO,IAAI;AACb,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,EAAC;AAC5F,CAAC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,EAAC;AACzF;AACA;AACA;AACA;AACA,CAAC,SAAS,cAAc,GAAG;AAC3B,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,cAAc,CAAC,MAAK;AACxE,EAAE,IAAI,OAAO,WAAW,CAAC,kBAAkB,KAAK,UAAU,EAAE;AAC5D,GAAG,WAAW,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE;AAC1D,IAAI,YAAY,EAAE,QAAQ;AAC1B,IAAI,UAAU,EAAE,MAAM;AACtB,IAAI,IAAI,aAAa,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC;AAC/C,IAAI,EAAC;AACL,GAAG;AACH;AACA,EAAE,IAAI,aAAa,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,OAAO,WAAW,CAAC,aAAa,KAAK,UAAU,EAAE;AAC3G,GAAG,WAAW,CAAC,aAAa,CAAC,IAAI,EAAC;AAClC,GAAG;AACH,EAAE;AACF,CAAC,cAAc,GAAE;AACjB,CAAC,KAAK,CAAC,UAAU,EAAE,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAC;AACrD;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE;AAClD,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;AACpE,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,KAAK,QAAQ,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AACvD,GAAG,MAAM,CAAC,OAAO,EAAC;AAClB;AACA;AACA;AACA;AACA,CAAC,MAAM,YAAY,GAAG,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAM;AACzE;AACA,CAAC,MAAM,YAAY,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;AACjF,IAAI,KAAK,CAAC,QAAQ;AAClB,KAAK,KAAK,CAAC,OAAO,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,IAAI,KAAK,EAAE,CAAC,GAAG,EAAE,EAAC;AACpF;AACA,CAAC,MAAM,WAAW,GAAG,kBAAkB,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,cAAc,EAAC;AACjF,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,kBAAkB,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;AAC1E,IAAI,mBAAmB,CAAC,WAAW,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;AAClE,IAAI,KAAI;AACR,CAAC,MAAM,eAAe,GAAG,sBAAsB,CAAC,YAAY,CAAC;AAC7D,KAAK,cAAc;AACnB,MAAM,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,GAAG,SAAS,EAAC;AAC9F;AACA;AACA;AACA,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAAC,YAAY,IAAI,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAC;AACjG,CAAC,MAAM,iBAAiB,GAAG,CAAC,YAAY,IAAI,OAAO,YAAY,CAAC,KAAK,EAAE,OAAO,KAAK,QAAQ,IAAI,YAAY,CAAC,KAAK,CAAC,OAAO,GAAG,GAAE;AAC9H;AACA;AACA,CAAC,IAAI,UAAU,GAAG,KAAI;AACtB,CAAC,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,UAAU,CAAC,KAAK,EAAE;AAClD,EAAE,WAAW;AACb,EAAE,YAAY;AACd,EAAE,WAAW,EAAE,KAAK,CAAC,OAAO,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,IAAI,KAAK,EAAE,GAAG,SAAS;AAClG,EAAE,eAAe,EAAE,eAAe;AAClC,EAAE,oBAAoB,EAAE,oBAAoB;AAC5C,EAAE,iBAAiB,EAAE,iBAAiB;AACtC,EAAE,eAAe,EAAE,CAAC,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,KAAK,SAAS;AAC5E,EAAE,qBAAqB,EAAE,oBAAoB,CAAC,MAAM,GAAG,oBAAoB,GAAG,IAAI;AAClF;AACA;AACA;AACA,EAAE,MAAM,EAAE,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC;AACjE,EAAE,YAAY,EAAE,MAAM;AACtB,GAAG,MAAM,KAAK,GAAG,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAM;AACpE,GAAG,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,GAAE;AAC/C,GAAG,MAAM,GAAG,GAAG,QAAQ,GAAE;AACzB,GAAG,MAAM,YAAY,GAAG,mBAAmB,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,GAAG,EAAC;AACtE,GAAG,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAC;AAC3D;AACA;AACA;AACA;AACA;AACA,GAAG,MAAM,iBAAiB,GAAG,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,uBAAuB,KAAK,GAAE;AACzG,GAAG,MAAM,SAAS,GAAG,iBAAiB,CAAC,MAAM,GAAG,CAAC,GAAG,EAAE,aAAa,EAAE,iBAAiB,EAAE,GAAG,GAAE;AAC7F;AACA,GAAG,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,KAAK,IAAI,IAAI,aAAa,CAAC,KAAK,IAAI,CAAC,EAAE,UAAU,IAAI,UAAU,CAAC,UAAU,CAAC,KAAK,EAAC;AACrH;AACA,GAAG,MAAM,KAAK,GAAG,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,mBAAmB,KAAK,GAAE;AACzF,GAAG,MAAM,KAAK,GAAG,EAAE,IAAI,KAAK,GAAG,EAAE,GAAG,SAAS,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,EAAE,GAAG,KAAK,GAAE;AACjG,GAAG,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,cAAc,EAAC;AAC9E,GAAG,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,KAAI;AACrD,GAAG,IAAI,CAAC,IAAI,EAAE;AACd,IAAI,OAAO,EAAE,GAAG,YAAY,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE;AACjD,IAAI;AACJ;AACA;AACA,GAAG,IAAI,kBAAkB,EAAE;AAC3B,IAAI,MAAM,IAAI,GAAG,0BAA0B,CAAC,KAAK;AACjD,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,EAAC;AAChE,IAAI,OAAO,EAAE,GAAG,YAAY,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,eAAe,CAAC,IAAI,CAAC,EAAE;AAC3E,IAAI;AACJ;AACA;AACA;AACA,GAAG,MAAM,SAAS,GAAG,sBAAsB,CAAC,MAAK;AACjD,GAAG,MAAM,SAAS,GAAG,CAAC,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,KAAI;AACrG,GAAG,OAAO,EAAE,GAAG,YAAY,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE;AAC7F,GAAG;AACH,EAAE,EAAC;AACH;AACA,CAAC,UAAU,GAAG,KAAI;AAClB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,EAAC;AAC7E,CAAC,KAAK,CAAC,CAAC,sBAAsB,EAAE,0BAA0B,EAAE,aAAa,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK;AACtJ;AACA;AACA;AACA,EAAE,IAAI,CAAC,kBAAkB,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE;AAC7D,GAAG,MAAM,IAAI,GAAG,kBAAkB,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,GAAE;AAClF,GAAG,MAAM,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,YAAY,GAAG,IAAI,EAAC;AACjH,GAAG,IAAI,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE;AAC9B,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,GAAG,KAAI;AAC9B,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,KAAI;AAC7C,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,MAAK;AAClD,IAAI;AACJ,GAAG;AACH,EAAE,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,UAAU,EAAE;AAClD,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,EAAC;AAClB,GAAG;AACH,EAAE,EAAC;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,qBAAqB,CAAC,WAAW,EAAE,MAAM,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE;AAClE,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC,SAAS,KAAK,KAAK;AAC1C,EAAE,EAAC;AACH;AACA,CAAC,OAAO;AACR,EAAE,WAAW,EAAE,IAAI;AACnB,EAAE,IAAI;AACN,EAAE,eAAe,EAAE,WAAW;AAC9B,EAAE,cAAc,EAAE,UAAU;AAC5B,EAAE,sBAAsB;AACxB,EAAE,0BAA0B;AAC5B,EAAE,aAAa;AACf;AACA;AACA;AACA;AACA,EAAE,iBAAiB,EAAE,QAAQ;AAC7B,EAAE,sBAAsB,EAAE,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC;AAC3D,EAAE;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"useSelfFetchList.js","sources":["../../../../src/components/CnIndexPage/useSelfFetchList.js"],"sourcesContent":["import { computed, ref, watch } from 'vue'\nimport { useListView } from '../../composables/index.js'\nimport { useObjectSubscription } from '../../composables/useObjectSubscription.js'\nimport { useObjectStore } from '../../store/index.js'\n// Both filter resolvers live in `utils/routeFilters.js` so CnLogsPage applies\n// the same two grammars (route-param interpolation + `?key=value` deep links)\n// without pulling in this composable's index-only sidebar/subscription wiring.\nimport { withPersonalLenses } from '../../utils/personalLenses.js'\nimport { parseSortKeysFromQuery, resolveFilterMap, resolveQueryFilters } from '../../utils/routeFilters.js'\n\nfunction resolveInitialQuickFilterIndex(quickFilters) {\n\tconst tabs = Array.isArray(quickFilters) ? quickFilters : null\n\tif (!tabs || tabs.length === 0) {\n\t\treturn null\n\t}\n\tconst di = tabs.findIndex((t) => t && t.default === true)\n\treturn di >= 0 ? di : 0\n}\n\n/**\n * OR-merge several quick-filter maps into one fetch filter. Values for the\n * same key collapse to an array (deduped) when more than one tab contributes\n * it — `buildQueryString` serialises an array as `key[]=a&key[]=b`, which the\n * OpenRegister API interprets as an IN / OR match.\n *\n * @param {Array<object>} filterMaps Already route-resolved filter maps.\n * @return {object} The merged filter (scalar when a key has one value, array when many).\n */\n/**\n * Rows one board fetch asks for. A board shows every matching row at once,\n * so it loads far more than a table page (OpenRegister serves up to 1000);\n * past this the board offers \"Load more\".\n *\n * @type {number}\n */\nexport const BOARD_PAGE_SIZE = 500\n\n/**\n * The sort a quick filter sets while it is active (`sort: { key, order }`, or a\n * list of those for a multi-column order), as sort keys, or null when it sets\n * none.\n *\n * @param {object|undefined} tab A quick filter.\n * @return {Array<{key: string, order: string}>|null} The sort keys.\n * @spec openspec/changes/screens-quick-filter-sort/specs/index-page/spec.md\n */\nexport function quickFilterSortKeys(tab) {\n\tconst sort = tab && tab.sort\n\tif (!sort) {\n\t\treturn null\n\t}\n\tconst keys = (Array.isArray(sort) ? sort : [sort])\n\t\t.filter((entry) => entry && typeof entry.key === 'string' && entry.key !== '')\n\t\t.map((entry) => ({ key: entry.key, order: entry.order === 'desc' ? 'desc' : 'asc' }))\n\treturn keys.length > 0 ? keys : null\n}\n\nfunction unionFilterMaps(filterMaps) {\n\tconst grouped = {}\n\tfor (const map of filterMaps) {\n\t\tif (!map || typeof map !== 'object') {\n\t\t\tcontinue\n\t\t}\n\t\tfor (const [k, v] of Object.entries(map)) {\n\t\t\tif (v === undefined || v === null || v === '') {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (!grouped[k]) {\n\t\t\t\tgrouped[k] = []\n\t\t\t}\n\t\t\tfor (const item of (Array.isArray(v) ? v : [v])) {\n\t\t\t\tif (!grouped[k].includes(item)) {\n\t\t\t\t\tgrouped[k].push(item)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tconst out = {}\n\tfor (const [k, arr] of Object.entries(grouped)) {\n\t\tout[k] = arr.length === 1 ? arr[0] : arr\n\t}\n\treturn out\n}\n\n/**\n * Self-fetch mode for CnIndexPage: when register+schema are set but no\n * `objects` prop was passed (manifest-driven pages), drive the list ourselves.\n *\n * @param {object} props CnIndexPage props.\n * @param {import('vue').ComponentInternalInstance|null} instance Pass `getCurrentInstance()`.\n * @param {typeof import('vue').inject} inject Pass Vue's `inject`.\n * @param {{activeFolderSchema?: import('vue').Ref<?{schema: string, register?: string}>}} [extras] `activeFolderSchema`: a ref the page sets to the selected folder's `{ schema, register? }`, switching the loaded object type while it is non-null.\n * @return {object} { isSelfFetch, list, selfObjectStore, selfObjectType, activeQuickFilterIndex }\n */\nexport function useSelfFetchList(props, instance, inject, extras = {}) {\n\tconst objectsProvided = !!(\n\t\tinstance && instance.proxy && instance.proxy.$options && instance.proxy.$options.propsData\n\t\t&& Object.hasOwn(instance.proxy.$options.propsData, 'objects')\n\t)\n\t// A named source wins over register/schema. Without this the page would\n\t// fire an OpenRegister request whose rows it then discards in favour of the\n\t// source's — wasted, but worse than wasted if the manifest names both by\n\t// mistake, because the request succeeds and nothing says the two disagree.\n\tconst isSelfFetch = !!(props.register && props.schema) && !objectsProvided && !props.entitySource\n\n\t// \"Also search inside files\" switch, seeded from `?contentSearch=1` so a\n\t// shared link reproduces the list. Only meaningful when `searchInFiles` is on.\n\tconst routeAtSetup = instance && instance.proxy && instance.proxy.$route\n\tconst contentSearch = ref(props.searchInFiles === true && String(routeAtSetup?.query?.contentSearch) === '1')\n\n\tconst activeQuickFilterIndex = ref(resolveInitialQuickFilterIndex(withPersonalLenses(props.quickFilters, props.personalLenses)))\n\tconst selectedQuickFilterIndices = ref([])\n\tconst isMultiQuickFilter = props.quickFilterMultiple === true\n\n\tif (!isSelfFetch) {\n\t\treturn {\n\t\t\tisSelfFetch: false,\n\t\t\tlist: null,\n\t\t\tselfObjectStore: null,\n\t\t\tselfObjectType: '',\n\t\t\tactiveQuickFilterIndex,\n\t\t\tselectedQuickFilterIndices,\n\t\t\tcontentSearch,\n\t\t\tselfFetchTokenCtx: null,\n\t\t\tinitialQueryFilterKeys: [],\n\t\t}\n\t}\n\n\t// The object type follows the selected folder's own schema when it declares\n\t// one; otherwise the page's register and schema.\n\tconst activeFolderSchema = extras.activeFolderSchema || null\n\tconst resolvedTarget = computed(() => {\n\t\tconst folder = activeFolderSchema && activeFolderSchema.value\n\t\tif (folder && folder.schema) {\n\t\t\tconst register = folder.register || props.register\n\t\t\treturn { register, schema: folder.schema, type: `${register}-${folder.schema}` }\n\t\t}\n\t\t// A collection endpoint gets its own type key, so a plain registration of\n\t\t// the same pair elsewhere never resets it.\n\t\tconst collectionUrl = props.collectionUrl || ''\n\t\tconst type = `${props.register}-${props.schema}` + (collectionUrl ? `@${collectionUrl}` : '')\n\t\treturn { register: props.register, schema: props.schema, type, collectionUrl }\n\t})\n\tconst objectType = computed(() => resolvedTarget.value.type)\n\tconst sidebarState = inject('sidebarState', null) ?? inject('objectSidebarState', null)\n\tconst objectStore = useObjectStore()\n\n\t// Token-resolution context for `@workspace.<key>` / `@config.<key>` /\n\t// `@objectId` / `@object.<field>` inside `props.filter` / quick-filter\n\t// tab filters. Same injects + unwrap shape as CnObjectListWidget's\n\t// `objectCtx`/`workspaceCtx`/`tokenCtx` computeds (and CnDeltaWidget) —\n\t// `cnWorkspaceContext` is the reactive bag a dashboard/workspace-root\n\t// (e.g. hrmq's App.vue for multi-administratie) provides; `cnObjectContext`\n\t// is a detail-page's object context (rare on an index page, but harmless\n\t// to support); `cnAppConfig` is the page-level app config bag. All three\n\t// default to null/absent so an app that never provides them is unaffected.\n\tconst objectCtxRaw = inject('cnObjectContext', null)\n\tconst workspaceCtxRaw = inject('cnWorkspaceContext', null)\n\tconst appConfigRaw = inject('cnAppConfig', null)\n\tconst unwrapCtx = (v) => ((v && typeof v === 'object' && 'value' in v) ? v.value : v)\n\n\t/**\n\t * Build the current token-resolution ctx `{ objectId?, object?, workspace, config }`\n\t * from the injected bags, unwrapping Vue refs. Called fresh on every fetch\n\t * so it always reflects the latest workspace/config state.\n\t *\n\t * @return {object} The token ctx.\n\t */\n\tfunction tokenCtx() {\n\t\tconst objCtx = unwrapCtx(objectCtxRaw)\n\t\tconst base = (objCtx && typeof objCtx === 'object') ? { ...objCtx } : {}\n\t\tbase.workspace = unwrapCtx(workspaceCtxRaw) || {}\n\t\tbase.config = unwrapCtx(appConfigRaw) || {}\n\t\treturn base\n\t}\n\n\t// Reactive signature of the workspace/config bags so a change (e.g. the\n\t// administration switcher writing `activeAdministrationId`) triggers a\n\t// re-fetch below — `fixedFilters` is a plain getter called at fetch time\n\t// (see useListView.resolveFixedFilters), it is NOT auto-tracked by Vue,\n\t// so without this the list would resolve the token once on mount and\n\t// never again. Stringified (like CnDeltaWidget's `sourceKey`) so the\n\t// watcher fires on real content changes only, not object identity.\n\tconst workspaceSignature = computed(() => JSON.stringify(unwrapCtx(workspaceCtxRaw) || {}))\n\tconst appConfigSignature = computed(() => JSON.stringify(unwrapCtx(appConfigRaw) || {}))\n\n\t// Pass register/schema in their positional id slots (not as a {register, schema} object as\n\t// second arg) — that previously made fetch URLs go to `/api/objects/undefined/[object Object]`.\n\t// Runs (sync, ahead of the list's own watcher) again whenever the type switches.\n\tfunction registerTarget() {\n\t\tconst { register, schema, type, collectionUrl } = resolvedTarget.value\n\t\tif (typeof objectStore.registerObjectType === 'function') {\n\t\t\tobjectStore.registerObjectType(type, schema, register, {\n\t\t\t\tregisterSlug: register,\n\t\t\t\tschemaSlug: schema,\n\t\t\t\t...(collectionUrl ? { collectionUrl } : {}),\n\t\t\t})\n\t\t}\n\t\t// A mixed list tells its own rows apart by `@self.register`, an id, so a slug register needs resolving.\n\t\tif (collectionUrl && !/^\\d+$/.test(String(register)) && typeof objectStore.fetchRegister === 'function') {\n\t\t\tobjectStore.fetchRegister(type)\n\t\t}\n\t}\n\tregisterTarget()\n\twatch(objectType, registerTarget, { flush: 'sync' })\n\n\t// Seed the visible-column set from the configured columns so the sidebar's\n\t// Columns tab reflects the curated default; null when none are configured\n\t// (schema-driven table — every column starts visible).\n\t// A column marked `hidden: true` is declared but starts outside the set,\n\t// so it is off until the person turns it on in the Columns tab.\n\tconst configuredColumnKeys = (props.columns || [])\n\t\t.filter((c) => !(c && typeof c === 'object' && c.hidden === true))\n\t\t.map((c) => (typeof c === 'string' ? c : c && c.key))\n\t\t.filter(Boolean)\n\n\t// Restore a persisted multi-column sort from the route query first (deep\n\t// link / reload); fall back to a host-passed `sortKeys` prop, then the\n\t// legacy single-key `sortKey`/`sortOrder` props.\n\tconst initialRoute = instance && instance.proxy && instance.proxy.$route\n\t// The page's own order, which a lens without a `sort` goes back to.\n\tconst pageSortKeys = (Array.isArray(props.sortKeys) && props.sortKeys.length > 0)\n\t\t? props.sortKeys\n\t\t: (props.sortKey ? [{ key: props.sortKey, order: props.sortOrder || 'asc' }] : [])\n\t// The lens that is active on mount may set its own order.\n\tconst initialTabs = withPersonalLenses(props.quickFilters, props.personalLenses)\n\tconst initialTabSort = (!isMultiQuickFilter && Array.isArray(initialTabs))\n\t\t? quickFilterSortKeys(initialTabs[activeQuickFilterIndex.value])\n\t\t: null\n\tconst initialSortKeys = parseSortKeysFromQuery(initialRoute)\n\t\t|| initialTabSort\n\t\t|| (Array.isArray(props.sortKeys) && props.sortKeys.length > 0 ? props.sortKeys : undefined)\n\t// Same deep-link restore for facet filters and search, so opening a\n\t// shared/bookmarked URL reproduces the same view (CnIndexPage persists\n\t// both back to the route on change).\n\tconst initialActiveFilters = resolveQueryFilters(initialRoute && initialRoute.query, tokenCtx())\n\tconst initialSearchTerm = (initialRoute && typeof initialRoute.query?._search === 'string') ? initialRoute.query._search : ''\n\n\t// Set right after useListView returns; the fixed-filters getter reads it lazily.\n\tlet listHandle = null\n\tconst list = useListView(() => objectType.value, {\n\t\tobjectStore,\n\t\tsidebarState,\n\t\tdefaultSort: props.sortKey ? { key: props.sortKey, order: props.sortOrder || 'asc' } : undefined,\n\t\tdefaultSortKeys: initialSortKeys,\n\t\tdefaultActiveFilters: initialActiveFilters,\n\t\tdefaultSearchTerm: initialSearchTerm,\n\t\tdefaultPageSize: props.viewMode === 'board' ? BOARD_PAGE_SIZE : ((props.pagination && props.pagination.limit) || undefined),\n\t\tdefaultVisibleColumns: configuredColumnKeys.length ? configuredColumnKeys : null,\n\t\t// `pages[].config.extend` → OpenRegister's repeated `_extend[]`. A\n\t\t// getter so a reactive change re-scopes the next fetch, matching how\n\t\t// `fixedFilters` is read.\n\t\textend: () => (Array.isArray(props.extend) ? props.extend : []),\n\t\tfixedFilters: () => {\n\t\t\tconst route = instance && instance.proxy && instance.proxy.$route\n\t\t\tconst params = (route && route.params) || {}\n\t\t\tconst ctx = tokenCtx()\n\t\t\tconst queryFilters = resolveQueryFilters(route && route.query, ctx)\n\t\t\tconst base = resolveFilterMap(props.filter, params, ctx)\n\t\t\t// A folder-sidebar scope declaring `searchFields` narrows what the\n\t\t\t// search box searches over while that scope is active. Read off the\n\t\t\t// instance, like `$route` above, because the active scope is the\n\t\t\t// component's own state rather than a prop — and read through the\n\t\t\t// one fixed-filter getter rather than a second search path.\n\t\t\tconst scopeSearchFields = (instance && instance.proxy && instance.proxy.activeScopeSearchFields) || []\n\t\t\tconst scopeBase = scopeSearchFields.length > 0 ? { _searchFields: scopeSearchFields } : {}\n\t\t\t// File-content search widens a text search, so it rides only with a term.\n\t\t\tconst widen = props.searchInFiles === true && contentSearch.value && !!(listHandle && listHandle.searchTerm.value)\n\t\t\t// The visible calendar month, only while the page is in calendar mode.\n\t\t\tconst month = (instance && instance.proxy && instance.proxy.calendarRangeFilter) || {}\n\t\t\tconst scope = { ...(widen ? { ...scopeBase, _content_search: 'true' } : scopeBase), ...month }\n\t\t\tconst lensed = withPersonalLenses(props.quickFilters, props.personalLenses)\n\t\t\tconst tabs = Array.isArray(lensed) ? lensed : null\n\t\t\tif (!tabs) {\n\t\t\t\treturn { ...queryFilters, ...scope, ...base }\n\t\t\t}\n\n\t\t\t// Multiple mode: OR the selected tabs' filters together (union).\n\t\t\tif (isMultiQuickFilter) {\n\t\t\t\tconst maps = selectedQuickFilterIndices.value\n\t\t\t\t\t.map((i) => resolveFilterMap(tabs[i]?.filter, params, ctx))\n\t\t\t\treturn { ...queryFilters, ...scope, ...base, ...unionFilterMaps(maps) }\n\t\t\t}\n\n\t\t\t// Single mode: the active tab's filter spread last so it wins\n\t\t\t// over a colliding props.filter entry.\n\t\t\tconst activeIdx = activeQuickFilterIndex.value\n\t\t\tconst tabFilter = (activeIdx !== null && activeIdx !== undefined) ? tabs[activeIdx]?.filter : null\n\t\t\treturn { ...queryFilters, ...scope, ...base, ...resolveFilterMap(tabFilter, params, ctx) }\n\t\t},\n\t})\n\n\tlistHandle = list\n\n\t// Re-fetch when the quick-filter selection changes (pre-existing), OR\n\t// when the workspace/app-config bag content changes (e.g. the\n\t// administration switcher writes a new `activeAdministrationId`) — a\n\t// `@workspace.<key>`/`@config.<key>` token in `props.filter` must re-scope\n\t// the list without a manual reload. A change to `props.filter` itself (a\n\t// host toggling a filter checkbox) re-fetches the same way.\n\tconst filterSignature = computed(() => JSON.stringify(props.filter ?? null))\n\twatch([activeQuickFilterIndex, selectedQuickFilterIndices, contentSearch, workspaceSignature, appConfigSignature, filterSignature], (now, before) => {\n\t\t// Switching lens: a lens with a `sort` sets that order; leaving one\n\t\t// for a lens without goes back to the page's own order. A column the\n\t\t// person sorts by afterwards still wins until the next switch.\n\t\tif (!isMultiQuickFilter && before && now[0] !== before[0]) {\n\t\t\tconst tabs = withPersonalLenses(props.quickFilters, props.personalLenses) || []\n\t\t\tconst keys = quickFilterSortKeys(tabs[now[0]]) || (quickFilterSortKeys(tabs[before[0]]) ? pageSortKeys : null)\n\t\t\tif (keys && list.sortKeys) {\n\t\t\t\tlist.sortKeys.value = keys\n\t\t\t\tlist.sortKey.value = keys[0]?.key ?? null\n\t\t\t\tlist.sortOrder.value = keys[0]?.order ?? 'asc'\n\t\t\t}\n\t\t}\n\t\tif (list && typeof list.refresh === 'function') {\n\t\t\tlist.refresh(1)\n\t\t}\n\t})\n\n\t// Live collection updates (manifest-live-updates): subscribe to the\n\t// page's `or-collection-{register}-{schema}` scope so another user's\n\t// create/update/delete refreshes this list without a manual reload.\n\t// The subscription lifecycle (mount/unmount, in-flight dedupe, epoch\n\t// guard against stale async resolution) lives in useObjectSubscription;\n\t// the refetch-on-event (with the last fetch params, burst-coalesced)\n\t// lives in liveUpdatesPlugin. The `subscribe` prop (default true; from\n\t// a manifest: `config.subscribe: false`) is the opt-out, read through\n\t// a reactive getter so a runtime flip attaches/detaches accordingly.\n\t// Stores without live-updates support (no `subscribe` action) are a\n\t// silent no-op inside the composable, keeping this fully inert.\n\tuseObjectSubscription(objectStore, () => objectType.value, null, {\n\t\tenabled: () => props.subscribe !== false,\n\t})\n\n\treturn {\n\t\tisSelfFetch: true,\n\t\tlist,\n\t\tselfObjectStore: objectStore,\n\t\tselfObjectType: objectType,\n\t\tactiveQuickFilterIndex,\n\t\tselectedQuickFilterIndices,\n\t\tcontentSearch,\n\t\t// The page persists the view state back into the query, and needs both\n\t\t// to do it without trampling the rest of it: the keys it adopted from\n\t\t// the query on load (the only non-`_` ones it may clear), and the ctx\n\t\t// those keys' `@`-tokens resolve against.\n\t\tselfFetchTokenCtx: tokenCtx,\n\t\tinitialQueryFilterKeys: Object.keys(initialActiveFilters),\n\t}\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import script from './CnNotesCard.vue2.js';
|
|
|
2
2
|
import { render } from './CnNotesCard.vue3.js';
|
|
3
3
|
|
|
4
4
|
script.render = render;
|
|
5
|
-
script.__scopeId = "data-v-
|
|
5
|
+
script.__scopeId = "data-v-5b558cb4";
|
|
6
6
|
const __sfc_main = script;
|
|
7
7
|
|
|
8
8
|
export { __sfc_main as default };
|
|
@@ -12,6 +12,7 @@ import __sfc_main$4 from '../CnVisibilityChip/CnVisibilityChip.vue.js';
|
|
|
12
12
|
import { useFileComments } from '../../composables/useFileComments.js';
|
|
13
13
|
import { extractMentionedIds, extractMentionedGroupIds } from '../../utils/mentions.js';
|
|
14
14
|
import { supportsReplies, threadNotes, quoteFor, threadRootId } from '../../utils/noteThreads.js';
|
|
15
|
+
import { userLocale } from '../../utils/userLocale.js';
|
|
15
16
|
import { prefixUrl, buildHeaders } from '../../utils/headers.js';
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -510,7 +511,7 @@ var script = {
|
|
|
510
511
|
return ''
|
|
511
512
|
}
|
|
512
513
|
try {
|
|
513
|
-
return new Date(dateStr).toLocaleString(
|
|
514
|
+
return new Date(dateStr).toLocaleString(userLocale(), {
|
|
514
515
|
year: 'numeric',
|
|
515
516
|
month: 'short',
|
|
516
517
|
day: 'numeric',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnNotesCard.vue2.js","sources":["../../../../src/components/CnNotesCard/CnNotesCard.vue"],"sourcesContent":["<!--\n CnNotesCard — Inline notes card for detail pages.\n\n Displays up to 5 recent notes with author, content, and timestamp.\n Includes an add-note form and integrates CnUserActionMenu on author names.\n Wraps CnDetailCard for consistent styling.\n-->\n<template>\n\t<CnDetailCard :title=\"titleLabel\"\n\t\t:icon=\"CommentTextOutline\"\n\t\t:collapsible=\"collapsible\"\n\t\t:chromeless=\"chromeless\">\n\t\t<div class=\"cn-notes-card\">\n\t\t\t<!-- Add note input -->\n\t\t\t<div v-if=\"!unavailable\" class=\"cn-notes-card__add-form\">\n\t\t\t\t<!-- Replying: the form says to whom; a reply to a reply goes to the top of its thread. -->\n\t\t\t\t<p\n\t\t\t\t\tv-if=\"replyTo\"\n\t\t\t\t\tclass=\"cn-notes-card__replying\"\n\t\t\t\t\trole=\"status\"\n\t\t\t\t\tdata-testid=\"cn-notes-card-replying\">\n\t\t\t\t\t{{ replyingLabel }}\n\t\t\t\t\t<NcButton variant=\"tertiary\" @click=\"replyTo = null\">\n\t\t\t\t\t\t{{ t('nextcloud-vue', 'Cancel') }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t</p>\n\t\t\t\t<CnNoteComposer\n\t\t\t\t\tclass=\"cn-notes-card__textarea\"\n\t\t\t\t\t:modelValue=\"newNoteText\"\n\t\t\t\t\t:placeholder=\"addNotePlaceholder\"\n\t\t\t\t\t:register=\"isFileSource ? '' : registerId\"\n\t\t\t\t\t:schema=\"isFileSource ? '' : schemaId\"\n\t\t\t\t\t:objectId=\"isFileSource ? '' : objectId\"\n\t\t\t\t\t:apiBase=\"apiBase\"\n\t\t\t\t\t@update:modelValue=\"newNoteText = $event\"\n\t\t\t\t\t@submit=\"submitNote\" />\n\t\t\t\t<!-- Internal or public, chosen before the note is written (only when the host says the caller may set it). -->\n\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\tv-if=\"visibilityToggleShown\"\n\t\t\t\t\t:modelValue=\"newNoteVisibility === 'public'\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\tdata-testid=\"cn-notes-card-visibility-switch\"\n\t\t\t\t\t@update:modelValue=\"(on) => newNoteVisibility = on ? 'public' : 'internal'\">\n\t\t\t\t\t{{ publicSwitchLabel }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t:disabled=\"!newNoteText.trim() || noteSaving\"\n\t\t\t\t\t@click=\"submitNote\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<Send :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ addNoteLabel }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\n\t\t\t<!-- Loading state -->\n\t\t\t<NcLoadingIcon v-if=\"loading\" />\n\n\t\t\t<!-- Empty state -->\n\t\t\t<div v-else-if=\"unavailable\" class=\"cn-notes-card__empty\" data-testid=\"cn-notes-card-unavailable\">\n\t\t\t\t{{ unavailableLabel }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"allNotes.length === 0\" class=\"cn-notes-card__empty\">\n\t\t\t\t{{ noNotesLabel }}\n\t\t\t</div>\n\n\t\t\t<!-- Notes list (last 5), threaded: a note, then its replies. -->\n\t\t\t<div v-else class=\"cn-notes-card__list\">\n\t\t\t\t<div\n\t\t\t\t\tv-for=\"thread in threads\"\n\t\t\t\t\t:key=\"thread.note.id\"\n\t\t\t\t\tclass=\"cn-notes-card__thread\"\n\t\t\t\t\trole=\"group\"\n\t\t\t\t\t:aria-label=\"threadLabel(thread.note)\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-for=\"row in threadRows(thread)\"\n\t\t\t\t\t\t:key=\"row.note.id\"\n\t\t\t\t\t\tclass=\"cn-notes-card__note\"\n\t\t\t\t\t\t:class=\"{ 'cn-notes-card__note--reply': row.isReply }\">\n\t\t\t\t\t\t<div class=\"cn-notes-card__note-header\">\n\t\t\t\t\t\t\t<CnUserActionMenu\n\t\t\t\t\t\t\t\tv-if=\"!isCurrentUser(row.note)\"\n\t\t\t\t\t\t\t\t:userId=\"getNoteAuthorId(row.note)\"\n\t\t\t\t\t\t\t\t:displayName=\"getNoteAuthorName(row.note)\">\n\t\t\t\t\t\t\t\t<strong class=\"cn-notes-card__author\">{{ getNoteAuthorName(row.note) }}</strong>\n\t\t\t\t\t\t\t</CnUserActionMenu>\n\t\t\t\t\t\t\t<strong v-else class=\"cn-notes-card__author cn-notes-card__author--self\">\n\t\t\t\t\t\t\t\t{{ getNoteAuthorName(row.note) }}\n\t\t\t\t\t\t\t</strong>\n\t\t\t\t\t\t\t<span class=\"cn-notes-card__time\">{{ formatDate(row.note.creationDateTime || row.note.created) }}</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div v-if=\"visibilityShown\" class=\"cn-notes-card__visibility\">\n\t\t\t\t\t\t\t<CnVisibilityChip :visibility=\"row.note.visibility\" />\n\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\tv-if=\"visibilityToggleShown\"\n\t\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\t\tdata-testid=\"cn-notes-card-visibility-toggle\"\n\t\t\t\t\t\t\t\t@click=\"toggleVisibility(row.note)\">\n\t\t\t\t\t\t\t\t{{ noteVisibility(row.note) === 'public' ? makeInternalLabel : makePublicLabel }}\n\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<p v-if=\"row.quote\" class=\"cn-notes-card__quote\" data-testid=\"cn-notes-card-quote\">\n\t\t\t\t\t\t\t{{ row.quote }}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p class=\"cn-notes-card__body\">\n\t\t\t\t\t\t\t<CnNoteBody :message=\"row.note.message || row.note.content || ''\" :record=\"isFileSource ? null : record\" />\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"canReply\"\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\t:aria-label=\"replyAria(row.note)\"\n\t\t\t\t\t\t\tdata-testid=\"cn-notes-card-reply\"\n\t\t\t\t\t\t\t@click=\"replyTo = row.note\">\n\t\t\t\t\t\t\t{{ replyLabel }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"canDeleteNote(row.note)\"\n\t\t\t\t\t\t\tvariant=\"tertiary-no-background\"\n\t\t\t\t\t\t\tclass=\"cn-notes-card__delete-btn\"\n\t\t\t\t\t\t\t:aria-label=\"deleteLabel\"\n\t\t\t\t\t\t\t@click=\"confirmDelete(row.note)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Delete :size=\"16\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- Footer: \"Show all\" link -->\n\t\t<template v-if=\"allNotes.length > maxDisplay\" #footer>\n\t\t\t<button\n\t\t\t\tclass=\"cn-notes-card__show-all\"\n\t\t\t\t@click=\"$emit('show-all')\">\n\t\t\t\t{{ showAllLabel }} ({{ allNotes.length }})\n\t\t\t</button>\n\t\t</template>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcLoadingIcon } from '@nextcloud/vue'\nimport { markRaw } from 'vue'\nimport CommentTextOutline from 'vue-material-design-icons/CommentTextOutline.vue'\nimport Delete from 'vue-material-design-icons/Delete.vue'\nimport Send from 'vue-material-design-icons/Send.vue'\nimport CnDetailCard from '../CnDetailCard/CnDetailCard.vue'\nimport CnNoteBody from '../CnNoteBody/CnNoteBody.vue'\nimport CnNoteComposer from '../CnNoteComposer/CnNoteComposer.vue'\nimport CnUserActionMenu from '../CnUserActionMenu/CnUserActionMenu.vue'\nimport CnVisibilityChip from '../CnVisibilityChip/CnVisibilityChip.vue'\nimport { useFileComments } from '../../composables/useFileComments.js'\nimport { buildHeaders, prefixUrl } from '../../utils/index.js'\nimport { extractMentionedGroupIds, extractMentionedIds } from '../../utils/mentions.js'\nimport { quoteFor, supportsReplies, threadNotes, threadRootId } from '../../utils/noteThreads.js'\n\n/**\n * CnNotesCard — Inline notes widget for detail pages.\n *\n * Shows up to 5 recent notes with add/delete functionality.\n * Integrates CnUserActionMenu on author names for quick communication.\n *\n * Basic usage\n * ```vue\n * <CnNotesCard\n * register-id=\"uuid-register\"\n * schema-id=\"uuid-schema\"\n * object-id=\"uuid-object\" />\n * ```\n *\n * With sidebar sync\n * ```vue\n * <CnNotesCard\n * register-id=\"reg\"\n * schema-id=\"schema\"\n * object-id=\"obj\"\n * @note-added=\"refreshNotes\"\n * @note-deleted=\"refreshNotes\"\n * @show-all=\"openSidebarNotesTab\" />\n * ```\n *\n * @event note-added Emitted after a new note is successfully persisted. Payload: the created note object.\n * @event note-deleted Emitted after a note is successfully deleted. Payload: the deleted note ID.\n * @event visibility-changed Emitted after a note's visibility was changed. Payload: `{ id, visibility }`.\n * @event mention Emitted after a note that mentions someone was added. Payload: `{ objectId, register, schema, noteId, mentionedUserIds }`, plus `mentionedGroupIds` when a group (`@\"group/<gid>\"`) is mentioned. nc-vue notifies nobody; the listener does.\n * @event show-all Emitted when the user clicks the \"Show all\" button — parents typically open a full notes sidebar tab.\n */\nexport default {\n\tname: 'CnNotesCard',\n\n\tcomponents: {\n\t\tCnDetailCard,\n\t\tCnNoteBody,\n\t\tCnNoteComposer,\n\t\tCnUserActionMenu,\n\t\tCnVisibilityChip,\n\t\tNcButton,\n\t\tNcCheckboxRadioSwitch,\n\t\tNcLoadingIcon,\n\t\tSend,\n\t\tDelete,\n\t},\n\n\tprops: {\n\t\t/** OpenRegister register ID */\n\t\tregisterId: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema ID */\n\t\tschemaId: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Object UUID */\n\t\tobjectId: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Show the notes of a plain Nextcloud file instead of an OpenRegister\n\t\t * object: the file's id. Used when no `objectId` is given; the notes\n\t\t * are the file's comments (`/remote.php/dav/comments/files/{fileId}`),\n\t\t * the same ones the Files sidebar shows.\n\t\t */\n\t\tfileId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Base API URL for OpenRegister */\n\t\tapiBase: {\n\t\t\ttype: String,\n\t\t\tdefault: '/apps/openregister/api',\n\t\t},\n\n\t\t/** Maximum number of notes to display */\n\t\tmaxDisplay: {\n\t\t\ttype: Number,\n\t\t\tdefault: 5,\n\t\t},\n\n\t\t/** Whether the card is collapsible */\n\t\tcollapsible: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Render the notes body without the surrounding CnDetailCard.\n\t\t *\n\t\t * Set when a surface already supplies the card and the title, such as a\n\t\t * tab panel whose open tab names the panel. Leaving the card on there\n\t\t * nests a card inside a card and shows the label twice.\n\t\t */\n\t\tchromeless: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Show a chip on every note reading internal or public. A note without a\n\t\t * value reads as internal. Off by default, so a host that passes nothing\n\t\t * renders the card as before. Not used for a file source (file comments\n\t\t * carry no flag).\n\t\t */\n\t\tshowVisibility: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Whether the caller may set visibility on this object: the answer the\n\t\t * server gives for `update` on it. The host passes it; the card never\n\t\t * infers it from the current user. When true the card offers the\n\t\t * public switch in the add-note form and a toggle on each note.\n\t\t */\n\t\tcanSetVisibility: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t// --- Pre-translated labels ---\n\t\t/** Card header title. */\n\t\ttitleLabel: { type: String, default: () => t('nextcloud-vue', 'Notes') },\n\t\t/** Label for the submit button that creates a new note. */\n\t\taddNoteLabel: { type: String, default: () => t('nextcloud-vue', 'Add note') },\n\t\t/** Placeholder shown inside the new-note textarea before any input. */\n\t\taddNotePlaceholder: { type: String, default: () => t('nextcloud-vue', 'Write a note…') },\n\t\t/** Empty-state text shown when the object has zero notes. */\n\t\tnoNotesLabel: { type: String, default: () => t('nextcloud-vue', 'No notes yet') },\n\t\t/** Label for the \"Show all\" button rendered when the note list is truncated. */\n\t\tshowAllLabel: { type: String, default: () => t('nextcloud-vue', 'Show all') },\n\t\t/** Text shown instead of the notes when Nextcloud refuses a file's comments (no access). */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'Notes are not available for this file') },\n\t\t/** Label of the add-note switch that makes the note public. */\n\t\tpublicSwitchLabel: { type: String, default: () => t('nextcloud-vue', 'Public (visible to the customer)') },\n\t\t/** Label of the per-note action that makes an internal note public. */\n\t\tmakePublicLabel: { type: String, default: () => t('nextcloud-vue', 'Make public') },\n\t\t/** Label of the per-note action that makes a public note internal. */\n\t\tmakeInternalLabel: { type: String, default: () => t('nextcloud-vue', 'Make internal') },\n\t\t/** Label of the Reply button (shown only when the backend supports replies). */\n\t\treplyLabel: { type: String, default: () => t('nextcloud-vue', 'Reply') },\n\t\t/** Aria label for the per-note delete icon button. */\n\t\tdeleteLabel: { type: String, default: () => t('nextcloud-vue', 'Delete note') },\n\t},\n\n\temits: ['mention', 'note-added', 'note-deleted', 'show-all', 'visibility-changed'],\n\n\tdata() {\n\t\treturn {\n\t\t\tCommentTextOutline: markRaw(CommentTextOutline),\n\t\t\tallNotes: [],\n\t\t\tloading: false,\n\t\t\tnewNoteText: '',\n\t\t\t/** Visibility the next note is written with (only sent when the caller may set it). */\n\t\t\tnewNoteVisibility: 'internal',\n\t\t\tnoteSaving: false,\n\t\t\tdeleteConfirmId: null,\n\t\t\t/** The file source answered 403 or 404: no notes and no add field. */\n\t\t\tunavailable: false,\n\t\t\t/** The note a reply is being written to, or null. */\n\t\t\treplyTo: null,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** Chips are shown: the host asked for them (or lets the caller set visibility) and the notes are object notes. */\n\t\tvisibilityShown() {\n\t\t\treturn (this.showVisibility || this.canSetVisibility) && !this.isFileSource\n\t\t},\n\n\t\t/** The switch and the per-note toggle are offered: only when the host says the caller may set it. */\n\t\tvisibilityToggleShown() {\n\t\t\treturn this.canSetVisibility && !this.isFileSource\n\t\t},\n\n\t\t/** The file source applies: a file id and no object. */\n\t\tisFileSource() {\n\t\t\treturn this.fileId !== null && this.fileId !== undefined && this.fileId !== '' && !this.objectId\n\t\t},\n\n\t\t/** @return {{apiBase: string, register: string, schema: string, objectId: string}} Where this record's files live, for pasted images. */\n\t\trecord() {\n\t\t\treturn { apiBase: this.apiBase, register: this.registerId, schema: this.schemaId, objectId: this.objectId }\n\t\t},\n\n\t\t/** @return {boolean} Whether the backend supports replies: its notes carry a `parentId` key. Not for a file's comments. */\n\t\tcanReply() {\n\t\t\treturn !this.isFileSource && supportsReplies(this.allNotes)\n\t\t},\n\n\t\t/** @return {Array<{note: object, replies: object[]}>} The shown notes as threads. */\n\t\tthreads() {\n\t\t\treturn threadNotes(this.displayedNotes)\n\t\t},\n\n\t\t/** @return {string} The line above the form while replying. */\n\t\treplyingLabel() {\n\t\t\treturn this.replyTo ? t('nextcloud-vue', 'Replying to {author}', { author: this.getNoteAuthorName(this.replyTo) }) : ''\n\t\t},\n\n\t\tdisplayedNotes() {\n\t\t\t// Reverse chronological, limited to maxDisplay\n\t\t\tconst sorted = [...this.allNotes].sort((a, b) => {\n\t\t\t\tconst dateA = new Date(a.creationDateTime || a.created || 0)\n\t\t\t\tconst dateB = new Date(b.creationDateTime || b.created || 0)\n\t\t\t\treturn dateB - dateA\n\t\t\t})\n\t\t\treturn sorted.slice(0, this.maxDisplay)\n\t\t},\n\t},\n\n\twatch: {\n\t\tfileId: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tif (this.isFileSource) {\n\t\t\t\t\tthis.fetchNotes()\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\n\t\tobjectId: {\n\t\t\timmediate: true,\n\t\t\thandler(newId) {\n\t\t\t\tif (newId && this.registerId && this.schemaId) {\n\t\t\t\t\tthis.fetchNotes()\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * A note's visibility; an entry with no value reads as internal.\n\t\t *\n\t\t * @param {object} note The note.\n\t\t * @return {'public'|'internal'} The visibility.\n\t\t */\n\t\tnoteVisibility(note) {\n\t\t\treturn note && note.visibility === 'public' ? 'public' : 'internal'\n\t\t},\n\n\t\t/**\n\t\t * The one place a note write goes out: creating a note and changing its\n\t\t * visibility both send through here, so the value is sent from one spot.\n\t\t *\n\t\t * @param {'POST'|'PATCH'} method The HTTP method.\n\t\t * @param {string} url The notes URL (with the note id for a change).\n\t\t * @param {object} body The JSON body.\n\t\t * @return {Promise<Response>} The response.\n\t\t */\n\t\twriteNote(method, url, body) {\n\t\t\treturn fetch(prefixUrl(url), { method, headers: buildHeaders(), body: JSON.stringify(body) })\n\t\t},\n\n\t\t/**\n\t\t * Flip a note between internal and public.\n\t\t *\n\t\t * @param {object} note The note.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync toggleVisibility(note) {\n\t\t\tif (!this.visibilityToggleShown) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst next = this.noteVisibility(note) === 'public' ? 'internal' : 'public'\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes/${note.id}`\n\t\t\t\tconst response = await this.writeNote('PATCH', url, { visibility: next })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tthis.allNotes = this.allNotes.map((n) => (n.id === note.id ? { ...n, visibility: next } : n))\n\t\t\t\t\t/** @event visibility-changed Emitted after a note's visibility was changed. Payload: `{ id, visibility }`. */\n\t\t\t\t\tthis.$emit('visibility-changed', { id: note.id, visibility: next })\n\t\t\t\t} else {\n\t\t\t\t\tthis.showError('Failed to change visibility')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to change visibility', err)\n\t\t\t\tthis.showError('Failed to change visibility')\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The rows of one thread: the note, then its replies. A reply whose parent\n\t\t * is far up the list carries a one-line quote of it.\n\t\t *\n\t\t * @param {{note: object, replies: object[]}} thread The thread.\n\t\t * @return {Array<{note: object, isReply: boolean, quote: string}>} The rows.\n\t\t */\n\t\tthreadRows(thread) {\n\t\t\tconst flat = this.threads.flatMap((t2) => [t2.note, ...t2.replies])\n\t\t\treturn [\n\t\t\t\t{ note: thread.note, isReply: false, quote: '' },\n\t\t\t\t...thread.replies.map((reply) => ({ note: reply, isReply: true, quote: quoteFor(reply, flat) })),\n\t\t\t]\n\t\t},\n\n\t\t/**\n\t\t * @param {object} note A top-level note.\n\t\t * @return {string} The name of its thread for assistive technology.\n\t\t */\n\t\tthreadLabel(note) {\n\t\t\treturn t('nextcloud-vue', 'Note by {author} and its replies', { author: this.getNoteAuthorName(note) })\n\t\t},\n\n\t\t/**\n\t\t * @param {object} note The note a Reply button answers.\n\t\t * @return {string} The button's accessible name, naming the author.\n\t\t */\n\t\treplyAria(note) {\n\t\t\treturn t('nextcloud-vue', 'Reply to {author}', { author: this.getNoteAuthorName(note) })\n\t\t},\n\n\t\t/**\n\t\t * Tell the host a saved note mentions someone. The payload keeps the\n\t\t * user ids and adds the group ids only when a group is mentioned.\n\t\t *\n\t\t * @param {string} text The saved text.\n\t\t * @param {string|null} noteId The note's id.\n\t\t * @return {void}\n\t\t */\n\t\temitMentionEvent(text, noteId) {\n\t\t\tconst mentionedUserIds = extractMentionedIds(text)\n\t\t\tconst mentionedGroupIds = extractMentionedGroupIds(text)\n\t\t\tif (mentionedUserIds.length === 0 && mentionedGroupIds.length === 0) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.$emit('mention', {\n\t\t\t\tobjectId: this.objectId,\n\t\t\t\tregister: this.registerId,\n\t\t\t\tschema: this.schemaId,\n\t\t\t\tnoteId,\n\t\t\t\tmentionedUserIds,\n\t\t\t\t...(mentionedGroupIds.length > 0 ? { mentionedGroupIds } : {}),\n\t\t\t})\n\t\t},\n\n\t\tgetNoteAuthorId(note) {\n\t\t\treturn note.actorId || note.author || ''\n\t\t},\n\n\t\tgetNoteAuthorName(note) {\n\t\t\treturn note.actorDisplayName || note.author || 'Unknown'\n\t\t},\n\n\t\tisCurrentUser(note) {\n\t\t\tconst authorId = this.getNoteAuthorId(note)\n\t\t\tconst currentUser = typeof OC !== 'undefined' ? OC?.currentUser : null\n\t\t\treturn authorId === currentUser\n\t\t},\n\n\t\tcanDeleteNote(note) {\n\t\t\treturn this.isCurrentUser(note)\n\t\t},\n\n\t\tfileComments() {\n\t\t\treturn useFileComments(this.fileId)\n\t\t},\n\n\t\tasync fetchNotes() {\n\t\t\tif (this.isFileSource) {\n\t\t\t\tthis.loading = true\n\t\t\t\tthis.unavailable = false\n\t\t\t\ttry {\n\t\t\t\t\tthis.allNotes = await this.fileComments().list()\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthis.allNotes = []\n\t\t\t\t\tthis.unavailable = err && (err.status === 403 || err.status === 404)\n\t\t\t\t\tif (!this.unavailable) {\n\t\t\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\t\t\tconsole.error('CnNotesCard: Failed to fetch file comments', err)\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tthis.loading = false\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!this.registerId || !this.schemaId || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes`\n\t\t\t\tconst response = await fetch(prefixUrl(url), { 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.allNotes = data.results || data || []\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to fetch notes', err)\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync submitNote() {\n\t\t\tif (!this.newNoteText.trim() || this.noteSaving) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.noteSaving = true\n\t\t\tif (this.isFileSource) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.fileComments().add(this.newNoteText.trim())\n\t\t\t\t\tthis.newNoteText = ''\n\t\t\t\t\tawait this.fetchNotes()\n\t\t\t\t\tthis.$emit('note-added')\n\t\t\t\t} catch (err) {\n\t\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\t\tconsole.error('CnNotesCard: Failed to add file comment', err)\n\t\t\t\t\tthis.showError('Failed to add note')\n\t\t\t\t} finally {\n\t\t\t\t\tthis.noteSaving = false\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes`\n\t\t\t\tconst body = { message: this.newNoteText.trim() }\n\t\t\t\tif (this.visibilityToggleShown) {\n\t\t\t\t\tbody.visibility = this.newNoteVisibility\n\t\t\t\t}\n\t\t\t\tif (this.replyTo) {\n\t\t\t\t\tbody.parentId = threadRootId(this.replyTo, this.allNotes)\n\t\t\t\t}\n\t\t\t\tconst response = await this.writeNote('POST', url, body)\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tlet noteId = null\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst created = await response.json()\n\t\t\t\t\t\tnoteId = (created && (created.id || (created.results && created.results.id))) || null\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Body not JSON: the event still fires with noteId null.\n\t\t\t\t\t}\n\t\t\t\t\tthis.emitMentionEvent(body.message, noteId)\n\t\t\t\t\tthis.replyTo = null\n\t\t\t\t\tthis.newNoteText = ''\n\t\t\t\t\tthis.newNoteVisibility = 'internal'\n\t\t\t\t\tawait this.fetchNotes()\n\t\t\t\t\tthis.$emit('note-added')\n\t\t\t\t} else {\n\t\t\t\t\tthis.showError('Failed to add note')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to add note', err)\n\t\t\t\tthis.showError('Failed to add note')\n\t\t\t} finally {\n\t\t\t\tthis.noteSaving = false\n\t\t\t}\n\t\t},\n\n\t\tasync confirmDelete(note) {\n\t\t\t// Simple inline confirmation — delete directly\n\t\t\tif (this.isFileSource) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.fileComments().remove(note.id)\n\t\t\t\t\tthis.allNotes = this.allNotes.filter((n) => n.id !== note.id)\n\t\t\t\t\tthis.$emit('note-deleted')\n\t\t\t\t} catch (err) {\n\t\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\t\tconsole.error('CnNotesCard: Failed to delete file comment', err)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes/${note.id}`\n\t\t\t\tconst response = await fetch(prefixUrl(url), {\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\tthis.allNotes = this.allNotes.filter((n) => n.id !== note.id)\n\t\t\t\t\tthis.$emit('note-deleted')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to delete note', err)\n\t\t\t}\n\t\t},\n\n\t\tformatDate(dateStr) {\n\t\t\tif (!dateStr) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\ttry {\n\t\t\t\treturn new Date(dateStr).toLocaleString(undefined, {\n\t\t\t\t\tyear: 'numeric',\n\t\t\t\t\tmonth: 'short',\n\t\t\t\t\tday: 'numeric',\n\t\t\t\t\thour: '2-digit',\n\t\t\t\t\tminute: '2-digit',\n\t\t\t\t})\n\t\t\t} catch {\n\t\t\t\treturn dateStr\n\t\t\t}\n\t\t},\n\n\t\tshowError(message) {\n\t\t\ttry {\n\t\t\t\timport('@nextcloud/dialogs').then(({ showError }) => {\n\t\t\t\t\tshowError(message)\n\t\t\t\t})\n\t\t\t} catch {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error(message)\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-notes-card__add-form {\n\tmargin-bottom: 12px;\n}\n\n.cn-notes-card__textarea {\n\twidth: 100%;\n\tmargin-bottom: 8px;\n\tbox-sizing: border-box;\n}\n\n.cn-notes-card__replying {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: space-between;\n\tmargin: 0 0 4px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-notes-card__note--reply {\n\tmargin-inline-start: 24px;\n}\n\n.cn-notes-card__quote {\n\tmargin: 0 0 2px;\n\tpadding-inline-start: 8px;\n\tborder-inline-start: 2px solid var(--color-border-dark);\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n}\n\n.cn-notes-card__empty {\n\ttext-align: center;\n\tpadding: 16px 12px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-notes-card__list {\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.cn-notes-card__note {\n\tpadding: 10px 0;\n\tborder-bottom: 1px solid var(--color-border);\n\tposition: relative;\n}\n\n.cn-notes-card__note:last-child {\n\tborder-bottom: none;\n}\n\n.cn-notes-card__note-header {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: baseline;\n\tmargin-bottom: 4px;\n}\n\n.cn-notes-card__author {\n\tfont-size: 13px;\n}\n\n.cn-notes-card__author--self {\n\tcolor: var(--color-main-text);\n}\n\n.cn-notes-card__visibility {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tmargin-bottom: 4px;\n}\n\n.cn-notes-card__time {\n\tfont-size: 11px;\n\tcolor: var(--color-text-maxcontrast);\n\tflex-shrink: 0;\n\tmargin-left: 8px;\n}\n\n.cn-notes-card__body {\n\tfont-size: 13px;\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\toverflow-wrap: anywhere;\n\tpadding-right: 32px;\n}\n\n.cn-notes-card__delete-btn {\n\tposition: absolute;\n\ttop: 8px;\n\tright: -4px;\n\topacity: 0;\n\ttransition: opacity 0.15s ease;\n}\n\n.cn-notes-card__note:hover .cn-notes-card__delete-btn {\n\topacity: 1;\n}\n\n.cn-notes-card__show-all {\n\tbackground: none;\n\tborder: none;\n\tcolor: var(--color-primary-element);\n\tfont-size: 13px;\n\tfont-weight: 500;\n\tcursor: pointer;\n\tpadding: 0;\n\twidth: 100%;\n\ttext-align: center;\n}\n\n.cn-notes-card__show-all:hover {\n\ttext-decoration: underline;\n}\n</style>\n"],"names":["CnDetailCard","CnNoteBody","CnNoteComposer","CnUserActionMenu","CnVisibilityChip","t"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnNotesCard.vue2.js","sources":["../../../../src/components/CnNotesCard/CnNotesCard.vue"],"sourcesContent":["<!--\n CnNotesCard — Inline notes card for detail pages.\n\n Displays up to 5 recent notes with author, content, and timestamp.\n Includes an add-note form and integrates CnUserActionMenu on author names.\n Wraps CnDetailCard for consistent styling.\n-->\n<template>\n\t<CnDetailCard :title=\"titleLabel\"\n\t\t:icon=\"CommentTextOutline\"\n\t\t:collapsible=\"collapsible\"\n\t\t:chromeless=\"chromeless\">\n\t\t<div class=\"cn-notes-card\">\n\t\t\t<!-- Add note input -->\n\t\t\t<div v-if=\"!unavailable\" class=\"cn-notes-card__add-form\">\n\t\t\t\t<!-- Replying: the form says to whom; a reply to a reply goes to the top of its thread. -->\n\t\t\t\t<p\n\t\t\t\t\tv-if=\"replyTo\"\n\t\t\t\t\tclass=\"cn-notes-card__replying\"\n\t\t\t\t\trole=\"status\"\n\t\t\t\t\tdata-testid=\"cn-notes-card-replying\">\n\t\t\t\t\t{{ replyingLabel }}\n\t\t\t\t\t<NcButton variant=\"tertiary\" @click=\"replyTo = null\">\n\t\t\t\t\t\t{{ t('nextcloud-vue', 'Cancel') }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t</p>\n\t\t\t\t<CnNoteComposer\n\t\t\t\t\tclass=\"cn-notes-card__textarea\"\n\t\t\t\t\t:modelValue=\"newNoteText\"\n\t\t\t\t\t:placeholder=\"addNotePlaceholder\"\n\t\t\t\t\t:register=\"isFileSource ? '' : registerId\"\n\t\t\t\t\t:schema=\"isFileSource ? '' : schemaId\"\n\t\t\t\t\t:objectId=\"isFileSource ? '' : objectId\"\n\t\t\t\t\t:apiBase=\"apiBase\"\n\t\t\t\t\t@update:modelValue=\"newNoteText = $event\"\n\t\t\t\t\t@submit=\"submitNote\" />\n\t\t\t\t<!-- Internal or public, chosen before the note is written (only when the host says the caller may set it). -->\n\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\tv-if=\"visibilityToggleShown\"\n\t\t\t\t\t:modelValue=\"newNoteVisibility === 'public'\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\tdata-testid=\"cn-notes-card-visibility-switch\"\n\t\t\t\t\t@update:modelValue=\"(on) => newNoteVisibility = on ? 'public' : 'internal'\">\n\t\t\t\t\t{{ publicSwitchLabel }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t:disabled=\"!newNoteText.trim() || noteSaving\"\n\t\t\t\t\t@click=\"submitNote\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<Send :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ addNoteLabel }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\n\t\t\t<!-- Loading state -->\n\t\t\t<NcLoadingIcon v-if=\"loading\" />\n\n\t\t\t<!-- Empty state -->\n\t\t\t<div v-else-if=\"unavailable\" class=\"cn-notes-card__empty\" data-testid=\"cn-notes-card-unavailable\">\n\t\t\t\t{{ unavailableLabel }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"allNotes.length === 0\" class=\"cn-notes-card__empty\">\n\t\t\t\t{{ noNotesLabel }}\n\t\t\t</div>\n\n\t\t\t<!-- Notes list (last 5), threaded: a note, then its replies. -->\n\t\t\t<div v-else class=\"cn-notes-card__list\">\n\t\t\t\t<div\n\t\t\t\t\tv-for=\"thread in threads\"\n\t\t\t\t\t:key=\"thread.note.id\"\n\t\t\t\t\tclass=\"cn-notes-card__thread\"\n\t\t\t\t\trole=\"group\"\n\t\t\t\t\t:aria-label=\"threadLabel(thread.note)\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-for=\"row in threadRows(thread)\"\n\t\t\t\t\t\t:key=\"row.note.id\"\n\t\t\t\t\t\tclass=\"cn-notes-card__note\"\n\t\t\t\t\t\t:class=\"{ 'cn-notes-card__note--reply': row.isReply }\">\n\t\t\t\t\t\t<div class=\"cn-notes-card__note-header\">\n\t\t\t\t\t\t\t<CnUserActionMenu\n\t\t\t\t\t\t\t\tv-if=\"!isCurrentUser(row.note)\"\n\t\t\t\t\t\t\t\t:userId=\"getNoteAuthorId(row.note)\"\n\t\t\t\t\t\t\t\t:displayName=\"getNoteAuthorName(row.note)\">\n\t\t\t\t\t\t\t\t<strong class=\"cn-notes-card__author\">{{ getNoteAuthorName(row.note) }}</strong>\n\t\t\t\t\t\t\t</CnUserActionMenu>\n\t\t\t\t\t\t\t<strong v-else class=\"cn-notes-card__author cn-notes-card__author--self\">\n\t\t\t\t\t\t\t\t{{ getNoteAuthorName(row.note) }}\n\t\t\t\t\t\t\t</strong>\n\t\t\t\t\t\t\t<span class=\"cn-notes-card__time\">{{ formatDate(row.note.creationDateTime || row.note.created) }}</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div v-if=\"visibilityShown\" class=\"cn-notes-card__visibility\">\n\t\t\t\t\t\t\t<CnVisibilityChip :visibility=\"row.note.visibility\" />\n\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\tv-if=\"visibilityToggleShown\"\n\t\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\t\tdata-testid=\"cn-notes-card-visibility-toggle\"\n\t\t\t\t\t\t\t\t@click=\"toggleVisibility(row.note)\">\n\t\t\t\t\t\t\t\t{{ noteVisibility(row.note) === 'public' ? makeInternalLabel : makePublicLabel }}\n\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<p v-if=\"row.quote\" class=\"cn-notes-card__quote\" data-testid=\"cn-notes-card-quote\">\n\t\t\t\t\t\t\t{{ row.quote }}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p class=\"cn-notes-card__body\">\n\t\t\t\t\t\t\t<CnNoteBody :message=\"row.note.message || row.note.content || ''\" :record=\"isFileSource ? null : record\" />\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"canReply\"\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\t:aria-label=\"replyAria(row.note)\"\n\t\t\t\t\t\t\tdata-testid=\"cn-notes-card-reply\"\n\t\t\t\t\t\t\t@click=\"replyTo = row.note\">\n\t\t\t\t\t\t\t{{ replyLabel }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"canDeleteNote(row.note)\"\n\t\t\t\t\t\t\tvariant=\"tertiary-no-background\"\n\t\t\t\t\t\t\tclass=\"cn-notes-card__delete-btn\"\n\t\t\t\t\t\t\t:aria-label=\"deleteLabel\"\n\t\t\t\t\t\t\t@click=\"confirmDelete(row.note)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Delete :size=\"16\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- Footer: \"Show all\" link -->\n\t\t<template v-if=\"allNotes.length > maxDisplay\" #footer>\n\t\t\t<button\n\t\t\t\tclass=\"cn-notes-card__show-all\"\n\t\t\t\t@click=\"$emit('show-all')\">\n\t\t\t\t{{ showAllLabel }} ({{ allNotes.length }})\n\t\t\t</button>\n\t\t</template>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcLoadingIcon } from '@nextcloud/vue'\nimport { markRaw } from 'vue'\nimport CommentTextOutline from 'vue-material-design-icons/CommentTextOutline.vue'\nimport Delete from 'vue-material-design-icons/Delete.vue'\nimport Send from 'vue-material-design-icons/Send.vue'\nimport CnDetailCard from '../CnDetailCard/CnDetailCard.vue'\nimport CnNoteBody from '../CnNoteBody/CnNoteBody.vue'\nimport CnNoteComposer from '../CnNoteComposer/CnNoteComposer.vue'\nimport CnUserActionMenu from '../CnUserActionMenu/CnUserActionMenu.vue'\nimport CnVisibilityChip from '../CnVisibilityChip/CnVisibilityChip.vue'\nimport { useFileComments } from '../../composables/useFileComments.js'\nimport { buildHeaders, prefixUrl } from '../../utils/index.js'\nimport { extractMentionedGroupIds, extractMentionedIds } from '../../utils/mentions.js'\nimport { quoteFor, supportsReplies, threadNotes, threadRootId } from '../../utils/noteThreads.js'\nimport { userLocale } from '../../utils/userLocale.js'\n\n/**\n * CnNotesCard — Inline notes widget for detail pages.\n *\n * Shows up to 5 recent notes with add/delete functionality.\n * Integrates CnUserActionMenu on author names for quick communication.\n *\n * Basic usage\n * ```vue\n * <CnNotesCard\n * register-id=\"uuid-register\"\n * schema-id=\"uuid-schema\"\n * object-id=\"uuid-object\" />\n * ```\n *\n * With sidebar sync\n * ```vue\n * <CnNotesCard\n * register-id=\"reg\"\n * schema-id=\"schema\"\n * object-id=\"obj\"\n * @note-added=\"refreshNotes\"\n * @note-deleted=\"refreshNotes\"\n * @show-all=\"openSidebarNotesTab\" />\n * ```\n *\n * @event note-added Emitted after a new note is successfully persisted. Payload: the created note object.\n * @event note-deleted Emitted after a note is successfully deleted. Payload: the deleted note ID.\n * @event visibility-changed Emitted after a note's visibility was changed. Payload: `{ id, visibility }`.\n * @event mention Emitted after a note that mentions someone was added. Payload: `{ objectId, register, schema, noteId, mentionedUserIds }`, plus `mentionedGroupIds` when a group (`@\"group/<gid>\"`) is mentioned. nc-vue notifies nobody; the listener does.\n * @event show-all Emitted when the user clicks the \"Show all\" button — parents typically open a full notes sidebar tab.\n */\nexport default {\n\tname: 'CnNotesCard',\n\n\tcomponents: {\n\t\tCnDetailCard,\n\t\tCnNoteBody,\n\t\tCnNoteComposer,\n\t\tCnUserActionMenu,\n\t\tCnVisibilityChip,\n\t\tNcButton,\n\t\tNcCheckboxRadioSwitch,\n\t\tNcLoadingIcon,\n\t\tSend,\n\t\tDelete,\n\t},\n\n\tprops: {\n\t\t/** OpenRegister register ID */\n\t\tregisterId: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema ID */\n\t\tschemaId: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Object UUID */\n\t\tobjectId: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Show the notes of a plain Nextcloud file instead of an OpenRegister\n\t\t * object: the file's id. Used when no `objectId` is given; the notes\n\t\t * are the file's comments (`/remote.php/dav/comments/files/{fileId}`),\n\t\t * the same ones the Files sidebar shows.\n\t\t */\n\t\tfileId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Base API URL for OpenRegister */\n\t\tapiBase: {\n\t\t\ttype: String,\n\t\t\tdefault: '/apps/openregister/api',\n\t\t},\n\n\t\t/** Maximum number of notes to display */\n\t\tmaxDisplay: {\n\t\t\ttype: Number,\n\t\t\tdefault: 5,\n\t\t},\n\n\t\t/** Whether the card is collapsible */\n\t\tcollapsible: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Render the notes body without the surrounding CnDetailCard.\n\t\t *\n\t\t * Set when a surface already supplies the card and the title, such as a\n\t\t * tab panel whose open tab names the panel. Leaving the card on there\n\t\t * nests a card inside a card and shows the label twice.\n\t\t */\n\t\tchromeless: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Show a chip on every note reading internal or public. A note without a\n\t\t * value reads as internal. Off by default, so a host that passes nothing\n\t\t * renders the card as before. Not used for a file source (file comments\n\t\t * carry no flag).\n\t\t */\n\t\tshowVisibility: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Whether the caller may set visibility on this object: the answer the\n\t\t * server gives for `update` on it. The host passes it; the card never\n\t\t * infers it from the current user. When true the card offers the\n\t\t * public switch in the add-note form and a toggle on each note.\n\t\t */\n\t\tcanSetVisibility: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t// --- Pre-translated labels ---\n\t\t/** Card header title. */\n\t\ttitleLabel: { type: String, default: () => t('nextcloud-vue', 'Notes') },\n\t\t/** Label for the submit button that creates a new note. */\n\t\taddNoteLabel: { type: String, default: () => t('nextcloud-vue', 'Add note') },\n\t\t/** Placeholder shown inside the new-note textarea before any input. */\n\t\taddNotePlaceholder: { type: String, default: () => t('nextcloud-vue', 'Write a note…') },\n\t\t/** Empty-state text shown when the object has zero notes. */\n\t\tnoNotesLabel: { type: String, default: () => t('nextcloud-vue', 'No notes yet') },\n\t\t/** Label for the \"Show all\" button rendered when the note list is truncated. */\n\t\tshowAllLabel: { type: String, default: () => t('nextcloud-vue', 'Show all') },\n\t\t/** Text shown instead of the notes when Nextcloud refuses a file's comments (no access). */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'Notes are not available for this file') },\n\t\t/** Label of the add-note switch that makes the note public. */\n\t\tpublicSwitchLabel: { type: String, default: () => t('nextcloud-vue', 'Public (visible to the customer)') },\n\t\t/** Label of the per-note action that makes an internal note public. */\n\t\tmakePublicLabel: { type: String, default: () => t('nextcloud-vue', 'Make public') },\n\t\t/** Label of the per-note action that makes a public note internal. */\n\t\tmakeInternalLabel: { type: String, default: () => t('nextcloud-vue', 'Make internal') },\n\t\t/** Label of the Reply button (shown only when the backend supports replies). */\n\t\treplyLabel: { type: String, default: () => t('nextcloud-vue', 'Reply') },\n\t\t/** Aria label for the per-note delete icon button. */\n\t\tdeleteLabel: { type: String, default: () => t('nextcloud-vue', 'Delete note') },\n\t},\n\n\temits: ['mention', 'note-added', 'note-deleted', 'show-all', 'visibility-changed'],\n\n\tdata() {\n\t\treturn {\n\t\t\tCommentTextOutline: markRaw(CommentTextOutline),\n\t\t\tallNotes: [],\n\t\t\tloading: false,\n\t\t\tnewNoteText: '',\n\t\t\t/** Visibility the next note is written with (only sent when the caller may set it). */\n\t\t\tnewNoteVisibility: 'internal',\n\t\t\tnoteSaving: false,\n\t\t\tdeleteConfirmId: null,\n\t\t\t/** The file source answered 403 or 404: no notes and no add field. */\n\t\t\tunavailable: false,\n\t\t\t/** The note a reply is being written to, or null. */\n\t\t\treplyTo: null,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** Chips are shown: the host asked for them (or lets the caller set visibility) and the notes are object notes. */\n\t\tvisibilityShown() {\n\t\t\treturn (this.showVisibility || this.canSetVisibility) && !this.isFileSource\n\t\t},\n\n\t\t/** The switch and the per-note toggle are offered: only when the host says the caller may set it. */\n\t\tvisibilityToggleShown() {\n\t\t\treturn this.canSetVisibility && !this.isFileSource\n\t\t},\n\n\t\t/** The file source applies: a file id and no object. */\n\t\tisFileSource() {\n\t\t\treturn this.fileId !== null && this.fileId !== undefined && this.fileId !== '' && !this.objectId\n\t\t},\n\n\t\t/** @return {{apiBase: string, register: string, schema: string, objectId: string}} Where this record's files live, for pasted images. */\n\t\trecord() {\n\t\t\treturn { apiBase: this.apiBase, register: this.registerId, schema: this.schemaId, objectId: this.objectId }\n\t\t},\n\n\t\t/** @return {boolean} Whether the backend supports replies: its notes carry a `parentId` key. Not for a file's comments. */\n\t\tcanReply() {\n\t\t\treturn !this.isFileSource && supportsReplies(this.allNotes)\n\t\t},\n\n\t\t/** @return {Array<{note: object, replies: object[]}>} The shown notes as threads. */\n\t\tthreads() {\n\t\t\treturn threadNotes(this.displayedNotes)\n\t\t},\n\n\t\t/** @return {string} The line above the form while replying. */\n\t\treplyingLabel() {\n\t\t\treturn this.replyTo ? t('nextcloud-vue', 'Replying to {author}', { author: this.getNoteAuthorName(this.replyTo) }) : ''\n\t\t},\n\n\t\tdisplayedNotes() {\n\t\t\t// Reverse chronological, limited to maxDisplay\n\t\t\tconst sorted = [...this.allNotes].sort((a, b) => {\n\t\t\t\tconst dateA = new Date(a.creationDateTime || a.created || 0)\n\t\t\t\tconst dateB = new Date(b.creationDateTime || b.created || 0)\n\t\t\t\treturn dateB - dateA\n\t\t\t})\n\t\t\treturn sorted.slice(0, this.maxDisplay)\n\t\t},\n\t},\n\n\twatch: {\n\t\tfileId: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tif (this.isFileSource) {\n\t\t\t\t\tthis.fetchNotes()\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\n\t\tobjectId: {\n\t\t\timmediate: true,\n\t\t\thandler(newId) {\n\t\t\t\tif (newId && this.registerId && this.schemaId) {\n\t\t\t\t\tthis.fetchNotes()\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * A note's visibility; an entry with no value reads as internal.\n\t\t *\n\t\t * @param {object} note The note.\n\t\t * @return {'public'|'internal'} The visibility.\n\t\t */\n\t\tnoteVisibility(note) {\n\t\t\treturn note && note.visibility === 'public' ? 'public' : 'internal'\n\t\t},\n\n\t\t/**\n\t\t * The one place a note write goes out: creating a note and changing its\n\t\t * visibility both send through here, so the value is sent from one spot.\n\t\t *\n\t\t * @param {'POST'|'PATCH'} method The HTTP method.\n\t\t * @param {string} url The notes URL (with the note id for a change).\n\t\t * @param {object} body The JSON body.\n\t\t * @return {Promise<Response>} The response.\n\t\t */\n\t\twriteNote(method, url, body) {\n\t\t\treturn fetch(prefixUrl(url), { method, headers: buildHeaders(), body: JSON.stringify(body) })\n\t\t},\n\n\t\t/**\n\t\t * Flip a note between internal and public.\n\t\t *\n\t\t * @param {object} note The note.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync toggleVisibility(note) {\n\t\t\tif (!this.visibilityToggleShown) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst next = this.noteVisibility(note) === 'public' ? 'internal' : 'public'\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes/${note.id}`\n\t\t\t\tconst response = await this.writeNote('PATCH', url, { visibility: next })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tthis.allNotes = this.allNotes.map((n) => (n.id === note.id ? { ...n, visibility: next } : n))\n\t\t\t\t\t/** @event visibility-changed Emitted after a note's visibility was changed. Payload: `{ id, visibility }`. */\n\t\t\t\t\tthis.$emit('visibility-changed', { id: note.id, visibility: next })\n\t\t\t\t} else {\n\t\t\t\t\tthis.showError('Failed to change visibility')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to change visibility', err)\n\t\t\t\tthis.showError('Failed to change visibility')\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The rows of one thread: the note, then its replies. A reply whose parent\n\t\t * is far up the list carries a one-line quote of it.\n\t\t *\n\t\t * @param {{note: object, replies: object[]}} thread The thread.\n\t\t * @return {Array<{note: object, isReply: boolean, quote: string}>} The rows.\n\t\t */\n\t\tthreadRows(thread) {\n\t\t\tconst flat = this.threads.flatMap((t2) => [t2.note, ...t2.replies])\n\t\t\treturn [\n\t\t\t\t{ note: thread.note, isReply: false, quote: '' },\n\t\t\t\t...thread.replies.map((reply) => ({ note: reply, isReply: true, quote: quoteFor(reply, flat) })),\n\t\t\t]\n\t\t},\n\n\t\t/**\n\t\t * @param {object} note A top-level note.\n\t\t * @return {string} The name of its thread for assistive technology.\n\t\t */\n\t\tthreadLabel(note) {\n\t\t\treturn t('nextcloud-vue', 'Note by {author} and its replies', { author: this.getNoteAuthorName(note) })\n\t\t},\n\n\t\t/**\n\t\t * @param {object} note The note a Reply button answers.\n\t\t * @return {string} The button's accessible name, naming the author.\n\t\t */\n\t\treplyAria(note) {\n\t\t\treturn t('nextcloud-vue', 'Reply to {author}', { author: this.getNoteAuthorName(note) })\n\t\t},\n\n\t\t/**\n\t\t * Tell the host a saved note mentions someone. The payload keeps the\n\t\t * user ids and adds the group ids only when a group is mentioned.\n\t\t *\n\t\t * @param {string} text The saved text.\n\t\t * @param {string|null} noteId The note's id.\n\t\t * @return {void}\n\t\t */\n\t\temitMentionEvent(text, noteId) {\n\t\t\tconst mentionedUserIds = extractMentionedIds(text)\n\t\t\tconst mentionedGroupIds = extractMentionedGroupIds(text)\n\t\t\tif (mentionedUserIds.length === 0 && mentionedGroupIds.length === 0) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.$emit('mention', {\n\t\t\t\tobjectId: this.objectId,\n\t\t\t\tregister: this.registerId,\n\t\t\t\tschema: this.schemaId,\n\t\t\t\tnoteId,\n\t\t\t\tmentionedUserIds,\n\t\t\t\t...(mentionedGroupIds.length > 0 ? { mentionedGroupIds } : {}),\n\t\t\t})\n\t\t},\n\n\t\tgetNoteAuthorId(note) {\n\t\t\treturn note.actorId || note.author || ''\n\t\t},\n\n\t\tgetNoteAuthorName(note) {\n\t\t\treturn note.actorDisplayName || note.author || 'Unknown'\n\t\t},\n\n\t\tisCurrentUser(note) {\n\t\t\tconst authorId = this.getNoteAuthorId(note)\n\t\t\tconst currentUser = typeof OC !== 'undefined' ? OC?.currentUser : null\n\t\t\treturn authorId === currentUser\n\t\t},\n\n\t\tcanDeleteNote(note) {\n\t\t\treturn this.isCurrentUser(note)\n\t\t},\n\n\t\tfileComments() {\n\t\t\treturn useFileComments(this.fileId)\n\t\t},\n\n\t\tasync fetchNotes() {\n\t\t\tif (this.isFileSource) {\n\t\t\t\tthis.loading = true\n\t\t\t\tthis.unavailable = false\n\t\t\t\ttry {\n\t\t\t\t\tthis.allNotes = await this.fileComments().list()\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthis.allNotes = []\n\t\t\t\t\tthis.unavailable = err && (err.status === 403 || err.status === 404)\n\t\t\t\t\tif (!this.unavailable) {\n\t\t\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\t\t\tconsole.error('CnNotesCard: Failed to fetch file comments', err)\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tthis.loading = false\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!this.registerId || !this.schemaId || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes`\n\t\t\t\tconst response = await fetch(prefixUrl(url), { 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.allNotes = data.results || data || []\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to fetch notes', err)\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync submitNote() {\n\t\t\tif (!this.newNoteText.trim() || this.noteSaving) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.noteSaving = true\n\t\t\tif (this.isFileSource) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.fileComments().add(this.newNoteText.trim())\n\t\t\t\t\tthis.newNoteText = ''\n\t\t\t\t\tawait this.fetchNotes()\n\t\t\t\t\tthis.$emit('note-added')\n\t\t\t\t} catch (err) {\n\t\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\t\tconsole.error('CnNotesCard: Failed to add file comment', err)\n\t\t\t\t\tthis.showError('Failed to add note')\n\t\t\t\t} finally {\n\t\t\t\t\tthis.noteSaving = false\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes`\n\t\t\t\tconst body = { message: this.newNoteText.trim() }\n\t\t\t\tif (this.visibilityToggleShown) {\n\t\t\t\t\tbody.visibility = this.newNoteVisibility\n\t\t\t\t}\n\t\t\t\tif (this.replyTo) {\n\t\t\t\t\tbody.parentId = threadRootId(this.replyTo, this.allNotes)\n\t\t\t\t}\n\t\t\t\tconst response = await this.writeNote('POST', url, body)\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tlet noteId = null\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst created = await response.json()\n\t\t\t\t\t\tnoteId = (created && (created.id || (created.results && created.results.id))) || null\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Body not JSON: the event still fires with noteId null.\n\t\t\t\t\t}\n\t\t\t\t\tthis.emitMentionEvent(body.message, noteId)\n\t\t\t\t\tthis.replyTo = null\n\t\t\t\t\tthis.newNoteText = ''\n\t\t\t\t\tthis.newNoteVisibility = 'internal'\n\t\t\t\t\tawait this.fetchNotes()\n\t\t\t\t\tthis.$emit('note-added')\n\t\t\t\t} else {\n\t\t\t\t\tthis.showError('Failed to add note')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to add note', err)\n\t\t\t\tthis.showError('Failed to add note')\n\t\t\t} finally {\n\t\t\t\tthis.noteSaving = false\n\t\t\t}\n\t\t},\n\n\t\tasync confirmDelete(note) {\n\t\t\t// Simple inline confirmation — delete directly\n\t\t\tif (this.isFileSource) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.fileComments().remove(note.id)\n\t\t\t\t\tthis.allNotes = this.allNotes.filter((n) => n.id !== note.id)\n\t\t\t\t\tthis.$emit('note-deleted')\n\t\t\t\t} catch (err) {\n\t\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\t\tconsole.error('CnNotesCard: Failed to delete file comment', err)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes/${note.id}`\n\t\t\t\tconst response = await fetch(prefixUrl(url), {\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\tthis.allNotes = this.allNotes.filter((n) => n.id !== note.id)\n\t\t\t\t\tthis.$emit('note-deleted')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to delete note', err)\n\t\t\t}\n\t\t},\n\n\t\tformatDate(dateStr) {\n\t\t\tif (!dateStr) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\ttry {\n\t\t\t\treturn new Date(dateStr).toLocaleString(userLocale(), {\n\t\t\t\t\tyear: 'numeric',\n\t\t\t\t\tmonth: 'short',\n\t\t\t\t\tday: 'numeric',\n\t\t\t\t\thour: '2-digit',\n\t\t\t\t\tminute: '2-digit',\n\t\t\t\t})\n\t\t\t} catch {\n\t\t\t\treturn dateStr\n\t\t\t}\n\t\t},\n\n\t\tshowError(message) {\n\t\t\ttry {\n\t\t\t\timport('@nextcloud/dialogs').then(({ showError }) => {\n\t\t\t\t\tshowError(message)\n\t\t\t\t})\n\t\t\t} catch {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error(message)\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-notes-card__add-form {\n\tmargin-bottom: 12px;\n}\n\n.cn-notes-card__textarea {\n\twidth: 100%;\n\tmargin-bottom: 8px;\n\tbox-sizing: border-box;\n}\n\n.cn-notes-card__replying {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: space-between;\n\tmargin: 0 0 4px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-notes-card__note--reply {\n\tmargin-inline-start: 24px;\n}\n\n.cn-notes-card__quote {\n\tmargin: 0 0 2px;\n\tpadding-inline-start: 8px;\n\tborder-inline-start: 2px solid var(--color-border-dark);\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n}\n\n.cn-notes-card__empty {\n\ttext-align: center;\n\tpadding: 16px 12px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-notes-card__list {\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.cn-notes-card__note {\n\tpadding: 10px 0;\n\tborder-bottom: 1px solid var(--color-border);\n\tposition: relative;\n}\n\n.cn-notes-card__note:last-child {\n\tborder-bottom: none;\n}\n\n.cn-notes-card__note-header {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: baseline;\n\tmargin-bottom: 4px;\n}\n\n.cn-notes-card__author {\n\tfont-size: 13px;\n}\n\n.cn-notes-card__author--self {\n\tcolor: var(--color-main-text);\n}\n\n.cn-notes-card__visibility {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tmargin-bottom: 4px;\n}\n\n.cn-notes-card__time {\n\tfont-size: 11px;\n\tcolor: var(--color-text-maxcontrast);\n\tflex-shrink: 0;\n\tmargin-left: 8px;\n}\n\n.cn-notes-card__body {\n\tfont-size: 13px;\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\toverflow-wrap: anywhere;\n\tpadding-right: 32px;\n}\n\n.cn-notes-card__delete-btn {\n\tposition: absolute;\n\ttop: 8px;\n\tright: -4px;\n\topacity: 0;\n\ttransition: opacity 0.15s ease;\n}\n\n.cn-notes-card__note:hover .cn-notes-card__delete-btn {\n\topacity: 1;\n}\n\n.cn-notes-card__show-all {\n\tbackground: none;\n\tborder: none;\n\tcolor: var(--color-primary-element);\n\tfont-size: 13px;\n\tfont-weight: 500;\n\tcursor: pointer;\n\tpadding: 0;\n\twidth: 100%;\n\ttext-align: center;\n}\n\n.cn-notes-card__show-all:hover {\n\ttext-decoration: underline;\n}\n</style>\n"],"names":["CnDetailCard","CnNoteBody","CnNoteComposer","CnUserActionMenu","CnVisibilityChip","t"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnNotesCard.vue3.js","sources":["../../../../src/components/CnNotesCard/CnNotesCard.vue?vue&type=template&id=7c1ded08&lang.js"],"sourcesContent":["<!--\n CnNotesCard — Inline notes card for detail pages.\n\n Displays up to 5 recent notes with author, content, and timestamp.\n Includes an add-note form and integrates CnUserActionMenu on author names.\n Wraps CnDetailCard for consistent styling.\n-->\n<template>\n\t<CnDetailCard :title=\"titleLabel\"\n\t\t:icon=\"CommentTextOutline\"\n\t\t:collapsible=\"collapsible\"\n\t\t:chromeless=\"chromeless\">\n\t\t<div class=\"cn-notes-card\">\n\t\t\t<!-- Add note input -->\n\t\t\t<div v-if=\"!unavailable\" class=\"cn-notes-card__add-form\">\n\t\t\t\t<!-- Replying: the form says to whom; a reply to a reply goes to the top of its thread. -->\n\t\t\t\t<p\n\t\t\t\t\tv-if=\"replyTo\"\n\t\t\t\t\tclass=\"cn-notes-card__replying\"\n\t\t\t\t\trole=\"status\"\n\t\t\t\t\tdata-testid=\"cn-notes-card-replying\">\n\t\t\t\t\t{{ replyingLabel }}\n\t\t\t\t\t<NcButton variant=\"tertiary\" @click=\"replyTo = null\">\n\t\t\t\t\t\t{{ t('nextcloud-vue', 'Cancel') }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t</p>\n\t\t\t\t<CnNoteComposer\n\t\t\t\t\tclass=\"cn-notes-card__textarea\"\n\t\t\t\t\t:modelValue=\"newNoteText\"\n\t\t\t\t\t:placeholder=\"addNotePlaceholder\"\n\t\t\t\t\t:register=\"isFileSource ? '' : registerId\"\n\t\t\t\t\t:schema=\"isFileSource ? '' : schemaId\"\n\t\t\t\t\t:objectId=\"isFileSource ? '' : objectId\"\n\t\t\t\t\t:apiBase=\"apiBase\"\n\t\t\t\t\t@update:modelValue=\"newNoteText = $event\"\n\t\t\t\t\t@submit=\"submitNote\" />\n\t\t\t\t<!-- Internal or public, chosen before the note is written (only when the host says the caller may set it). -->\n\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\tv-if=\"visibilityToggleShown\"\n\t\t\t\t\t:modelValue=\"newNoteVisibility === 'public'\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\tdata-testid=\"cn-notes-card-visibility-switch\"\n\t\t\t\t\t@update:modelValue=\"(on) => newNoteVisibility = on ? 'public' : 'internal'\">\n\t\t\t\t\t{{ publicSwitchLabel }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t:disabled=\"!newNoteText.trim() || noteSaving\"\n\t\t\t\t\t@click=\"submitNote\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<Send :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ addNoteLabel }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\n\t\t\t<!-- Loading state -->\n\t\t\t<NcLoadingIcon v-if=\"loading\" />\n\n\t\t\t<!-- Empty state -->\n\t\t\t<div v-else-if=\"unavailable\" class=\"cn-notes-card__empty\" data-testid=\"cn-notes-card-unavailable\">\n\t\t\t\t{{ unavailableLabel }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"allNotes.length === 0\" class=\"cn-notes-card__empty\">\n\t\t\t\t{{ noNotesLabel }}\n\t\t\t</div>\n\n\t\t\t<!-- Notes list (last 5), threaded: a note, then its replies. -->\n\t\t\t<div v-else class=\"cn-notes-card__list\">\n\t\t\t\t<div\n\t\t\t\t\tv-for=\"thread in threads\"\n\t\t\t\t\t:key=\"thread.note.id\"\n\t\t\t\t\tclass=\"cn-notes-card__thread\"\n\t\t\t\t\trole=\"group\"\n\t\t\t\t\t:aria-label=\"threadLabel(thread.note)\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-for=\"row in threadRows(thread)\"\n\t\t\t\t\t\t:key=\"row.note.id\"\n\t\t\t\t\t\tclass=\"cn-notes-card__note\"\n\t\t\t\t\t\t:class=\"{ 'cn-notes-card__note--reply': row.isReply }\">\n\t\t\t\t\t\t<div class=\"cn-notes-card__note-header\">\n\t\t\t\t\t\t\t<CnUserActionMenu\n\t\t\t\t\t\t\t\tv-if=\"!isCurrentUser(row.note)\"\n\t\t\t\t\t\t\t\t:userId=\"getNoteAuthorId(row.note)\"\n\t\t\t\t\t\t\t\t:displayName=\"getNoteAuthorName(row.note)\">\n\t\t\t\t\t\t\t\t<strong class=\"cn-notes-card__author\">{{ getNoteAuthorName(row.note) }}</strong>\n\t\t\t\t\t\t\t</CnUserActionMenu>\n\t\t\t\t\t\t\t<strong v-else class=\"cn-notes-card__author cn-notes-card__author--self\">\n\t\t\t\t\t\t\t\t{{ getNoteAuthorName(row.note) }}\n\t\t\t\t\t\t\t</strong>\n\t\t\t\t\t\t\t<span class=\"cn-notes-card__time\">{{ formatDate(row.note.creationDateTime || row.note.created) }}</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div v-if=\"visibilityShown\" class=\"cn-notes-card__visibility\">\n\t\t\t\t\t\t\t<CnVisibilityChip :visibility=\"row.note.visibility\" />\n\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\tv-if=\"visibilityToggleShown\"\n\t\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\t\tdata-testid=\"cn-notes-card-visibility-toggle\"\n\t\t\t\t\t\t\t\t@click=\"toggleVisibility(row.note)\">\n\t\t\t\t\t\t\t\t{{ noteVisibility(row.note) === 'public' ? makeInternalLabel : makePublicLabel }}\n\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<p v-if=\"row.quote\" class=\"cn-notes-card__quote\" data-testid=\"cn-notes-card-quote\">\n\t\t\t\t\t\t\t{{ row.quote }}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p class=\"cn-notes-card__body\">\n\t\t\t\t\t\t\t<CnNoteBody :message=\"row.note.message || row.note.content || ''\" :record=\"isFileSource ? null : record\" />\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"canReply\"\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\t:aria-label=\"replyAria(row.note)\"\n\t\t\t\t\t\t\tdata-testid=\"cn-notes-card-reply\"\n\t\t\t\t\t\t\t@click=\"replyTo = row.note\">\n\t\t\t\t\t\t\t{{ replyLabel }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"canDeleteNote(row.note)\"\n\t\t\t\t\t\t\tvariant=\"tertiary-no-background\"\n\t\t\t\t\t\t\tclass=\"cn-notes-card__delete-btn\"\n\t\t\t\t\t\t\t:aria-label=\"deleteLabel\"\n\t\t\t\t\t\t\t@click=\"confirmDelete(row.note)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Delete :size=\"16\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- Footer: \"Show all\" link -->\n\t\t<template v-if=\"allNotes.length > maxDisplay\" #footer>\n\t\t\t<button\n\t\t\t\tclass=\"cn-notes-card__show-all\"\n\t\t\t\t@click=\"$emit('show-all')\">\n\t\t\t\t{{ showAllLabel }} ({{ allNotes.length }})\n\t\t\t</button>\n\t\t</template>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcLoadingIcon } from '@nextcloud/vue'\nimport { markRaw } from 'vue'\nimport CommentTextOutline from 'vue-material-design-icons/CommentTextOutline.vue'\nimport Delete from 'vue-material-design-icons/Delete.vue'\nimport Send from 'vue-material-design-icons/Send.vue'\nimport CnDetailCard from '../CnDetailCard/CnDetailCard.vue'\nimport CnNoteBody from '../CnNoteBody/CnNoteBody.vue'\nimport CnNoteComposer from '../CnNoteComposer/CnNoteComposer.vue'\nimport CnUserActionMenu from '../CnUserActionMenu/CnUserActionMenu.vue'\nimport CnVisibilityChip from '../CnVisibilityChip/CnVisibilityChip.vue'\nimport { useFileComments } from '../../composables/useFileComments.js'\nimport { buildHeaders, prefixUrl } from '../../utils/index.js'\nimport { extractMentionedGroupIds, extractMentionedIds } from '../../utils/mentions.js'\nimport { quoteFor, supportsReplies, threadNotes, threadRootId } from '../../utils/noteThreads.js'\n\n/**\n * CnNotesCard — Inline notes widget for detail pages.\n *\n * Shows up to 5 recent notes with add/delete functionality.\n * Integrates CnUserActionMenu on author names for quick communication.\n *\n * Basic usage\n * ```vue\n * <CnNotesCard\n * register-id=\"uuid-register\"\n * schema-id=\"uuid-schema\"\n * object-id=\"uuid-object\" />\n * ```\n *\n * With sidebar sync\n * ```vue\n * <CnNotesCard\n * register-id=\"reg\"\n * schema-id=\"schema\"\n * object-id=\"obj\"\n * @note-added=\"refreshNotes\"\n * @note-deleted=\"refreshNotes\"\n * @show-all=\"openSidebarNotesTab\" />\n * ```\n *\n * @event note-added Emitted after a new note is successfully persisted. Payload: the created note object.\n * @event note-deleted Emitted after a note is successfully deleted. Payload: the deleted note ID.\n * @event visibility-changed Emitted after a note's visibility was changed. Payload: `{ id, visibility }`.\n * @event mention Emitted after a note that mentions someone was added. Payload: `{ objectId, register, schema, noteId, mentionedUserIds }`, plus `mentionedGroupIds` when a group (`@\"group/<gid>\"`) is mentioned. nc-vue notifies nobody; the listener does.\n * @event show-all Emitted when the user clicks the \"Show all\" button — parents typically open a full notes sidebar tab.\n */\nexport default {\n\tname: 'CnNotesCard',\n\n\tcomponents: {\n\t\tCnDetailCard,\n\t\tCnNoteBody,\n\t\tCnNoteComposer,\n\t\tCnUserActionMenu,\n\t\tCnVisibilityChip,\n\t\tNcButton,\n\t\tNcCheckboxRadioSwitch,\n\t\tNcLoadingIcon,\n\t\tSend,\n\t\tDelete,\n\t},\n\n\tprops: {\n\t\t/** OpenRegister register ID */\n\t\tregisterId: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema ID */\n\t\tschemaId: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Object UUID */\n\t\tobjectId: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Show the notes of a plain Nextcloud file instead of an OpenRegister\n\t\t * object: the file's id. Used when no `objectId` is given; the notes\n\t\t * are the file's comments (`/remote.php/dav/comments/files/{fileId}`),\n\t\t * the same ones the Files sidebar shows.\n\t\t */\n\t\tfileId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Base API URL for OpenRegister */\n\t\tapiBase: {\n\t\t\ttype: String,\n\t\t\tdefault: '/apps/openregister/api',\n\t\t},\n\n\t\t/** Maximum number of notes to display */\n\t\tmaxDisplay: {\n\t\t\ttype: Number,\n\t\t\tdefault: 5,\n\t\t},\n\n\t\t/** Whether the card is collapsible */\n\t\tcollapsible: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Render the notes body without the surrounding CnDetailCard.\n\t\t *\n\t\t * Set when a surface already supplies the card and the title, such as a\n\t\t * tab panel whose open tab names the panel. Leaving the card on there\n\t\t * nests a card inside a card and shows the label twice.\n\t\t */\n\t\tchromeless: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Show a chip on every note reading internal or public. A note without a\n\t\t * value reads as internal. Off by default, so a host that passes nothing\n\t\t * renders the card as before. Not used for a file source (file comments\n\t\t * carry no flag).\n\t\t */\n\t\tshowVisibility: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Whether the caller may set visibility on this object: the answer the\n\t\t * server gives for `update` on it. The host passes it; the card never\n\t\t * infers it from the current user. When true the card offers the\n\t\t * public switch in the add-note form and a toggle on each note.\n\t\t */\n\t\tcanSetVisibility: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t// --- Pre-translated labels ---\n\t\t/** Card header title. */\n\t\ttitleLabel: { type: String, default: () => t('nextcloud-vue', 'Notes') },\n\t\t/** Label for the submit button that creates a new note. */\n\t\taddNoteLabel: { type: String, default: () => t('nextcloud-vue', 'Add note') },\n\t\t/** Placeholder shown inside the new-note textarea before any input. */\n\t\taddNotePlaceholder: { type: String, default: () => t('nextcloud-vue', 'Write a note…') },\n\t\t/** Empty-state text shown when the object has zero notes. */\n\t\tnoNotesLabel: { type: String, default: () => t('nextcloud-vue', 'No notes yet') },\n\t\t/** Label for the \"Show all\" button rendered when the note list is truncated. */\n\t\tshowAllLabel: { type: String, default: () => t('nextcloud-vue', 'Show all') },\n\t\t/** Text shown instead of the notes when Nextcloud refuses a file's comments (no access). */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'Notes are not available for this file') },\n\t\t/** Label of the add-note switch that makes the note public. */\n\t\tpublicSwitchLabel: { type: String, default: () => t('nextcloud-vue', 'Public (visible to the customer)') },\n\t\t/** Label of the per-note action that makes an internal note public. */\n\t\tmakePublicLabel: { type: String, default: () => t('nextcloud-vue', 'Make public') },\n\t\t/** Label of the per-note action that makes a public note internal. */\n\t\tmakeInternalLabel: { type: String, default: () => t('nextcloud-vue', 'Make internal') },\n\t\t/** Label of the Reply button (shown only when the backend supports replies). */\n\t\treplyLabel: { type: String, default: () => t('nextcloud-vue', 'Reply') },\n\t\t/** Aria label for the per-note delete icon button. */\n\t\tdeleteLabel: { type: String, default: () => t('nextcloud-vue', 'Delete note') },\n\t},\n\n\temits: ['mention', 'note-added', 'note-deleted', 'show-all', 'visibility-changed'],\n\n\tdata() {\n\t\treturn {\n\t\t\tCommentTextOutline: markRaw(CommentTextOutline),\n\t\t\tallNotes: [],\n\t\t\tloading: false,\n\t\t\tnewNoteText: '',\n\t\t\t/** Visibility the next note is written with (only sent when the caller may set it). */\n\t\t\tnewNoteVisibility: 'internal',\n\t\t\tnoteSaving: false,\n\t\t\tdeleteConfirmId: null,\n\t\t\t/** The file source answered 403 or 404: no notes and no add field. */\n\t\t\tunavailable: false,\n\t\t\t/** The note a reply is being written to, or null. */\n\t\t\treplyTo: null,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** Chips are shown: the host asked for them (or lets the caller set visibility) and the notes are object notes. */\n\t\tvisibilityShown() {\n\t\t\treturn (this.showVisibility || this.canSetVisibility) && !this.isFileSource\n\t\t},\n\n\t\t/** The switch and the per-note toggle are offered: only when the host says the caller may set it. */\n\t\tvisibilityToggleShown() {\n\t\t\treturn this.canSetVisibility && !this.isFileSource\n\t\t},\n\n\t\t/** The file source applies: a file id and no object. */\n\t\tisFileSource() {\n\t\t\treturn this.fileId !== null && this.fileId !== undefined && this.fileId !== '' && !this.objectId\n\t\t},\n\n\t\t/** @return {{apiBase: string, register: string, schema: string, objectId: string}} Where this record's files live, for pasted images. */\n\t\trecord() {\n\t\t\treturn { apiBase: this.apiBase, register: this.registerId, schema: this.schemaId, objectId: this.objectId }\n\t\t},\n\n\t\t/** @return {boolean} Whether the backend supports replies: its notes carry a `parentId` key. Not for a file's comments. */\n\t\tcanReply() {\n\t\t\treturn !this.isFileSource && supportsReplies(this.allNotes)\n\t\t},\n\n\t\t/** @return {Array<{note: object, replies: object[]}>} The shown notes as threads. */\n\t\tthreads() {\n\t\t\treturn threadNotes(this.displayedNotes)\n\t\t},\n\n\t\t/** @return {string} The line above the form while replying. */\n\t\treplyingLabel() {\n\t\t\treturn this.replyTo ? t('nextcloud-vue', 'Replying to {author}', { author: this.getNoteAuthorName(this.replyTo) }) : ''\n\t\t},\n\n\t\tdisplayedNotes() {\n\t\t\t// Reverse chronological, limited to maxDisplay\n\t\t\tconst sorted = [...this.allNotes].sort((a, b) => {\n\t\t\t\tconst dateA = new Date(a.creationDateTime || a.created || 0)\n\t\t\t\tconst dateB = new Date(b.creationDateTime || b.created || 0)\n\t\t\t\treturn dateB - dateA\n\t\t\t})\n\t\t\treturn sorted.slice(0, this.maxDisplay)\n\t\t},\n\t},\n\n\twatch: {\n\t\tfileId: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tif (this.isFileSource) {\n\t\t\t\t\tthis.fetchNotes()\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\n\t\tobjectId: {\n\t\t\timmediate: true,\n\t\t\thandler(newId) {\n\t\t\t\tif (newId && this.registerId && this.schemaId) {\n\t\t\t\t\tthis.fetchNotes()\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * A note's visibility; an entry with no value reads as internal.\n\t\t *\n\t\t * @param {object} note The note.\n\t\t * @return {'public'|'internal'} The visibility.\n\t\t */\n\t\tnoteVisibility(note) {\n\t\t\treturn note && note.visibility === 'public' ? 'public' : 'internal'\n\t\t},\n\n\t\t/**\n\t\t * The one place a note write goes out: creating a note and changing its\n\t\t * visibility both send through here, so the value is sent from one spot.\n\t\t *\n\t\t * @param {'POST'|'PATCH'} method The HTTP method.\n\t\t * @param {string} url The notes URL (with the note id for a change).\n\t\t * @param {object} body The JSON body.\n\t\t * @return {Promise<Response>} The response.\n\t\t */\n\t\twriteNote(method, url, body) {\n\t\t\treturn fetch(prefixUrl(url), { method, headers: buildHeaders(), body: JSON.stringify(body) })\n\t\t},\n\n\t\t/**\n\t\t * Flip a note between internal and public.\n\t\t *\n\t\t * @param {object} note The note.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync toggleVisibility(note) {\n\t\t\tif (!this.visibilityToggleShown) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst next = this.noteVisibility(note) === 'public' ? 'internal' : 'public'\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes/${note.id}`\n\t\t\t\tconst response = await this.writeNote('PATCH', url, { visibility: next })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tthis.allNotes = this.allNotes.map((n) => (n.id === note.id ? { ...n, visibility: next } : n))\n\t\t\t\t\t/** @event visibility-changed Emitted after a note's visibility was changed. Payload: `{ id, visibility }`. */\n\t\t\t\t\tthis.$emit('visibility-changed', { id: note.id, visibility: next })\n\t\t\t\t} else {\n\t\t\t\t\tthis.showError('Failed to change visibility')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to change visibility', err)\n\t\t\t\tthis.showError('Failed to change visibility')\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The rows of one thread: the note, then its replies. A reply whose parent\n\t\t * is far up the list carries a one-line quote of it.\n\t\t *\n\t\t * @param {{note: object, replies: object[]}} thread The thread.\n\t\t * @return {Array<{note: object, isReply: boolean, quote: string}>} The rows.\n\t\t */\n\t\tthreadRows(thread) {\n\t\t\tconst flat = this.threads.flatMap((t2) => [t2.note, ...t2.replies])\n\t\t\treturn [\n\t\t\t\t{ note: thread.note, isReply: false, quote: '' },\n\t\t\t\t...thread.replies.map((reply) => ({ note: reply, isReply: true, quote: quoteFor(reply, flat) })),\n\t\t\t]\n\t\t},\n\n\t\t/**\n\t\t * @param {object} note A top-level note.\n\t\t * @return {string} The name of its thread for assistive technology.\n\t\t */\n\t\tthreadLabel(note) {\n\t\t\treturn t('nextcloud-vue', 'Note by {author} and its replies', { author: this.getNoteAuthorName(note) })\n\t\t},\n\n\t\t/**\n\t\t * @param {object} note The note a Reply button answers.\n\t\t * @return {string} The button's accessible name, naming the author.\n\t\t */\n\t\treplyAria(note) {\n\t\t\treturn t('nextcloud-vue', 'Reply to {author}', { author: this.getNoteAuthorName(note) })\n\t\t},\n\n\t\t/**\n\t\t * Tell the host a saved note mentions someone. The payload keeps the\n\t\t * user ids and adds the group ids only when a group is mentioned.\n\t\t *\n\t\t * @param {string} text The saved text.\n\t\t * @param {string|null} noteId The note's id.\n\t\t * @return {void}\n\t\t */\n\t\temitMentionEvent(text, noteId) {\n\t\t\tconst mentionedUserIds = extractMentionedIds(text)\n\t\t\tconst mentionedGroupIds = extractMentionedGroupIds(text)\n\t\t\tif (mentionedUserIds.length === 0 && mentionedGroupIds.length === 0) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.$emit('mention', {\n\t\t\t\tobjectId: this.objectId,\n\t\t\t\tregister: this.registerId,\n\t\t\t\tschema: this.schemaId,\n\t\t\t\tnoteId,\n\t\t\t\tmentionedUserIds,\n\t\t\t\t...(mentionedGroupIds.length > 0 ? { mentionedGroupIds } : {}),\n\t\t\t})\n\t\t},\n\n\t\tgetNoteAuthorId(note) {\n\t\t\treturn note.actorId || note.author || ''\n\t\t},\n\n\t\tgetNoteAuthorName(note) {\n\t\t\treturn note.actorDisplayName || note.author || 'Unknown'\n\t\t},\n\n\t\tisCurrentUser(note) {\n\t\t\tconst authorId = this.getNoteAuthorId(note)\n\t\t\tconst currentUser = typeof OC !== 'undefined' ? OC?.currentUser : null\n\t\t\treturn authorId === currentUser\n\t\t},\n\n\t\tcanDeleteNote(note) {\n\t\t\treturn this.isCurrentUser(note)\n\t\t},\n\n\t\tfileComments() {\n\t\t\treturn useFileComments(this.fileId)\n\t\t},\n\n\t\tasync fetchNotes() {\n\t\t\tif (this.isFileSource) {\n\t\t\t\tthis.loading = true\n\t\t\t\tthis.unavailable = false\n\t\t\t\ttry {\n\t\t\t\t\tthis.allNotes = await this.fileComments().list()\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthis.allNotes = []\n\t\t\t\t\tthis.unavailable = err && (err.status === 403 || err.status === 404)\n\t\t\t\t\tif (!this.unavailable) {\n\t\t\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\t\t\tconsole.error('CnNotesCard: Failed to fetch file comments', err)\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tthis.loading = false\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!this.registerId || !this.schemaId || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes`\n\t\t\t\tconst response = await fetch(prefixUrl(url), { 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.allNotes = data.results || data || []\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to fetch notes', err)\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync submitNote() {\n\t\t\tif (!this.newNoteText.trim() || this.noteSaving) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.noteSaving = true\n\t\t\tif (this.isFileSource) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.fileComments().add(this.newNoteText.trim())\n\t\t\t\t\tthis.newNoteText = ''\n\t\t\t\t\tawait this.fetchNotes()\n\t\t\t\t\tthis.$emit('note-added')\n\t\t\t\t} catch (err) {\n\t\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\t\tconsole.error('CnNotesCard: Failed to add file comment', err)\n\t\t\t\t\tthis.showError('Failed to add note')\n\t\t\t\t} finally {\n\t\t\t\t\tthis.noteSaving = false\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes`\n\t\t\t\tconst body = { message: this.newNoteText.trim() }\n\t\t\t\tif (this.visibilityToggleShown) {\n\t\t\t\t\tbody.visibility = this.newNoteVisibility\n\t\t\t\t}\n\t\t\t\tif (this.replyTo) {\n\t\t\t\t\tbody.parentId = threadRootId(this.replyTo, this.allNotes)\n\t\t\t\t}\n\t\t\t\tconst response = await this.writeNote('POST', url, body)\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tlet noteId = null\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst created = await response.json()\n\t\t\t\t\t\tnoteId = (created && (created.id || (created.results && created.results.id))) || null\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Body not JSON: the event still fires with noteId null.\n\t\t\t\t\t}\n\t\t\t\t\tthis.emitMentionEvent(body.message, noteId)\n\t\t\t\t\tthis.replyTo = null\n\t\t\t\t\tthis.newNoteText = ''\n\t\t\t\t\tthis.newNoteVisibility = 'internal'\n\t\t\t\t\tawait this.fetchNotes()\n\t\t\t\t\tthis.$emit('note-added')\n\t\t\t\t} else {\n\t\t\t\t\tthis.showError('Failed to add note')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to add note', err)\n\t\t\t\tthis.showError('Failed to add note')\n\t\t\t} finally {\n\t\t\t\tthis.noteSaving = false\n\t\t\t}\n\t\t},\n\n\t\tasync confirmDelete(note) {\n\t\t\t// Simple inline confirmation — delete directly\n\t\t\tif (this.isFileSource) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.fileComments().remove(note.id)\n\t\t\t\t\tthis.allNotes = this.allNotes.filter((n) => n.id !== note.id)\n\t\t\t\t\tthis.$emit('note-deleted')\n\t\t\t\t} catch (err) {\n\t\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\t\tconsole.error('CnNotesCard: Failed to delete file comment', err)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes/${note.id}`\n\t\t\t\tconst response = await fetch(prefixUrl(url), {\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\tthis.allNotes = this.allNotes.filter((n) => n.id !== note.id)\n\t\t\t\t\tthis.$emit('note-deleted')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to delete note', err)\n\t\t\t}\n\t\t},\n\n\t\tformatDate(dateStr) {\n\t\t\tif (!dateStr) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\ttry {\n\t\t\t\treturn new Date(dateStr).toLocaleString(undefined, {\n\t\t\t\t\tyear: 'numeric',\n\t\t\t\t\tmonth: 'short',\n\t\t\t\t\tday: 'numeric',\n\t\t\t\t\thour: '2-digit',\n\t\t\t\t\tminute: '2-digit',\n\t\t\t\t})\n\t\t\t} catch {\n\t\t\t\treturn dateStr\n\t\t\t}\n\t\t},\n\n\t\tshowError(message) {\n\t\t\ttry {\n\t\t\t\timport('@nextcloud/dialogs').then(({ showError }) => {\n\t\t\t\t\tshowError(message)\n\t\t\t\t})\n\t\t\t} catch {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error(message)\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-notes-card__add-form {\n\tmargin-bottom: 12px;\n}\n\n.cn-notes-card__textarea {\n\twidth: 100%;\n\tmargin-bottom: 8px;\n\tbox-sizing: border-box;\n}\n\n.cn-notes-card__replying {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: space-between;\n\tmargin: 0 0 4px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-notes-card__note--reply {\n\tmargin-inline-start: 24px;\n}\n\n.cn-notes-card__quote {\n\tmargin: 0 0 2px;\n\tpadding-inline-start: 8px;\n\tborder-inline-start: 2px solid var(--color-border-dark);\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n}\n\n.cn-notes-card__empty {\n\ttext-align: center;\n\tpadding: 16px 12px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-notes-card__list {\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.cn-notes-card__note {\n\tpadding: 10px 0;\n\tborder-bottom: 1px solid var(--color-border);\n\tposition: relative;\n}\n\n.cn-notes-card__note:last-child {\n\tborder-bottom: none;\n}\n\n.cn-notes-card__note-header {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: baseline;\n\tmargin-bottom: 4px;\n}\n\n.cn-notes-card__author {\n\tfont-size: 13px;\n}\n\n.cn-notes-card__author--self {\n\tcolor: var(--color-main-text);\n}\n\n.cn-notes-card__visibility {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tmargin-bottom: 4px;\n}\n\n.cn-notes-card__time {\n\tfont-size: 11px;\n\tcolor: var(--color-text-maxcontrast);\n\tflex-shrink: 0;\n\tmargin-left: 8px;\n}\n\n.cn-notes-card__body {\n\tfont-size: 13px;\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\toverflow-wrap: anywhere;\n\tpadding-right: 32px;\n}\n\n.cn-notes-card__delete-btn {\n\tposition: absolute;\n\ttop: 8px;\n\tright: -4px;\n\topacity: 0;\n\ttransition: opacity 0.15s ease;\n}\n\n.cn-notes-card__note:hover .cn-notes-card__delete-btn {\n\topacity: 1;\n}\n\n.cn-notes-card__show-all {\n\tbackground: none;\n\tborder: none;\n\tcolor: var(--color-primary-element);\n\tfont-size: 13px;\n\tfont-weight: 500;\n\tcursor: pointer;\n\tpadding: 0;\n\twidth: 100%;\n\ttext-align: center;\n}\n\n.cn-notes-card__show-all:hover {\n\ttext-decoration: underline;\n}\n</style>\n"],"names":["_createBlock","_openBlock","_createElementBlock","_createTextVNode","_toDisplayString","_createVNode","_Fragment","_renderList","_normalizeClass","_createElementVNode"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnNotesCard.vue3.js","sources":["../../../../src/components/CnNotesCard/CnNotesCard.vue?vue&type=template&id=5b558cb4&lang.js"],"sourcesContent":["<!--\n CnNotesCard — Inline notes card for detail pages.\n\n Displays up to 5 recent notes with author, content, and timestamp.\n Includes an add-note form and integrates CnUserActionMenu on author names.\n Wraps CnDetailCard for consistent styling.\n-->\n<template>\n\t<CnDetailCard :title=\"titleLabel\"\n\t\t:icon=\"CommentTextOutline\"\n\t\t:collapsible=\"collapsible\"\n\t\t:chromeless=\"chromeless\">\n\t\t<div class=\"cn-notes-card\">\n\t\t\t<!-- Add note input -->\n\t\t\t<div v-if=\"!unavailable\" class=\"cn-notes-card__add-form\">\n\t\t\t\t<!-- Replying: the form says to whom; a reply to a reply goes to the top of its thread. -->\n\t\t\t\t<p\n\t\t\t\t\tv-if=\"replyTo\"\n\t\t\t\t\tclass=\"cn-notes-card__replying\"\n\t\t\t\t\trole=\"status\"\n\t\t\t\t\tdata-testid=\"cn-notes-card-replying\">\n\t\t\t\t\t{{ replyingLabel }}\n\t\t\t\t\t<NcButton variant=\"tertiary\" @click=\"replyTo = null\">\n\t\t\t\t\t\t{{ t('nextcloud-vue', 'Cancel') }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t</p>\n\t\t\t\t<CnNoteComposer\n\t\t\t\t\tclass=\"cn-notes-card__textarea\"\n\t\t\t\t\t:modelValue=\"newNoteText\"\n\t\t\t\t\t:placeholder=\"addNotePlaceholder\"\n\t\t\t\t\t:register=\"isFileSource ? '' : registerId\"\n\t\t\t\t\t:schema=\"isFileSource ? '' : schemaId\"\n\t\t\t\t\t:objectId=\"isFileSource ? '' : objectId\"\n\t\t\t\t\t:apiBase=\"apiBase\"\n\t\t\t\t\t@update:modelValue=\"newNoteText = $event\"\n\t\t\t\t\t@submit=\"submitNote\" />\n\t\t\t\t<!-- Internal or public, chosen before the note is written (only when the host says the caller may set it). -->\n\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\tv-if=\"visibilityToggleShown\"\n\t\t\t\t\t:modelValue=\"newNoteVisibility === 'public'\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\tdata-testid=\"cn-notes-card-visibility-switch\"\n\t\t\t\t\t@update:modelValue=\"(on) => newNoteVisibility = on ? 'public' : 'internal'\">\n\t\t\t\t\t{{ publicSwitchLabel }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t:disabled=\"!newNoteText.trim() || noteSaving\"\n\t\t\t\t\t@click=\"submitNote\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<Send :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ addNoteLabel }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\n\t\t\t<!-- Loading state -->\n\t\t\t<NcLoadingIcon v-if=\"loading\" />\n\n\t\t\t<!-- Empty state -->\n\t\t\t<div v-else-if=\"unavailable\" class=\"cn-notes-card__empty\" data-testid=\"cn-notes-card-unavailable\">\n\t\t\t\t{{ unavailableLabel }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"allNotes.length === 0\" class=\"cn-notes-card__empty\">\n\t\t\t\t{{ noNotesLabel }}\n\t\t\t</div>\n\n\t\t\t<!-- Notes list (last 5), threaded: a note, then its replies. -->\n\t\t\t<div v-else class=\"cn-notes-card__list\">\n\t\t\t\t<div\n\t\t\t\t\tv-for=\"thread in threads\"\n\t\t\t\t\t:key=\"thread.note.id\"\n\t\t\t\t\tclass=\"cn-notes-card__thread\"\n\t\t\t\t\trole=\"group\"\n\t\t\t\t\t:aria-label=\"threadLabel(thread.note)\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-for=\"row in threadRows(thread)\"\n\t\t\t\t\t\t:key=\"row.note.id\"\n\t\t\t\t\t\tclass=\"cn-notes-card__note\"\n\t\t\t\t\t\t:class=\"{ 'cn-notes-card__note--reply': row.isReply }\">\n\t\t\t\t\t\t<div class=\"cn-notes-card__note-header\">\n\t\t\t\t\t\t\t<CnUserActionMenu\n\t\t\t\t\t\t\t\tv-if=\"!isCurrentUser(row.note)\"\n\t\t\t\t\t\t\t\t:userId=\"getNoteAuthorId(row.note)\"\n\t\t\t\t\t\t\t\t:displayName=\"getNoteAuthorName(row.note)\">\n\t\t\t\t\t\t\t\t<strong class=\"cn-notes-card__author\">{{ getNoteAuthorName(row.note) }}</strong>\n\t\t\t\t\t\t\t</CnUserActionMenu>\n\t\t\t\t\t\t\t<strong v-else class=\"cn-notes-card__author cn-notes-card__author--self\">\n\t\t\t\t\t\t\t\t{{ getNoteAuthorName(row.note) }}\n\t\t\t\t\t\t\t</strong>\n\t\t\t\t\t\t\t<span class=\"cn-notes-card__time\">{{ formatDate(row.note.creationDateTime || row.note.created) }}</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div v-if=\"visibilityShown\" class=\"cn-notes-card__visibility\">\n\t\t\t\t\t\t\t<CnVisibilityChip :visibility=\"row.note.visibility\" />\n\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\tv-if=\"visibilityToggleShown\"\n\t\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\t\tdata-testid=\"cn-notes-card-visibility-toggle\"\n\t\t\t\t\t\t\t\t@click=\"toggleVisibility(row.note)\">\n\t\t\t\t\t\t\t\t{{ noteVisibility(row.note) === 'public' ? makeInternalLabel : makePublicLabel }}\n\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<p v-if=\"row.quote\" class=\"cn-notes-card__quote\" data-testid=\"cn-notes-card-quote\">\n\t\t\t\t\t\t\t{{ row.quote }}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p class=\"cn-notes-card__body\">\n\t\t\t\t\t\t\t<CnNoteBody :message=\"row.note.message || row.note.content || ''\" :record=\"isFileSource ? null : record\" />\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"canReply\"\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\t:aria-label=\"replyAria(row.note)\"\n\t\t\t\t\t\t\tdata-testid=\"cn-notes-card-reply\"\n\t\t\t\t\t\t\t@click=\"replyTo = row.note\">\n\t\t\t\t\t\t\t{{ replyLabel }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"canDeleteNote(row.note)\"\n\t\t\t\t\t\t\tvariant=\"tertiary-no-background\"\n\t\t\t\t\t\t\tclass=\"cn-notes-card__delete-btn\"\n\t\t\t\t\t\t\t:aria-label=\"deleteLabel\"\n\t\t\t\t\t\t\t@click=\"confirmDelete(row.note)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Delete :size=\"16\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- Footer: \"Show all\" link -->\n\t\t<template v-if=\"allNotes.length > maxDisplay\" #footer>\n\t\t\t<button\n\t\t\t\tclass=\"cn-notes-card__show-all\"\n\t\t\t\t@click=\"$emit('show-all')\">\n\t\t\t\t{{ showAllLabel }} ({{ allNotes.length }})\n\t\t\t</button>\n\t\t</template>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcLoadingIcon } from '@nextcloud/vue'\nimport { markRaw } from 'vue'\nimport CommentTextOutline from 'vue-material-design-icons/CommentTextOutline.vue'\nimport Delete from 'vue-material-design-icons/Delete.vue'\nimport Send from 'vue-material-design-icons/Send.vue'\nimport CnDetailCard from '../CnDetailCard/CnDetailCard.vue'\nimport CnNoteBody from '../CnNoteBody/CnNoteBody.vue'\nimport CnNoteComposer from '../CnNoteComposer/CnNoteComposer.vue'\nimport CnUserActionMenu from '../CnUserActionMenu/CnUserActionMenu.vue'\nimport CnVisibilityChip from '../CnVisibilityChip/CnVisibilityChip.vue'\nimport { useFileComments } from '../../composables/useFileComments.js'\nimport { buildHeaders, prefixUrl } from '../../utils/index.js'\nimport { extractMentionedGroupIds, extractMentionedIds } from '../../utils/mentions.js'\nimport { quoteFor, supportsReplies, threadNotes, threadRootId } from '../../utils/noteThreads.js'\nimport { userLocale } from '../../utils/userLocale.js'\n\n/**\n * CnNotesCard — Inline notes widget for detail pages.\n *\n * Shows up to 5 recent notes with add/delete functionality.\n * Integrates CnUserActionMenu on author names for quick communication.\n *\n * Basic usage\n * ```vue\n * <CnNotesCard\n * register-id=\"uuid-register\"\n * schema-id=\"uuid-schema\"\n * object-id=\"uuid-object\" />\n * ```\n *\n * With sidebar sync\n * ```vue\n * <CnNotesCard\n * register-id=\"reg\"\n * schema-id=\"schema\"\n * object-id=\"obj\"\n * @note-added=\"refreshNotes\"\n * @note-deleted=\"refreshNotes\"\n * @show-all=\"openSidebarNotesTab\" />\n * ```\n *\n * @event note-added Emitted after a new note is successfully persisted. Payload: the created note object.\n * @event note-deleted Emitted after a note is successfully deleted. Payload: the deleted note ID.\n * @event visibility-changed Emitted after a note's visibility was changed. Payload: `{ id, visibility }`.\n * @event mention Emitted after a note that mentions someone was added. Payload: `{ objectId, register, schema, noteId, mentionedUserIds }`, plus `mentionedGroupIds` when a group (`@\"group/<gid>\"`) is mentioned. nc-vue notifies nobody; the listener does.\n * @event show-all Emitted when the user clicks the \"Show all\" button — parents typically open a full notes sidebar tab.\n */\nexport default {\n\tname: 'CnNotesCard',\n\n\tcomponents: {\n\t\tCnDetailCard,\n\t\tCnNoteBody,\n\t\tCnNoteComposer,\n\t\tCnUserActionMenu,\n\t\tCnVisibilityChip,\n\t\tNcButton,\n\t\tNcCheckboxRadioSwitch,\n\t\tNcLoadingIcon,\n\t\tSend,\n\t\tDelete,\n\t},\n\n\tprops: {\n\t\t/** OpenRegister register ID */\n\t\tregisterId: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema ID */\n\t\tschemaId: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Object UUID */\n\t\tobjectId: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Show the notes of a plain Nextcloud file instead of an OpenRegister\n\t\t * object: the file's id. Used when no `objectId` is given; the notes\n\t\t * are the file's comments (`/remote.php/dav/comments/files/{fileId}`),\n\t\t * the same ones the Files sidebar shows.\n\t\t */\n\t\tfileId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Base API URL for OpenRegister */\n\t\tapiBase: {\n\t\t\ttype: String,\n\t\t\tdefault: '/apps/openregister/api',\n\t\t},\n\n\t\t/** Maximum number of notes to display */\n\t\tmaxDisplay: {\n\t\t\ttype: Number,\n\t\t\tdefault: 5,\n\t\t},\n\n\t\t/** Whether the card is collapsible */\n\t\tcollapsible: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Render the notes body without the surrounding CnDetailCard.\n\t\t *\n\t\t * Set when a surface already supplies the card and the title, such as a\n\t\t * tab panel whose open tab names the panel. Leaving the card on there\n\t\t * nests a card inside a card and shows the label twice.\n\t\t */\n\t\tchromeless: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Show a chip on every note reading internal or public. A note without a\n\t\t * value reads as internal. Off by default, so a host that passes nothing\n\t\t * renders the card as before. Not used for a file source (file comments\n\t\t * carry no flag).\n\t\t */\n\t\tshowVisibility: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Whether the caller may set visibility on this object: the answer the\n\t\t * server gives for `update` on it. The host passes it; the card never\n\t\t * infers it from the current user. When true the card offers the\n\t\t * public switch in the add-note form and a toggle on each note.\n\t\t */\n\t\tcanSetVisibility: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t// --- Pre-translated labels ---\n\t\t/** Card header title. */\n\t\ttitleLabel: { type: String, default: () => t('nextcloud-vue', 'Notes') },\n\t\t/** Label for the submit button that creates a new note. */\n\t\taddNoteLabel: { type: String, default: () => t('nextcloud-vue', 'Add note') },\n\t\t/** Placeholder shown inside the new-note textarea before any input. */\n\t\taddNotePlaceholder: { type: String, default: () => t('nextcloud-vue', 'Write a note…') },\n\t\t/** Empty-state text shown when the object has zero notes. */\n\t\tnoNotesLabel: { type: String, default: () => t('nextcloud-vue', 'No notes yet') },\n\t\t/** Label for the \"Show all\" button rendered when the note list is truncated. */\n\t\tshowAllLabel: { type: String, default: () => t('nextcloud-vue', 'Show all') },\n\t\t/** Text shown instead of the notes when Nextcloud refuses a file's comments (no access). */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'Notes are not available for this file') },\n\t\t/** Label of the add-note switch that makes the note public. */\n\t\tpublicSwitchLabel: { type: String, default: () => t('nextcloud-vue', 'Public (visible to the customer)') },\n\t\t/** Label of the per-note action that makes an internal note public. */\n\t\tmakePublicLabel: { type: String, default: () => t('nextcloud-vue', 'Make public') },\n\t\t/** Label of the per-note action that makes a public note internal. */\n\t\tmakeInternalLabel: { type: String, default: () => t('nextcloud-vue', 'Make internal') },\n\t\t/** Label of the Reply button (shown only when the backend supports replies). */\n\t\treplyLabel: { type: String, default: () => t('nextcloud-vue', 'Reply') },\n\t\t/** Aria label for the per-note delete icon button. */\n\t\tdeleteLabel: { type: String, default: () => t('nextcloud-vue', 'Delete note') },\n\t},\n\n\temits: ['mention', 'note-added', 'note-deleted', 'show-all', 'visibility-changed'],\n\n\tdata() {\n\t\treturn {\n\t\t\tCommentTextOutline: markRaw(CommentTextOutline),\n\t\t\tallNotes: [],\n\t\t\tloading: false,\n\t\t\tnewNoteText: '',\n\t\t\t/** Visibility the next note is written with (only sent when the caller may set it). */\n\t\t\tnewNoteVisibility: 'internal',\n\t\t\tnoteSaving: false,\n\t\t\tdeleteConfirmId: null,\n\t\t\t/** The file source answered 403 or 404: no notes and no add field. */\n\t\t\tunavailable: false,\n\t\t\t/** The note a reply is being written to, or null. */\n\t\t\treplyTo: null,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** Chips are shown: the host asked for them (or lets the caller set visibility) and the notes are object notes. */\n\t\tvisibilityShown() {\n\t\t\treturn (this.showVisibility || this.canSetVisibility) && !this.isFileSource\n\t\t},\n\n\t\t/** The switch and the per-note toggle are offered: only when the host says the caller may set it. */\n\t\tvisibilityToggleShown() {\n\t\t\treturn this.canSetVisibility && !this.isFileSource\n\t\t},\n\n\t\t/** The file source applies: a file id and no object. */\n\t\tisFileSource() {\n\t\t\treturn this.fileId !== null && this.fileId !== undefined && this.fileId !== '' && !this.objectId\n\t\t},\n\n\t\t/** @return {{apiBase: string, register: string, schema: string, objectId: string}} Where this record's files live, for pasted images. */\n\t\trecord() {\n\t\t\treturn { apiBase: this.apiBase, register: this.registerId, schema: this.schemaId, objectId: this.objectId }\n\t\t},\n\n\t\t/** @return {boolean} Whether the backend supports replies: its notes carry a `parentId` key. Not for a file's comments. */\n\t\tcanReply() {\n\t\t\treturn !this.isFileSource && supportsReplies(this.allNotes)\n\t\t},\n\n\t\t/** @return {Array<{note: object, replies: object[]}>} The shown notes as threads. */\n\t\tthreads() {\n\t\t\treturn threadNotes(this.displayedNotes)\n\t\t},\n\n\t\t/** @return {string} The line above the form while replying. */\n\t\treplyingLabel() {\n\t\t\treturn this.replyTo ? t('nextcloud-vue', 'Replying to {author}', { author: this.getNoteAuthorName(this.replyTo) }) : ''\n\t\t},\n\n\t\tdisplayedNotes() {\n\t\t\t// Reverse chronological, limited to maxDisplay\n\t\t\tconst sorted = [...this.allNotes].sort((a, b) => {\n\t\t\t\tconst dateA = new Date(a.creationDateTime || a.created || 0)\n\t\t\t\tconst dateB = new Date(b.creationDateTime || b.created || 0)\n\t\t\t\treturn dateB - dateA\n\t\t\t})\n\t\t\treturn sorted.slice(0, this.maxDisplay)\n\t\t},\n\t},\n\n\twatch: {\n\t\tfileId: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tif (this.isFileSource) {\n\t\t\t\t\tthis.fetchNotes()\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\n\t\tobjectId: {\n\t\t\timmediate: true,\n\t\t\thandler(newId) {\n\t\t\t\tif (newId && this.registerId && this.schemaId) {\n\t\t\t\t\tthis.fetchNotes()\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * A note's visibility; an entry with no value reads as internal.\n\t\t *\n\t\t * @param {object} note The note.\n\t\t * @return {'public'|'internal'} The visibility.\n\t\t */\n\t\tnoteVisibility(note) {\n\t\t\treturn note && note.visibility === 'public' ? 'public' : 'internal'\n\t\t},\n\n\t\t/**\n\t\t * The one place a note write goes out: creating a note and changing its\n\t\t * visibility both send through here, so the value is sent from one spot.\n\t\t *\n\t\t * @param {'POST'|'PATCH'} method The HTTP method.\n\t\t * @param {string} url The notes URL (with the note id for a change).\n\t\t * @param {object} body The JSON body.\n\t\t * @return {Promise<Response>} The response.\n\t\t */\n\t\twriteNote(method, url, body) {\n\t\t\treturn fetch(prefixUrl(url), { method, headers: buildHeaders(), body: JSON.stringify(body) })\n\t\t},\n\n\t\t/**\n\t\t * Flip a note between internal and public.\n\t\t *\n\t\t * @param {object} note The note.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync toggleVisibility(note) {\n\t\t\tif (!this.visibilityToggleShown) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst next = this.noteVisibility(note) === 'public' ? 'internal' : 'public'\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes/${note.id}`\n\t\t\t\tconst response = await this.writeNote('PATCH', url, { visibility: next })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tthis.allNotes = this.allNotes.map((n) => (n.id === note.id ? { ...n, visibility: next } : n))\n\t\t\t\t\t/** @event visibility-changed Emitted after a note's visibility was changed. Payload: `{ id, visibility }`. */\n\t\t\t\t\tthis.$emit('visibility-changed', { id: note.id, visibility: next })\n\t\t\t\t} else {\n\t\t\t\t\tthis.showError('Failed to change visibility')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to change visibility', err)\n\t\t\t\tthis.showError('Failed to change visibility')\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The rows of one thread: the note, then its replies. A reply whose parent\n\t\t * is far up the list carries a one-line quote of it.\n\t\t *\n\t\t * @param {{note: object, replies: object[]}} thread The thread.\n\t\t * @return {Array<{note: object, isReply: boolean, quote: string}>} The rows.\n\t\t */\n\t\tthreadRows(thread) {\n\t\t\tconst flat = this.threads.flatMap((t2) => [t2.note, ...t2.replies])\n\t\t\treturn [\n\t\t\t\t{ note: thread.note, isReply: false, quote: '' },\n\t\t\t\t...thread.replies.map((reply) => ({ note: reply, isReply: true, quote: quoteFor(reply, flat) })),\n\t\t\t]\n\t\t},\n\n\t\t/**\n\t\t * @param {object} note A top-level note.\n\t\t * @return {string} The name of its thread for assistive technology.\n\t\t */\n\t\tthreadLabel(note) {\n\t\t\treturn t('nextcloud-vue', 'Note by {author} and its replies', { author: this.getNoteAuthorName(note) })\n\t\t},\n\n\t\t/**\n\t\t * @param {object} note The note a Reply button answers.\n\t\t * @return {string} The button's accessible name, naming the author.\n\t\t */\n\t\treplyAria(note) {\n\t\t\treturn t('nextcloud-vue', 'Reply to {author}', { author: this.getNoteAuthorName(note) })\n\t\t},\n\n\t\t/**\n\t\t * Tell the host a saved note mentions someone. The payload keeps the\n\t\t * user ids and adds the group ids only when a group is mentioned.\n\t\t *\n\t\t * @param {string} text The saved text.\n\t\t * @param {string|null} noteId The note's id.\n\t\t * @return {void}\n\t\t */\n\t\temitMentionEvent(text, noteId) {\n\t\t\tconst mentionedUserIds = extractMentionedIds(text)\n\t\t\tconst mentionedGroupIds = extractMentionedGroupIds(text)\n\t\t\tif (mentionedUserIds.length === 0 && mentionedGroupIds.length === 0) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.$emit('mention', {\n\t\t\t\tobjectId: this.objectId,\n\t\t\t\tregister: this.registerId,\n\t\t\t\tschema: this.schemaId,\n\t\t\t\tnoteId,\n\t\t\t\tmentionedUserIds,\n\t\t\t\t...(mentionedGroupIds.length > 0 ? { mentionedGroupIds } : {}),\n\t\t\t})\n\t\t},\n\n\t\tgetNoteAuthorId(note) {\n\t\t\treturn note.actorId || note.author || ''\n\t\t},\n\n\t\tgetNoteAuthorName(note) {\n\t\t\treturn note.actorDisplayName || note.author || 'Unknown'\n\t\t},\n\n\t\tisCurrentUser(note) {\n\t\t\tconst authorId = this.getNoteAuthorId(note)\n\t\t\tconst currentUser = typeof OC !== 'undefined' ? OC?.currentUser : null\n\t\t\treturn authorId === currentUser\n\t\t},\n\n\t\tcanDeleteNote(note) {\n\t\t\treturn this.isCurrentUser(note)\n\t\t},\n\n\t\tfileComments() {\n\t\t\treturn useFileComments(this.fileId)\n\t\t},\n\n\t\tasync fetchNotes() {\n\t\t\tif (this.isFileSource) {\n\t\t\t\tthis.loading = true\n\t\t\t\tthis.unavailable = false\n\t\t\t\ttry {\n\t\t\t\t\tthis.allNotes = await this.fileComments().list()\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthis.allNotes = []\n\t\t\t\t\tthis.unavailable = err && (err.status === 403 || err.status === 404)\n\t\t\t\t\tif (!this.unavailable) {\n\t\t\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\t\t\tconsole.error('CnNotesCard: Failed to fetch file comments', err)\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tthis.loading = false\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!this.registerId || !this.schemaId || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes`\n\t\t\t\tconst response = await fetch(prefixUrl(url), { 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.allNotes = data.results || data || []\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to fetch notes', err)\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync submitNote() {\n\t\t\tif (!this.newNoteText.trim() || this.noteSaving) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.noteSaving = true\n\t\t\tif (this.isFileSource) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.fileComments().add(this.newNoteText.trim())\n\t\t\t\t\tthis.newNoteText = ''\n\t\t\t\t\tawait this.fetchNotes()\n\t\t\t\t\tthis.$emit('note-added')\n\t\t\t\t} catch (err) {\n\t\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\t\tconsole.error('CnNotesCard: Failed to add file comment', err)\n\t\t\t\t\tthis.showError('Failed to add note')\n\t\t\t\t} finally {\n\t\t\t\t\tthis.noteSaving = false\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes`\n\t\t\t\tconst body = { message: this.newNoteText.trim() }\n\t\t\t\tif (this.visibilityToggleShown) {\n\t\t\t\t\tbody.visibility = this.newNoteVisibility\n\t\t\t\t}\n\t\t\t\tif (this.replyTo) {\n\t\t\t\t\tbody.parentId = threadRootId(this.replyTo, this.allNotes)\n\t\t\t\t}\n\t\t\t\tconst response = await this.writeNote('POST', url, body)\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tlet noteId = null\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst created = await response.json()\n\t\t\t\t\t\tnoteId = (created && (created.id || (created.results && created.results.id))) || null\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Body not JSON: the event still fires with noteId null.\n\t\t\t\t\t}\n\t\t\t\t\tthis.emitMentionEvent(body.message, noteId)\n\t\t\t\t\tthis.replyTo = null\n\t\t\t\t\tthis.newNoteText = ''\n\t\t\t\t\tthis.newNoteVisibility = 'internal'\n\t\t\t\t\tawait this.fetchNotes()\n\t\t\t\t\tthis.$emit('note-added')\n\t\t\t\t} else {\n\t\t\t\t\tthis.showError('Failed to add note')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to add note', err)\n\t\t\t\tthis.showError('Failed to add note')\n\t\t\t} finally {\n\t\t\t\tthis.noteSaving = false\n\t\t\t}\n\t\t},\n\n\t\tasync confirmDelete(note) {\n\t\t\t// Simple inline confirmation — delete directly\n\t\t\tif (this.isFileSource) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.fileComments().remove(note.id)\n\t\t\t\t\tthis.allNotes = this.allNotes.filter((n) => n.id !== note.id)\n\t\t\t\t\tthis.$emit('note-deleted')\n\t\t\t\t} catch (err) {\n\t\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\t\tconsole.error('CnNotesCard: Failed to delete file comment', err)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/notes/${note.id}`\n\t\t\t\tconst response = await fetch(prefixUrl(url), {\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\tthis.allNotes = this.allNotes.filter((n) => n.id !== note.id)\n\t\t\t\t\tthis.$emit('note-deleted')\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error('CnNotesCard: Failed to delete note', err)\n\t\t\t}\n\t\t},\n\n\t\tformatDate(dateStr) {\n\t\t\tif (!dateStr) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\ttry {\n\t\t\t\treturn new Date(dateStr).toLocaleString(userLocale(), {\n\t\t\t\t\tyear: 'numeric',\n\t\t\t\t\tmonth: 'short',\n\t\t\t\t\tday: 'numeric',\n\t\t\t\t\thour: '2-digit',\n\t\t\t\t\tminute: '2-digit',\n\t\t\t\t})\n\t\t\t} catch {\n\t\t\t\treturn dateStr\n\t\t\t}\n\t\t},\n\n\t\tshowError(message) {\n\t\t\ttry {\n\t\t\t\timport('@nextcloud/dialogs').then(({ showError }) => {\n\t\t\t\t\tshowError(message)\n\t\t\t\t})\n\t\t\t} catch {\n\t\t\t\t// eslint-disable-next-line no-console -- diagnostic for a failure this code already degrades from\n\t\t\t\tconsole.error(message)\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-notes-card__add-form {\n\tmargin-bottom: 12px;\n}\n\n.cn-notes-card__textarea {\n\twidth: 100%;\n\tmargin-bottom: 8px;\n\tbox-sizing: border-box;\n}\n\n.cn-notes-card__replying {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: space-between;\n\tmargin: 0 0 4px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-notes-card__note--reply {\n\tmargin-inline-start: 24px;\n}\n\n.cn-notes-card__quote {\n\tmargin: 0 0 2px;\n\tpadding-inline-start: 8px;\n\tborder-inline-start: 2px solid var(--color-border-dark);\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n}\n\n.cn-notes-card__empty {\n\ttext-align: center;\n\tpadding: 16px 12px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-notes-card__list {\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.cn-notes-card__note {\n\tpadding: 10px 0;\n\tborder-bottom: 1px solid var(--color-border);\n\tposition: relative;\n}\n\n.cn-notes-card__note:last-child {\n\tborder-bottom: none;\n}\n\n.cn-notes-card__note-header {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: baseline;\n\tmargin-bottom: 4px;\n}\n\n.cn-notes-card__author {\n\tfont-size: 13px;\n}\n\n.cn-notes-card__author--self {\n\tcolor: var(--color-main-text);\n}\n\n.cn-notes-card__visibility {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tmargin-bottom: 4px;\n}\n\n.cn-notes-card__time {\n\tfont-size: 11px;\n\tcolor: var(--color-text-maxcontrast);\n\tflex-shrink: 0;\n\tmargin-left: 8px;\n}\n\n.cn-notes-card__body {\n\tfont-size: 13px;\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\toverflow-wrap: anywhere;\n\tpadding-right: 32px;\n}\n\n.cn-notes-card__delete-btn {\n\tposition: absolute;\n\ttop: 8px;\n\tright: -4px;\n\topacity: 0;\n\ttransition: opacity 0.15s ease;\n}\n\n.cn-notes-card__note:hover .cn-notes-card__delete-btn {\n\topacity: 1;\n}\n\n.cn-notes-card__show-all {\n\tbackground: none;\n\tborder: none;\n\tcolor: var(--color-primary-element);\n\tfont-size: 13px;\n\tfont-weight: 500;\n\tcursor: pointer;\n\tpadding: 0;\n\twidth: 100%;\n\ttext-align: center;\n}\n\n.cn-notes-card__show-all:hover {\n\ttext-decoration: underline;\n}\n</style>\n"],"names":["_createBlock","_openBlock","_createElementBlock","_createTextVNode","_toDisplayString","_createVNode","_Fragment","_renderList","_normalizeClass","_createElementVNode"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import script from './CnObjectCalendar.vue2.js';
|
|
|
2
2
|
import { render } from './CnObjectCalendar.vue3.js';
|
|
3
3
|
|
|
4
4
|
script.render = render;
|
|
5
|
-
script.__scopeId = "data-v-
|
|
5
|
+
script.__scopeId = "data-v-e1c69ee2";
|
|
6
6
|
const __sfc_main = script;
|
|
7
7
|
|
|
8
8
|
export { __sfc_main as default };
|