@conduction/nextcloud-vue 2.104.0 → 2.106.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue.js +1 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js +18 -0
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js.map +1 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js +3 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue.js +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +18 -0
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +93 -1
- 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/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +6 -3
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +3 -3
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +112 -5
- 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/CnDetailWidgetHeaderItems.vue.js +9 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue.js.map +1 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue2.js +24 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue2.js.map +1 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue3.js +49 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue3.js.map +1 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +36 -18
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +17 -38
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
- 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/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue.js +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js.map +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js.map +1 -1
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue.js +1 -1
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js +2 -0
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js.map +1 -1
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js +32 -29
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +53 -2
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +119 -111
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue.js +1 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue2.js +62 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue.js +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js +73 -4
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js +74 -27
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +208 -46
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +121 -98
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js +24 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js +20 -4
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js +25 -6
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js +112 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js +100 -44
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue.js +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue2.js +67 -4
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue3.js +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue.js +9 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue.js.map +1 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue2.js +88 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue3.js +39 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue.js +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js +295 -12
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js +267 -144
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue.js +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +4 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +3 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +93 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +322 -246
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue.js +1 -1
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js +122 -7
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js +189 -93
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js.map +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js +3 -3
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue.js +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +16 -4
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
- package/dist/esm/components/CnTabs/CnTabs.vue.js +1 -1
- package/dist/esm/components/CnTabs/CnTabs.vue2.js.map +1 -1
- package/dist/esm/components/CnTabs/CnTabs.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +42 -0
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +38 -19
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue.js +9 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue.js.map +1 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue2.js +258 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue3.js +69 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue.js +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js +11 -0
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js.map +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js +4 -4
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +16 -14
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +12 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +24 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +24 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +1369 -748
- package/dist/esm/utils/dueText.js +18 -3
- package/dist/esm/utils/dueText.js.map +1 -1
- package/dist/esm/utils/libraryWidgetKeys.js +2 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/nextcloudApps.js +45 -0
- package/dist/esm/utils/nextcloudApps.js.map +1 -0
- package/dist/esm/utils/scopeListLayout.js +9 -2
- package/dist/esm/utils/scopeListLayout.js.map +1 -1
- package/dist/esm/utils/sortOrder.js +11 -1
- package/dist/esm/utils/sortOrder.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/visibleWhen.js +12 -4
- package/dist/esm/utils/visibleWhen.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +8965 -6497
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +1369 -748
- package/l10n/en.json +24 -1
- package/l10n/nl.json +24 -1
- package/package.json +1 -1
- package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +1 -1
- package/src/components/CnCardGrid/CnCardGrid.md +2 -0
- package/src/components/CnCardGrid/CnCardGrid.vue +20 -0
- package/src/components/CnCellRenderer/CnCellRenderer.vue +19 -1
- package/src/components/CnChartWidget/CnChartWidget.md +2 -0
- package/src/components/CnChartWidget/CnChartWidget.vue +93 -1
- package/src/components/CnDashboardPage/CnDashboardPage.vue +9 -6
- package/src/components/CnDetailPage/CnDetailPage.md +3 -2
- package/src/components/CnDetailPage/CnDetailPage.vue +112 -5
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue +60 -0
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +36 -29
- package/src/components/CnFactsWidget/CnFactsWidget.vue +4 -0
- package/src/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue +1 -1
- package/src/components/CnFeaturesBoard/CnFeaturesBoard.vue +4 -1
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +70 -4
- package/src/components/CnFlowRunsWidget/CnFlowRunsWidget.vue +62 -1
- package/src/components/CnFlowsPage/CnFlowBoard.vue +132 -8
- package/src/components/CnIndexPage/CnIndexPage.md +8 -5
- package/src/components/CnIndexPage/CnIndexPage.vue +236 -54
- package/src/components/CnIndexPage/CnIndexPageWidgets.vue +36 -1
- package/src/components/CnIndexPage/useSelfFetchList.js +25 -6
- package/src/components/CnIndexSidebar/CnIndexSidebar.md +2 -0
- package/src/components/CnIndexSidebar/CnIndexSidebar.vue +148 -1
- package/src/components/CnNcWidgetWidget/CnNcWidgetWidget.vue +68 -5
- package/src/components/CnNoticeWidget/CnNoticeWidget.vue +153 -0
- package/src/components/CnNoticeWidget/index.js +12 -0
- package/src/components/CnObjectCard/CnObjectCard.md +1 -0
- package/src/components/CnObjectCard/CnObjectCard.vue +354 -13
- package/src/components/CnObjectSidebar/CnFilesTab.vue +6 -0
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +190 -4
- package/src/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue +209 -9
- package/src/components/CnSettingsField/CnSettingsField.vue +4 -1
- package/src/components/CnSetupWizard/CnSetupWizard.vue +9 -1
- package/src/components/CnTabs/CnTabs.vue +11 -0
- package/src/components/CnTabsWidget/CnTabsWidget.vue +91 -18
- package/src/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.md +11 -0
- package/src/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue +382 -0
- package/src/components/CnTeamWorkloadWidget/index.js +14 -0
- package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +15 -4
- package/src/components/CnWidgetGrid/builtInWidgets.js +2 -0
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +12 -0
- package/src/components/index.js +2 -0
- package/src/css/dialog.css +20 -2
- package/src/css/index-page.css +14 -2
- package/src/css/look-board-detail.css +125 -8
- package/src/css/look-board-index.css +100 -4
- package/src/css/look-board.css +122 -14
- package/src/index.js +2 -1
- package/src/schemas/app-manifest-v2.schema.json +110 -8
- package/src/utils/dueText.js +18 -3
- package/src/utils/libraryWidgetKeys.js +2 -0
- package/src/utils/nextcloudApps.js +50 -0
- package/src/utils/scopeListLayout.js +9 -2
- package/src/utils/sortOrder.js +10 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
- package/src/utils/visibleWhen.js +12 -4
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import { translate } from '@nextcloud/l10n';
|
|
1
2
|
import { NcButton, NcCheckboxRadioSwitch } from '@nextcloud/vue';
|
|
2
3
|
import { useClickDragGuard } from '../../composables/useClickDragGuard.js';
|
|
3
4
|
import { normalizeLook } from '../../composables/useLook.js';
|
|
5
|
+
import { isBadgeVariant } from '../../utils/badgeVariants.js';
|
|
6
|
+
import { formatBoardDate } from '../../utils/boardDate.js';
|
|
7
|
+
import { resolveDateVariant } from '../../utils/dateVariant.js';
|
|
8
|
+
import { resolveDue } from '../../utils/dueText.js';
|
|
9
|
+
import { readPath } from '../../utils/readPath.js';
|
|
4
10
|
import { resolveImageUrl } from '../../utils/resolveImageUrl.js';
|
|
5
11
|
import { preventMiddleClickAutoscroll, isRowMiddleClick } from '../../utils/rowAuxClick.js';
|
|
6
12
|
import { formatValue } from '../../utils/schema.js';
|
|
@@ -49,6 +55,8 @@ var script = {
|
|
|
49
55
|
cnTranslate: { default: () => (key) => key },
|
|
50
56
|
/** The look CnAppRoot provides; `board` draws the record card of the screens. */
|
|
51
57
|
cnLook: { default: 'nextcloud' },
|
|
58
|
+
/** The cell formatters CnAppRoot provides, for a layout part whose page column names one. */
|
|
59
|
+
cnFormatters: { default: () => ({}) },
|
|
52
60
|
},
|
|
53
61
|
|
|
54
62
|
props: {
|
|
@@ -141,6 +149,25 @@ var script = {
|
|
|
141
149
|
default: null,
|
|
142
150
|
},
|
|
143
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Board look: the record layout (manifest key `config.cardLayout`).
|
|
154
|
+
* Every part names a field of the object (a dot path) and is left out
|
|
155
|
+
* while that field is empty:
|
|
156
|
+
* `{ headPill, number, title, meta, footerPill, footerDate }`.
|
|
157
|
+
* A pill is `{ field, colorMap?, labels?, variant? }`: `colorMap` maps a
|
|
158
|
+
* value to a CnStatusBadge variant (ignoring case), `labels` a value to
|
|
159
|
+
* the text shown. `meta` is a list of fields, joined with " · ".
|
|
160
|
+
* `footerDate` is `{ field, label? }`, drawn as "Termijn 5 okt".
|
|
161
|
+
* Without it the card keeps its head, facts and action.
|
|
162
|
+
*
|
|
163
|
+
* @type {{headPill?: object, number?: string, title?: string, meta?: Array<string>, footerPill?: object, footerDate?: {field: string, label?: string}}}
|
|
164
|
+
* @spec openspec/changes/board-record-card-layout/specs/board-record-card-layout/spec.md#requirement-a-board-card-can-draw-the-record-layout-from-config
|
|
165
|
+
*/
|
|
166
|
+
layout: {
|
|
167
|
+
type: Object,
|
|
168
|
+
default: null,
|
|
169
|
+
},
|
|
170
|
+
|
|
144
171
|
/**
|
|
145
172
|
* The property keys the facts list shows, in order (manifest key
|
|
146
173
|
* `config.cardFields`). Without it the card shows the first
|
|
@@ -153,6 +180,17 @@ var script = {
|
|
|
153
180
|
default: null,
|
|
154
181
|
},
|
|
155
182
|
|
|
183
|
+
/**
|
|
184
|
+
* The page's columns by key: a fact whose key names a column renders
|
|
185
|
+
* through that column's label, formatter and widget, as the table does.
|
|
186
|
+
*
|
|
187
|
+
* @type {object}
|
|
188
|
+
*/
|
|
189
|
+
cardFieldColumns: {
|
|
190
|
+
type: Object,
|
|
191
|
+
default: null,
|
|
192
|
+
},
|
|
193
|
+
|
|
156
194
|
/** Maximum number of metadata fields to show */
|
|
157
195
|
maxMetadata: {
|
|
158
196
|
type: Number,
|
|
@@ -204,6 +242,92 @@ var script = {
|
|
|
204
242
|
return null
|
|
205
243
|
},
|
|
206
244
|
|
|
245
|
+
/**
|
|
246
|
+
* The record layout when the board look draws it, else null.
|
|
247
|
+
*
|
|
248
|
+
* @return {?object}
|
|
249
|
+
* @spec openspec/changes/board-record-card-layout/specs/board-record-card-layout/spec.md#requirement-a-board-card-can-draw-the-record-layout-from-config
|
|
250
|
+
*/
|
|
251
|
+
recordLayout() {
|
|
252
|
+
return this.isBoardLook && this.layout && typeof this.layout === 'object' ? this.layout : null
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* The record layout's head pill, or null.
|
|
257
|
+
*
|
|
258
|
+
* @return {?{label: string, variant: string}}
|
|
259
|
+
*/
|
|
260
|
+
recordHeadPill() {
|
|
261
|
+
return this.recordLayout ? this.layoutPill(this.recordLayout.headPill) : null
|
|
262
|
+
},
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* The record layout's footer pill, or null.
|
|
266
|
+
*
|
|
267
|
+
* @return {?{label: string, variant: string}}
|
|
268
|
+
*/
|
|
269
|
+
recordFootPill() {
|
|
270
|
+
return this.recordLayout ? this.layoutPill(this.recordLayout.footerPill) : null
|
|
271
|
+
},
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* The record number at the end of the head, or ''.
|
|
275
|
+
*
|
|
276
|
+
* @return {string}
|
|
277
|
+
*/
|
|
278
|
+
recordNumber() {
|
|
279
|
+
return this.recordLayout ? this.layoutText(this.recordLayout.number) : ''
|
|
280
|
+
},
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* The title: the layout's `title` field, else the card's own title.
|
|
284
|
+
*
|
|
285
|
+
* @return {string}
|
|
286
|
+
*/
|
|
287
|
+
recordTitle() {
|
|
288
|
+
const text = this.recordLayout ? this.layoutText(this.recordLayout.title) : '';
|
|
289
|
+
return text !== '' ? text : this.title
|
|
290
|
+
},
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* The meta line: the layout's `meta` fields that hold a value, joined.
|
|
294
|
+
*
|
|
295
|
+
* @return {string}
|
|
296
|
+
*/
|
|
297
|
+
recordMeta() {
|
|
298
|
+
return this.recordMetaParts.map((part) => part.text).join(' · ')
|
|
299
|
+
},
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* The meta line's parts that hold a value: each with its text and, when
|
|
303
|
+
* its field names a page column, that column (whose widget draws it).
|
|
304
|
+
*
|
|
305
|
+
* @return {Array<{field: string, value: unknown, text: string, column: ?object}>}
|
|
306
|
+
*/
|
|
307
|
+
recordMetaParts() {
|
|
308
|
+
const fields = this.recordLayout && Array.isArray(this.recordLayout.meta) ? this.recordLayout.meta : [];
|
|
309
|
+
return fields
|
|
310
|
+
.map((part) => this.metaPart(part))
|
|
311
|
+
.filter((part) => part !== null && part.text !== '')
|
|
312
|
+
},
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* The footer date with its label ("Termijn 5 okt"), or ''.
|
|
316
|
+
*
|
|
317
|
+
* @return {string}
|
|
318
|
+
*/
|
|
319
|
+
recordDate() {
|
|
320
|
+
const def = this.recordLayout ? this.recordLayout.footerDate : null;
|
|
321
|
+
if (!def || typeof def.field !== 'string') {
|
|
322
|
+
return ''
|
|
323
|
+
}
|
|
324
|
+
const date = formatBoardDate(readPath(this.object, def.field));
|
|
325
|
+
if (date === '') {
|
|
326
|
+
return ''
|
|
327
|
+
}
|
|
328
|
+
return typeof def.label === 'string' && def.label !== '' ? `${this.cnTranslate(def.label)} ${date}` : date
|
|
329
|
+
},
|
|
330
|
+
|
|
207
331
|
/**
|
|
208
332
|
* The accent variant when it is a known one, else ''.
|
|
209
333
|
*
|
|
@@ -272,12 +396,7 @@ var script = {
|
|
|
272
396
|
if (Array.isArray(this.cardFields)) {
|
|
273
397
|
return this.cardFields
|
|
274
398
|
.filter((key) => typeof key === 'string' && this.schema.properties[key] && !this.configFields.includes(key))
|
|
275
|
-
.map((key) => (
|
|
276
|
-
key,
|
|
277
|
-
label: this.cnTranslate(this.schema.properties[key].title || key),
|
|
278
|
-
value: this.object[key],
|
|
279
|
-
property: this.schema.properties[key],
|
|
280
|
-
}))
|
|
399
|
+
.map((key) => this.metadataField(key, this.schema.properties[key]))
|
|
281
400
|
}
|
|
282
401
|
|
|
283
402
|
return Object.entries(this.schema.properties)
|
|
@@ -302,16 +421,180 @@ var script = {
|
|
|
302
421
|
return orderA - orderB
|
|
303
422
|
})
|
|
304
423
|
.slice(0, this.maxMetadata)
|
|
305
|
-
.map(([key, prop]) => (
|
|
306
|
-
key,
|
|
307
|
-
label: this.cnTranslate(prop.title || key),
|
|
308
|
-
value: this.object[key],
|
|
309
|
-
property: prop,
|
|
310
|
-
}))
|
|
424
|
+
.map(([key, prop]) => this.metadataField(key, prop))
|
|
311
425
|
},
|
|
312
426
|
},
|
|
313
427
|
|
|
314
428
|
methods: {
|
|
429
|
+
/**
|
|
430
|
+
* One meta part: a field name reads through the page column it names;
|
|
431
|
+
* `{ field, formatter?, formatterOptions? }` reads as plain text through
|
|
432
|
+
* its own formatter, so a column's widget (a badge) stays in the table.
|
|
433
|
+
*
|
|
434
|
+
* @param {string|{field: string, formatter?: string, formatterOptions?: object}} part The part.
|
|
435
|
+
* @return {?{field: string, value: unknown, text: string, column: ?object}} The part, or null when it names no field.
|
|
436
|
+
* @spec openspec/changes/card-layout-part-formatter/specs/card-layout-part-formatter/spec.md#requirement-a-card-meta-part-can-name-its-own-formatter
|
|
437
|
+
*/
|
|
438
|
+
metaPart(part) {
|
|
439
|
+
if (typeof part === 'string' && part !== '') {
|
|
440
|
+
return { field: part, value: readPath(this.object, part), text: this.layoutText(part), column: this.layoutColumn(part) }
|
|
441
|
+
}
|
|
442
|
+
if (!part || typeof part !== 'object' || typeof part.field !== 'string' || part.field === '') {
|
|
443
|
+
return null
|
|
444
|
+
}
|
|
445
|
+
const column = typeof part.formatter === 'string' ? { formatter: part.formatter, formatterOptions: part.formatterOptions } : null;
|
|
446
|
+
return { field: part.field, value: readPath(this.object, part.field), text: this.layoutText(part.field, column), column }
|
|
447
|
+
},
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* A field's value as text: a person or a record by its display name,
|
|
451
|
+
* title or name, anything else as a string. '' for an empty value or
|
|
452
|
+
* a field that is not named.
|
|
453
|
+
*
|
|
454
|
+
* @param {unknown} field A dot path into the object.
|
|
455
|
+
* @param {?object} [own] The column to read through instead of the one the field names.
|
|
456
|
+
* @return {string}
|
|
457
|
+
*/
|
|
458
|
+
layoutText(field, own) {
|
|
459
|
+
if (typeof field !== 'string' || field === '') {
|
|
460
|
+
return ''
|
|
461
|
+
}
|
|
462
|
+
const value = readPath(this.object, field);
|
|
463
|
+
if (value === null || value === undefined || value === '') {
|
|
464
|
+
return ''
|
|
465
|
+
}
|
|
466
|
+
// A part whose field names a page column with a formatter reads as
|
|
467
|
+
// its table cell does (a case type uuid as its name).
|
|
468
|
+
const column = own === undefined ? this.layoutColumn(field) : own;
|
|
469
|
+
const format = column && column.formatter && this.cnFormatters ? this.cnFormatters[column.formatter] : null;
|
|
470
|
+
if (typeof format === 'function') {
|
|
471
|
+
const formatted = format(value, this.object, this.schema?.properties?.[field], column.formatterOptions || undefined);
|
|
472
|
+
return formatted === null || formatted === undefined ? '' : String(formatted)
|
|
473
|
+
}
|
|
474
|
+
if (typeof value === 'object') {
|
|
475
|
+
const name = value.displayName || value.title || value.name;
|
|
476
|
+
return typeof name === 'string' ? name : ''
|
|
477
|
+
}
|
|
478
|
+
return String(value)
|
|
479
|
+
},
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* The page column a layout part's field names, or null.
|
|
483
|
+
*
|
|
484
|
+
* @param {string} field The part's field.
|
|
485
|
+
* @return {?object} The column.
|
|
486
|
+
*/
|
|
487
|
+
layoutColumn(field) {
|
|
488
|
+
return (this.cardFieldColumns && typeof field === 'string' && this.cardFieldColumns[field]) || null
|
|
489
|
+
},
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* A pill that reads its date field through the due rules: `variantWhen`
|
|
493
|
+
* (the first rule the days left match gives the tone), else `due`
|
|
494
|
+
* (overdue reads as error, within `due.soonWithin` days as warning).
|
|
495
|
+
* The label is `labels[variant]`, else `labels.overdue` / `labels.soon`,
|
|
496
|
+
* else Overdue / Soon, through the host's translate. Any other date
|
|
497
|
+
* draws no pill.
|
|
498
|
+
*
|
|
499
|
+
* @param {{field: string, due?: object, variantWhen?: Array, labels?: object}} def The pill.
|
|
500
|
+
* @return {?{label: string, variant: string}}
|
|
501
|
+
*/
|
|
502
|
+
datePill(def) {
|
|
503
|
+
const value = readPath(this.object, def.field);
|
|
504
|
+
const variant = Array.isArray(def.variantWhen)
|
|
505
|
+
? this.dateRuleVariant(value, def.variantWhen)
|
|
506
|
+
: this.dueVariant(value, def.due);
|
|
507
|
+
if (variant === '') {
|
|
508
|
+
return null
|
|
509
|
+
}
|
|
510
|
+
const labels = def.labels && typeof def.labels === 'object' ? def.labels : {};
|
|
511
|
+
const state = variant === 'error' ? 'overdue' : (variant === 'warning' ? 'soon' : '');
|
|
512
|
+
const authored = labels[variant] || (state && labels[state]);
|
|
513
|
+
if (typeof authored === 'string' && authored !== '') {
|
|
514
|
+
return { label: this.cnTranslate(authored), variant }
|
|
515
|
+
}
|
|
516
|
+
if (state === 'overdue') {
|
|
517
|
+
return { label: translate('nextcloud-vue', 'Overdue'), variant }
|
|
518
|
+
}
|
|
519
|
+
if (state === 'soon') {
|
|
520
|
+
return { label: translate('nextcloud-vue', 'Soon'), variant }
|
|
521
|
+
}
|
|
522
|
+
return null
|
|
523
|
+
},
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* The variant of the first `variantWhen` rule a date matches, or ''.
|
|
527
|
+
*
|
|
528
|
+
* @param {unknown} value The date.
|
|
529
|
+
* @param {Array} rules The rules.
|
|
530
|
+
* @return {string} The variant, or ''.
|
|
531
|
+
*/
|
|
532
|
+
dateRuleVariant(value, rules) {
|
|
533
|
+
const matched = resolveDateVariant(value, rules);
|
|
534
|
+
return matched === 'default' ? '' : matched
|
|
535
|
+
},
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* The variant the due rules give a date: error when overdue, warning
|
|
539
|
+
* within `soonWithin` days, else ''.
|
|
540
|
+
*
|
|
541
|
+
* @param {unknown} value The date.
|
|
542
|
+
* @param {object} config The `due` config.
|
|
543
|
+
* @return {string} The variant, or ''.
|
|
544
|
+
*/
|
|
545
|
+
dueVariant(value, config) {
|
|
546
|
+
const due = resolveDue(value, config);
|
|
547
|
+
if (due && due.tone === 'danger') {
|
|
548
|
+
return 'error'
|
|
549
|
+
}
|
|
550
|
+
return due && due.soon ? 'warning' : ''
|
|
551
|
+
},
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* A layout pill as `{ label, variant }`, or null while its field is
|
|
555
|
+
* empty.
|
|
556
|
+
*
|
|
557
|
+
* @param {?{field: string, colorMap?: object, labels?: object, variant?: string}} def The pill.
|
|
558
|
+
* @return {?{label: string, variant: string}}
|
|
559
|
+
*/
|
|
560
|
+
layoutPill(def) {
|
|
561
|
+
if (!def || typeof def !== 'object') {
|
|
562
|
+
return null
|
|
563
|
+
}
|
|
564
|
+
if (def.due || Array.isArray(def.variantWhen)) {
|
|
565
|
+
return this.datePill(def)
|
|
566
|
+
}
|
|
567
|
+
const value = this.layoutText(def.field);
|
|
568
|
+
if (value === '') {
|
|
569
|
+
return null
|
|
570
|
+
}
|
|
571
|
+
const labels = def.labels && typeof def.labels === 'object' ? def.labels : {};
|
|
572
|
+
const label = typeof labels[value] === 'string' ? this.cnTranslate(labels[value]) : value;
|
|
573
|
+
const colorMap = def.colorMap && typeof def.colorMap === 'object' ? def.colorMap : {};
|
|
574
|
+
const key = Object.keys(colorMap).find((k) => k.toLowerCase() === value.toLowerCase());
|
|
575
|
+
const variant = key !== undefined ? colorMap[key] : def.variant;
|
|
576
|
+
return { label, variant: isBadgeVariant(variant) ? variant : 'default' }
|
|
577
|
+
},
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* One fact of the card: the property's value with the matching page
|
|
581
|
+
* column (label, formatter, widget) when there is one.
|
|
582
|
+
*
|
|
583
|
+
* @param {string} key The property key.
|
|
584
|
+
* @param {object} prop The schema property.
|
|
585
|
+
* @return {object} { key, label, value, property, column }
|
|
586
|
+
*/
|
|
587
|
+
metadataField(key, prop) {
|
|
588
|
+
const column = (this.cardFieldColumns && this.cardFieldColumns[key]) || null;
|
|
589
|
+
return {
|
|
590
|
+
key,
|
|
591
|
+
label: this.cnTranslate((column && column.label) || prop.title || key),
|
|
592
|
+
value: this.object[key],
|
|
593
|
+
property: prop,
|
|
594
|
+
column,
|
|
595
|
+
}
|
|
596
|
+
},
|
|
597
|
+
|
|
315
598
|
formatValue,
|
|
316
599
|
|
|
317
600
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnObjectCard.vue2.js","sources":["../../../../src/components/CnObjectCard/CnObjectCard.vue"],"sourcesContent":["<template>\n\t<div\n\t\tclass=\"cn-object-card\"\n\t\t:class=\"[{ 'cn-object-card--selected': selected, 'cn-object-card--board': isBoardLook }, accentVariant && ['cn-object-card--accent', `cn-object-card--accent-${accentVariant}`]]\"\n\t\t@mousedown=\"onCardMouseDown\"\n\t\t@click=\"onCardClick($event)\"\n\t\t@auxclick=\"onCardAuxClick($event)\">\n\t\t<!-- Selection checkbox -->\n\t\t<div v-if=\"selectable\"\n\t\t\tclass=\"cn-object-card__checkbox\"\n\t\t\t@click.stop\n\t\t\t@auxclick.stop>\n\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t:modelValue=\"selected\"\n\t\t\t\t@update:modelValue=\"$emit('select', object)\" />\n\t\t</div>\n\n\t\t<!-- Card content -->\n\t\t<div class=\"cn-object-card__content\">\n\t\t\t<!-- Header: image + title -->\n\t\t\t<div class=\"cn-object-card__header\">\n\t\t\t\t<!-- Board look: the leading element, initials in a circle or an icon on a tint. -->\n\t\t\t\t<span\n\t\t\t\t\tv-if=\"isBoardLook && leadingKind\"\n\t\t\t\t\tclass=\"cn-object-card__leading\"\n\t\t\t\t\t:class=\"`cn-object-card__leading--${leadingKind}`\"\n\t\t\t\t\tdata-testid=\"cn-object-card-leading\"\n\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t<template v-if=\"leadingKind === 'initials'\">{{ leading.initials }}</template>\n\t\t\t\t\t<CnIcon v-else :name=\"leading.icon\" :size=\"20\" />\n\t\t\t\t</span>\n\t\t\t\t<img\n\t\t\t\t\tv-if=\"imageUrl\"\n\t\t\t\t\t:src=\"imageUrl\"\n\t\t\t\t\t:alt=\"title\"\n\t\t\t\t\tclass=\"cn-object-card__image\">\n\n\t\t\t\t<div class=\"cn-object-card__title-area\">\n\t\t\t\t\t<h3 class=\"cn-object-card__title\">\n\t\t\t\t\t\t<!-- Beside the title, not in the badges row: the badges\n\t\t\t\t\t\t slot is the consumer's, and a lock is the library's\n\t\t\t\t\t\t to report. A card whose consumer passes no badges\n\t\t\t\t\t\t would otherwise show no padlock at all. -->\n\t\t\t\t\t\t<CnLockIndicator :object=\"object\" :size=\"16\" />\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tv-if=\"accentVariant && accent.icon\"\n\t\t\t\t\t\t\tclass=\"cn-object-card__accent-icon\"\n\t\t\t\t\t\t\tdata-testid=\"cn-object-card-accent-icon\"\n\t\t\t\t\t\t\t:role=\"accent.label ? 'img' : null\"\n\t\t\t\t\t\t\t:aria-label=\"accent.label || null\"\n\t\t\t\t\t\t\t:aria-hidden=\"accent.label ? null : 'true'\"\n\t\t\t\t\t\t\t:title=\"accent.label || null\">\n\t\t\t\t\t\t\t<CnIcon :name=\"accent.icon\" :size=\"16\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t{{ title }}\n\t\t\t\t\t</h3>\n\t\t\t\t\t<p v-if=\"description\" class=\"cn-object-card__description\">\n\t\t\t\t\t\t{{ truncatedDescription }}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t<!-- Board look, end of the head: the status pill, or else the row menu. -->\n\t\t\t\t<template v-if=\"isBoardLook\">\n\t\t\t\t\t<CnStatusBadge\n\t\t\t\t\t\tv-if=\"statusPill\"\n\t\t\t\t\t\tclass=\"cn-object-card__status\"\n\t\t\t\t\t\t:label=\"statusPill.label\"\n\t\t\t\t\t\t:variant=\"statusPill.variant\"\n\t\t\t\t\t\tdata-testid=\"cn-object-card-status\" />\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-else-if=\"$slots.actions\"\n\t\t\t\t\t\tclass=\"cn-object-card__menu\"\n\t\t\t\t\t\t@click.stop\n\t\t\t\t\t\t@auxclick.stop>\n\t\t\t\t\t\t<slot name=\"actions\" :object=\"object\" />\n\t\t\t\t\t</div>\n\t\t\t\t</template>\n\t\t\t</div>\n\n\t\t\t<!-- Badges slot -->\n\t\t\t<div v-if=\"$slots.badges\" class=\"cn-object-card__badges\">\n\t\t\t\t<slot name=\"badges\" :object=\"object\" />\n\t\t\t</div>\n\n\t\t\t<!-- Metadata: visible properties as label:value pairs -->\n\t\t\t<div v-if=\"metadataFields.length > 0\" class=\"cn-object-card__metadata\" :class=\"{ 'cn-object-card__metadata--facts': isBoardLook }\">\n\t\t\t\t<slot name=\"metadata\" :object=\"object\" :fields=\"metadataFields\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-for=\"field in metadataFields\"\n\t\t\t\t\t\t:key=\"field.key\"\n\t\t\t\t\t\tclass=\"cn-object-card__meta-item\">\n\t\t\t\t\t\t<span class=\"cn-object-card__meta-label\">{{ field.label }}</span>\n\t\t\t\t\t\t<CnCellRenderer\n\t\t\t\t\t\t\t:value=\"field.value\"\n\t\t\t\t\t\t\t:property=\"field.property\"\n\t\t\t\t\t\t\t:truncate=\"60\" />\n\t\t\t\t\t</div>\n\t\t\t\t</slot>\n\t\t\t</div>\n\n\t\t\t<!-- Board look: one footer action, with a muted meta text at the start. -->\n\t\t\t<div\n\t\t\t\tv-if=\"isBoardLook && footerAction\"\n\t\t\t\tclass=\"cn-object-card__footer\"\n\t\t\t\tdata-testid=\"cn-object-card-footer\"\n\t\t\t\t@click.stop\n\t\t\t\t@auxclick.stop>\n\t\t\t\t<span v-if=\"footerAction.meta\" class=\"cn-object-card__footer-meta\">{{ footerAction.meta }}</span>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\tclass=\"cn-object-card__footer-action\"\n\t\t\t\t\tdata-testid=\"cn-object-card-footer-action\"\n\t\t\t\t\t:aria-label=\"footerAction.ariaLabel || `${footerAction.label} ${title}`\"\n\t\t\t\t\t@click=\"$emit('footer-action', object, footerAction)\">\n\t\t\t\t\t{{ footerAction.label }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- Actions slot -->\n\t\t<div v-if=\"$slots.actions && !isBoardLook\"\n\t\t\tclass=\"cn-object-card__actions\"\n\t\t\t@click.stop\n\t\t\t@auxclick.stop>\n\t\t\t<slot name=\"actions\" :object=\"object\" />\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { NcButton, NcCheckboxRadioSwitch } from '@nextcloud/vue'\nimport { useClickDragGuard } from '../../composables/useClickDragGuard.js'\nimport { normalizeLook } from '../../composables/useLook.js'\nimport { resolveImageUrl } from '../../utils/resolveImageUrl.js'\nimport { isRowMiddleClick, preventMiddleClickAutoscroll } from '../../utils/rowAuxClick.js'\nimport { formatValue } from '../../utils/schema.js'\nimport { CnCellRenderer } from '../CnCellRenderer/index.js'\nimport { CnIcon } from '../CnIcon/index.js'\nimport { CnLockIndicator } from '../CnLockIndicator/index.js'\nimport { CnStatusBadge } from '../CnStatusBadge/index.js'\n\nconst ACCENT_VARIANTS = ['success', 'warning', 'error', 'info', 'primary']\n\n/**\n * CnObjectCard — Schema-configuration-driven card for object display.\n *\n * Uses `schema.configuration` to determine which fields map to the card title,\n * description, and image. Remaining visible properties are shown as metadata.\n *\n * ```vue\n * <CnObjectCard :object=\"publication\" :schema=\"pubSchema\">\n * <template #actions=\"{ object }\">\n * <NcActions><NcActionButton @click=\"edit(object)\">Edit</NcActionButton></NcActions>\n * </template>\n * </CnObjectCard>\n * ```\n */\nexport default {\n\tname: 'CnObjectCard',\n\n\tcomponents: {\n\t\tNcButton,\n\t\tNcCheckboxRadioSwitch,\n\t\tCnCellRenderer,\n\t\tCnIcon,\n\t\tCnLockIndicator,\n\t\tCnStatusBadge,\n\t},\n\n\tinject: {\n\t\t/**\n\t\t * Consumer translation function, provided by CnAppRoot as\n\t\t * `cnTranslate: this.translate` (bound to the host app's id). Metadata\n\t\t * labels come from schema property titles, authored in English as the\n\t\t * canonical source; the visible label is resolved through this function\n\t\t * so it follows the user's language. Defaults to identity when used\n\t\t * standalone (no CnAppRoot ancestor).\n\t\t */\n\t\tcnTranslate: { default: () => (key) => key },\n\t\t/** The look CnAppRoot provides; `board` draws the record card of the screens. */\n\t\tcnLook: { default: 'nextcloud' },\n\t},\n\n\tprops: {\n\t\t/** The object data */\n\t\tobject: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Schema definition with properties and configuration */\n\t\tschema: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Whether this card is selected */\n\t\tselected: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether to show selection checkbox */\n\t\tselectable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * When true, a body click on a SELECTABLE card emits `click`\n\t\t * (navigation) instead of toggling selection — selection then happens\n\t\t * via the checkbox only. The card counterpart of CnIndexPage's\n\t\t * `rowClickToView` (a table row click already navigates in that mode).\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tclickToView: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Board look: the status pill at the end of the head row, as a label\n\t\t * (`\"Open\"`) or `{ label, variant }` with a CnStatusBadge variant\n\t\t * (`success`, `warning`, `error`, `info`, `primary`, `default`).\n\t\t * Without it the head row ends in the row menu, when there is one.\n\t\t *\n\t\t * @type {(string|{label: string, variant?: string})}\n\t\t * @spec openspec/changes/screens-card-parity/specs/card-board-look/spec.md#requirement-a-record-card-has-a-head-facts-and-one-action\n\t\t */\n\t\tstatus: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Board look: the leading element of the head row. `{ initials }`\n\t\t * draws the initials in a 36px circle; `{ icon }` a schema icon in a\n\t\t * 36px rounded square on a tint.\n\t\t *\n\t\t * @type {{initials?: string, icon?: string}}\n\t\t */\n\t\tleading: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Board look: the card's one footer action. `{ label, meta?,\n\t\t * ariaLabel? }`; `meta` is the 13px muted text at the start of the\n\t\t * footer. Clicking emits `footer-action`.\n\t\t *\n\t\t * @type {{label: string, meta?: string, ariaLabel?: string}}\n\t\t */\n\t\tfooterAction: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * A status accent: a colored border at the start of the card and,\n\t\t * with `icon`, a colored icon before the title. `variant` is one of\n\t\t * `success`, `warning`, `error`, `info` or `primary`; `icon` is a\n\t\t * name registered with CnIcon; `label` names the status for screen\n\t\t * readers and as the icon's tooltip.\n\t\t *\n\t\t * @type {{variant: string, icon?: string, label?: string}}\n\t\t */\n\t\taccent: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The property keys the facts list shows, in order (manifest key\n\t\t * `config.cardFields`). Without it the card shows the first\n\t\t * `maxMetadata` visible properties, as before.\n\t\t *\n\t\t * @type {Array<string>}\n\t\t */\n\t\tcardFields: {\n\t\t\ttype: Array,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Maximum number of metadata fields to show */\n\t\tmaxMetadata: {\n\t\t\ttype: Number,\n\t\t\tdefault: 4,\n\t\t},\n\t},\n\n\temits: ['click', 'select', 'aux-click', 'footer-action'],\n\n\tsetup() {\n\t\t// Tell a deliberate card click apart from a text-selection drag.\n\t\treturn useClickDragGuard()\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * Whether the record card of the board look is drawn.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tisBoardLook() {\n\t\t\treturn normalizeLook(this.cnLook) === 'board'\n\t\t},\n\n\t\t/**\n\t\t * `initials`, `icon` or '' for the head row's leading element.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tleadingKind() {\n\t\t\tif (this.leading && typeof this.leading.initials === 'string' && this.leading.initials !== '') {\n\t\t\t\treturn 'initials'\n\t\t\t}\n\t\t\treturn this.leading && typeof this.leading.icon === 'string' && this.leading.icon !== '' ? 'icon' : ''\n\t\t},\n\n\t\t/**\n\t\t * The status as `{ label, variant }`, or null.\n\t\t *\n\t\t * @return {?{label: string, variant: string}}\n\t\t */\n\t\tstatusPill() {\n\t\t\tif (typeof this.status === 'string' && this.status !== '') {\n\t\t\t\treturn { label: this.status, variant: 'default' }\n\t\t\t}\n\t\t\tif (this.status && typeof this.status.label === 'string' && this.status.label !== '') {\n\t\t\t\treturn { label: this.status.label, variant: this.status.variant || 'default' }\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * The accent variant when it is a known one, else ''.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\taccentVariant() {\n\t\t\tconst variant = this.accent?.variant\n\t\t\treturn ACCENT_VARIANTS.includes(variant) ? variant : ''\n\t\t},\n\n\t\tconfig() {\n\t\t\treturn this.schema?.configuration || {}\n\t\t},\n\n\t\ttitle() {\n\t\t\tconst field = this.config.objectNameField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn this.object.title || this.object.name || this.object.id || '—'\n\t\t},\n\n\t\tdescription() {\n\t\t\tconst field = this.config.objectDescriptionField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\ttruncatedDescription() {\n\t\t\tif (!this.description) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (this.description.length > 120) {\n\t\t\t\treturn this.description.substring(0, 120) + '...'\n\t\t\t}\n\t\t\treturn this.description\n\t\t},\n\n\t\timageUrl() {\n\t\t\tconst field = this.config.objectImageField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn resolveImageUrl(this.object[field])\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/** Fields excluded from metadata (already shown as title/desc/image) */\n\t\tconfigFields() {\n\t\t\treturn [\n\t\t\t\tthis.config.objectNameField,\n\t\t\t\tthis.config.objectDescriptionField,\n\t\t\t\tthis.config.objectSummaryField,\n\t\t\t\tthis.config.objectImageField,\n\t\t\t].filter(Boolean)\n\t\t},\n\n\t\t/** Remaining visible properties for the metadata section */\n\t\tmetadataFields() {\n\t\t\tif (!this.schema?.properties) {\n\t\t\t\treturn []\n\t\t\t}\n\n\t\t\t// The page names the facts: those properties, in that order.\n\t\t\tif (Array.isArray(this.cardFields)) {\n\t\t\t\treturn this.cardFields\n\t\t\t\t\t.filter((key) => typeof key === 'string' && this.schema.properties[key] && !this.configFields.includes(key))\n\t\t\t\t\t.map((key) => ({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tlabel: this.cnTranslate(this.schema.properties[key].title || key),\n\t\t\t\t\t\tvalue: this.object[key],\n\t\t\t\t\t\tproperty: this.schema.properties[key],\n\t\t\t\t\t}))\n\t\t\t}\n\n\t\t\treturn Object.entries(this.schema.properties)\n\t\t\t\t.filter(([key, prop]) => {\n\t\t\t\t\tif (this.configFields.includes(key)) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\tif (prop.visible === false) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\tif (prop.type === 'object') {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\tif (prop.format === 'markdown') {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\treturn true\n\t\t\t\t})\n\t\t\t\t.sort(([, a], [, b]) => {\n\t\t\t\t\tconst orderA = typeof a.order === 'number' ? a.order : Infinity\n\t\t\t\t\tconst orderB = typeof b.order === 'number' ? b.order : Infinity\n\t\t\t\t\treturn orderA - orderB\n\t\t\t\t})\n\t\t\t\t.slice(0, this.maxMetadata)\n\t\t\t\t.map(([key, prop]) => ({\n\t\t\t\t\tkey,\n\t\t\t\t\tlabel: this.cnTranslate(prop.title || key),\n\t\t\t\t\tvalue: this.object[key],\n\t\t\t\t\tproperty: prop,\n\t\t\t\t}))\n\t\t},\n\t},\n\n\tmethods: {\n\t\tformatValue,\n\n\t\t/**\n\t\t * Card-body click: emits `select` when `selectable` (ignoring drags),\n\t\t * otherwise emits `click` for navigation. With `clickToView`, a\n\t\t * selectable card's body click navigates too — the checkbox is the\n\t\t * only selection surface, mirroring the table's rowClickToView split.\n\t\t *\n\t\t * @param {MouseEvent} [event] The originating click event.\n\t\t */\n\t\tonCardClick(event) {\n\t\t\tif (this.selectable && !this.clickToView) {\n\t\t\t\tif (this.wasDrag(event)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * @event select Emitted when the card toggles selection (clicking the body of a selectable card, or its checkbox).\n\t\t\t\t * @type {object} The card's object.\n\t\t\t\t */\n\t\t\t\tthis.$emit('select', this.object)\n\t\t\t\t// Deprecation: selectable cards used to emit `click`. Keep emitting it\n\t\t\t\t// for listeners that still rely on it, but warn them to migrate to `select`.\n\t\t\t\t// `$.vnode.props`, not `$attrs`: `click` is a declared emit, and\n\t\t\t\t// Vue keeps declared emits out of `$attrs`.\n\t\t\t\tif (this.$.vnode.props?.onClick) {\n\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\tconsole.warn('[CnObjectCard] @click on selectable cards is deprecated; use @select instead.')\n\t\t\t\t\tthis.$emit('click', this.object)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event click Emitted when a non-selectable (or `clickToView`) card is clicked. Payload: `(object, event)` — the card's object and the native click event, for opening it in a new tab on a ctrl/cmd/shift click. A middle click emits `aux-click` instead. Selectable cards emit `select`; they also emit `click` (deprecated) when a `click` listener is present, so migrate selectable consumers to `@select`.\n\t\t\t * @type {object} The card's object.\n\t\t\t */\n\t\t\tthis.$emit('click', this.object, event)\n\t\t},\n\n\t\t/**\n\t\t * Card mousedown: record the press for the drag guard, and on a card a\n\t\t * middle click opens, keep the browser from starting autoscroll.\n\t\t *\n\t\t * @param {MouseEvent} event The mousedown event.\n\t\t */\n\t\tonCardMouseDown(event) {\n\t\t\tthis.onPointerDown(event)\n\t\t\tif (!this.selectable || this.clickToView) {\n\t\t\t\tpreventMiddleClickAutoscroll(event)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Card-body middle click: emits `aux-click`, not `click`, so an existing\n\t\t * `click` listener that navigates never moves the current tab away.\n\t\t * Ignored on a select-on-click card, on nested controls and on drags.\n\t\t *\n\t\t * @param {MouseEvent} event The auxclick event.\n\t\t */\n\t\tonCardAuxClick(event) {\n\t\t\tif (!isRowMiddleClick(event) || this.wasDrag(event)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (this.selectable && !this.clickToView) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event aux-click Emitted when a non-selectable (or `clickToView`) card is middle-clicked, for opening it in a new tab (see `openRowTarget`). Payload: `(object, event)` — the card's object and the native auxclick event.\n\t\t\t * @type {object} The card's object.\n\t\t\t */\n\t\t\tthis.$emit('aux-click', this.object, event)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-object-card {\n\tdisplay: flex;\n\tgap: 12px;\n\tpadding: 16px;\n\tbackground: var(--color-main-background);\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-large, 10px);\n\tcursor: pointer;\n\ttransition: box-shadow 0.2s ease, border-color 0.2s ease;\n}\n\n.cn-object-card:hover {\n\tborder-color: var(--color-primary-element);\n\tbox-shadow: 0 2px 8px var(--color-box-shadow);\n}\n\n.cn-object-card--selected {\n\tborder-color: var(--color-primary-element);\n\tbackground: var(--color-primary-element-light);\n}\n\n/* The 4px start border takes 3px of padding, so the content stays put. */\n.cn-object-card.cn-object-card--accent {\n\tborder-inline-start-width: 4px;\n\tpadding-inline-start: 13px;\n}\n\n.cn-object-card.cn-object-card--accent-success {\n\tborder-inline-start-color: var(--color-element-success);\n}\n\n.cn-object-card.cn-object-card--accent-warning {\n\tborder-inline-start-color: var(--color-element-warning);\n}\n\n.cn-object-card.cn-object-card--accent-error {\n\tborder-inline-start-color: var(--color-element-error);\n}\n\n.cn-object-card.cn-object-card--accent-info {\n\tborder-inline-start-color: var(--color-element-info);\n}\n\n.cn-object-card.cn-object-card--accent-primary {\n\tborder-inline-start-color: var(--color-primary-element);\n}\n\n.cn-object-card__accent-icon {\n\tdisplay: inline-flex;\n\tvertical-align: -2px;\n\tmargin-inline-end: 4px;\n}\n\n.cn-object-card--accent-success .cn-object-card__accent-icon {\n\tcolor: var(--color-text-success);\n}\n\n.cn-object-card--accent-warning .cn-object-card__accent-icon {\n\tcolor: var(--color-text-warning);\n}\n\n.cn-object-card--accent-error .cn-object-card__accent-icon {\n\tcolor: var(--color-text-error);\n}\n\n.cn-object-card--accent-info .cn-object-card__accent-icon {\n\tcolor: var(--color-element-info);\n}\n\n.cn-object-card--accent-primary .cn-object-card__accent-icon {\n\tcolor: var(--color-primary-element);\n}\n\n.cn-object-card__checkbox {\n\tflex-shrink: 0;\n\tpadding-top: 2px;\n}\n\n.cn-object-card__content {\n\tflex: 1;\n\tmin-width: 0;\n}\n\n.cn-object-card__header {\n\tdisplay: flex;\n\tgap: 12px;\n\talign-items: flex-start;\n}\n\n.cn-object-card__image {\n\twidth: 48px;\n\theight: 48px;\n\tborder-radius: var(--border-radius);\n\tobject-fit: cover;\n\tflex-shrink: 0;\n}\n\n.cn-object-card__title-area {\n\tflex: 1;\n\tmin-width: 0;\n}\n\n.cn-object-card__title {\n\tmargin: 0;\n\tfont-size: 16px;\n\tfont-weight: 600;\n\tline-height: 1.3;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-object-card__description {\n\tmargin: 4px 0 0;\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n\tline-height: 1.4;\n}\n\n.cn-object-card__badges {\n\tmargin-top: 8px;\n}\n\n.cn-object-card__metadata {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(auto-fill, minmax(160px, 1fr));\n\tgap: 8px;\n\tmargin-top: 12px;\n\tpadding-top: 12px;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-object-card__meta-item {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n}\n\n.cn-object-card__meta-label {\n\tfont-size: 11px;\n\tfont-weight: 500;\n\tcolor: var(--color-text-maxcontrast);\n\ttext-transform: uppercase;\n\tletter-spacing: 0.3px;\n}\n\n.cn-object-card__actions {\n\tflex-shrink: 0;\n}\n</style>\n"],"names":["CnCellRenderer","CnIcon","CnLockIndicator","CnStatusBadge"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnObjectCard.vue2.js","sources":["../../../../src/components/CnObjectCard/CnObjectCard.vue"],"sourcesContent":["<template>\n\t<div\n\t\tclass=\"cn-object-card\"\n\t\t:class=\"[{ 'cn-object-card--selected': selected, 'cn-object-card--board': isBoardLook }, accentVariant && ['cn-object-card--accent', `cn-object-card--accent-${accentVariant}`]]\"\n\t\t@mousedown=\"onCardMouseDown\"\n\t\t@click=\"onCardClick($event)\"\n\t\t@auxclick=\"onCardAuxClick($event)\">\n\t\t<!-- Selection checkbox -->\n\t\t<div v-if=\"selectable\"\n\t\t\tclass=\"cn-object-card__checkbox\"\n\t\t\t@click.stop\n\t\t\t@auxclick.stop>\n\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t:modelValue=\"selected\"\n\t\t\t\t@update:modelValue=\"$emit('select', object)\" />\n\t\t</div>\n\n\t\t<!-- Board look, record layout (`layout`): head pill and number, title,\n\t\t meta line, then a footer with a pill and a date. -->\n\t\t<div v-if=\"recordLayout\" class=\"cn-object-card__content cn-object-card__record\" data-testid=\"cn-object-card-record\">\n\t\t\t<div class=\"cn-object-card__record-head\">\n\t\t\t\t<CnStatusBadge\n\t\t\t\t\tv-if=\"recordHeadPill\"\n\t\t\t\t\tclass=\"cn-object-card__record-pill\"\n\t\t\t\t\t:label=\"recordHeadPill.label\"\n\t\t\t\t\t:variant=\"recordHeadPill.variant\"\n\t\t\t\t\tdata-testid=\"cn-object-card-head-pill\" />\n\t\t\t\t<span v-if=\"recordNumber\" class=\"cn-object-card__record-number\" data-testid=\"cn-object-card-number\">{{ recordNumber }}</span>\n\t\t\t\t<div\n\t\t\t\t\tv-if=\"$slots.actions\"\n\t\t\t\t\tclass=\"cn-object-card__menu\"\n\t\t\t\t\t@click.stop\n\t\t\t\t\t@auxclick.stop>\n\t\t\t\t\t<slot name=\"actions\" :object=\"object\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<h3 class=\"cn-object-card__title\">\n\t\t\t\t<CnLockIndicator :object=\"object\" :size=\"16\" />\n\t\t\t\t{{ recordTitle }}\n\t\t\t</h3>\n\t\t\t<!-- A part whose field names a page column with a widget draws through\n\t\t\t it, as its table cell does; the rest are text. -->\n\t\t\t<p v-if=\"recordMetaParts.length > 0\" class=\"cn-object-card__record-meta\" data-testid=\"cn-object-card-meta\">\n\t\t\t\t<template v-for=\"(part, index) in recordMetaParts\" :key=\"part.field\">\n\t\t\t\t\t<span v-if=\"index > 0\" aria-hidden=\"true\"> · </span>\n\t\t\t\t\t<CnCellRenderer\n\t\t\t\t\t\tv-if=\"part.column && part.column.widget\"\n\t\t\t\t\t\t:value=\"part.value\"\n\t\t\t\t\t\t:widget=\"part.column.widget\"\n\t\t\t\t\t\t:widgetProps=\"part.column.widgetProps || undefined\"\n\t\t\t\t\t\t:formatter=\"part.column.formatter || null\"\n\t\t\t\t\t\t:formatterOptions=\"part.column.formatterOptions || null\"\n\t\t\t\t\t\t:row=\"object\" />\n\t\t\t\t\t<span v-else>{{ part.text }}</span>\n\t\t\t\t</template>\n\t\t\t</p>\n\t\t\t<div v-if=\"$slots.badges\" class=\"cn-object-card__badges\">\n\t\t\t\t<slot name=\"badges\" :object=\"object\" />\n\t\t\t</div>\n\t\t\t<div v-if=\"recordFootPill || recordDate\" class=\"cn-object-card__record-foot\" data-testid=\"cn-object-card-foot\">\n\t\t\t\t<CnStatusBadge\n\t\t\t\t\tv-if=\"recordFootPill\"\n\t\t\t\t\tclass=\"cn-object-card__record-pill\"\n\t\t\t\t\t:label=\"recordFootPill.label\"\n\t\t\t\t\t:variant=\"recordFootPill.variant\"\n\t\t\t\t\tdata-testid=\"cn-object-card-foot-pill\" />\n\t\t\t\t<span v-if=\"recordDate\" class=\"cn-object-card__record-date\" data-testid=\"cn-object-card-date\">{{ recordDate }}</span>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- Card content -->\n\t\t<div v-else class=\"cn-object-card__content\">\n\t\t\t<!-- Header: image + title -->\n\t\t\t<div class=\"cn-object-card__header\">\n\t\t\t\t<!-- Board look: the leading element, initials in a circle or an icon on a tint. -->\n\t\t\t\t<span\n\t\t\t\t\tv-if=\"isBoardLook && leadingKind\"\n\t\t\t\t\tclass=\"cn-object-card__leading\"\n\t\t\t\t\t:class=\"`cn-object-card__leading--${leadingKind}`\"\n\t\t\t\t\tdata-testid=\"cn-object-card-leading\"\n\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t<template v-if=\"leadingKind === 'initials'\">{{ leading.initials }}</template>\n\t\t\t\t\t<CnIcon v-else :name=\"leading.icon\" :size=\"20\" />\n\t\t\t\t</span>\n\t\t\t\t<img\n\t\t\t\t\tv-if=\"imageUrl\"\n\t\t\t\t\t:src=\"imageUrl\"\n\t\t\t\t\t:alt=\"title\"\n\t\t\t\t\tclass=\"cn-object-card__image\">\n\n\t\t\t\t<div class=\"cn-object-card__title-area\">\n\t\t\t\t\t<h3 class=\"cn-object-card__title\">\n\t\t\t\t\t\t<!-- Beside the title, not in the badges row: the badges\n\t\t\t\t\t\t slot is the consumer's, and a lock is the library's\n\t\t\t\t\t\t to report. A card whose consumer passes no badges\n\t\t\t\t\t\t would otherwise show no padlock at all. -->\n\t\t\t\t\t\t<CnLockIndicator :object=\"object\" :size=\"16\" />\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tv-if=\"accentVariant && accent.icon\"\n\t\t\t\t\t\t\tclass=\"cn-object-card__accent-icon\"\n\t\t\t\t\t\t\tdata-testid=\"cn-object-card-accent-icon\"\n\t\t\t\t\t\t\t:role=\"accent.label ? 'img' : null\"\n\t\t\t\t\t\t\t:aria-label=\"accent.label || null\"\n\t\t\t\t\t\t\t:aria-hidden=\"accent.label ? null : 'true'\"\n\t\t\t\t\t\t\t:title=\"accent.label || null\">\n\t\t\t\t\t\t\t<CnIcon :name=\"accent.icon\" :size=\"16\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t{{ title }}\n\t\t\t\t\t</h3>\n\t\t\t\t\t<p v-if=\"description\" class=\"cn-object-card__description\">\n\t\t\t\t\t\t{{ truncatedDescription }}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t<!-- Board look, end of the head: the status pill, or else the row menu. -->\n\t\t\t\t<template v-if=\"isBoardLook\">\n\t\t\t\t\t<CnStatusBadge\n\t\t\t\t\t\tv-if=\"statusPill\"\n\t\t\t\t\t\tclass=\"cn-object-card__status\"\n\t\t\t\t\t\t:label=\"statusPill.label\"\n\t\t\t\t\t\t:variant=\"statusPill.variant\"\n\t\t\t\t\t\tdata-testid=\"cn-object-card-status\" />\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-else-if=\"$slots.actions\"\n\t\t\t\t\t\tclass=\"cn-object-card__menu\"\n\t\t\t\t\t\t@click.stop\n\t\t\t\t\t\t@auxclick.stop>\n\t\t\t\t\t\t<slot name=\"actions\" :object=\"object\" />\n\t\t\t\t\t</div>\n\t\t\t\t</template>\n\t\t\t</div>\n\n\t\t\t<!-- Badges slot -->\n\t\t\t<div v-if=\"$slots.badges\" class=\"cn-object-card__badges\">\n\t\t\t\t<slot name=\"badges\" :object=\"object\" />\n\t\t\t</div>\n\n\t\t\t<!-- Metadata: visible properties as label:value pairs -->\n\t\t\t<div v-if=\"metadataFields.length > 0\" class=\"cn-object-card__metadata\" :class=\"{ 'cn-object-card__metadata--facts': isBoardLook }\">\n\t\t\t\t<slot name=\"metadata\" :object=\"object\" :fields=\"metadataFields\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-for=\"field in metadataFields\"\n\t\t\t\t\t\t:key=\"field.key\"\n\t\t\t\t\t\tclass=\"cn-object-card__meta-item\">\n\t\t\t\t\t\t<span class=\"cn-object-card__meta-label\">{{ field.label }}</span>\n\t\t\t\t\t\t<CnCellRenderer\n\t\t\t\t\t\t\t:value=\"field.value\"\n\t\t\t\t\t\t\t:property=\"field.property\"\n\t\t\t\t\t\t\t:formatter=\"field.column && field.column.formatter || null\"\n\t\t\t\t\t\t\t:formatterOptions=\"field.column && field.column.formatterOptions || null\"\n\t\t\t\t\t\t\t:widget=\"field.column && field.column.widget || null\"\n\t\t\t\t\t\t\t:widgetProps=\"field.column && field.column.widgetProps || undefined\"\n\t\t\t\t\t\t\t:row=\"object\"\n\t\t\t\t\t\t\t:truncate=\"60\" />\n\t\t\t\t\t</div>\n\t\t\t\t</slot>\n\t\t\t</div>\n\n\t\t\t<!-- Board look: one footer action, with a muted meta text at the start. -->\n\t\t\t<div\n\t\t\t\tv-if=\"isBoardLook && footerAction\"\n\t\t\t\tclass=\"cn-object-card__footer\"\n\t\t\t\tdata-testid=\"cn-object-card-footer\"\n\t\t\t\t@click.stop\n\t\t\t\t@auxclick.stop>\n\t\t\t\t<span v-if=\"footerAction.meta\" class=\"cn-object-card__footer-meta\">{{ footerAction.meta }}</span>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\tclass=\"cn-object-card__footer-action\"\n\t\t\t\t\tdata-testid=\"cn-object-card-footer-action\"\n\t\t\t\t\t:aria-label=\"footerAction.ariaLabel || `${footerAction.label} ${title}`\"\n\t\t\t\t\t@click=\"$emit('footer-action', object, footerAction)\">\n\t\t\t\t\t{{ footerAction.label }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- Actions slot -->\n\t\t<div v-if=\"$slots.actions && !isBoardLook\"\n\t\t\tclass=\"cn-object-card__actions\"\n\t\t\t@click.stop\n\t\t\t@auxclick.stop>\n\t\t\t<slot name=\"actions\" :object=\"object\" />\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch } from '@nextcloud/vue'\nimport { useClickDragGuard } from '../../composables/useClickDragGuard.js'\nimport { normalizeLook } from '../../composables/useLook.js'\nimport { isBadgeVariant } from '../../utils/badgeVariants.js'\nimport { formatBoardDate } from '../../utils/boardDate.js'\nimport { resolveDateVariant } from '../../utils/dateVariant.js'\nimport { resolveDue } from '../../utils/dueText.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { resolveImageUrl } from '../../utils/resolveImageUrl.js'\nimport { isRowMiddleClick, preventMiddleClickAutoscroll } from '../../utils/rowAuxClick.js'\nimport { formatValue } from '../../utils/schema.js'\nimport { CnCellRenderer } from '../CnCellRenderer/index.js'\nimport { CnIcon } from '../CnIcon/index.js'\nimport { CnLockIndicator } from '../CnLockIndicator/index.js'\nimport { CnStatusBadge } from '../CnStatusBadge/index.js'\n\nconst ACCENT_VARIANTS = ['success', 'warning', 'error', 'info', 'primary']\n\n/**\n * CnObjectCard — Schema-configuration-driven card for object display.\n *\n * Uses `schema.configuration` to determine which fields map to the card title,\n * description, and image. Remaining visible properties are shown as metadata.\n *\n * ```vue\n * <CnObjectCard :object=\"publication\" :schema=\"pubSchema\">\n * <template #actions=\"{ object }\">\n * <NcActions><NcActionButton @click=\"edit(object)\">Edit</NcActionButton></NcActions>\n * </template>\n * </CnObjectCard>\n * ```\n */\nexport default {\n\tname: 'CnObjectCard',\n\n\tcomponents: {\n\t\tNcButton,\n\t\tNcCheckboxRadioSwitch,\n\t\tCnCellRenderer,\n\t\tCnIcon,\n\t\tCnLockIndicator,\n\t\tCnStatusBadge,\n\t},\n\n\tinject: {\n\t\t/**\n\t\t * Consumer translation function, provided by CnAppRoot as\n\t\t * `cnTranslate: this.translate` (bound to the host app's id). Metadata\n\t\t * labels come from schema property titles, authored in English as the\n\t\t * canonical source; the visible label is resolved through this function\n\t\t * so it follows the user's language. Defaults to identity when used\n\t\t * standalone (no CnAppRoot ancestor).\n\t\t */\n\t\tcnTranslate: { default: () => (key) => key },\n\t\t/** The look CnAppRoot provides; `board` draws the record card of the screens. */\n\t\tcnLook: { default: 'nextcloud' },\n\t\t/** The cell formatters CnAppRoot provides, for a layout part whose page column names one. */\n\t\tcnFormatters: { default: () => ({}) },\n\t},\n\n\tprops: {\n\t\t/** The object data */\n\t\tobject: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Schema definition with properties and configuration */\n\t\tschema: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Whether this card is selected */\n\t\tselected: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether to show selection checkbox */\n\t\tselectable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * When true, a body click on a SELECTABLE card emits `click`\n\t\t * (navigation) instead of toggling selection — selection then happens\n\t\t * via the checkbox only. The card counterpart of CnIndexPage's\n\t\t * `rowClickToView` (a table row click already navigates in that mode).\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tclickToView: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Board look: the status pill at the end of the head row, as a label\n\t\t * (`\"Open\"`) or `{ label, variant }` with a CnStatusBadge variant\n\t\t * (`success`, `warning`, `error`, `info`, `primary`, `default`).\n\t\t * Without it the head row ends in the row menu, when there is one.\n\t\t *\n\t\t * @type {(string|{label: string, variant?: string})}\n\t\t * @spec openspec/changes/screens-card-parity/specs/card-board-look/spec.md#requirement-a-record-card-has-a-head-facts-and-one-action\n\t\t */\n\t\tstatus: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Board look: the leading element of the head row. `{ initials }`\n\t\t * draws the initials in a 36px circle; `{ icon }` a schema icon in a\n\t\t * 36px rounded square on a tint.\n\t\t *\n\t\t * @type {{initials?: string, icon?: string}}\n\t\t */\n\t\tleading: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Board look: the card's one footer action. `{ label, meta?,\n\t\t * ariaLabel? }`; `meta` is the 13px muted text at the start of the\n\t\t * footer. Clicking emits `footer-action`.\n\t\t *\n\t\t * @type {{label: string, meta?: string, ariaLabel?: string}}\n\t\t */\n\t\tfooterAction: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * A status accent: a colored border at the start of the card and,\n\t\t * with `icon`, a colored icon before the title. `variant` is one of\n\t\t * `success`, `warning`, `error`, `info` or `primary`; `icon` is a\n\t\t * name registered with CnIcon; `label` names the status for screen\n\t\t * readers and as the icon's tooltip.\n\t\t *\n\t\t * @type {{variant: string, icon?: string, label?: string}}\n\t\t */\n\t\taccent: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Board look: the record layout (manifest key `config.cardLayout`).\n\t\t * Every part names a field of the object (a dot path) and is left out\n\t\t * while that field is empty:\n\t\t * `{ headPill, number, title, meta, footerPill, footerDate }`.\n\t\t * A pill is `{ field, colorMap?, labels?, variant? }`: `colorMap` maps a\n\t\t * value to a CnStatusBadge variant (ignoring case), `labels` a value to\n\t\t * the text shown. `meta` is a list of fields, joined with \" · \".\n\t\t * `footerDate` is `{ field, label? }`, drawn as \"Termijn 5 okt\".\n\t\t * Without it the card keeps its head, facts and action.\n\t\t *\n\t\t * @type {{headPill?: object, number?: string, title?: string, meta?: Array<string>, footerPill?: object, footerDate?: {field: string, label?: string}}}\n\t\t * @spec openspec/changes/board-record-card-layout/specs/board-record-card-layout/spec.md#requirement-a-board-card-can-draw-the-record-layout-from-config\n\t\t */\n\t\tlayout: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The property keys the facts list shows, in order (manifest key\n\t\t * `config.cardFields`). Without it the card shows the first\n\t\t * `maxMetadata` visible properties, as before.\n\t\t *\n\t\t * @type {Array<string>}\n\t\t */\n\t\tcardFields: {\n\t\t\ttype: Array,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The page's columns by key: a fact whose key names a column renders\n\t\t * through that column's label, formatter and widget, as the table does.\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcardFieldColumns: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Maximum number of metadata fields to show */\n\t\tmaxMetadata: {\n\t\t\ttype: Number,\n\t\t\tdefault: 4,\n\t\t},\n\t},\n\n\temits: ['click', 'select', 'aux-click', 'footer-action'],\n\n\tsetup() {\n\t\t// Tell a deliberate card click apart from a text-selection drag.\n\t\treturn useClickDragGuard()\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * Whether the record card of the board look is drawn.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tisBoardLook() {\n\t\t\treturn normalizeLook(this.cnLook) === 'board'\n\t\t},\n\n\t\t/**\n\t\t * `initials`, `icon` or '' for the head row's leading element.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tleadingKind() {\n\t\t\tif (this.leading && typeof this.leading.initials === 'string' && this.leading.initials !== '') {\n\t\t\t\treturn 'initials'\n\t\t\t}\n\t\t\treturn this.leading && typeof this.leading.icon === 'string' && this.leading.icon !== '' ? 'icon' : ''\n\t\t},\n\n\t\t/**\n\t\t * The status as `{ label, variant }`, or null.\n\t\t *\n\t\t * @return {?{label: string, variant: string}}\n\t\t */\n\t\tstatusPill() {\n\t\t\tif (typeof this.status === 'string' && this.status !== '') {\n\t\t\t\treturn { label: this.status, variant: 'default' }\n\t\t\t}\n\t\t\tif (this.status && typeof this.status.label === 'string' && this.status.label !== '') {\n\t\t\t\treturn { label: this.status.label, variant: this.status.variant || 'default' }\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * The record layout when the board look draws it, else null.\n\t\t *\n\t\t * @return {?object}\n\t\t * @spec openspec/changes/board-record-card-layout/specs/board-record-card-layout/spec.md#requirement-a-board-card-can-draw-the-record-layout-from-config\n\t\t */\n\t\trecordLayout() {\n\t\t\treturn this.isBoardLook && this.layout && typeof this.layout === 'object' ? this.layout : null\n\t\t},\n\n\t\t/**\n\t\t * The record layout's head pill, or null.\n\t\t *\n\t\t * @return {?{label: string, variant: string}}\n\t\t */\n\t\trecordHeadPill() {\n\t\t\treturn this.recordLayout ? this.layoutPill(this.recordLayout.headPill) : null\n\t\t},\n\n\t\t/**\n\t\t * The record layout's footer pill, or null.\n\t\t *\n\t\t * @return {?{label: string, variant: string}}\n\t\t */\n\t\trecordFootPill() {\n\t\t\treturn this.recordLayout ? this.layoutPill(this.recordLayout.footerPill) : null\n\t\t},\n\n\t\t/**\n\t\t * The record number at the end of the head, or ''.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\trecordNumber() {\n\t\t\treturn this.recordLayout ? this.layoutText(this.recordLayout.number) : ''\n\t\t},\n\n\t\t/**\n\t\t * The title: the layout's `title` field, else the card's own title.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\trecordTitle() {\n\t\t\tconst text = this.recordLayout ? this.layoutText(this.recordLayout.title) : ''\n\t\t\treturn text !== '' ? text : this.title\n\t\t},\n\n\t\t/**\n\t\t * The meta line: the layout's `meta` fields that hold a value, joined.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\trecordMeta() {\n\t\t\treturn this.recordMetaParts.map((part) => part.text).join(' · ')\n\t\t},\n\n\t\t/**\n\t\t * The meta line's parts that hold a value: each with its text and, when\n\t\t * its field names a page column, that column (whose widget draws it).\n\t\t *\n\t\t * @return {Array<{field: string, value: unknown, text: string, column: ?object}>}\n\t\t */\n\t\trecordMetaParts() {\n\t\t\tconst fields = this.recordLayout && Array.isArray(this.recordLayout.meta) ? this.recordLayout.meta : []\n\t\t\treturn fields\n\t\t\t\t.map((part) => this.metaPart(part))\n\t\t\t\t.filter((part) => part !== null && part.text !== '')\n\t\t},\n\n\t\t/**\n\t\t * The footer date with its label (\"Termijn 5 okt\"), or ''.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\trecordDate() {\n\t\t\tconst def = this.recordLayout ? this.recordLayout.footerDate : null\n\t\t\tif (!def || typeof def.field !== 'string') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst date = formatBoardDate(readPath(this.object, def.field))\n\t\t\tif (date === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn typeof def.label === 'string' && def.label !== '' ? `${this.cnTranslate(def.label)} ${date}` : date\n\t\t},\n\n\t\t/**\n\t\t * The accent variant when it is a known one, else ''.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\taccentVariant() {\n\t\t\tconst variant = this.accent?.variant\n\t\t\treturn ACCENT_VARIANTS.includes(variant) ? variant : ''\n\t\t},\n\n\t\tconfig() {\n\t\t\treturn this.schema?.configuration || {}\n\t\t},\n\n\t\ttitle() {\n\t\t\tconst field = this.config.objectNameField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn this.object.title || this.object.name || this.object.id || '—'\n\t\t},\n\n\t\tdescription() {\n\t\t\tconst field = this.config.objectDescriptionField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\ttruncatedDescription() {\n\t\t\tif (!this.description) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (this.description.length > 120) {\n\t\t\t\treturn this.description.substring(0, 120) + '...'\n\t\t\t}\n\t\t\treturn this.description\n\t\t},\n\n\t\timageUrl() {\n\t\t\tconst field = this.config.objectImageField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn resolveImageUrl(this.object[field])\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/** Fields excluded from metadata (already shown as title/desc/image) */\n\t\tconfigFields() {\n\t\t\treturn [\n\t\t\t\tthis.config.objectNameField,\n\t\t\t\tthis.config.objectDescriptionField,\n\t\t\t\tthis.config.objectSummaryField,\n\t\t\t\tthis.config.objectImageField,\n\t\t\t].filter(Boolean)\n\t\t},\n\n\t\t/** Remaining visible properties for the metadata section */\n\t\tmetadataFields() {\n\t\t\tif (!this.schema?.properties) {\n\t\t\t\treturn []\n\t\t\t}\n\n\t\t\t// The page names the facts: those properties, in that order.\n\t\t\tif (Array.isArray(this.cardFields)) {\n\t\t\t\treturn this.cardFields\n\t\t\t\t\t.filter((key) => typeof key === 'string' && this.schema.properties[key] && !this.configFields.includes(key))\n\t\t\t\t\t.map((key) => this.metadataField(key, this.schema.properties[key]))\n\t\t\t}\n\n\t\t\treturn Object.entries(this.schema.properties)\n\t\t\t\t.filter(([key, prop]) => {\n\t\t\t\t\tif (this.configFields.includes(key)) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\tif (prop.visible === false) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\tif (prop.type === 'object') {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\tif (prop.format === 'markdown') {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\treturn true\n\t\t\t\t})\n\t\t\t\t.sort(([, a], [, b]) => {\n\t\t\t\t\tconst orderA = typeof a.order === 'number' ? a.order : Infinity\n\t\t\t\t\tconst orderB = typeof b.order === 'number' ? b.order : Infinity\n\t\t\t\t\treturn orderA - orderB\n\t\t\t\t})\n\t\t\t\t.slice(0, this.maxMetadata)\n\t\t\t\t.map(([key, prop]) => this.metadataField(key, prop))\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * One meta part: a field name reads through the page column it names;\n\t\t * `{ field, formatter?, formatterOptions? }` reads as plain text through\n\t\t * its own formatter, so a column's widget (a badge) stays in the table.\n\t\t *\n\t\t * @param {string|{field: string, formatter?: string, formatterOptions?: object}} part The part.\n\t\t * @return {?{field: string, value: unknown, text: string, column: ?object}} The part, or null when it names no field.\n\t\t * @spec openspec/changes/card-layout-part-formatter/specs/card-layout-part-formatter/spec.md#requirement-a-card-meta-part-can-name-its-own-formatter\n\t\t */\n\t\tmetaPart(part) {\n\t\t\tif (typeof part === 'string' && part !== '') {\n\t\t\t\treturn { field: part, value: readPath(this.object, part), text: this.layoutText(part), column: this.layoutColumn(part) }\n\t\t\t}\n\t\t\tif (!part || typeof part !== 'object' || typeof part.field !== 'string' || part.field === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst column = typeof part.formatter === 'string' ? { formatter: part.formatter, formatterOptions: part.formatterOptions } : null\n\t\t\treturn { field: part.field, value: readPath(this.object, part.field), text: this.layoutText(part.field, column), column }\n\t\t},\n\n\t\t/**\n\t\t * A field's value as text: a person or a record by its display name,\n\t\t * title or name, anything else as a string. '' for an empty value or\n\t\t * a field that is not named.\n\t\t *\n\t\t * @param {unknown} field A dot path into the object.\n\t\t * @param {?object} [own] The column to read through instead of the one the field names.\n\t\t * @return {string}\n\t\t */\n\t\tlayoutText(field, own) {\n\t\t\tif (typeof field !== 'string' || field === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst value = readPath(this.object, field)\n\t\t\tif (value === null || value === undefined || value === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\t// A part whose field names a page column with a formatter reads as\n\t\t\t// its table cell does (a case type uuid as its name).\n\t\t\tconst column = own === undefined ? this.layoutColumn(field) : own\n\t\t\tconst format = column && column.formatter && this.cnFormatters ? this.cnFormatters[column.formatter] : null\n\t\t\tif (typeof format === 'function') {\n\t\t\t\tconst formatted = format(value, this.object, this.schema?.properties?.[field], column.formatterOptions || undefined)\n\t\t\t\treturn formatted === null || formatted === undefined ? '' : String(formatted)\n\t\t\t}\n\t\t\tif (typeof value === 'object') {\n\t\t\t\tconst name = value.displayName || value.title || value.name\n\t\t\t\treturn typeof name === 'string' ? name : ''\n\t\t\t}\n\t\t\treturn String(value)\n\t\t},\n\n\t\t/**\n\t\t * The page column a layout part's field names, or null.\n\t\t *\n\t\t * @param {string} field The part's field.\n\t\t * @return {?object} The column.\n\t\t */\n\t\tlayoutColumn(field) {\n\t\t\treturn (this.cardFieldColumns && typeof field === 'string' && this.cardFieldColumns[field]) || null\n\t\t},\n\n\t\t/**\n\t\t * A pill that reads its date field through the due rules: `variantWhen`\n\t\t * (the first rule the days left match gives the tone), else `due`\n\t\t * (overdue reads as error, within `due.soonWithin` days as warning).\n\t\t * The label is `labels[variant]`, else `labels.overdue` / `labels.soon`,\n\t\t * else Overdue / Soon, through the host's translate. Any other date\n\t\t * draws no pill.\n\t\t *\n\t\t * @param {{field: string, due?: object, variantWhen?: Array, labels?: object}} def The pill.\n\t\t * @return {?{label: string, variant: string}}\n\t\t */\n\t\tdatePill(def) {\n\t\t\tconst value = readPath(this.object, def.field)\n\t\t\tconst variant = Array.isArray(def.variantWhen)\n\t\t\t\t? this.dateRuleVariant(value, def.variantWhen)\n\t\t\t\t: this.dueVariant(value, def.due)\n\t\t\tif (variant === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst labels = def.labels && typeof def.labels === 'object' ? def.labels : {}\n\t\t\tconst state = variant === 'error' ? 'overdue' : (variant === 'warning' ? 'soon' : '')\n\t\t\tconst authored = labels[variant] || (state && labels[state])\n\t\t\tif (typeof authored === 'string' && authored !== '') {\n\t\t\t\treturn { label: this.cnTranslate(authored), variant }\n\t\t\t}\n\t\t\tif (state === 'overdue') {\n\t\t\t\treturn { label: t('nextcloud-vue', 'Overdue'), variant }\n\t\t\t}\n\t\t\tif (state === 'soon') {\n\t\t\t\treturn { label: t('nextcloud-vue', 'Soon'), variant }\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * The variant of the first `variantWhen` rule a date matches, or ''.\n\t\t *\n\t\t * @param {unknown} value The date.\n\t\t * @param {Array} rules The rules.\n\t\t * @return {string} The variant, or ''.\n\t\t */\n\t\tdateRuleVariant(value, rules) {\n\t\t\tconst matched = resolveDateVariant(value, rules)\n\t\t\treturn matched === 'default' ? '' : matched\n\t\t},\n\n\t\t/**\n\t\t * The variant the due rules give a date: error when overdue, warning\n\t\t * within `soonWithin` days, else ''.\n\t\t *\n\t\t * @param {unknown} value The date.\n\t\t * @param {object} config The `due` config.\n\t\t * @return {string} The variant, or ''.\n\t\t */\n\t\tdueVariant(value, config) {\n\t\t\tconst due = resolveDue(value, config)\n\t\t\tif (due && due.tone === 'danger') {\n\t\t\t\treturn 'error'\n\t\t\t}\n\t\t\treturn due && due.soon ? 'warning' : ''\n\t\t},\n\n\t\t/**\n\t\t * A layout pill as `{ label, variant }`, or null while its field is\n\t\t * empty.\n\t\t *\n\t\t * @param {?{field: string, colorMap?: object, labels?: object, variant?: string}} def The pill.\n\t\t * @return {?{label: string, variant: string}}\n\t\t */\n\t\tlayoutPill(def) {\n\t\t\tif (!def || typeof def !== 'object') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (def.due || Array.isArray(def.variantWhen)) {\n\t\t\t\treturn this.datePill(def)\n\t\t\t}\n\t\t\tconst value = this.layoutText(def.field)\n\t\t\tif (value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst labels = def.labels && typeof def.labels === 'object' ? def.labels : {}\n\t\t\tconst label = typeof labels[value] === 'string' ? this.cnTranslate(labels[value]) : value\n\t\t\tconst colorMap = def.colorMap && typeof def.colorMap === 'object' ? def.colorMap : {}\n\t\t\tconst key = Object.keys(colorMap).find((k) => k.toLowerCase() === value.toLowerCase())\n\t\t\tconst variant = key !== undefined ? colorMap[key] : def.variant\n\t\t\treturn { label, variant: isBadgeVariant(variant) ? variant : 'default' }\n\t\t},\n\n\t\t/**\n\t\t * One fact of the card: the property's value with the matching page\n\t\t * column (label, formatter, widget) when there is one.\n\t\t *\n\t\t * @param {string} key The property key.\n\t\t * @param {object} prop The schema property.\n\t\t * @return {object} { key, label, value, property, column }\n\t\t */\n\t\tmetadataField(key, prop) {\n\t\t\tconst column = (this.cardFieldColumns && this.cardFieldColumns[key]) || null\n\t\t\treturn {\n\t\t\t\tkey,\n\t\t\t\tlabel: this.cnTranslate((column && column.label) || prop.title || key),\n\t\t\t\tvalue: this.object[key],\n\t\t\t\tproperty: prop,\n\t\t\t\tcolumn,\n\t\t\t}\n\t\t},\n\n\t\tformatValue,\n\n\t\t/**\n\t\t * Card-body click: emits `select` when `selectable` (ignoring drags),\n\t\t * otherwise emits `click` for navigation. With `clickToView`, a\n\t\t * selectable card's body click navigates too — the checkbox is the\n\t\t * only selection surface, mirroring the table's rowClickToView split.\n\t\t *\n\t\t * @param {MouseEvent} [event] The originating click event.\n\t\t */\n\t\tonCardClick(event) {\n\t\t\tif (this.selectable && !this.clickToView) {\n\t\t\t\tif (this.wasDrag(event)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * @event select Emitted when the card toggles selection (clicking the body of a selectable card, or its checkbox).\n\t\t\t\t * @type {object} The card's object.\n\t\t\t\t */\n\t\t\t\tthis.$emit('select', this.object)\n\t\t\t\t// Deprecation: selectable cards used to emit `click`. Keep emitting it\n\t\t\t\t// for listeners that still rely on it, but warn them to migrate to `select`.\n\t\t\t\t// `$.vnode.props`, not `$attrs`: `click` is a declared emit, and\n\t\t\t\t// Vue keeps declared emits out of `$attrs`.\n\t\t\t\tif (this.$.vnode.props?.onClick) {\n\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\tconsole.warn('[CnObjectCard] @click on selectable cards is deprecated; use @select instead.')\n\t\t\t\t\tthis.$emit('click', this.object)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event click Emitted when a non-selectable (or `clickToView`) card is clicked. Payload: `(object, event)` — the card's object and the native click event, for opening it in a new tab on a ctrl/cmd/shift click. A middle click emits `aux-click` instead. Selectable cards emit `select`; they also emit `click` (deprecated) when a `click` listener is present, so migrate selectable consumers to `@select`.\n\t\t\t * @type {object} The card's object.\n\t\t\t */\n\t\t\tthis.$emit('click', this.object, event)\n\t\t},\n\n\t\t/**\n\t\t * Card mousedown: record the press for the drag guard, and on a card a\n\t\t * middle click opens, keep the browser from starting autoscroll.\n\t\t *\n\t\t * @param {MouseEvent} event The mousedown event.\n\t\t */\n\t\tonCardMouseDown(event) {\n\t\t\tthis.onPointerDown(event)\n\t\t\tif (!this.selectable || this.clickToView) {\n\t\t\t\tpreventMiddleClickAutoscroll(event)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Card-body middle click: emits `aux-click`, not `click`, so an existing\n\t\t * `click` listener that navigates never moves the current tab away.\n\t\t * Ignored on a select-on-click card, on nested controls and on drags.\n\t\t *\n\t\t * @param {MouseEvent} event The auxclick event.\n\t\t */\n\t\tonCardAuxClick(event) {\n\t\t\tif (!isRowMiddleClick(event) || this.wasDrag(event)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (this.selectable && !this.clickToView) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event aux-click Emitted when a non-selectable (or `clickToView`) card is middle-clicked, for opening it in a new tab (see `openRowTarget`). Payload: `(object, event)` — the card's object and the native auxclick event.\n\t\t\t * @type {object} The card's object.\n\t\t\t */\n\t\t\tthis.$emit('aux-click', this.object, event)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-object-card {\n\tdisplay: flex;\n\tgap: 12px;\n\tpadding: 16px;\n\tbackground: var(--color-main-background);\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-large, 10px);\n\tcursor: pointer;\n\ttransition: box-shadow 0.2s ease, border-color 0.2s ease;\n}\n\n.cn-object-card:hover {\n\tborder-color: var(--color-primary-element);\n\tbox-shadow: 0 2px 8px var(--color-box-shadow);\n}\n\n.cn-object-card--selected {\n\tborder-color: var(--color-primary-element);\n\tbackground: var(--color-primary-element-light);\n}\n\n/* The 4px start border takes 3px of padding, so the content stays put. */\n.cn-object-card.cn-object-card--accent {\n\tborder-inline-start-width: 4px;\n\tpadding-inline-start: 13px;\n}\n\n.cn-object-card.cn-object-card--accent-success {\n\tborder-inline-start-color: var(--color-element-success);\n}\n\n.cn-object-card.cn-object-card--accent-warning {\n\tborder-inline-start-color: var(--color-element-warning);\n}\n\n.cn-object-card.cn-object-card--accent-error {\n\tborder-inline-start-color: var(--color-element-error);\n}\n\n.cn-object-card.cn-object-card--accent-info {\n\tborder-inline-start-color: var(--color-element-info);\n}\n\n.cn-object-card.cn-object-card--accent-primary {\n\tborder-inline-start-color: var(--color-primary-element);\n}\n\n.cn-object-card__accent-icon {\n\tdisplay: inline-flex;\n\tvertical-align: -2px;\n\tmargin-inline-end: 4px;\n}\n\n.cn-object-card--accent-success .cn-object-card__accent-icon {\n\tcolor: var(--color-text-success);\n}\n\n.cn-object-card--accent-warning .cn-object-card__accent-icon {\n\tcolor: var(--color-text-warning);\n}\n\n.cn-object-card--accent-error .cn-object-card__accent-icon {\n\tcolor: var(--color-text-error);\n}\n\n.cn-object-card--accent-info .cn-object-card__accent-icon {\n\tcolor: var(--color-element-info);\n}\n\n.cn-object-card--accent-primary .cn-object-card__accent-icon {\n\tcolor: var(--color-primary-element);\n}\n\n.cn-object-card__checkbox {\n\tflex-shrink: 0;\n\tpadding-top: 2px;\n}\n\n.cn-object-card__content {\n\tflex: 1;\n\tmin-width: 0;\n}\n\n.cn-object-card__header {\n\tdisplay: flex;\n\tgap: 12px;\n\talign-items: flex-start;\n}\n\n.cn-object-card__image {\n\twidth: 48px;\n\theight: 48px;\n\tborder-radius: var(--border-radius);\n\tobject-fit: cover;\n\tflex-shrink: 0;\n}\n\n.cn-object-card__title-area {\n\tflex: 1;\n\tmin-width: 0;\n}\n\n.cn-object-card__title {\n\tmargin: 0;\n\tfont-size: 16px;\n\tfont-weight: 600;\n\tline-height: 1.3;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-object-card__description {\n\tmargin: 4px 0 0;\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n\tline-height: 1.4;\n}\n\n.cn-object-card__badges {\n\tmargin-top: 8px;\n}\n\n.cn-object-card__metadata {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(auto-fill, minmax(160px, 1fr));\n\tgap: 8px;\n\tmargin-top: 12px;\n\tpadding-top: 12px;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-object-card__meta-item {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n}\n\n.cn-object-card__meta-label {\n\tfont-size: 11px;\n\tfont-weight: 500;\n\tcolor: var(--color-text-maxcontrast);\n\ttext-transform: uppercase;\n\tletter-spacing: 0.3px;\n}\n\n.cn-object-card__actions {\n\tflex-shrink: 0;\n}\n</style>\n"],"names":["CnCellRenderer","CnIcon","CnLockIndicator","CnStatusBadge","t"],"mappings":"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"}
|