@conduction/nextcloud-vue 2.100.0 → 2.102.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 +22 -0
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +8 -6
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +29 -4
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js +9 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue.js +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js +22 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js +26 -16
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +70 -6
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +105 -74
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue.js +9 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue2.js +139 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue3.js +76 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +160 -2
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +206 -94
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/filesReview.js +61 -0
- package/dist/esm/components/CnFilesBrowser/filesReview.js.map +1 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue.js +9 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue2.js +279 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue3.js +122 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnGroupedCardsWidget/index.js +29 -0
- package/dist/esm/components/CnGroupedCardsWidget/index.js.map +1 -0
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +320 -74
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +323 -213
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useNamedSource.js +30 -3
- package/dist/esm/components/CnIndexPage/useNamedSource.js.map +1 -1
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue.js +1 -1
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue2.js +15 -0
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnMenuWidget/CnMenuWidget.vue.js +1 -1
- package/dist/esm/components/CnMenuWidget/CnMenuWidget.vue2.js +25 -1
- package/dist/esm/components/CnMenuWidget/CnMenuWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnMenuWidget/CnMenuWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +14 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +14 -6
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue.js +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +10 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +6 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue.js +1 -1
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js +91 -4
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js.map +1 -1
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js +63 -38
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js.map +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue.js +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js +106 -4
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js.map +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js +70 -25
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js.map +1 -1
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue.js +9 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue.js.map +1 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue2.js +175 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue3.js +77 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue.js +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +35 -2
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +4 -0
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +2 -23
- 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 +176 -20
- package/dist/esm/composables/indexSources.js.map +1 -1
- package/dist/esm/composables/useEndpointSource.js +28 -6
- package/dist/esm/composables/useEndpointSource.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 +41 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +39 -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 +939 -376
- package/dist/esm/utils/builtInFormatters.js +24 -4
- package/dist/esm/utils/builtInFormatters.js.map +1 -1
- package/dist/esm/utils/languageMapText.js +50 -0
- package/dist/esm/utils/languageMapText.js.map +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js +3 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/mapList.js +71 -0
- package/dist/esm/utils/mapList.js.map +1 -0
- package/dist/esm/utils/rowClassRules.js +43 -0
- package/dist/esm/utils/rowClassRules.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 +19 -2
- package/dist/esm/utils/visibleWhen.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +9681 -7136
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +939 -376
- package/l10n/en.json +41 -1
- package/l10n/nl.json +39 -1
- package/package.json +1 -1
- package/src/components/CnActionsBar/CnActionsBar.md +1 -0
- package/src/components/CnActionsBar/CnActionsBar.vue +31 -4
- package/src/components/CnChartWidget/CnChartWidget.md +3 -2
- package/src/components/CnChartWidget/CnChartWidget.vue +42 -4
- package/src/components/CnChoiceCards/CnChoiceCards.md +39 -0
- package/src/components/CnChoiceCards/CnChoiceCards.vue +93 -16
- package/src/components/CnDashboardPage/CnDashboardPage.vue +110 -21
- package/src/components/CnExportsWidget/CnExportsWidget.vue +233 -0
- package/src/components/CnExportsWidget/index.js +7 -0
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +324 -0
- package/src/components/CnFilesBrowser/filesReview.js +57 -0
- package/src/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue +433 -0
- package/src/components/CnGroupedCardsWidget/index.js +28 -0
- package/src/components/CnIndexPage/CnIndexPage.md +5 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +313 -9
- package/src/components/CnIndexPage/useNamedSource.js +30 -3
- package/src/components/CnMapWidget/CnMapWidget.vue +37 -0
- package/src/components/CnMenuWidget/CnMenuWidget.vue +25 -1
- package/src/components/CnObjectListWidget/CnObjectListWidget.vue +29 -1
- package/src/components/CnObjectSidebar/CnFilesTab.vue +15 -0
- package/src/components/CnOrderedListField/CnOrderedListField.vue +151 -5
- package/src/components/CnQuickFilterBar/CnQuickFilterBar.md +1 -0
- package/src/components/CnQuickFilterBar/CnQuickFilterBar.vue +159 -5
- package/src/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue +272 -0
- package/src/components/CnSavedViewAlertWidget/index.js +7 -0
- package/src/components/CnSetupWizard/CnSetupWizard.vue +35 -2
- package/src/components/CnWidgetGrid/builtInWidgets.js +4 -0
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +2 -23
- package/src/components/index.js +3 -0
- package/src/composables/indexSources.js +175 -19
- package/src/composables/useEndpointSource.js +28 -6
- package/src/css/index-page.css +117 -0
- package/src/css/look-board-index.css +10 -0
- package/src/css/look-board.css +44 -0
- package/src/index.js +1 -0
- package/src/schemas/app-manifest-v2.schema.json +85 -3
- package/src/utils/builtInFormatters.js +24 -4
- package/src/utils/languageMapText.js +46 -0
- package/src/utils/libraryWidgetKeys.js +3 -0
- package/src/utils/mapList.js +67 -0
- package/src/utils/rowClassRules.js +39 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
- package/src/utils/visibleWhen.js +19 -2
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
- SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
3
|
+
- SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
-->
|
|
5
|
+
<template>
|
|
6
|
+
<div class="cn-saved-view-alert" data-testid="cn-saved-view-alert">
|
|
7
|
+
<p v-if="!view" class="cn-saved-view-alert__empty" data-testid="cn-saved-view-alert-empty">
|
|
8
|
+
{{ emptyText }}
|
|
9
|
+
</p>
|
|
10
|
+
<template v-else>
|
|
11
|
+
<dl class="cn-saved-view-alert__facts">
|
|
12
|
+
<dt>{{ t('nextcloud-vue', 'Name') }}</dt>
|
|
13
|
+
<dd data-testid="cn-saved-view-alert-name">
|
|
14
|
+
{{ view.name }}
|
|
15
|
+
</dd>
|
|
16
|
+
<template v-if="countText">
|
|
17
|
+
<dt>{{ t('nextcloud-vue', 'Now') }}</dt>
|
|
18
|
+
<dd data-testid="cn-saved-view-alert-count">
|
|
19
|
+
{{ countText }}
|
|
20
|
+
</dd>
|
|
21
|
+
</template>
|
|
22
|
+
</dl>
|
|
23
|
+
<NcCheckboxRadioSwitch
|
|
24
|
+
type="switch"
|
|
25
|
+
:modelValue="enabled"
|
|
26
|
+
:disabled="saving || !canEdit"
|
|
27
|
+
data-testid="cn-saved-view-alert-switch"
|
|
28
|
+
@update:modelValue="onToggle">
|
|
29
|
+
<span class="cn-saved-view-alert__switch-text">
|
|
30
|
+
<span>{{ t('nextcloud-vue', 'Tell me above a number') }}</span>
|
|
31
|
+
<span class="cn-saved-view-alert__hint">{{ hintText }}</span>
|
|
32
|
+
</span>
|
|
33
|
+
</NcCheckboxRadioSwitch>
|
|
34
|
+
<NcTextField v-if="enabled"
|
|
35
|
+
:modelValue="String(threshold)"
|
|
36
|
+
type="number"
|
|
37
|
+
min="0"
|
|
38
|
+
:label="t('nextcloud-vue', 'Threshold')"
|
|
39
|
+
:disabled="saving || !canEdit"
|
|
40
|
+
data-testid="cn-saved-view-alert-threshold"
|
|
41
|
+
@update:modelValue="onThreshold" />
|
|
42
|
+
<p v-if="error"
|
|
43
|
+
class="cn-saved-view-alert__error"
|
|
44
|
+
role="alert"
|
|
45
|
+
data-testid="cn-saved-view-alert-error">
|
|
46
|
+
{{ error }}
|
|
47
|
+
</p>
|
|
48
|
+
</template>
|
|
49
|
+
</div>
|
|
50
|
+
</template>
|
|
51
|
+
|
|
52
|
+
<script>
|
|
53
|
+
import { getCurrentUser } from '@nextcloud/auth'
|
|
54
|
+
import { translatePlural as n, translate as t } from '@nextcloud/l10n'
|
|
55
|
+
import { NcCheckboxRadioSwitch, NcTextField } from '@nextcloud/vue'
|
|
56
|
+
import { useSavedViewsApi } from '../../composables/useSavedViewsApi.js'
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* CnSavedViewAlertWidget — the saved view an index page has applied, with its
|
|
60
|
+
* count alert (DqZoekresultaten "Opgeslagen zoekopdracht"): its name, how many
|
|
61
|
+
* rows it holds now, and a switch that asks OpenRegister to tell the reader
|
|
62
|
+
* when the count reaches a threshold.
|
|
63
|
+
*
|
|
64
|
+
* The alert is the view's own `alert` (`{ operator: 'gte', threshold,
|
|
65
|
+
* recipients }`), saved with a PATCH on the view; OpenRegister evaluates it on
|
|
66
|
+
* its sweep and fires on the crossing, not on the state. Switching it off
|
|
67
|
+
* clears it. The widget reads the page through the `cnIndexList` CnIndexPage
|
|
68
|
+
* provides, so it belongs in an index page's `sidePanel`
|
|
69
|
+
* (`type: "saved-view-alert"`).
|
|
70
|
+
*
|
|
71
|
+
* Example (manifest):
|
|
72
|
+
* ```json
|
|
73
|
+
* { "id": "alert", "type": "saved-view-alert", "title": "Saved search", "content": { "noun": { "one": "case", "other": "cases" } } }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export default {
|
|
77
|
+
name: 'CnSavedViewAlertWidget',
|
|
78
|
+
|
|
79
|
+
components: { NcCheckboxRadioSwitch, NcTextField },
|
|
80
|
+
|
|
81
|
+
inject: {
|
|
82
|
+
/** The index page's list: its applied saved view and its total. */
|
|
83
|
+
cnIndexList: { default: null },
|
|
84
|
+
/** Host translate function provided by CnAppRoot. */
|
|
85
|
+
cnTranslate: { default: () => (key) => key },
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
props: {
|
|
89
|
+
/**
|
|
90
|
+
* The widget content: `{ noun?: { one, other }, emptyText? }`. `noun`
|
|
91
|
+
* names what is counted ("9 zaken"); `emptyText` shows while no saved
|
|
92
|
+
* view is applied. Both are translated with the app's catalogue.
|
|
93
|
+
*/
|
|
94
|
+
content: {
|
|
95
|
+
type: Object,
|
|
96
|
+
default: () => ({}),
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
data() {
|
|
101
|
+
return { saving: false, error: '', draft: null }
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
computed: {
|
|
105
|
+
/** @return {object|null} The applied saved view, or null. */
|
|
106
|
+
view() {
|
|
107
|
+
return (this.cnIndexList && this.cnIndexList.appliedView) || null
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/** @return {boolean} Whether the view carries an alert. */
|
|
111
|
+
enabled() {
|
|
112
|
+
const alert = this.view && this.view.alert
|
|
113
|
+
return Boolean(alert && typeof alert === 'object' && Number.isFinite(Number(alert.threshold)))
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
/** @return {number} The threshold being edited, else the view's, else 10. */
|
|
117
|
+
threshold() {
|
|
118
|
+
if (this.draft !== null) {
|
|
119
|
+
return this.draft
|
|
120
|
+
}
|
|
121
|
+
const value = this.enabled ? Number(this.view.alert.threshold) : 10
|
|
122
|
+
return Number.isFinite(value) ? value : 10
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
/** @return {boolean} Whether the reader may change the view: its owner, or when the view says nothing. */
|
|
126
|
+
canEdit() {
|
|
127
|
+
const owner = this.view && this.view.owner
|
|
128
|
+
if (!owner) {
|
|
129
|
+
return true
|
|
130
|
+
}
|
|
131
|
+
const user = getCurrentUser()
|
|
132
|
+
return Boolean(user && user.uid === owner)
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
/** @return {string} "9 zaken", or '' while the total is unknown. */
|
|
136
|
+
countText() {
|
|
137
|
+
const total = this.cnIndexList ? this.cnIndexList.total : undefined
|
|
138
|
+
if (typeof total !== 'number') {
|
|
139
|
+
return ''
|
|
140
|
+
}
|
|
141
|
+
const noun = this.content && this.content.noun
|
|
142
|
+
if (noun && typeof noun === 'object' && noun.one && noun.other) {
|
|
143
|
+
return `${total} ${this.cnTranslate(total === 1 ? noun.one : noun.other)}`
|
|
144
|
+
}
|
|
145
|
+
return n('nextcloud-vue', '%n result', '%n results', total)
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
/** @return {string} The line under the switch. */
|
|
149
|
+
hintText() {
|
|
150
|
+
return t('nextcloud-vue', 'A message to you when there are {threshold} or more', { threshold: this.threshold })
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
/** @return {string} What shows while no saved view is applied. */
|
|
154
|
+
emptyText() {
|
|
155
|
+
const own = this.content && this.content.emptyText
|
|
156
|
+
return own ? this.cnTranslate(own) : t('nextcloud-vue', 'Save this search or open a saved one to set an alert on it.')
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
methods: {
|
|
161
|
+
t,
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Switch the alert on (at the shown threshold) or off.
|
|
165
|
+
*
|
|
166
|
+
* @param {boolean} on The new state.
|
|
167
|
+
* @return {Promise<void>}
|
|
168
|
+
*/
|
|
169
|
+
async onToggle(on) {
|
|
170
|
+
await this.save(on ? this.alertFor(this.threshold) : null)
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Save a new threshold, when the alert is on.
|
|
175
|
+
*
|
|
176
|
+
* @param {string} value The typed value.
|
|
177
|
+
* @return {Promise<void>}
|
|
178
|
+
*/
|
|
179
|
+
async onThreshold(value) {
|
|
180
|
+
const number = Math.max(0, Math.floor(Number(value)))
|
|
181
|
+
if (!Number.isFinite(number)) {
|
|
182
|
+
return
|
|
183
|
+
}
|
|
184
|
+
this.draft = number
|
|
185
|
+
await this.save(this.alertFor(number))
|
|
186
|
+
this.draft = null
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* The alert the view stores: reaching the threshold tells the reader.
|
|
191
|
+
*
|
|
192
|
+
* @param {number} threshold The threshold.
|
|
193
|
+
* @return {{operator: string, threshold: number, recipients: Array<string>}}
|
|
194
|
+
*/
|
|
195
|
+
alertFor(threshold) {
|
|
196
|
+
const user = getCurrentUser()
|
|
197
|
+
return { operator: 'gte', threshold, recipients: user && user.uid ? [user.uid] : [] }
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* PATCH the view's alert and hand the saved view back to the page.
|
|
202
|
+
*
|
|
203
|
+
* @param {object|null} alert The alert, or null to clear it.
|
|
204
|
+
* @return {Promise<void>}
|
|
205
|
+
*/
|
|
206
|
+
async save(alert) {
|
|
207
|
+
if (!this.view) {
|
|
208
|
+
return
|
|
209
|
+
}
|
|
210
|
+
this.saving = true
|
|
211
|
+
this.error = ''
|
|
212
|
+
try {
|
|
213
|
+
const saved = await useSavedViewsApi().patchView(this.view.uuid || this.view.id, { alert })
|
|
214
|
+
if (saved && this.cnIndexList && typeof this.cnIndexList.replaceSavedView === 'function') {
|
|
215
|
+
this.cnIndexList.replaceSavedView(saved)
|
|
216
|
+
}
|
|
217
|
+
} catch (error) {
|
|
218
|
+
this.error = (error && error.response && error.response.data && error.response.data.error) || t('nextcloud-vue', 'The alert could not be saved.')
|
|
219
|
+
} finally {
|
|
220
|
+
this.saving = false
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
}
|
|
225
|
+
</script>
|
|
226
|
+
|
|
227
|
+
<style scoped>
|
|
228
|
+
.cn-saved-view-alert {
|
|
229
|
+
display: flex;
|
|
230
|
+
flex-direction: column;
|
|
231
|
+
gap: 12px;
|
|
232
|
+
font-size: 14px;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.cn-saved-view-alert__facts {
|
|
236
|
+
display: grid;
|
|
237
|
+
grid-template-columns: max-content 1fr;
|
|
238
|
+
gap: 6px 16px;
|
|
239
|
+
margin: 0;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.cn-saved-view-alert__facts dt {
|
|
243
|
+
color: var(--color-text-maxcontrast);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.cn-saved-view-alert__facts dd {
|
|
247
|
+
margin: 0;
|
|
248
|
+
font-weight: 500;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.cn-saved-view-alert__switch-text {
|
|
252
|
+
display: flex;
|
|
253
|
+
flex-direction: column;
|
|
254
|
+
gap: 2px;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.cn-saved-view-alert__hint,
|
|
258
|
+
.cn-saved-view-alert__empty {
|
|
259
|
+
color: var(--color-text-maxcontrast);
|
|
260
|
+
font-size: 13px;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.cn-saved-view-alert__empty,
|
|
264
|
+
.cn-saved-view-alert__error {
|
|
265
|
+
margin: 0;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.cn-saved-view-alert__error {
|
|
269
|
+
color: var(--color-error-text, var(--color-error));
|
|
270
|
+
font-size: 13px;
|
|
271
|
+
}
|
|
272
|
+
</style>
|
|
@@ -438,7 +438,7 @@ export default {
|
|
|
438
438
|
*/
|
|
439
439
|
setup(props) {
|
|
440
440
|
const { isBoard } = useLook()
|
|
441
|
-
const wantsSource = (props.steps || []).some((s) => s && s.optionsSource)
|
|
441
|
+
const wantsSource = (props.steps || []).some((s) => s && (s.optionsSource || s.visibleWhen))
|
|
442
442
|
if (!wantsSource) {
|
|
443
443
|
return { isBoard }
|
|
444
444
|
}
|
|
@@ -506,7 +506,7 @@ export default {
|
|
|
506
506
|
|
|
507
507
|
setupSteps() {
|
|
508
508
|
const skipped = new Set(this.skippedSteps.map((entry) => entry.step.id))
|
|
509
|
-
return this.declaredSteps.filter((s) => !skipped.has(s.id))
|
|
509
|
+
return this.declaredSteps.filter((s) => !skipped.has(s.id) && this.stepConditionHolds(s))
|
|
510
510
|
},
|
|
511
511
|
|
|
512
512
|
/**
|
|
@@ -869,6 +869,39 @@ export default {
|
|
|
869
869
|
})
|
|
870
870
|
},
|
|
871
871
|
|
|
872
|
+
/**
|
|
873
|
+
* Whether a step's `visibleWhen` holds: the value at that path in the
|
|
874
|
+
* setup status (`"flags.hasPayouts"`, dots walk into objects) is truthy,
|
|
875
|
+
* or equals `equals` when the step gives `{ path, equals }`. A step
|
|
876
|
+
* without `visibleWhen` always shows; one with it stays hidden until the
|
|
877
|
+
* status says so, also while the status loads (DqInstellen: the dwangsom
|
|
878
|
+
* step only when the app pays penalties).
|
|
879
|
+
*
|
|
880
|
+
* @param {object} step The step declaration.
|
|
881
|
+
* @return {boolean}
|
|
882
|
+
*/
|
|
883
|
+
stepConditionHolds(step) {
|
|
884
|
+
const when = step && step.visibleWhen
|
|
885
|
+
if (when === undefined || when === null || when === '') {
|
|
886
|
+
return true
|
|
887
|
+
}
|
|
888
|
+
const path = typeof when === 'string' ? when : when.path
|
|
889
|
+
if (typeof path !== 'string' || path === '') {
|
|
890
|
+
return true
|
|
891
|
+
}
|
|
892
|
+
let node = this.setupStatus
|
|
893
|
+
for (const key of path.split('.')) {
|
|
894
|
+
if (node === null || node === undefined || typeof node !== 'object') {
|
|
895
|
+
return false
|
|
896
|
+
}
|
|
897
|
+
node = node[key]
|
|
898
|
+
}
|
|
899
|
+
if (typeof when === 'object' && Object.hasOwn(when, 'equals')) {
|
|
900
|
+
return node === when.equals
|
|
901
|
+
}
|
|
902
|
+
return Boolean(node)
|
|
903
|
+
},
|
|
904
|
+
|
|
872
905
|
/**
|
|
873
906
|
* The option list a `choice` step declares `optionsSource` for, read
|
|
874
907
|
* from the setup status document the app already serves.
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import CnAuditTrailWidget from '../CnAuditTrailWidget/CnAuditTrailWidget.vue'
|
|
18
18
|
import CnBannerWidget from '../CnBannerWidget/CnBannerWidget.vue'
|
|
19
19
|
import CnDividerWidget from '../CnDividerWidget/CnDividerWidget.vue'
|
|
20
|
+
import CnExportsWidget from '../CnExportsWidget/CnExportsWidget.vue'
|
|
20
21
|
import CnHeaderWidget from '../CnHeaderWidget/CnHeaderWidget.vue'
|
|
21
22
|
import CnIntegrationWidget from '../CnIntegrationWidget/CnIntegrationWidget.vue'
|
|
22
23
|
import CnNavCardGrid from '../CnNavCardGrid/CnNavCardGrid.vue'
|
|
@@ -24,6 +25,7 @@ import CnObjectDataWidget from '../CnObjectDataWidget/CnObjectDataWidget.vue'
|
|
|
24
25
|
import CnObjectGeoWidget from '../CnObjectGeoWidget/CnObjectGeoWidget.vue'
|
|
25
26
|
import CnObjectMetadataWidget from '../CnObjectMetadataWidget/CnObjectMetadataWidget.vue'
|
|
26
27
|
import CnRelatedObjectsWidget from '../CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue'
|
|
28
|
+
import CnSavedViewAlertWidget from '../CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue'
|
|
27
29
|
import CnTextWidget from '../CnTextWidget/CnTextWidget.vue'
|
|
28
30
|
import CnTimelineWidget from '../CnTimelineWidget/CnTimelineWidget.vue'
|
|
29
31
|
import CnWidgetCardGrid from '../CnWidgetCardGrid/CnWidgetCardGrid.vue'
|
|
@@ -89,4 +91,6 @@ export const BUILT_IN_WIDGETS = {
|
|
|
89
91
|
header: CnHeaderWidget,
|
|
90
92
|
text: CnTextWidget,
|
|
91
93
|
divider: CnDividerWidget,
|
|
94
|
+
'saved-view-alert': CnSavedViewAlertWidget,
|
|
95
|
+
exports: CnExportsWidget,
|
|
92
96
|
}
|
|
@@ -75,6 +75,7 @@ import '../CnTasksWidget/index.js'
|
|
|
75
75
|
import '../CnSectionsWidget/index.js'
|
|
76
76
|
import '../CnFactsWidget/index.js'
|
|
77
77
|
import '../CnDeviceFramesWidget/index.js'
|
|
78
|
+
import '../CnGroupedCardsWidget/index.js'
|
|
78
79
|
import '../CnChecklistRunWidget/index.js'
|
|
79
80
|
import '../CnWorkingCalendarWidget/index.js'
|
|
80
81
|
import '../CnPartyActionsWidget/index.js'
|
|
@@ -88,8 +88,8 @@ import { dispatchAction, resolveObjectOpType } from '../../utils/actionsDispatch
|
|
|
88
88
|
import { resolveObjectTokenContext } from '../../utils/detailObjectContext.js'
|
|
89
89
|
import { pageFilter, pageSort } from '../../utils/pageControls.js'
|
|
90
90
|
import { dropOptionalUnresolved, hasUnresolvedTokens, resolveFilterTokens } from '../../utils/resolveFilterTokens.js'
|
|
91
|
+
import { compileRowClass } from '../../utils/rowClassRules.js'
|
|
91
92
|
import { fieldsFromSchema } from '../../utils/schema.js'
|
|
92
|
-
import { compareVisibleWhen, readVisibleWhenPath } from '../../utils/visibleWhen.js'
|
|
93
93
|
import { CnIcon } from '../CnIcon/index.js'
|
|
94
94
|
import { CnRowActions } from '../CnRowActions/index.js'
|
|
95
95
|
import { CnWidgetWrapper } from '../CnWidgetWrapper/index.js'
|
|
@@ -762,28 +762,7 @@ export default {
|
|
|
762
762
|
* @return {?(row: object) => string} The row-class function, or null.
|
|
763
763
|
*/
|
|
764
764
|
compiledRowClass() {
|
|
765
|
-
|
|
766
|
-
if (typeof rc === 'function') {
|
|
767
|
-
return rc
|
|
768
|
-
}
|
|
769
|
-
if (!Array.isArray(rc) || rc.length === 0) {
|
|
770
|
-
return null
|
|
771
|
-
}
|
|
772
|
-
const rules = rc
|
|
773
|
-
return (row) => {
|
|
774
|
-
const classes = []
|
|
775
|
-
for (const rule of rules) {
|
|
776
|
-
if (!rule || !rule.class) {
|
|
777
|
-
continue
|
|
778
|
-
}
|
|
779
|
-
const when = rule.when || {}
|
|
780
|
-
const actual = readVisibleWhenPath(row, when.field)
|
|
781
|
-
if (compareVisibleWhen(actual, when.op || 'eq', when.value)) {
|
|
782
|
-
classes.push(rule.class)
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
return classes.join(' ')
|
|
786
|
-
}
|
|
765
|
+
return compileRowClass(this.rowClass)
|
|
787
766
|
},
|
|
788
767
|
|
|
789
768
|
/**
|
package/src/components/index.js
CHANGED
|
@@ -30,6 +30,8 @@ export { CnDateAxisView } from './CnDateAxisView/index.js'
|
|
|
30
30
|
export { CnObjectRow } from './CnObjectRow/index.js'
|
|
31
31
|
export { CnObjectList } from './CnObjectList/index.js'
|
|
32
32
|
export { CnOrderedListField } from './CnOrderedListField/index.js'
|
|
33
|
+
export { CnExportsWidget } from './CnExportsWidget/index.js'
|
|
34
|
+
export { CnSavedViewAlertWidget } from './CnSavedViewAlertWidget/index.js'
|
|
33
35
|
export { CnObjectKanban } from './CnObjectKanban/index.js'
|
|
34
36
|
export { CnObjectCalendar } from './CnObjectCalendar/index.js'
|
|
35
37
|
export { CnFolderTree } from './CnFolderTree/index.js'
|
|
@@ -224,6 +226,7 @@ export { CnTasksWidgetForm } from './CnTasksWidgetForm/index.js'
|
|
|
224
226
|
export { CnSectionsWidget } from './CnSectionsWidget/index.js'
|
|
225
227
|
export { CnFactsWidget } from './CnFactsWidget/index.js'
|
|
226
228
|
export { CnDeviceFramesWidget } from './CnDeviceFramesWidget/index.js'
|
|
229
|
+
export { CnGroupedCardsWidget } from './CnGroupedCardsWidget/index.js'
|
|
227
230
|
export { CnChecklistRunWidget } from './CnChecklistRunWidget/index.js'
|
|
228
231
|
export { CnWorkingCalendarWidget } from './CnWorkingCalendarWidget/index.js'
|
|
229
232
|
export { CnPartyActionsWidget } from './CnPartyActionsWidget/index.js'
|