@conduction/nextcloud-vue 2.141.0 → 2.142.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/CnCellRenderer/CnCellRenderer.vue.js +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +13 -0
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +3 -3
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +21 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +34 -3
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +43 -3
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +21 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +2 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js +14 -0
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue.js +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +3 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +2 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue.js +1 -1
- package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue2.js +31 -1
- package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue2.js.map +1 -1
- package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/contacts/CnContactsTab.vue.js +1 -1
- package/dist/esm/integrations/builtin/contacts/CnContactsTab.vue2.js +52 -1
- package/dist/esm/integrations/builtin/contacts/CnContactsTab.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/contacts/CnContactsTab.vue3.js +119 -65
- package/dist/esm/integrations/builtin/contacts/CnContactsTab.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/deck/CnDeckCard.vue.js +1 -1
- package/dist/esm/integrations/builtin/deck/CnDeckCard.vue2.js +86 -4
- package/dist/esm/integrations/builtin/deck/CnDeckCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/deck/CnDeckCard.vue3.js +67 -5
- package/dist/esm/integrations/builtin/deck/CnDeckCard.vue3.js.map +1 -1
- package/dist/esm/l10n/en.json.js +10 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +11 -2
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +527 -358
- package/dist/esm/utils/buildViewTree.js +23 -8
- package/dist/esm/utils/buildViewTree.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +1064 -616
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +527 -358
- package/l10n/en.json +10 -1
- package/l10n/nl.json +11 -2
- package/package.json +1 -1
- package/src/components/CnCellRenderer/CnCellRenderer.vue +15 -1
- package/src/components/CnDataTable/CnDataTable.md +1 -0
- package/src/components/CnDataTable/CnDataTable.vue +22 -1
- package/src/components/CnFactsWidget/CnFactsWidget.vue +34 -3
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +44 -4
- package/src/components/CnIndexPage/CnIndexPage.vue +22 -1
- package/src/components/CnIndexPage/useSelfFetchList.js +14 -0
- package/src/components/CnObjectSidebar/CnFilesTab.vue +4 -1
- package/src/components/CnPartyPicker/CnPartyPicker.vue +31 -1
- package/src/css/look-board-detail.css +95 -0
- package/src/css/look-board-index.css +53 -0
- package/src/css/look-board.css +17 -0
- package/src/integrations/builtin/contacts/CnContactsTab.vue +101 -26
- package/src/integrations/builtin/contacts/__tests__/CnContactsTabBoardRows.spec.js +67 -0
- package/src/integrations/builtin/deck/CnDeckCard.vue +121 -2
- package/src/integrations/builtin/deck/__tests__/CnDeckCardHeaderActions.spec.js +68 -0
- package/src/utils/buildViewTree.js +23 -8
package/l10n/en.json
CHANGED
|
@@ -2382,7 +2382,16 @@
|
|
|
2382
2382
|
"Open profile": "Open profile",
|
|
2383
2383
|
"Link a contact from your address book.": "Link a contact from your address book.",
|
|
2384
2384
|
"The value could not be shown.": "The value could not be shown.",
|
|
2385
|
-
"No value": "No value"
|
|
2385
|
+
"No value": "No value",
|
|
2386
|
+
"Link an existing card": "Link an existing card",
|
|
2387
|
+
"New card": "New card",
|
|
2388
|
+
"Could not link card.": "Could not link card.",
|
|
2389
|
+
"Could not create card.": "Could not create card.",
|
|
2390
|
+
"This card is already linked.": "This card is already linked.",
|
|
2391
|
+
"From {date}": "From {date}",
|
|
2392
|
+
"Until {date}": "Until {date}",
|
|
2393
|
+
"More actions for {name}": "More actions for {name}",
|
|
2394
|
+
"Unlink contact": "Unlink contact"
|
|
2386
2395
|
},
|
|
2387
2396
|
"plurals": {
|
|
2388
2397
|
"{count} member": [
|
package/l10n/nl.json
CHANGED
|
@@ -1989,7 +1989,7 @@
|
|
|
1989
1989
|
"Save current view": "Huidige weergave opslaan",
|
|
1990
1990
|
"Share view: {name}": "Weergave delen: {name}",
|
|
1991
1991
|
"The view \"{name}\" leaves your list and the menu on the left.": "De weergave \"{name}\" verdwijnt uit uw lijst en uit het menu links.",
|
|
1992
|
-
"Whoever gets the view sees it under Shared with me. It is yours and stays yours.": "Wie de weergave krijgt, ziet
|
|
1992
|
+
"Whoever gets the view sees it under Shared with me. It is yours and stays yours.": "Wie de weergave krijgt, ziet hem onder Gedeeld met mij. Hij is van u en blijft dat.",
|
|
1993
1993
|
"Whoever you share the view with sees the change at once.": "Iedereen met wie u de weergave deelt, ziet de wijziging meteen.",
|
|
1994
1994
|
"Reason": "Reden",
|
|
1995
1995
|
"Could not be read": "Kon niet worden gelezen",
|
|
@@ -2635,7 +2635,16 @@
|
|
|
2635
2635
|
"Save as draft": "Opslaan als concept",
|
|
2636
2636
|
"Draft saved at {time}": "Concept opgeslagen om {time}",
|
|
2637
2637
|
"The draft could not be saved": "Het concept kon niet worden opgeslagen",
|
|
2638
|
-
"No value": "Geen waarde"
|
|
2638
|
+
"No value": "Geen waarde",
|
|
2639
|
+
"Link an existing card": "Bestaande kaart koppelen",
|
|
2640
|
+
"New card": "Nieuwe kaart",
|
|
2641
|
+
"Could not link card.": "De kaart kon niet worden gekoppeld.",
|
|
2642
|
+
"Could not create card.": "De kaart kon niet worden gemaakt.",
|
|
2643
|
+
"This card is already linked.": "Deze kaart is al gekoppeld.",
|
|
2644
|
+
"From {date}": "Vanaf {date}",
|
|
2645
|
+
"Until {date}": "Tot {date}",
|
|
2646
|
+
"More actions for {name}": "Meer acties voor {name}",
|
|
2647
|
+
"Unlink contact": "Contact ontkoppelen"
|
|
2639
2648
|
},
|
|
2640
2649
|
"plurals": {
|
|
2641
2650
|
"{count} member": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@conduction/nextcloud-vue",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.142.0",
|
|
4
4
|
"description": "Shared Vue component library for Conduction Nextcloud apps — complements @nextcloud/vue with higher-level components, OpenRegister integration, and NL Design System support",
|
|
5
5
|
"homepage": "https://github.com/ConductionNL/nextcloud-vue#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -175,7 +175,7 @@
|
|
|
175
175
|
</template>
|
|
176
176
|
<template v-else-if="widget === 'avatar'">
|
|
177
177
|
<span v-if="avatarName || avatarUserId" class="cn-cell-renderer__avatar">
|
|
178
|
-
<span v-if="avatarUserId" class="cn-cell-renderer__avatar-picture" aria-hidden="true">
|
|
178
|
+
<span v-if="avatarUserId && !isBoardLook" class="cn-cell-renderer__avatar-picture" aria-hidden="true">
|
|
179
179
|
<NcAvatar
|
|
180
180
|
:user="avatarUserId"
|
|
181
181
|
:displayName="avatarName || avatarUserId"
|
|
@@ -186,6 +186,7 @@
|
|
|
186
186
|
<span
|
|
187
187
|
v-else
|
|
188
188
|
class="cn-cell-renderer__avatar-initials"
|
|
189
|
+
:class="avatarToneClass"
|
|
189
190
|
:style="{ width: avatarSize + 'px', height: avatarSize + 'px' }"
|
|
190
191
|
aria-hidden="true">{{ avatarInitials }}</span>
|
|
191
192
|
<span class="cn-cell-renderer__avatar-text">
|
|
@@ -942,6 +943,19 @@ export default {
|
|
|
942
943
|
* @return {number}
|
|
943
944
|
* @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-avatar-and-date-cells
|
|
944
945
|
*/
|
|
946
|
+
/**
|
|
947
|
+
* `avatar` widget: the chip's tone class in the board look,
|
|
948
|
+
* `widgetProps.tone` `neutral` (DqContacten's grey chip) or the
|
|
949
|
+
* default light primary.
|
|
950
|
+
*
|
|
951
|
+
* @return {string}
|
|
952
|
+
* @spec openspec/changes/board-avatar-chip/specs/data-table/spec.md#requirement-a-board-avatar-cell-draws-the-initials-chip
|
|
953
|
+
*/
|
|
954
|
+
avatarToneClass() {
|
|
955
|
+
const tone = this.widgetProps && this.widgetProps.tone
|
|
956
|
+
return tone === 'neutral' ? 'cn-cell-renderer__avatar-initials--neutral' : ''
|
|
957
|
+
},
|
|
958
|
+
|
|
945
959
|
avatarSize() {
|
|
946
960
|
const size = Number(this.widgetProps && this.widgetProps.size)
|
|
947
961
|
return Number.isFinite(size) && size > 0 ? size : (this.isBoardLook ? 32 : 24)
|
|
@@ -194,6 +194,7 @@ export default {
|
|
|
194
194
|
| `scrollable` | Boolean | `false` | Constrain height and make the table vertically scrollable |
|
|
195
195
|
| `loadingText` | String | `'Loading…'` | Text shown below the spinner during loading |
|
|
196
196
|
| `rowIcon` | String \| Function | `null` | Optional leading icon for every row: a static MDI name applied to all rows, or `(row) => iconName` to vary it per row (resolved via the CnIcon registry). Unset = no icon column. |
|
|
197
|
+
| `rowIconTone` | String | `'primary'` | The tone of the leading icon's tile in the board look: `primary`, `teal` or `neutral` (DqOrganisaties draws a teal tile). |
|
|
197
198
|
| `rowIndicators` | Array | `[]` | State indicators the page declares for its rows: `{ id, field, equals?, in?, icon, text, tooltip? }`. The condition is `equals`, `in`, or plain truthiness when neither is given. `text` is required, so an indicator is never colour and shape alone. The page declares which indicators exist; a record cannot add one it has not declared. |
|
|
198
199
|
| `rowIndicatorCap` | Number | `3` | How many declared indicators render on the row before the rest move into the row menu, reachable as `indicatorsFor(row).overflow`. |
|
|
199
200
|
| `selectAllLabel` | String | `'Select all rows'` | Accessible name (`aria-label`) for the header select-all checkbox, so screen readers announce a named control (WCAG 4.1.2) |
|
|
@@ -276,7 +276,7 @@
|
|
|
276
276
|
<td
|
|
277
277
|
v-if="rowIcon"
|
|
278
278
|
class="cn-table-col--icon"
|
|
279
|
-
:class="pinClass(selectable ? 1 : 0)"
|
|
279
|
+
:class="[pinClass(selectable ? 1 : 0), 'cn-table-col--icon-' + iconTone]"
|
|
280
280
|
:style="pinStyle(selectable ? 1 : 0)">
|
|
281
281
|
<CnIcon :name="getRowIcon(row)" :size="20" />
|
|
282
282
|
</td>
|
|
@@ -650,6 +650,17 @@ export default {
|
|
|
650
650
|
default: null,
|
|
651
651
|
},
|
|
652
652
|
|
|
653
|
+
/**
|
|
654
|
+
* The tone of the leading icon's tile in the board look: `primary`
|
|
655
|
+
* (default), `teal` or `neutral` (DqOrganisaties draws a teal tile).
|
|
656
|
+
*
|
|
657
|
+
* @type {string}
|
|
658
|
+
*/
|
|
659
|
+
rowIconTone: {
|
|
660
|
+
type: String,
|
|
661
|
+
default: 'primary',
|
|
662
|
+
},
|
|
663
|
+
|
|
653
664
|
/**
|
|
654
665
|
* State indicators a page declares for its rows. Each entry is
|
|
655
666
|
* `{ id, field, equals?, in?, icon, text, tooltip? }`: `field` is a
|
|
@@ -1176,6 +1187,16 @@ export default {
|
|
|
1176
1187
|
},
|
|
1177
1188
|
|
|
1178
1189
|
computed: {
|
|
1190
|
+
/**
|
|
1191
|
+
* The leading icon tile's tone, one the board look draws.
|
|
1192
|
+
*
|
|
1193
|
+
* @return {string} `primary`, `teal` or `neutral`.
|
|
1194
|
+
* @spec openspec/changes/board-row-icon-tile/specs/data-table/spec.md#requirement-a-board-tables-leading-icon-sits-on-a-tile
|
|
1195
|
+
*/
|
|
1196
|
+
iconTone() {
|
|
1197
|
+
return ['primary', 'teal', 'neutral'].includes(this.rowIconTone) ? this.rowIconTone : 'primary'
|
|
1198
|
+
},
|
|
1199
|
+
|
|
1179
1200
|
/**
|
|
1180
1201
|
* Whether the table is drawn as the board look's white card.
|
|
1181
1202
|
*
|
|
@@ -249,7 +249,7 @@ import { formatBoardDate } from '../../utils/boardDate.js'
|
|
|
249
249
|
import { conditionalLine } from '../../utils/conditionalLine.js'
|
|
250
250
|
import { parseDateValue } from '../../utils/dateVariant.js'
|
|
251
251
|
import { fetchListTotal } from '../../utils/fetchFilterCounts.js'
|
|
252
|
-
import { fillTemplate } from '../../utils/fillTemplate.js'
|
|
252
|
+
import { fillTemplate, formatLongDate } from '../../utils/fillTemplate.js'
|
|
253
253
|
import { formatMoney, metricLocale, unwrapAppConfig } from '../../utils/formatMetric.js'
|
|
254
254
|
import { readPath } from '../../utils/readPath.js'
|
|
255
255
|
import { hasUnresolvedDeepTokens, resolveDeepTokens } from '../../utils/resolveFilterTokens.js'
|
|
@@ -416,6 +416,8 @@ export default {
|
|
|
416
416
|
cnDispatchAction: { default: null },
|
|
417
417
|
/** The page's object sidebar channel; a `link.sidebarTab` opens one of its tabs. */
|
|
418
418
|
objectSidebarState: { default: null },
|
|
419
|
+
/** The records the detail page reads beside the record (`@context.<name>`), for a `labelPath`. */
|
|
420
|
+
cnDetailVisibilityRows: { default: null },
|
|
419
421
|
},
|
|
420
422
|
|
|
421
423
|
props: {
|
|
@@ -432,13 +434,14 @@ export default {
|
|
|
432
434
|
* `route` (`{ name, params?, query? }`, `@source.<path>` in a param) on a `title` or a `row` links its value to that route; a param that does not fill leaves it plain.
|
|
433
435
|
* `format: 'user'` shows a Nextcloud user id as the user's display name, read once per id; the entry stays empty until the name is known.
|
|
434
436
|
* `template` ("{available} {unit}") fills its `{path}` placeholders from the record instead of reading `path`; it is empty when every placeholder is. `suffix` (" kg") is added to a value that is not empty.
|
|
437
|
+
* `labelPath` ("@context.caseType.handlerLabel") names a value on the record or the page's `@context` records that labels the row when it holds text; `label` is the fallback.
|
|
435
438
|
* `emptyValue` ("No") is shown, translated, when the entry has no value, so the entry stays drawn whatever `hideEmpty` says (an override that was never set reads "No").
|
|
436
439
|
* - `action` — an action drawn as a button under the facts; `headerAction` — one drawn in the card header (reported through the `header` event).
|
|
437
440
|
* - `actions` — action buttons under the facts in the `headerActions` shape (`api-call`, `open-form`, `navigate`, `open-modal`, ...; `confirm`, `variant`). `@source.<field>` names a field of the record shown, and an action whose token names an empty field is not drawn. `visibleWhen` reads the record shown; `adminOnly: true` draws the action for an instance admin only (visibility, never authorisation). An api-call or a saved form refreshes the page, and the facts read their source again.
|
|
438
441
|
* - `rowsPath` — a path to a list of `{ label, value }` the record holds, drawn as rows after `fields` (a preview the server builds).
|
|
439
442
|
* - `headerPill` — a status pill in the card header (reported through the `header` event): `{ path?, text?, map?, variant?, variantMap?, colorMap? }`, read from the record like a `pill` entry (DqBezwaar "Advies ontvangen"); nothing shows while the value is empty.
|
|
440
443
|
* - `notice` — `{ text, variant? }`, a note band inside the card under the facts (`info` by default; `success`, `warning` or `error`); the text is translated.
|
|
441
|
-
* `format` is `text` (default), `date` (board short date), `date-long` (always with the year), `list` (an array joined by ", ", each item read at `itemPath`), `bytes` (a size, "1.5 MB"), `number` (in the reader's language, `decimals` fraction digits when set) or `currency` (a money amount in the reader's language, "€ 1.234,50": the code in `currency`, else the record's `currencyField`, else the app's reporting currency, else EUR; `decimals` defaults to 2).
|
|
444
|
+
* `format` is `text` (default), `date` (board short date), `date-long` (always with the year), `longdate` (the month written out, the year only outside this year: "3 oktober"), `list` (an array joined by ", ", each item read at `itemPath`), `bytes` (a size, "1.5 MB"), `number` (in the reader's language, `decimals` fraction digits when set) or `currency` (a money amount in the reader's language, "€ 1.234,50": the code in `currency`, else the record's `currencyField`, else the app's reporting currency, else EUR; `decimals` defaults to 2).
|
|
442
445
|
* `map` turns a raw value into a label (translated). `parts` (on a `line`) lists paths, or `{ path, label?, format? }`, joined by `separator` (default " · "); empty parts are dropped.
|
|
443
446
|
* - `source` — `{ register, schema, id }` or `{ url }`; omitted = the current object. `{ register, schema, filter, sort? }` without `id` reads the first object that matches `filter` in `sort` order (`{ field, dir }`): the latest count of a shift. An entry with `from: "object"` reads the current object even then (a client card that also shows the ticket's channel).
|
|
444
447
|
* - `endpointSource` — `{ url, method?, params?, responsePath? }`, the block a stat or chart takes: the facts read an app endpoint, shared and cached like those.
|
|
@@ -722,7 +725,7 @@ export default {
|
|
|
722
725
|
}
|
|
723
726
|
if (kind === 'row') {
|
|
724
727
|
const last = out[out.length - 1]
|
|
725
|
-
const row = { key, label: this.
|
|
728
|
+
const row = { key, label: this.labelOf(record, field), value, ...this.rowExtras(record, field, value) }
|
|
726
729
|
if (field.route && !row.href) {
|
|
727
730
|
row.to = this.resolveRoute(field.route, record)
|
|
728
731
|
}
|
|
@@ -1406,6 +1409,30 @@ export default {
|
|
|
1406
1409
|
}
|
|
1407
1410
|
},
|
|
1408
1411
|
|
|
1412
|
+
/**
|
|
1413
|
+
* A row's label: the value at `labelPath` (the record, or the page's
|
|
1414
|
+
* `@context.<name>` records) when it holds text, else `label`, both
|
|
1415
|
+
* through the host translate. A case type can name its handler
|
|
1416
|
+
* ("Regisseur") while another keeps "Behandelaar".
|
|
1417
|
+
*
|
|
1418
|
+
* @param {object} record The record shown.
|
|
1419
|
+
* @param {object} field The entry.
|
|
1420
|
+
* @return {string}
|
|
1421
|
+
* @spec openspec/changes/facts-label-from-path/specs/facts-widget/spec.md#requirement-a-facts-row-can-take-its-label-from-the-record-or-its-context
|
|
1422
|
+
*/
|
|
1423
|
+
labelOf(record, field) {
|
|
1424
|
+
if (typeof field.labelPath === 'string' && field.labelPath !== '') {
|
|
1425
|
+
const rows = this.cnDetailVisibilityRows && typeof this.cnDetailVisibilityRows === 'object' && 'value' in this.cnDetailVisibilityRows
|
|
1426
|
+
? this.cnDetailVisibilityRows.value
|
|
1427
|
+
: this.cnDetailVisibilityRows
|
|
1428
|
+
const named = readPath({ ...(record || {}), '@context': rows || {} }, field.labelPath)
|
|
1429
|
+
if (typeof named === 'string' && named.trim() !== '') {
|
|
1430
|
+
return this.tr(named.trim())
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
return this.tr(field.label || '')
|
|
1434
|
+
},
|
|
1435
|
+
|
|
1409
1436
|
/**
|
|
1410
1437
|
* Copy a row's value to the clipboard.
|
|
1411
1438
|
*
|
|
@@ -1775,6 +1802,10 @@ export default {
|
|
|
1775
1802
|
.filter((item) => item !== '')
|
|
1776
1803
|
return items.join(', ')
|
|
1777
1804
|
}
|
|
1805
|
+
// The month written out, the year only outside this year: "3 oktober".
|
|
1806
|
+
if (format === 'longdate') {
|
|
1807
|
+
return formatLongDate(raw)
|
|
1808
|
+
}
|
|
1778
1809
|
if (format === 'date' || format === 'date-long') {
|
|
1779
1810
|
const date = parseDateValue(raw)
|
|
1780
1811
|
if (date === null) {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<template>
|
|
6
6
|
<div
|
|
7
7
|
class="cn-files-browser"
|
|
8
|
-
:class="{ 'cn-files-browser--dragging': dragging, 'cn-files-browser--drop-panel': dropOverlay &&
|
|
8
|
+
:class="{ 'cn-files-browser--dragging': dragging, 'cn-files-browser--drop-panel': dropOverlay && dropDetailTemplate !== '' }"
|
|
9
9
|
data-testid="cn-files-browser"
|
|
10
10
|
@dragenter.prevent="onDragEnter"
|
|
11
11
|
@dragover.prevent="onDragOver"
|
|
@@ -1094,10 +1094,22 @@ export default {
|
|
|
1094
1094
|
* @spec openspec/changes/files-drop-panel/specs/files-browser/spec.md#requirement-the-drop-state-fills-the-panel-and-says-where-the-files-go
|
|
1095
1095
|
*/
|
|
1096
1096
|
dropDetail: {
|
|
1097
|
-
type: String,
|
|
1097
|
+
type: [String, Array],
|
|
1098
1098
|
default: '',
|
|
1099
1099
|
},
|
|
1100
1100
|
|
|
1101
|
+
/**
|
|
1102
|
+
* Named values filled into `dropDetail` as `{name}`, such as the case
|
|
1103
|
+
* number (`{ "case": "@object.identifier" }` in a detail page's props).
|
|
1104
|
+
* While a value is unknown the line is left out.
|
|
1105
|
+
*
|
|
1106
|
+
* @spec openspec/changes/files-drop-detail-values/specs/files-drop-detail-values/spec.md#requirement-the-drop-detail-line-can-name-the-record
|
|
1107
|
+
*/
|
|
1108
|
+
dropDetailValues: {
|
|
1109
|
+
type: Object,
|
|
1110
|
+
default: null,
|
|
1111
|
+
},
|
|
1112
|
+
|
|
1101
1113
|
/** Show a line under the list saying files can be dropped on it. */
|
|
1102
1114
|
dropHint: {
|
|
1103
1115
|
type: Boolean,
|
|
@@ -1390,6 +1402,22 @@ export default {
|
|
|
1390
1402
|
},
|
|
1391
1403
|
|
|
1392
1404
|
computed: {
|
|
1405
|
+
/**
|
|
1406
|
+
* The `dropDetail` text: the string, or the text of the first variant
|
|
1407
|
+
* `{ when, text }` whose `when` is `true` or that has none.
|
|
1408
|
+
*
|
|
1409
|
+
* @return {string}
|
|
1410
|
+
* @spec openspec/changes/files-drop-detail-values/specs/files-drop-detail-values/spec.md#requirement-the-drop-detail-line-can-name-the-record
|
|
1411
|
+
*/
|
|
1412
|
+
dropDetailTemplate() {
|
|
1413
|
+
if (typeof this.dropDetail === 'string') {
|
|
1414
|
+
return this.dropDetail
|
|
1415
|
+
}
|
|
1416
|
+
const variants = Array.isArray(this.dropDetail) ? this.dropDetail : []
|
|
1417
|
+
const chosen = variants.find((item) => item && typeof item.text === 'string' && (!('when' in item) || item.when === true))
|
|
1418
|
+
return chosen ? chosen.text : ''
|
|
1419
|
+
},
|
|
1420
|
+
|
|
1393
1421
|
/**
|
|
1394
1422
|
* `dropDetail` through the host translate with `{count}` filled, '' when
|
|
1395
1423
|
* there is none or the count it needs is unknown.
|
|
@@ -1398,10 +1426,22 @@ export default {
|
|
|
1398
1426
|
* @return {string}
|
|
1399
1427
|
*/
|
|
1400
1428
|
dropDetailText() {
|
|
1401
|
-
|
|
1429
|
+
const template = this.dropDetailTemplate
|
|
1430
|
+
if (!template) {
|
|
1402
1431
|
return ''
|
|
1403
1432
|
}
|
|
1404
|
-
|
|
1433
|
+
let text = this.cnTranslate(template)
|
|
1434
|
+
// `dropDetailValues`: named values such as the case number; a value
|
|
1435
|
+
// still unknown (an unresolved `@` token, or empty) leaves the line out.
|
|
1436
|
+
// @spec openspec/changes/files-drop-detail-values/specs/files-drop-detail-values/spec.md#requirement-the-drop-detail-line-can-name-the-record
|
|
1437
|
+
const values = this.dropDetailValues && typeof this.dropDetailValues === 'object' ? this.dropDetailValues : {}
|
|
1438
|
+
for (const [name, value] of Object.entries(values)) {
|
|
1439
|
+
const shown = value === null || value === undefined ? '' : String(value)
|
|
1440
|
+
if (shown === '' || shown.startsWith('@')) {
|
|
1441
|
+
return ''
|
|
1442
|
+
}
|
|
1443
|
+
text = text.split(`{${name}}`).join(shown)
|
|
1444
|
+
}
|
|
1405
1445
|
if (!text.includes('{count}')) {
|
|
1406
1446
|
return text
|
|
1407
1447
|
}
|
|
@@ -875,6 +875,7 @@
|
|
|
875
875
|
:columns="renderedColumns"
|
|
876
876
|
:pinnedCount="pinnedColumnCount"
|
|
877
877
|
:rowIcon="rowIcon"
|
|
878
|
+
:rowIconTone="rowIconTone"
|
|
878
879
|
:rowIndicators="rowIndicators"
|
|
879
880
|
:rowIndicatorCap="rowIndicatorCap"
|
|
880
881
|
:rows="displayObjects"
|
|
@@ -3185,6 +3186,17 @@ export default {
|
|
|
3185
3186
|
default: null,
|
|
3186
3187
|
},
|
|
3187
3188
|
|
|
3189
|
+
/**
|
|
3190
|
+
* The leading icon's tile tone in the board look (`primary`, `teal`,
|
|
3191
|
+
* `neutral`), from `pages[].config.rowIconTone`. Forwarded to CnDataTable.
|
|
3192
|
+
*
|
|
3193
|
+
* @type {string}
|
|
3194
|
+
*/
|
|
3195
|
+
rowIconTone: {
|
|
3196
|
+
type: String,
|
|
3197
|
+
default: 'primary',
|
|
3198
|
+
},
|
|
3199
|
+
|
|
3188
3200
|
/** Columns to exclude in schema mode */
|
|
3189
3201
|
excludeColumns: {
|
|
3190
3202
|
type: Array,
|
|
@@ -6422,6 +6434,7 @@ export default {
|
|
|
6422
6434
|
r: this.register,
|
|
6423
6435
|
s: this.exportSchemaSlug,
|
|
6424
6436
|
f: this.filter || null,
|
|
6437
|
+
a: this.effectiveActiveFilters || null,
|
|
6425
6438
|
e: this.countEntries,
|
|
6426
6439
|
// The store's total, not the error override in effectivePagination,
|
|
6427
6440
|
// so a failed fetch and its recovery do not refetch the counts.
|
|
@@ -10012,7 +10025,15 @@ export default {
|
|
|
10012
10025
|
const counts = await fetchFilterCounts({
|
|
10013
10026
|
register: this.register,
|
|
10014
10027
|
schema,
|
|
10015
|
-
|
|
10028
|
+
// A quick filter counts within the list as filtered (the
|
|
10029
|
+
// active filters, its own field its own); a saved view counts
|
|
10030
|
+
// its own query.
|
|
10031
|
+
entries: this.countEntries.map((entry) => ({
|
|
10032
|
+
key: entry.key,
|
|
10033
|
+
filter: entry.key.startsWith('tab:')
|
|
10034
|
+
? { ...(this.effectiveActiveFilters || {}), ...resolveFilterMap(entry.filter, params, ctx) }
|
|
10035
|
+
: resolveFilterMap(entry.filter, params, ctx),
|
|
10036
|
+
})),
|
|
10016
10037
|
baseFilter: resolveFilterMap(this.filter, params, ctx),
|
|
10017
10038
|
ctx,
|
|
10018
10039
|
})
|
|
@@ -5,7 +5,9 @@ import { useObjectStore } from '../../store/index.js'
|
|
|
5
5
|
// Both filter resolvers live in `utils/routeFilters.js` so CnLogsPage applies
|
|
6
6
|
// the same two grammars (route-param interpolation + `?key=value` deep links)
|
|
7
7
|
// without pulling in this composable's index-only sidebar/subscription wiring.
|
|
8
|
+
import { loadMyTeam } from '../../utils/myTeam.js'
|
|
8
9
|
import { withPersonalLenses } from '../../utils/personalLenses.js'
|
|
10
|
+
import { dropOptionalUnresolved, MY_TEAM_TOKEN, resolveFilterTokens } from '../../utils/resolveFilterTokens.js'
|
|
9
11
|
import { parseSortKeysFromQuery, resolveFilterMap, resolveQueryFilters } from '../../utils/routeFilters.js'
|
|
10
12
|
import { orderToSortKeys } from '../../utils/sortOrder.js'
|
|
11
13
|
|
|
@@ -392,6 +394,18 @@ export function useSelfFetchList(props, instance, inject, extras = {}) {
|
|
|
392
394
|
// a reactive getter so a runtime flip attaches/detaches accordingly.
|
|
393
395
|
// Stores without live-updates support (no `subscribe` action) are a
|
|
394
396
|
// silent no-op inside the composable, keeping this fully inert.
|
|
397
|
+
// An address carrying `@myTeam` (a shared link) waits for the team, as a
|
|
398
|
+
// saved view on it does: once read, the token becomes the team, or goes
|
|
399
|
+
// for a reader in none.
|
|
400
|
+
const carriesMyTeam = Object.values(initialActiveFilters || {})
|
|
401
|
+
.some((value) => value === MY_TEAM_TOKEN || (Array.isArray(value) && value.includes(MY_TEAM_TOKEN)))
|
|
402
|
+
if (carriesMyTeam) {
|
|
403
|
+
loadMyTeam().then(() => {
|
|
404
|
+
list.activeFilters.value = dropOptionalUnresolved(resolveFilterTokens(list.activeFilters.value, tokenCtx()))
|
|
405
|
+
list.refresh(1)
|
|
406
|
+
})
|
|
407
|
+
}
|
|
408
|
+
|
|
395
409
|
useObjectSubscription(objectStore, () => objectType.value, null, {
|
|
396
410
|
enabled: () => props.subscribe !== false,
|
|
397
411
|
})
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
:dropOverlay="dropOverlay"
|
|
17
17
|
:dropLabel="dropLabel"
|
|
18
18
|
:dropDetail="dropDetail"
|
|
19
|
+
:dropDetailValues="dropDetailValues"
|
|
19
20
|
:dropHint="dropHint"
|
|
20
21
|
:rowActions="rowActions"
|
|
21
22
|
:newActions="newActions"
|
|
@@ -360,7 +361,9 @@ export default {
|
|
|
360
361
|
/** Forwarded to CnFilesBrowser: the drop state's line ("Laat los om toe te voegen"); the library's own without it. */
|
|
361
362
|
dropLabel: { type: String, default: undefined },
|
|
362
363
|
/** Forwarded to CnFilesBrowser: the drop state's second line, `{count}` the files dragged; it also makes the overlay fill the panel. */
|
|
363
|
-
dropDetail: { type: String, default: '' },
|
|
364
|
+
dropDetail: { type: [String, Array], default: '' },
|
|
365
|
+
/** Forwarded to CnFilesBrowser: named values filled into `dropDetail`. */
|
|
366
|
+
dropDetailValues: { type: Object, default: null },
|
|
364
367
|
/** Forwarded to CnFilesBrowser: "Or drag files onto this list." under the list. */
|
|
365
368
|
dropHint: { type: Boolean, default: false },
|
|
366
369
|
/**
|
|
@@ -52,7 +52,9 @@ const SEARCH_DELAY = 250
|
|
|
52
52
|
* Organisatie · KvK …"). Built on CnSearchSelect.
|
|
53
53
|
*
|
|
54
54
|
* `sources`: each `{ id, register, schema, label?, title?, secondary?,
|
|
55
|
-
* limit?, icon? }` searches OpenRegister with `_search`; `
|
|
55
|
+
* limit?, icon?, lookup? }` searches OpenRegister with `_search`; `lookup`
|
|
56
|
+
* (`{ url, when }`) sends a term matching `when` to the app's exact lookup
|
|
57
|
+
* instead (a POST of `{ term }` answering `{ results }`); `title` and
|
|
56
58
|
* `secondary` are templates filled from the row (default `{name}` / none),
|
|
57
59
|
* `label` names the kind ("Resident") and starts the second line; `label`
|
|
58
60
|
* and `secondary` go through the host translate, so a manifest can write
|
|
@@ -284,6 +286,10 @@ export default {
|
|
|
284
286
|
const { data } = await axios.post(generateUrl('/contactsmenu/contacts'), { filter: term })
|
|
285
287
|
return (data && Array.isArray(data.contacts) ? data.contacts : []).map((c) => this.contactOptionOf(source, c))
|
|
286
288
|
}
|
|
289
|
+
if (this.isExactLookup(source, term) === true) {
|
|
290
|
+
const { data } = await axios.post(generateUrl(source.lookup.url), { term })
|
|
291
|
+
return (data && Array.isArray(data.results) ? data.results : []).map((row) => this.optionOf(source, row))
|
|
292
|
+
}
|
|
287
293
|
if (!source.register || !source.schema) {
|
|
288
294
|
return []
|
|
289
295
|
}
|
|
@@ -311,6 +317,30 @@ export default {
|
|
|
311
317
|
this.searching = false
|
|
312
318
|
},
|
|
313
319
|
|
|
320
|
+
/**
|
|
321
|
+
* Whether a typed term goes to the source's exact lookup instead of the
|
|
322
|
+
* free-text search: `source.lookup` is `{ url, when }`, `when` a regular
|
|
323
|
+
* expression the whole term must match ("^[0-9]{9}$" for a BSN). The
|
|
324
|
+
* lookup is a POST, so the term never sits in a URL or a server log line,
|
|
325
|
+
* and the app behind it may check and record who looked whom up.
|
|
326
|
+
*
|
|
327
|
+
* @param {object} source The source.
|
|
328
|
+
* @param {string} term The typed term.
|
|
329
|
+
* @return {boolean}
|
|
330
|
+
* @spec openspec/changes/party-picker-exact-lookup/specs/party-picker/spec.md#requirement-a-party-source-can-look-a-term-up-exactly
|
|
331
|
+
*/
|
|
332
|
+
isExactLookup(source, term) {
|
|
333
|
+
const lookup = source && source.lookup
|
|
334
|
+
if (!lookup || typeof lookup.url !== 'string' || lookup.url === '' || typeof lookup.when !== 'string') {
|
|
335
|
+
return false
|
|
336
|
+
}
|
|
337
|
+
try {
|
|
338
|
+
return new RegExp(lookup.when).test(term)
|
|
339
|
+
} catch {
|
|
340
|
+
return false
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
|
|
314
344
|
/**
|
|
315
345
|
* Name a value the list does not hold: the first OpenRegister source
|
|
316
346
|
* that has an object with that id.
|
|
@@ -1585,6 +1585,49 @@
|
|
|
1585
1585
|
line-height: 1.2;
|
|
1586
1586
|
}
|
|
1587
1587
|
|
|
1588
|
+
/* The contacts tab's rows as DqZaakBetrokkenen "Partijen" draws them: the
|
|
1589
|
+
role heading 15px bold ink in sentence case, each person on a row 12px
|
|
1590
|
+
high-padded under a hairline, the details and the period 13px muted.
|
|
1591
|
+
@spec openspec/changes/board-contacts-rows/specs/contacts/spec.md */
|
|
1592
|
+
.cn-look-board .cn-contacts-tab .cn-contacts-tab__group-title {
|
|
1593
|
+
margin: 6px 0 0;
|
|
1594
|
+
font-size: 15px;
|
|
1595
|
+
font-weight: 700;
|
|
1596
|
+
letter-spacing: 0;
|
|
1597
|
+
text-transform: none;
|
|
1598
|
+
color: var(--color-main-text);
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
.cn-look-board .cn-contacts-tab .cn-contacts-tab__item {
|
|
1602
|
+
align-items: center;
|
|
1603
|
+
padding: 12px 0;
|
|
1604
|
+
border-top: 1px solid var(--cn-board-hairline);
|
|
1605
|
+
border-radius: 0;
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
.cn-look-board .cn-contacts-tab .cn-contacts-tab__item:first-child {
|
|
1609
|
+
margin-top: 8px;
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
.cn-look-board .cn-contacts-tab .cn-contacts-tab__name {
|
|
1613
|
+
font-size: 15px;
|
|
1614
|
+
font-weight: 600;
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
.cn-look-board .cn-contacts-tab .cn-contacts-tab__meta,
|
|
1618
|
+
.cn-look-board .cn-contacts-tab .cn-contacts-tab__period {
|
|
1619
|
+
font-size: 13px;
|
|
1620
|
+
color: var(--color-text-maxcontrast);
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
.cn-look-board .cn-contacts-tab .cn-contacts-tab__period {
|
|
1624
|
+
flex: none;
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
.cn-look-board .cn-contacts-tab .cn-contacts-tab__group {
|
|
1628
|
+
margin-bottom: 8px;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1588
1631
|
/* The contacts tab inside a detail card (DqZaakBetrokkenen "Partijen") takes
|
|
1589
1632
|
the card's padding instead of its own, and its buttons start at the card's
|
|
1590
1633
|
edge under the subtitle.
|
|
@@ -1596,3 +1639,55 @@
|
|
|
1596
1639
|
.cn-look-board .cn-detail-page__leaf-card .cn-contacts-tab .cn-contacts-tab__header {
|
|
1597
1640
|
justify-content: flex-start;
|
|
1598
1641
|
}
|
|
1642
|
+
|
|
1643
|
+
/* A body card's subtitle as the Dq boards draw it: 14px muted at line
|
|
1644
|
+
height 1.2, 3px under the title, and the content 12px under it.
|
|
1645
|
+
@spec openspec/changes/board-card-subtitle-gaps/specs/board-card/spec.md */
|
|
1646
|
+
.cn-look-board .cn-detail-page .cn-widget-wrapper:not(.cn-detail-page__side *) .cn-widget-wrapper__title-stack:has(> .cn-widget-wrapper__subtitle) {
|
|
1647
|
+
gap: 3px;
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
.cn-look-board .cn-detail-page .cn-widget-wrapper:not(.cn-detail-page__side *) .cn-widget-wrapper__subtitle {
|
|
1651
|
+
font-size: 14px;
|
|
1652
|
+
line-height: 1.2;
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
.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 {
|
|
1656
|
+
padding-top: 12px;
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
/* A checklist (DqTaak): each item an 18-20px box at the card's own inset, the
|
|
1660
|
+
label 10px after it in weight 600, 12px between items, the list 2px below
|
|
1661
|
+
the title block. Nextcloud's checkbox pads its box 7px in and makes every row
|
|
1662
|
+
34px tall, which put the list 7px right and 2px apart too far per item.
|
|
1663
|
+
@spec openspec/changes/board-checklist-rows/specs/checklist-widget/spec.md#requirement-a-board-checklist-sits-at-the-card-inset */
|
|
1664
|
+
.cn-look-board .cn-checklist-widget__items {
|
|
1665
|
+
display: flex;
|
|
1666
|
+
flex-direction: column;
|
|
1667
|
+
gap: 12px;
|
|
1668
|
+
margin-top: 2px;
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
.cn-look-board .cn-checklist-widget__item .checkbox-content {
|
|
1672
|
+
padding: 0;
|
|
1673
|
+
gap: 10px;
|
|
1674
|
+
min-height: 20px;
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
.cn-look-board .cn-checklist-widget__item .checkbox-content.checkbox-content .checkbox-content__icon {
|
|
1678
|
+
margin: 0;
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
.cn-look-board .cn-checklist-widget__item .checkbox-radio-switch__input {
|
|
1682
|
+
min-height: 20px;
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
.cn-look-board .cn-checklist-widget__item .checkbox-content__wrapper,
|
|
1686
|
+
.cn-look-board .cn-checklist-widget__item .checkbox-content__text {
|
|
1687
|
+
line-height: 18px;
|
|
1688
|
+
min-height: 0;
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
.cn-look-board .cn-checklist-widget__item .checkbox-content__text {
|
|
1692
|
+
font-weight: 600;
|
|
1693
|
+
}
|
|
@@ -1008,6 +1008,19 @@
|
|
|
1008
1008
|
font-weight: 700;
|
|
1009
1009
|
}
|
|
1010
1010
|
|
|
1011
|
+
/* `widgetProps.tone: "neutral"`: the grey person chip (DqContacten), 13px,
|
|
1012
|
+
12px before the name.
|
|
1013
|
+
@spec openspec/changes/board-avatar-chip/specs/data-table/spec.md#requirement-a-board-avatar-cell-draws-the-initials-chip */
|
|
1014
|
+
.cn-look-board .cn-table-container--board .cn-data-table .cn-cell-renderer__avatar-initials--neutral {
|
|
1015
|
+
background: var(--color-background-dark);
|
|
1016
|
+
color: var(--color-main-text);
|
|
1017
|
+
font-size: 13px;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
.cn-look-board .cn-table-container--board .cn-data-table .cn-cell-renderer__avatar:has(.cn-cell-renderer__avatar-initials--neutral) {
|
|
1021
|
+
gap: 12px;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1011
1024
|
.cn-look-board .cn-table-container--board .cn-data-table td.cn-table-col--title .cn-cell-renderer__avatar-name {
|
|
1012
1025
|
text-decoration: underline;
|
|
1013
1026
|
text-underline-offset: 2px;
|
|
@@ -2184,3 +2197,43 @@
|
|
|
2184
2197
|
color: var(--color-text-maxcontrast);
|
|
2185
2198
|
font-size: 13px;
|
|
2186
2199
|
}
|
|
2200
|
+
|
|
2201
|
+
/* A table's leading icon on a 32px tile, radius 8, an 18px glyph, 12px
|
|
2202
|
+
before the title (DqOrganisaties, PqOrganisaties: teal; most boards: the
|
|
2203
|
+
light primary). The tile's tone is the page's `rowIconTone`.
|
|
2204
|
+
@spec openspec/changes/board-row-icon-tile/specs/data-table/spec.md#requirement-a-board-tables-leading-icon-sits-on-a-tile */
|
|
2205
|
+
.cn-look-board .cn-data-table td.cn-table-col--icon,
|
|
2206
|
+
.cn-look-board .cn-data-table th.cn-table-col--icon {
|
|
2207
|
+
width: 48px;
|
|
2208
|
+
padding-inline: 16px 0;
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
.cn-look-board .cn-data-table td.cn-table-col--icon .material-design-icon {
|
|
2212
|
+
width: 32px;
|
|
2213
|
+
height: 32px;
|
|
2214
|
+
border-radius: 8px;
|
|
2215
|
+
justify-content: center;
|
|
2216
|
+
align-items: center;
|
|
2217
|
+
background: var(--color-primary-element-light);
|
|
2218
|
+
color: var(--color-primary-element-light-text);
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
.cn-look-board .cn-data-table td.cn-table-col--icon-teal .material-design-icon {
|
|
2222
|
+
background: var(--cn-status-teal-bg);
|
|
2223
|
+
color: var(--cn-status-teal-text);
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
.cn-look-board .cn-data-table td.cn-table-col--icon-neutral .material-design-icon {
|
|
2227
|
+
background: var(--color-background-dark);
|
|
2228
|
+
color: var(--color-main-text);
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
.cn-look-board .cn-data-table td.cn-table-col--icon .material-design-icon svg {
|
|
2232
|
+
width: 18px;
|
|
2233
|
+
height: 18px;
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
.cn-look-board .cn-data-table td.cn-table-col--icon + td,
|
|
2237
|
+
.cn-look-board .cn-data-table th.cn-table-col--icon + th {
|
|
2238
|
+
padding-inline-start: 12px;
|
|
2239
|
+
}
|
package/src/css/look-board.css
CHANGED
|
@@ -3115,6 +3115,23 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .v-popper__popper.action-
|
|
|
3115
3115
|
background: var(--cn-board-sunken-ground);
|
|
3116
3116
|
}
|
|
3117
3117
|
|
|
3118
|
+
/* An option's two lines at line height 1.2 and its icon at the top of the
|
|
3119
|
+
row, as DqVolgendeStap draws them (rows 60 high, not 70). */
|
|
3120
|
+
.cn-look-board .cn-choice-cards .cn-choice-cards__row-title:not(.cn-look-nextcloud *),
|
|
3121
|
+
.cn-look-board .cn-choice-cards .cn-choice-cards__row-description:not(.cn-look-nextcloud *) {
|
|
3122
|
+
line-height: 1.2;
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
.cn-look-board .cn-choice-cards .cn-choice-cards__row-icon:not(.cn-look-nextcloud *) {
|
|
3126
|
+
align-self: flex-start;
|
|
3127
|
+
}
|
|
3128
|
+
|
|
3129
|
+
/* The chosen option's fields start under its text: radio 18, icon 20 and
|
|
3130
|
+
two 12px gaps past the row's 14px inset. */
|
|
3131
|
+
.cn-look-board .cn-choice-cards .cn-choice-cards__cell--with-details:has(.cn-choice-cards__row-icon) .cn-choice-cards__details:not(.cn-look-nextcloud *) {
|
|
3132
|
+
padding-inline-start: 76px;
|
|
3133
|
+
}
|
|
3134
|
+
|
|
3118
3135
|
/* A chosen option stays white under its primary edge, as every Dq dialog board
|
|
3119
3136
|
draws it (design-system #371); the Nextcloud look keeps the tint.
|
|
3120
3137
|
@spec openspec/changes/board-choice-row-chosen-white/specs/board-choice-row-chosen-white/spec.md#requirement-a-chosen-board-option-is-white */
|