@conduction/nextcloud-vue 2.65.0 → 2.67.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 +19 -0
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +10 -3
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js +2 -2
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +99 -2
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +438 -383
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue2.js +9 -3
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue3.js +1 -1
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +4 -4
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +78 -21
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +129 -96
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnFkResolveCell/CnFkResolveCell.vue2.js +3 -1
- package/dist/esm/components/CnFkResolveCell/CnFkResolveCell.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +144 -4
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js +63 -7
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js +2 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +31 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +335 -313
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js +11 -0
- package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js.map +1 -1
- package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue3.js +2 -1
- package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue3.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +5 -11
- 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/composables/useDependencyCheck.js +44 -1
- package/dist/esm/composables/useDependencyCheck.js.map +1 -1
- package/dist/esm/composables/useListView.js +43 -1
- package/dist/esm/composables/useListView.js.map +1 -1
- package/dist/esm/composables/useSetupStatus.js +26 -3
- package/dist/esm/composables/useSetupStatus.js.map +1 -1
- package/dist/esm/l10n/en.json.js +7 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +7 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/mixins/pageViews.js +400 -0
- package/dist/esm/mixins/pageViews.js.map +1 -0
- package/dist/esm/nextcloud-vue.css +38 -2
- package/dist/esm/store/plugins/liveUpdates.js +19 -9
- package/dist/esm/store/plugins/liveUpdates.js.map +1 -1
- package/dist/esm/store/useObjectStore.js +20 -9
- package/dist/esm/store/useObjectStore.js.map +1 -1
- package/dist/esm/utils/actionsDispatcher.js +11 -2
- package/dist/esm/utils/actionsDispatcher.js.map +1 -1
- package/dist/esm/utils/columnFilters.js +27 -3
- package/dist/esm/utils/columnFilters.js.map +1 -1
- package/dist/esm/utils/schema.js +40 -2
- package/dist/esm/utils/schema.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +2377 -1247
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +38 -2
- package/l10n/en.json +7 -1
- package/l10n/nl.json +7 -1
- package/package.json +1 -1
- package/src/components/CnActionsBar/CnActionsBar.md +2 -1
- package/src/components/CnActionsBar/CnActionsBar.vue +25 -1
- package/src/components/CnAppNav/CnAppNav.vue +2 -2
- package/src/components/CnDashboardPage/CnDashboardPage.vue +165 -8
- package/src/components/CnDataTable/CnColumnFilterPopover.vue +11 -5
- package/src/components/CnDataTable/CnDataTable.md +1 -1
- package/src/components/CnDataTable/CnDataTable.vue +4 -4
- package/src/components/CnDetailPage/CnDetailPage.vue +94 -5
- package/src/components/CnFkResolveCell/CnFkResolveCell.vue +3 -1
- package/src/components/CnFormDialog/CnFormDialog.vue +144 -4
- package/src/components/CnHeaderWidget/CnHeaderWidget.vue +67 -8
- package/src/components/CnIndexPage/CnIndexPage.md +2 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +47 -1
- package/src/components/CnSegmentedControl/CnSegmentedControl.md +1 -1
- package/src/components/CnSegmentedControl/CnSegmentedControl.vue +12 -0
- package/src/components/CnSetupWizard/CnSetupWizard.vue +5 -11
- package/src/composables/useDependencyCheck.js +43 -0
- package/src/composables/useListView.js +43 -1
- package/src/composables/useSetupStatus.js +26 -3
- package/src/css/actions-bar.css +20 -2
- package/src/css/detail-page.css +5 -0
- package/src/mixins/pageViews.js +396 -0
- package/src/schemas/app-manifest-v2.schema.json +31 -3
- package/src/schemas/app-manifest.schema.json +1 -1
- package/src/store/plugins/liveUpdates.js +19 -9
- package/src/store/useObjectStore.js +19 -8
- package/src/utils/actionsDispatcher.js +11 -2
- package/src/utils/columnFilters.js +29 -2
- package/src/utils/schema.js +40 -2
- package/src/utils/validateManifestV2.compiled.js +2 -2
|
@@ -199,13 +199,12 @@
|
|
|
199
199
|
|
|
200
200
|
<script>
|
|
201
201
|
import { getCurrentUser } from '@nextcloud/auth'
|
|
202
|
-
import { loadState } from '@nextcloud/initial-state'
|
|
203
202
|
import { translate as t } from '@nextcloud/l10n'
|
|
204
203
|
import { NcButton, NcCheckboxRadioSwitch, NcLoadingIcon, NcNoteCard, NcSelect, NcTextField } from '@nextcloud/vue'
|
|
205
204
|
import CnChoiceCards from '../CnChoiceCards/CnChoiceCards.vue'
|
|
206
205
|
import CnLeafDependencySettings from '../CnLeafDependencySettings/CnLeafDependencySettings.vue'
|
|
207
206
|
import CnWizardDialog from '../CnWizardDialog/CnWizardDialog.vue'
|
|
208
|
-
import { checkDependencies, isDependencyResolved } from '../../composables/useDependencyCheck.js'
|
|
207
|
+
import { checkDependencies, isDependencyResolved, missingRequiredApps, readServerAppStatuses } from '../../composables/useDependencyCheck.js'
|
|
209
208
|
import { useSetupStatus } from '../../composables/useSetupStatus.js'
|
|
210
209
|
import { fieldsFromSchema } from '../../utils/schema.js'
|
|
211
210
|
|
|
@@ -474,16 +473,15 @@ export default {
|
|
|
474
473
|
*
|
|
475
474
|
* @return {Array<{ step: object, missing: Array<string> }>}
|
|
476
475
|
* @spec openspec/changes/setup-wizard-card-load-and-dependency-gate/specs/cn-setup-wizard/spec.md#requirement-the-wizard-checks-dependencies-before-any-step
|
|
476
|
+
* @spec openspec/changes/optional-step-requires/specs/cn-setup-wizard/spec.md#requirement-a-step-whose-required-apps-are-absent-is-not-applicable
|
|
477
477
|
*/
|
|
478
478
|
skippedSteps() {
|
|
479
479
|
return this.declaredSteps
|
|
480
480
|
.filter((s) => Array.isArray(s.requires) && s.requires.length > 0)
|
|
481
481
|
.map((step) => {
|
|
482
482
|
const known = Object.fromEntries(this.dependencyRows.map((d) => [d.id, d]))
|
|
483
|
-
const missing =
|
|
484
|
-
.map((row) => known[row.id] || row)
|
|
485
|
-
.filter((row) => !isDependencyResolved(row))
|
|
486
|
-
.map((row) => row.name || row.id)
|
|
483
|
+
const missing = missingRequiredApps(step.requires, this.serverAppStatuses)
|
|
484
|
+
.map((row) => (known[row.id] || row).name || row.id)
|
|
487
485
|
return { step, missing }
|
|
488
486
|
})
|
|
489
487
|
.filter((entry) => entry.missing.length > 0)
|
|
@@ -523,11 +521,7 @@ export default {
|
|
|
523
521
|
* @return {object}
|
|
524
522
|
*/
|
|
525
523
|
serverAppStatuses() {
|
|
526
|
-
|
|
527
|
-
return loadState(this.appId, 'dependency_statuses', {}) || {}
|
|
528
|
-
} catch {
|
|
529
|
-
return {}
|
|
530
|
-
}
|
|
524
|
+
return readServerAppStatuses(this.appId)
|
|
531
525
|
},
|
|
532
526
|
|
|
533
527
|
/**
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* SPDX-License-Identifier: EUPL-1.2
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { loadState } from '@nextcloud/initial-state'
|
|
6
7
|
import { useAppStatus } from './useAppStatus.js'
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -59,3 +60,45 @@ export function checkDependencies(entries, serverStatuses = {}) {
|
|
|
59
60
|
export function isDependencyResolved(row) {
|
|
60
61
|
return !!row && row.installed === true && row.enabled === true
|
|
61
62
|
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Read the `dependency_statuses` initial state an app may inject from PHP.
|
|
66
|
+
*
|
|
67
|
+
* Keyed by app id: `{ installed, enabled }`. Returns `{}` when the app injects
|
|
68
|
+
* none or the state cannot be read, so callers fall back to `useAppStatus`.
|
|
69
|
+
*
|
|
70
|
+
* @param {string} appId The app whose initial state to read.
|
|
71
|
+
* @return {object} Server-reported statuses keyed by app id.
|
|
72
|
+
*
|
|
73
|
+
* @spec openspec/changes/optional-step-requires/specs/cn-setup-wizard/spec.md#requirement-a-step-whose-required-apps-are-absent-is-not-applicable
|
|
74
|
+
*/
|
|
75
|
+
export function readServerAppStatuses(appId) {
|
|
76
|
+
try {
|
|
77
|
+
const statuses = loadState(appId, 'dependency_statuses', {})
|
|
78
|
+
return (statuses && typeof statuses === 'object') ? statuses : {}
|
|
79
|
+
} catch {
|
|
80
|
+
return {}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* The apps in a setup step's `requires` list that are not installed and
|
|
86
|
+
* enabled.
|
|
87
|
+
*
|
|
88
|
+
* This is the one resolution every setup surface uses: `CnSetupWizard` skips a
|
|
89
|
+
* step when it is non-empty, and `useSetupStatus` then counts that step as not
|
|
90
|
+
* applicable rather than unmet. Keeping both on one function is what stops the
|
|
91
|
+
* wizard and the status from disagreeing about the same step.
|
|
92
|
+
*
|
|
93
|
+
* @param {Array<string>} requires The step's `requires` app ids.
|
|
94
|
+
* @param {object} [serverStatuses] Server-reported statuses keyed by app id.
|
|
95
|
+
* @return {Array<{id: string, name: string, required: boolean, installed: boolean, enabled: boolean}>} The missing apps.
|
|
96
|
+
*
|
|
97
|
+
* @spec openspec/changes/optional-step-requires/specs/cn-setup-wizard/spec.md#requirement-a-step-whose-required-apps-are-absent-is-not-applicable
|
|
98
|
+
*/
|
|
99
|
+
export function missingRequiredApps(requires, serverStatuses = {}) {
|
|
100
|
+
if (!Array.isArray(requires) || requires.length === 0) {
|
|
101
|
+
return []
|
|
102
|
+
}
|
|
103
|
+
return checkDependencies(requires, serverStatuses).filter((row) => !isDependencyResolved(row))
|
|
104
|
+
}
|
|
@@ -94,6 +94,13 @@ export function useListView(objectTypeOrOptions, options) {
|
|
|
94
94
|
// field (a folder pane grouping by it, say) reads them here rather than
|
|
95
95
|
// deriving them from `objects`, which is only the current page.
|
|
96
96
|
const facets = computed(() => objectStore.facets[objectType] || {})
|
|
97
|
+
// Outcome of the latest `refresh()`: the store's error for it, or null once
|
|
98
|
+
// it succeeded or a later fetch stored new rows. The store keeps the previous
|
|
99
|
+
// rows on a failed fetch, so this is how a consumer tells stale rows from
|
|
100
|
+
// current ones.
|
|
101
|
+
const error = ref(null)
|
|
102
|
+
let refreshSeq = 0
|
|
103
|
+
let pendingRefreshes = 0
|
|
97
104
|
|
|
98
105
|
let searchTimeout = null
|
|
99
106
|
|
|
@@ -178,14 +185,48 @@ export function useListView(objectTypeOrOptions, options) {
|
|
|
178
185
|
|
|
179
186
|
/**
|
|
180
187
|
* Fetch the collection using current state params and update sidebar facet data.
|
|
188
|
+
* Only the most recently started refresh sets `error`, so an older response
|
|
189
|
+
* settling late cannot override a newer one's outcome.
|
|
181
190
|
*
|
|
182
191
|
* @param {number} [page] Page to fetch
|
|
183
192
|
* @return {Promise<void>}
|
|
184
193
|
*/
|
|
185
194
|
async function refresh(page = 1) {
|
|
186
|
-
|
|
195
|
+
const seq = ++refreshSeq
|
|
196
|
+
// This call's own result. `errors[objectType]` is shared by every call
|
|
197
|
+
// for the type and is not cleared on success, so it cannot say which
|
|
198
|
+
// request failed; it is only the fallback for a store that ignores
|
|
199
|
+
// `options.outcome`.
|
|
200
|
+
const outcome = {}
|
|
201
|
+
pendingRefreshes++
|
|
202
|
+
try {
|
|
203
|
+
await objectStore.fetchCollection(objectType, buildParams(page), { outcome })
|
|
204
|
+
} catch (e) {
|
|
205
|
+
if (seq === refreshSeq) {
|
|
206
|
+
error.value = e
|
|
207
|
+
}
|
|
208
|
+
throw e
|
|
209
|
+
} finally {
|
|
210
|
+
pendingRefreshes--
|
|
211
|
+
}
|
|
212
|
+
if (seq === refreshSeq) {
|
|
213
|
+
error.value = ('error' in outcome) ? outcome.error : (objectStore.errors?.[objectType] || null)
|
|
214
|
+
}
|
|
187
215
|
}
|
|
188
216
|
|
|
217
|
+
// A fetch outside `refresh()` (e.g. the live-updates refetch) that stores
|
|
218
|
+
// new rows recovers the list from an earlier failure. Rows written while
|
|
219
|
+
// a refresh is pending are left to that refresh, which decides `error`.
|
|
220
|
+
watch(
|
|
221
|
+
() => objectStore.collections[objectType],
|
|
222
|
+
() => {
|
|
223
|
+
if (pendingRefreshes === 0) {
|
|
224
|
+
error.value = null
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
{ flush: 'sync' },
|
|
228
|
+
)
|
|
229
|
+
|
|
189
230
|
// ── Event handlers ───────────────────────────────────────────────────
|
|
190
231
|
|
|
191
232
|
/**
|
|
@@ -323,6 +364,7 @@ export function useListView(objectTypeOrOptions, options) {
|
|
|
323
364
|
loading,
|
|
324
365
|
pagination,
|
|
325
366
|
facets,
|
|
367
|
+
error,
|
|
326
368
|
// Local state
|
|
327
369
|
searchTerm,
|
|
328
370
|
sortKey,
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { computed, ref } from 'vue'
|
|
7
|
+
import { missingRequiredApps, readServerAppStatuses } from './useDependencyCheck.js'
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Per-`appId` cache of setup-status results. The Vue refs are stored so all
|
|
@@ -27,6 +28,14 @@ const cache = new Map()
|
|
|
27
28
|
* every non-admin user of an app with a `setup` block met a wizard they had no
|
|
28
29
|
* permission to complete instead of the app itself.
|
|
29
30
|
*
|
|
31
|
+
* A step that declares `requires: [appId, ...]` is **not applicable** while any
|
|
32
|
+
* of those apps is not installed and enabled: it is neither met nor unmet, so
|
|
33
|
+
* it never lands in `requiredUnmet` or `optionalUnmet`. `CnSetupWizard` skips
|
|
34
|
+
* such a step, and counting it as unmet kept the wizard reopening (optional
|
|
35
|
+
* step) or gating the app (required step) for a step it would never show. App
|
|
36
|
+
* status is resolved exactly as the wizard does it: the `dependency_statuses`
|
|
37
|
+
* initial state first, then `useAppStatus`.
|
|
38
|
+
*
|
|
30
39
|
* @param {string} appId Nextcloud app id (e.g. `"procest"`).
|
|
31
40
|
* @param {object} manifest The app manifest (reads `manifest.setup`).
|
|
32
41
|
* @return {{
|
|
@@ -35,6 +44,7 @@ const cache = new Map()
|
|
|
35
44
|
* requiredUnmet: import('vue').ComputedRef<Array<object>>,
|
|
36
45
|
* optionalUnmet: import('vue').ComputedRef<Array<object>>,
|
|
37
46
|
* optionalUnmetReported: import('vue').ComputedRef<Array<object>>,
|
|
47
|
+
* notApplicable: import('vue').ComputedRef<Array<object>>,
|
|
38
48
|
* completed: import('vue').ComputedRef<boolean>,
|
|
39
49
|
* enabled: boolean,
|
|
40
50
|
* loading: import('vue').Ref<boolean>,
|
|
@@ -45,6 +55,7 @@ const cache = new Map()
|
|
|
45
55
|
*
|
|
46
56
|
* @example
|
|
47
57
|
* const { requiredUnmet, completed, loading } = useSetupStatus('procest', manifest)
|
|
58
|
+
* @spec openspec/changes/optional-step-requires/specs/cn-setup-wizard/spec.md#requirement-a-step-whose-required-apps-are-absent-is-not-applicable
|
|
48
59
|
*/
|
|
49
60
|
export function useSetupStatus(appId, manifest) {
|
|
50
61
|
const setup = (manifest && manifest.setup) || {}
|
|
@@ -68,6 +79,9 @@ export function useSetupStatus(appId, manifest) {
|
|
|
68
79
|
cache.set(appId, entry)
|
|
69
80
|
}
|
|
70
81
|
const { status, loading, error, forbidden } = entry
|
|
82
|
+
// Same source the wizard's dependency gate reads. Initial state is fixed
|
|
83
|
+
// for the page lifetime, so one read per call is enough.
|
|
84
|
+
const serverAppStatuses = readServerAppStatuses(appId)
|
|
71
85
|
|
|
72
86
|
const steps = computed(() => stepDefs.map((s) => {
|
|
73
87
|
const bag = status.value.steps || {}
|
|
@@ -81,7 +95,12 @@ export function useSetupStatus(appId, manifest) {
|
|
|
81
95
|
// that act on an unmet step — CnAppRoot auto-opening the non-gating
|
|
82
96
|
// wizard — must act only on steps the server actually reported, or an
|
|
83
97
|
// unknowable step parks the wizard over the app for ever.
|
|
84
|
-
|
|
98
|
+
//
|
|
99
|
+
// `applicable` is false when the step `requires` an app that is not
|
|
100
|
+
// installed and enabled. The wizard skips such a step, so it can never
|
|
101
|
+
// be done here; it is not applicable rather than unmet.
|
|
102
|
+
const missingApps = missingRequiredApps(s.requires, serverAppStatuses).map((row) => row.id)
|
|
103
|
+
return { ...s, done: st.done === true, reported, detail: st.detail, applicable: missingApps.length === 0, missingApps }
|
|
85
104
|
}))
|
|
86
105
|
// Presentational step types carry no work, so the server never reports a
|
|
87
106
|
// `done` flag for them. Counting them as "unmet" made `optionalUnmet`
|
|
@@ -89,7 +108,9 @@ export function useSetupStatus(appId, manifest) {
|
|
|
89
108
|
// which kept CnAppRoot's non-gating setup wizard auto-opening over the
|
|
90
109
|
// app on every fresh browser profile no matter how complete setup was.
|
|
91
110
|
// Only actionable steps can be unmet.
|
|
92
|
-
|
|
111
|
+
// A step whose required apps are absent is skipped by the wizard, so it
|
|
112
|
+
// is neither met nor unmet (see `applicable` above).
|
|
113
|
+
const isActionable = (s) => s.type !== 'info' && s.type !== 'summary' && s.applicable !== false
|
|
93
114
|
// `forbidden` empties BOTH lists, and that is what actually suppresses the
|
|
94
115
|
// wizard: CnAppRoot gates on `requiredUnmet.length > 0` (blocking) and on
|
|
95
116
|
// `requiredUnmet.length === 0 && optionalUnmet.length > 0` (auto-open) —
|
|
@@ -110,6 +131,8 @@ export function useSetupStatus(appId, manifest) {
|
|
|
110
131
|
// suppressing it is what left dossiq's `seed` step (and with it the app's
|
|
111
132
|
// only demo-data affordance) permanently unreachable.
|
|
112
133
|
const optionalUnmetReported = computed(() => optionalUnmet.value.filter((s) => s.reported === true))
|
|
134
|
+
// Steps the wizard skips because an app in their `requires` is absent.
|
|
135
|
+
const notApplicable = computed(() => steps.value.filter((s) => s.applicable === false))
|
|
113
136
|
const completed = computed(() => {
|
|
114
137
|
if (!enabled) {
|
|
115
138
|
return true
|
|
@@ -170,7 +193,7 @@ export function useSetupStatus(appId, manifest) {
|
|
|
170
193
|
refresh()
|
|
171
194
|
}
|
|
172
195
|
|
|
173
|
-
return { steps, status, requiredUnmet, optionalUnmet, optionalUnmetReported, completed, enabled, loading, error, forbidden, refresh }
|
|
196
|
+
return { steps, status, requiredUnmet, optionalUnmet, optionalUnmetReported, notApplicable, completed, enabled, loading, error, forbidden, refresh }
|
|
174
197
|
}
|
|
175
198
|
|
|
176
199
|
/**
|
package/src/css/actions-bar.css
CHANGED
|
@@ -35,6 +35,23 @@
|
|
|
35
35
|
color: var(--color-text-maxcontrast);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/* Beside the inline search (`showCountWithSearch`): the search field shrinks
|
|
39
|
+
first and the counter stays on one line. */
|
|
40
|
+
.cn-actions-bar__count--beside-search {
|
|
41
|
+
flex-shrink: 0;
|
|
42
|
+
white-space: nowrap;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* Taken out of the flex row so it adds no gap, but kept in the accessibility
|
|
46
|
+
tree so the live region exists before a total appears. */
|
|
47
|
+
.cn-actions-bar__count--empty {
|
|
48
|
+
position: absolute;
|
|
49
|
+
width: 1px;
|
|
50
|
+
height: 1px;
|
|
51
|
+
overflow: hidden;
|
|
52
|
+
clip-path: inset(50%);
|
|
53
|
+
}
|
|
54
|
+
|
|
38
55
|
/* Inline search field */
|
|
39
56
|
.cn-actions-bar__search {
|
|
40
57
|
position: relative;
|
|
@@ -294,8 +311,9 @@
|
|
|
294
311
|
display: contents;
|
|
295
312
|
}
|
|
296
313
|
|
|
297
|
-
/* #after-search filter buttons
|
|
298
|
-
search field (DOM order — search first via its
|
|
314
|
+
/* #after-search filter buttons, the beside-search counter and the view
|
|
315
|
+
toggle ride beside the search field (DOM order — search first via its
|
|
316
|
+
own order). */
|
|
299
317
|
.cn-actions-bar__info > * {
|
|
300
318
|
order: 1;
|
|
301
319
|
}
|
package/src/css/detail-page.css
CHANGED