@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
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
grid-column: 1 / -1;
|
|
78
78
|
grid-row: 2;
|
|
79
79
|
justify-self: start;
|
|
80
|
-
margin-block: 6px
|
|
80
|
+
margin-block: 6px 0;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
.cn-look-board.cn-index-page--sidebar-open .cn-page-header .cn-header-trail,
|
|
@@ -90,6 +90,13 @@
|
|
|
90
90
|
grid-row: 4;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
/* Without a breadcrumb trail the count line takes the trail's row, so no
|
|
94
|
+
empty row adds a second gap (DqZakenSorteren: 58px under the title). */
|
|
95
|
+
.cn-look-board.cn-index-page--sidebar-open .cn-page-header:not(:has(.cn-header-trail)) .cn-page-header__text > .cn-page-header__description,
|
|
96
|
+
.cn-look-board .cn-index-page--sidebar-open .cn-page-header:not(:has(.cn-header-trail)) .cn-page-header__text > .cn-page-header__description {
|
|
97
|
+
grid-row: 3;
|
|
98
|
+
}
|
|
99
|
+
|
|
93
100
|
/* The header buttons keep the board's button under a theme that styles every
|
|
94
101
|
secondary or primary button with `!important` (the nldesign theme: a
|
|
95
102
|
primary border, 8px 16px padding): Download and the Actions menu are 40px,
|
|
@@ -190,6 +197,15 @@
|
|
|
190
197
|
gap: 8px;
|
|
191
198
|
}
|
|
192
199
|
|
|
200
|
+
/* With the side panel open the boards keep Filter on row 1 after Save view
|
|
201
|
+
and wrap the view switch alone to row 2 (DqFilterBeheren, DqZakenSorteren):
|
|
202
|
+
the unit dissolves into the bar's flex row.
|
|
203
|
+
@spec openspec/changes/board-filter-row-one-beside-side-panel/specs/board-filter-row-one-beside-side-panel/spec.md */
|
|
204
|
+
.cn-look-board.cn-index-page--sidebar-open .cn-actions-bar--board .cn-actions-bar__view-controls,
|
|
205
|
+
.cn-look-board .cn-index-page--sidebar-open .cn-actions-bar--board .cn-actions-bar__view-controls {
|
|
206
|
+
display: contents;
|
|
207
|
+
}
|
|
208
|
+
|
|
193
209
|
/* `quickFilterPlacement: "toolbar"` (DqTeamwachtrij): the chips take the room
|
|
194
210
|
the Filter button and the view switch leave on row 1, so the three stay on
|
|
195
211
|
one row in the column beside a side panel; the chips that do not fit move
|
|
@@ -909,16 +925,21 @@
|
|
|
909
925
|
`#content[class*="app-"]`, an id selector no class rule outranks, so a plain
|
|
910
926
|
`content-box` here was ignored and the cell left 12px for the checkbox (the
|
|
911
927
|
header's checkbox showed as a stray bracket). */
|
|
912
|
-
/* The
|
|
913
|
-
|
|
928
|
+
/* The cell pads 16px as the boards do and the checkbox starts 4px further in,
|
|
929
|
+
a native checkbox's margin (DqZoekresultaten, DqPostvak, DqContracten), in
|
|
930
|
+
the same 60px. */
|
|
914
931
|
.cn-look-board .cn-table-container--board .cn-data-table .cn-table-col--checkbox {
|
|
915
932
|
box-sizing: border-box !important;
|
|
916
933
|
width: 60px;
|
|
917
934
|
min-width: 60px;
|
|
918
|
-
padding-inline:
|
|
935
|
+
padding-inline: 16px;
|
|
919
936
|
text-align: start;
|
|
920
937
|
}
|
|
921
938
|
|
|
939
|
+
.cn-look-board .cn-table-container--board .cn-data-table .cn-table-col--checkbox .checkbox-radio-switch {
|
|
940
|
+
margin-inline-start: 4px;
|
|
941
|
+
}
|
|
942
|
+
|
|
922
943
|
.cn-look-board .cn-table-container--board .cn-data-table .checkbox-radio-switch {
|
|
923
944
|
--icon-size: 18px;
|
|
924
945
|
}
|
|
@@ -991,6 +1012,20 @@
|
|
|
991
1012
|
text-decoration: none;
|
|
992
1013
|
}
|
|
993
1014
|
|
|
1015
|
+
/* In such a plain log an icon-and-name cell is regular too (DqZaakContact
|
|
1016
|
+
Kanaal "Mijn Zuiddrecht"); elsewhere the icon label stays 600.
|
|
1017
|
+
@spec openspec/changes/board-log-table-icon-label-regular/specs/board-log-table-icon-label-regular/spec.md#requirement-a-plain-logs-icon-label-cell-is-regular */
|
|
1018
|
+
.cn-look-board .cn-table-container--board.cn-table-container--title-text .cn-cell-renderer__icon-label:not(.cn-look-nextcloud *) {
|
|
1019
|
+
font-weight: 400;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
/* In such a plain log a wrapping prose cell runs at line height 1.45, as
|
|
1023
|
+
DqZaakContact draws the contact summary (rows 61.6 high, not 57).
|
|
1024
|
+
@spec openspec/changes/board-log-table-prose-line-height/specs/board-log-table-prose-line-height/spec.md#requirement-a-plain-logs-prose-cell-runs-at-line-height-1-45 */
|
|
1025
|
+
.cn-look-board .cn-table-container--board.cn-table-container--title-text .cn-data-table td.cn-cell--wrap:not(.cn-look-nextcloud *) {
|
|
1026
|
+
line-height: 1.45;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
994
1029
|
/* `rowTitle: "strong"` (DqZaaktypeStatussen "Statussen", "Resultaten"): the
|
|
995
1030
|
name column of a card's list, the cell's 14px at weight 600 in the main
|
|
996
1031
|
ink, no underline; the row stays a link.
|
|
@@ -1414,6 +1449,19 @@
|
|
|
1414
1449
|
padding-top: 0;
|
|
1415
1450
|
}
|
|
1416
1451
|
|
|
1452
|
+
/* The selection box sits flush where the boards draw it: NcCheckbox pads its
|
|
1453
|
+
content 7px on each side (DqAanMijToegewezen card head, DqTeamwachtrij rows,
|
|
1454
|
+
whose box starts 18px in).
|
|
1455
|
+
@spec openspec/changes/board-selection-box-flush/specs/board-selection-box-flush/spec.md#requirement-a-cards-and-a-rows-selection-box-sits-where-the-board-draws-it */
|
|
1456
|
+
.cn-look-board .cn-object-card__record-head > .cn-object-card__checkbox .checkbox-radio-switch__content,
|
|
1457
|
+
.cn-look-board .cn-object-row__checkbox .checkbox-radio-switch__content {
|
|
1458
|
+
padding-inline: 0;
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
.cn-look-board .cn-object-row__checkbox {
|
|
1462
|
+
margin-inline-start: 6px;
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1417
1465
|
.cn-look-board .cn-object-card--board .cn-object-card__record-head > .cn-object-card__checkbox ~ .cn-object-card__record-pill {
|
|
1418
1466
|
margin-inline-start: auto;
|
|
1419
1467
|
}
|
package/src/css/look-board.css
CHANGED
|
@@ -329,9 +329,11 @@
|
|
|
329
329
|
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-banner-widget__kicker {
|
|
330
330
|
--nldesign-component-paragraph-font-size: 13px;
|
|
331
331
|
--nldesign-component-paragraph-font-weight: 700;
|
|
332
|
+
--nldesign-component-paragraph-line-height: normal;
|
|
332
333
|
font-size: 13px;
|
|
333
334
|
font-weight: 700;
|
|
334
335
|
letter-spacing: 0;
|
|
336
|
+
line-height: normal;
|
|
335
337
|
text-transform: none;
|
|
336
338
|
}
|
|
337
339
|
|
|
@@ -662,12 +664,17 @@
|
|
|
662
664
|
}
|
|
663
665
|
|
|
664
666
|
/* Two buttons in a card's title row stand 8px apart (DqZaakContact "Live
|
|
665
|
-
gesprek", DqZaakEmail "Mail koppelen" / "Mail opstellen")
|
|
667
|
+
gesprek", DqZaakEmail "Mail koppelen" / "Mail opstellen"), also in an
|
|
668
|
+
integration card's CnDetailCard header (DqZaakTaken "Afspraken", "Kaarten").
|
|
666
669
|
@spec openspec/changes/board-card-header-actions-gap/specs/board-card-header-actions-gap/spec.md#requirement-a-board-cards-title-row-buttons-stand-8px-apart */
|
|
667
670
|
.cn-look-board .cn-widget-wrapper__actions:not(.cn-look-nextcloud *) {
|
|
668
671
|
gap: 8px;
|
|
669
672
|
}
|
|
670
673
|
|
|
674
|
+
.cn-look-board .cn-detail-card__header-right:not(.cn-look-nextcloud *) {
|
|
675
|
+
gap: 8px;
|
|
676
|
+
}
|
|
677
|
+
|
|
671
678
|
/* A detail page marked `cardButtons: "regular"` draws them at the 40px
|
|
672
679
|
control height: the case page's tab cards (DqZaakContact "Live gesprek",
|
|
673
680
|
DqZaakHistorie, DqZaakBetrokkenen), where setting and case-type pages keep 34.
|
|
@@ -1465,6 +1472,90 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
1465
1472
|
text-decoration: underline;
|
|
1466
1473
|
}
|
|
1467
1474
|
|
|
1475
|
+
/* A plain table an app draws in a settings card (dossiq's ZGW mapping, StUF
|
|
1476
|
+
endpoints and audit log, AWB terms) reads as the board's settings tables:
|
|
1477
|
+
14px, a near-white head with muted 600 labels, 10px 12px cells, soft rules.
|
|
1478
|
+
The theme paints every th through its table header tokens, so the head
|
|
1479
|
+
hands those tokens the board's values too.
|
|
1480
|
+
@spec openspec/changes/board-settings-plain-tables/specs/settings-board-look/spec.md */
|
|
1481
|
+
.cn-look-board .settings-section table:not(.cn-data-table):not(.cn-look-nextcloud *) {
|
|
1482
|
+
width: 100%;
|
|
1483
|
+
border-collapse: collapse;
|
|
1484
|
+
font-size: 14px;
|
|
1485
|
+
line-height: 1.2;
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
.cn-look-board .settings-section table:not(.cn-data-table):not(.cn-look-nextcloud *) th {
|
|
1489
|
+
--nldesign-component-table-header-background-color: var(--cn-board-table-head-bg, color-mix(in srgb, var(--color-background-hover) 40%, var(--color-main-background)));
|
|
1490
|
+
--nldesign-component-table-header-color: var(--color-text-maxcontrast);
|
|
1491
|
+
--nldesign-component-table-header-font-weight: 600;
|
|
1492
|
+
padding: 10px 12px;
|
|
1493
|
+
border-bottom: 1px solid var(--color-border);
|
|
1494
|
+
background: var(--cn-board-table-head-bg, color-mix(in srgb, var(--color-background-hover) 40%, var(--color-main-background)));
|
|
1495
|
+
color: var(--color-text-maxcontrast);
|
|
1496
|
+
font-size: 14px;
|
|
1497
|
+
font-weight: 600;
|
|
1498
|
+
line-height: 1.2;
|
|
1499
|
+
text-align: start;
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
/* The working calendar's month reads as the board draws it: the month name
|
|
1503
|
+
first, at the content edge, with the previous and next month buttons after
|
|
1504
|
+
it, and the buttons add no height to the line, so the month sits 20px under
|
|
1505
|
+
the card title (DqInstellingenAlgemeen "Werkdagen en feestdagen": the
|
|
1506
|
+
arrow put the month 30px in and 28px down).
|
|
1507
|
+
@spec openspec/changes/working-calendar-board-head/specs/settings-board-look/spec.md */
|
|
1508
|
+
.cn-look-board .cn-working-calendar__title:not(.cn-look-nextcloud *) {
|
|
1509
|
+
order: -1;
|
|
1510
|
+
min-width: 0;
|
|
1511
|
+
margin-inline-end: 4px;
|
|
1512
|
+
line-height: 1.2;
|
|
1513
|
+
text-align: start;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
.cn-look-board .settings-section table:not(.cn-data-table):not(.cn-look-nextcloud *) td {
|
|
1517
|
+
padding: 10px 12px;
|
|
1518
|
+
border-bottom: 1px solid var(--color-background-dark);
|
|
1519
|
+
color: var(--color-main-text);
|
|
1520
|
+
font-size: 14px;
|
|
1521
|
+
line-height: 1.2;
|
|
1522
|
+
vertical-align: middle;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
/* A strong cell's name in a settings card reads 15px bold over its muted
|
|
1526
|
+
second line, as the boards draw a connection's name (DqInstellingen
|
|
1527
|
+
"Koppelingen": <strong> 15px), not the index tables' 14px 500.
|
|
1528
|
+
@spec openspec/changes/board-settings-strong-cell-name/specs/settings-board-look/spec.md */
|
|
1529
|
+
.cn-look-board .settings-section .cn-data-table td.cn-cell--strong:not(.cn-look-nextcloud *) {
|
|
1530
|
+
font-weight: 400;
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
.cn-look-board .settings-section .cn-data-table td.cn-cell--strong:not(.cn-look-nextcloud *) > .cn-cell-renderer {
|
|
1534
|
+
font-size: 15px;
|
|
1535
|
+
font-weight: 700;
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
.cn-look-board .cn-working-calendar__head:not(.cn-look-nextcloud *) > .button-vue:not(.cn-working-calendar__add) {
|
|
1539
|
+
margin-block: -8px;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
/* In a one-column settings card a single-line field is at most 560px wide,
|
|
1543
|
+
its hint under it, as the boards draw a field on its own row
|
|
1544
|
+
(DqBeheerGeavanceerd "Financiële integratie", "Storeregister"); a text
|
|
1545
|
+
area, a note or a switch still spans the card.
|
|
1546
|
+
@spec openspec/changes/board-settings-single-field-width/specs/settings-board-look/spec.md */
|
|
1547
|
+
.cn-look-board .cn-settings-fields__grid--1:not(.cn-look-nextcloud *) > .cn-settings-field--text,
|
|
1548
|
+
.cn-look-board .cn-settings-fields__grid--1:not(.cn-look-nextcloud *) > .cn-settings-field--password,
|
|
1549
|
+
.cn-look-board .cn-settings-fields__grid--1:not(.cn-look-nextcloud *) > .cn-settings-field--secret,
|
|
1550
|
+
.cn-look-board .cn-settings-fields__grid--1:not(.cn-look-nextcloud *) > .cn-settings-field--number,
|
|
1551
|
+
.cn-look-board .cn-settings-fields__grid--1:not(.cn-look-nextcloud *) > .cn-settings-field--email,
|
|
1552
|
+
.cn-look-board .cn-settings-fields__grid--1:not(.cn-look-nextcloud *) > .cn-settings-field--url,
|
|
1553
|
+
.cn-look-board .cn-settings-fields__grid--1:not(.cn-look-nextcloud *) > .cn-settings-field--select,
|
|
1554
|
+
.cn-look-board .cn-settings-fields__grid--1:not(.cn-look-nextcloud *) > .cn-settings-field--date,
|
|
1555
|
+
.cn-look-board .cn-settings-fields__grid--1:not(.cn-look-nextcloud *) > .cn-settings-field--datetime-local {
|
|
1556
|
+
max-width: 560px;
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1468
1559
|
/* Section actions sit at the end of the title row. The row is a grid, so a
|
|
1469
1560
|
long title wraps beside the buttons instead of running under them. A
|
|
1470
1561
|
half-width card keeps them there (DqVthInstellingen "Inspectiechecklists",
|
|
@@ -1513,6 +1604,42 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
1513
1604
|
align-self: center;
|
|
1514
1605
|
}
|
|
1515
1606
|
|
|
1607
|
+
/* Without a subtitle the title centres on the title-row buttons, as the boards
|
|
1608
|
+
draw the card head (DqVthInstellingen "Inspectiechecklists",
|
|
1609
|
+
DqInstellingenAlgemeen "Werkdagen en feestdagen": title 27.5px down, live 21).
|
|
1610
|
+
@spec openspec/changes/board-settings-title-centred-and-link-flush/specs/settings-board-look/spec.md */
|
|
1611
|
+
.cn-look-board .settings-section:not(.cn-look-nextcloud *):has(> .cn-settings-section__actions):not(:has(> .settings-section__desc)) > .settings-section__name {
|
|
1612
|
+
align-self: center;
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
/* A switch or radio in a board settings card starts at the card's content
|
|
1616
|
+
edge, its label 12px (switch) or 10px (radio) after the control, as the
|
|
1617
|
+
boards draw them (DqBeheerinstellingen "AI-ondersteunde verwerking").
|
|
1618
|
+
NcCheckboxRadioSwitch pads its content 9px on each side, which set the
|
|
1619
|
+
control 9px in from the fields above and below it.
|
|
1620
|
+
@spec openspec/changes/board-settings-switch-radio-flush/specs/settings-board-look/spec.md */
|
|
1621
|
+
.cn-look-board .cn-settings-fields:not(.cn-look-nextcloud *) .checkbox-content {
|
|
1622
|
+
padding-inline: 0;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
.cn-look-board .cn-settings-fields:not(.cn-look-nextcloud *) .checkbox-content-switch {
|
|
1626
|
+
gap: 12px;
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
.cn-look-board .cn-settings-fields:not(.cn-look-nextcloud *) .checkbox-content-radio {
|
|
1630
|
+
gap: 10px;
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
/* The "Uitleg tonen" toggle is a text link flush with the card's right edge
|
|
1634
|
+
(DqBeheerinstellingen Zaak-e-mail), not a padded tertiary button.
|
|
1635
|
+
@spec openspec/changes/board-settings-title-centred-and-link-flush/specs/settings-board-look/spec.md */
|
|
1636
|
+
.cn-look-board .cn-settings-fields__hints-toggle:not(.cn-look-nextcloud *) .button-vue {
|
|
1637
|
+
--button-padding: 0px;
|
|
1638
|
+
--button-padding-default: 0px;
|
|
1639
|
+
padding-inline: 0;
|
|
1640
|
+
min-width: 0;
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1516
1643
|
@container (max-width: 400px) {
|
|
1517
1644
|
.cn-look-board .settings-section:not(.cn-look-nextcloud *) > .cn-settings-section__actions,
|
|
1518
1645
|
.cn-look-board .settings-section:not(.cn-look-nextcloud *):has(> .settings-section__desc) > .cn-settings-section__actions {
|
|
@@ -1576,8 +1703,12 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
1576
1703
|
max-width: none;
|
|
1577
1704
|
}
|
|
1578
1705
|
|
|
1579
|
-
|
|
1580
|
-
|
|
1706
|
+
/* A board card's title and subtitle run the card's width, wide or not
|
|
1707
|
+
(DqBeheerGeavanceerd "Eerste keer", "StUF-ZKN-endpoints": the subtitle
|
|
1708
|
+
wrapped at NcSettingsSection's 900px measure, the board's does not).
|
|
1709
|
+
@spec openspec/changes/board-settings-desc-full-width/specs/settings-board-look/spec.md */
|
|
1710
|
+
.cn-look-board .settings-section:not(.cn-look-nextcloud *) .settings-section__name,
|
|
1711
|
+
.cn-look-board .settings-section:not(.cn-look-nextcloud *) .settings-section__desc {
|
|
1581
1712
|
max-width: none;
|
|
1582
1713
|
}
|
|
1583
1714
|
|
|
@@ -2136,7 +2267,7 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
2136
2267
|
12px follows it: the boards' card is title, 6px, rule, row (DqMijnTeam
|
|
2137
2268
|
"Vastgelopen zaken", DqMijnWerk "Zaken die u volgt").
|
|
2138
2269
|
@spec openspec/changes/board-card-title-above-ruled-list/specs/board-card-title-above-ruled-list/spec.md#requirement-a-ruled-list-starts-6px-under-the-card-title */
|
|
2139
|
-
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-widget-wrapper:not(.cn-widget-wrapper--nc-dashboard):not(.cn-widget-wrapper--borderless):has(> .cn-widget-wrapper__content .cn-record-list--rule-above, > .cn-widget-wrapper__content .cn-tasks-widget__list, > .cn-widget-wrapper__content .cn-decision-list__rows) .cn-widget-wrapper__header {
|
|
2270
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-widget-wrapper:not(.cn-widget-wrapper--nc-dashboard):not(.cn-widget-wrapper--borderless):has(> .cn-widget-wrapper__content .cn-record-list--rule-above, > .cn-widget-wrapper__content .cn-tasks-widget__list, > .cn-widget-wrapper__content .cn-decision-list__rows, > .cn-widget-wrapper__content .cn-nc-widget-widget__body--vertical) .cn-widget-wrapper__header {
|
|
2140
2271
|
padding-bottom: 6px;
|
|
2141
2272
|
}
|
|
2142
2273
|
|
|
@@ -2672,13 +2803,13 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
2672
2803
|
|
|
2673
2804
|
/* A vertical NC widget is the board's activity list (DqMijnWerk "Recente
|
|
2674
2805
|
activiteit"): hairline rows 12px above and below the text, a 10px dot in
|
|
2675
|
-
the icon's place, the title 14px in the main ink and wrapping
|
|
2676
|
-
|
|
2677
|
-
|
|
2806
|
+
the icon's place, the title 14px in the main ink and wrapping. Thematiq underlines links with a heavier
|
|
2807
|
+
selector, hence the !important. The first hairline stands 6px under the
|
|
2808
|
+
title, as on every Dq list card (design-system #432).
|
|
2678
2809
|
@spec openspec/changes/board-nc-widget-activity-rows/specs/board-nc-widget-activity-rows/spec.md#requirement-a-board-dashboard-nc-widget-draws-its-items-as-activity-rows */
|
|
2679
2810
|
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-widget-wrapper:not(.cn-widget-wrapper--borderless) .cn-nc-widget-widget__body--vertical {
|
|
2680
2811
|
gap: 0;
|
|
2681
|
-
padding:
|
|
2812
|
+
padding: 0 var(--cn-board-dashboard-card-inset) 10px;
|
|
2682
2813
|
}
|
|
2683
2814
|
|
|
2684
2815
|
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-nc-widget-widget__body--vertical a.cn-nc-widget-widget__item--vertical {
|
|
@@ -3112,6 +3243,25 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
3112
3243
|
line-height: normal;
|
|
3113
3244
|
}
|
|
3114
3245
|
|
|
3246
|
+
/* A bar list in a framed section of a sections card is the board's small
|
|
3247
|
+
list: 13px rows 8px apart, a 150px label column, a 10px bar and a 48px
|
|
3248
|
+
value column (DqDoorlooptijd "Naleving per zaaktype").
|
|
3249
|
+
@spec openspec/changes/board-section-bar-list-compact/specs/board-section-bar-list-compact/spec.md#requirement-a-bar-list-in-a-sections-card-section-is-compact */
|
|
3250
|
+
.cn-look-board .cn-sections-widget__section .cn-chart-widget__bar-list:not(.cn-look-nextcloud *) {
|
|
3251
|
+
gap: 8px;
|
|
3252
|
+
}
|
|
3253
|
+
|
|
3254
|
+
.cn-look-board .cn-sections-widget__section .cn-chart-widget__bar-list:not(.cn-look-nextcloud *) .cn-chart-widget__bar-line {
|
|
3255
|
+
grid-template-columns: 150px minmax(0, 1fr) 48px;
|
|
3256
|
+
gap: 10px;
|
|
3257
|
+
font-size: 13px;
|
|
3258
|
+
}
|
|
3259
|
+
|
|
3260
|
+
.cn-look-board .cn-sections-widget__section .cn-chart-widget__bar-list:not(.cn-look-nextcloud *) .cn-chart-widget__bar-track {
|
|
3261
|
+
height: 10px;
|
|
3262
|
+
border-radius: 5px;
|
|
3263
|
+
}
|
|
3264
|
+
|
|
3115
3265
|
/* A bar list with the value at the bar's end (DqProcesanalyse "Doorlooptijd
|
|
3116
3266
|
per status") sets its rows in 13px, the label in the secondary text, the
|
|
3117
3267
|
value in the main ink at 600, rows 34px apart.
|
|
@@ -3157,6 +3307,11 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
3157
3307
|
line-height: 1.2;
|
|
3158
3308
|
}
|
|
3159
3309
|
|
|
3310
|
+
/* An option's title bold, as the dialog boards draw it (a <strong>). */
|
|
3311
|
+
.cn-look-board .cn-choice-cards .cn-choice-cards__row-title:not(.cn-look-nextcloud *) {
|
|
3312
|
+
font-weight: 700;
|
|
3313
|
+
}
|
|
3314
|
+
|
|
3160
3315
|
.cn-look-board .cn-choice-cards .cn-choice-cards__row-icon:not(.cn-look-nextcloud *) {
|
|
3161
3316
|
align-self: flex-start;
|
|
3162
3317
|
}
|
package/src/css/table.css
CHANGED
|
@@ -310,7 +310,7 @@
|
|
|
310
310
|
.cn-data-table--fit td.cn-table-col--grow.cn-cell--wrap {
|
|
311
311
|
min-width: 8em;
|
|
312
312
|
max-width: none;
|
|
313
|
-
overflow-wrap:
|
|
313
|
+
overflow-wrap: break-word;
|
|
314
314
|
white-space: normal;
|
|
315
315
|
}
|
|
316
316
|
|
|
@@ -359,6 +359,13 @@
|
|
|
359
359
|
font-weight: 500;
|
|
360
360
|
}
|
|
361
361
|
|
|
362
|
+
/* A lead cell's value reads 15px, a person's name over their function
|
|
363
|
+
(DqAfdelingen). */
|
|
364
|
+
.cn-data-table td.cn-cell--lead > .cn-cell-renderer,
|
|
365
|
+
.cn-data-table td.cn-cell--lead .cn-table-row__link > .cn-cell-renderer {
|
|
366
|
+
font-size: 15px;
|
|
367
|
+
}
|
|
368
|
+
|
|
362
369
|
.cn-data-table td.cn-cell--muted {
|
|
363
370
|
color: var(--color-text-maxcontrast);
|
|
364
371
|
}
|
|
@@ -83,22 +83,42 @@
|
|
|
83
83
|
v-for="ev in displayedEvents"
|
|
84
84
|
:key="rowKey(ev)"
|
|
85
85
|
class="cn-calendar-card__row">
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
<div class="cn-calendar-card__meta">
|
|
93
|
-
<span v-if="ev.dtstart" class="cn-calendar-card__when">{{ formatShort(ev.dtstart) }}</span>
|
|
94
|
-
<span v-if="ev.location" class="cn-calendar-card__location">· {{ ev.location }}</span>
|
|
86
|
+
<!-- The board look draws a meeting as a ruled row: its title, one
|
|
87
|
+
meta line (when, where, who) and its status at the end. -->
|
|
88
|
+
<template v-if="boardRows">
|
|
89
|
+
<div class="cn-calendar-card__row-main">
|
|
90
|
+
<span class="cn-calendar-card__title">{{ ev.summary || untitledLabel }}</span>
|
|
91
|
+
<span class="cn-calendar-card__meta" data-testid="cn-calendar-card-meta">{{ boardMetaOf(ev) }}</span>
|
|
95
92
|
</div>
|
|
96
|
-
|
|
93
|
+
<span v-if="statusOf(ev)"
|
|
94
|
+
class="cn-status-badge"
|
|
95
|
+
:class="`cn-status-badge--${statusVariantOf(ev)}`"
|
|
96
|
+
data-testid="cn-calendar-card-status">{{ statusOf(ev) }}</span>
|
|
97
|
+
</template>
|
|
98
|
+
<template v-else>
|
|
99
|
+
<div class="cn-calendar-card__row-icon">
|
|
100
|
+
<CalendarClock v-if="isUpcoming(ev)" :size="20" class="cn-calendar-card__icon--upcoming" />
|
|
101
|
+
<CalendarCheck v-else :size="20" class="cn-calendar-card__icon--past" />
|
|
102
|
+
</div>
|
|
103
|
+
<div class="cn-calendar-card__row-main">
|
|
104
|
+
<span class="cn-calendar-card__title">{{ ev.summary || untitledLabel }}</span>
|
|
105
|
+
<div class="cn-calendar-card__meta">
|
|
106
|
+
<span v-if="ev.dtstart" class="cn-calendar-card__when">{{ formatShort(ev.dtstart) }}</span>
|
|
107
|
+
<span v-if="ev.location" class="cn-calendar-card__location">· {{ ev.location }}</span>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</template>
|
|
97
111
|
</div>
|
|
112
|
+
<a v-if="boardRows"
|
|
113
|
+
class="cn-calendar-card__open"
|
|
114
|
+
:href="calendarAppUrl"
|
|
115
|
+
target="_blank"
|
|
116
|
+
rel="noopener"
|
|
117
|
+
data-testid="cn-calendar-card-open">{{ openInCalendarLabel }}</a>
|
|
98
118
|
</div>
|
|
99
119
|
|
|
100
120
|
<!-- Footer: detail surface gets "Open in NC Calendar" CTA -->
|
|
101
|
-
<template v-if="surface === 'detail-page'" #footer>
|
|
121
|
+
<template v-if="surface === 'detail-page' && !isBoard" #footer>
|
|
102
122
|
<a
|
|
103
123
|
class="cn-calendar-card__cta"
|
|
104
124
|
:href="calendarAppUrl"
|
|
@@ -144,9 +164,12 @@ import CnCalendarEventCreate from '../../../components/CnCalendarEventCreate/CnC
|
|
|
144
164
|
import CnCalendarEventPicker from '../../../components/CnCalendarEventPicker/CnCalendarEventPicker.vue'
|
|
145
165
|
import CnDetailCard from '../../../components/CnDetailCard/CnDetailCard.vue'
|
|
146
166
|
import CnIcon from '../../../components/CnIcon/CnIcon.vue'
|
|
167
|
+
import { normalizeLook } from '../../../composables/useLook.js'
|
|
168
|
+
import { formatBoardDate, formatTimeOfDay } from '../../../utils/boardDate.js'
|
|
147
169
|
import { buildHeaders, prefixUrl } from '../../../utils/index.js'
|
|
148
170
|
import { userLocale } from '../../../utils/userLocale.js'
|
|
149
171
|
import { linkCalendarEvent } from './calendarEventLink.js'
|
|
172
|
+
import { eventAttendeeNames, eventStatusLabel, eventStatusVariant } from './eventStatus.js'
|
|
150
173
|
|
|
151
174
|
/**
|
|
152
175
|
* CnCalendarCard — surface-aware compact widget for the calendar
|
|
@@ -158,6 +181,10 @@ export default {
|
|
|
158
181
|
|
|
159
182
|
components: { CnCalendarEventCreate, CnCalendarEventPicker, CnDetailCard, CnIcon, LinkVariant, NcButton, NcLoadingIcon, Plus, CalendarClock, CalendarCheck },
|
|
160
183
|
|
|
184
|
+
inject: {
|
|
185
|
+
cnLook: { default: 'nextcloud' },
|
|
186
|
+
},
|
|
187
|
+
|
|
161
188
|
props: {
|
|
162
189
|
/** OpenRegister register id (slug or uuid). Optional for user-dashboard. */
|
|
163
190
|
register: { type: String, default: '' },
|
|
@@ -233,6 +260,16 @@ export default {
|
|
|
233
260
|
*
|
|
234
261
|
* @return {Array<string>}
|
|
235
262
|
*/
|
|
263
|
+
/** @return {boolean} The board look draws ruled rows. */
|
|
264
|
+
isBoard() {
|
|
265
|
+
return normalizeLook(this.cnLook) === 'board'
|
|
266
|
+
},
|
|
267
|
+
|
|
268
|
+
/** @return {boolean} The meetings are ruled rows: the board look on a detail page. */
|
|
269
|
+
boardRows() {
|
|
270
|
+
return this.isBoard && this.surface === 'detail-page'
|
|
271
|
+
},
|
|
272
|
+
|
|
236
273
|
shownHeaderActions() {
|
|
237
274
|
if (this.surface !== 'detail-page' || !this.objectId || !Array.isArray(this.headerActions)) {
|
|
238
275
|
return []
|
|
@@ -292,6 +329,34 @@ export default {
|
|
|
292
329
|
},
|
|
293
330
|
|
|
294
331
|
methods: {
|
|
332
|
+
/**
|
|
333
|
+
* A meeting's meta line in the board look: "14 okt, 10:00 tot 10:30",
|
|
334
|
+
* its place and its attendees, separated by middots.
|
|
335
|
+
*
|
|
336
|
+
* @param {object} ev The event.
|
|
337
|
+
* @return {string}
|
|
338
|
+
*/
|
|
339
|
+
boardMetaOf(ev) {
|
|
340
|
+
const start = ev.dtstart ? new Date(ev.dtstart) : null
|
|
341
|
+
const end = ev.dtend ? new Date(ev.dtend) : null
|
|
342
|
+
let when = ''
|
|
343
|
+
if (start && !Number.isNaN(start.getTime())) {
|
|
344
|
+
when = `${formatBoardDate(start)}, ${formatTimeOfDay(start)}`
|
|
345
|
+
if (end && !Number.isNaN(end.getTime())) {
|
|
346
|
+
when = t('nextcloud-vue', '{start} until {end}', { start: when, end: formatTimeOfDay(end) })
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return [when, ev.location, ...eventAttendeeNames(ev)].filter(Boolean).join(' · ')
|
|
350
|
+
},
|
|
351
|
+
|
|
352
|
+
statusOf(ev) {
|
|
353
|
+
return eventStatusLabel(ev)
|
|
354
|
+
},
|
|
355
|
+
|
|
356
|
+
statusVariantOf(ev) {
|
|
357
|
+
return eventStatusVariant(ev)
|
|
358
|
+
},
|
|
359
|
+
|
|
295
360
|
/**
|
|
296
361
|
* A meeting was made on this object: close the form, read the list again.
|
|
297
362
|
*
|
|
@@ -242,6 +242,7 @@ import CnStatusBadge from '../../../components/CnStatusBadge/CnStatusBadge.vue'
|
|
|
242
242
|
import { buildHeaders, prefixUrl } from '../../../utils/index.js'
|
|
243
243
|
import { userLocale } from '../../../utils/userLocale.js'
|
|
244
244
|
import { linkCalendarEvent } from './calendarEventLink.js'
|
|
245
|
+
import { eventStatusLabel, eventStatusVariant } from './eventStatus.js'
|
|
245
246
|
|
|
246
247
|
const MAX_AVATARS = 3
|
|
247
248
|
|
|
@@ -542,31 +543,11 @@ export default {
|
|
|
542
543
|
},
|
|
543
544
|
|
|
544
545
|
statusLabel(ev) {
|
|
545
|
-
|
|
546
|
-
if (status === 'confirmed') {
|
|
547
|
-
return t('nextcloud-vue', 'Confirmed')
|
|
548
|
-
}
|
|
549
|
-
if (status === 'tentative') {
|
|
550
|
-
return t('nextcloud-vue', 'Tentative')
|
|
551
|
-
}
|
|
552
|
-
if (status === 'cancelled') {
|
|
553
|
-
return t('nextcloud-vue', 'Cancelled')
|
|
554
|
-
}
|
|
555
|
-
return ''
|
|
546
|
+
return eventStatusLabel(ev)
|
|
556
547
|
},
|
|
557
548
|
|
|
558
549
|
statusVariant(ev) {
|
|
559
|
-
|
|
560
|
-
if (status === 'confirmed') {
|
|
561
|
-
return 'success'
|
|
562
|
-
}
|
|
563
|
-
if (status === 'tentative') {
|
|
564
|
-
return 'warning'
|
|
565
|
-
}
|
|
566
|
-
if (status === 'cancelled') {
|
|
567
|
-
return 'error'
|
|
568
|
-
}
|
|
569
|
-
return 'default'
|
|
550
|
+
return eventStatusVariant(ev)
|
|
570
551
|
},
|
|
571
552
|
|
|
572
553
|
attendeeList(ev) {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CnCalendarCard in the board look on a detail page (DqZaakTaken
|
|
3
|
+
* "Afspraken"): each meeting is a ruled row with its title, one meta line
|
|
4
|
+
* (when, where, who) and its status at the end, and "Open in Calendar" is a
|
|
5
|
+
* link under the rows rather than a card footer.
|
|
6
|
+
*
|
|
7
|
+
* @spec openspec/changes/board-deck-calendar-rows/specs/integrations/spec.md
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { flushPromises, mount } = require('@vue/test-utils')
|
|
11
|
+
|
|
12
|
+
jest.mock('@nextcloud/router', () => ({ generateUrl: (path) => path }))
|
|
13
|
+
|
|
14
|
+
const CnCalendarCard = require('../CnCalendarCard.vue').default
|
|
15
|
+
|
|
16
|
+
const EVENT = { id: 'e1', summary: 'Toelichting stukken', dtstart: '2026-10-14T10:00:00', dtend: '2026-10-14T10:30:00', location: 'stadskantoor, balie 3', attendees: [{ name: 'Sanne de Vries' }], status: 'TENTATIVE' }
|
|
17
|
+
|
|
18
|
+
function mountCard(look) {
|
|
19
|
+
global.fetch = jest.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve({ results: [EVENT] }) })
|
|
20
|
+
return mount(CnCalendarCard, {
|
|
21
|
+
props: { register: 'reg', schema: 'case', objectId: 'c-1', surface: 'detail-page' },
|
|
22
|
+
global: { provide: { cnLook: look }, stubs: { NcLoadingIcon: true } },
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe('CnCalendarCard board rows', () => {
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
delete global.fetch
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('draws the meeting as a row with its meta line and status, and the link under the rows', async () => {
|
|
32
|
+
const w = mountCard('board')
|
|
33
|
+
await flushPromises()
|
|
34
|
+
const row = w.find('.cn-calendar-card__row')
|
|
35
|
+
expect(row.find('.cn-calendar-card__row-icon').exists()).toBe(false)
|
|
36
|
+
const meta = row.find('[data-testid="cn-calendar-card-meta"]').text()
|
|
37
|
+
expect(meta).toContain('stadskantoor, balie 3')
|
|
38
|
+
expect(meta).toContain('Sanne de Vries')
|
|
39
|
+
expect(row.find('[data-testid="cn-calendar-card-status"]').text()).toBe('Tentative')
|
|
40
|
+
expect(w.find('[data-testid="cn-calendar-card-open"]').exists()).toBe(true)
|
|
41
|
+
expect(w.find('.cn-detail-card__footer').exists()).toBe(false)
|
|
42
|
+
w.unmount()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('keeps the icon rows and the footer in the Nextcloud look', async () => {
|
|
46
|
+
const w = mountCard('nextcloud')
|
|
47
|
+
await flushPromises()
|
|
48
|
+
expect(w.find('.cn-calendar-card__row-icon').exists()).toBe(true)
|
|
49
|
+
expect(w.find('.cn-detail-card__footer').exists()).toBe(true)
|
|
50
|
+
w.unmount()
|
|
51
|
+
})
|
|
52
|
+
})
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
3
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
*
|
|
5
|
+
* A calendar event's status as a label and a badge tone, shared by the
|
|
6
|
+
* calendar tab and the calendar card.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { translate as t } from '@nextcloud/l10n'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The event's status in words, or '' when it has none the reader needs.
|
|
13
|
+
*
|
|
14
|
+
* @param {object} ev The event.
|
|
15
|
+
* @return {string}
|
|
16
|
+
*/
|
|
17
|
+
export function eventStatusLabel(ev) {
|
|
18
|
+
const status = String(ev?.status || '').toLowerCase()
|
|
19
|
+
if (status === 'confirmed') {
|
|
20
|
+
return t('nextcloud-vue', 'Confirmed')
|
|
21
|
+
}
|
|
22
|
+
if (status === 'tentative') {
|
|
23
|
+
return t('nextcloud-vue', 'Tentative')
|
|
24
|
+
}
|
|
25
|
+
if (status === 'cancelled') {
|
|
26
|
+
return t('nextcloud-vue', 'Cancelled')
|
|
27
|
+
}
|
|
28
|
+
return ''
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The badge tone of the event's status.
|
|
33
|
+
*
|
|
34
|
+
* @param {object} ev The event.
|
|
35
|
+
* @return {string} `success`, `warning`, `error` or `default`.
|
|
36
|
+
*/
|
|
37
|
+
export function eventStatusVariant(ev) {
|
|
38
|
+
const status = String(ev?.status || '').toLowerCase()
|
|
39
|
+
if (status === 'confirmed') {
|
|
40
|
+
return 'success'
|
|
41
|
+
}
|
|
42
|
+
if (status === 'tentative') {
|
|
43
|
+
return 'warning'
|
|
44
|
+
}
|
|
45
|
+
if (status === 'cancelled') {
|
|
46
|
+
return 'error'
|
|
47
|
+
}
|
|
48
|
+
return 'default'
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The names of the event's attendees.
|
|
53
|
+
*
|
|
54
|
+
* @param {object} ev The event.
|
|
55
|
+
* @return {Array<string>}
|
|
56
|
+
*/
|
|
57
|
+
export function eventAttendeeNames(ev) {
|
|
58
|
+
const raw = ev?.attendees || ev?.participants || []
|
|
59
|
+
if (!Array.isArray(raw)) {
|
|
60
|
+
return []
|
|
61
|
+
}
|
|
62
|
+
return raw.map((att) => (typeof att === 'string' ? att : (att.name || att.displayName || att.cn || att.email || ''))).filter(Boolean)
|
|
63
|
+
}
|