@conduction/nextcloud-vue 2.143.0 → 2.145.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/CnActionDialog/CnActionDialog.vue.js +1 -1
- package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js +7 -2
- package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js +1 -0
- package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue.js +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js +55 -2
- 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/CnAuditTrailWidget/CnAuditTrailWidget.vue.js +1 -1
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue2.js +16 -0
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue3.js +3 -1
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnConversationThread/CnConversationThread.vue.js +1 -1
- package/dist/esm/components/CnConversationThread/CnConversationThread.vue2.js.map +1 -1
- package/dist/esm/components/CnConversationThread/CnConversationThread.vue3.js +1 -1
- package/dist/esm/components/CnConversationThread/CnConversationThread.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue.js +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue2.js +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue3.js +3 -3
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue3.js.map +1 -1
- package/dist/esm/components/CnEventsCard/CnEventsCard.vue.js +1 -1
- package/dist/esm/components/CnEventsCard/CnEventsCard.vue2.js +9 -0
- package/dist/esm/components/CnEventsCard/CnEventsCard.vue2.js.map +1 -1
- package/dist/esm/components/CnEventsCard/CnEventsCard.vue3.js +24 -13
- package/dist/esm/components/CnEventsCard/CnEventsCard.vue3.js.map +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +2 -2
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +2 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +9 -4
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnMailTab/CnMailTab.vue.js +1 -1
- package/dist/esm/components/CnMailTab/CnMailTab.vue2.js.map +1 -1
- package/dist/esm/components/CnMailTab/CnMailTab.vue3.js +2 -2
- package/dist/esm/components/CnMailTab/CnMailTab.vue3.js.map +1 -1
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue.js +1 -1
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue2.js +3 -0
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue2.js.map +1 -1
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue3.js +19 -14
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue3.js.map +1 -1
- package/dist/esm/components/CnNotificationMatrix/CnNotificationMatrix.vue.js +1 -1
- package/dist/esm/components/CnNotificationMatrix/CnNotificationMatrix.vue2.js.map +1 -1
- package/dist/esm/components/CnNotificationMatrix/CnNotificationMatrix.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue2.js +30 -0
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue3.js +158 -102
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +73 -12
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +165 -126
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue.js +1 -1
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue3.js +12 -0
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js +14 -0
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js.map +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js +2 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js.map +1 -1
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue.js +1 -1
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js +110 -2
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js +146 -80
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +13 -8
- 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/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue.js +1 -1
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js +10 -2
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js.map +1 -1
- package/dist/esm/composables/indexSources.js +35 -9
- package/dist/esm/composables/indexSources.js.map +1 -1
- package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue.js +1 -1
- package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue2.js +45 -0
- package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue3.js +67 -34
- package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue.js +1 -1
- package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue2.js +3 -22
- package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/calendar/eventStatus.js +67 -0
- package/dist/esm/integrations/builtin/calendar/eventStatus.js.map +1 -0
- package/dist/esm/integrations/builtin/deck/CnDeckCard.vue.js +1 -1
- package/dist/esm/integrations/builtin/deck/CnDeckCard.vue2.js +39 -0
- package/dist/esm/integrations/builtin/deck/CnDeckCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/deck/CnDeckCard.vue3.js +81 -32
- package/dist/esm/integrations/builtin/deck/CnDeckCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/deck/CnDeckTab.vue.js +1 -1
- package/dist/esm/integrations/builtin/deck/CnDeckTab.vue2.js +5 -6
- package/dist/esm/integrations/builtin/deck/CnDeckTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/deck/CnDeckTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/deck/deckCardParts.js +59 -0
- package/dist/esm/integrations/builtin/deck/deckCardParts.js.map +1 -0
- package/dist/esm/l10n/en.json.js +6 -0
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +8 -0
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +1505 -637
- package/dist/esm/utils/builtInFormatters.js +18 -1
- package/dist/esm/utils/builtInFormatters.js.map +1 -1
- package/dist/esm/utils/fetchFilterCounts.js +5 -2
- package/dist/esm/utils/fetchFilterCounts.js.map +1 -1
- package/dist/esm/utils/localHeaderRows.js +95 -0
- package/dist/esm/utils/localHeaderRows.js.map +1 -0
- package/dist/esm/utils/nextcloudDirectory.js +19 -6
- package/dist/esm/utils/nextcloudDirectory.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +1848 -924
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +1505 -637
- package/l10n/en.json +6 -0
- package/l10n/nl.json +8 -0
- package/package.json +1 -1
- package/src/components/CnActionDialog/CnActionDialog.vue +36 -4
- package/src/components/CnAuditTrailCard/CnAuditTrailCard.vue +55 -2
- package/src/components/CnAuditTrailWidget/CnAuditTrailWidget.vue +18 -0
- package/src/components/CnConversationThread/CnConversationThread.vue +5 -2
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue +2 -1
- package/src/components/CnEventsCard/CnEventsCard.vue +27 -5
- package/src/components/CnFieldListWidget/CnFieldListWidget.vue +2 -2
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +15 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +9 -4
- package/src/components/CnMailTab/CnMailTab.vue +6 -4
- package/src/components/CnNotesCard/CnNotesCard.vue +8 -0
- package/src/components/CnNotificationMatrix/CnNotificationMatrix.vue +4 -1
- package/src/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue +114 -46
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +131 -20
- package/src/components/CnRetentionWidget/CnRetentionWidget.vue +26 -1
- package/src/components/CnSettingsField/CnSettingsField.vue +15 -0
- package/src/components/CnTasksWidget/CnTasksWidget.vue +170 -13
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +13 -8
- package/src/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue +10 -2
- package/src/composables/indexSources.js +35 -9
- package/src/css/dialog.css +25 -10
- package/src/css/kpi-card.css +3 -0
- package/src/css/look-board-detail.css +513 -0
- package/src/css/look-board-index.css +52 -4
- package/src/css/look-board.css +163 -8
- package/src/css/table.css +8 -1
- package/src/integrations/builtin/calendar/CnCalendarCard.vue +76 -11
- package/src/integrations/builtin/calendar/CnCalendarTab.vue +3 -22
- package/src/integrations/builtin/calendar/__tests__/CnCalendarCardBoardRows.spec.js +52 -0
- package/src/integrations/builtin/calendar/eventStatus.js +63 -0
- package/src/integrations/builtin/deck/CnDeckCard.vue +66 -0
- package/src/integrations/builtin/deck/CnDeckTab.vue +5 -6
- package/src/integrations/builtin/deck/__tests__/CnDeckCardBoardRows.spec.js +49 -0
- package/src/integrations/builtin/deck/deckCardParts.js +56 -0
- package/src/utils/builtInFormatters.js +17 -0
- package/src/utils/fetchFilterCounts.js +5 -2
- package/src/utils/localHeaderRows.js +91 -0
- package/src/utils/nextcloudDirectory.js +19 -6
package/l10n/en.json
CHANGED
|
@@ -1706,6 +1706,12 @@
|
|
|
1706
1706
|
"expires {date}": "expires {date}",
|
|
1707
1707
|
"Loading …": "Loading …",
|
|
1708
1708
|
"Reorder {item}: drag, or press the up and down arrow keys": "Reorder {item}: drag, or press the up and down arrow keys",
|
|
1709
|
+
"Board {name}": "Board {name}",
|
|
1710
|
+
"list {name}": "list {name}",
|
|
1711
|
+
"Tentative": "Tentative",
|
|
1712
|
+
"Confirmed": "Confirmed",
|
|
1713
|
+
"Cancelled": "Cancelled",
|
|
1714
|
+
"{start} until {end}": "{start} until {end}",
|
|
1709
1715
|
"No contacts linked": "No contacts linked",
|
|
1710
1716
|
"No relations yet": "No relations yet",
|
|
1711
1717
|
"Period": "Period",
|
package/l10n/nl.json
CHANGED
|
@@ -1919,6 +1919,12 @@
|
|
|
1919
1919
|
"Made {date}": "Gemaakt {date}",
|
|
1920
1920
|
"expires {date}": "verloopt {date}",
|
|
1921
1921
|
"Reorder {item}: drag, or press the up and down arrow keys": "{item} verplaatsen: slepen, of de pijltoetsen omhoog en omlaag",
|
|
1922
|
+
"Board {name}": "Bord {name}",
|
|
1923
|
+
"list {name}": "lijst {name}",
|
|
1924
|
+
"Tentative": "Voorlopig",
|
|
1925
|
+
"Confirmed": "Bevestigd",
|
|
1926
|
+
"Cancelled": "Geannuleerd",
|
|
1927
|
+
"{start} until {end}": "{start} tot {end}",
|
|
1922
1928
|
"No contacts linked": "Geen contacten gekoppeld",
|
|
1923
1929
|
"No relations yet": "Nog geen relaties",
|
|
1924
1930
|
"Period": "Periode",
|
|
@@ -1940,6 +1946,8 @@
|
|
|
1940
1946
|
"Absent today": "Vandaag afwezig",
|
|
1941
1947
|
"{message} until {time}": "{message} tot {time}",
|
|
1942
1948
|
"Away": "Afwezig",
|
|
1949
|
+
"Present": "Aanwezig",
|
|
1950
|
+
"Absent until {date}": "Afwezig tot {date}",
|
|
1943
1951
|
"Busy": "Bezet",
|
|
1944
1952
|
"No one in the team": "Niemand in het team",
|
|
1945
1953
|
"Also replace the criteria with the current filters": "Vervang ook de criteria door de huidige filters",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@conduction/nextcloud-vue",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.145.0",
|
|
4
4
|
"description": "Shared Vue component library for Conduction Nextcloud apps — complements @nextcloud/vue with higher-level components, OpenRegister integration, and NL Design System support",
|
|
5
5
|
"homepage": "https://github.com/ConductionNL/nextcloud-vue#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
:heading="text(config.note.title)"
|
|
146
146
|
data-testid="cn-action-dialog-note">
|
|
147
147
|
<template v-if="config.note.icon" #icon>
|
|
148
|
-
<CnIcon :name="config.note.icon" :size="20" />
|
|
148
|
+
<CnIcon class="cn-action-dialog__note-icon" :name="config.note.icon" :size="20" />
|
|
149
149
|
</template>
|
|
150
150
|
{{ text(config.note.text) }}
|
|
151
151
|
</NcNoteCard>
|
|
@@ -191,6 +191,7 @@ import CircleOutline from 'vue-material-design-icons/CircleOutline.vue'
|
|
|
191
191
|
import HelpCircleOutline from 'vue-material-design-icons/HelpCircleOutline.vue'
|
|
192
192
|
import CnFormField from '../CnFormField/CnFormField.vue'
|
|
193
193
|
import { fetchEndpointSource, interpolateUrlTokens } from '../../composables/useEndpointSource.js'
|
|
194
|
+
import { BUILT_IN_FORMATTERS } from '../../utils/builtInFormatters.js'
|
|
194
195
|
import { fillTemplate } from '../../utils/fillTemplate.js'
|
|
195
196
|
import { readPath } from '../../utils/readPath.js'
|
|
196
197
|
import { CnDialog } from '../CnDialog/index.js'
|
|
@@ -219,7 +220,8 @@ let reasonSeq = 0
|
|
|
219
220
|
* `eyebrow` a template filled from the record ("Close off · {identifier}").
|
|
220
221
|
* - `summary`: `{ source?, title, meta?, badge?, icon? }`: templates filled from
|
|
221
222
|
* the record (`source` an endpointSource to read it from, else `object`).
|
|
222
|
-
* - `facts`: `[{ title?, items: [{ label, value }] }]`, `value` a template
|
|
223
|
+
* - `facts`: `[{ title?, items: [{ label, value }] }]`, `value` a template; a
|
|
224
|
+
* `{path|<formatter>}` token reads through the built-in and app formatters.
|
|
223
225
|
* - `checklist`: `{ title?, source, itemsPath?, labels?, required? }`: items
|
|
224
226
|
* `{ id, met, label?, detail? }` read from `source`; `labels[id]` gives an
|
|
225
227
|
* item's `{ label, detail?, unmetDetail? }`; the ids in `required` must be
|
|
@@ -262,6 +264,8 @@ export default {
|
|
|
262
264
|
cnTranslate: { default: () => (key) => key },
|
|
263
265
|
/** The page's pre-bound action dispatcher (CnPageRenderer), for `confirm.action`. */
|
|
264
266
|
cnDispatchAction: { default: null },
|
|
267
|
+
/** The app's named formatters (CnAppRoot), for `{path|<formatter>}` in a template. */
|
|
268
|
+
cnFormatters: { default: () => ({}) },
|
|
265
269
|
},
|
|
266
270
|
|
|
267
271
|
props: {
|
|
@@ -594,7 +598,8 @@ export default {
|
|
|
594
598
|
if (typeof template !== 'string' || template === '') {
|
|
595
599
|
return ''
|
|
596
600
|
}
|
|
597
|
-
|
|
601
|
+
const formatters = { ...BUILT_IN_FORMATTERS, ...(this.cnFormatters || {}) }
|
|
602
|
+
return fillTemplate(this.cnTranslate(template), row || this.record || {}, new Date(), { formatters }).trim()
|
|
598
603
|
},
|
|
599
604
|
|
|
600
605
|
/**
|
|
@@ -836,6 +841,7 @@ export default {
|
|
|
836
841
|
.cn-action-dialog__summary-text strong {
|
|
837
842
|
font-size: 15px;
|
|
838
843
|
font-weight: 600;
|
|
844
|
+
line-height: 1.2;
|
|
839
845
|
}
|
|
840
846
|
|
|
841
847
|
.cn-action-dialog__summary-text .cn-action-dialog__muted {
|
|
@@ -945,11 +951,36 @@ export default {
|
|
|
945
951
|
|
|
946
952
|
/* A checkbox field is a tinted box with a 2px edge, its label bold and its
|
|
947
953
|
hint under it (DqArchiveren). */
|
|
954
|
+
/* A note's own icon stands on the heading's line, as the variant's icon
|
|
955
|
+
does (NcNoteCard centres a slotted icon on the whole note). */
|
|
956
|
+
.cn-action-dialog__note-icon {
|
|
957
|
+
align-self: flex-start;
|
|
958
|
+
margin-top: 1px;
|
|
959
|
+
}
|
|
960
|
+
|
|
948
961
|
.cn-action-dialog__checkbox {
|
|
949
962
|
padding: 12px 14px;
|
|
950
963
|
border: 2px solid var(--color-primary-element);
|
|
951
964
|
border-radius: var(--border-radius-element, 8px);
|
|
952
|
-
background: var(--color-
|
|
965
|
+
background: var(--color-main-background);
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
/* The box sits at the card's inset, 12px before the label, the label on
|
|
969
|
+
its first line (DqArchiveren "Sanne de Vries laten weten ..."):
|
|
970
|
+
NcCheckboxRadioSwitch pads its row and centres a 34px target. */
|
|
971
|
+
.cn-action-dialog__checkbox :deep(.checkbox-content) {
|
|
972
|
+
padding: 0;
|
|
973
|
+
gap: 12px;
|
|
974
|
+
align-items: flex-start;
|
|
975
|
+
min-height: 0;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
.cn-action-dialog__checkbox :deep(.checkbox-content__icon) {
|
|
979
|
+
margin: 0;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
.cn-action-dialog__checkbox :deep(.checkbox-radio-switch__input) {
|
|
983
|
+
min-height: 0;
|
|
953
984
|
}
|
|
954
985
|
|
|
955
986
|
.cn-action-dialog__checkbox-text {
|
|
@@ -961,6 +992,7 @@ export default {
|
|
|
961
992
|
.cn-action-dialog__checkbox-label {
|
|
962
993
|
font-size: 15px;
|
|
963
994
|
font-weight: 600;
|
|
995
|
+
line-height: 1.2;
|
|
964
996
|
}
|
|
965
997
|
|
|
966
998
|
.cn-action-dialog__checkbox .cn-action-dialog__muted {
|
|
@@ -69,9 +69,21 @@ import CnDetailCard from '../CnDetailCard/CnDetailCard.vue'
|
|
|
69
69
|
import { formatBoardDate, formatTimeOfDay } from '../../utils/boardDate.js'
|
|
70
70
|
import { buildHeaders, prefixUrl } from '../../utils/index.js'
|
|
71
71
|
import { leafSourceUrl } from '../../utils/leafSourceUrl.js'
|
|
72
|
+
import { readPath } from '../../utils/readPath.js'
|
|
72
73
|
import { userDisplayName } from '../../utils/userDisplayName.js'
|
|
73
74
|
import { userLocale } from '../../utils/userLocale.js'
|
|
74
75
|
|
|
76
|
+
/**
|
|
77
|
+
* A changed value as an entry records it: OpenRegister writes `{ old, new }`,
|
|
78
|
+
* other sources the value itself.
|
|
79
|
+
*
|
|
80
|
+
* @param {unknown} value The recorded change.
|
|
81
|
+
* @return {unknown} The value it changed to.
|
|
82
|
+
*/
|
|
83
|
+
function newValueOf(value) {
|
|
84
|
+
return value !== null && typeof value === 'object' && Object.hasOwn(value, 'new') ? value.new : value
|
|
85
|
+
}
|
|
86
|
+
|
|
75
87
|
/**
|
|
76
88
|
* @param {object} entry An audit entry.
|
|
77
89
|
* @return {number} When it happened, in ms; 0 when unreadable.
|
|
@@ -202,6 +214,18 @@ export default {
|
|
|
202
214
|
* @type {{[key: string]: {[value: string]: string}}|null}
|
|
203
215
|
*/
|
|
204
216
|
valueLabels: { type: Object, default: null },
|
|
217
|
+
/**
|
|
218
|
+
* What happened, in words, by the field an entry changed: rules
|
|
219
|
+
* `[{ action?, field, to?, label }]`, the first whose `field` the entry
|
|
220
|
+
* changed (to `to`, when given) wins over `actionLabels`. A label fills
|
|
221
|
+
* the same tokens, plus `{object.<path>}` from `object`
|
|
222
|
+
* ("Version {object.version} published" for `isDraft` set to false).
|
|
223
|
+
*
|
|
224
|
+
* @type {Array<{action?: string, field: string, to?: unknown, label: string}>}
|
|
225
|
+
*/
|
|
226
|
+
changeLabels: { type: Array, default: () => [] },
|
|
227
|
+
/** The audited record, for `{object.<path>}` in a label; null without one. */
|
|
228
|
+
object: { type: Object, default: null },
|
|
205
229
|
/**
|
|
206
230
|
* Records beside the object whose events belong in its history:
|
|
207
231
|
* `[{ as, register, schema, filter, limit? }]`. The card lists the
|
|
@@ -394,12 +418,16 @@ export default {
|
|
|
394
418
|
* @return {string} The line.
|
|
395
419
|
*/
|
|
396
420
|
formatAction(entry) {
|
|
397
|
-
const label = this.labelFor(entry)
|
|
421
|
+
const label = this.changeLabelFor(entry) ?? this.labelFor(entry)
|
|
398
422
|
if (label !== null) {
|
|
399
423
|
return label
|
|
400
424
|
.replace('{actor}', this.actorName(entry))
|
|
401
425
|
.replace('{state}', entry.stateAfter || '')
|
|
402
426
|
.replace(/\{changed\.([\w-]+)\}/g, (match, key) => this.changedValue(entry, key))
|
|
427
|
+
.replace(/\{object\.([\w.-]+)\}/g, (match, path) => {
|
|
428
|
+
const value = this.object ? readPath(this.object, path) : undefined
|
|
429
|
+
return value === null || value === undefined || typeof value === 'object' ? '' : String(value)
|
|
430
|
+
})
|
|
403
431
|
}
|
|
404
432
|
const action = entry.action || entry.event || this.actionLabel
|
|
405
433
|
return entry.stateAfter ? `${action} (${entry.stateAfter})` : action
|
|
@@ -416,7 +444,7 @@ export default {
|
|
|
416
444
|
*/
|
|
417
445
|
changedValue(entry, key) {
|
|
418
446
|
const changed = entry && typeof entry.changed === 'object' && entry.changed !== null ? entry.changed : {}
|
|
419
|
-
const value = changed[key]
|
|
447
|
+
const value = newValueOf(changed[key])
|
|
420
448
|
if (value === null || value === undefined || typeof value === 'object') {
|
|
421
449
|
return ''
|
|
422
450
|
}
|
|
@@ -424,6 +452,31 @@ export default {
|
|
|
424
452
|
return words && typeof words[value] === 'string' ? words[value] : String(value)
|
|
425
453
|
},
|
|
426
454
|
|
|
455
|
+
/**
|
|
456
|
+
* The `changeLabels` rule an entry matches: the first whose field the
|
|
457
|
+
* entry changed, for its action and to its value when the rule names them.
|
|
458
|
+
*
|
|
459
|
+
* @param {object} entry The entry.
|
|
460
|
+
* @return {string|null} The label, or null when no rule matches.
|
|
461
|
+
*/
|
|
462
|
+
changeLabelFor(entry) {
|
|
463
|
+
const changed = entry && typeof entry.changed === 'object' && entry.changed !== null ? entry.changed : {}
|
|
464
|
+
const action = entry.action || entry.event || ''
|
|
465
|
+
for (const rule of Array.isArray(this.changeLabels) ? this.changeLabels : []) {
|
|
466
|
+
if (!rule || typeof rule.label !== 'string' || rule.label === '' || typeof rule.field !== 'string' || !Object.hasOwn(changed, rule.field)) {
|
|
467
|
+
continue
|
|
468
|
+
}
|
|
469
|
+
if (rule.action && rule.action !== action) {
|
|
470
|
+
continue
|
|
471
|
+
}
|
|
472
|
+
if (Object.hasOwn(rule, 'to') && String(newValueOf(changed[rule.field])) !== String(rule.to)) {
|
|
473
|
+
continue
|
|
474
|
+
}
|
|
475
|
+
return rule.label
|
|
476
|
+
}
|
|
477
|
+
return null
|
|
478
|
+
},
|
|
479
|
+
|
|
427
480
|
/**
|
|
428
481
|
* The `actionLabels` entry for an entry: by action and state first,
|
|
429
482
|
* then by action.
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
:excludeActions="resolvedExcludeActions"
|
|
21
21
|
:actionLabels="actionLabels"
|
|
22
22
|
:valueLabels="valueLabels"
|
|
23
|
+
:changeLabels="changeLabels"
|
|
24
|
+
:object="ctx.object || ctx.objectData || null"
|
|
23
25
|
:relatedSources="relatedSources"
|
|
24
26
|
:footnote="footnote"
|
|
25
27
|
v-bind="emptyText ? { noEntriesLabel: emptyText } : {}" />
|
|
@@ -193,6 +195,22 @@ export default {
|
|
|
193
195
|
.map(([key, text]) => [key, translate(text)]))
|
|
194
196
|
},
|
|
195
197
|
|
|
198
|
+
/**
|
|
199
|
+
* `content.changeLabels`, each rule's label through the app's translate.
|
|
200
|
+
*
|
|
201
|
+
* @return {Array<object>}
|
|
202
|
+
*/
|
|
203
|
+
changeLabels() {
|
|
204
|
+
const rules = this.content.changeLabels
|
|
205
|
+
if (!Array.isArray(rules)) {
|
|
206
|
+
return []
|
|
207
|
+
}
|
|
208
|
+
const translate = typeof this.cnTranslate === 'function' ? this.cnTranslate : (text) => text
|
|
209
|
+
return rules
|
|
210
|
+
.filter((rule) => rule && typeof rule.label === 'string' && rule.label !== '')
|
|
211
|
+
.map((rule) => ({ ...rule, label: translate(rule.label) }))
|
|
212
|
+
},
|
|
213
|
+
|
|
196
214
|
/**
|
|
197
215
|
* `content.footnote`, a muted line under the trail with the record's
|
|
198
216
|
* fields filled in ("Reference {identifier}"); '' when a field is empty.
|
|
@@ -17,9 +17,11 @@
|
|
|
17
17
|
class="cn-conversation-thread__title">
|
|
18
18
|
{{ title }}
|
|
19
19
|
</component>
|
|
20
|
-
<p
|
|
20
|
+
<!-- A div, not a <p>: a theme that sets every paragraph's size with
|
|
21
|
+
!important would otherwise override the 14px subtitle. -->
|
|
22
|
+
<div v-if="subtitle" class="cn-conversation-thread__subtitle" data-testid="cn-conversation-subtitle">
|
|
21
23
|
{{ subtitle }}
|
|
22
|
-
</
|
|
24
|
+
</div>
|
|
23
25
|
</div>
|
|
24
26
|
<div v-if="$slots['header-actions']" class="cn-conversation-thread__header-actions">
|
|
25
27
|
<!-- @slot header-actions Buttons beside the title, for example "Log contact". -->
|
|
@@ -633,6 +635,7 @@ export default {
|
|
|
633
635
|
.cn-conversation-thread__subtitle {
|
|
634
636
|
color: var(--color-text-maxcontrast);
|
|
635
637
|
font-size: 14px;
|
|
638
|
+
line-height: normal;
|
|
636
639
|
margin: 0;
|
|
637
640
|
}
|
|
638
641
|
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
v-else
|
|
32
32
|
type="button"
|
|
33
33
|
class="cn-detail-page__catalog-action"
|
|
34
|
+
:class="{ 'cn-detail-page__catalog-action--add': action.add === true }"
|
|
34
35
|
data-testid="cn-detail-widget-header-action"
|
|
35
36
|
@click="action.run()">
|
|
36
37
|
<CnIcon v-if="action.icon" :name="action.icon" :size="16" />
|
|
@@ -56,7 +57,7 @@ export default {
|
|
|
56
57
|
components: { CnIcon, CnStatusBadge, NcButton },
|
|
57
58
|
|
|
58
59
|
props: {
|
|
59
|
-
/** The reported header: `{ pill, note, actions: [{ label, icon?, variant?, run }] }
|
|
60
|
+
/** The reported header: `{ pill, note, actions: [{ label, icon?, variant?, add?, run }] }`; `add: true` marks a list's Add. */
|
|
60
61
|
header: {
|
|
61
62
|
type: Object,
|
|
62
63
|
required: true,
|
|
@@ -28,9 +28,12 @@
|
|
|
28
28
|
:key="keyOf(event, index)"
|
|
29
29
|
class="cn-events-card__event"
|
|
30
30
|
data-testid="cn-events-card-event">
|
|
31
|
-
<span class="cn-events-
|
|
32
|
-
<span class="cn-events-
|
|
33
|
-
|
|
31
|
+
<span v-if="dayOf(event)" class="cn-events-card__day" aria-hidden="true">{{ dayOf(event) }}</span>
|
|
32
|
+
<span class="cn-events-card__text">
|
|
33
|
+
<span class="cn-events-card__summary">{{ summaryOf(event) }}</span>
|
|
34
|
+
<span class="cn-events-card__when">{{ whenOf(event) }}</span>
|
|
35
|
+
<span v-if="event.location" class="cn-events-card__where">{{ event.location }}</span>
|
|
36
|
+
</span>
|
|
34
37
|
</li>
|
|
35
38
|
</ul>
|
|
36
39
|
<p v-else class="cn-events-card__muted" data-testid="cn-events-card-empty">
|
|
@@ -292,6 +295,15 @@ export default {
|
|
|
292
295
|
return summary === '' ? t('nextcloud-vue', 'Appointment') : summary
|
|
293
296
|
},
|
|
294
297
|
|
|
298
|
+
/**
|
|
299
|
+
* @param {object} event The event.
|
|
300
|
+
* @return {string} The day of the month it starts on, '' when it has no readable start.
|
|
301
|
+
*/
|
|
302
|
+
dayOf(event) {
|
|
303
|
+
const parsed = new Date(String(event?.dtstart ?? '').trim())
|
|
304
|
+
return Number.isNaN(parsed.getTime()) ? '' : String(parsed.getDate())
|
|
305
|
+
},
|
|
306
|
+
|
|
295
307
|
/**
|
|
296
308
|
* @param {object} event The event.
|
|
297
309
|
* @return {string} When it is: its start and end, or whichever it has.
|
|
@@ -333,8 +345,7 @@ function formatMoment(value) {
|
|
|
333
345
|
|
|
334
346
|
.cn-events-card__event {
|
|
335
347
|
display: flex;
|
|
336
|
-
|
|
337
|
-
gap: 2px;
|
|
348
|
+
gap: 12px;
|
|
338
349
|
padding-bottom: 8px;
|
|
339
350
|
border-bottom: 1px solid var(--color-border);
|
|
340
351
|
}
|
|
@@ -344,6 +355,17 @@ function formatMoment(value) {
|
|
|
344
355
|
border-bottom: none;
|
|
345
356
|
}
|
|
346
357
|
|
|
358
|
+
.cn-events-card__day {
|
|
359
|
+
display: none;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.cn-events-card__text {
|
|
363
|
+
display: flex;
|
|
364
|
+
flex-direction: column;
|
|
365
|
+
gap: 2px;
|
|
366
|
+
min-width: 0;
|
|
367
|
+
}
|
|
368
|
+
|
|
347
369
|
.cn-events-card__summary {
|
|
348
370
|
font-weight: 600;
|
|
349
371
|
}
|
|
@@ -607,7 +607,7 @@ export default {
|
|
|
607
607
|
/**
|
|
608
608
|
* The card title row's actions: the add button with `add.placement: "title"`.
|
|
609
609
|
*
|
|
610
|
-
* @return {Array<{label: string, icon: string, run: () => void}>} The actions.
|
|
610
|
+
* @return {Array<{label: string, icon: string, add: boolean, run: () => void}>} The actions.
|
|
611
611
|
*/
|
|
612
612
|
titleActions() {
|
|
613
613
|
if (!(this.canAdd && this.addTrigger && this.addPlacement === 'title')) {
|
|
@@ -616,7 +616,7 @@ export default {
|
|
|
616
616
|
const run = () => {
|
|
617
617
|
this.adding = !this.adding
|
|
618
618
|
}
|
|
619
|
-
return [{ label: this.addLabel, icon: 'Plus', run }]
|
|
619
|
+
return [{ label: this.addLabel, icon: 'Plus', add: true, run }]
|
|
620
620
|
},
|
|
621
621
|
|
|
622
622
|
addLabel() {
|
|
@@ -2178,7 +2178,8 @@ export default {
|
|
|
2178
2178
|
const object = {
|
|
2179
2179
|
...entry,
|
|
2180
2180
|
name: node.basename,
|
|
2181
|
-
|
|
2181
|
+
// A template drops an object value, so the Date is handed over as ISO text.
|
|
2182
|
+
modified: node.mtime instanceof Date ? node.mtime.toISOString() : node.mtime,
|
|
2182
2183
|
size: this.formatSize(node.size),
|
|
2183
2184
|
type: this.typeLabelOf(node),
|
|
2184
2185
|
...(owner ? { owner } : {}),
|
|
@@ -3648,6 +3649,19 @@ export default {
|
|
|
3648
3649
|
width: auto;
|
|
3649
3650
|
}
|
|
3650
3651
|
|
|
3652
|
+
/* The row button and the row menu stand side by side on one line, not
|
|
3653
|
+
stacked (DqZaakDocumenten: Beoordelen, then the menu, 14px apart).
|
|
3654
|
+
@spec openspec/changes/files-row-button-beside-menu/specs/files-row-button-beside-menu/spec.md#requirement-a-files-row-button-stands-beside-the-row-menu */
|
|
3655
|
+
.cn-files-browser__col-actions > .cn-files-browser__row-button,
|
|
3656
|
+
.cn-files-browser__col-actions > .cn-files-browser__row-menu {
|
|
3657
|
+
display: inline-flex;
|
|
3658
|
+
vertical-align: middle;
|
|
3659
|
+
}
|
|
3660
|
+
|
|
3661
|
+
.cn-files-browser__col-actions > .cn-files-browser__row-button + .cn-files-browser__row-menu {
|
|
3662
|
+
margin-inline-start: 14px;
|
|
3663
|
+
}
|
|
3664
|
+
|
|
3651
3665
|
.cn-files-browser__col-name {
|
|
3652
3666
|
min-width: 0;
|
|
3653
3667
|
}
|
|
@@ -8940,7 +8940,7 @@ export default {
|
|
|
8940
8940
|
// through the app's label lookup.
|
|
8941
8941
|
const countText = this.presentedCountText
|
|
8942
8942
|
// The note after the breadcrumb already says how many there are.
|
|
8943
|
-
if (!countText && !this.countSubtitle && this.headerMetaCarriesCount) {
|
|
8943
|
+
if (!countText && !this.countSubtitle && (this.headerMetaCarriesCount || this.showCount === false)) {
|
|
8944
8944
|
return this.description
|
|
8945
8945
|
}
|
|
8946
8946
|
if (!countText && !this.countSubtitle) {
|
|
@@ -9877,9 +9877,12 @@ export default {
|
|
|
9877
9877
|
}
|
|
9878
9878
|
const sorted = [...groups].sort((a, b) => b.count - a.count)
|
|
9879
9879
|
const total = sorted.reduce((sum, g) => sum + g.count, 0)
|
|
9880
|
+
// Each tab asks to be counted as the list counts it (within the
|
|
9881
|
+
// active filters, through the list endpoint); the grouped number,
|
|
9882
|
+
// over the page filter only, stands until that count arrives.
|
|
9880
9883
|
this.generatedQuickFilters = [
|
|
9881
|
-
{ label: from.allLabel || t('nextcloud-vue', 'All'), filter: {}, default: true, count: total },
|
|
9882
|
-
...sorted.map((g) => ({ label: (labels && labels[g.key]) || g.key, filter: { [from.field]: g.key }, count: g.count })),
|
|
9884
|
+
{ label: from.allLabel || t('nextcloud-vue', 'All'), filter: {}, default: true, count: total, showCount: true },
|
|
9885
|
+
...sorted.map((g) => ({ label: (labels && labels[g.key]) || g.key, filter: { [from.field]: g.key }, count: g.count, showCount: true })),
|
|
9883
9886
|
]
|
|
9884
9887
|
},
|
|
9885
9888
|
|
|
@@ -9993,7 +9996,7 @@ export default {
|
|
|
9993
9996
|
]
|
|
9994
9997
|
let counts
|
|
9995
9998
|
try {
|
|
9996
|
-
counts = await fetchFilterCounts({ register: this.register, schema, entries, baseFilter: base, ctx })
|
|
9999
|
+
counts = await fetchFilterCounts({ register: this.register, schema, entries, baseFilter: base, ctx, via: 'list' })
|
|
9997
10000
|
} catch {
|
|
9998
10001
|
counts = {}
|
|
9999
10002
|
}
|
|
@@ -10050,6 +10053,8 @@ export default {
|
|
|
10050
10053
|
})),
|
|
10051
10054
|
baseFilter: resolveFilterMap(this.filter, params, ctx),
|
|
10052
10055
|
ctx,
|
|
10056
|
+
// The chips count what the list shows: the list's own request.
|
|
10057
|
+
via: 'list',
|
|
10053
10058
|
})
|
|
10054
10059
|
if (requestKey !== this.countRequestKey) {
|
|
10055
10060
|
return
|
|
@@ -19,9 +19,11 @@
|
|
|
19
19
|
<h3 v-if="heading" class="cn-mail-tab__title">
|
|
20
20
|
{{ heading }}
|
|
21
21
|
</h3>
|
|
22
|
-
<p
|
|
22
|
+
<!-- Divs, not <p>: a theme that sizes every paragraph with !important
|
|
23
|
+
would override the card's 14px description. -->
|
|
24
|
+
<div v-if="description" class="cn-mail-tab__subtitle">
|
|
23
25
|
{{ description }}
|
|
24
|
-
</
|
|
26
|
+
</div>
|
|
25
27
|
</div>
|
|
26
28
|
<div v-if="hasHeaderActions" class="cn-mail-tab__header-actions">
|
|
27
29
|
<NcButton
|
|
@@ -77,9 +79,9 @@
|
|
|
77
79
|
{{ t('nextcloud-vue', 'Empty draft') }}
|
|
78
80
|
</NcButton>
|
|
79
81
|
</div>
|
|
80
|
-
<
|
|
82
|
+
<div v-if="hint" class="cn-mail-tab__hint">
|
|
81
83
|
{{ hint }}
|
|
82
|
-
</
|
|
84
|
+
</div>
|
|
83
85
|
|
|
84
86
|
<NcNoteCard
|
|
85
87
|
v-if="error"
|
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
:key="row.note.id"
|
|
97
97
|
class="cn-notes-card__note"
|
|
98
98
|
:class="{ 'cn-notes-card__note--reply': row.isReply }">
|
|
99
|
+
<span class="cn-notes-card__initials" aria-hidden="true">{{ initialsOf(getNoteAuthorName(row.note)) }}</span>
|
|
99
100
|
<div class="cn-notes-card__note-header">
|
|
100
101
|
<CnUserActionMenu
|
|
101
102
|
v-if="!isCurrentUser(row.note)"
|
|
@@ -175,6 +176,7 @@ import CnUserActionMenu from '../CnUserActionMenu/CnUserActionMenu.vue'
|
|
|
175
176
|
import CnVisibilityChip from '../CnVisibilityChip/CnVisibilityChip.vue'
|
|
176
177
|
import { useFileComments } from '../../composables/useFileComments.js'
|
|
177
178
|
import { buildHeaders, prefixUrl } from '../../utils/index.js'
|
|
179
|
+
import { initialsOf } from '../../utils/initials.js'
|
|
178
180
|
import { leafSourceUrl } from '../../utils/leafSourceUrl.js'
|
|
179
181
|
import { extractMentionedGroupIds, extractMentionedIds } from '../../utils/mentions.js'
|
|
180
182
|
import { quoteFor, supportsReplies, threadNotes, threadRootId } from '../../utils/noteThreads.js'
|
|
@@ -635,6 +637,8 @@ export default {
|
|
|
635
637
|
return note.actorId || note.author || ''
|
|
636
638
|
},
|
|
637
639
|
|
|
640
|
+
initialsOf,
|
|
641
|
+
|
|
638
642
|
getNoteAuthorName(note) {
|
|
639
643
|
return note.actorDisplayName || note.author || 'Unknown'
|
|
640
644
|
},
|
|
@@ -870,6 +874,10 @@ export default {
|
|
|
870
874
|
border-bottom: none;
|
|
871
875
|
}
|
|
872
876
|
|
|
877
|
+
.cn-notes-card__initials {
|
|
878
|
+
display: none;
|
|
879
|
+
}
|
|
880
|
+
|
|
873
881
|
.cn-notes-card__note-header {
|
|
874
882
|
display: flex;
|
|
875
883
|
justify-content: space-between;
|
|
@@ -1135,7 +1135,10 @@ export default {
|
|
|
1135
1135
|
min-inline-size: 20px;
|
|
1136
1136
|
block-size: 20px;
|
|
1137
1137
|
min-block-size: 20px;
|
|
1138
|
-
|
|
1138
|
+
/* A block box, so the line's baseline adds no height: the row is
|
|
1139
|
+
42px as on the board (10px, the 1px-low checkbox, 10px, the rule). */
|
|
1140
|
+
display: block;
|
|
1141
|
+
margin: 1px auto 0;
|
|
1139
1142
|
}
|
|
1140
1143
|
|
|
1141
1144
|
.cn-notification-matrix__group {
|