@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
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
-->
|
|
5
5
|
|
|
6
6
|
<template>
|
|
7
|
-
<div class="cn-object-parties" data-testid="cn-object-parties">
|
|
7
|
+
<div class="cn-object-parties" :class="{ 'cn-object-parties--board': isBoard }" data-testid="cn-object-parties">
|
|
8
8
|
<div v-if="canAdd" class="cn-object-parties__manage">
|
|
9
9
|
<NcButton data-testid="cn-object-parties-add" @click="adding = true">
|
|
10
10
|
<template #icon>
|
|
@@ -112,51 +112,89 @@
|
|
|
112
112
|
class="cn-object-parties__party"
|
|
113
113
|
:data-party="party.partyUuid || party.contactUid"
|
|
114
114
|
data-testid="cn-object-parties-party">
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
115
|
+
<!-- The board look draws a party as one ruled row (DqZaakBetrokkenen
|
|
116
|
+
"Rollen"): an initials tile, the name over one meta line that
|
|
117
|
+
names the role, the pills at the end. -->
|
|
118
|
+
<template v-if="isBoard">
|
|
119
|
+
<span class="cn-object-parties__tile" aria-hidden="true">{{ initialsOf(nameOf(party)) }}</span>
|
|
120
|
+
<span class="cn-object-parties__text">
|
|
121
|
+
<span class="cn-object-parties__name">{{ nameOf(party) }}</span>
|
|
122
|
+
<span class="cn-object-parties__meta" data-testid="cn-object-parties-meta">{{ boardMetaOf(party, group) }}</span>
|
|
123
|
+
</span>
|
|
124
|
+
<span class="cn-object-parties__end">
|
|
125
|
+
<span
|
|
126
|
+
v-if="notAccepted(party)"
|
|
127
|
+
class="cn-status-badge cn-status-badge--warning"
|
|
128
|
+
data-testid="cn-object-parties-not-accepted">{{ label('notAccepted') }}</span>
|
|
129
|
+
<span
|
|
130
|
+
v-for="indicator in indicatorsFor(party)"
|
|
131
|
+
:key="`${party.partyUuid}-${indicator.key}`"
|
|
132
|
+
class="cn-status-badge cn-status-badge--default"
|
|
133
|
+
:class="`cn-object-parties__indicator--${indicator.severity}`"
|
|
134
|
+
:data-effect="indicator.effect"
|
|
135
|
+
:title="indicator.verdict"
|
|
136
|
+
data-testid="cn-object-parties-indicator">{{ indicator.label }}</span>
|
|
137
|
+
<NcButton
|
|
138
|
+
v-if="canRemove && party.partyUuid"
|
|
139
|
+
class="cn-object-parties__remove"
|
|
140
|
+
variant="tertiary"
|
|
141
|
+
:aria-label="removeLabel(party, group)"
|
|
142
|
+
:title="removeLabel(party, group)"
|
|
143
|
+
data-testid="cn-object-parties-remove"
|
|
144
|
+
@click="removing = { party, group }">
|
|
145
|
+
<template #icon>
|
|
146
|
+
<TrashCanOutline :size="20" />
|
|
147
|
+
</template>
|
|
148
|
+
</NcButton>
|
|
149
|
+
</span>
|
|
150
|
+
</template>
|
|
151
|
+
<template v-else>
|
|
152
|
+
<span class="cn-object-parties__name">{{ nameOf(party) }}</span>
|
|
153
|
+
<span
|
|
154
|
+
v-if="primary && party.partyUuid === primary"
|
|
155
|
+
class="cn-status-badge cn-status-badge--primary"
|
|
156
|
+
data-testid="cn-object-parties-primary">{{ label('primary') }}</span>
|
|
157
|
+
<span v-if="kindOf(party)" class="cn-object-parties__muted">{{ kindOf(party) }}</span>
|
|
158
|
+
<span
|
|
159
|
+
v-if="notAccepted(party)"
|
|
160
|
+
class="cn-status-badge cn-status-badge--warning"
|
|
161
|
+
data-testid="cn-object-parties-not-accepted">{{ label('notAccepted') }}</span>
|
|
162
|
+
<span
|
|
163
|
+
v-for="(line, index) in extraLinesOf(party)"
|
|
164
|
+
:key="`line-${index}`"
|
|
165
|
+
class="cn-object-parties__muted"
|
|
166
|
+
data-testid="cn-object-parties-extra-line">{{ line }}</span>
|
|
167
|
+
<span v-if="party.email" class="cn-object-parties__muted">{{ party.email }}</span>
|
|
168
|
+
<span
|
|
169
|
+
v-if="representedBy(party)"
|
|
170
|
+
class="cn-object-parties__muted"
|
|
171
|
+
data-testid="cn-object-parties-represented">{{ label('representedBy') }}: {{ representedBy(party) }}</span>
|
|
172
|
+
<span
|
|
173
|
+
v-if="correspondenceOf(party)"
|
|
174
|
+
class="cn-object-parties__muted"
|
|
175
|
+
:data-party-documents="party.partyUuid || party.contactUid"
|
|
176
|
+
data-testid="cn-object-parties-documents">{{ correspondenceOf(party) }}</span>
|
|
177
|
+
<span
|
|
178
|
+
v-for="indicator in indicatorsFor(party)"
|
|
179
|
+
:key="`${party.partyUuid}-${indicator.key}`"
|
|
180
|
+
class="cn-status-badge cn-status-badge--default"
|
|
181
|
+
:class="`cn-object-parties__indicator--${indicator.severity}`"
|
|
182
|
+
:data-effect="indicator.effect"
|
|
183
|
+
:title="indicator.verdict"
|
|
184
|
+
data-testid="cn-object-parties-indicator">{{ indicator.label }} · {{ indicator.verdict }}</span>
|
|
185
|
+
<NcButton
|
|
186
|
+
v-if="canRemove && party.partyUuid"
|
|
187
|
+
class="cn-object-parties__remove"
|
|
188
|
+
variant="tertiary"
|
|
189
|
+
:aria-label="removeLabel(party, group)"
|
|
190
|
+
:title="removeLabel(party, group)"
|
|
191
|
+
data-testid="cn-object-parties-remove"
|
|
192
|
+
@click="removing = { party, group }">
|
|
193
|
+
<template #icon>
|
|
194
|
+
<TrashCanOutline :size="20" />
|
|
195
|
+
</template>
|
|
196
|
+
</NcButton>
|
|
197
|
+
</template>
|
|
160
198
|
</li>
|
|
161
199
|
</ul>
|
|
162
200
|
</section>
|
|
@@ -200,6 +238,7 @@ import TrashCanOutline from 'vue-material-design-icons/TrashCanOutline.vue'
|
|
|
200
238
|
import CnConfirmDialog from '../../dialogs/CnConfirmDialog.vue'
|
|
201
239
|
import CnPartyAddDialog from '../../dialogs/CnPartyAddDialog.vue'
|
|
202
240
|
import { interpolateUrlTokens } from '../../composables/useEndpointSource.js'
|
|
241
|
+
import { normalizeLook } from '../../composables/useLook.js'
|
|
203
242
|
import innerHeading from '../../mixins/innerHeading.js'
|
|
204
243
|
import { conditionalLine } from '../../utils/conditionalLine.js'
|
|
205
244
|
import { initialsOf } from '../../utils/initials.js'
|
|
@@ -287,6 +326,7 @@ export default {
|
|
|
287
326
|
|
|
288
327
|
inject: {
|
|
289
328
|
cnTranslate: { default: () => (key) => key },
|
|
329
|
+
cnLook: { default: 'nextcloud' },
|
|
290
330
|
},
|
|
291
331
|
|
|
292
332
|
props: {
|
|
@@ -347,6 +387,11 @@ export default {
|
|
|
347
387
|
},
|
|
348
388
|
|
|
349
389
|
computed: {
|
|
390
|
+
/** @return {boolean} The board look draws one ruled row per party. */
|
|
391
|
+
isBoard() {
|
|
392
|
+
return normalizeLook(this.cnLook) === 'board'
|
|
393
|
+
},
|
|
394
|
+
|
|
350
395
|
/** @return {Array<object>} The role groups, primary first. */
|
|
351
396
|
groups() {
|
|
352
397
|
return rolesInOrder(this.listing, this.translatedMap(this.content?.roleLabels))
|
|
@@ -916,6 +961,29 @@ export default {
|
|
|
916
961
|
* @param {object} party The listing row.
|
|
917
962
|
* @return {Array<object>}
|
|
918
963
|
*/
|
|
964
|
+
/**
|
|
965
|
+
* The board row's meta line: the primary mark, the role, the kind,
|
|
966
|
+
* whom the party represents, its extra lines, e-mail and documents,
|
|
967
|
+
* separated by middots.
|
|
968
|
+
*
|
|
969
|
+
* @param {object} party The party.
|
|
970
|
+
* @param {object} group Its role group.
|
|
971
|
+
* @return {string}
|
|
972
|
+
*/
|
|
973
|
+
boardMetaOf(party, group) {
|
|
974
|
+
const parts = []
|
|
975
|
+
if (this.primary && party.partyUuid === this.primary) {
|
|
976
|
+
parts.push(this.label('primary'))
|
|
977
|
+
}
|
|
978
|
+
parts.push(group.label, this.kindOf(party))
|
|
979
|
+
const represented = this.representedBy(party)
|
|
980
|
+
if (represented) {
|
|
981
|
+
parts.push(`${this.label('representedBy')}: ${represented}`)
|
|
982
|
+
}
|
|
983
|
+
parts.push(...this.extraLinesOf(party), party.email, this.correspondenceOf(party))
|
|
984
|
+
return parts.filter((part) => typeof part === 'string' && part !== '').join(' · ')
|
|
985
|
+
},
|
|
986
|
+
|
|
919
987
|
indicatorsFor(party) {
|
|
920
988
|
const record = this.partyRecords[party.partyUuid]
|
|
921
989
|
if (!record) {
|
|
@@ -53,15 +53,37 @@
|
|
|
53
53
|
scope="col"
|
|
54
54
|
:aria-sort="col.sortable ? sortStateOf(col.key) : undefined"
|
|
55
55
|
:class="{ 'cn-record-list__cell--end': col.align === 'end' }">
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
56
|
+
<span v-if="col.sortable || tableFilterable" class="cn-record-list__head">
|
|
57
|
+
<button
|
|
58
|
+
v-if="col.sortable"
|
|
59
|
+
type="button"
|
|
60
|
+
class="cn-record-list__sort"
|
|
61
|
+
:data-testid="`cn-record-list-sort-${col.key}`"
|
|
62
|
+
@click="toggleTableSort(col.key)">
|
|
63
|
+
{{ col.label }}
|
|
64
|
+
<span class="cn-record-list__sort-mark" aria-hidden="true">{{ sortMarkOf(col.key) }}</span>
|
|
65
|
+
</button>
|
|
66
|
+
<template v-else>
|
|
67
|
+
{{ col.label }}
|
|
68
|
+
</template>
|
|
69
|
+
<!-- `content.filterable`: the head offers the values the column holds and keeps the rows with a chosen one. -->
|
|
70
|
+
<NcActions
|
|
71
|
+
v-if="tableFilterable"
|
|
72
|
+
class="cn-record-list__head-filter"
|
|
73
|
+
:aria-label="filterLabelOf(col.label)"
|
|
74
|
+
:data-testid="`cn-record-list-filter-${col.key}`">
|
|
75
|
+
<template #icon>
|
|
76
|
+
<FilterOutline :size="14" />
|
|
77
|
+
</template>
|
|
78
|
+
<NcActionCheckbox
|
|
79
|
+
v-for="option in tableFilterOptions(col.key)"
|
|
80
|
+
:key="option"
|
|
81
|
+
:modelValue="(tableFilters[col.key] || []).includes(option)"
|
|
82
|
+
@update:modelValue="toggleTableFilter(col.key, option)">
|
|
83
|
+
{{ option }}
|
|
84
|
+
</NcActionCheckbox>
|
|
85
|
+
</NcActions>
|
|
86
|
+
</span>
|
|
65
87
|
<template v-else>
|
|
66
88
|
{{ col.label }}
|
|
67
89
|
</template>
|
|
@@ -550,10 +572,11 @@
|
|
|
550
572
|
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
|
|
551
573
|
import { translate as t } from '@nextcloud/l10n'
|
|
552
574
|
import { generateUrl } from '@nextcloud/router'
|
|
553
|
-
import { NcActionButton, NcActionLink, NcActions, NcButton, NcLoadingIcon } from '@nextcloud/vue'
|
|
575
|
+
import { NcActionButton, NcActionCheckbox, NcActionLink, NcActions, NcButton, NcLoadingIcon } from '@nextcloud/vue'
|
|
554
576
|
import { inject, ref } from 'vue'
|
|
555
577
|
import Check from 'vue-material-design-icons/Check.vue'
|
|
556
578
|
import ChevronRight from 'vue-material-design-icons/ChevronRight.vue'
|
|
579
|
+
import FilterOutline from 'vue-material-design-icons/FilterOutline.vue'
|
|
557
580
|
import CnIcon from '../CnIcon/CnIcon.vue'
|
|
558
581
|
import CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'
|
|
559
582
|
import CnRecordNoteRows from './CnRecordNoteRows.vue'
|
|
@@ -649,7 +672,7 @@ function unwrap(value) {
|
|
|
649
672
|
export default {
|
|
650
673
|
name: 'CnRecordListWidget',
|
|
651
674
|
|
|
652
|
-
components: { Check, ChevronRight, CnIcon, CnRecordNoteRows, CnStatusBadge, NcActionButton, NcActionLink, NcActions, NcButton, NcLoadingIcon },
|
|
675
|
+
components: { Check, ChevronRight, CnIcon, CnRecordNoteRows, CnStatusBadge, FilterOutline, NcActionButton, NcActionCheckbox, NcActionLink, NcActions, NcButton, NcLoadingIcon },
|
|
653
676
|
|
|
654
677
|
inject: {
|
|
655
678
|
/** Detail-page object context (`{ objectId, object, register, schema }`). */
|
|
@@ -714,6 +737,8 @@ export default {
|
|
|
714
737
|
* without a value.
|
|
715
738
|
* `density: "compact"` draws the rows 10px above and below, at least
|
|
716
739
|
* 56px tall, with the title at 500 (DqProcesanalyse).
|
|
740
|
+
* On `cards` it draws the small framed card: 12px 14px in, the title
|
|
741
|
+
* 15px/700 with the pill at its end (DqInspectie).
|
|
717
742
|
* `density: "stacked"` stands the rows 10px apart with no rule and no
|
|
718
743
|
* row padding (DqDagAfsluiten "Morgen eerst").
|
|
719
744
|
* In `rows`, `text` is a line under the meta line ("12 dagen stil"),
|
|
@@ -809,6 +834,8 @@ export default {
|
|
|
809
834
|
return {
|
|
810
835
|
/** The reader's sort of a `table`: the column key and `ascending` or `descending`. */
|
|
811
836
|
tableSort: { key: '', dir: '' },
|
|
837
|
+
/** The reader's head filters of a `table`: `{ [columnKey]: cellTexts[] }`. */
|
|
838
|
+
tableFilters: {},
|
|
812
839
|
rows: [],
|
|
813
840
|
/** The `aggregates` figures per row id: `{ [rowId]: { [key]: value } }`. */
|
|
814
841
|
aggregateValues: {},
|
|
@@ -1183,7 +1210,16 @@ export default {
|
|
|
1183
1210
|
const isTemplate = (value) => typeof value === 'string' || (Array.isArray(value) && value.length > 0 && value.every((entry) => typeof entry === 'string'))
|
|
1184
1211
|
return columns
|
|
1185
1212
|
.filter((col) => col && typeof col === 'object' && isTemplate(col.value))
|
|
1186
|
-
.map((col, index) => ({ ...col, key: `col-${index}`, label: typeof col.label === 'string' ? this.translate(col.label) : '' }))
|
|
1213
|
+
.map((col, index) => ({ ...col, key: `col-${index}`, label: typeof col.label === 'string' ? this.translate(col.label) : '', sortable: col.sortable === true || this.content?.sortable === true }))
|
|
1214
|
+
},
|
|
1215
|
+
|
|
1216
|
+
/**
|
|
1217
|
+
* Whether the `table` heads filter (`content.filterable`).
|
|
1218
|
+
*
|
|
1219
|
+
* @return {boolean}
|
|
1220
|
+
*/
|
|
1221
|
+
tableFilterable() {
|
|
1222
|
+
return this.content?.filterable === true
|
|
1187
1223
|
},
|
|
1188
1224
|
|
|
1189
1225
|
/**
|
|
@@ -1193,8 +1229,27 @@ export default {
|
|
|
1193
1229
|
* @spec openspec/changes/record-list-table/specs/record-list-table/spec.md#requirement-a-record-list-can-draw-its-rows-as-a-small-table
|
|
1194
1230
|
*/
|
|
1195
1231
|
tableRows() {
|
|
1232
|
+
const rows = this.tableAllRows.filter((row) => Object.entries(this.tableFilters).every(([key, values]) => {
|
|
1233
|
+
const index = this.tableColumns.findIndex((col) => col.key === key)
|
|
1234
|
+
return values.length === 0 || index < 0 || values.includes(row.cells[index].text)
|
|
1235
|
+
}))
|
|
1236
|
+
const { key, dir } = this.tableSort
|
|
1237
|
+
const index = this.tableColumns.findIndex((col) => col.key === key)
|
|
1238
|
+
if (index < 0 || !dir) {
|
|
1239
|
+
return rows
|
|
1240
|
+
}
|
|
1241
|
+
const sign = dir === 'descending' ? -1 : 1
|
|
1242
|
+
return [...rows].sort((a, b) => sign * compareCells(a.cells[index].text, b.cells[index].text))
|
|
1243
|
+
},
|
|
1244
|
+
|
|
1245
|
+
/**
|
|
1246
|
+
* Every `table` row, before the reader's head filters and sort.
|
|
1247
|
+
*
|
|
1248
|
+
* @return {Array<object>} `{ key, cells: [{ key, text, align, alert }] }`.
|
|
1249
|
+
*/
|
|
1250
|
+
tableAllRows() {
|
|
1196
1251
|
const indentPath = this.content?.indentPath
|
|
1197
|
-
|
|
1252
|
+
return this.items.map((item) => ({
|
|
1198
1253
|
key: item.key,
|
|
1199
1254
|
row: item.row,
|
|
1200
1255
|
rowActions: this.rowActions.length > 0 ? this.rowActionsOf(item.row) : [],
|
|
@@ -1215,13 +1270,6 @@ export default {
|
|
|
1215
1270
|
}
|
|
1216
1271
|
}),
|
|
1217
1272
|
}))
|
|
1218
|
-
const { key, dir } = this.tableSort
|
|
1219
|
-
const index = this.tableColumns.findIndex((col) => col.key === key)
|
|
1220
|
-
if (index < 0 || !dir) {
|
|
1221
|
-
return rows
|
|
1222
|
-
}
|
|
1223
|
-
const sign = dir === 'descending' ? -1 : 1
|
|
1224
|
-
return [...rows].sort((a, b) => sign * compareCells(a.cells[index].text, b.cells[index].text))
|
|
1225
1273
|
},
|
|
1226
1274
|
|
|
1227
1275
|
/**
|
|
@@ -2246,6 +2294,41 @@ export default {
|
|
|
2246
2294
|
this.tableSort = { key, dir }
|
|
2247
2295
|
},
|
|
2248
2296
|
|
|
2297
|
+
/**
|
|
2298
|
+
* The values a `table` column's head filter offers: each text the column holds, once.
|
|
2299
|
+
*
|
|
2300
|
+
* @param {string} key The column key.
|
|
2301
|
+
* @return {Array<string>} The texts, in row order.
|
|
2302
|
+
*/
|
|
2303
|
+
tableFilterOptions(key) {
|
|
2304
|
+
const index = this.tableColumns.findIndex((col) => col.key === key)
|
|
2305
|
+
if (index < 0) {
|
|
2306
|
+
return []
|
|
2307
|
+
}
|
|
2308
|
+
return [...new Set(this.tableAllRows.map((row) => row.cells[index].text).filter((text) => text !== ''))]
|
|
2309
|
+
},
|
|
2310
|
+
|
|
2311
|
+
/**
|
|
2312
|
+
* Keep or drop one value of a `table` column's head filter.
|
|
2313
|
+
*
|
|
2314
|
+
* @param {string} key The column key.
|
|
2315
|
+
* @param {string} value The cell text.
|
|
2316
|
+
*/
|
|
2317
|
+
toggleTableFilter(key, value) {
|
|
2318
|
+
const current = this.tableFilters[key] || []
|
|
2319
|
+
this.tableFilters = { ...this.tableFilters, [key]: current.includes(value) ? current.filter((v) => v !== value) : [...current, value] }
|
|
2320
|
+
},
|
|
2321
|
+
|
|
2322
|
+
/**
|
|
2323
|
+
* The accessible name of a column's head filter.
|
|
2324
|
+
*
|
|
2325
|
+
* @param {string} label The column label.
|
|
2326
|
+
* @return {string}
|
|
2327
|
+
*/
|
|
2328
|
+
filterLabelOf(label) {
|
|
2329
|
+
return t('nextcloud-vue', 'Filter by {column}', { column: label })
|
|
2330
|
+
},
|
|
2331
|
+
|
|
2249
2332
|
/**
|
|
2250
2333
|
* The rows of a read with `flattenPath` set: each entry of the list at
|
|
2251
2334
|
* that path on a record becomes a row, with the record at `@parent`.
|
|
@@ -3232,6 +3315,16 @@ export default {
|
|
|
3232
3315
|
font-size: 10px;
|
|
3233
3316
|
}
|
|
3234
3317
|
|
|
3318
|
+
.cn-record-list__head {
|
|
3319
|
+
display: inline-flex;
|
|
3320
|
+
gap: 4px;
|
|
3321
|
+
align-items: center;
|
|
3322
|
+
}
|
|
3323
|
+
|
|
3324
|
+
.cn-record-list__head-filter {
|
|
3325
|
+
--button-size: 22px;
|
|
3326
|
+
}
|
|
3327
|
+
|
|
3235
3328
|
.cn-record-list__table .cn-record-list__cell--end {
|
|
3236
3329
|
padding-inline-start: 12px;
|
|
3237
3330
|
text-align: end;
|
|
@@ -3383,6 +3476,24 @@ export default {
|
|
|
3383
3476
|
text-decoration: none;
|
|
3384
3477
|
}
|
|
3385
3478
|
|
|
3479
|
+
/* `density: "compact"` on cards: the boards' small framed rows (DqInspectie
|
|
3480
|
+
"Molenweg 4" and the outbox): 12px 14px in, the title 15px/700 on an
|
|
3481
|
+
18px line with the pill at its end, the meta 6px under it. */
|
|
3482
|
+
.cn-record-list--compact .cn-record-list__card {
|
|
3483
|
+
gap: 6px;
|
|
3484
|
+
padding: 12px 14px;
|
|
3485
|
+
}
|
|
3486
|
+
|
|
3487
|
+
.cn-record-list--compact .cn-record-list__card-head {
|
|
3488
|
+
align-items: flex-start;
|
|
3489
|
+
}
|
|
3490
|
+
|
|
3491
|
+
.cn-record-list--compact .cn-record-list__card .cn-record-list__title {
|
|
3492
|
+
font-size: 15px;
|
|
3493
|
+
font-weight: 700;
|
|
3494
|
+
line-height: 1.2;
|
|
3495
|
+
}
|
|
3496
|
+
|
|
3386
3497
|
.cn-record-list__card--link:hover,
|
|
3387
3498
|
.cn-record-list__card--link:focus-visible {
|
|
3388
3499
|
border-color: var(--color-border-dark, var(--color-border));
|
|
@@ -85,6 +85,7 @@
|
|
|
85
85
|
</component>
|
|
86
86
|
<ul class="cn-retention__rows">
|
|
87
87
|
<li v-for="hold in holds" :key="hold.id" class="cn-retention__row">
|
|
88
|
+
<span class="cn-retention__mark cn-retention__mark--hold" aria-hidden="true">LH</span>
|
|
88
89
|
<span class="cn-retention__row-text">
|
|
89
90
|
<span class="cn-retention__row-title">{{ hold.reason || t('nextcloud-vue', 'Legal hold') }}</span>
|
|
90
91
|
<span class="cn-retention__muted">{{ t('nextcloud-vue', 'Placed on {date} by {by}', { date: hold.placedDate, by: hold.placedBy }) }}</span>
|
|
@@ -92,6 +93,7 @@
|
|
|
92
93
|
<CnStatusBadge :label="t('nextcloud-vue', 'Active')" variant="warning" />
|
|
93
94
|
</li>
|
|
94
95
|
<li v-if="holds.length === 0" class="cn-retention__row">
|
|
96
|
+
<span class="cn-retention__mark cn-retention__mark--hold" aria-hidden="true">LH</span>
|
|
95
97
|
<span class="cn-retention__row-text">
|
|
96
98
|
<span class="cn-retention__row-title">{{ t('nextcloud-vue', 'No legal hold') }}</span>
|
|
97
99
|
<span class="cn-retention__muted">{{ t('nextcloud-vue', 'If an objection or appeal runs, destruction is suspended') }}</span>
|
|
@@ -107,6 +109,7 @@
|
|
|
107
109
|
</component>
|
|
108
110
|
<ul class="cn-retention__rows">
|
|
109
111
|
<li class="cn-retention__row">
|
|
112
|
+
<span class="cn-retention__mark" aria-hidden="true">ED</span>
|
|
110
113
|
<span class="cn-retention__row-text">
|
|
111
114
|
<span class="cn-retention__row-title">{{ transfers ? t('nextcloud-vue', 'Goes to the e-Depot') : t('nextcloud-vue', 'Not applicable') }}</span>
|
|
112
115
|
<span class="cn-retention__muted">{{ transfers ? t('nextcloud-vue', 'After the retention period the record is transferred') : t('nextcloud-vue', 'Only records appraised to keep go to the e-Depot') }}</span>
|
|
@@ -643,17 +646,39 @@ export default {
|
|
|
643
646
|
align-items: center;
|
|
644
647
|
justify-content: space-between;
|
|
645
648
|
gap: 12px;
|
|
646
|
-
padding:
|
|
649
|
+
padding: 12px 0;
|
|
647
650
|
border-top: 1px solid var(--color-border);
|
|
648
651
|
}
|
|
649
652
|
|
|
650
653
|
.cn-retention__row-text {
|
|
651
654
|
display: flex;
|
|
655
|
+
flex: 1 1 auto;
|
|
652
656
|
flex-direction: column;
|
|
653
657
|
gap: 2px;
|
|
654
658
|
min-width: 0;
|
|
655
659
|
}
|
|
656
660
|
|
|
661
|
+
/* A round mark before a hold or transfer row: LH (legal hold) on the error
|
|
662
|
+
tint, ED (e-Depot) on the chip ground (DqZaakArchivering). */
|
|
663
|
+
.cn-retention__mark {
|
|
664
|
+
display: inline-flex;
|
|
665
|
+
flex: none;
|
|
666
|
+
align-items: center;
|
|
667
|
+
justify-content: center;
|
|
668
|
+
width: 32px;
|
|
669
|
+
height: 32px;
|
|
670
|
+
border-radius: 16px;
|
|
671
|
+
background: var(--color-background-dark);
|
|
672
|
+
color: var(--color-text-maxcontrast);
|
|
673
|
+
font-size: 12px;
|
|
674
|
+
font-weight: 700;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
.cn-retention__mark--hold {
|
|
678
|
+
background: var(--color-error-light, #fcedec);
|
|
679
|
+
color: var(--color-error-text, #a30000);
|
|
680
|
+
}
|
|
681
|
+
|
|
657
682
|
.cn-retention__row-title {
|
|
658
683
|
font-weight: 600;
|
|
659
684
|
}
|
|
@@ -275,6 +275,7 @@
|
|
|
275
275
|
type="number"
|
|
276
276
|
:min="field.min"
|
|
277
277
|
:max="field.max"
|
|
278
|
+
:step="numberStep"
|
|
278
279
|
:modelValue="stringValue"
|
|
279
280
|
:readonly="field.readOnly"
|
|
280
281
|
:error="!!error"
|
|
@@ -424,6 +425,20 @@ export default {
|
|
|
424
425
|
return INPUT_TYPES.includes(this.kind) ? this.kind : 'text'
|
|
425
426
|
},
|
|
426
427
|
|
|
428
|
+
/**
|
|
429
|
+
* The number input's step: the field's own, 1 for a whole number, else
|
|
430
|
+
* any, so a decimal value (0.8) is not invalid to the browser.
|
|
431
|
+
*
|
|
432
|
+
* @return {string}
|
|
433
|
+
* @spec openspec/changes/settings-number-decimal-step/specs/settings-fields/spec.md#requirement-a-number-setting-steps-as-it-is-declared
|
|
434
|
+
*/
|
|
435
|
+
numberStep() {
|
|
436
|
+
if (typeof this.field.step === 'number' || (typeof this.field.step === 'string' && this.field.step !== '')) {
|
|
437
|
+
return String(this.field.step)
|
|
438
|
+
}
|
|
439
|
+
return this.field.integer ? '1' : 'any'
|
|
440
|
+
},
|
|
441
|
+
|
|
427
442
|
/** @return {string} The label. */
|
|
428
443
|
label() {
|
|
429
444
|
return String(this.field.label || this.field.key || '')
|