@conduction/nextcloud-vue 2.103.0 → 2.105.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/CnActionsBar/CnActionsBar.vue2.js +23 -0
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +94 -72
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +18 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +3 -3
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +93 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +6 -3
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +3 -3
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +39 -2
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +14 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +99 -3
- 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/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue.js +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js.map +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js.map +1 -1
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue.js +1 -1
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js +2 -0
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js.map +1 -1
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js +32 -29
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue.js +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js +73 -4
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js +74 -27
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +213 -4
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +105 -85
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js +10 -4
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue.js +9 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue.js.map +1 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue2.js +88 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue3.js +39 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue.js +1 -1
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue2.js +57 -5
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue3.js +37 -4
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue3.js.map +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js.map +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js +3 -3
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue.js +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +16 -4
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
- package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue.js +1 -1
- package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue.js +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js +11 -0
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js.map +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js +4 -4
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +16 -14
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +18 -2
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
- package/dist/esm/composables/indexSources.js +7 -7
- package/dist/esm/composables/indexSources.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 +8 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +8 -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 +680 -328
- package/dist/esm/utils/libraryWidgetKeys.js +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/nextcloudApps.js +45 -0
- package/dist/esm/utils/nextcloudApps.js.map +1 -0
- package/dist/esm/utils/nextcloudDirectory.js +18 -1
- package/dist/esm/utils/nextcloudDirectory.js.map +1 -1
- package/dist/esm/utils/scopeListLayout.js +9 -2
- package/dist/esm/utils/scopeListLayout.js.map +1 -1
- package/dist/esm/utils/sortOrder.js +61 -0
- package/dist/esm/utils/sortOrder.js.map +1 -0
- package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/visibleWhen.js +12 -4
- package/dist/esm/utils/visibleWhen.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +4046 -2999
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +680 -328
- package/l10n/en.json +8 -1
- package/l10n/nl.json +8 -1
- package/package.json +1 -1
- package/src/components/CnActionsBar/CnActionsBar.md +1 -0
- package/src/components/CnActionsBar/CnActionsBar.vue +39 -2
- package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +1 -1
- package/src/components/CnAppRoot/CnAppRoot.md +1 -1
- package/src/components/CnAppRoot/CnAppRoot.vue +21 -4
- package/src/components/CnChartWidget/CnChartWidget.md +2 -0
- package/src/components/CnChartWidget/CnChartWidget.vue +93 -1
- package/src/components/CnDashboardPage/CnDashboardPage.vue +9 -6
- package/src/components/CnDataTable/CnDataTable.md +1 -0
- package/src/components/CnDataTable/CnDataTable.vue +49 -0
- package/src/components/CnDetailPage/CnDetailPage.md +2 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +99 -3
- package/src/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue +1 -1
- package/src/components/CnFeaturesBoard/CnFeaturesBoard.vue +4 -1
- package/src/components/CnFlowsPage/CnFlowBoard.vue +132 -8
- package/src/components/CnIndexPage/CnIndexPage.md +5 -2
- package/src/components/CnIndexPage/CnIndexPage.vue +228 -9
- package/src/components/CnIndexPage/useSelfFetchList.js +9 -3
- package/src/components/CnNoticeWidget/CnNoticeWidget.vue +153 -0
- package/src/components/CnNoticeWidget/index.js +12 -0
- package/src/components/CnObjectRow/CnObjectRow.vue +95 -1
- package/src/components/CnSettingsField/CnSettingsField.vue +4 -1
- package/src/components/CnSetupWizard/CnSetupWizard.vue +9 -1
- package/src/components/CnUserSettingsDialog/CnUserSettingsDialog.vue +7 -2
- package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +15 -4
- package/src/components/CnWidgetGrid/builtInWidgets.js +2 -0
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +18 -2
- package/src/components/index.js +1 -0
- package/src/composables/indexSources.js +7 -7
- package/src/css/dialog.css +20 -2
- package/src/css/index-page.css +19 -0
- package/src/css/look-board-detail.css +77 -4
- package/src/css/look-board-index.css +84 -2
- package/src/css/look-board.css +97 -12
- package/src/index.js +1 -0
- package/src/schemas/app-manifest-v2.schema.json +58 -3
- package/src/utils/libraryWidgetKeys.js +1 -0
- package/src/utils/nextcloudApps.js +50 -0
- package/src/utils/nextcloudDirectory.js +17 -0
- package/src/utils/scopeListLayout.js +9 -2
- package/src/utils/sortOrder.js +58 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
- package/src/utils/visibleWhen.js +12 -4
|
@@ -1267,7 +1267,7 @@ import { isActivityWidget, resolveHeaderMeta } from '../../utils/headerMeta.js'
|
|
|
1267
1267
|
import { patchStoredSelf } from '../../utils/patchStoredSelf.js'
|
|
1268
1268
|
import { setReadState } from '../../utils/recordInteractions.js'
|
|
1269
1269
|
import { slotRenders } from '../../utils/slotContent.js'
|
|
1270
|
-
import { evaluateVisibleWhen, isLocallyDecidableVisibleWhen } from '../../utils/visibleWhen.js'
|
|
1270
|
+
import { evaluateVisibleWhen, isLocallyDecidableVisibleWhen, readVisibleWhenPath } from '../../utils/visibleWhen.js'
|
|
1271
1271
|
import {
|
|
1272
1272
|
isCardWidgetDef,
|
|
1273
1273
|
isContentOnlyWidgetDef,
|
|
@@ -2567,6 +2567,22 @@ export default {
|
|
|
2567
2567
|
default: null,
|
|
2568
2568
|
},
|
|
2569
2569
|
|
|
2570
|
+
/**
|
|
2571
|
+
* A field path whose value picks the tabs of the page's `tabs` widgets
|
|
2572
|
+
* and their order for this record (manifest `config.tabsFrom`), read
|
|
2573
|
+
* like a `visibleWhen` field: `@context.caseType.tabs` reads the list a
|
|
2574
|
+
* case type keeps. A non-empty list of tab ids (a tab's `id`, else its
|
|
2575
|
+
* `widgetId`, or the string entry itself) keeps those tabs in that
|
|
2576
|
+
* order and leaves the rest out. Any other value keeps the declared
|
|
2577
|
+
* tabs. Edit mode shows them all.
|
|
2578
|
+
*
|
|
2579
|
+
* @spec openspec/changes/detail-tabs-from/specs/detail-page/spec.md#requirement-a-record-can-pick-its-tabs-and-their-order
|
|
2580
|
+
*/
|
|
2581
|
+
tabsFrom: {
|
|
2582
|
+
type: String,
|
|
2583
|
+
default: '',
|
|
2584
|
+
},
|
|
2585
|
+
|
|
2570
2586
|
/**
|
|
2571
2587
|
* A column of cards beside the body (manifest `config.sideColumn`),
|
|
2572
2588
|
* for the record's facts: deadline, requester, handler, links. Each
|
|
@@ -2582,6 +2598,22 @@ export default {
|
|
|
2582
2598
|
default: () => [],
|
|
2583
2599
|
},
|
|
2584
2600
|
|
|
2601
|
+
/**
|
|
2602
|
+
* A field path whose value picks the side column and its order for
|
|
2603
|
+
* this record (manifest `config.sideColumnFrom`), read like a
|
|
2604
|
+
* `visibleWhen` field: `@context.caseType.sideCards` reads the list a
|
|
2605
|
+
* case type keeps. A non-empty list of ids keeps those `sideColumn`
|
|
2606
|
+
* entries, in that order, and leaves the rest out; each still follows
|
|
2607
|
+
* its own `visibleWhen`. Any other value keeps `sideColumn` as
|
|
2608
|
+
* declared, so a record whose list is empty changes nothing.
|
|
2609
|
+
*
|
|
2610
|
+
* @spec openspec/changes/detail-side-column-from/specs/detail-page/spec.md#requirement-a-record-can-pick-the-side-column-and-its-order
|
|
2611
|
+
*/
|
|
2612
|
+
sideColumnFrom: {
|
|
2613
|
+
type: String,
|
|
2614
|
+
default: '',
|
|
2615
|
+
},
|
|
2616
|
+
|
|
2585
2617
|
/**
|
|
2586
2618
|
* Draw the header as a card (manifest `config.headerCard: true`): the
|
|
2587
2619
|
* pills, the title and the actions on the page's surface colour inside
|
|
@@ -3492,7 +3524,7 @@ export default {
|
|
|
3492
3524
|
* @spec openspec/changes/detail-side-visible-when/specs/detail-page/spec.md#requirement-a-side-column-widget-shows-only-while-its-visiblewhen-holds
|
|
3493
3525
|
*/
|
|
3494
3526
|
sideColumnWidgets() {
|
|
3495
|
-
const resolved = this.
|
|
3527
|
+
const resolved = this.pickedSideWidgets.filter((widget) => this.sideWidgetVisible(widget))
|
|
3496
3528
|
if (!this.isBoard) {
|
|
3497
3529
|
return resolved
|
|
3498
3530
|
}
|
|
@@ -3504,6 +3536,28 @@ export default {
|
|
|
3504
3536
|
.map(({ widget }) => widget)
|
|
3505
3537
|
},
|
|
3506
3538
|
|
|
3539
|
+
/**
|
|
3540
|
+
* The side column's definitions as the record picks them
|
|
3541
|
+
* (`sideColumnFrom`): the ids it lists, in its order, or every
|
|
3542
|
+
* declared entry when it lists none. Edit mode shows them all.
|
|
3543
|
+
*
|
|
3544
|
+
* @return {Array<object>}
|
|
3545
|
+
* @spec openspec/changes/detail-side-column-from/specs/detail-page/spec.md#requirement-a-record-can-pick-the-side-column-and-its-order
|
|
3546
|
+
*/
|
|
3547
|
+
pickedSideWidgets() {
|
|
3548
|
+
const declared = this.declaredSideWidgets
|
|
3549
|
+
if (!this.sideColumnFrom || this.editingBody || !this.widgetVisibilityData) {
|
|
3550
|
+
return declared
|
|
3551
|
+
}
|
|
3552
|
+
const ids = readVisibleWhenPath(this.widgetVisibilityData, this.sideColumnFrom)
|
|
3553
|
+
if (!Array.isArray(ids) || ids.length === 0) {
|
|
3554
|
+
return declared
|
|
3555
|
+
}
|
|
3556
|
+
return ids
|
|
3557
|
+
.map((id) => declared.find((widget) => widget.id === id) || null)
|
|
3558
|
+
.filter(Boolean)
|
|
3559
|
+
},
|
|
3560
|
+
|
|
3507
3561
|
/**
|
|
3508
3562
|
* The side column's entries resolved to definitions, before any
|
|
3509
3563
|
* `visibleWhen` is read: a string names a widget declared in
|
|
@@ -4513,7 +4567,7 @@ export default {
|
|
|
4513
4567
|
*/
|
|
4514
4568
|
bodyGridWidgets() {
|
|
4515
4569
|
if (this.hasGridLayout) {
|
|
4516
|
-
return this.widgets
|
|
4570
|
+
return this.pickTabs(this.widgets)
|
|
4517
4571
|
}
|
|
4518
4572
|
if (this.shouldRenderAutoBody) {
|
|
4519
4573
|
return this.autoBodyWidgets || []
|
|
@@ -4521,6 +4575,21 @@ export default {
|
|
|
4521
4575
|
return []
|
|
4522
4576
|
},
|
|
4523
4577
|
|
|
4578
|
+
/**
|
|
4579
|
+
* The tab ids `tabsFrom` reads off this record, or null when it reads
|
|
4580
|
+
* no non-empty list (or the body is being edited).
|
|
4581
|
+
*
|
|
4582
|
+
* @spec openspec/changes/detail-tabs-from/specs/detail-page/spec.md#requirement-a-record-can-pick-its-tabs-and-their-order
|
|
4583
|
+
* @return {Array<string>|null}
|
|
4584
|
+
*/
|
|
4585
|
+
pickedTabIds() {
|
|
4586
|
+
if (!this.tabsFrom || this.editingBody || !this.widgetVisibilityData) {
|
|
4587
|
+
return null
|
|
4588
|
+
}
|
|
4589
|
+
const ids = readVisibleWhenPath(this.widgetVisibilityData, this.tabsFrom)
|
|
4590
|
+
return Array.isArray(ids) && ids.length > 0 ? ids.map((id) => String(id)) : null
|
|
4591
|
+
},
|
|
4592
|
+
|
|
4524
4593
|
/**
|
|
4525
4594
|
* Whether the body renders as an adjustable widget grid (vs. the
|
|
4526
4595
|
* hand-authored default slot). True for explicit grid pages and for the
|
|
@@ -4939,6 +5008,33 @@ export default {
|
|
|
4939
5008
|
},
|
|
4940
5009
|
|
|
4941
5010
|
methods: {
|
|
5011
|
+
/**
|
|
5012
|
+
* The widget definitions with each `tabs` widget's tabs narrowed and
|
|
5013
|
+
* ordered by `pickedTabIds`; the definitions as given without a pick.
|
|
5014
|
+
* A new definition is returned for a changed widget; the declared one
|
|
5015
|
+
* is never mutated.
|
|
5016
|
+
*
|
|
5017
|
+
* @spec openspec/changes/detail-tabs-from/specs/detail-page/spec.md#requirement-a-record-can-pick-its-tabs-and-their-order
|
|
5018
|
+
* @param {Array<object>} widgets The widget definitions.
|
|
5019
|
+
* @return {Array<object>}
|
|
5020
|
+
*/
|
|
5021
|
+
pickTabs(widgets) {
|
|
5022
|
+
const ids = this.pickedTabIds
|
|
5023
|
+
if (!ids || !Array.isArray(widgets)) {
|
|
5024
|
+
return widgets
|
|
5025
|
+
}
|
|
5026
|
+
const idOf = (tab) => String(typeof tab === 'string' ? tab : (tab && (tab.id ?? tab.widgetId)) ?? '')
|
|
5027
|
+
return widgets.map((widget) => {
|
|
5028
|
+
if (!widget || widget.type !== 'tabs' || !Array.isArray(widget.content?.tabs)) {
|
|
5029
|
+
return widget
|
|
5030
|
+
}
|
|
5031
|
+
const tabs = ids
|
|
5032
|
+
.map((id) => widget.content.tabs.find((tab) => idOf(tab) === id))
|
|
5033
|
+
.filter(Boolean)
|
|
5034
|
+
return tabs.length > 0 ? { ...widget, content: { ...widget.content, tabs } } : widget
|
|
5035
|
+
})
|
|
5036
|
+
},
|
|
5037
|
+
|
|
4942
5038
|
/**
|
|
4943
5039
|
* The tag after an admin-only entry in the board look ("beheerder",
|
|
4944
5040
|
* DqZaakMeer), or null for any other entry or look. It is drawn by
|
|
@@ -460,7 +460,7 @@ export default {
|
|
|
460
460
|
* @return {object}
|
|
461
461
|
*/
|
|
462
462
|
boardOptions() {
|
|
463
|
-
const keys = ['layout', 'tabs', 'filter', 'statusLabels', 'next', 'issueLabels', 'subtitle', 'notice', 'noticeLink', 'summaries', 'documentationButton', 'suggestButton']
|
|
463
|
+
const keys = ['layout', 'tabs', 'filter', 'statusLabels', 'next', 'issueLabels', 'subtitle', 'notice', 'noticeLink', 'summaries', 'documentationButton', 'suggestButton', 'actionsMenu']
|
|
464
464
|
const options = {}
|
|
465
465
|
for (const key of keys) {
|
|
466
466
|
if (this.board && this.board[key] !== undefined && this.board[key] !== null) {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
{{ t('nextcloud-vue', 'Suggest feature') }}
|
|
37
37
|
</NcButton>
|
|
38
38
|
<NcActions
|
|
39
|
-
v-if="!tabs"
|
|
39
|
+
v-if="!tabs && actionsMenu"
|
|
40
40
|
:menuName="t('nextcloud-vue', 'Actions')"
|
|
41
41
|
:forceName="true"
|
|
42
42
|
data-testid="cn-features-board-actions">
|
|
@@ -85,6 +85,7 @@
|
|
|
85
85
|
</button>
|
|
86
86
|
</div>
|
|
87
87
|
<NcActions
|
|
88
|
+
v-if="actionsMenu"
|
|
88
89
|
:menuName="t('nextcloud-vue', 'Actions')"
|
|
89
90
|
:forceName="true"
|
|
90
91
|
class="cn-features-board__tab-actions"
|
|
@@ -375,6 +376,8 @@ export default {
|
|
|
375
376
|
|
|
376
377
|
/** Show the Features and Roadmap folder tabs. */
|
|
377
378
|
tabs: { type: Boolean, default: true },
|
|
379
|
+
/** Show the Actions menu (suggest, buildiq, AI skills, support), in the header or the tab row; false draws none. */
|
|
380
|
+
actionsMenu: { type: Boolean, default: true },
|
|
378
381
|
/** `chips`: pill buttons with a count. `segmented`: a segmented control without counts. */
|
|
379
382
|
filter: {
|
|
380
383
|
type: String,
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
<NcButton v-if="showRun"
|
|
37
37
|
:disabled="store.running || !store.flow.id"
|
|
38
38
|
data-testid="flow-board-run"
|
|
39
|
-
@click="
|
|
39
|
+
@click="onRun">
|
|
40
40
|
{{ t('nextcloud-vue', 'Run') }}
|
|
41
41
|
</NcButton>
|
|
42
42
|
<NcButton v-if="testSubjectReady"
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
:key="group.app"
|
|
110
110
|
class="cn-flow-board__palette-group">
|
|
111
111
|
<h4 class="cn-flow-board__palette-app">
|
|
112
|
-
{{ group.
|
|
112
|
+
{{ group.name }}
|
|
113
113
|
</h4>
|
|
114
114
|
<ul class="cn-flow-board__palette-list">
|
|
115
115
|
<li v-for="entry in group.entries" :key="entry.id">
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
:toolbarActions="false"
|
|
136
136
|
:addStep="!showPalette"
|
|
137
137
|
@save="$emit('save')"
|
|
138
|
-
@run="
|
|
138
|
+
@run="onRun" />
|
|
139
139
|
<div v-if="store.inRunView"
|
|
140
140
|
class="cn-flow-board__legend"
|
|
141
141
|
data-testid="flow-board-legend">
|
|
@@ -183,6 +183,15 @@
|
|
|
183
183
|
<h3 class="cn-flow-board__card-title" data-testid="flow-board-step-name">
|
|
184
184
|
{{ stepName }}
|
|
185
185
|
</h3>
|
|
186
|
+
<dl v-if="stepSettings.length > 0" class="cn-flow-board__settings">
|
|
187
|
+
<div v-for="setting in stepSettings"
|
|
188
|
+
:key="setting.key"
|
|
189
|
+
class="cn-flow-board__setting"
|
|
190
|
+
data-testid="flow-board-step-setting">
|
|
191
|
+
<dt>{{ setting.label }}</dt>
|
|
192
|
+
<dd>{{ setting.value }}</dd>
|
|
193
|
+
</div>
|
|
194
|
+
</dl>
|
|
186
195
|
<div class="cn-flow-board__step-actions">
|
|
187
196
|
<NcButton data-testid="flow-board-edit-step" @click="store.editingNodeId = store.selectedNodeId">
|
|
188
197
|
{{ t('nextcloud-vue', 'Edit step') }}
|
|
@@ -212,7 +221,23 @@
|
|
|
212
221
|
</NcButton>
|
|
213
222
|
</div>
|
|
214
223
|
</template>
|
|
215
|
-
<
|
|
224
|
+
<template v-else-if="showRuns">
|
|
225
|
+
<NcButton variant="tertiary"
|
|
226
|
+
class="cn-flow-board__runs-back"
|
|
227
|
+
data-testid="flow-board-hide-runs"
|
|
228
|
+
@click="showRuns = false">
|
|
229
|
+
{{ t('nextcloud-vue', 'Back to the step settings') }}
|
|
230
|
+
</NcButton>
|
|
231
|
+
<CnFlowSidebar embedded />
|
|
232
|
+
</template>
|
|
233
|
+
<div v-else class="cn-flow-board__inspector-empty" data-testid="flow-board-inspector-empty">
|
|
234
|
+
<p>{{ t('nextcloud-vue', 'Select a step on the canvas to see its settings.') }}</p>
|
|
235
|
+
<NcButton variant="secondary"
|
|
236
|
+
data-testid="flow-board-show-runs"
|
|
237
|
+
@click="showRuns = true">
|
|
238
|
+
{{ t('nextcloud-vue', 'Show runs') }}
|
|
239
|
+
</NcButton>
|
|
240
|
+
</div>
|
|
216
241
|
</aside>
|
|
217
242
|
</div>
|
|
218
243
|
</div>
|
|
@@ -232,6 +257,7 @@ import CnResourceSelect from '../CnResourceSelect/CnResourceSelect.vue'
|
|
|
232
257
|
import { FLOW_RUN_ACTIVE_STATUSES, useFlowStore } from '../../composables/useFlowStore.js'
|
|
233
258
|
import { formatRelativeDate } from '../../utils/boardDate.js'
|
|
234
259
|
import { flowOutcomeLevels, flowRunDurationMs, flowRunLogLines, flowRunName, formatFlowDuration } from '../../utils/flowRunLog.js'
|
|
260
|
+
import { appDisplayNames } from '../../utils/nextcloudApps.js'
|
|
235
261
|
import { CnStatusBadge } from '../CnStatusBadge/index.js'
|
|
236
262
|
|
|
237
263
|
/**
|
|
@@ -278,7 +304,7 @@ export default {
|
|
|
278
304
|
},
|
|
279
305
|
|
|
280
306
|
data() {
|
|
281
|
-
return { runTab: 'step', testOpen: false, testRecord: null }
|
|
307
|
+
return { runTab: 'step', testOpen: false, testRecord: null, appNames: {}, showRuns: false }
|
|
282
308
|
},
|
|
283
309
|
|
|
284
310
|
computed: {
|
|
@@ -414,17 +440,25 @@ export default {
|
|
|
414
440
|
return { tone: 'success', text: this.t('nextcloud-vue', 'The flow is valid.') }
|
|
415
441
|
},
|
|
416
442
|
|
|
417
|
-
/**
|
|
443
|
+
/**
|
|
444
|
+
* The palette grouped by owning app, each group named by the app's
|
|
445
|
+
* display name (its id when Nextcloud names none), the app that owns
|
|
446
|
+
* this flow first.
|
|
447
|
+
*
|
|
448
|
+
* @return {Array<{app: string, name: string, entries: Array<object>}>} The groups.
|
|
449
|
+
*/
|
|
418
450
|
paletteGroups() {
|
|
419
451
|
const groups = {}
|
|
420
452
|
;(this.store.nodeCatalog || []).forEach((entry) => {
|
|
421
453
|
const app = String(entry?.app || String(entry?.id || '').split('.')[0] || '')
|
|
422
454
|
if (!groups[app]) {
|
|
423
|
-
groups[app] = { app, entries: [] }
|
|
455
|
+
groups[app] = { app, name: this.appNames[app] || app, entries: [] }
|
|
424
456
|
}
|
|
425
457
|
groups[app].entries.push(entry)
|
|
426
458
|
})
|
|
427
|
-
|
|
459
|
+
const list = Object.values(groups)
|
|
460
|
+
const host = list.findIndex((group) => group.app === this.app)
|
|
461
|
+
return host > 0 ? [list[host], ...list.slice(0, host), ...list.slice(host + 1)] : list
|
|
428
462
|
},
|
|
429
463
|
|
|
430
464
|
/** @return {object|null} The run on screen. */
|
|
@@ -477,6 +511,37 @@ export default {
|
|
|
477
511
|
return entry ? (entry.displayName || entry.id) : String(node?.type || '')
|
|
478
512
|
},
|
|
479
513
|
|
|
514
|
+
/**
|
|
515
|
+
* The selected step's settings as its owner declares them in the
|
|
516
|
+
* catalogue's `configForm`: label and value, a select's option label,
|
|
517
|
+
* Yes or No for a switch. Unset settings are left out.
|
|
518
|
+
*
|
|
519
|
+
* @return {Array<{key: string, label: string, value: string}>} The settings.
|
|
520
|
+
*/
|
|
521
|
+
stepSettings() {
|
|
522
|
+
const node = this.store.selectedNode
|
|
523
|
+
const entry = node ? this.store.catalogEntry(node.type) : null
|
|
524
|
+
const config = (node && node.config) || {}
|
|
525
|
+
const form = (entry && Array.isArray(entry.configForm)) ? entry.configForm : []
|
|
526
|
+
return form
|
|
527
|
+
.filter((field) => field && field.key && config[field.key] !== undefined && config[field.key] !== null && config[field.key] !== '')
|
|
528
|
+
.map((field) => {
|
|
529
|
+
const raw = config[field.key]
|
|
530
|
+
const option = Array.isArray(field.options) ? field.options.find((o) => o && o.value === raw) : null
|
|
531
|
+
let value
|
|
532
|
+
if (option) {
|
|
533
|
+
value = String(option.label ?? option.value)
|
|
534
|
+
} else if (typeof raw === 'boolean') {
|
|
535
|
+
value = raw ? this.t('nextcloud-vue', 'Yes') : this.t('nextcloud-vue', 'No')
|
|
536
|
+
} else if (typeof raw === 'object') {
|
|
537
|
+
value = JSON.stringify(raw)
|
|
538
|
+
} else {
|
|
539
|
+
value = String(raw)
|
|
540
|
+
}
|
|
541
|
+
return { key: field.key, label: field.label || field.key, value }
|
|
542
|
+
})
|
|
543
|
+
},
|
|
544
|
+
|
|
480
545
|
/** @return {string} The selected step's name. */
|
|
481
546
|
stepName() {
|
|
482
547
|
const node = this.store.selectedNode
|
|
@@ -507,7 +572,36 @@ export default {
|
|
|
507
572
|
},
|
|
508
573
|
},
|
|
509
574
|
|
|
575
|
+
watch: {
|
|
576
|
+
// A selected step takes the panel back from the run history.
|
|
577
|
+
'store.selectedNodeId': function(id) {
|
|
578
|
+
if (id) {
|
|
579
|
+
this.showRuns = false
|
|
580
|
+
}
|
|
581
|
+
},
|
|
582
|
+
},
|
|
583
|
+
|
|
584
|
+
async created() {
|
|
585
|
+
// The palette names its groups by app display name; only the column
|
|
586
|
+
// palette draws them, so only it reads the names.
|
|
587
|
+
if (this.palette !== 'column') {
|
|
588
|
+
return
|
|
589
|
+
}
|
|
590
|
+
const { default: axios } = await import('@nextcloud/axios')
|
|
591
|
+
this.appNames = await appDisplayNames(axios)
|
|
592
|
+
},
|
|
593
|
+
|
|
510
594
|
methods: {
|
|
595
|
+
/**
|
|
596
|
+
* Run the flow, with the run history in the panel to follow it.
|
|
597
|
+
*
|
|
598
|
+
* @return {void}
|
|
599
|
+
*/
|
|
600
|
+
onRun() {
|
|
601
|
+
this.showRuns = true
|
|
602
|
+
this.$emit('run')
|
|
603
|
+
},
|
|
604
|
+
|
|
511
605
|
/**
|
|
512
606
|
* Run the saved flow once with the picked record as its subject, then
|
|
513
607
|
* close the dialog; the run shows on the canvas as any run does.
|
|
@@ -822,6 +916,36 @@ export default {
|
|
|
822
916
|
text-align: center;
|
|
823
917
|
}
|
|
824
918
|
|
|
919
|
+
.cn-flow-board__settings {
|
|
920
|
+
display: flex;
|
|
921
|
+
flex-direction: column;
|
|
922
|
+
gap: 10px;
|
|
923
|
+
margin: 0;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
.cn-flow-board__setting dt {
|
|
927
|
+
font-size: 13px;
|
|
928
|
+
color: var(--color-text-maxcontrast);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
.cn-flow-board__setting dd {
|
|
932
|
+
margin: 2px 0 0;
|
|
933
|
+
font-weight: 600;
|
|
934
|
+
overflow-wrap: anywhere;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
.cn-flow-board__inspector-empty {
|
|
938
|
+
display: flex;
|
|
939
|
+
flex-direction: column;
|
|
940
|
+
align-items: flex-start;
|
|
941
|
+
gap: 12px;
|
|
942
|
+
color: var(--color-text-maxcontrast);
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
.cn-flow-board__inspector-empty p {
|
|
946
|
+
margin: 0;
|
|
947
|
+
}
|
|
948
|
+
|
|
825
949
|
.cn-flow-board__step-actions,
|
|
826
950
|
.cn-flow-board__step-footer {
|
|
827
951
|
display: flex;
|
|
@@ -389,6 +389,8 @@ export default {
|
|
|
389
389
|
| `customComponents` | Object | `null` | Custom-component / handler registry. When set, takes precedence over the injected `cnCustomComponents` from CnAppRoot. Used to resolve `actions[].handler` registry names declared in the manifest (manifest-actions-dispatch). Named handlers resolve out of the v2 `registry` (a `kind: "handler"` entry) FIRST and fall back to this map. |
|
|
390
390
|
| `showViewToggle` | Boolean | `true` | Whether to show the Cards/Table view toggle |
|
|
391
391
|
| `inlineSearch` | Boolean | `false` | Show an inline search field in the actions bar (in addition to / instead of the sidebar search). Fed from the manifest as `pages[].config.inlineSearch`. The field takes the place of the "Showing X of Y" counter unless `showCountWithSearch` is set. |
|
|
392
|
+
| `search` | Boolean | `true` | `false` draws no inline search in the actions bar, also in the board look, which otherwise draws one on every index page (manifest: `config.search`). Wins over `inlineSearch`. |
|
|
393
|
+
| `appConfig` | Object | `{}` | The app config `@config.<key>` tokens resolve against (manifest: `config.appConfig`), as on the dashboard and detail pages, merged over a config an ancestor provides on `cnAppConfig`. A quick filter's `filter` and its `label` / `activeLabel` take the token: `"Residence @config.municipality"` reads "Residence Zuiddrecht" (board DqContacten); the label is translated first, and a key the config does not hold leaves the token as written. |
|
|
392
394
|
| `showCountWithSearch` | Boolean | `false` | Keep the "Showing X of Y" counter visible beside the inline search field, after the search and any `#after-search` controls (only relevant with `inlineSearch`, which otherwise takes the counter's place). Fed from the manifest as `pages[].config.showCountWithSearch`. |
|
|
393
395
|
| `searchInFiles` | Boolean | `false` | "Also search inside files" switch beside the search box (manifest `config.searchInFiles`). On, a search with a term sends `_content_search=true`; rows found through a file show "Found in {file}" (`@self.matchedFile`). State kept in the route as `contentSearch=1`. Emits `content-search`. |
|
|
394
396
|
| `searchPlaceholder` | String | `''` | Placeholder for the inline search field (manifest `config.searchPlaceholder`). |
|
|
@@ -878,8 +880,9 @@ The list view (`view-mode="list"`) and standalone sort dropdown add these props:
|
|
|
878
880
|
| `listConfig` | Object | `{}` | Field mapping for the default list rows (`CnObjectRow`). |
|
|
879
881
|
| `listComponent` | String | `''` | Custom row component, resolved against the v2 `registry` (any kind carrying a `component`) and then the legacy `customComponents` map. |
|
|
880
882
|
| `showSortSelect` | Boolean | `false` | Show a standalone sort dropdown in the actions bar. |
|
|
881
|
-
| `sortSelectOptions` | Array | `[]` | Options `{ value, label }` for the sort dropdown. |
|
|
882
|
-
| `sortSelectValue` | String | `''` | Selected sort dropdown value
|
|
883
|
+
| `sortSelectOptions` | Array | `[]` | Options `{ value, label, order? }` for the sort dropdown. On a self-fetch page a choice orders the list as a header click does (`_order`, kept in the address): by the option's `order`, else its `value` read as an order (`"-createdAt"`, `"priority:desc,title"`). |
|
|
884
|
+
| `sortSelectValue` | String | `''` | Selected sort dropdown value. Empty lets a self-fetch page show the option matching its current order, so a header click that matches an option shows it. |
|
|
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. |
|
|
883
886
|
|
|
884
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.
|
|
885
888
|
|