@conduction/nextcloud-vue 2.105.0 → 2.106.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/CnCardGrid/CnCardGrid.vue.js +1 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js +18 -0
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js.map +1 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js +3 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue.js +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +18 -0
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +53 -4
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue.js +9 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue.js.map +1 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue2.js +24 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue2.js.map +1 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue3.js +49 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue3.js.map +1 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +36 -18
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +17 -38
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
- 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 +53 -2
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +119 -111
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue.js +1 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue2.js +62 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +159 -50
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +121 -98
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js +24 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js +20 -4
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js +22 -4
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js +112 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js +100 -44
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue.js +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue2.js +67 -4
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue3.js +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue.js +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js +295 -12
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js +267 -144
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue.js +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +4 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +3 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +93 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +322 -246
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue.js +1 -1
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js +122 -7
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js +189 -93
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTabs/CnTabs.vue.js +1 -1
- package/dist/esm/components/CnTabs/CnTabs.vue2.js.map +1 -1
- package/dist/esm/components/CnTabs/CnTabs.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +42 -0
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +38 -19
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue.js +9 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue.js.map +1 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue2.js +258 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue3.js +69 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +12 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +21 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +21 -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 +803 -453
- package/dist/esm/utils/dueText.js +18 -3
- package/dist/esm/utils/dueText.js.map +1 -1
- package/dist/esm/utils/libraryWidgetKeys.js +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/sortOrder.js +11 -1
- package/dist/esm/utils/sortOrder.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 +8281 -6350
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +803 -453
- package/l10n/en.json +21 -1
- package/l10n/nl.json +21 -1
- package/package.json +1 -1
- package/src/components/CnCardGrid/CnCardGrid.md +2 -0
- package/src/components/CnCardGrid/CnCardGrid.vue +20 -0
- package/src/components/CnCellRenderer/CnCellRenderer.vue +19 -1
- package/src/components/CnDetailPage/CnDetailPage.md +2 -2
- package/src/components/CnDetailPage/CnDetailPage.vue +53 -4
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue +60 -0
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +36 -29
- package/src/components/CnFactsWidget/CnFactsWidget.vue +4 -0
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +70 -4
- package/src/components/CnFlowRunsWidget/CnFlowRunsWidget.vue +62 -1
- package/src/components/CnIndexPage/CnIndexPage.md +7 -5
- package/src/components/CnIndexPage/CnIndexPage.vue +187 -58
- package/src/components/CnIndexPage/CnIndexPageWidgets.vue +36 -1
- package/src/components/CnIndexPage/useSelfFetchList.js +22 -4
- package/src/components/CnIndexSidebar/CnIndexSidebar.md +2 -0
- package/src/components/CnIndexSidebar/CnIndexSidebar.vue +148 -1
- package/src/components/CnNcWidgetWidget/CnNcWidgetWidget.vue +68 -5
- package/src/components/CnObjectCard/CnObjectCard.md +1 -0
- package/src/components/CnObjectCard/CnObjectCard.vue +354 -13
- package/src/components/CnObjectSidebar/CnFilesTab.vue +6 -0
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +190 -4
- package/src/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue +209 -9
- package/src/components/CnTabs/CnTabs.vue +11 -0
- package/src/components/CnTabsWidget/CnTabsWidget.vue +91 -18
- package/src/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.md +11 -0
- package/src/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue +382 -0
- package/src/components/CnTeamWorkloadWidget/index.js +14 -0
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +12 -0
- package/src/components/index.js +1 -0
- package/src/css/index-page.css +14 -2
- package/src/css/look-board-detail.css +48 -4
- package/src/css/look-board-index.css +64 -2
- package/src/css/look-board.css +25 -2
- package/src/index.js +1 -1
- package/src/schemas/app-manifest-v2.schema.json +75 -6
- package/src/utils/dueText.js +18 -3
- package/src/utils/libraryWidgetKeys.js +1 -0
- package/src/utils/sortOrder.js +10 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
|
@@ -105,9 +105,10 @@ import { translate as t } from '@nextcloud/l10n'
|
|
|
105
105
|
import { NcLoadingIcon } from '@nextcloud/vue'
|
|
106
106
|
import { computed, inject, ref } from 'vue'
|
|
107
107
|
import { useEndpointSource } from '../../composables/useEndpointSource.js'
|
|
108
|
+
import { dispatchAction } from '../../utils/actionsDispatcher.js'
|
|
108
109
|
import { resolveObjectTokenContext } from '../../utils/detailObjectContext.js'
|
|
109
110
|
import { followLinkClick, resolveHref } from '../../utils/linkNavigation.js'
|
|
110
|
-
import { resolveFilterValue } from '../../utils/resolveFilterTokens.js'
|
|
111
|
+
import { resolveDeepTokens, resolveFilterValue } from '../../utils/resolveFilterTokens.js'
|
|
111
112
|
|
|
112
113
|
/**
|
|
113
114
|
* The OpenRegister endpoint that lists the caller's live flow runs.
|
|
@@ -205,6 +206,8 @@ export default {
|
|
|
205
206
|
* so a library string localises through the consuming app's l10n.
|
|
206
207
|
*/
|
|
207
208
|
cnTranslate: { default: () => (key) => key },
|
|
209
|
+
/** The page's action dispatcher (CnPageRenderer), for `headerAction`. */
|
|
210
|
+
cnDispatchAction: { default: null },
|
|
208
211
|
},
|
|
209
212
|
|
|
210
213
|
props: {
|
|
@@ -228,6 +231,10 @@ export default {
|
|
|
228
231
|
* subject's finished runs render below it. Absent = today's org-wide
|
|
229
232
|
* widget, unchanged.
|
|
230
233
|
* - `emptyText` — override for the "nothing running" line.
|
|
234
|
+
* - `headerAction` — an action descriptor drawn in the card header
|
|
235
|
+
* (`{ label, icon?, ...action }`, "Flow uitvoeren"), reported through
|
|
236
|
+
* the `header` event and dispatched with the page's dispatcher; its
|
|
237
|
+
* tokens resolve against the record. The runs are read again after it.
|
|
231
238
|
*
|
|
232
239
|
* @type {{limit?: number, pollSeconds?: number, rowRoute?: string, runRoute?: string, subject?: string, emptyText?: string, title?: string}}
|
|
233
240
|
*/
|
|
@@ -257,6 +264,8 @@ export default {
|
|
|
257
264
|
},
|
|
258
265
|
},
|
|
259
266
|
|
|
267
|
+
emits: ['header'],
|
|
268
|
+
|
|
260
269
|
setup(props) {
|
|
261
270
|
// The shared endpoint engine owns request dedup, the short-TTL cache
|
|
262
271
|
// and the cn:page:refresh / cn:widget:refresh subscriptions — the same
|
|
@@ -352,6 +361,7 @@ export default {
|
|
|
352
361
|
refetchCompleted,
|
|
353
362
|
resolvedSubject,
|
|
354
363
|
injectedTranslate,
|
|
364
|
+
tokenCtx,
|
|
355
365
|
}
|
|
356
366
|
},
|
|
357
367
|
|
|
@@ -521,7 +531,17 @@ export default {
|
|
|
521
531
|
},
|
|
522
532
|
},
|
|
523
533
|
|
|
534
|
+
watch: {
|
|
535
|
+
'content.headerAction': {
|
|
536
|
+
deep: true,
|
|
537
|
+
handler() {
|
|
538
|
+
this.emitHeader()
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
|
|
524
543
|
mounted() {
|
|
544
|
+
this.emitHeader()
|
|
525
545
|
this.startPolling()
|
|
526
546
|
document.addEventListener('visibilitychange', this.onVisibilityChange)
|
|
527
547
|
},
|
|
@@ -531,6 +551,47 @@ export default {
|
|
|
531
551
|
},
|
|
532
552
|
|
|
533
553
|
methods: {
|
|
554
|
+
/**
|
|
555
|
+
* Tell the card around the runs what its header shows: the header
|
|
556
|
+
* action, if any.
|
|
557
|
+
*
|
|
558
|
+
* @return {void}
|
|
559
|
+
*/
|
|
560
|
+
emitHeader() {
|
|
561
|
+
const action = this.content && this.content.headerAction
|
|
562
|
+
const usable = action && typeof action === 'object' && typeof action.label === 'string' && action.label !== ''
|
|
563
|
+
/**
|
|
564
|
+
* @event header The card header's parts: `{ link, note, action, pill }`, `action` being `{ label, icon, run }` or null.
|
|
565
|
+
*/
|
|
566
|
+
this.$emit('header', {
|
|
567
|
+
link: null,
|
|
568
|
+
note: '',
|
|
569
|
+
action: usable ? { label: this.tr(action.label), icon: action.icon || '', run: () => this.runHeaderAction() } : null,
|
|
570
|
+
pill: null,
|
|
571
|
+
})
|
|
572
|
+
},
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Run the header action with the record's tokens resolved, then read the
|
|
576
|
+
* runs again so a started run shows.
|
|
577
|
+
*
|
|
578
|
+
* @return {Promise<void>}
|
|
579
|
+
*/
|
|
580
|
+
async runHeaderAction() {
|
|
581
|
+
const { label, icon, ...action } = resolveDeepTokens(this.content.headerAction, this.tokenCtx())
|
|
582
|
+
try {
|
|
583
|
+
const outcome = await (typeof this.cnDispatchAction === 'function'
|
|
584
|
+
? this.cnDispatchAction(action)
|
|
585
|
+
: dispatchAction(action, { router: this.$router || null }))
|
|
586
|
+
if (outcome === false) {
|
|
587
|
+
return
|
|
588
|
+
}
|
|
589
|
+
} catch {
|
|
590
|
+
return
|
|
591
|
+
}
|
|
592
|
+
this.refetchAll()
|
|
593
|
+
},
|
|
594
|
+
|
|
534
595
|
/**
|
|
535
596
|
* Start (or restart) the refetch interval, unless polling is disabled.
|
|
536
597
|
*
|
|
@@ -416,7 +416,7 @@ export default {
|
|
|
416
416
|
| `quickFilterMode` | String | `'chips'` | How the quick filters render: `'chips'` (pill strip) or `'dropdown'` (a single `NcSelect`). Fed from `pages[].config.quickFilterMode`. |
|
|
417
417
|
| `quickFilterMultiple` | Boolean | `false` | Allow several quick filters active at once; selected tabs' filters are OR-ed into the fetch (same field → `field[]=` array). Fed from `pages[].config.quickFilterMultiple`. |
|
|
418
418
|
| `quickFilterMaxVisible` | Number | `0` | Chips mode only — how many quick-filter pills render inline before the rest move behind one more chip — a `⋯` pill that opens a panel of the hidden lenses. `0` renders every tab, which wraps the actions bar onto a second line once a page declares more than a handful. The visible set is the first *n* entries of `quickFilters`. Fed from `pages[].config.quickFilterMaxVisible`. |
|
|
419
|
-
| `quickFilterPlacement` | String | `''` | Where the quick-filter chips sit. `'toolbar'` keeps them on one row with the Filter button and the view switch, in whatever width that row has beside a side panel (DqTeamwachtrij): the chips take the room the buttons leave, and those that do not fit move behind the overflow chip. Fed from `pages[].config.quickFilterPlacement`. |
|
|
419
|
+
| `quickFilterPlacement` | String | `''` | Where the quick-filter chips sit. `'toolbar'` keeps them on one row with the Filter button and the view switch, in whatever width that row has beside a side panel (DqTeamwachtrij): the chips take the room the buttons leave, and those that do not fit move behind the overflow chip. Fed from `pages[].config.quickFilterPlacement`. `'row'` puts them on a row of their own above the toolbar, wrapping onto more lines instead of folding into the overflow chip (DqTeamwachtrij); beside a side panel the row sits in the list column. |
|
|
420
420
|
| `cardComponent` | String | `''` | Optional name of a consumer-provided card component (registered in the v2 `registry` — any kind carrying a `component` — or in the legacy `customComponents` map on `CnAppRoot`) to render in place of the default `CnObjectCard` when the page is in card-grid view mode. Resolution priority: `#card` scoped slot → `cardComponent` registry entry → default `CnObjectCard`. Unknown names log `console.warn` once and fall back to the default. |
|
|
421
421
|
| `customComponents` | Object | `null` | Optional explicit `customComponents` registry. Overrides the registry injected from `CnAppRoot` via `cnCustomComponents`. Mostly used by unit tests; production consumers register components on `CnAppRoot` instead. |
|
|
422
422
|
| `subscribe` | Boolean | `true` | Self-fetch mode only. When `register` + `schema` are set (and no `objects` prop), the page subscribes to the collection's `or-collection-{register}-{schema}` live-update scope on mount and refetches on an update event; released on unmount. Set `false` (manifest: `config.subscribe: false`) for static / read-once views. No-op in consumer-managed mode or on stores without live-updates support. |
|
|
@@ -879,9 +879,9 @@ The list view (`view-mode="list"`) and standalone sort dropdown add these props:
|
|
|
879
879
|
| `listIcon` | String | `''` | MDI icon for the list view-toggle option. |
|
|
880
880
|
| `listConfig` | Object | `{}` | Field mapping for the default list rows (`CnObjectRow`). |
|
|
881
881
|
| `listComponent` | String | `''` | Custom row component, resolved against the v2 `registry` (any kind carrying a `component`) and then the legacy `customComponents` map. |
|
|
882
|
-
| `showSortSelect` | Boolean | `false` |
|
|
883
|
-
| `sortSelectOptions` | Array | `[]` |
|
|
884
|
-
| `sortSelectValue` | String | `''` |
|
|
882
|
+
| `showSortSelect` | Boolean | `false` | Deprecated, without effect: the toolbar draws no sort select. The table sorts by its column headers; the list, card and map views by the Sort section in the index sidebar. |
|
|
883
|
+
| `sortSelectOptions` | Array | `[]` | The orders the index sidebar's Sort section offers in the list, card and map views: `{ value, label, order? }`, the order its `order` or its `value` read as one (`"-createdAt"`, `"priority:desc,title"`). Without them the section offers the sortable columns. |
|
|
884
|
+
| `sortSelectValue` | String | `''` | Deprecated, without effect: the Sort section shows the current order. |
|
|
885
885
|
| `defaultOrder` | String, Object or Array | `''` | The order a self-fetch page opens on when neither the address nor `sortKeys`/`sortKey` gives one (manifest `config.defaultOrder`): `"-createdAt"`, `"priority:desc,title"`, an `_order` map `{ "priority": "desc" }` or a `[{ key, order }]` list. |
|
|
886
886
|
|
|
887
887
|
The `#list-item`, `#row-icon`, `#row-badges`, and `#row-actions` slots override the list rows (see [CnObjectList](./cn-object-list.md)). Emits `@sort-change` with the chosen sort value.
|
|
@@ -1097,6 +1097,8 @@ Sources: `register` (fetch the folder list from an OpenRegister `register`/`sche
|
|
|
1097
1097
|
}
|
|
1098
1098
|
```
|
|
1099
1099
|
|
|
1100
|
+
`scopeViews` limits the scope's look (columns, title, count line and the other scope keys) to the view modes it names, e.g. `["table", "list"]`, so a board view keeps the page's generic look (DqWerkbord) while the scope still filters it.
|
|
1101
|
+
|
|
1100
1102
|
`pane: false` draws no pane. The folder still comes from the deep-link filter (`/cases?caseType=<uuid>`) and its scope look (title, count line, columns, quick filters, `afterList` from the folder or its row's `x-index`) still applies, so a list narrowed to one case type looks like that case type's list without a folder column (boards DqWooVerzoeken, DqKlachten):
|
|
1101
1103
|
|
|
1102
1104
|
```json
|
|
@@ -1149,7 +1151,7 @@ columns are right.
|
|
|
1149
1151
|
|
|
1150
1152
|
## Board look
|
|
1151
1153
|
|
|
1152
|
-
With `look: "board"` (the page's `look` prop, `config.look`, or the app's) the index page takes the DqZaken setup: a header with the count line from `countText` (`{shown}`, `{total}`), the buttons Download, Actions, the buildiq square and the primary one in that order, a two-row toolbar (saved-view chips, Filter with a count and the view switch; then search and active filter chips), a bulk band between toolbar and table (`bulkHint`), the table as a white card with one menu button per row, and a footer inside the card (`footerNote`). `cardFields` names the facts of each card in the cards view. Without the look nothing changes.
|
|
1154
|
+
With `look: "board"` (the page's `look` prop, `config.look`, or the app's) the index page takes the DqZaken setup: a header with the count line from `countText` (`{shown}`, `{total}`), the buttons Download, Actions, the buildiq square and the primary one in that order, a two-row toolbar (saved-view chips, Filter with a count and the view switch; then search and active filter chips), a bulk band between toolbar and table (`bulkHint`), the table as a white card with one menu button per row, and a footer inside the card (`footerNote`). `cardFields` names the facts of each card in the cards view, and `cardLayout` draws each card as a record instead: a pill and the number on the head row, the title, a meta line, and a footer with a pill and a date, every part from a field (`{ headPill: { field, colorMap, labels }, number, title, meta: [...], footerPill, footerDate: { field, label } }`). Without the look nothing changes.
|
|
1153
1155
|
|
|
1154
1156
|
`bulkBandAlways` (`config.bulkBandAlways`) draws the board bulk band before a selection too, its buttons
|
|
1155
1157
|
disabled until rows are selected (DqZaken, DqWerkbord).
|
|
@@ -157,6 +157,25 @@
|
|
|
157
157
|
:widgets="sidePanel" />
|
|
158
158
|
|
|
159
159
|
<!-- Actions bar -->
|
|
160
|
+
<!-- `quickFilterPlacement: "row"`: the chips on a row of their own above
|
|
161
|
+
the toolbar, wrapping onto more lines (DqTeamwachtrij). -->
|
|
162
|
+
<div
|
|
163
|
+
v-if="quickFilterPlacement === 'row' && tabStripEntries && tabStripEntries.length > 0"
|
|
164
|
+
class="cn-index-page__quick-filter-row"
|
|
165
|
+
data-testid="cn-index-page-quick-filter-row">
|
|
166
|
+
<CnQuickFilterBar
|
|
167
|
+
inline
|
|
168
|
+
:tabs="tabStripEntries"
|
|
169
|
+
:mode="quickFilterMode"
|
|
170
|
+
:maxVisible="quickFilterMaxVisible"
|
|
171
|
+
:fit="false"
|
|
172
|
+
:multiple="quickFilterMultiple"
|
|
173
|
+
:activeIndex="activeQuickFilterIndex"
|
|
174
|
+
:selectedIndices="selectedQuickFilterIndices"
|
|
175
|
+
:counts="effectiveTabCounts"
|
|
176
|
+
@update:activeIndex="onQuickFilterChange"
|
|
177
|
+
@update:selectedIndices="onQuickFilterMultiChange" />
|
|
178
|
+
</div>
|
|
160
179
|
<CnActionsBar
|
|
161
180
|
:layout="isBoardLook ? 'board' : 'nextcloud'"
|
|
162
181
|
:activeFilterChips="activeFilterChips"
|
|
@@ -189,9 +208,6 @@
|
|
|
189
208
|
:mapLabel="mapLabel"
|
|
190
209
|
:mapIcon="mapIcon"
|
|
191
210
|
:listIcon="listIcon"
|
|
192
|
-
:showSortSelect="showSortSelect"
|
|
193
|
-
:sortOptions="sortSelectOptions"
|
|
194
|
-
:sortValue="effectiveSortSelectValue"
|
|
195
211
|
:showSearch="search !== false && (inlineSearch || isBoardLook)"
|
|
196
212
|
:searchPlacement="searchPlacement"
|
|
197
213
|
:searchValue="effectiveSearchValue"
|
|
@@ -210,7 +226,6 @@
|
|
|
210
226
|
:bulkActions="mergedBulkActions"
|
|
211
227
|
:documentationUrl="documentationUrl"
|
|
212
228
|
:documentationLabel="documentationLabel || undefined"
|
|
213
|
-
@sortChange="onSortSelectChange"
|
|
214
229
|
@add="onAddClick"
|
|
215
230
|
@clearSelection="onSelect([])"
|
|
216
231
|
@removeFilter="onRemoveActiveFilter"
|
|
@@ -365,7 +380,7 @@
|
|
|
365
380
|
(between the view toggle and the actions) when the manifest
|
|
366
381
|
declares `config.quickFilters`. Switching tabs re-fetches with
|
|
367
382
|
the merged filter; @event quick-filter-change. -->
|
|
368
|
-
<template v-if="tabStripEntries && tabStripEntries.length > 0" #filters>
|
|
383
|
+
<template v-if="tabStripEntries && tabStripEntries.length > 0 && quickFilterPlacement !== 'row'" #filters>
|
|
369
384
|
<CnQuickFilterBar
|
|
370
385
|
inline
|
|
371
386
|
:tabs="tabStripEntries"
|
|
@@ -373,7 +388,7 @@
|
|
|
373
388
|
:maxVisible="quickFilterMaxVisible"
|
|
374
389
|
:fit="quickFilterPlacement === 'toolbar'"
|
|
375
390
|
:multiple="quickFilterMultiple"
|
|
376
|
-
:activeIndex="
|
|
391
|
+
:activeIndex="shownQuickFilterIndex"
|
|
377
392
|
:selectedIndices="selectedQuickFilterIndices"
|
|
378
393
|
:counts="effectiveTabCounts"
|
|
379
394
|
@update:activeIndex="onQuickFilterChange"
|
|
@@ -772,7 +787,7 @@
|
|
|
772
787
|
:rowTitle="rowTitle"
|
|
773
788
|
:showUnread="showUnreadRows"
|
|
774
789
|
:filterable="tableHeaderFilters"
|
|
775
|
-
:activeFilters="
|
|
790
|
+
:activeFilters="tableActiveFilters"
|
|
776
791
|
:filterRegister="typeof register === 'string' ? register : ''"
|
|
777
792
|
@columnFilter="onColumnFilterEvent"
|
|
778
793
|
@sort="onSortEvent"
|
|
@@ -1057,6 +1072,8 @@
|
|
|
1057
1072
|
:selectable="selectable"
|
|
1058
1073
|
:clickToView="rowClickOpens"
|
|
1059
1074
|
:cardFields="resolvedCardFields"
|
|
1075
|
+
:cardLayout="cardLayout"
|
|
1076
|
+
:cardFieldColumns="cardFieldColumns"
|
|
1060
1077
|
:accentOf="cardAccent"
|
|
1061
1078
|
:selectedIds="internalSelectedIds"
|
|
1062
1079
|
:rowKey="rowKey"
|
|
@@ -1229,6 +1246,8 @@
|
|
|
1229
1246
|
:showMetadata="resolvedSidebar.showMetadata !== false"
|
|
1230
1247
|
:personalColumns="personalColumns"
|
|
1231
1248
|
:pinnedCount="pinnedColumnCount"
|
|
1249
|
+
:sortOptions="sidebarSortOptions"
|
|
1250
|
+
:currentSort="currentSortKeys"
|
|
1232
1251
|
v-bind="sidebarSearchProps"
|
|
1233
1252
|
@update:open="sidebarOpen = $event"
|
|
1234
1253
|
@search="onSearchEvent"
|
|
@@ -1237,7 +1256,8 @@
|
|
|
1237
1256
|
@pinChange="onPinChange"
|
|
1238
1257
|
@columnsReset="onColumnsReset"
|
|
1239
1258
|
@filterChange="onFilterEvent"
|
|
1240
|
-
@clearFilters="onClearFilters"
|
|
1259
|
+
@clearFilters="onClearFilters"
|
|
1260
|
+
@sortChange="onSidebarSortChange" />
|
|
1241
1261
|
</div>
|
|
1242
1262
|
</template>
|
|
1243
1263
|
|
|
@@ -1285,6 +1305,7 @@ import {
|
|
|
1285
1305
|
refIdOf,
|
|
1286
1306
|
resolveDropValue,
|
|
1287
1307
|
} from '../../utils/boardReferenceColumns.js'
|
|
1308
|
+
import { isColumnSortable } from '../../utils/columnFilters.js'
|
|
1288
1309
|
import { reportBindingProblems } from '../../utils/diagnostics.js'
|
|
1289
1310
|
import { fetchGroupedCounts } from '../../utils/fetchAggregate.js'
|
|
1290
1311
|
import { fetchFilterCounts, fetchListTotal } from '../../utils/fetchFilterCounts.js'
|
|
@@ -1311,7 +1332,7 @@ import { DEFAULT_ROW_INDICATOR_CAP } from '../../utils/rowIndicators.js'
|
|
|
1311
1332
|
import { buildRouteQueryFromViewState, buildViewCreatePayload, extractViewState, extractViewStateFromRouteQuery, normalizeSharedWith, savedViewScope, viewMatchesScope } from '../../utils/savedViewHelpers.js'
|
|
1312
1333
|
import { columnsFromSchema, fieldsFromSchema } from '../../utils/schema.js'
|
|
1313
1334
|
import { resolveScopeLayout, resolveScopePresentation } from '../../utils/scopeListLayout.js'
|
|
1314
|
-
import { orderToSortKeys
|
|
1335
|
+
import { orderToSortKeys } from '../../utils/sortOrder.js'
|
|
1315
1336
|
import { dispatchObjectCreated } from '../../utils/walkthroughSignals.js'
|
|
1316
1337
|
import { CnActionButtons } from '../CnActionButtons/index.js'
|
|
1317
1338
|
import { CnActionsBar } from '../CnActionsBar/index.js'
|
|
@@ -1350,7 +1371,7 @@ import { orderColumns, personalColumnsKey, reconcilePersonalColumns } from './pe
|
|
|
1350
1371
|
import { createSelfModeActions, resolveRowTarget } from './selfModeActions.js'
|
|
1351
1372
|
import { applyRowPatches, normalisePaneWidth, rowIdOf, splitLayoutFor } from './splitView.js'
|
|
1352
1373
|
import { useNamedSource } from './useNamedSource.js'
|
|
1353
|
-
import { BOARD_PAGE_SIZE, useSelfFetchList } from './useSelfFetchList.js'
|
|
1374
|
+
import { BOARD_PAGE_SIZE, resolveInitialQuickFilterIndex, useSelfFetchList } from './useSelfFetchList.js'
|
|
1354
1375
|
|
|
1355
1376
|
/** Rows fetched for one month in calendar mode. */
|
|
1356
1377
|
const CALENDAR_PAGE_SIZE = 200
|
|
@@ -1934,6 +1955,20 @@ export default {
|
|
|
1934
1955
|
default: null,
|
|
1935
1956
|
},
|
|
1936
1957
|
|
|
1958
|
+
/**
|
|
1959
|
+
* Board look: the record layout of each card in the cards view
|
|
1960
|
+
* (manifest key `config.cardLayout`): `{ headPill, number, title,
|
|
1961
|
+
* meta, footerPill, footerDate }`, each part naming a field. See
|
|
1962
|
+
* CnObjectCard `layout`.
|
|
1963
|
+
*
|
|
1964
|
+
* @type {object}
|
|
1965
|
+
* @spec openspec/changes/board-record-card-layout/specs/board-record-card-layout/spec.md#requirement-a-board-card-can-draw-the-record-layout-from-config
|
|
1966
|
+
*/
|
|
1967
|
+
cardLayout: {
|
|
1968
|
+
type: Object,
|
|
1969
|
+
default: null,
|
|
1970
|
+
},
|
|
1971
|
+
|
|
1937
1972
|
/**
|
|
1938
1973
|
* Gives each card in the card view a status accent: a colored start
|
|
1939
1974
|
* border and icon. See CnObjectCard `accent`.
|
|
@@ -2157,13 +2192,15 @@ export default {
|
|
|
2157
2192
|
* the Filter button and the view switch, in whatever width that row has
|
|
2158
2193
|
* beside a side panel (DqTeamwachtrij): the chips take the room the
|
|
2159
2194
|
* buttons leave, and those that do not fit move into the overflow chip.
|
|
2195
|
+
* `'row'` puts them on a row of their own above the toolbar, wrapping
|
|
2196
|
+
* onto more lines instead of folding into the overflow chip.
|
|
2160
2197
|
*
|
|
2161
|
-
* @type {''|'toolbar'}
|
|
2198
|
+
* @type {''|'toolbar'|'row'}
|
|
2162
2199
|
*/
|
|
2163
2200
|
quickFilterPlacement: {
|
|
2164
2201
|
type: String,
|
|
2165
2202
|
default: '',
|
|
2166
|
-
validator: (v) => ['', 'toolbar'].includes(v),
|
|
2203
|
+
validator: (v) => ['', 'toolbar', 'row'].includes(v),
|
|
2167
2204
|
},
|
|
2168
2205
|
|
|
2169
2206
|
/**
|
|
@@ -3197,9 +3234,11 @@ export default {
|
|
|
3197
3234
|
},
|
|
3198
3235
|
|
|
3199
3236
|
/**
|
|
3200
|
-
*
|
|
3201
|
-
*
|
|
3202
|
-
*
|
|
3237
|
+
* Deprecated, without effect: the toolbar draws no sort select. The
|
|
3238
|
+
* table sorts by its column headers, the list, card and map views by
|
|
3239
|
+
* the Sort section in the index sidebar.
|
|
3240
|
+
*
|
|
3241
|
+
* @deprecated
|
|
3203
3242
|
*/
|
|
3204
3243
|
showSortSelect: {
|
|
3205
3244
|
type: Boolean,
|
|
@@ -3207,7 +3246,11 @@ export default {
|
|
|
3207
3246
|
},
|
|
3208
3247
|
|
|
3209
3248
|
/**
|
|
3210
|
-
*
|
|
3249
|
+
* The orders the index sidebar's Sort section offers in the list, card
|
|
3250
|
+
* and map views (manifest `config.sortSelectOptions`): `{ value, label,
|
|
3251
|
+
* order? }`, the order its `order` (an `orderToSortKeys` form) or its
|
|
3252
|
+
* `value` read as one. Without them the section offers the sortable
|
|
3253
|
+
* columns.
|
|
3211
3254
|
*
|
|
3212
3255
|
* @type {Array<{ value: string, label: string }>}
|
|
3213
3256
|
*/
|
|
@@ -3217,8 +3260,10 @@ export default {
|
|
|
3217
3260
|
},
|
|
3218
3261
|
|
|
3219
3262
|
/**
|
|
3220
|
-
*
|
|
3221
|
-
*
|
|
3263
|
+
* Deprecated, without effect: the toolbar sort select is gone; the
|
|
3264
|
+
* Sort section in the index sidebar shows the current order.
|
|
3265
|
+
*
|
|
3266
|
+
* @deprecated
|
|
3222
3267
|
*/
|
|
3223
3268
|
sortSelectValue: {
|
|
3224
3269
|
type: String,
|
|
@@ -3271,6 +3316,9 @@ export default {
|
|
|
3271
3316
|
* defaults to `field`).
|
|
3272
3317
|
* - `folders` — explicit folder list for `source:'custom'`.
|
|
3273
3318
|
* - `allLabel` / `title` / `allowCreate` — passed to CnFolderSidebar.
|
|
3319
|
+
* - `scopeViews` — the view modes the scope's look (columns, title,
|
|
3320
|
+
* count line and the other scope keys) applies in, e.g. `["table",
|
|
3321
|
+
* "list"]`; other views keep the page's own look. Default: every view.
|
|
3274
3322
|
* - `pane` — `false` draws no pane: the scope still comes from the
|
|
3275
3323
|
* deep-link filter (`?caseType=<id>`) and still applies its look, as
|
|
3276
3324
|
* a list narrowed to one case type does without a folder column.
|
|
@@ -5002,22 +5050,45 @@ export default {
|
|
|
5002
5050
|
},
|
|
5003
5051
|
|
|
5004
5052
|
/**
|
|
5005
|
-
* The
|
|
5006
|
-
*
|
|
5007
|
-
* list's current order (a header click that matches one shows it).
|
|
5053
|
+
* The list's current order, `[{ key, order }]`: the self-fetched list's,
|
|
5054
|
+
* else the `sortKeys` / `sortKey` props.
|
|
5008
5055
|
*
|
|
5009
|
-
* @return {string
|
|
5056
|
+
* @return {Array<{key: string, order: string}>} The order.
|
|
5010
5057
|
*/
|
|
5011
|
-
|
|
5012
|
-
if (this.
|
|
5013
|
-
return this.
|
|
5058
|
+
currentSortKeys() {
|
|
5059
|
+
if (this.isSelfFetchMode && this.list && this.list.sortKeys) {
|
|
5060
|
+
return this.list.sortKeys.value || []
|
|
5014
5061
|
}
|
|
5015
|
-
if (
|
|
5016
|
-
return
|
|
5062
|
+
if (Array.isArray(this.sortKeys) && this.sortKeys.length > 0) {
|
|
5063
|
+
return this.sortKeys
|
|
5017
5064
|
}
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5065
|
+
return this.sortKey ? [{ key: this.sortKey, order: this.sortOrder || 'asc' }] : []
|
|
5066
|
+
},
|
|
5067
|
+
|
|
5068
|
+
/**
|
|
5069
|
+
* The orders the index sidebar's Sort section offers: none in the table
|
|
5070
|
+
* view, which sorts by its column headers; else `sortSelectOptions`,
|
|
5071
|
+
* or else the sortable columns, ascending.
|
|
5072
|
+
*
|
|
5073
|
+
* @return {Array<{value: string, label: string, keys: Array<{key: string, order: string}>}>} The options.
|
|
5074
|
+
*/
|
|
5075
|
+
sidebarSortOptions() {
|
|
5076
|
+
if (this.currentViewMode === 'table') {
|
|
5077
|
+
return []
|
|
5078
|
+
}
|
|
5079
|
+
if (Array.isArray(this.sortSelectOptions) && this.sortSelectOptions.length > 0) {
|
|
5080
|
+
return this.sortSelectOptions
|
|
5081
|
+
.filter((o) => o && o.value !== undefined && o.value !== null)
|
|
5082
|
+
.map((o) => ({
|
|
5083
|
+
value: String(o.value),
|
|
5084
|
+
label: this.cnTranslate(o.label || String(o.value)),
|
|
5085
|
+
keys: orderToSortKeys(o.order !== undefined ? o.order : o.value),
|
|
5086
|
+
}))
|
|
5087
|
+
.filter((o) => o.keys.length > 0)
|
|
5088
|
+
}
|
|
5089
|
+
return (this.tableColumns || [])
|
|
5090
|
+
.filter((c) => c && typeof c === 'object' && c.key && isColumnSortable(c, this.effectiveSchema))
|
|
5091
|
+
.map((c) => ({ value: c.key, label: this.cnTranslate(c.label || c.key), keys: [{ key: c.key, order: 'asc' }] }))
|
|
5021
5092
|
},
|
|
5022
5093
|
|
|
5023
5094
|
/**
|
|
@@ -5049,7 +5120,7 @@ export default {
|
|
|
5049
5120
|
* @spec openspec/changes/index-columns-per-scope/specs/index-page/spec.md
|
|
5050
5121
|
*/
|
|
5051
5122
|
activeScopeLayout() {
|
|
5052
|
-
if (!this.folderSidebar) {
|
|
5123
|
+
if (!this.folderSidebar || !this.scopeShapesView) {
|
|
5053
5124
|
return { columns: null, sortKeys: [], searchFields: [] }
|
|
5054
5125
|
}
|
|
5055
5126
|
return resolveScopeLayout({
|
|
@@ -5059,6 +5130,23 @@ export default {
|
|
|
5059
5130
|
})
|
|
5060
5131
|
},
|
|
5061
5132
|
|
|
5133
|
+
/**
|
|
5134
|
+
* Whether the active scope's look applies in the current view mode:
|
|
5135
|
+
* always, unless `folderSidebar.scopeViews` names the view modes it is
|
|
5136
|
+
* for (`["table", "list"]`), so the board keeps the page's generic
|
|
5137
|
+
* look (DqWerkbord). The scope's filter applies in every view.
|
|
5138
|
+
*
|
|
5139
|
+
* @spec openspec/changes/index-scope-views/specs/index-page/spec.md#requirement-a-scope-look-can-be-limited-to-view-modes
|
|
5140
|
+
* @return {boolean}
|
|
5141
|
+
*/
|
|
5142
|
+
scopeShapesView() {
|
|
5143
|
+
const views = this.folderSidebar && this.folderSidebar.scopeViews
|
|
5144
|
+
if (!Array.isArray(views) || views.length === 0) {
|
|
5145
|
+
return true
|
|
5146
|
+
}
|
|
5147
|
+
return views.includes(this.currentViewMode)
|
|
5148
|
+
},
|
|
5149
|
+
|
|
5062
5150
|
/**
|
|
5063
5151
|
* This page's own value of each presentation key, which a query preset
|
|
5064
5152
|
* may have set: what `presented()` falls back to without a scope.
|
|
@@ -5093,7 +5181,7 @@ export default {
|
|
|
5093
5181
|
* @spec openspec/changes/index-scope-presentation/specs/index-page/spec.md#requirement-a-preset-or-a-scope-sets-the-list-s-presentation
|
|
5094
5182
|
*/
|
|
5095
5183
|
activeScopePresentation() {
|
|
5096
|
-
if (!this.folderSidebar) {
|
|
5184
|
+
if (!this.folderSidebar || !this.scopeShapesView) {
|
|
5097
5185
|
return {}
|
|
5098
5186
|
}
|
|
5099
5187
|
return resolveScopePresentation({ scope: this.activeScope, row: this.activeScopeRow })
|
|
@@ -5335,6 +5423,20 @@ export default {
|
|
|
5335
5423
|
* @return {(Array<object>|null)} The tabs.
|
|
5336
5424
|
* @spec openspec/changes/working-list-row-actions/specs/index-page/spec.md
|
|
5337
5425
|
*/
|
|
5426
|
+
/**
|
|
5427
|
+
* The chip the strip lights: the active tab, else the default tab of
|
|
5428
|
+
* tabs that arrived after setup (`quickFiltersFrom`), which is the
|
|
5429
|
+
* one the fetch applies.
|
|
5430
|
+
*
|
|
5431
|
+
* @return {number|null} The tab index, or null without tabs.
|
|
5432
|
+
*/
|
|
5433
|
+
shownQuickFilterIndex() {
|
|
5434
|
+
if (this.activeQuickFilterIndex !== null && this.activeQuickFilterIndex !== undefined) {
|
|
5435
|
+
return this.activeQuickFilterIndex
|
|
5436
|
+
}
|
|
5437
|
+
return this.quickFilterMultiple ? null : resolveInitialQuickFilterIndex(this.tabStripEntries)
|
|
5438
|
+
},
|
|
5439
|
+
|
|
5338
5440
|
tabStripEntries() {
|
|
5339
5441
|
if (this.lensTabs.length > 0) {
|
|
5340
5442
|
return this.lensTabs
|
|
@@ -5561,6 +5663,22 @@ export default {
|
|
|
5561
5663
|
return specs
|
|
5562
5664
|
},
|
|
5563
5665
|
|
|
5666
|
+
/**
|
|
5667
|
+
* The rendered columns by key, so a card fact shows what its table
|
|
5668
|
+
* cell shows (label, formatter, widget).
|
|
5669
|
+
*
|
|
5670
|
+
* @return {object} Column definitions keyed by property.
|
|
5671
|
+
*/
|
|
5672
|
+
cardFieldColumns() {
|
|
5673
|
+
const byKey = {}
|
|
5674
|
+
for (const col of this.renderedColumns || []) {
|
|
5675
|
+
if (col && typeof col === 'object' && typeof col.key === 'string') {
|
|
5676
|
+
byKey[col.key] = col
|
|
5677
|
+
}
|
|
5678
|
+
}
|
|
5679
|
+
return byKey
|
|
5680
|
+
},
|
|
5681
|
+
|
|
5564
5682
|
/**
|
|
5565
5683
|
* The property keys the board look's card facts show: the page's
|
|
5566
5684
|
* `cardFields`, else the first four list columns. Null without the
|
|
@@ -6410,8 +6528,11 @@ export default {
|
|
|
6410
6528
|
|
|
6411
6529
|
const present = new Set(cols.map((c) => (typeof c === 'string' ? c : c.key)))
|
|
6412
6530
|
const byKey = new Map(this.governedColumns.map((c) => [c.key, c]))
|
|
6531
|
+
// A scope that sets its own columns does not get its folder field back:
|
|
6532
|
+
// every row of the scope holds the same value there.
|
|
6533
|
+
const scopeField = this.activeScopeLayout.columns ? this.folderFilterKey : ''
|
|
6413
6534
|
visible.forEach((key) => {
|
|
6414
|
-
if (present.has(key)) {
|
|
6535
|
+
if (present.has(key) || key === scopeField) {
|
|
6415
6536
|
return
|
|
6416
6537
|
}
|
|
6417
6538
|
const def = byKey.get(key)
|
|
@@ -6886,6 +7007,28 @@ export default {
|
|
|
6886
7007
|
return count > 0 ? `${name}, ${t('nextcloud-vue', '{count} active', { count })}` : name
|
|
6887
7008
|
},
|
|
6888
7009
|
|
|
7010
|
+
/** @return {string} The field the folder sidebar filters by, or ''. */
|
|
7011
|
+
folderFilterKey() {
|
|
7012
|
+
return (this.folderSidebar && (this.folderSidebar.filterField || this.folderSidebar.field)) || ''
|
|
7013
|
+
},
|
|
7014
|
+
|
|
7015
|
+
/**
|
|
7016
|
+
* The filters the table's header filters show: every active filter but
|
|
7017
|
+
* the selected folder's own, which the Active chip already names, so
|
|
7018
|
+
* the table draws no summary chip for it.
|
|
7019
|
+
*
|
|
7020
|
+
* @return {object} The filters.
|
|
7021
|
+
*/
|
|
7022
|
+
tableActiveFilters() {
|
|
7023
|
+
const filters = this.effectiveActiveFilters || {}
|
|
7024
|
+
const key = this.folderFilterKey
|
|
7025
|
+
if (!key || this.selectedFolderId === null || this.selectedFolderId === undefined || !Object.hasOwn(filters, key)) {
|
|
7026
|
+
return filters
|
|
7027
|
+
}
|
|
7028
|
+
const { [key]: _folder, ...rest } = filters
|
|
7029
|
+
return rest
|
|
7030
|
+
},
|
|
7031
|
+
|
|
6889
7032
|
/**
|
|
6890
7033
|
* The active filters as chips for the board toolbar's second row, one
|
|
6891
7034
|
* per filter: "Team: Woo". A filter with no value is not active.
|
|
@@ -7289,6 +7432,8 @@ export default {
|
|
|
7289
7432
|
showMetadata: this.resolvedSidebar.showMetadata !== false,
|
|
7290
7433
|
personalColumns: this.personalColumns,
|
|
7291
7434
|
pinnedCount: this.pinnedColumnCount,
|
|
7435
|
+
sortOptions: this.sidebarSortOptions,
|
|
7436
|
+
currentSort: this.currentSortKeys,
|
|
7292
7437
|
...this.sidebarSearchProps,
|
|
7293
7438
|
}
|
|
7294
7439
|
},
|
|
@@ -8761,35 +8906,18 @@ export default {
|
|
|
8761
8906
|
},
|
|
8762
8907
|
|
|
8763
8908
|
/**
|
|
8764
|
-
*
|
|
8765
|
-
*
|
|
8766
|
-
*
|
|
8767
|
-
* @param {object} option A `sortSelectOptions` entry.
|
|
8768
|
-
* @return {Array<{key: string, order: string}>} The sort keys.
|
|
8769
|
-
*/
|
|
8770
|
-
sortSelectKeys(option) {
|
|
8771
|
-
if (!option) {
|
|
8772
|
-
return []
|
|
8773
|
-
}
|
|
8774
|
-
return orderToSortKeys(option.order !== undefined ? option.order : option.value)
|
|
8775
|
-
},
|
|
8776
|
-
|
|
8777
|
-
/**
|
|
8778
|
-
* A choice in the sort select. On a self-fetch page it orders the list
|
|
8779
|
-
* as a header click does (`_order`, kept in the address); every page
|
|
8780
|
-
* also emits `sort-change` with the value.
|
|
8909
|
+
* An order chosen in the index sidebar's Sort section. It goes the way
|
|
8910
|
+
* a header click goes: the self-fetched list sorts (`_order`, kept in
|
|
8911
|
+
* the address), and `sort` is emitted for a host that sorts itself.
|
|
8781
8912
|
*
|
|
8782
|
-
* @param {string}
|
|
8913
|
+
* @param {Array<{key: string, order: string}>} keys The chosen order.
|
|
8783
8914
|
* @return {void}
|
|
8784
8915
|
*/
|
|
8785
|
-
|
|
8786
|
-
|
|
8787
|
-
|
|
8788
|
-
if (option && keys.length > 0 && this.isSelfFetchMode && typeof this.list.onSort === 'function') {
|
|
8789
|
-
this.list.onSort({ key: keys[0].key, order: keys[0].order, keys })
|
|
8790
|
-
this.persistViewStateToRoute(this.currentViewState())
|
|
8916
|
+
onSidebarSortChange(keys) {
|
|
8917
|
+
if (!Array.isArray(keys) || keys.length === 0) {
|
|
8918
|
+
return
|
|
8791
8919
|
}
|
|
8792
|
-
this
|
|
8920
|
+
this.onSortEvent({ key: keys[0].key, order: keys[0].order, keys })
|
|
8793
8921
|
},
|
|
8794
8922
|
|
|
8795
8923
|
/**
|
|
@@ -9977,6 +10105,7 @@ export default {
|
|
|
9977
10105
|
'columns-reset': () => this.onColumnsReset(),
|
|
9978
10106
|
'filter-change': (event) => this.onFilterEvent(event),
|
|
9979
10107
|
'clear-filters': () => this.onClearFilters(),
|
|
10108
|
+
'sort-change': (keys) => this.onSidebarSortChange(keys),
|
|
9980
10109
|
},
|
|
9981
10110
|
}
|
|
9982
10111
|
},
|