@conduction/nextcloud-vue 2.61.0 → 2.63.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/CnAdminActionCard/CnAdminActionCard.vue.js +10 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue.js.map +1 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue2.js +189 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue2.js.map +1 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue3.js +72 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue3.js.map +1 -0
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js +394 -27
- 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/CnAppRoot/CnAppRoot.vue2.js +99 -9
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +39 -18
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +79 -2
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js +38 -25
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue2.js +21 -1
- package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue2.js.map +1 -1
- package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue3.js +4 -1
- package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue3.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js +53 -37
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +30 -6
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +2 -2
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue.js +10 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue.js.map +1 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue2.js +293 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue2.js.map +1 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue3.js +189 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue3.js.map +1 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +256 -23
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +119 -51
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +2 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue2.js +3 -1
- package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue2.js.map +1 -1
- package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue3.js +1 -1
- package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue3.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +234 -9
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +96 -57
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +51 -2
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +5 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/selfModeActions.js +3 -3
- package/dist/esm/components/CnIndexPage/selfModeActions.js.map +1 -1
- package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue2.js.map +1 -1
- package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +36 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +4 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +53 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +22 -5
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue2.js.map +1 -1
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue3.js.map +1 -1
- package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue2.js +121 -12
- package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue2.js.map +1 -1
- package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue3.js +3 -1
- package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue3.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +326 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +112 -26
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
- package/dist/esm/components/CnStorePage/CnStorePage.vue2.js.map +1 -1
- package/dist/esm/components/CnStorePage/CnStorePage.vue3.js.map +1 -1
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js +10 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js.map +1 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js +337 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js +102 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnTimelineWidget/dashboardRegistration.js +34 -0
- package/dist/esm/components/CnTimelineWidget/dashboardRegistration.js.map +1 -0
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue2.js +131 -8
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue2.js.map +1 -1
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue3.js +40 -38
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +8 -6
- 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/CnWikiPage/CnWikiPage.vue2.js.map +1 -1
- package/dist/esm/components/CnWikiPage/CnWikiPage.vue3.js.map +1 -1
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js +19 -0
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue3.js +1 -1
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue3.js.map +1 -1
- package/dist/esm/composables/useDependencyCheck.js +65 -0
- package/dist/esm/composables/useDependencyCheck.js.map +1 -0
- package/dist/esm/composables/useWalkthrough.js +218 -6
- package/dist/esm/composables/useWalkthrough.js.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +48 -0
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +48 -0
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +557 -9
- package/dist/esm/store/useObjectStore.js +8 -0
- package/dist/esm/store/useObjectStore.js.map +1 -1
- package/dist/esm/utils/columnFilters.js +311 -0
- package/dist/esm/utils/columnFilters.js.map +1 -0
- package/dist/esm/utils/groupAutocomplete.js +123 -0
- package/dist/esm/utils/groupAutocomplete.js.map +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js +2 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/pickerOptions.js +198 -0
- package/dist/esm/utils/pickerOptions.js.map +1 -0
- package/dist/esm/utils/schema.js +83 -7
- package/dist/esm/utils/schema.js.map +1 -1
- package/dist/esm/utils/timelineEvents.js +174 -0
- package/dist/esm/utils/timelineEvents.js.map +1 -0
- package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/walkthroughSignals.js +88 -0
- package/dist/esm/utils/walkthroughSignals.js.map +1 -0
- package/dist/nextcloud-vue.cjs.js +9779 -5236
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +557 -9
- package/l10n/en.json +48 -0
- package/l10n/nl.json +48 -0
- package/package.json +3 -2
- package/scripts/manifest-schema-hash.js +41 -0
- package/scripts/record-manifest-schema-hash.js +52 -0
- package/src/components/CnAdminActionCard/CnAdminActionCard.vue +234 -0
- package/src/components/CnAdminActionCard/index.js +4 -0
- package/src/components/CnAppNav/CnAppNav.vue +394 -27
- package/src/components/CnAppRoot/CnAppRoot.vue +129 -15
- package/src/components/CnBannerWidget/CnBannerWidget.vue +113 -2
- package/src/components/CnBrandStripe/CnBrandStripe.md +16 -0
- package/src/components/CnBrandStripe/CnBrandStripe.vue +58 -5
- package/src/components/CnChoiceCards/CnChoiceCards.vue +56 -31
- package/src/components/CnDashboardPage/CnDashboardPage.vue +32 -8
- package/src/components/CnDataTable/CnColumnFilterPopover.vue +524 -0
- package/src/components/CnDataTable/CnDataTable.md +4 -1
- package/src/components/CnDataTable/CnDataTable.vue +302 -21
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +2 -2
- package/src/components/CnFieldHelper/CnFieldHelper.vue +4 -2
- package/src/components/CnFormDialog/CnFormDialog.vue +290 -31
- package/src/components/CnIndexPage/CnIndexPage.vue +55 -2
- package/src/components/CnIndexPage/selfModeActions.js +3 -3
- package/src/components/CnLinkCardsPage/CnLinkCardsPage.vue +35 -2
- package/src/components/CnObjectListWidget/CnObjectListWidget.vue +39 -1
- package/src/components/CnObjectSidebar/CnFilesTab.vue +65 -0
- package/src/components/CnReportsPage/CnReportsPage.vue +7 -0
- package/src/components/CnResourceSelect/CnResourceSelect.vue +123 -12
- package/src/components/CnSetupWizard/CnSetupWizard.vue +392 -3
- package/src/components/CnStorePage/CnStorePage.vue +7 -0
- package/src/components/CnTimelineWidget/CnTimelineWidget.vue +477 -0
- package/src/components/CnTimelineWidget/dashboardRegistration.js +32 -0
- package/src/components/CnTimelineWidget/index.js +4 -0
- package/src/components/CnWalkthrough/CnWalkthrough.vue +143 -10
- package/src/components/CnWidgetGrid/builtInWidgets.js +2 -0
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
- package/src/components/CnWikiPage/CnWikiPage.vue +7 -0
- package/src/components/CnWizardDialog/CnWizardDialog.vue +20 -1
- package/src/components/index.js +2 -0
- package/src/composables/useDependencyCheck.js +61 -0
- package/src/composables/useWalkthrough.js +217 -5
- package/src/css/dashboard.css +49 -0
- package/src/css/detail-page.css +19 -0
- package/src/css/table.css +82 -2
- package/src/index.js +2 -0
- package/src/public/index.js +5 -0
- package/src/schemas/app-manifest-v2.schema.json +23 -1
- package/src/store/useObjectStore.js +8 -0
- package/src/utils/columnFilters.js +324 -0
- package/src/utils/groupAutocomplete.js +119 -0
- package/src/utils/libraryWidgetKeys.js +2 -0
- package/src/utils/pickerOptions.js +194 -0
- package/src/utils/schema.js +83 -7
- package/src/utils/timelineEvents.js +171 -0
- package/src/utils/validateManifestV2.compiled.js +2 -2
- package/src/utils/walkthroughSignals.js +94 -0
|
@@ -199,6 +199,162 @@ export function persistWalkthroughSeenVersion(appId, configKey, version, options
|
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
/**
|
|
203
|
+
* localStorage key prefix for the per-browser mirror of tour progress.
|
|
204
|
+
*/
|
|
205
|
+
export const WALKTHROUGH_PROGRESS_STORAGE_PREFIX = 'cn-walkthrough-progress:'
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* The preference key that holds tour progress, next to the completion key.
|
|
209
|
+
*
|
|
210
|
+
* @param {string} configKey `manifest.walkthrough.completionConfigKey` (may be empty).
|
|
211
|
+
* @return {string} `<configKey>-progress`, or '' when no key is declared.
|
|
212
|
+
*/
|
|
213
|
+
export function walkthroughProgressKey(configKey) {
|
|
214
|
+
return configKey ? configKey + '-progress' : ''
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Normalise stored progress (an object, or the JSON string a preference
|
|
219
|
+
* holds) into `{ tourId, stepId, index, version }`, or null.
|
|
220
|
+
*
|
|
221
|
+
* @spec openspec/changes/walkthrough-advance-pause-resume/specs/cn-walkthrough/spec.md
|
|
222
|
+
* @param {unknown} value The stored value.
|
|
223
|
+
* @return {{tourId: string, stepId: string, index: number, version: string}|null} The progress.
|
|
224
|
+
*/
|
|
225
|
+
export function normaliseWalkthroughProgress(value) {
|
|
226
|
+
let data = value
|
|
227
|
+
if (typeof data === 'string') {
|
|
228
|
+
if (data === '') {
|
|
229
|
+
return null
|
|
230
|
+
}
|
|
231
|
+
try {
|
|
232
|
+
data = JSON.parse(data)
|
|
233
|
+
} catch {
|
|
234
|
+
return null
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (!isPlainObject(data) || typeof data.tourId !== 'string' || data.tourId === '') {
|
|
238
|
+
return null
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
tourId: data.tourId,
|
|
242
|
+
stepId: typeof data.stepId === 'string' ? data.stepId : '',
|
|
243
|
+
index: Number.isInteger(data.index) && data.index >= 0 ? data.index : 0,
|
|
244
|
+
version: typeof data.version === 'string' ? data.version : '',
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Read the per-browser mirror of the tour progress. Synchronous.
|
|
250
|
+
*
|
|
251
|
+
* @spec openspec/changes/walkthrough-advance-pause-resume/specs/cn-walkthrough/spec.md
|
|
252
|
+
* @param {string} appId The Nextcloud app id.
|
|
253
|
+
* @param {Storage} [storage] Injectable storage backend.
|
|
254
|
+
* @return {object|null} The progress, or null.
|
|
255
|
+
*/
|
|
256
|
+
export function readLocalWalkthroughProgress(appId, storage) {
|
|
257
|
+
const s = resolveStorage(storage)
|
|
258
|
+
if (!s) {
|
|
259
|
+
return null
|
|
260
|
+
}
|
|
261
|
+
try {
|
|
262
|
+
return normaliseWalkthroughProgress(s.getItem(WALKTHROUGH_PROGRESS_STORAGE_PREFIX + appId))
|
|
263
|
+
} catch {
|
|
264
|
+
return null
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Load the user's tour progress: the per-user preference
|
|
270
|
+
* `<completionConfigKey>-progress` when declared, else the local mirror.
|
|
271
|
+
*
|
|
272
|
+
* @spec openspec/changes/walkthrough-advance-pause-resume/specs/cn-walkthrough/spec.md
|
|
273
|
+
* @param {string} appId The Nextcloud app id.
|
|
274
|
+
* @param {string} configKey `manifest.walkthrough.completionConfigKey` (may be empty).
|
|
275
|
+
* @param {object} [options] `{ http, storage }` injection points for tests.
|
|
276
|
+
* @return {Promise<object|null>} The progress, or null.
|
|
277
|
+
*/
|
|
278
|
+
export async function loadWalkthroughProgress(appId, configKey, options = {}) {
|
|
279
|
+
const local = readLocalWalkthroughProgress(appId, options.storage)
|
|
280
|
+
const key = walkthroughProgressKey(configKey)
|
|
281
|
+
if (!key) {
|
|
282
|
+
return local
|
|
283
|
+
}
|
|
284
|
+
const http = options.http || axios
|
|
285
|
+
try {
|
|
286
|
+
const { data } = await http.get(walkthroughPreferenceUrl(appId, key))
|
|
287
|
+
if (!isPlainObject(data) || !('value' in data)) {
|
|
288
|
+
return local
|
|
289
|
+
}
|
|
290
|
+
return normaliseWalkthroughProgress(data.value) || local
|
|
291
|
+
} catch {
|
|
292
|
+
return local
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Persist the user's tour progress, or clear it with `null`. Writes the
|
|
298
|
+
* local mirror and, with a completion key, the per-user preference. Never
|
|
299
|
+
* throws.
|
|
300
|
+
*
|
|
301
|
+
* @spec openspec/changes/walkthrough-advance-pause-resume/specs/cn-walkthrough/spec.md
|
|
302
|
+
* @param {string} appId The Nextcloud app id.
|
|
303
|
+
* @param {string} configKey `manifest.walkthrough.completionConfigKey` (may be empty).
|
|
304
|
+
* @param {object|null} progress `{ tourId, stepId, index, version }`, or null to clear.
|
|
305
|
+
* @param {object} [options] `{ http, storage }` injection points for tests.
|
|
306
|
+
* @return {Promise<boolean>} True when the server preference was written.
|
|
307
|
+
*/
|
|
308
|
+
export function persistWalkthroughProgress(appId, configKey, progress, options = {}) {
|
|
309
|
+
const value = progress ? normaliseWalkthroughProgress(progress) : null
|
|
310
|
+
const raw = value ? JSON.stringify(value) : ''
|
|
311
|
+
const s = resolveStorage(options.storage)
|
|
312
|
+
if (s) {
|
|
313
|
+
try {
|
|
314
|
+
if (raw) {
|
|
315
|
+
s.setItem(WALKTHROUGH_PROGRESS_STORAGE_PREFIX + appId, raw)
|
|
316
|
+
} else {
|
|
317
|
+
s.removeItem(WALKTHROUGH_PROGRESS_STORAGE_PREFIX + appId)
|
|
318
|
+
}
|
|
319
|
+
} catch {
|
|
320
|
+
/* quota / private mode: best-effort */
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
const key = walkthroughProgressKey(configKey)
|
|
324
|
+
if (!key) {
|
|
325
|
+
return Promise.resolve(false)
|
|
326
|
+
}
|
|
327
|
+
const http = options.http || axios
|
|
328
|
+
try {
|
|
329
|
+
return Promise.resolve(http.put(walkthroughPreferenceUrl(appId, key), { value: raw }))
|
|
330
|
+
.then(() => true)
|
|
331
|
+
.catch(() => false)
|
|
332
|
+
} catch {
|
|
333
|
+
return Promise.resolve(false)
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Whether an `object-created` signal satisfies a step's `advanceOn`.
|
|
339
|
+
*
|
|
340
|
+
* The signal's own `register` / `schema` (the slugs the creating surface
|
|
341
|
+
* knows) are compared first; an object's `@self` values are numeric ids on
|
|
342
|
+
* OpenRegister and only match a step that also uses ids.
|
|
343
|
+
*
|
|
344
|
+
* @param {object} advanceOn The step's `advanceOn`.
|
|
345
|
+
* @param {object} signal `{ register?, schema?, object? }`.
|
|
346
|
+
* @return {boolean} True when it matches.
|
|
347
|
+
*/
|
|
348
|
+
function objectCreatedMatches(advanceOn, signal) {
|
|
349
|
+
const obj = signal.object || {}
|
|
350
|
+
const self = obj['@self'] || {}
|
|
351
|
+
const same = (want, candidates) => !want || candidates
|
|
352
|
+
.filter((c) => c !== null && c !== undefined && c !== '')
|
|
353
|
+
.some((c) => String(c).toLowerCase() === String(want).toLowerCase())
|
|
354
|
+
return same(advanceOn.register, [signal.register, obj.register, self.register])
|
|
355
|
+
&& same(advanceOn.schema, [signal.schema, obj.schema, self.schema])
|
|
356
|
+
}
|
|
357
|
+
|
|
202
358
|
/**
|
|
203
359
|
* Compare two semver-ish strings. Missing / unparseable parts sort as 0.
|
|
204
360
|
*
|
|
@@ -276,6 +432,9 @@ export function useWalkthrough(appId, manifest, options = {}) {
|
|
|
276
432
|
const currentIndex = ref(0)
|
|
277
433
|
const context = ref({})
|
|
278
434
|
const running = ref(false)
|
|
435
|
+
// True while the tour is hidden by ESC or a backdrop click. The tour
|
|
436
|
+
// and its step stay, so it continues where it was.
|
|
437
|
+
const paused = ref(false)
|
|
279
438
|
// True while a user-initiated replay is active (the "Restart tutorial"
|
|
280
439
|
// entry). A replay shows the FULL tour regardless of the persisted
|
|
281
440
|
// seen-version — otherwise a returning user, whose seenVersion already
|
|
@@ -479,6 +638,7 @@ export function useWalkthrough(appId, manifest, options = {}) {
|
|
|
479
638
|
*/
|
|
480
639
|
function start(tourId, startIndex = 0) {
|
|
481
640
|
replaying.value = false
|
|
641
|
+
paused.value = false
|
|
482
642
|
activeTourId.value = tourId
|
|
483
643
|
currentIndex.value = startIndex
|
|
484
644
|
context.value = {}
|
|
@@ -503,9 +663,59 @@ export function useWalkthrough(appId, manifest, options = {}) {
|
|
|
503
663
|
*/
|
|
504
664
|
function dismiss() {
|
|
505
665
|
running.value = false
|
|
666
|
+
paused.value = false
|
|
506
667
|
activeTourId.value = null
|
|
507
668
|
replaying.value = false
|
|
508
669
|
}
|
|
670
|
+
/**
|
|
671
|
+
* Hide the active tour without ending it (ESC, a click on the dim).
|
|
672
|
+
* The tour and step are kept, so `resumePaused()` continues there.
|
|
673
|
+
*
|
|
674
|
+
* @spec openspec/changes/walkthrough-advance-pause-resume/specs/cn-walkthrough/spec.md
|
|
675
|
+
* @return {void}
|
|
676
|
+
*/
|
|
677
|
+
function pause() {
|
|
678
|
+
if (!activeTourId.value) {
|
|
679
|
+
return
|
|
680
|
+
}
|
|
681
|
+
running.value = false
|
|
682
|
+
paused.value = true
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Show a paused tour again at the step it was on.
|
|
686
|
+
*
|
|
687
|
+
* @spec openspec/changes/walkthrough-advance-pause-resume/specs/cn-walkthrough/spec.md
|
|
688
|
+
* @return {boolean} True when there was a paused tour to show.
|
|
689
|
+
*/
|
|
690
|
+
function resumePaused() {
|
|
691
|
+
if (!paused.value || !activeTourId.value) {
|
|
692
|
+
return false
|
|
693
|
+
}
|
|
694
|
+
paused.value = false
|
|
695
|
+
running.value = true
|
|
696
|
+
return true
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Start a tour at a remembered step ("continue where you left off").
|
|
700
|
+
* Runs in replay mode so a returning user sees the full tour, and
|
|
701
|
+
* falls back to the first step when the step no longer exists.
|
|
702
|
+
*
|
|
703
|
+
* @spec openspec/changes/walkthrough-advance-pause-resume/specs/cn-walkthrough/spec.md
|
|
704
|
+
* @param {string} tourId The tour id.
|
|
705
|
+
* @param {string} [stepId] The step to continue at.
|
|
706
|
+
* @return {boolean} True when the tour exists and started.
|
|
707
|
+
*/
|
|
708
|
+
function resumeAt(tourId, stepId) {
|
|
709
|
+
const tour = tours.find((t) => t.id === tourId)
|
|
710
|
+
if (!tour) {
|
|
711
|
+
return false
|
|
712
|
+
}
|
|
713
|
+
replaying.value = true
|
|
714
|
+
const idx = composeSteps(tour).findIndex((s) => s.id === stepId)
|
|
715
|
+
start(tourId, Math.max(0, idx))
|
|
716
|
+
replaying.value = true
|
|
717
|
+
return true
|
|
718
|
+
}
|
|
509
719
|
/**
|
|
510
720
|
* Mark the active tour complete: stop running and invoke the
|
|
511
721
|
* `onComplete(appVersion)` persistence callback so the seen version is
|
|
@@ -515,6 +725,7 @@ export function useWalkthrough(appId, manifest, options = {}) {
|
|
|
515
725
|
*/
|
|
516
726
|
function complete() {
|
|
517
727
|
running.value = false
|
|
728
|
+
paused.value = false
|
|
518
729
|
activeTourId.value = null
|
|
519
730
|
replaying.value = false
|
|
520
731
|
if (typeof options.onComplete === 'function') {
|
|
@@ -542,12 +753,9 @@ export function useWalkthrough(appId, manifest, options = {}) {
|
|
|
542
753
|
runCapture(step, { params: signal.params || {} })
|
|
543
754
|
}
|
|
544
755
|
} else if (signal.kind === 'object-created' && a.type === 'object-created') {
|
|
545
|
-
|
|
546
|
-
const reg = obj.register ?? obj['@self']?.register
|
|
547
|
-
const sch = obj.schema ?? obj['@self']?.schema
|
|
548
|
-
match = (!a.register || reg === a.register) && (!a.schema || sch === a.schema)
|
|
756
|
+
match = objectCreatedMatches(a, signal)
|
|
549
757
|
if (match) {
|
|
550
|
-
runCapture(step, { object:
|
|
758
|
+
runCapture(step, { object: signal.object || {} })
|
|
551
759
|
}
|
|
552
760
|
} else if (signal.kind === 'element' && a.type === 'element-appears') {
|
|
553
761
|
match = true
|
|
@@ -575,9 +783,13 @@ export function useWalkthrough(appId, manifest, options = {}) {
|
|
|
575
783
|
isLast,
|
|
576
784
|
context,
|
|
577
785
|
running,
|
|
786
|
+
paused,
|
|
578
787
|
replaying,
|
|
579
788
|
start,
|
|
580
789
|
restart,
|
|
790
|
+
pause,
|
|
791
|
+
resumePaused,
|
|
792
|
+
resumeAt,
|
|
581
793
|
next,
|
|
582
794
|
back,
|
|
583
795
|
skip,
|
package/src/css/dashboard.css
CHANGED
|
@@ -80,3 +80,52 @@
|
|
|
80
80
|
.cn-dashboard-list__item:hover {
|
|
81
81
|
background: var(--color-background-hover);
|
|
82
82
|
}
|
|
83
|
+
|
|
84
|
+
/* "Install <app>" placeholder in a widget whose app is missing.
|
|
85
|
+
*
|
|
86
|
+
* NcEmptyContent centres its content with `justify-content: center`. In a
|
|
87
|
+
* two-row dashboard tile (about 150px inside an `overflow: hidden` wrapper)
|
|
88
|
+
* the icon, name, description and button are taller than the tile, and plain
|
|
89
|
+
* `center` overflows on BOTH sides, so the top ran out of the widget and the
|
|
90
|
+
* name was cut off. `safe center` falls back to the start edge when the
|
|
91
|
+
* content does not fit, the spacing is compact, and what still does not fit
|
|
92
|
+
* scrolls instead of being clipped. Shared by CnDashboardPage and
|
|
93
|
+
* CnDetailWidgetHost (`cn-requires-app`). The class is doubled to outrank
|
|
94
|
+
* NcEmptyContent's own scoped rules (`.empty-content[data-v-…]`) whatever
|
|
95
|
+
* order the stylesheets load in. */
|
|
96
|
+
.cn-requires-app.cn-requires-app.empty-content,
|
|
97
|
+
.cn-requires-app.cn-requires-app .empty-content {
|
|
98
|
+
justify-content: safe center;
|
|
99
|
+
min-height: 0;
|
|
100
|
+
max-height: 100%;
|
|
101
|
+
overflow: auto;
|
|
102
|
+
margin: 0;
|
|
103
|
+
padding: calc(2 * var(--default-grid-baseline, 4px));
|
|
104
|
+
gap: var(--default-grid-baseline, 4px);
|
|
105
|
+
box-sizing: border-box;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.cn-requires-app.cn-requires-app .empty-content__icon {
|
|
109
|
+
width: auto;
|
|
110
|
+
height: auto;
|
|
111
|
+
min-height: 0;
|
|
112
|
+
margin: 0;
|
|
113
|
+
opacity: 0.7;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.cn-requires-app.cn-requires-app .empty-content__name {
|
|
117
|
+
margin: 0;
|
|
118
|
+
font-size: var(--default-font-size, 15px);
|
|
119
|
+
font-weight: 600;
|
|
120
|
+
text-align: center;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.cn-requires-app.cn-requires-app .empty-content__description {
|
|
124
|
+
margin: 0;
|
|
125
|
+
text-align: center;
|
|
126
|
+
font-size: 0.9em;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.cn-requires-app.cn-requires-app .empty-content__action {
|
|
130
|
+
margin-top: var(--default-grid-baseline, 4px);
|
|
131
|
+
}
|
package/src/css/detail-page.css
CHANGED
|
@@ -106,6 +106,25 @@
|
|
|
106
106
|
flex-shrink: 0;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
/* Every control in the header sits on one line at one height. The lifecycle
|
|
110
|
+
bar carries `margin: 0 0 8px` for its place above a page body; in the
|
|
111
|
+
header that margin pushed its buttons up and made the row 8px taller, so
|
|
112
|
+
the Edit button beside it read as the bigger one. A consumer's actions
|
|
113
|
+
component can bring its own margins too, so they are reset here as well. */
|
|
114
|
+
.cn-detail-page .cn-detail-page__header-actions .cn-lifecycle-actions {
|
|
115
|
+
margin: 0;
|
|
116
|
+
flex-wrap: nowrap;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.cn-detail-page .cn-detail-page__header-actions > * {
|
|
120
|
+
margin-block: 0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.cn-detail-page .cn-detail-page__header-actions .button-vue {
|
|
124
|
+
min-height: var(--default-clickable-area);
|
|
125
|
+
block-size: var(--default-clickable-area);
|
|
126
|
+
}
|
|
127
|
+
|
|
109
128
|
/* The sentence a refused lock acquire left behind, under the locked banner. */
|
|
110
129
|
.cn-detail-page__lock-refusal {
|
|
111
130
|
margin: 0 0 calc(3 * var(--default-grid-baseline));
|
package/src/css/table.css
CHANGED
|
@@ -295,8 +295,88 @@
|
|
|
295
295
|
outline-offset: -2px;
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
-
/*
|
|
299
|
-
|
|
298
|
+
/* Header filter button (CnDataTable `filterable`). 24px hit area with the
|
|
299
|
+
16px icon; the filled icon plus the primary colour marks an active filter,
|
|
300
|
+
so the state never rests on colour alone. */
|
|
301
|
+
.cn-table-header__filter {
|
|
302
|
+
display: inline-flex;
|
|
303
|
+
align-items: center;
|
|
304
|
+
justify-content: center;
|
|
305
|
+
width: 24px;
|
|
306
|
+
min-width: 24px;
|
|
307
|
+
height: 24px;
|
|
308
|
+
min-height: 24px;
|
|
309
|
+
margin: 0 0 0 4px;
|
|
310
|
+
padding: 0;
|
|
311
|
+
border: none;
|
|
312
|
+
border-radius: var(--border-radius, 4px);
|
|
313
|
+
background: transparent;
|
|
314
|
+
color: var(--color-text-maxcontrast);
|
|
315
|
+
vertical-align: middle;
|
|
316
|
+
cursor: pointer;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.cn-table-header__filter:hover {
|
|
320
|
+
background-color: var(--color-background-hover);
|
|
321
|
+
color: var(--color-main-text);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.cn-table-header__filter:focus-visible {
|
|
325
|
+
outline: 2px solid var(--color-main-text);
|
|
326
|
+
outline-offset: 0;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.cn-table-header__filter--active {
|
|
330
|
+
color: var(--color-primary-element);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/* Active header filters above the table, one removable chip each. */
|
|
334
|
+
.cn-data-table__filter-chips {
|
|
335
|
+
display: flex;
|
|
336
|
+
flex-wrap: wrap;
|
|
337
|
+
gap: 6px;
|
|
338
|
+
margin: 0 0 8px;
|
|
339
|
+
padding: 0;
|
|
340
|
+
list-style: none;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.cn-data-table__filter-chip {
|
|
344
|
+
display: inline-flex;
|
|
345
|
+
align-items: center;
|
|
346
|
+
gap: 4px;
|
|
347
|
+
padding: 2px 4px 2px 10px;
|
|
348
|
+
border: 1px solid var(--color-border-dark);
|
|
349
|
+
border-radius: var(--border-radius-pill, 16px);
|
|
350
|
+
background-color: var(--color-background-dark);
|
|
351
|
+
color: var(--color-main-text);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.cn-data-table__filter-chip-remove {
|
|
355
|
+
display: inline-flex;
|
|
356
|
+
align-items: center;
|
|
357
|
+
justify-content: center;
|
|
358
|
+
width: 24px;
|
|
359
|
+
min-width: 24px;
|
|
360
|
+
height: 24px;
|
|
361
|
+
min-height: 24px;
|
|
362
|
+
margin: 0;
|
|
363
|
+
padding: 0;
|
|
364
|
+
border: none;
|
|
365
|
+
border-radius: 50%;
|
|
366
|
+
background: transparent;
|
|
367
|
+
color: var(--color-main-text);
|
|
368
|
+
cursor: pointer;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.cn-data-table__filter-chip-remove:hover {
|
|
372
|
+
background-color: var(--color-background-hover);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.cn-data-table__filter-chip-remove:focus-visible {
|
|
376
|
+
outline: 2px solid var(--color-main-text);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/* Multi-column sort priority badge (1, 2, 3), rendered only when two or more rendered, sortable columns are sorted. */
|
|
300
380
|
.cn-table-sort-badge {
|
|
301
381
|
display: inline-flex;
|
|
302
382
|
align-items: center;
|
package/src/index.js
CHANGED
|
@@ -35,6 +35,7 @@ export {
|
|
|
35
35
|
CnActionsBar,
|
|
36
36
|
CnActionsMenu,
|
|
37
37
|
CnAddWidgetModal,
|
|
38
|
+
CnAdminActionCard,
|
|
38
39
|
CnAdminSettingsShell,
|
|
39
40
|
CnAdvancedFormDialog,
|
|
40
41
|
CnAppLoading,
|
|
@@ -268,6 +269,7 @@ export {
|
|
|
268
269
|
CnTileWidget,
|
|
269
270
|
CnTimelineStages,
|
|
270
271
|
CnTimelineView,
|
|
272
|
+
CnTimelineWidget,
|
|
271
273
|
CnTranslatedBadge,
|
|
272
274
|
CnTreeView,
|
|
273
275
|
CnUserActionMenu,
|
package/src/public/index.js
CHANGED
|
@@ -40,6 +40,10 @@
|
|
|
40
40
|
* claiming purity is worth nothing; the check is in CI.
|
|
41
41
|
*/
|
|
42
42
|
|
|
43
|
+
// The brand stripe imports nothing at all, so it is public-safe as it is: a
|
|
44
|
+
// portal draws the organisation's motif under its header with the same
|
|
45
|
+
// component, and the same tokens, as a Nextcloud page (brand-motif-token).
|
|
46
|
+
import CnBrandStripe from '../components/CnBrandStripe/CnBrandStripe.vue'
|
|
43
47
|
import CnSiteCard from './components/CnSiteCard.vue'
|
|
44
48
|
import CnSiteCardGrid from './components/CnSiteCardGrid.vue'
|
|
45
49
|
import CnSiteEmptyState from './components/CnSiteEmptyState.vue'
|
|
@@ -50,6 +54,7 @@ import CnSiteSearch from './components/CnSiteSearch.vue'
|
|
|
50
54
|
import CnSiteSection from './components/CnSiteSection.vue'
|
|
51
55
|
|
|
52
56
|
export {
|
|
57
|
+
CnBrandStripe,
|
|
53
58
|
CnSiteCard,
|
|
54
59
|
CnSiteCardGrid,
|
|
55
60
|
CnSiteEmptyState,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"$id": "https://raw.githubusercontent.com/ConductionNL/nextcloud-vue/main/src/schemas/app-manifest-v2.schema.json",
|
|
4
4
|
"title": "Conduction App Manifest v2",
|
|
5
5
|
"description": "v2 schema for the JSON-driven page and navigation manifest consumed by @conduction/nextcloud-vue. Introduces a uniform widgets[] array on every page type with a per-slot grid coordinate system, a typed actions[] discriminator, and the required $schema field for version detection. v1 manifests continue to validate against app-manifest.schema.json (unchanged).",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.45.0",
|
|
7
7
|
"type": "object",
|
|
8
8
|
"required": ["$schema", "version"],
|
|
9
9
|
"allOf": [
|
|
@@ -97,6 +97,8 @@
|
|
|
97
97
|
"suggestFrom": { "type": "string", "description": "choice: the configKey of an earlier choice this step pre-fills a suggestion from. When that value is set and the user has not yet picked here, the option matching suggestMap[parentValue] is auto-selected (still user-overridable)." },
|
|
98
98
|
"suggestMap": { "type": "object", "description": "choice: map of suggestFrom value → suggested option value. Used to auto-suggest a default (e.g. RGS template suggested from organisation type).", "additionalProperties": { "type": "string" } },
|
|
99
99
|
"multiple": { "type": "boolean", "default": false, "description": "choice: allow multi-select." },
|
|
100
|
+
"loadAction": { "type": "string", "minLength": 1, "description": "choice with display cards: an actionId each option card loads itself with. Every card except the one whose value is `none` gets its own Load button, which POSTs { dataset: <value> } to /api/setup/action/{loadAction}, spins while it runs and shows the result on that card. A successful load also selects the card. With loadAction the separate run-action step that loaded the picked dataset is no longer needed; manifests that keep it still work." },
|
|
101
|
+
"requires": { "type": "array", "items": { "type": "string", "minLength": 1 }, "uniqueItems": true, "description": "App ids this step needs. When any of them is not installed and enabled, the wizard skips the step and the summary shows it as skipped, naming the missing apps. Do not combine with required: true; setup status would keep reporting the skipped step as unmet." },
|
|
100
102
|
"action": { "type": "string", "description": "run-action: actionId POSTed to /api/setup/action/{action}." },
|
|
101
103
|
"onDemand": { "type": "boolean", "default": false, "description": "run-action: the step runs only when the user clicks Run, never automatically, and is never outstanding work (it does not open the wizard or decide where a resumed wizard starts). The summary ticks it only when its action succeeded in the current session and shows it as not run otherwise, whatever the server reports. For destructive steps an app reports as done on purpose so they never auto-run, such as removing example data." },
|
|
102
104
|
"healthCheck": { "type": "boolean", "default": false, "description": "summary: render a health recap." },
|
|
@@ -1173,6 +1175,11 @@
|
|
|
1173
1175
|
"type": "string",
|
|
1174
1176
|
"description": "i18n translation key resolved by the consuming app's t() function at render time."
|
|
1175
1177
|
},
|
|
1178
|
+
"translateLabel": {
|
|
1179
|
+
"type": "boolean",
|
|
1180
|
+
"default": true,
|
|
1181
|
+
"description": "Whether CnAppNav runs `label` through the translate function. Set false for a user-authored title (e.g. a catalog name) that must render as written even when it equals a translation key such as 'Search'. Rendered as text either way, never as HTML."
|
|
1182
|
+
},
|
|
1176
1183
|
"icon": {
|
|
1177
1184
|
"type": "string",
|
|
1178
1185
|
"description": "CSS class for the icon (e.g. 'icon-checkmark') or MDI component name."
|
|
@@ -1186,6 +1193,11 @@
|
|
|
1186
1193
|
"additionalProperties": { "type": ["string", "number", "boolean"] },
|
|
1187
1194
|
"description": "Optional vue-router query parameters merged into the target route link (e.g. a filter like { caseType: '<uuid>' }). Deep-links a nav entry to a pre-filtered index page."
|
|
1188
1195
|
},
|
|
1196
|
+
"params": {
|
|
1197
|
+
"type": "object",
|
|
1198
|
+
"additionalProperties": { "type": ["string", "number"], "minLength": 1 },
|
|
1199
|
+
"description": "Optional vue-router route params for a parameterised route (e.g. { catalogSlug: 'news' } for a page at '/catalogs/:catalogSlug'). String values must be non-empty. CnAppNav links to { name: route, params, query }. The entry is active only while every declared param equals the current route's param (compared as strings), so sibling entries on one route that differ in params are never marked together. On pages whose path sits below its page path with these params filled in, it is active too: by the same params check when those routes carry the same param names, otherwise as the one entry marked below its route."
|
|
1200
|
+
},
|
|
1189
1201
|
"order": {
|
|
1190
1202
|
"type": "integer",
|
|
1191
1203
|
"description": "Display order in the menu. Items without an order render last."
|
|
@@ -1259,6 +1271,11 @@
|
|
|
1259
1271
|
"properties": {
|
|
1260
1272
|
"id": { "type": "string" },
|
|
1261
1273
|
"label": { "type": "string" },
|
|
1274
|
+
"translateLabel": {
|
|
1275
|
+
"type": "boolean",
|
|
1276
|
+
"default": true,
|
|
1277
|
+
"description": "Same as menuItem.translateLabel: false renders `label` as written instead of translating it."
|
|
1278
|
+
},
|
|
1262
1279
|
"icon": { "type": "string" },
|
|
1263
1280
|
"route": { "type": "string" },
|
|
1264
1281
|
"query": {
|
|
@@ -1266,6 +1283,11 @@
|
|
|
1266
1283
|
"additionalProperties": { "type": ["string", "number", "boolean"] },
|
|
1267
1284
|
"description": "Optional vue-router query parameters merged into the target route link (e.g. a filter like { caseType: '<uuid>' }). Deep-links a nav entry to a pre-filtered index page."
|
|
1268
1285
|
},
|
|
1286
|
+
"params": {
|
|
1287
|
+
"type": "object",
|
|
1288
|
+
"additionalProperties": { "type": ["string", "number"], "minLength": 1 },
|
|
1289
|
+
"description": "Optional vue-router route params for a parameterised route; string values must be non-empty. Same contract as menuItem.params: part of the link, and the entry is active only while every declared param equals the current route's param."
|
|
1290
|
+
},
|
|
1269
1291
|
"order": { "type": "integer" },
|
|
1270
1292
|
"permission": { "type": "string" },
|
|
1271
1293
|
"section": {
|
|
@@ -5,6 +5,7 @@ import { genericError, networkError, parseResponseError } from '../utils/errors.
|
|
|
5
5
|
import { normalizeFacets } from '../utils/facets.js'
|
|
6
6
|
import { buildHeaders, buildQueryString, capitalize, prefixUrl } from '../utils/headers.js'
|
|
7
7
|
import { extractId } from '../utils/id.js'
|
|
8
|
+
import { dispatchObjectCreated } from '../utils/walkthroughSignals.js'
|
|
8
9
|
import { mergePluginActions, mergePluginGetters, mergePluginState } from './pluginMerge.js'
|
|
9
10
|
import { liveUpdatesPlugin } from './plugins/liveUpdates.js'
|
|
10
11
|
|
|
@@ -830,6 +831,13 @@ const baseActions = {
|
|
|
830
831
|
[type]: { ...(this.objects[type] || {}), [savedId]: data },
|
|
831
832
|
}
|
|
832
833
|
|
|
834
|
+
// Every create through the store lets an `advanceOn:
|
|
835
|
+
// object-created` walkthrough step advance, whichever form made it.
|
|
836
|
+
if (!isUpdate) {
|
|
837
|
+
const config = this.objectTypeRegistry[type] || {}
|
|
838
|
+
dispatchObjectCreated({ register: config.registerSlug || config.register, schema: config.schemaSlug || config.schema, object: data })
|
|
839
|
+
}
|
|
840
|
+
|
|
833
841
|
return data
|
|
834
842
|
} catch (error) {
|
|
835
843
|
this.errors = {
|