@conduction/nextcloud-vue 2.83.0 → 2.85.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 +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/CnAuditTrailCard/CnAuditTrailCard.vue.js +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js +1 -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 +232 -4
- package/dist/esm/components/CnBoardView/CnBoardView.vue2.js.map +1 -1
- package/dist/esm/components/CnBoardView/CnBoardView.vue3.js +95 -51
- package/dist/esm/components/CnBoardView/CnBoardView.vue3.js.map +1 -1
- package/dist/esm/components/CnBodySections/CnBodySections.vue.js +1 -1
- package/dist/esm/components/CnBodySections/CnBodySections.vue2.js +22 -1
- package/dist/esm/components/CnBodySections/CnBodySections.vue2.js.map +1 -1
- package/dist/esm/components/CnBodySections/CnBodySections.vue3.js.map +1 -1
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue.js +1 -1
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js +47 -4
- 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/CnDashboardGrid/CnDashboardGrid.vue.js +1 -1
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js +239 -3
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js +5 -5
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +50 -0
- 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/CnDeltaWidget/CnDeltaWidget.vue.js +1 -1
- package/dist/esm/components/CnDeltaWidget/CnDeltaWidget.vue2.js +1 -1
- package/dist/esm/components/CnDeltaWidget/CnDeltaWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnDeltaWidget/CnDeltaWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +226 -8
- 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/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/CnFieldListWidget/CnFieldListWidget.vue.js +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +38 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +45 -5
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnGaugeWidget/CnGaugeWidget.vue.js +1 -1
- package/dist/esm/components/CnGaugeWidget/CnGaugeWidget.vue2.js +1 -1
- package/dist/esm/components/CnGaugeWidget/CnGaugeWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnGaugeWidget/CnGaugeWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +548 -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/CnInteractionFormWidget/CnInteractionFormWidget.vue2.js +29 -6
- package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js +126 -2
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js +24 -2
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +106 -3
- 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/CnReportsPage/CnReportsPage.vue.js +1 -1
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue2.js +135 -2
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue2.js.map +1 -1
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue3.js +95 -43
- package/dist/esm/components/CnReportsPage/CnReportsPage.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/CnStagesWidget/CnStagesWidget.vue.js +1 -1
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js +72 -5
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js +33 -8
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue.js +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +135 -11
- 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/CnStatsBlockWidget/CnStatsBlockWidget.vue.js +1 -1
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js +17 -2
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js +1 -1
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +39 -6
- 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/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/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/CnWalkthrough/CnWalkthrough.vue.js +1 -1
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue2.js +16 -0
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue2.js.map +1 -1
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue3.js.map +1 -1
- package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue.js +1 -1
- package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue2.js +2 -1
- package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.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/CnTransitionInputDialog.vue.js +1 -1
- package/dist/esm/dialogs/CnTransitionInputDialog.vue2.js +68 -6
- package/dist/esm/dialogs/CnTransitionInputDialog.vue2.js.map +1 -1
- package/dist/esm/dialogs/CnTransitionInputDialog.vue3.js +133 -105
- package/dist/esm/dialogs/CnTransitionInputDialog.vue3.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +38 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +78 -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 +1030 -533
- package/dist/esm/store/useObjectStore.js +16 -2
- package/dist/esm/store/useObjectStore.js.map +1 -1
- package/dist/esm/utils/boardColumns.js +8 -1
- package/dist/esm/utils/boardColumns.js.map +1 -1
- package/dist/esm/utils/boardReferenceColumns.js +278 -0
- package/dist/esm/utils/boardReferenceColumns.js.map +1 -0
- package/dist/esm/utils/buildManifest.js +41 -4
- package/dist/esm/utils/buildManifest.js.map +1 -1
- package/dist/esm/utils/detailWidgetVisibility.js +149 -0
- package/dist/esm/utils/detailWidgetVisibility.js.map +1 -0
- package/dist/esm/utils/formatMetric.js +39 -3
- package/dist/esm/utils/formatMetric.js.map +1 -1
- package/dist/esm/utils/gridStack.js +40 -1
- package/dist/esm/utils/gridStack.js.map +1 -1
- package/dist/esm/utils/humaniseKey.js +41 -0
- package/dist/esm/utils/humaniseKey.js.map +1 -0
- package/dist/esm/utils/notificationRuleLabel.js +6 -23
- package/dist/esm/utils/notificationRuleLabel.js.map +1 -1
- package/dist/esm/utils/resolveManifestTokens.js +1 -0
- package/dist/esm/utils/resolveManifestTokens.js.map +1 -1
- package/dist/esm/utils/sentinelTokens.js +9 -0
- package/dist/esm/utils/sentinelTokens.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/widgetDispatch.js +8 -2
- package/dist/esm/utils/widgetDispatch.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +17159 -13422
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +1030 -533
- package/l10n/en.json +38 -1
- package/l10n/nl.json +78 -1
- package/package.json +1 -1
- package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +160 -8
- package/src/components/CnAuditTrailCard/CnAuditTrailCard.vue +1 -1
- package/src/components/CnBoardView/CnBoardView.vue +262 -6
- package/src/components/CnBodySections/CnBodySections.vue +22 -1
- package/src/components/CnCountdownWidget/CnCountdownWidget.vue +47 -4
- package/src/components/CnDashboardGrid/CnDashboardGrid.vue +244 -8
- package/src/components/CnDashboardPage/CnDashboardPage.vue +62 -2
- package/src/components/CnDeltaWidget/CnDeltaWidget.vue +1 -1
- package/src/components/CnDetailPage/CnDetailPage.md +3 -1
- package/src/components/CnDetailPage/CnDetailPage.vue +226 -8
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +3 -1
- package/src/components/CnFactsWidget/CnFactsWidget.vue +18 -5
- package/src/components/CnFieldListWidget/CnFieldListWidget.vue +63 -1
- package/src/components/CnGaugeWidget/CnGaugeWidget.vue +1 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +586 -25
- package/src/components/CnIndexPage/useSelfFetchList.js +10 -1
- package/src/components/CnInteractionFormWidget/CnInteractionFormWidget.vue +29 -6
- package/src/components/CnObjectDataWidget/CnObjectDataWidget.md +1 -1
- package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +154 -5
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +106 -3
- package/src/components/CnRegisterMapping/CnRegisterMapping.md +5 -0
- package/src/components/CnRegisterMapping/CnRegisterMapping.vue +231 -96
- package/src/components/CnReportsPage/CnReportsPage.vue +179 -1
- package/src/components/CnSettingsPage/CnSettingsPage.vue +5 -1
- package/src/components/CnStagesWidget/CnStagesWidget.vue +103 -6
- package/src/components/CnStatWidget/CnStatWidget.vue +137 -12
- package/src/components/CnStatsBlockWidget/CnStatsBlockWidget.vue +34 -3
- package/src/components/CnTabsWidget/CnTabsWidget.vue +39 -6
- package/src/components/CnToggleTableWidget/CnToggleTableWidget.vue +140 -7
- package/src/components/CnVersionInfoCard/CnVersionInfoCard.md +2 -1
- package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +42 -13
- package/src/components/CnWalkthrough/CnWalkthrough.vue +16 -0
- package/src/components/CnWeekStripWidget/CnWeekStripWidget.vue +2 -1
- 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 +65 -4
- package/src/css/dialog.css +4 -2
- package/src/css/form-field.css +14 -0
- package/src/css/form-widget.css +11 -0
- package/src/css/index-page.css +49 -0
- package/src/css/kpi-card.css +13 -0
- package/src/css/look-board-reports.css +58 -0
- package/src/css/look-board.css +108 -7
- package/src/dialogs/CnTransitionInputDialog.vue +87 -7
- package/src/index.js +2 -0
- package/src/schemas/app-manifest-v2.schema.json +137 -6
- package/src/store/useObjectStore.js +16 -2
- package/src/utils/boardColumns.js +8 -1
- package/src/utils/boardReferenceColumns.js +274 -0
- package/src/utils/buildManifest.js +40 -3
- package/src/utils/detailWidgetVisibility.js +145 -0
- package/src/utils/formatMetric.js +38 -2
- package/src/utils/gridStack.js +39 -0
- package/src/utils/humaniseKey.js +38 -0
- package/src/utils/notificationRuleLabel.js +5 -23
- package/src/utils/resolveManifestTokens.js +1 -0
- package/src/utils/sentinelTokens.js +9 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
- package/src/utils/widgetDispatch.js +8 -2
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<template>
|
|
6
6
|
<div
|
|
7
7
|
class="cn-board-view"
|
|
8
|
-
:class="{ 'cn-board-view--board': isBoardLook }"
|
|
8
|
+
:class="{ 'cn-board-view--board': isBoardLook, 'cn-board-view--wrap': wrapColumns, 'cn-board-view--selecting': selectedKeys.length > 0 }"
|
|
9
9
|
data-testid="cn-board-view">
|
|
10
10
|
<p v-if="!usable" class="cn-board-view__unusable" data-testid="cn-board-unusable">
|
|
11
11
|
{{ unusableText }}
|
|
@@ -36,9 +36,11 @@
|
|
|
36
36
|
v-for="column in lane.columns"
|
|
37
37
|
:key="`col-${lane.key}-${column.key}`"
|
|
38
38
|
class="cn-board-view__column"
|
|
39
|
+
:class="{ 'cn-board-view__column--unreachable': isUnreachable(column) }"
|
|
39
40
|
role="listitem"
|
|
40
41
|
data-testid="cn-board-column"
|
|
41
42
|
:data-column="column.key"
|
|
43
|
+
:data-unreachable="isUnreachable(column) ? 'true' : null"
|
|
42
44
|
@dragover.prevent
|
|
43
45
|
@drop="onDrop(column, $event)">
|
|
44
46
|
<!-- Board look: a dot, the label and a white count badge, with an
|
|
@@ -116,11 +118,21 @@
|
|
|
116
118
|
:data-card-id="cardKey(card)"
|
|
117
119
|
:draggable="canMove"
|
|
118
120
|
@dragstart="onDragStart(card, column, $event)"
|
|
121
|
+
@dragend="onDragEnd"
|
|
119
122
|
@keydown="onCardKeydown(card, column, lane, $event)">
|
|
120
123
|
<!-- Board look: title link, sub line, pill, footer, and a
|
|
121
124
|
menu button instead of the Move to select. -->
|
|
122
125
|
<template v-if="isBoardLook">
|
|
123
126
|
<div class="cn-board-view__card-head">
|
|
127
|
+
<input
|
|
128
|
+
v-if="selectable"
|
|
129
|
+
type="checkbox"
|
|
130
|
+
class="cn-board-view__select"
|
|
131
|
+
data-testid="cn-board-card-select"
|
|
132
|
+
:data-card-id="cardKey(card)"
|
|
133
|
+
:checked="isSelected(card)"
|
|
134
|
+
:aria-label="selectLabel(card)"
|
|
135
|
+
@change="toggleSelected(card)">
|
|
124
136
|
<a
|
|
125
137
|
href="#"
|
|
126
138
|
class="cn-board-view__card-title"
|
|
@@ -164,8 +176,14 @@
|
|
|
164
176
|
class="cn-board-view__menu-item"
|
|
165
177
|
data-testid="cn-board-menu-move"
|
|
166
178
|
:data-target="target.key"
|
|
167
|
-
|
|
179
|
+
:aria-disabled="isMoveAllowed(card, target) ? null : 'true'"
|
|
180
|
+
:class="{ 'cn-board-view__menu-item--blocked': !isMoveAllowed(card, target) }"
|
|
181
|
+
@click="isMoveAllowed(card, target) && onMenuMove(card, column, target)">
|
|
168
182
|
{{ target.label }}
|
|
183
|
+
<span
|
|
184
|
+
v-if="!isMoveAllowed(card, target)"
|
|
185
|
+
class="cn-board-view__menu-note"
|
|
186
|
+
data-testid="cn-board-menu-blocked">{{ notAllowedLabel }}</span>
|
|
169
187
|
</button>
|
|
170
188
|
</div>
|
|
171
189
|
<button
|
|
@@ -216,6 +234,16 @@
|
|
|
216
234
|
</span>
|
|
217
235
|
</template>
|
|
218
236
|
<template v-else>
|
|
237
|
+
<label v-if="selectable" class="cn-board-view__select-label">
|
|
238
|
+
<input
|
|
239
|
+
type="checkbox"
|
|
240
|
+
class="cn-board-view__select"
|
|
241
|
+
data-testid="cn-board-card-select"
|
|
242
|
+
:data-card-id="cardKey(card)"
|
|
243
|
+
:checked="isSelected(card)"
|
|
244
|
+
:aria-label="selectLabel(card)"
|
|
245
|
+
@change="toggleSelected(card)">
|
|
246
|
+
</label>
|
|
219
247
|
<span
|
|
220
248
|
v-if="dueLabel(card)"
|
|
221
249
|
class="cn-board-view__due"
|
|
@@ -354,6 +382,12 @@ export default {
|
|
|
354
382
|
* draws the screens' board anatomy (screens-kanban-parity).
|
|
355
383
|
*/
|
|
356
384
|
cnLook: { default: 'nextcloud' },
|
|
385
|
+
/**
|
|
386
|
+
* The app's cell-formatter registry, provided by CnAppRoot. A card
|
|
387
|
+
* role named in `cardRoles.formatters` shows its value through it, as
|
|
388
|
+
* the table's cells do (screens-board-reference-columns).
|
|
389
|
+
*/
|
|
390
|
+
cnFormatters: { default: () => ({}) },
|
|
357
391
|
},
|
|
358
392
|
|
|
359
393
|
props: {
|
|
@@ -494,9 +528,72 @@ export default {
|
|
|
494
528
|
type: Number,
|
|
495
529
|
default: 0,
|
|
496
530
|
},
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* The column a row belongs in, for a status whose raw value is not
|
|
534
|
+
* the column key: a reference whose rows are merged by name
|
|
535
|
+
* (screens-board-reference-columns). Absent, the row's `statusField`
|
|
536
|
+
* value is the key.
|
|
537
|
+
*
|
|
538
|
+
* @type {((row: object) => string)|null}
|
|
539
|
+
* @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-columns-can-be-the-rows-a-field-references
|
|
540
|
+
*/
|
|
541
|
+
columnKeyOf: {
|
|
542
|
+
type: Function,
|
|
543
|
+
default: null,
|
|
544
|
+
},
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Wrap the columns onto more rows, as many to a row as fit at 240px,
|
|
548
|
+
* instead of one row that scrolls sideways (manifest
|
|
549
|
+
* `config.board.wrap`). For a board with more stages than fit.
|
|
550
|
+
*
|
|
551
|
+
* @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-a-wide-board-can-wrap-its-columns
|
|
552
|
+
*/
|
|
553
|
+
wrapColumns: {
|
|
554
|
+
type: Boolean,
|
|
555
|
+
default: false,
|
|
556
|
+
},
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Offer a checkbox on every card, so cards can be selected for the
|
|
560
|
+
* list's bulk actions (the same selection the table holds).
|
|
561
|
+
*
|
|
562
|
+
* @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-cards-can-be-selected-for-bulk-actions
|
|
563
|
+
*/
|
|
564
|
+
selectable: {
|
|
565
|
+
type: Boolean,
|
|
566
|
+
default: false,
|
|
567
|
+
},
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* The selected cards, by row key.
|
|
571
|
+
*
|
|
572
|
+
* @type {Array<string|number>}
|
|
573
|
+
*/
|
|
574
|
+
selectedIds: {
|
|
575
|
+
type: Array,
|
|
576
|
+
default: () => [],
|
|
577
|
+
},
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* The columns one card may move to, asked when its menu opens or its
|
|
581
|
+
* drag starts: `(card) => Promise<Array<string>|null>`, column keys,
|
|
582
|
+
* `null` for every column. A column the card cannot reach is greyed
|
|
583
|
+
* during the drag and marked "not allowed" in the menu, and a drop on
|
|
584
|
+
* it is refused without asking the host. Absent, every column is
|
|
585
|
+
* offered and the host's move decides.
|
|
586
|
+
*
|
|
587
|
+
* @type {((card: object) => Promise<Array<string>|null>)|null}
|
|
588
|
+
* @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-the-board-shows-where-a-card-can-go
|
|
589
|
+
*/
|
|
590
|
+
allowedMoves: {
|
|
591
|
+
type: Function,
|
|
592
|
+
default: null,
|
|
593
|
+
},
|
|
497
594
|
},
|
|
498
595
|
|
|
499
|
-
emits: ['card-click', 'card-aux-click', 'moved', 'refused', 'stale', 'load-more'],
|
|
596
|
+
emits: ['card-click', 'card-aux-click', 'moved', 'refused', 'stale', 'load-more', 'select'],
|
|
500
597
|
|
|
501
598
|
data() {
|
|
502
599
|
return {
|
|
@@ -512,6 +609,10 @@ export default {
|
|
|
512
609
|
expanded: [],
|
|
513
610
|
/** The card whose menu is open (board look), by card key. */
|
|
514
611
|
openMenuKey: null,
|
|
612
|
+
/** Column keys each card may move to (`allowedMoves`), by card key; absent = not asked yet. */
|
|
613
|
+
allowedByCard: {},
|
|
614
|
+
/** The column keys the dragged card may reach, or null for all. */
|
|
615
|
+
dragAllowed: null,
|
|
515
616
|
}
|
|
516
617
|
},
|
|
517
618
|
|
|
@@ -529,6 +630,7 @@ export default {
|
|
|
529
630
|
statusField: this.statusField,
|
|
530
631
|
offBoardLabel: t('nextcloud-vue', 'Elsewhere'),
|
|
531
632
|
colorField: this.colorField,
|
|
633
|
+
keyOf: this.columnKeyOf,
|
|
532
634
|
})
|
|
533
635
|
},
|
|
534
636
|
|
|
@@ -556,9 +658,20 @@ export default {
|
|
|
556
658
|
due: (given && given.due) || '',
|
|
557
659
|
owner: (given && given.owner) || '',
|
|
558
660
|
pillColors: (given && given.pillColors) || {},
|
|
661
|
+
formatters: (given && given.formatters && typeof given.formatters === 'object') ? given.formatters : {},
|
|
559
662
|
}
|
|
560
663
|
},
|
|
561
664
|
|
|
665
|
+
/** @return {string} The note on a menu target the card cannot reach. */
|
|
666
|
+
notAllowedLabel() {
|
|
667
|
+
return t('nextcloud-vue', 'not allowed')
|
|
668
|
+
},
|
|
669
|
+
|
|
670
|
+
/** @return {Array<string>} The selected row keys as strings. */
|
|
671
|
+
selectedKeys() {
|
|
672
|
+
return (Array.isArray(this.selectedIds) ? this.selectedIds : []).map(String)
|
|
673
|
+
},
|
|
674
|
+
|
|
562
675
|
/** @return {string} The Open in new tab menu item. */
|
|
563
676
|
openInNewTabLabel() {
|
|
564
677
|
return t('nextcloud-vue', 'Open in new tab')
|
|
@@ -617,6 +730,97 @@ export default {
|
|
|
617
730
|
|
|
618
731
|
preventMiddleClickAutoscroll,
|
|
619
732
|
|
|
733
|
+
/**
|
|
734
|
+
* Whether a card is selected.
|
|
735
|
+
*
|
|
736
|
+
* @param {object} card The card.
|
|
737
|
+
* @return {boolean} True when selected.
|
|
738
|
+
*/
|
|
739
|
+
isSelected(card) {
|
|
740
|
+
return this.selectedKeys.includes(this.cardKey(card))
|
|
741
|
+
},
|
|
742
|
+
|
|
743
|
+
/**
|
|
744
|
+
* The checkbox's accessible name.
|
|
745
|
+
*
|
|
746
|
+
* @param {object} card The card.
|
|
747
|
+
* @return {string} "Select <name>".
|
|
748
|
+
*/
|
|
749
|
+
selectLabel(card) {
|
|
750
|
+
const name = this.roleText(card, this.roles.title) || this.cardKey(card)
|
|
751
|
+
return t('nextcloud-vue', 'Select {name}', { name })
|
|
752
|
+
},
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Select a card, or unselect it.
|
|
756
|
+
*
|
|
757
|
+
* @param {object} card The card.
|
|
758
|
+
* @return {void}
|
|
759
|
+
* @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-cards-can-be-selected-for-bulk-actions
|
|
760
|
+
*/
|
|
761
|
+
toggleSelected(card) {
|
|
762
|
+
const key = this.cardKey(card)
|
|
763
|
+
const next = this.isSelected(card)
|
|
764
|
+
? this.selectedIds.filter((id) => String(id) !== key)
|
|
765
|
+
: [...this.selectedIds, card?.[this.rowKey]]
|
|
766
|
+
/**
|
|
767
|
+
* @event select Emitted when a card's checkbox changes. Payload: the selected row keys.
|
|
768
|
+
*/
|
|
769
|
+
this.$emit('select', next)
|
|
770
|
+
},
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* Ask the host where one card may go (`allowedMoves`), once per card.
|
|
774
|
+
*
|
|
775
|
+
* @param {object} card The card.
|
|
776
|
+
* @return {Promise<Array<string>|null>} The column keys, or null for all.
|
|
777
|
+
* @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-the-board-shows-where-a-card-can-go
|
|
778
|
+
*/
|
|
779
|
+
async loadAllowed(card) {
|
|
780
|
+
if (typeof this.allowedMoves !== 'function') {
|
|
781
|
+
return null
|
|
782
|
+
}
|
|
783
|
+
const key = this.cardKey(card)
|
|
784
|
+
if (Object.hasOwn(this.allowedByCard, key)) {
|
|
785
|
+
return this.allowedByCard[key]
|
|
786
|
+
}
|
|
787
|
+
let allowed
|
|
788
|
+
try {
|
|
789
|
+
const answer = await this.allowedMoves(card)
|
|
790
|
+
allowed = Array.isArray(answer) ? answer.map(String) : null
|
|
791
|
+
} catch {
|
|
792
|
+
// Unknown is not "nowhere": the host's move stays the authority.
|
|
793
|
+
allowed = null
|
|
794
|
+
}
|
|
795
|
+
this.allowedByCard = { ...this.allowedByCard, [key]: allowed }
|
|
796
|
+
return allowed
|
|
797
|
+
},
|
|
798
|
+
|
|
799
|
+
/**
|
|
800
|
+
* Whether a card may move to a column, as far as the board knows.
|
|
801
|
+
*
|
|
802
|
+
* @param {object} card The card.
|
|
803
|
+
* @param {object} target The column.
|
|
804
|
+
* @return {boolean} False only when the host said it cannot.
|
|
805
|
+
*/
|
|
806
|
+
isMoveAllowed(card, target) {
|
|
807
|
+
const allowed = this.allowedByCard[this.cardKey(card)]
|
|
808
|
+
return !Array.isArray(allowed) || allowed.includes(String(target.key))
|
|
809
|
+
},
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Whether a column is out of reach for the card being dragged.
|
|
813
|
+
*
|
|
814
|
+
* @param {object} column The column.
|
|
815
|
+
* @return {boolean} True while a drag is on and the card cannot go there.
|
|
816
|
+
*/
|
|
817
|
+
isUnreachable(column) {
|
|
818
|
+
return this.dragging !== null
|
|
819
|
+
&& Array.isArray(this.dragAllowed)
|
|
820
|
+
&& column.key !== this.dragging.fromKey
|
|
821
|
+
&& !this.dragAllowed.includes(String(column.key))
|
|
822
|
+
},
|
|
823
|
+
|
|
620
824
|
/**
|
|
621
825
|
* A card's due state under `dueRule`.
|
|
622
826
|
*
|
|
@@ -658,11 +862,35 @@ export default {
|
|
|
658
862
|
const fields = Array.isArray(role) ? role : [role]
|
|
659
863
|
return fields
|
|
660
864
|
.filter((field) => typeof field === 'string' && field !== '')
|
|
661
|
-
.map((field) => this.
|
|
865
|
+
.map((field) => this.fieldText(card, field))
|
|
662
866
|
.filter((value) => value !== '')
|
|
663
867
|
.join(' \u00b7 ')
|
|
664
868
|
},
|
|
665
869
|
|
|
870
|
+
/**
|
|
871
|
+
* One card field as text: through the formatter `cardRoles.formatters`
|
|
872
|
+
* names for it, else the value itself.
|
|
873
|
+
*
|
|
874
|
+
* @param {object} card The card's row.
|
|
875
|
+
* @param {string} field The dot-path.
|
|
876
|
+
* @return {string} The text.
|
|
877
|
+
* @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-a-card-field-can-show-through-a-formatter
|
|
878
|
+
*/
|
|
879
|
+
fieldText(card, field) {
|
|
880
|
+
const raw = readPath(card, field)
|
|
881
|
+
const id = this.roles.formatters[field]
|
|
882
|
+
const fn = id && this.cnFormatters ? this.cnFormatters[id] : null
|
|
883
|
+
if (typeof fn === 'function') {
|
|
884
|
+
try {
|
|
885
|
+
const out = fn(raw, card, null)
|
|
886
|
+
return out === null || out === undefined ? '' : String(out).trim()
|
|
887
|
+
} catch {
|
|
888
|
+
return this.textOf(raw)
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
return this.textOf(raw)
|
|
892
|
+
},
|
|
893
|
+
|
|
666
894
|
/**
|
|
667
895
|
* A value as text: a string or number as is, an object by its label.
|
|
668
896
|
*
|
|
@@ -687,7 +915,7 @@ export default {
|
|
|
687
915
|
* @return {string} A CnStatusBadge variant.
|
|
688
916
|
*/
|
|
689
917
|
pillVariant(card) {
|
|
690
|
-
const raw = this.
|
|
918
|
+
const raw = this.fieldText(card, this.roles.pill)
|
|
691
919
|
const variant = this.roles.pillColors[raw] ?? this.roles.pillColors[raw.toLowerCase()]
|
|
692
920
|
return isBadgeVariant(variant) ? variant : 'default'
|
|
693
921
|
},
|
|
@@ -727,7 +955,7 @@ export default {
|
|
|
727
955
|
* @return {string} The name, '' when there is none.
|
|
728
956
|
*/
|
|
729
957
|
ownerName(card) {
|
|
730
|
-
return this.roles.owner === '' ? '' : this.
|
|
958
|
+
return this.roles.owner === '' ? '' : this.fieldText(card, this.roles.owner)
|
|
731
959
|
},
|
|
732
960
|
|
|
733
961
|
/**
|
|
@@ -879,6 +1107,7 @@ export default {
|
|
|
879
1107
|
const key = this.cardKey(card)
|
|
880
1108
|
this.openMenuKey = this.openMenuKey === key ? null : key
|
|
881
1109
|
if (this.openMenuKey !== null) {
|
|
1110
|
+
this.loadAllowed(card)
|
|
882
1111
|
this.focusMenuItem(card, 0)
|
|
883
1112
|
}
|
|
884
1113
|
},
|
|
@@ -967,6 +1196,7 @@ export default {
|
|
|
967
1196
|
event.preventDefault()
|
|
968
1197
|
if (!this.isMenuOpen(card)) {
|
|
969
1198
|
this.openMenuKey = this.cardKey(card)
|
|
1199
|
+
this.loadAllowed(card)
|
|
970
1200
|
this.focusMenuItem(card, 0)
|
|
971
1201
|
}
|
|
972
1202
|
}
|
|
@@ -1113,8 +1343,27 @@ export default {
|
|
|
1113
1343
|
*/
|
|
1114
1344
|
onDragStart(card, column, event) {
|
|
1115
1345
|
this.dragging = { card, fromKey: column.key }
|
|
1346
|
+
this.dragAllowed = null
|
|
1116
1347
|
// Firefox drops a drag that carries no data.
|
|
1117
1348
|
event?.dataTransfer?.setData?.('text/plain', this.cardKey(card))
|
|
1349
|
+
if (typeof this.allowedMoves === 'function') {
|
|
1350
|
+
this.loadAllowed(card).then((allowed) => {
|
|
1351
|
+
if (this.dragging && this.dragging.card === card) {
|
|
1352
|
+
this.dragAllowed = allowed
|
|
1353
|
+
}
|
|
1354
|
+
})
|
|
1355
|
+
}
|
|
1356
|
+
},
|
|
1357
|
+
|
|
1358
|
+
/**
|
|
1359
|
+
* The drag ended (dropped anywhere, or cancelled): no column stays
|
|
1360
|
+
* greyed. A drop on a column has already run by now.
|
|
1361
|
+
*
|
|
1362
|
+
* @return {void}
|
|
1363
|
+
*/
|
|
1364
|
+
onDragEnd() {
|
|
1365
|
+
this.dragging = null
|
|
1366
|
+
this.dragAllowed = null
|
|
1118
1367
|
},
|
|
1119
1368
|
|
|
1120
1369
|
/**
|
|
@@ -1129,6 +1378,13 @@ export default {
|
|
|
1129
1378
|
}
|
|
1130
1379
|
const { card, fromKey } = this.dragging
|
|
1131
1380
|
this.dragging = null
|
|
1381
|
+
this.dragAllowed = null
|
|
1382
|
+
if (column.key !== fromKey && !this.isMoveAllowed(card, column)) {
|
|
1383
|
+
const name = this.roleText(card, this.roles.title) || this.cardKey(card)
|
|
1384
|
+
this.refusal = t('nextcloud-vue', '{name} cannot move to {column}.', { name, column: column.label })
|
|
1385
|
+
this.$emit('refused', { card, message: this.refusal })
|
|
1386
|
+
return
|
|
1387
|
+
}
|
|
1132
1388
|
await this.move(card, fromKey, column.key)
|
|
1133
1389
|
},
|
|
1134
1390
|
|
|
@@ -82,6 +82,8 @@ export default {
|
|
|
82
82
|
cnRegistry: { default: () => ({}) },
|
|
83
83
|
/** Legacy custom-component map provided by CnAppRoot. */
|
|
84
84
|
cnCustomComponents: { default: () => ({}) },
|
|
85
|
+
/** The host's translate function for manifest-authored strings, provided by CnAppRoot. */
|
|
86
|
+
cnTranslate: { default: null },
|
|
85
87
|
},
|
|
86
88
|
|
|
87
89
|
props: {
|
|
@@ -201,7 +203,7 @@ export default {
|
|
|
201
203
|
return {
|
|
202
204
|
id,
|
|
203
205
|
name,
|
|
204
|
-
title: (section && section.title) || '',
|
|
206
|
+
title: this.translateTitle((section && section.title) || ''),
|
|
205
207
|
card: !!(section && section.card),
|
|
206
208
|
colSpan: section && section.colSpan,
|
|
207
209
|
placement: section && section.placement,
|
|
@@ -213,6 +215,25 @@ export default {
|
|
|
213
215
|
},
|
|
214
216
|
|
|
215
217
|
methods: {
|
|
218
|
+
/**
|
|
219
|
+
* A manifest-authored section title in the reader's language.
|
|
220
|
+
*
|
|
221
|
+
* The title is written in the manifest, so it belongs to the host
|
|
222
|
+
* app's catalogue, the same as every other manifest title the detail
|
|
223
|
+
* page shows. A section heading printed raw read "Asked about" to a
|
|
224
|
+
* Dutch handler on a pipelinq ticket (Zuiddrecht live round 3).
|
|
225
|
+
*
|
|
226
|
+
* @param {string} title The title as written in the manifest.
|
|
227
|
+
* @return {string} The translated title, or '' when there is none.
|
|
228
|
+
* @spec openspec/changes/detail-page-strings-dutch/specs/detail-page-strings-dutch/spec.md#requirement-the-detail-page-speaks-the-readers-language
|
|
229
|
+
*/
|
|
230
|
+
translateTitle(title) {
|
|
231
|
+
if (title === '' || typeof this.cnTranslate !== 'function') {
|
|
232
|
+
return title
|
|
233
|
+
}
|
|
234
|
+
return this.cnTranslate(title)
|
|
235
|
+
},
|
|
236
|
+
|
|
216
237
|
/**
|
|
217
238
|
* Resolve a section's host-app component by registry name. Precedence
|
|
218
239
|
* matches CnPageRenderer.resolveCustomComponent: the v2 `cnRegistry`
|
|
@@ -69,6 +69,18 @@ const VARIANT_COLORS = Object.freeze({
|
|
|
69
69
|
* negative number: "-3 days left" is a puzzle, and an overdue case is the one
|
|
70
70
|
* state a handler must not have to decode.
|
|
71
71
|
*
|
|
72
|
+
* ## A settled record
|
|
73
|
+
*
|
|
74
|
+
* `settledField` names a property on the record that is truthy once the work
|
|
75
|
+
* the date belongs to is done, such as a case in its final status. A settled
|
|
76
|
+
* record reads `settledLabel` (default "Closed") in no threshold colour, never
|
|
77
|
+
* "overdue": a closed case missed nothing that can still be acted on, and a red
|
|
78
|
+
* count of days on it sends a handler after a case that needs nobody.
|
|
79
|
+
*
|
|
80
|
+
* ```js
|
|
81
|
+
* content: { field: 'deadline', settledField: 'isFinalStatus', settledLabel: 'Handled' }
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
72
84
|
* ## An unset date
|
|
73
85
|
*
|
|
74
86
|
* Renders a dash and no threshold colour. A case with no deadline is not urgent
|
|
@@ -91,8 +103,10 @@ export default {
|
|
|
91
103
|
* - `icon` — MDI icon name.
|
|
92
104
|
* - `thresholds` — `{ warn, danger }` in days remaining.
|
|
93
105
|
* - `showDate` — render the absolute date underneath (default true).
|
|
106
|
+
* - `settledField` — property on the record that is truthy once the work is done; the tile then reads `settledLabel` and never counts overdue.
|
|
107
|
+
* - `settledLabel` — the headline of a settled record, run through the host's translate function (default "Closed").
|
|
94
108
|
*
|
|
95
|
-
* @type {{ field?: string, label?: string, icon?: string, thresholds?: {warn?: number, danger?: number}, showDate?: boolean }}
|
|
109
|
+
* @type {{ field?: string, label?: string, icon?: string, thresholds?: {warn?: number, danger?: number}, showDate?: boolean, settledField?: string, settledLabel?: string }}
|
|
96
110
|
*/
|
|
97
111
|
content: {
|
|
98
112
|
type: Object,
|
|
@@ -115,6 +129,7 @@ export default {
|
|
|
115
129
|
return {
|
|
116
130
|
cnObjectContextInjected: inject('cnObjectContext', null),
|
|
117
131
|
cnDetailObjectContextInjected: inject('cnDetailObjectContext', null),
|
|
132
|
+
cnTranslate: inject('cnTranslate', null),
|
|
118
133
|
}
|
|
119
134
|
},
|
|
120
135
|
|
|
@@ -166,17 +181,44 @@ export default {
|
|
|
166
181
|
return Math.round((startOfDay(this.targetDate) - startOfDay(new Date())) / MS_PER_DAY)
|
|
167
182
|
},
|
|
168
183
|
|
|
169
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* Whether the record says its work is done (`settledField` is truthy).
|
|
186
|
+
*
|
|
187
|
+
* @return {boolean} True for a settled record.
|
|
188
|
+
* @spec openspec/changes/countdown-settled-record/specs/countdown-settled-record/spec.md#requirement-a-settled-record-never-reads-as-overdue
|
|
189
|
+
*/
|
|
190
|
+
isSettled() {
|
|
191
|
+
const field = this.content?.settledField
|
|
192
|
+
if (!this.record || !field) {
|
|
193
|
+
return false
|
|
194
|
+
}
|
|
195
|
+
return Boolean(getByPath(this.record, field))
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Whether the date has passed on a record still open.
|
|
200
|
+
*
|
|
201
|
+
* @return {boolean} True when overdue.
|
|
202
|
+
* @spec openspec/changes/countdown-settled-record/specs/countdown-settled-record/spec.md#requirement-a-settled-record-never-reads-as-overdue
|
|
203
|
+
*/
|
|
170
204
|
isOverdue() {
|
|
171
|
-
return this.daysRemaining !== null && this.daysRemaining < 0
|
|
205
|
+
return !this.isSettled && this.daysRemaining !== null && this.daysRemaining < 0
|
|
172
206
|
},
|
|
173
207
|
|
|
174
208
|
/**
|
|
175
209
|
* The headline: the remaining time in words.
|
|
176
210
|
*
|
|
177
211
|
* @return {string} The headline text.
|
|
212
|
+
* @spec openspec/changes/countdown-settled-record/specs/countdown-settled-record/spec.md#requirement-a-settled-record-never-reads-as-overdue
|
|
178
213
|
*/
|
|
179
214
|
headline() {
|
|
215
|
+
if (this.isSettled) {
|
|
216
|
+
const label = this.content?.settledLabel
|
|
217
|
+
if (label) {
|
|
218
|
+
return typeof this.cnTranslate === 'function' ? this.cnTranslate(label) : label
|
|
219
|
+
}
|
|
220
|
+
return t('nextcloud-vue', 'Closed')
|
|
221
|
+
}
|
|
180
222
|
const days = this.daysRemaining
|
|
181
223
|
if (days === null) {
|
|
182
224
|
return '—'
|
|
@@ -213,10 +255,11 @@ export default {
|
|
|
213
255
|
* The threshold band this date falls in.
|
|
214
256
|
*
|
|
215
257
|
* @return {string} One of default / success / warning / error.
|
|
258
|
+
* @spec openspec/changes/countdown-settled-record/specs/countdown-settled-record/spec.md#requirement-a-settled-record-never-reads-as-overdue
|
|
216
259
|
*/
|
|
217
260
|
variant() {
|
|
218
261
|
const days = this.daysRemaining
|
|
219
|
-
if (days === null) {
|
|
262
|
+
if (days === null || this.isSettled) {
|
|
220
263
|
return 'default'
|
|
221
264
|
}
|
|
222
265
|
if (days < 0) {
|