@conduction/nextcloud-vue 2.56.0-beta.3 → 2.56.0-beta.4

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.
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/dist/nextcloud-vue.cjs.js.map
3
- size: 33667612 bytes
4
- sha256: 99d23a886ff7c0e30fbe0745ed20fa6399710f26529d6b8495de7aa1f01e40a1
3
+ size: 33677319 bytes
4
+ sha256: 01032564aced4b648d5ee120b13ec9044a3664bce422f2588379b83ccab9bc63
@@ -23058,6 +23058,13 @@ a.cn-flow-runs-widget__row-content:hover .cn-flow-runs-widget__name[data-v-75628
23058
23058
  color: var(--color-main-text);
23059
23059
  }
23060
23060
 
23061
+ /* An on-demand step that did not run says so quietly: it is a choice the
23062
+ user did not make, not a failure. */
23063
+ .cn-setup-summary__item--not-run .cn-setup-summary__value[data-v-75b2078b] {
23064
+ font-weight: normal;
23065
+ color: var(--color-text-maxcontrast);
23066
+ }
23067
+
23061
23068
 
23062
23069
  .cn-admin-settings-shell[data-v-260aa222] {
23063
23070
  max-width: 900px;
package/l10n/en.json CHANGED
@@ -354,6 +354,7 @@
354
354
  "No widgets configured": "No widgets configured",
355
355
  "Not configured": "Not configured",
356
356
  "Not set": "Not set",
357
+ "Not run": "Not run",
357
358
  "Notes": "Notes",
358
359
  "Number": "Number",
359
360
  "Number configuration": "Number configuration",
package/l10n/nl.json CHANGED
@@ -354,6 +354,7 @@
354
354
  "No widgets configured": "Geen widgets geconfigureerd",
355
355
  "Not configured": "Niet geconfigureerd",
356
356
  "Not set": "Niet ingesteld",
357
+ "Not run": "Niet uitgevoerd",
357
358
  "Notes": "Notities",
358
359
  "Number": "Getal",
359
360
  "Number configuration": "Nummerconfiguratie",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@conduction/nextcloud-vue",
3
- "version": "2.56.0-beta.3",
3
+ "version": "2.56.0-beta.4",
4
4
  "description": "Shared Vue component library for Conduction Nextcloud apps — complements @nextcloud/vue with higher-level components, OpenRegister integration, and NL Design System support",
5
5
  "homepage": "https://github.com/ConductionNL/nextcloud-vue#readme",
6
6
  "bugs": {
@@ -487,9 +487,18 @@
487
487
  dismissed the walkthrough remounts and the first-visit tour
488
488
  starts (or resumes) then. `!== true` keeps apps that opted out
489
489
  of the support note (`cnSupportVisible` undefined) unaffected.
490
+
491
+ Withheld the same way while the setup status is still loading
492
+ and while the non-gating setup wizard is open
493
+ (`walkthroughHeldForSetup`). On a first run the wizard and the
494
+ first-visit tour both qualify; the tour used to open behind the
495
+ wizard, and its window-level ESC listener meant closing the
496
+ wizard with ESC also dismissed the tour and recorded it as seen.
497
+ Held back, the tour is never mounted, so nothing is recorded; it
498
+ starts when the wizard is dismissed or finished.
490
499
  -->
491
500
  <!-- @slot walkthrough Override the gating-free walkthrough overlay. Scope: { manifest, seenVersion }. -->
492
- <slot v-if="walkthroughEnabled && walkthroughSeenResolved && cnSupportVisible !== true"
501
+ <slot v-if="walkthroughEnabled && walkthroughSeenResolved && cnSupportVisible !== true && !walkthroughHeldForSetup"
493
502
  name="walkthrough"
494
503
  :manifest="manifest"
495
504
  :seenVersion="walkthroughSeenVersion">
@@ -2376,6 +2385,10 @@ export default {
2376
2385
  * Neither guard subsumes the other — (1) is about steps the server never
2377
2386
  * reports, (2) about steps it can never mark done — so both are needed.
2378
2387
  *
2388
+ * 3. On-demand steps (`onDemand: true`) are excluded too: they run only
2389
+ * when the user asks (learniq's "Remove the example data"), so they
2390
+ * are never outstanding work.
2391
+ *
2379
2392
  * @return {boolean} True when an actionable optional step is genuinely outstanding.
2380
2393
  */
2381
2394
  optionalSetupPending() {
@@ -2395,7 +2408,9 @@ export default {
2395
2408
  const outstanding = s.completed.value === true
2396
2409
  ? (s.optionalUnmetReported ? s.optionalUnmetReported.value : [])
2397
2410
  : s.optionalUnmet.value
2398
- return outstanding.some((st) => st.type !== 'info' && st.type !== 'summary')
2411
+ // On-demand steps (`onDemand: true`) run only when the user asks,
2412
+ // so they are never outstanding and never reason to open the wizard.
2413
+ return outstanding.some((st) => st.type !== 'info' && st.type !== 'summary' && st.onDemand !== true)
2399
2414
  },
2400
2415
 
2401
2416
  /**
@@ -2478,6 +2493,20 @@ export default {
2478
2493
  return (w && typeof w.completionConfigKey === 'string' && w.completionConfigKey) || ''
2479
2494
  },
2480
2495
 
2496
+ /**
2497
+ * Whether the setup flow holds the walkthrough back: the setup status
2498
+ * has not settled yet (an outstanding optional step may still open the
2499
+ * wizard), or the non-gating setup wizard is open. The gating setup
2500
+ * phase needs no check here, it replaces the shell (and the tour with
2501
+ * it) outright. Apps without a `setup` block settle immediately, so
2502
+ * this is `false` for them from the first render.
2503
+ *
2504
+ * @return {boolean} True while the tour must wait for setup.
2505
+ */
2506
+ walkthroughHeldForSetup() {
2507
+ return !this.setupStatusSettled || this.setupWizardOpen
2508
+ },
2509
+
2481
2510
  /**
2482
2511
  * The user's last-seen app version for walkthrough composition. Resolved
2483
2512
  * from the per-user `completionConfigKey` preference (cross-device) with
@@ -133,7 +133,7 @@
133
133
  v-for="item in summaryItems"
134
134
  :key="item.id"
135
135
  class="cn-setup-summary__item"
136
- :class="{ 'cn-setup-summary__item--done': item.done }">
136
+ :class="{ 'cn-setup-summary__item--done': item.done, 'cn-setup-summary__item--not-run': item.notRun }">
137
137
  <span class="cn-setup-summary__mark">{{ item.done ? '✓' : '○' }}</span>
138
138
  <span class="cn-setup-summary__label">{{ item.title }}</span>
139
139
  <span v-if="item.value" class="cn-setup-summary__value">{{ item.value }}</span>
@@ -380,7 +380,14 @@ export default {
380
380
  * a done marker (info steps always done; choice steps done when picked;
381
381
  * run-action steps done when the action succeeded).
382
382
  *
383
- * @return {Array<{ id: string, title: string, value: string, done: boolean }>}
383
+ * An on-demand step (`onDemand: true`) is the exception: it is done
384
+ * only when its action succeeded in THIS session. Apps report such a
385
+ * step as `done` on purpose so it never auto-runs (learniq's "Remove
386
+ * the example data"), and reading that flag here ticked a removal
387
+ * nobody ran. When it did not run it gets `notRun: true` and the value
388
+ * "Not run" instead.
389
+ *
390
+ * @return {Array<{ id: string, title: string, value: string, done: boolean, notRun: boolean }>}
384
391
  */
385
392
  summaryItems() {
386
393
  return this.setupSteps
@@ -399,6 +406,16 @@ export default {
399
406
  .map((f) => `${f.label}: ${this.configModel[f.key] !== null && this.configModel[f.key] !== undefined ? this.configModel[f.key] : ''}`)
400
407
  .join(', ')
401
408
  }
409
+ if (this.isOnDemand(step)) {
410
+ const ran = this.ranThisSession(step.id)
411
+ return {
412
+ id: step.id,
413
+ title: this.stepTitle(step),
414
+ value: ran ? '' : t('nextcloud-vue', 'Not run'),
415
+ done: ran,
416
+ notRun: !ran,
417
+ }
418
+ }
402
419
  let done
403
420
  if (step.type === 'info') {
404
421
  done = true
@@ -407,7 +424,7 @@ export default {
407
424
  } else {
408
425
  done = this.isStepDone(step.id)
409
426
  }
410
- return { id: step.id, title: this.stepTitle(step), value, done }
427
+ return { id: step.id, title: this.stepTitle(step), value, done, notRun: false }
411
428
  })
412
429
  },
413
430
 
@@ -427,7 +444,9 @@ export default {
427
444
  if (this.completedStepIds.length === 0) {
428
445
  return ''
429
446
  }
430
- const actionable = this.setupSteps.filter((s) => s.type !== 'info' && s.type !== 'summary')
447
+ // An on-demand step is never outstanding work, so it is never the
448
+ // step to resume on.
449
+ const actionable = this.setupSteps.filter((s) => s.type !== 'info' && s.type !== 'summary' && !this.isOnDemand(s))
431
450
  const firstUnmetIndex = actionable.findIndex((s) => {
432
451
  if (s.type === 'choice') {
433
452
  return !(this.hasChoice(s) || this.isServerDone(s.id))
@@ -459,14 +478,16 @@ export default {
459
478
  * the step has nothing else for the user to decide by then (the
460
479
  * choice it acts on was already made on an earlier step), so
461
480
  * requiring a click before showing progress just adds a stall.
462
- * No-ops for any other step type, or one already run/running.
481
+ * No-ops for any other step type, or one already run/running, and
482
+ * never fires an on-demand step (`onDemand: true`): those run only
483
+ * when the user clicks Run.
463
484
  *
464
485
  * @param {string} stepId The step id becoming current.
465
486
  * @return {void}
466
487
  */
467
488
  maybeAutoRunStep(stepId) {
468
489
  const step = this.setupSteps.find((s) => s.id === stepId)
469
- if (step && step.type === 'run-action' && !this.isStepDone(step.id) && !this.running[step.id]) {
490
+ if (step && step.type === 'run-action' && !this.isOnDemand(step) && !this.isStepDone(step.id) && !this.running[step.id]) {
470
491
  this.runAction(step)
471
492
  }
472
493
  },
@@ -847,6 +868,29 @@ export default {
847
868
  }
848
869
  },
849
870
 
871
+ /**
872
+ * Whether a step is marked on-demand (`onDemand: true`): it runs only
873
+ * when the user asks, never automatically, and the summary ticks it
874
+ * only when it ran in this session.
875
+ *
876
+ * @param {object} step The manifest step.
877
+ * @return {boolean}
878
+ */
879
+ isOnDemand(step) {
880
+ return !!step && step.onDemand === true
881
+ },
882
+
883
+ /**
884
+ * Whether a step's action succeeded in the CURRENT session, ignoring
885
+ * whatever the server reports.
886
+ *
887
+ * @param {string} id Step id.
888
+ * @return {boolean}
889
+ */
890
+ ranThisSession(id) {
891
+ return !!(this.actionResult[id] && this.actionResult[id].success)
892
+ },
893
+
850
894
  isStepDone(id) {
851
895
  return this.isServerDone(id) || this.localDone[id] === true || (this.actionResult[id] && this.actionResult[id].success)
852
896
  },
@@ -964,4 +1008,11 @@ export default {
964
1008
  font-weight: 600;
965
1009
  color: var(--color-main-text);
966
1010
  }
1011
+
1012
+ /* An on-demand step that did not run says so quietly: it is a choice the
1013
+ user did not make, not a failure. */
1014
+ .cn-setup-summary__item--not-run .cn-setup-summary__value {
1015
+ font-weight: normal;
1016
+ color: var(--color-text-maxcontrast);
1017
+ }
967
1018
  </style>
@@ -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.41.0",
6
+ "version": "2.42.0",
7
7
  "type": "object",
8
8
  "required": ["$schema", "version"],
9
9
  "allOf": [
@@ -98,6 +98,7 @@
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
100
  "action": { "type": "string", "description": "run-action: actionId POSTed to /api/setup/action/{action}." },
101
+ "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." },
101
102
  "healthCheck": { "type": "boolean", "default": false, "description": "summary: render a health recap." },
102
103
  "component": { "type": "string", "description": "component: app-registered component name (or use the #step-<id> slot)." }
103
104
  }