@conduction/nextcloud-vue 2.147.0 → 2.149.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/CnAuditTrailCard/CnAuditTrailCard.vue.js +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js +24 -7
- 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 +12 -1
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue3.js +2 -1
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnChecklistRunWidget/CnChecklistRunWidget.vue.js +1 -1
- package/dist/esm/components/CnChecklistRunWidget/CnChecklistRunWidget.vue2.js +23 -1
- package/dist/esm/components/CnChecklistRunWidget/CnChecklistRunWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnChecklistRunWidget/CnChecklistRunWidget.vue3.js +1 -1
- package/dist/esm/components/CnChecklistRunWidget/CnChecklistRunWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +34 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +71 -8
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +2 -2
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue.js +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue3.js.map +1 -1
- package/dist/esm/components/CnDeviceFramesWidget/CnDeviceFramesWidget.vue.js +1 -1
- package/dist/esm/components/CnDeviceFramesWidget/CnDeviceFramesWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnDeviceFramesWidget/CnDeviceFramesWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDuplicateWarning/CnDuplicateWarning.vue.js +1 -1
- package/dist/esm/components/CnDuplicateWarning/CnDuplicateWarning.vue2.js +64 -8
- package/dist/esm/components/CnDuplicateWarning/CnDuplicateWarning.vue2.js.map +1 -1
- package/dist/esm/components/CnDuplicateWarning/CnDuplicateWarning.vue3.js +14 -4
- package/dist/esm/components/CnDuplicateWarning/CnDuplicateWarning.vue3.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +32 -4
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js +10 -2
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +84 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +61 -33
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue.js +1 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue2.js +49 -2
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue3.js +90 -59
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnFollowingWidgetHost/CnFollowingWidgetHost.vue2.js +3 -1
- package/dist/esm/components/CnFollowingWidgetHost/CnFollowingWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnFollowingWidgetHost/CnFollowingWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue.js +1 -1
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue2.js +10 -0
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue2.js.map +1 -1
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue.js +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js +11 -0
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js +28 -21
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js +8 -0
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +3 -15
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +123 -115
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue.js +1 -1
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue2.js +4 -0
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue2.js.map +1 -1
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue3.js.map +1 -1
- package/dist/esm/components/CnStepper/CnStepper.vue.js +1 -1
- package/dist/esm/components/CnStepper/CnStepper.vue2.js.map +1 -1
- package/dist/esm/components/CnStepper/CnStepper.vue3.js.map +1 -1
- package/dist/esm/dialogs/CnAccessPurposeDialog.vue.js +1 -1
- package/dist/esm/dialogs/CnAccessPurposeDialog.vue2.js +3 -1
- package/dist/esm/dialogs/CnAccessPurposeDialog.vue2.js.map +1 -1
- package/dist/esm/dialogs/CnAccessPurposeDialog.vue3.js +26 -15
- package/dist/esm/dialogs/CnAccessPurposeDialog.vue3.js.map +1 -1
- package/dist/esm/l10n/en.json.js +3 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +3 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +785 -518
- package/dist/esm/utils/builtInFormatters.js +53 -1
- package/dist/esm/utils/builtInFormatters.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +2688 -2154
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +785 -518
- package/l10n/en.json +3 -1
- package/l10n/nl.json +3 -1
- package/package.json +1 -1
- package/src/components/CnAuditTrailCard/CnAuditTrailCard.vue +24 -7
- package/src/components/CnAuditTrailWidget/CnAuditTrailWidget.vue +13 -1
- package/src/components/CnChecklistRunWidget/CnChecklistRunWidget.vue +29 -2
- package/src/components/CnDataTable/CnDataTable.vue +34 -1
- package/src/components/CnDetailPage/CnDetailPage.md +1 -1
- package/src/components/CnDetailPage/CnDetailPage.vue +73 -10
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue +6 -1
- package/src/components/CnDeviceFramesWidget/CnDeviceFramesWidget.vue +1 -0
- package/src/components/CnDuplicateWarning/CnDuplicateWarning.vue +74 -10
- package/src/components/CnFactsWidget/CnFactsWidget.vue +41 -4
- package/src/components/CnFieldListWidget/CnFieldListWidget.vue +131 -3
- package/src/components/CnFlowRunsWidget/CnFlowRunsWidget.vue +103 -5
- package/src/components/CnFollowingWidgetHost/CnFollowingWidgetHost.vue +3 -1
- package/src/components/CnNotesCard/CnNotesCard.vue +10 -0
- package/src/components/CnObjectCard/CnObjectCard.vue +16 -0
- package/src/components/CnObjectDataWidget/CnObjectDataWidget.md +1 -1
- package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +8 -0
- package/src/components/CnObjectListWidget/CnObjectListWidget.vue +1 -1
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +19 -19
- package/src/components/CnRegisterMapping/CnRegisterMapping.vue +4 -0
- package/src/components/CnStepper/CnStepper.vue +10 -2
- package/src/css/dialog.css +22 -2
- package/src/css/look-board-detail.css +52 -3
- package/src/css/look-board-index.css +51 -1
- package/src/css/look-board.css +48 -5
- package/src/css/table.css +5 -2
- package/src/dialogs/CnAccessPurposeDialog.vue +27 -12
- package/src/schemas/app-manifest-v2.schema.json +4 -2
- package/src/utils/builtInFormatters.js +52 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
|
@@ -61,7 +61,8 @@
|
|
|
61
61
|
:data-testid="`cn-record-list-sort-${col.key}`"
|
|
62
62
|
@click="toggleTableSort(col.key)">
|
|
63
63
|
{{ col.label }}
|
|
64
|
-
<
|
|
64
|
+
<ChevronUp v-if="sortStateOf(col.key) === 'ascending'" class="cn-record-list__sort-mark" :size="14" />
|
|
65
|
+
<ChevronDown v-else class="cn-record-list__sort-mark" :size="14" />
|
|
65
66
|
</button>
|
|
66
67
|
<template v-else>
|
|
67
68
|
{{ col.label }}
|
|
@@ -575,7 +576,9 @@ import { generateUrl } from '@nextcloud/router'
|
|
|
575
576
|
import { NcActionButton, NcActionCheckbox, NcActionLink, NcActions, NcButton, NcLoadingIcon } from '@nextcloud/vue'
|
|
576
577
|
import { inject, ref } from 'vue'
|
|
577
578
|
import Check from 'vue-material-design-icons/Check.vue'
|
|
579
|
+
import ChevronDown from 'vue-material-design-icons/ChevronDown.vue'
|
|
578
580
|
import ChevronRight from 'vue-material-design-icons/ChevronRight.vue'
|
|
581
|
+
import ChevronUp from 'vue-material-design-icons/ChevronUp.vue'
|
|
579
582
|
import FilterOutline from 'vue-material-design-icons/FilterOutline.vue'
|
|
580
583
|
import CnIcon from '../CnIcon/CnIcon.vue'
|
|
581
584
|
import CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'
|
|
@@ -672,7 +675,7 @@ function unwrap(value) {
|
|
|
672
675
|
export default {
|
|
673
676
|
name: 'CnRecordListWidget',
|
|
674
677
|
|
|
675
|
-
components: { Check, ChevronRight, CnIcon, CnRecordNoteRows, CnStatusBadge, FilterOutline, NcActionButton, NcActionCheckbox, NcActionLink, NcActions, NcButton, NcLoadingIcon },
|
|
678
|
+
components: { Check, ChevronDown, ChevronRight, ChevronUp, CnIcon, CnRecordNoteRows, CnStatusBadge, FilterOutline, NcActionButton, NcActionCheckbox, NcActionLink, NcActions, NcButton, NcLoadingIcon },
|
|
676
679
|
|
|
677
680
|
inject: {
|
|
678
681
|
/** Detail-page object context (`{ objectId, object, register, schema }`). */
|
|
@@ -2269,20 +2272,6 @@ export default {
|
|
|
2269
2272
|
return this.tableSort.key === key && this.tableSort.dir ? this.tableSort.dir : 'none'
|
|
2270
2273
|
},
|
|
2271
2274
|
|
|
2272
|
-
/**
|
|
2273
|
-
* The arrow after a sortable column's label.
|
|
2274
|
-
*
|
|
2275
|
-
* @param {string} key The column key.
|
|
2276
|
-
* @return {string} An up or down arrow, or '' while the column is not the sort.
|
|
2277
|
-
*/
|
|
2278
|
-
sortMarkOf(key) {
|
|
2279
|
-
const state = this.sortStateOf(key)
|
|
2280
|
-
if (state === 'ascending') {
|
|
2281
|
-
return '▲'
|
|
2282
|
-
}
|
|
2283
|
-
return state === 'descending' ? '▼' : ''
|
|
2284
|
-
},
|
|
2285
|
-
|
|
2286
2275
|
/**
|
|
2287
2276
|
* Sort the `table` by a column: ascending first, then descending.
|
|
2288
2277
|
*
|
|
@@ -3312,7 +3301,7 @@ export default {
|
|
|
3312
3301
|
}
|
|
3313
3302
|
|
|
3314
3303
|
.cn-record-list__sort-mark {
|
|
3315
|
-
|
|
3304
|
+
color: var(--color-text-maxcontrast);
|
|
3316
3305
|
}
|
|
3317
3306
|
|
|
3318
3307
|
.cn-record-list__head {
|
|
@@ -3321,8 +3310,14 @@ export default {
|
|
|
3321
3310
|
align-items: center;
|
|
3322
3311
|
}
|
|
3323
3312
|
|
|
3324
|
-
|
|
3313
|
+
/* The funnel is a 22px control, as the boards draw it beside a head, not
|
|
3314
|
+
NcActions' 34px trigger that made the head row 54px. */
|
|
3315
|
+
.cn-record-list__head-filter :deep(.button-vue) {
|
|
3325
3316
|
--button-size: 22px;
|
|
3317
|
+
width: 22px;
|
|
3318
|
+
min-width: 22px;
|
|
3319
|
+
height: 22px;
|
|
3320
|
+
min-height: 22px;
|
|
3326
3321
|
}
|
|
3327
3322
|
|
|
3328
3323
|
.cn-record-list__table .cn-record-list__cell--end {
|
|
@@ -3413,11 +3408,16 @@ export default {
|
|
|
3413
3408
|
font-weight: 600;
|
|
3414
3409
|
height: 34px;
|
|
3415
3410
|
justify-content: center;
|
|
3416
|
-
margin: 0;
|
|
3417
3411
|
padding: 0 14px;
|
|
3418
3412
|
text-decoration: none;
|
|
3419
3413
|
}
|
|
3420
3414
|
|
|
3415
|
+
/* server.css gives every button `margin: 3px 3px 3px 0` at (0,2,1); the
|
|
3416
|
+
doubled class outranks it. */
|
|
3417
|
+
.cn-record-list__action.cn-record-list__action {
|
|
3418
|
+
margin: 0;
|
|
3419
|
+
}
|
|
3420
|
+
|
|
3421
3421
|
.cn-record-list__action:hover,
|
|
3422
3422
|
.cn-record-list__action:focus-visible {
|
|
3423
3423
|
background: var(--color-primary-element-light-hover, var(--color-primary-element-light));
|
|
@@ -1094,6 +1094,10 @@ export default {
|
|
|
1094
1094
|
const results = data.results || data
|
|
1095
1095
|
this.registers = Array.isArray(results) ? results : []
|
|
1096
1096
|
this.registersLoaded = true
|
|
1097
|
+
// A configuration that arrived while the registers were loading
|
|
1098
|
+
// skipped its schema read (the watcher waits for the registers),
|
|
1099
|
+
// so read the mapped registers' schemas now.
|
|
1100
|
+
this.mappedRegisterIds().forEach((id) => this.loadSchemasForRegister(id))
|
|
1097
1101
|
} catch (error) {
|
|
1098
1102
|
this.registersError = error.message || t('nextcloud-vue', 'The registers could not be loaded: {reason}', { reason: t('nextcloud-vue', 'no connection') })
|
|
1099
1103
|
} finally {
|
|
@@ -154,6 +154,14 @@ export default {
|
|
|
154
154
|
font: inherit;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
/* Nextcloud's server.css gives every plain button a 3px margin and the
|
|
158
|
+
clickable-area height (`button:not(.button-vue, …):not(…)`, 0,2,1), which
|
|
159
|
+
made a done step 40px tall around its 28px circle. Two classes outrank it. */
|
|
160
|
+
.cn-stepper button.cn-stepper__step {
|
|
161
|
+
margin: 0;
|
|
162
|
+
min-height: 0;
|
|
163
|
+
}
|
|
164
|
+
|
|
157
165
|
button.cn-stepper__step {
|
|
158
166
|
cursor: pointer;
|
|
159
167
|
}
|
|
@@ -230,14 +238,14 @@ button.cn-stepper__step {
|
|
|
230
238
|
}
|
|
231
239
|
|
|
232
240
|
/* The board look: one row, 28px circles, the label beside the circle. */
|
|
233
|
-
/* The board leaves
|
|
241
|
+
/* The board leaves 16px between the stepper and the step's body (DqInstellen). */
|
|
234
242
|
.cn-stepper--board {
|
|
235
243
|
flex-wrap: wrap;
|
|
236
244
|
align-items: center;
|
|
237
245
|
justify-content: flex-start;
|
|
238
246
|
gap: 8px;
|
|
239
247
|
padding: 0;
|
|
240
|
-
margin: 0 0
|
|
248
|
+
margin: 0 0 16px;
|
|
241
249
|
}
|
|
242
250
|
|
|
243
251
|
.cn-stepper--board .cn-stepper__item {
|
package/src/css/dialog.css
CHANGED
|
@@ -265,8 +265,11 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .modal-mask {
|
|
|
265
265
|
margin-bottom: 4px;
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
-
/* Footer: 16px 24px, hairline on top, right aligned, 40px buttons, 10px gap
|
|
269
|
-
|
|
268
|
+
/* Footer: 16px 24px, hairline on top, right aligned, 40px buttons, 10px gap,
|
|
269
|
+
flush with the dialog's bottom. NcDialog's own footer rule (6px 0 12px
|
|
270
|
+
margin, 12px end padding) ties a two-class selector and wins when its
|
|
271
|
+
stylesheet loads later, so `.dialog` is added to outrank it. */
|
|
272
|
+
.cn-dialog-board .dialog .dialog__actions {
|
|
270
273
|
display: flex;
|
|
271
274
|
flex-wrap: wrap;
|
|
272
275
|
align-items: center;
|
|
@@ -592,3 +595,20 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .modal-mask {
|
|
|
592
595
|
max-height: calc(100% - var(--cn-dialog-top, 88px) - 24px);
|
|
593
596
|
}
|
|
594
597
|
}
|
|
598
|
+
|
|
599
|
+
/* The chosen option's fields start 12px under its description, the label on
|
|
600
|
+
the normal line, as DqVolgendeStap draws "Opschorten": the row's 12px
|
|
601
|
+
bottom padding plus the cell's 8px gap and a 21px label line put them
|
|
602
|
+
11.6px lower (r31).
|
|
603
|
+
@spec openspec/changes/board-choice-card-fields-under-the-text/specs/dialog/spec.md */
|
|
604
|
+
.cn-dialog-board .cn-choice-cards .cn-choice-cards__cell--with-details {
|
|
605
|
+
gap: 12px;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
.cn-dialog-board .cn-choice-cards .cn-choice-cards__cell--with-details .cn-choice-cards__row {
|
|
609
|
+
padding-bottom: 0;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
.cn-dialog-board .cn-transition-input-fields .cn-transition-input-fields__label {
|
|
613
|
+
line-height: normal;
|
|
614
|
+
}
|
|
@@ -751,6 +751,14 @@
|
|
|
751
751
|
padding: calc(12px - var(--cn-board-first-line-leading)) var(--cn-board-card-inline-padding) 20px;
|
|
752
752
|
}
|
|
753
753
|
|
|
754
|
+
/* A card that opens on a record-list table starts 12px under its title: the
|
|
755
|
+
table's head row sets its own padding and line height, so no first line
|
|
756
|
+
carries the half-leading the rule above takes off (r31 DqZaaktype
|
|
757
|
+
"Berichten aan de aanvrager" sat 2.2px high). */
|
|
758
|
+
.cn-look-board .cn-detail-page .cn-widget-wrapper__content:has(> .cn-record-list > .cn-record-list__table:first-child):not(.cn-look-nextcloud *) {
|
|
759
|
+
padding-top: 12px;
|
|
760
|
+
}
|
|
761
|
+
|
|
754
762
|
/* A history card with stacked rows (DqTaak "Historie") opens on the first
|
|
755
763
|
row's hairline 6px under the title, the row's own 12px padding above its
|
|
756
764
|
text, as drawn: 19px from the title to the first action.
|
|
@@ -841,6 +849,15 @@
|
|
|
841
849
|
font-weight: 500;
|
|
842
850
|
}
|
|
843
851
|
|
|
852
|
+
/* The files table's checkbox column is the board's 42px (12px either side
|
|
853
|
+
of the 18px box): DqZaakDocumenten and DqDocumentenBeheer both draw it so.
|
|
854
|
+
The component's 36px pushed the file icon and name 6px left (r31: name 96
|
|
855
|
+
vs 100; probed with the rule: icon 54 as drawn, name 102).
|
|
856
|
+
@spec openspec/changes/board-files-select-column-42/specs/board-files-select-column-42/spec.md#requirement-the-files-tables-checkbox-column-is-42px */
|
|
857
|
+
.cn-look-board .cn-files-browser__col-select:not(.cn-look-nextcloud *) {
|
|
858
|
+
width: 42px;
|
|
859
|
+
}
|
|
860
|
+
|
|
844
861
|
/* A labelled select in a page card is the board's field, as in a board
|
|
845
862
|
dialog (dialog.css): its label above the control at 14px/600 on the normal
|
|
846
863
|
line (the theme's label weight token set to 600 here), the control 40px,
|
|
@@ -1584,10 +1601,10 @@
|
|
|
1584
1601
|
|
|
1585
1602
|
/* The buttons above the groups are the card's 34px controls ("Bekijken als
|
|
1586
1603
|
flow", "Taak toevoegen"), not the page's 40px ones. */
|
|
1587
|
-
/* The buttons sit 14px
|
|
1588
|
-
|
|
1604
|
+
/* The buttons sit 14px above the groups, the card's gap; above them the
|
|
1605
|
+
content's own top padding is the space under the subtitle. */
|
|
1589
1606
|
.cn-look-board .cn-grouped-cards__actions.cn-grouped-cards__actions:not(.cn-look-nextcloud *) {
|
|
1590
|
-
margin-block:
|
|
1607
|
+
margin-block: 0 14px;
|
|
1591
1608
|
}
|
|
1592
1609
|
|
|
1593
1610
|
.cn-look-board .cn-grouped-cards__actions:not(.cn-look-nextcloud *) .button-vue {
|
|
@@ -2379,3 +2396,35 @@
|
|
|
2379
2396
|
.cn-look-board .cn-timeline-manage__draft-label:not(.cn-look-nextcloud *) {
|
|
2380
2397
|
line-height: 1.2;
|
|
2381
2398
|
}
|
|
2399
|
+
|
|
2400
|
+
/* A facts card's link with an icon (Werkinstructie) sets the icon beside its
|
|
2401
|
+
text, 10px apart, the text on the normal line starting 10px under the
|
|
2402
|
+
title, as the Dq boards draw it. The anchor was a block, so the icon stood
|
|
2403
|
+
on its own line above the text (r31).
|
|
2404
|
+
@spec openspec/changes/board-facts-link-icon-beside-text/specs/facts-widget/spec.md */
|
|
2405
|
+
.cn-look-board .cn-facts-widget .cn-facts-widget__link:has(> .material-design-icon):not(.cn-look-nextcloud *) {
|
|
2406
|
+
display: flex;
|
|
2407
|
+
align-items: center;
|
|
2408
|
+
gap: 10px;
|
|
2409
|
+
margin-top: var(--cn-board-first-line-leading);
|
|
2410
|
+
line-height: normal;
|
|
2411
|
+
}
|
|
2412
|
+
|
|
2413
|
+
/* A table in a detail page card names each row in the link colour at 14px,
|
|
2414
|
+
as DqZaakGerelateerd draws "Deelzaken" and "Objecten" (r31: 15px in the
|
|
2415
|
+
body ink). The row opens the record, so its name reads as the link.
|
|
2416
|
+
@spec openspec/changes/board-detail-table-title-cells/specs/board-tables/spec.md */
|
|
2417
|
+
.cn-look-board .cn-detail-page .cn-object-list-widget td.cn-table-col--title:not(.cn-look-nextcloud *),
|
|
2418
|
+
.cn-look-board .cn-detail-page .cn-object-list-widget td.cn-table-col--title .cn-cell-renderer:not(.cn-look-nextcloud *) {
|
|
2419
|
+
font-size: 14px;
|
|
2420
|
+
line-height: 1.2;
|
|
2421
|
+
color: var(--color-primary-element);
|
|
2422
|
+
}
|
|
2423
|
+
|
|
2424
|
+
/* A data card keeps its 14px under a subtitle too (DqZaakBetrokkenen
|
|
2425
|
+
"Zetels"): the subtitle rule's 12px won over the data card's 14px, so the
|
|
2426
|
+
labels sat 2.2px high (r31).
|
|
2427
|
+
@spec openspec/changes/board-data-card-under-subtitle/specs/board-card/spec.md */
|
|
2428
|
+
.cn-look-board .cn-detail-page .cn-widget-wrapper:not(.cn-detail-page__side *):has(> .cn-widget-wrapper__header .cn-widget-wrapper__subtitle) > .cn-widget-wrapper__content:has(> .cn-object-data-widget__grid-wrap) {
|
|
2429
|
+
padding-top: 14px;
|
|
2430
|
+
}
|
|
@@ -1079,8 +1079,9 @@
|
|
|
1079
1079
|
@spec openspec/changes/board-avatar-chip/specs/data-table/spec.md#requirement-a-board-avatar-cell-draws-the-initials-chip */
|
|
1080
1080
|
.cn-look-board .cn-table-container--board .cn-data-table .cn-cell-renderer__avatar-initials--neutral {
|
|
1081
1081
|
background: var(--color-background-dark);
|
|
1082
|
-
color: var(--
|
|
1082
|
+
color: var(--cn-board-text-soft);
|
|
1083
1083
|
font-size: 13px;
|
|
1084
|
+
line-height: normal;
|
|
1084
1085
|
}
|
|
1085
1086
|
|
|
1086
1087
|
.cn-look-board .cn-table-container--board .cn-data-table .cn-cell-renderer__avatar:has(.cn-cell-renderer__avatar-initials--neutral) {
|
|
@@ -1703,9 +1704,19 @@
|
|
|
1703
1704
|
--app-sidebar-width: 360px;
|
|
1704
1705
|
}
|
|
1705
1706
|
|
|
1707
|
+
/* The subtitle 2px under the title at a normal line height, and the tab's
|
|
1708
|
+
content 20px in from the panel edge (the tab's 10px and 10px here), as
|
|
1709
|
+
DqFilterBeheren draws the side panel.
|
|
1710
|
+
@spec openspec/changes/board-side-panel-rhythm/specs/board-side-panel-rhythm/spec.md */
|
|
1706
1711
|
.cn-look-board:has(.cn-index-page) > .app-sidebar .app-sidebar-header__subname {
|
|
1712
|
+
margin-top: 2px;
|
|
1707
1713
|
color: var(--color-text-maxcontrast);
|
|
1708
1714
|
font-size: 14px;
|
|
1715
|
+
line-height: normal;
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
.cn-look-board:has(.cn-index-page) > .app-sidebar .cn-index-sidebar__section {
|
|
1719
|
+
padding: 10px;
|
|
1709
1720
|
}
|
|
1710
1721
|
|
|
1711
1722
|
.cn-look-board:has(.cn-index-page) > .app-sidebar .app-sidebar__close {
|
|
@@ -1924,9 +1935,33 @@
|
|
|
1924
1935
|
@spec openspec/changes/board-index-sidebar-title-inset/specs/board-index-sidebar-title-inset/spec.md#requirement-the-index-side-panel-title-is-inset-as-the-board-draws-it */
|
|
1925
1936
|
.cn-look-board .cn-index-sidebar-panel .app-sidebar-header.app-sidebar-header .app-sidebar-header__info .app-sidebar-header__desc.app-sidebar-header__desc {
|
|
1926
1937
|
padding-block-start: 15px;
|
|
1938
|
+
padding-block-end: 0;
|
|
1927
1939
|
padding-inline-start: 20px;
|
|
1928
1940
|
}
|
|
1929
1941
|
|
|
1942
|
+
/* The line under the title is a paragraph the theme sets with `!important`
|
|
1943
|
+
(15px, its own leading): 14px muted at its normal leading, 2px under the
|
|
1944
|
+
title, so the tab row starts 14px under it and the first field 20px under
|
|
1945
|
+
the tabs (DqZakenSorteren, DqFilterBeheren: title 20, line 46, tabs 77,
|
|
1946
|
+
search field 137).
|
|
1947
|
+
@spec openspec/changes/board-side-panel-header-rhythm/specs/board-side-panel-header-rhythm/spec.md#requirement-the-side-panel-header-and-first-field-sit-as-the-boards-draw-them */
|
|
1948
|
+
.cn-look-board .cn-index-sidebar-panel .app-sidebar-header__subname {
|
|
1949
|
+
--nldesign-component-paragraph-font-size: 14px;
|
|
1950
|
+
--nldesign-component-paragraph-line-height: normal;
|
|
1951
|
+
--nldesign-component-paragraph-color: var(--color-text-maxcontrast);
|
|
1952
|
+
font-size: 14px !important;
|
|
1953
|
+
line-height: normal !important;
|
|
1954
|
+
margin-block-start: -3px !important;
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
.cn-look-board .cn-index-sidebar-panel .cn-index-sidebar__tab-content > .cn-index-sidebar__section:first-child {
|
|
1958
|
+
padding-top: 8px;
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
.cn-look-board .cn-index-sidebar-panel .cn-index-sidebar__tab-content > .cn-index-sidebar__section:first-child > .input-field {
|
|
1962
|
+
margin-top: 0;
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1930
1965
|
.cn-look-board .cn-index-sidebar-panel .app-sidebar-tabs__nav[role="tablist"] {
|
|
1931
1966
|
justify-content: flex-start;
|
|
1932
1967
|
gap: 4px;
|
|
@@ -2119,6 +2154,7 @@
|
|
|
2119
2154
|
.cn-look-board .cn-saved-views-panel:not(.cn-look-nextcloud *) .cn-saved-views-panel__name-text {
|
|
2120
2155
|
font-size: 14px;
|
|
2121
2156
|
font-weight: 600;
|
|
2157
|
+
line-height: normal;
|
|
2122
2158
|
}
|
|
2123
2159
|
|
|
2124
2160
|
/* A view's count: a grey pill at the end of its row (DqFilterBeheren). */
|
|
@@ -2363,6 +2399,20 @@
|
|
|
2363
2399
|
padding-inline-start: 12px;
|
|
2364
2400
|
}
|
|
2365
2401
|
|
|
2402
|
+
/* The boards draw the leading icon inside the title cell, so the title's
|
|
2403
|
+
heading starts over the icon (DqOrganisaties "Naam" at 76, the icon's x),
|
|
2404
|
+
as an avatar shares its column's heading (DqContacten). The blank icon
|
|
2405
|
+
heading stays for the column count; the title heading reaches back over it.
|
|
2406
|
+
@spec openspec/changes/board-head-over-row-icon/specs/data-table/spec.md#requirement-a-board-title-heading-starts-over-the-row-icon */
|
|
2407
|
+
.cn-look-board .cn-table-container--board .cn-data-table th.cn-table-col--icon + th:not(.cn-look-nextcloud *) {
|
|
2408
|
+
padding-inline-start: 0;
|
|
2409
|
+
overflow: visible;
|
|
2410
|
+
}
|
|
2411
|
+
|
|
2412
|
+
.cn-look-board .cn-table-container--board .cn-data-table th.cn-table-col--icon + th:not(.cn-look-nextcloud *) > :first-child {
|
|
2413
|
+
margin-inline-start: -32px;
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2366
2416
|
/* ---- The table beside the open side panel (DqZakenSorteren, DqFilterBeheren) */
|
|
2367
2417
|
/* The table takes its column's width: its configured column widths make way
|
|
2368
2418
|
for the content, titles and names wrap (a long word hyphenated, an
|
package/src/css/look-board.css
CHANGED
|
@@ -942,14 +942,15 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
942
942
|
}
|
|
943
943
|
|
|
944
944
|
/* A saved view's manage menu (DqFilterBeheren, DqFilterInMenu "Beheer
|
|
945
|
-
<view>"):
|
|
945
|
+
<view>"): 278px wide outside (the board's 264px of content, 6px in and a
|
|
946
|
+
1px line), rows of at least 40px, 6px 10px in, 8px rounded,
|
|
946
947
|
the icon 12px before a 14px label at 600 with its explanation under it in
|
|
947
948
|
12px muted text at 400; the separator in the soft line, and Delete in the
|
|
948
949
|
error red. Its rows carry the panel's `cn-saved-views-` test ids.
|
|
949
950
|
@spec openspec/changes/board-saved-view-manage-menu/specs/board-saved-view-manage-menu/spec.md#requirement-a-saved-views-manage-menu-is-the-boards-menu */
|
|
950
951
|
body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-item__popper:has(li[data-testid^="cn-saved-views-"]) .v-popper__wrapper .v-popper__inner {
|
|
951
952
|
box-sizing: border-box;
|
|
952
|
-
width:
|
|
953
|
+
width: 278px;
|
|
953
954
|
max-width: calc(100vw - 32px);
|
|
954
955
|
}
|
|
955
956
|
|
|
@@ -1520,8 +1521,8 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
1520
1521
|
text-align: start;
|
|
1521
1522
|
}
|
|
1522
1523
|
|
|
1523
|
-
/* Body
|
|
1524
|
-
A row header (dossiq's prerequisites) reads as a strong cell, not as a
|
|
1524
|
+
/* Body cells read 14px at 1.2, as the boards' settings tables do; a row's
|
|
1525
|
+
height comes from its content (a pill or a 34px button). A row header (dossiq's prerequisites) reads as a strong cell, not as a
|
|
1525
1526
|
head: the theme paints every th, so its tokens are handed the cell's. */
|
|
1526
1527
|
.cn-look-board .settings-section table:not(.cn-data-table):not(.cn-look-nextcloud *) td,
|
|
1527
1528
|
.cn-look-board .settings-section table:not(.cn-data-table):not(.cn-look-nextcloud *) tbody th {
|
|
@@ -1529,7 +1530,7 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
1529
1530
|
border-bottom: 1px solid var(--color-background-dark);
|
|
1530
1531
|
color: var(--color-main-text);
|
|
1531
1532
|
font-size: 14px;
|
|
1532
|
-
line-height: 1.
|
|
1533
|
+
line-height: 1.2;
|
|
1533
1534
|
vertical-align: middle;
|
|
1534
1535
|
}
|
|
1535
1536
|
|
|
@@ -1660,6 +1661,38 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
1660
1661
|
min-width: 0;
|
|
1661
1662
|
}
|
|
1662
1663
|
|
|
1664
|
+
/* A settings card's first line sits where the boards draw it: an
|
|
1665
|
+
"Uitleg tonen" link, a switch or a note adds no height beyond its text, so
|
|
1666
|
+
the first text is 16px under the subtitle (DqBeheerinstellingen
|
|
1667
|
+
"Zaak-e-mail" and "AI-ondersteunde verwerking", DqBeheerGeavanceerd "KCC"
|
|
1668
|
+
and "Storeregister": 7px and 29px lower live). The controls keep their full
|
|
1669
|
+
hit area; the negative margin only takes it out of the line.
|
|
1670
|
+
@spec openspec/changes/board-settings-first-line/specs/settings-board-look/spec.md */
|
|
1671
|
+
.cn-look-board .cn-settings-fields__hints-toggle:not(.cn-look-nextcloud *) {
|
|
1672
|
+
margin-block: -8px;
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
.cn-look-board .cn-settings-field--switch:not(.cn-look-nextcloud *) > .checkbox-radio-switch {
|
|
1676
|
+
margin-block: -8px;
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
.cn-look-board .cn-settings-field--status:not(.cn-look-nextcloud *) > .notecard {
|
|
1680
|
+
margin: 0;
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
/* A card's longer explanation reads as the boards' second paragraph: 14px
|
|
1684
|
+
muted at 1.5, the fields 14px under it (DqBeheerGeavanceerd "Urgentie in de
|
|
1685
|
+
werkvoorraad": 15px and 30px live). The theme sizes every paragraph through
|
|
1686
|
+
its tokens. */
|
|
1687
|
+
.cn-look-board .cn-settings-section__description-text:not(.cn-look-nextcloud *) {
|
|
1688
|
+
--nldesign-component-paragraph-font-size: 14px;
|
|
1689
|
+
--nldesign-component-paragraph-line-height: 1.5;
|
|
1690
|
+
--nldesign-component-paragraph-color: var(--color-text-maxcontrast);
|
|
1691
|
+
margin: 0;
|
|
1692
|
+
font-size: 14px;
|
|
1693
|
+
line-height: 1.5;
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1663
1696
|
@container (max-width: 400px) {
|
|
1664
1697
|
.cn-look-board .settings-section:not(.cn-look-nextcloud *) > .cn-settings-section__actions,
|
|
1665
1698
|
.cn-look-board .settings-section:not(.cn-look-nextcloud *):has(> .settings-section__desc) > .cn-settings-section__actions {
|
|
@@ -2614,6 +2647,12 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
2614
2647
|
font-weight: 500;
|
|
2615
2648
|
}
|
|
2616
2649
|
|
|
2650
|
+
/* A compact card keeps its 15px/700 title on a dashboard page too (DqInspectie). */
|
|
2651
|
+
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list--compact .cn-record-list__card .cn-record-list__title {
|
|
2652
|
+
font-weight: 700;
|
|
2653
|
+
line-height: 1.2;
|
|
2654
|
+
}
|
|
2655
|
+
|
|
2617
2656
|
.cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-record-list--compact .cn-record-list__main {
|
|
2618
2657
|
gap: 2px;
|
|
2619
2658
|
}
|
|
@@ -3220,6 +3259,8 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
3220
3259
|
Nextcloud's input height stretched it to 13x36. Its weight outranks the
|
|
3221
3260
|
18px other native radios take.
|
|
3222
3261
|
@spec openspec/changes/board-setup-choice-radio/specs/board-setup-choice-radio/spec.md#requirement-a-setup-steps-choice-radio-is-20px */
|
|
3262
|
+
/* The board's native radio keeps the browser's 3px end margin before the
|
|
3263
|
+
12px gap, so the option title starts 56px in (DqInstellen), not 53. */
|
|
3223
3264
|
.cn-look-board .cn-setup-step .cn-choice-cards input.cn-choice-cards__row-input:not(.cn-look-nextcloud *) {
|
|
3224
3265
|
box-sizing: border-box;
|
|
3225
3266
|
width: 20px;
|
|
@@ -3227,6 +3268,7 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
3227
3268
|
height: 20px;
|
|
3228
3269
|
min-height: 20px;
|
|
3229
3270
|
accent-color: var(--color-primary-element);
|
|
3271
|
+
margin-inline-end: 3px;
|
|
3230
3272
|
}
|
|
3231
3273
|
|
|
3232
3274
|
/* The chosen setup choice is edged by a real 2px border, as DqInstellen
|
|
@@ -3469,4 +3511,5 @@ html :where(.cn-look-board) :is(h2, h3, h5, h6):where(.cn-inner-heading) {
|
|
|
3469
3511
|
.cn-look-board .cn-saved-view-share__mode:not(.cn-look-nextcloud *) {
|
|
3470
3512
|
border-radius: 8px;
|
|
3471
3513
|
background: var(--cn-board-sunken-ground);
|
|
3514
|
+
line-height: normal;
|
|
3472
3515
|
}
|
package/src/css/table.css
CHANGED
|
@@ -616,10 +616,13 @@
|
|
|
616
616
|
cursor: grab;
|
|
617
617
|
}
|
|
618
618
|
|
|
619
|
-
/* The handle before a reorderable row's name: a muted 16px grip 10px before
|
|
619
|
+
/* The handle before a reorderable row's name: a muted 16px grip 10px before
|
|
620
|
+
it. It floats, so a name that wraps in a narrow cell wraps beside the grip
|
|
621
|
+
instead of dropping under it. */
|
|
620
622
|
.cn-table-row__handle {
|
|
621
623
|
display: inline-flex;
|
|
622
|
-
|
|
624
|
+
float: inline-start;
|
|
625
|
+
margin-block-start: 1px;
|
|
623
626
|
margin-inline-end: 10px;
|
|
624
627
|
color: var(--color-text-maxcontrast);
|
|
625
628
|
cursor: grab;
|
|
@@ -17,17 +17,23 @@
|
|
|
17
17
|
<legend class="cn-access-purpose__legend">
|
|
18
18
|
{{ t('nextcloud-vue', 'Purpose') }}
|
|
19
19
|
</legend>
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
<template v-for="option in choices" :key="option.value">
|
|
21
|
+
<NcCheckboxRadioSwitch
|
|
22
|
+
v-model="purpose"
|
|
23
|
+
type="radio"
|
|
24
|
+
name="cn-access-purpose"
|
|
25
|
+
:value="option.value"
|
|
26
|
+
:disabled="loading"
|
|
27
|
+
:data-testid="`cn-access-purpose-option-${option.value}`">
|
|
28
|
+
{{ option.label }}
|
|
29
|
+
</NcCheckboxRadioSwitch>
|
|
30
|
+
<!-- What choosing this purpose does besides recording it ("you become this case's handler"). -->
|
|
31
|
+
<p v-if="option.hint"
|
|
32
|
+
class="cn-access-purpose__hint"
|
|
33
|
+
:data-testid="`cn-access-purpose-hint-${option.value}`">
|
|
34
|
+
{{ option.hint }}
|
|
35
|
+
</p>
|
|
36
|
+
</template>
|
|
31
37
|
</fieldset>
|
|
32
38
|
<NcTextArea
|
|
33
39
|
v-if="purpose === OTHER"
|
|
@@ -94,8 +100,10 @@ export default {
|
|
|
94
100
|
|
|
95
101
|
/**
|
|
96
102
|
* The purposes offered, already translated. "Other" is added at the end.
|
|
103
|
+
* A `hint` is a line under the option that says what choosing it does
|
|
104
|
+
* besides recording it.
|
|
97
105
|
*
|
|
98
|
-
* @type {Array<{value: string, label: string}>}
|
|
106
|
+
* @type {Array<{value: string, label: string, hint?: string}>}
|
|
99
107
|
*/
|
|
100
108
|
options: {
|
|
101
109
|
type: Array,
|
|
@@ -176,6 +184,13 @@ export default {
|
|
|
176
184
|
border: 0;
|
|
177
185
|
}
|
|
178
186
|
|
|
187
|
+
.cn-access-purpose__hint {
|
|
188
|
+
margin: 0 0 6px;
|
|
189
|
+
padding-inline-start: 36px;
|
|
190
|
+
color: var(--color-text-maxcontrast);
|
|
191
|
+
font-size: 13px;
|
|
192
|
+
}
|
|
193
|
+
|
|
179
194
|
.cn-access-purpose__legend {
|
|
180
195
|
margin-bottom: 4px;
|
|
181
196
|
font-weight: 600;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"$id": "https://raw.githubusercontent.com/ConductionNL/nextcloud-vue/main/src/schemas/app-manifest-v2.schema.json",
|
|
4
4
|
"title": "Conduction App Manifest v2",
|
|
5
5
|
"description": "v2 schema for the JSON-driven page and navigation manifest consumed by @conduction/nextcloud-vue. Introduces a uniform widgets[] array on every page type with a per-slot grid coordinate system, a typed actions[] discriminator, and the required $schema field for version detection. v1 manifests continue to validate against app-manifest.schema.json (unchanged).",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.157.0",
|
|
7
7
|
"type": "object",
|
|
8
8
|
"required": ["$schema", "version"],
|
|
9
9
|
"allOf": [
|
|
@@ -5811,11 +5811,13 @@
|
|
|
5811
5811
|
"additionalProperties": false,
|
|
5812
5812
|
"properties": {
|
|
5813
5813
|
"value": { "type": "string", "minLength": 1 },
|
|
5814
|
-
"label": { "type": "string", "minLength": 1, "description": "i18n key." }
|
|
5814
|
+
"label": { "type": "string", "minLength": 1, "description": "i18n key." },
|
|
5815
|
+
"hint": { "type": "string", "description": "i18n key of a line under the option: what choosing it does besides recording it." }
|
|
5815
5816
|
}
|
|
5816
5817
|
}
|
|
5817
5818
|
},
|
|
5818
5819
|
"url": { "type": "string", "minLength": 1, "description": "App endpoint that records the purpose; {objectId} is filled in." },
|
|
5820
|
+
"checkUrl": { "type": "string", "minLength": 1, "description": "App endpoint asked first (GET, {objectId} filled in): an answer { required: false } opens the record without the dialog, because the app recorded the purpose itself." },
|
|
5819
5821
|
"title": { "type": "string", "description": "i18n key of the dialog's title." },
|
|
5820
5822
|
"description": { "type": "string", "description": "i18n key of the sentence under the title." }
|
|
5821
5823
|
}
|
|
@@ -524,6 +524,57 @@ export function formatIsoDuration(value) {
|
|
|
524
524
|
return words[period.unit] ? words[period.unit]() : String(value)
|
|
525
525
|
}
|
|
526
526
|
|
|
527
|
+
/** The ISO designator of each date unit a term is written in. */
|
|
528
|
+
const UNIT_DESIGNATOR = { years: 'Y', months: 'M', weeks: 'W', days: 'D' }
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* A one-unit ISO-8601 period, a day count that is whole weeks read as weeks
|
|
532
|
+
* (a term of `P28D` is "4 weeks"); null when it is not a one-unit period.
|
|
533
|
+
*
|
|
534
|
+
* @param {unknown} value The stored period.
|
|
535
|
+
* @return {{amount: number, unit: string}|null}
|
|
536
|
+
*/
|
|
537
|
+
function termPeriod(value) {
|
|
538
|
+
if (value === null || value === undefined || value === '') {
|
|
539
|
+
return null
|
|
540
|
+
}
|
|
541
|
+
const period = parseDuration(String(value))
|
|
542
|
+
if (period === null || !UNIT_DESIGNATOR[period.unit]) {
|
|
543
|
+
return null
|
|
544
|
+
}
|
|
545
|
+
if (period.unit === 'days' && period.amount > 0 && period.amount % 7 === 0) {
|
|
546
|
+
return { amount: period.amount / 7, unit: 'weeks' }
|
|
547
|
+
}
|
|
548
|
+
return period
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* A term in words, with the extension it may get (`format: 'duration'`):
|
|
553
|
+
* `P28D` reads "4 weeks", and with an extension of `P14D` "4 weeks,
|
|
554
|
+
* extendable by 2" (the unit is said once when both share it). A value that
|
|
555
|
+
* is not a one-unit period is returned as written, '' for null or empty.
|
|
556
|
+
*
|
|
557
|
+
* @spec openspec/changes/data-widget-duration-format/specs/data-widget/spec.md#requirement-a-term-reads-in-words-with-its-extension
|
|
558
|
+
* @param {unknown} value The stored term.
|
|
559
|
+
* @param {unknown} [extension] The stored extension period, if any.
|
|
560
|
+
* @return {string}
|
|
561
|
+
*/
|
|
562
|
+
export function formatTermDuration(value, extension = null) {
|
|
563
|
+
const term = termPeriod(value)
|
|
564
|
+
if (term === null) {
|
|
565
|
+
return value === null || value === undefined ? '' : String(value)
|
|
566
|
+
}
|
|
567
|
+
const words = formatIsoDuration(`P${term.amount}${UNIT_DESIGNATOR[term.unit]}`)
|
|
568
|
+
const extra = termPeriod(extension)
|
|
569
|
+
if (extra === null || extra.amount === 0) {
|
|
570
|
+
return words
|
|
571
|
+
}
|
|
572
|
+
const extraWords = extra.unit === term.unit
|
|
573
|
+
? String(extra.amount)
|
|
574
|
+
: formatIsoDuration(`P${extra.amount}${UNIT_DESIGNATOR[extra.unit]}`)
|
|
575
|
+
return t('nextcloud-vue', '{term}, extendable by {extension}', { term: words, extension: extraWords })
|
|
576
|
+
}
|
|
577
|
+
|
|
527
578
|
/**
|
|
528
579
|
* A Nextcloud user id as its display name (`userName` registry key): the id
|
|
529
580
|
* while the name is looked up, and for a user nobody answers for.
|
|
@@ -553,6 +604,7 @@ export const BUILT_IN_FORMATTERS = {
|
|
|
553
604
|
connectionSettingsLabel: formatConnectionSettingsLabel,
|
|
554
605
|
masked: formatMasked,
|
|
555
606
|
isoDuration: formatIsoDuration,
|
|
607
|
+
termDuration: formatTermDuration,
|
|
556
608
|
valueMap: formatValueMap,
|
|
557
609
|
userName: formatUserName,
|
|
558
610
|
}
|