@conduction/nextcloud-vue 2.77.0 → 2.79.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/bundled-packages.json +0 -2
- package/dist/esm/bundled-packages.json +0 -2
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +113 -104
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnAiCompanion/CnAiCompanion.vue2.js +23 -0
- package/dist/esm/components/CnAiCompanion/CnAiCompanion.vue2.js.map +1 -1
- package/dist/esm/components/CnAiCompanion/CnAiCompanion.vue3.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +12 -2
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnBoardView/CnBoardView.vue2.js +2 -1
- package/dist/esm/components/CnBoardView/CnBoardView.vue2.js.map +1 -1
- package/dist/esm/components/CnBoardView/CnBoardView.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +117 -0
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +122 -97
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +37 -0
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js +2 -2
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +168 -5
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +140 -92
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +84 -2
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +4 -2
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDateRangePicker/CnDateRangePicker.vue.js +1 -1
- package/dist/esm/components/CnDateRangePicker/CnDateRangePicker.vue2.js +45 -2
- package/dist/esm/components/CnDateRangePicker/CnDateRangePicker.vue2.js.map +1 -1
- package/dist/esm/components/CnDateRangePicker/CnDateRangePicker.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +61 -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/CnFilesBrowser/CnFilesBrowser.vue2.js +173 -5
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +181 -99
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/filesBrowser.js +29 -11
- package/dist/esm/components/CnFilesBrowser/filesBrowser.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/openRegisterSource.js +252 -0
- package/dist/esm/components/CnFilesBrowser/openRegisterSource.js.map +1 -0
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +8 -2
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnFormPage/CnFormPage.vue2.js +4 -1
- package/dist/esm/components/CnFormPage/CnFormPage.vue2.js.map +1 -1
- package/dist/esm/components/CnFormPage/CnFormPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +31 -2
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +3 -2
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +100 -3
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +4 -2
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js +3 -2
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js.map +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js.map +1 -1
- package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue2.js.map +1 -1
- package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js +1 -1
- package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +36 -0
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +35 -23
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStatusBadge/CnStatusBadge.vue2.js +6 -2
- package/dist/esm/components/CnStatusBadge/CnStatusBadge.vue2.js.map +1 -1
- package/dist/esm/components/CnStatusBadge/CnStatusBadge.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +30 -1
- 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/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +13 -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/composables/useAppManifest.js +8 -3
- package/dist/esm/composables/useAppManifest.js.map +1 -1
- package/dist/esm/composables/useFormDraft.js +11 -1
- package/dist/esm/composables/useFormDraft.js.map +1 -1
- package/dist/esm/composables/useObjectPresence.js +15 -4
- package/dist/esm/composables/useObjectPresence.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 +68 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +113 -2
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +526 -16
- package/dist/esm/utils/badgeVariants.js +32 -0
- package/dist/esm/utils/badgeVariants.js.map +1 -0
- package/dist/esm/utils/boardDate.js +193 -0
- package/dist/esm/utils/boardDate.js.map +1 -0
- package/dist/esm/utils/dynamicProperties.js +5 -1
- package/dist/esm/utils/dynamicProperties.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +57 -6
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +2569 -811
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +526 -16
- package/l10n/en.json +68 -1
- package/l10n/nl.json +113 -2
- package/package.json +1 -1
- package/scripts/build-validators.js +26 -0
- package/src/components/CnActionsBar/CnActionsBar.vue +48 -39
- package/src/components/CnAiCompanion/CnAiCompanion.vue +23 -0
- package/src/components/CnAppRoot/CnAppRoot.vue +12 -2
- package/src/components/CnBoardView/CnBoardView.vue +2 -1
- package/src/components/CnCellRenderer/CnCellRenderer.md +1 -0
- package/src/components/CnCellRenderer/CnCellRenderer.vue +169 -10
- package/src/components/CnChartWidget/CnChartWidget.vue +39 -2
- package/src/components/CnDashboardPage/CnDashboardPage.vue +248 -8
- package/src/components/CnDataTable/CnDataTable.md +2 -0
- package/src/components/CnDataTable/CnDataTable.vue +88 -4
- package/src/components/CnDateRangePicker/CnDateRangePicker.vue +44 -1
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +61 -1
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +232 -11
- package/src/components/CnFilesBrowser/filesBrowser.js +43 -2
- package/src/components/CnFilesBrowser/index.js +1 -0
- package/src/components/CnFilesBrowser/openRegisterSource.js +248 -0
- package/src/components/CnFormDialog/CnFormDialog.vue +8 -2
- package/src/components/CnFormPage/CnFormPage.vue +4 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +33 -3
- package/src/components/CnObjectSidebar/CnFilesTab.vue +103 -4
- package/src/components/CnQuickFilterBar/CnQuickFilterBar.vue +3 -2
- package/src/components/CnSavedViewsControl/CnSavedViewsControl.vue +1 -1
- package/src/components/CnStatWidget/CnStatWidget.vue +52 -2
- package/src/components/CnStatusBadge/CnStatusBadge.vue +6 -2
- package/src/components/CnTabsWidget/CnTabsWidget.vue +30 -1
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +13 -0
- package/src/components/index.js +1 -1
- package/src/composables/__tests__/useObjectPresence.spec.js +24 -0
- package/src/composables/useAppManifest.js +8 -3
- package/src/composables/useFormDraft.js +11 -1
- package/src/composables/useObjectPresence.js +15 -4
- package/src/css/badge.css +31 -0
- package/src/css/kpi-card.css +51 -0
- package/src/css/look-board-detail.css +10 -0
- package/src/css/look-board-index.css +128 -14
- package/src/css/look-board.css +85 -0
- package/src/css/table.css +37 -0
- package/src/index.js +4 -0
- package/src/schemas/app-manifest-v2.schema.json +50 -5
- package/src/utils/badgeVariants.js +29 -0
- package/src/utils/boardDate.js +189 -0
- package/src/utils/dynamicProperties.js +5 -1
- package/src/utils/validateManifestV2.compiled.js +57 -2
- package/dist/esm/_virtual/equal.js +0 -4
- package/dist/esm/_virtual/equal.js.map +0 -1
- package/dist/esm/_virtual/ucs2length.js +0 -4
- package/dist/esm/_virtual/ucs2length.js.map +0 -1
- package/dist/esm/node_modules/ajv/dist/runtime/equal.js +0 -9
- package/dist/esm/node_modules/ajv/dist/runtime/equal.js.map +0 -1
- package/dist/esm/node_modules/ajv/dist/runtime/ucs2length.js +0 -25
- package/dist/esm/node_modules/ajv/dist/runtime/ucs2length.js.map +0 -1
- package/dist/esm/node_modules/fast-deep-equal/index.js +0 -47
- package/dist/esm/node_modules/fast-deep-equal/index.js.map +0 -1
|
@@ -24,12 +24,15 @@
|
|
|
24
24
|
</span>
|
|
25
25
|
</template>
|
|
26
26
|
|
|
27
|
-
<!-- Built-in "badge" widget
|
|
27
|
+
<!-- Built-in "badge" widget: renders the value as a status pill. An enum
|
|
28
|
+
value shows its label (x-enum-labels, translated) unless a formatter
|
|
29
|
+
shapes it; the colour stays keyed on the raw value. -->
|
|
28
30
|
<template v-else-if="widget === 'badge'">
|
|
29
31
|
<CnStatusBadge v-if="hasValue"
|
|
30
|
-
:label="
|
|
32
|
+
:label="labelledValue"
|
|
31
33
|
:variant="badgeVariant"
|
|
32
|
-
:colorMap="badgeColorMap"
|
|
34
|
+
:colorMap="badgeColorMap"
|
|
35
|
+
:colorKey="badgeColorKey" />
|
|
33
36
|
<span v-else class="cn-cell-renderer__dash">—</span>
|
|
34
37
|
</template>
|
|
35
38
|
|
|
@@ -78,7 +81,7 @@
|
|
|
78
81
|
v-if="linkRoute"
|
|
79
82
|
:to="linkRoute"
|
|
80
83
|
class="cn-cell-renderer__link">
|
|
81
|
-
{{
|
|
84
|
+
{{ labelledValue }}
|
|
82
85
|
</router-link>
|
|
83
86
|
<a
|
|
84
87
|
v-else-if="linkHref"
|
|
@@ -86,9 +89,9 @@
|
|
|
86
89
|
target="_blank"
|
|
87
90
|
rel="noopener"
|
|
88
91
|
class="cn-cell-renderer__link">
|
|
89
|
-
{{
|
|
92
|
+
{{ labelledValue }}
|
|
90
93
|
</a>
|
|
91
|
-
<span v-else :title="rawTitle">{{
|
|
94
|
+
<span v-else :title="rawTitle">{{ labelledValue }}</span>
|
|
92
95
|
</template>
|
|
93
96
|
|
|
94
97
|
<!-- Built-in "avatar" widget: a person as an avatar with the name beside
|
|
@@ -115,6 +118,19 @@
|
|
|
115
118
|
<span v-else class="cn-cell-renderer__dash">—</span>
|
|
116
119
|
</template>
|
|
117
120
|
|
|
121
|
+
<!-- Built-in "age" widget: how long something has waited ("4 uur",
|
|
122
|
+
"3 dagen"), coloured by widgetProps.variantWhen rules on the days
|
|
123
|
+
the cell shows. The full date is the tooltip. -->
|
|
124
|
+
<template v-else-if="widget === 'age'">
|
|
125
|
+
<time
|
|
126
|
+
v-if="dateTimestamp"
|
|
127
|
+
class="cn-cell-renderer__age"
|
|
128
|
+
:class="ageVariant ? 'cn-cell-renderer__age--' + ageVariant : null"
|
|
129
|
+
:datetime="dateTimestamp.toISOString()"
|
|
130
|
+
:title="absoluteDateLabel">{{ ageLabel }}</time>
|
|
131
|
+
<span v-else class="cn-cell-renderer__dash">—</span>
|
|
132
|
+
</template>
|
|
133
|
+
|
|
118
134
|
<!-- Built-in "date" widget: a date whose colour follows
|
|
119
135
|
widgetProps.variantWhen, rules on the number of days until it
|
|
120
136
|
(0 = today, negative = overdue). -->
|
|
@@ -141,7 +157,7 @@
|
|
|
141
157
|
class="cn-cell-renderer__swatch-dot"
|
|
142
158
|
:style="{ backgroundColor: swatchColor }"
|
|
143
159
|
aria-hidden="true" />
|
|
144
|
-
<span v-if="hasValue" :title="rawTitle">{{
|
|
160
|
+
<span v-if="hasValue" :title="rawTitle">{{ labelledValue }}</span>
|
|
145
161
|
<span v-else class="cn-cell-renderer__dash">—</span>
|
|
146
162
|
</span>
|
|
147
163
|
</template>
|
|
@@ -153,7 +169,12 @@
|
|
|
153
169
|
|
|
154
170
|
<!-- Date / date-time: dynamic NcDateTime (relative time, absolute on hover) -->
|
|
155
171
|
<template v-else-if="isDate">
|
|
156
|
-
<
|
|
172
|
+
<time
|
|
173
|
+
v-if="dateTimestamp && isBoardLook"
|
|
174
|
+
class="cn-cell-renderer__date"
|
|
175
|
+
:datetime="dateTimestamp.toISOString()"
|
|
176
|
+
:title="absoluteDateLabel">{{ boardDateLabel }}</time>
|
|
177
|
+
<NcDateTime v-else-if="dateTimestamp" :timestamp="dateTimestamp" />
|
|
157
178
|
<span v-else class="cn-cell-renderer__dash">—</span>
|
|
158
179
|
</template>
|
|
159
180
|
|
|
@@ -207,6 +228,8 @@ import { NcAvatar, NcDateTime } from '@nextcloud/vue'
|
|
|
207
228
|
import CheckBold from 'vue-material-design-icons/CheckBold.vue'
|
|
208
229
|
import CnFkResolveCell from '../CnFkResolveCell/CnFkResolveCell.vue'
|
|
209
230
|
import CnGroupNameCell from './CnGroupNameCell.vue'
|
|
231
|
+
import { normalizeLook } from '../../composables/useLook.js'
|
|
232
|
+
import { formatAge, formatBoardDate, resolveAgeVariant } from '../../utils/boardDate.js'
|
|
210
233
|
import { parseDateValue, resolveDateVariant } from '../../utils/dateVariant.js'
|
|
211
234
|
import { safeCurrencyCode } from '../../utils/formatMetric.js'
|
|
212
235
|
import { objectFieldValue } from '../../utils/objectName.js'
|
|
@@ -269,6 +292,12 @@ export default {
|
|
|
269
292
|
* Defaults to identity so standalone use is unaffected.
|
|
270
293
|
*/
|
|
271
294
|
cnTranslate: { default: () => (key) => key },
|
|
295
|
+
/**
|
|
296
|
+
* The look the app is drawn in, provided by CnAppRoot (or a page with
|
|
297
|
+
* `config.look`). Under `board` a date cell reads the board's short
|
|
298
|
+
* form ("5 okt"). Defaults to `nextcloud`, which renders as before.
|
|
299
|
+
*/
|
|
300
|
+
cnLook: { default: 'nextcloud' },
|
|
272
301
|
},
|
|
273
302
|
|
|
274
303
|
props: {
|
|
@@ -323,6 +352,10 @@ export default {
|
|
|
323
352
|
* a date whose colour follows `widgetProps.variantWhen`, rules on the
|
|
324
353
|
* number of days until the date (`[{ op: "lt", value: 0, variant:
|
|
325
354
|
* "error" }, { op: "lte", value: 5, variant: "warning" }]`).
|
|
355
|
+
* The built-in id `"age"` renders how long the row has waited since
|
|
356
|
+
* the date ("4 hours", "3 days"), coloured by `widgetProps.variantWhen`
|
|
357
|
+
* rules on the days it shows (`[{ op: "gte", value: 3, variant:
|
|
358
|
+
* "error" }]`).
|
|
326
359
|
* The built-in id `"group"` shows a Nextcloud group id (or a list of
|
|
327
360
|
* them) as the group's display name; a column whose property is
|
|
328
361
|
* marked `referenceType: "nextcloud-group"` gets it without asking.
|
|
@@ -525,6 +558,69 @@ export default {
|
|
|
525
558
|
return variant === 'default' ? '' : variant
|
|
526
559
|
},
|
|
527
560
|
|
|
561
|
+
/**
|
|
562
|
+
* Whether the app takes the board look (`cnLook` is `board`).
|
|
563
|
+
*
|
|
564
|
+
* @return {boolean}
|
|
565
|
+
* @spec openspec/changes/screens-cell-date-parity/specs/cell-date-age/spec.md#requirement-a-board-date-cell-reads-day-and-short-month-in-the-user-language
|
|
566
|
+
*/
|
|
567
|
+
isBoardLook() {
|
|
568
|
+
return normalizeLook(this.cnLook) === 'board'
|
|
569
|
+
},
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* The board's short date ("5 okt", "14 feb 2024" outside this year).
|
|
573
|
+
*
|
|
574
|
+
* @return {string}
|
|
575
|
+
* @spec openspec/changes/screens-cell-date-parity/specs/cell-date-age/spec.md#requirement-a-board-date-cell-reads-day-and-short-month-in-the-user-language
|
|
576
|
+
*/
|
|
577
|
+
boardDateLabel() {
|
|
578
|
+
return formatBoardDate(this.value)
|
|
579
|
+
},
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* The full date for a tooltip: day, month and year in the user's
|
|
583
|
+
* locale, with the time for a date-time value.
|
|
584
|
+
*
|
|
585
|
+
* @return {string|undefined}
|
|
586
|
+
* @spec openspec/changes/screens-cell-date-parity/specs/cell-date-age/spec.md#requirement-an-age-cell-says-how-long-something-has-waited
|
|
587
|
+
*/
|
|
588
|
+
absoluteDateLabel() {
|
|
589
|
+
const date = parseDateValue(this.value)
|
|
590
|
+
if (date === null) {
|
|
591
|
+
return undefined
|
|
592
|
+
}
|
|
593
|
+
const withTime = this.property?.format === 'date-time' || this.widget === 'age'
|
|
594
|
+
const options = { day: 'numeric', month: 'long', year: 'numeric', ...(withTime ? { hour: '2-digit', minute: '2-digit' } : {}) }
|
|
595
|
+
try {
|
|
596
|
+
return new Intl.DateTimeFormat(getCanonicalLocale() || undefined, options).format(date)
|
|
597
|
+
} catch {
|
|
598
|
+
return new Intl.DateTimeFormat(undefined, options).format(date)
|
|
599
|
+
}
|
|
600
|
+
},
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* `age` widget: how long the row has waited ("4 uur", "3 dagen").
|
|
604
|
+
*
|
|
605
|
+
* @return {string}
|
|
606
|
+
* @spec openspec/changes/screens-cell-date-parity/specs/cell-date-age/spec.md#requirement-an-age-cell-says-how-long-something-has-waited
|
|
607
|
+
*/
|
|
608
|
+
ageLabel() {
|
|
609
|
+
return formatAge(this.value)
|
|
610
|
+
},
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* `age` widget: the variant of the first `widgetProps.variantWhen`
|
|
614
|
+
* rule the shown days match, or '' for none.
|
|
615
|
+
*
|
|
616
|
+
* @return {string}
|
|
617
|
+
* @spec openspec/changes/screens-cell-date-parity/specs/cell-date-age/spec.md#requirement-an-age-cell-turns-red-past-its-threshold
|
|
618
|
+
*/
|
|
619
|
+
ageVariant() {
|
|
620
|
+
const variant = resolveAgeVariant(this.value, this.widgetProps && this.widgetProps.variantWhen)
|
|
621
|
+
return variant === 'default' ? '' : variant
|
|
622
|
+
},
|
|
623
|
+
|
|
528
624
|
/**
|
|
529
625
|
* `date` widget: the date written out in the user's locale.
|
|
530
626
|
*
|
|
@@ -541,6 +637,11 @@ export default {
|
|
|
541
637
|
// 08:30"); `widgetProps.timeOnly: true` shows just the time
|
|
542
638
|
// ("08:30"), for a timetable row. Default: the date alone.
|
|
543
639
|
const props = this.widgetProps || {}
|
|
640
|
+
// The board look writes a plain date in its short form ("5 okt");
|
|
641
|
+
// a time of day keeps the full form below.
|
|
642
|
+
if (this.isBoardLook && props.timeOnly !== true && props.showTime !== true) {
|
|
643
|
+
return formatBoardDate(date)
|
|
644
|
+
}
|
|
544
645
|
const options = props.timeOnly === true
|
|
545
646
|
? { hour: '2-digit', minute: '2-digit' }
|
|
546
647
|
: { day: 'numeric', month: 'short', year: 'numeric', ...(props.showTime === true ? { hour: '2-digit', minute: '2-digit' } : {}) }
|
|
@@ -632,6 +733,43 @@ export default {
|
|
|
632
733
|
.map((gid) => String(gid))
|
|
633
734
|
},
|
|
634
735
|
|
|
736
|
+
/**
|
|
737
|
+
* The text a built-in widget (`badge`, `link`) or a swatch shows. An
|
|
738
|
+
* enum value reads its label the way the plain enum cell does
|
|
739
|
+
* (`enumLabel`: `x-enum-labels`, translated), so a list says "Active"
|
|
740
|
+
* where the detail page does, not the stored "active". A column
|
|
741
|
+
* formatter still wins: an app that shapes the value itself gets
|
|
742
|
+
* exactly what its formatter returns.
|
|
743
|
+
*
|
|
744
|
+
* @return {string}
|
|
745
|
+
* @spec openspec/changes/cell-labels-and-draft-indicator/specs/cell-labels-and-draft-indicator/spec.md#requirement-a-built-in-cell-widget-shows-an-enum-value-by-its-label
|
|
746
|
+
*/
|
|
747
|
+
labelledValue() {
|
|
748
|
+
if (!this.hasFormatter && this.isEnum && this.hasValue && typeof this.value !== 'object') {
|
|
749
|
+
return this.enumLabel
|
|
750
|
+
}
|
|
751
|
+
return String(this.formattedValue)
|
|
752
|
+
},
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* The key the built-in `badge` looks its colour up by: the raw value
|
|
756
|
+
* when `widgetProps.colorMap` has an entry for it (case-insensitive),
|
|
757
|
+
* so a translated label keeps the colour the manifest keyed on the
|
|
758
|
+
* stored code. Otherwise '' and the badge looks up its label, as before,
|
|
759
|
+
* which keeps a map keyed on a formatter's output working.
|
|
760
|
+
*
|
|
761
|
+
* @return {string}
|
|
762
|
+
* @spec openspec/changes/cell-labels-and-draft-indicator/specs/cell-labels-and-draft-indicator/spec.md#requirement-a-built-in-cell-widget-shows-an-enum-value-by-its-label
|
|
763
|
+
*/
|
|
764
|
+
badgeColorKey() {
|
|
765
|
+
const map = this.badgeColorMap
|
|
766
|
+
if (!map || !this.hasValue || typeof this.value === 'object') {
|
|
767
|
+
return ''
|
|
768
|
+
}
|
|
769
|
+
const raw = String(this.value).toLowerCase()
|
|
770
|
+
return Object.keys(map).some((key) => key.toLowerCase() === raw) ? String(this.value) : ''
|
|
771
|
+
},
|
|
772
|
+
|
|
635
773
|
/** Variant for the built-in `badge` widget — `widgetProps.variant` or `'default'`. */
|
|
636
774
|
badgeVariant() {
|
|
637
775
|
return (this.widgetProps && this.widgetProps.variant) || 'default'
|
|
@@ -1087,10 +1225,29 @@ export default {
|
|
|
1087
1225
|
does not rest on colour alone. */
|
|
1088
1226
|
.cn-cell-renderer__date--success,
|
|
1089
1227
|
.cn-cell-renderer__date--warning,
|
|
1090
|
-
.cn-cell-renderer__date--error
|
|
1228
|
+
.cn-cell-renderer__date--error,
|
|
1229
|
+
.cn-cell-renderer__age--success,
|
|
1230
|
+
.cn-cell-renderer__age--warning,
|
|
1231
|
+
.cn-cell-renderer__age--error {
|
|
1091
1232
|
font-weight: 600;
|
|
1092
1233
|
}
|
|
1093
1234
|
|
|
1235
|
+
.cn-cell-renderer__age {
|
|
1236
|
+
white-space: nowrap;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
.cn-cell-renderer__age--success {
|
|
1240
|
+
color: var(--color-text-success, var(--color-success-text));
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
.cn-cell-renderer__age--warning {
|
|
1244
|
+
color: var(--color-text-warning, var(--color-warning-text));
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
.cn-cell-renderer__age--error {
|
|
1248
|
+
color: var(--color-text-error, var(--color-error-text));
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1094
1251
|
.cn-cell-renderer__date--success {
|
|
1095
1252
|
color: var(--color-text-success, var(--color-success-text));
|
|
1096
1253
|
}
|
|
@@ -1103,8 +1260,10 @@ export default {
|
|
|
1103
1260
|
color: var(--color-text-error, var(--color-error-text));
|
|
1104
1261
|
}
|
|
1105
1262
|
|
|
1263
|
+
/* The text variant, not the fill: from Nextcloud 32 `--color-success` is a
|
|
1264
|
+
background colour and too pale for a 16px glyph on a light theme. */
|
|
1106
1265
|
.cn-cell-renderer__icon--success {
|
|
1107
|
-
color: var(--color-success);
|
|
1266
|
+
color: var(--color-text-success, var(--color-success-text, var(--color-success)));
|
|
1108
1267
|
}
|
|
1109
1268
|
|
|
1110
1269
|
.cn-cell-renderer__swatch-wrap {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
:aria-pressed="String(Boolean(activeView && activeView.key === view.key))"
|
|
30
30
|
:data-testid="`cn-chart-widget-view-${view.key}`"
|
|
31
31
|
@click="activeViewKey = view.key">
|
|
32
|
-
{{ view.label
|
|
32
|
+
{{ view.label ? hostTranslate(view.label) : view.key }}
|
|
33
33
|
</button>
|
|
34
34
|
</div>
|
|
35
35
|
<div v-if="showEmptyState" class="cn-chart-widget__empty" data-testid="cn-chart-widget-empty">
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
:height="computedHeight"
|
|
54
54
|
:width="computedWidth"
|
|
55
55
|
:options="mergedOptions"
|
|
56
|
-
:series="
|
|
56
|
+
:series="plottedSeries" />
|
|
57
57
|
</div>
|
|
58
58
|
<div v-else class="cn-chart-widget__fallback">
|
|
59
59
|
<!-- @slot Rendered when the ApexCharts peer dependency is not available (defaults to the unavailableLabel text). -->
|
|
@@ -213,6 +213,11 @@ export default {
|
|
|
213
213
|
* always a ref to inject, even outside a dashboard.
|
|
214
214
|
*/
|
|
215
215
|
cnDashboardDateRange: { default: () => ref(null) },
|
|
216
|
+
/**
|
|
217
|
+
* Host translate function provided by CnAppRoot: manifest-authored
|
|
218
|
+
* view labels and series names are i18n keys (screens-dashboard-i18n).
|
|
219
|
+
*/
|
|
220
|
+
cnTranslate: { default: () => (key) => key },
|
|
216
221
|
},
|
|
217
222
|
|
|
218
223
|
props: {
|
|
@@ -918,6 +923,25 @@ export default {
|
|
|
918
923
|
*
|
|
919
924
|
* @return {Array} The displayed series.
|
|
920
925
|
*/
|
|
926
|
+
/**
|
|
927
|
+
* The displayed series with each series name through the host
|
|
928
|
+
* translate function, so a manifest series named "Revenue" reads in
|
|
929
|
+
* the user's language in the legend and the tooltip. Views still
|
|
930
|
+
* filter on the name as written (`displayedSeries`).
|
|
931
|
+
*
|
|
932
|
+
* @spec openspec/changes/screens-dashboard-i18n/specs/dashboard-page/spec.md#requirement-chart-view-labels-and-series-names-are-translated
|
|
933
|
+
* @return {Array} The series handed to ApexCharts.
|
|
934
|
+
*/
|
|
935
|
+
plottedSeries() {
|
|
936
|
+
const series = this.displayedSeries
|
|
937
|
+
if (!Array.isArray(series)) {
|
|
938
|
+
return series
|
|
939
|
+
}
|
|
940
|
+
return series.map((entry) => (entry && typeof entry === 'object' && typeof entry.name === 'string' && entry.name !== '')
|
|
941
|
+
? { ...entry, name: this.hostTranslate(entry.name) }
|
|
942
|
+
: entry)
|
|
943
|
+
},
|
|
944
|
+
|
|
921
945
|
displayedSeries() {
|
|
922
946
|
const series = this.resolvedSeries
|
|
923
947
|
const view = this.activeView
|
|
@@ -1417,6 +1441,19 @@ export default {
|
|
|
1417
1441
|
},
|
|
1418
1442
|
|
|
1419
1443
|
methods: {
|
|
1444
|
+
/**
|
|
1445
|
+
* A manifest-authored label through the host translate function.
|
|
1446
|
+
*
|
|
1447
|
+
* @spec openspec/changes/screens-dashboard-i18n/specs/dashboard-page/spec.md#requirement-chart-view-labels-and-series-names-are-translated
|
|
1448
|
+
* @param {string} key The label.
|
|
1449
|
+
* @return {string} The translated label.
|
|
1450
|
+
*/
|
|
1451
|
+
hostTranslate(key) {
|
|
1452
|
+
const translate = typeof this.cnTranslate === 'function' ? this.cnTranslate : null
|
|
1453
|
+
const out = translate ? translate(key) : key
|
|
1454
|
+
return (typeof out === 'string' && out !== '') ? out : key
|
|
1455
|
+
},
|
|
1456
|
+
|
|
1420
1457
|
/**
|
|
1421
1458
|
* Re-query the chart's dataSource / endpointSource. Exposed as a
|
|
1422
1459
|
* ref-callable method (B3 canonical refresh mode) AND invoked by the
|