@conduction/nextcloud-vue 2.74.0 → 2.76.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.
Files changed (126) hide show
  1. package/dist/esm/components/CnAppNav/CnAppNav.vue2.js +19 -14
  2. package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
  3. package/dist/esm/components/CnAppNav/CnAppNav.vue3.js +2 -2
  4. package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
  5. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +77 -26
  6. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  7. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +22 -14
  8. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  9. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +23 -4
  10. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
  11. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
  12. package/dist/esm/components/CnBrandBar/CnBrandBar.vue.js +9 -0
  13. package/dist/esm/components/CnBrandBar/CnBrandBar.vue.js.map +1 -0
  14. package/dist/esm/components/CnBrandBar/CnBrandBar.vue2.js +107 -0
  15. package/dist/esm/components/CnBrandBar/CnBrandBar.vue2.js.map +1 -0
  16. package/dist/esm/components/CnBrandBar/CnBrandBar.vue3.js +79 -0
  17. package/dist/esm/components/CnBrandBar/CnBrandBar.vue3.js.map +1 -0
  18. package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js +6 -0
  19. package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js.map +1 -1
  20. package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js +3 -2
  21. package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js.map +1 -1
  22. package/dist/esm/components/CnCredentials/CnCredentials.vue2.js +11 -10
  23. package/dist/esm/components/CnCredentials/CnCredentials.vue2.js.map +1 -1
  24. package/dist/esm/components/CnCredentials/CnCredentials.vue3.js.map +1 -1
  25. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +8 -5
  26. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  27. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  28. package/dist/esm/components/CnEnvironmentBanner/CnEnvironmentBanner.vue2.js +4 -1
  29. package/dist/esm/components/CnEnvironmentBanner/CnEnvironmentBanner.vue2.js.map +1 -1
  30. package/dist/esm/components/CnEnvironmentBanner/CnEnvironmentBanner.vue3.js.map +1 -1
  31. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +7 -0
  32. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
  33. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +14 -7
  34. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
  35. package/dist/esm/components/CnFormPage/CnFormPage.vue2.js +32 -0
  36. package/dist/esm/components/CnFormPage/CnFormPage.vue2.js.map +1 -1
  37. package/dist/esm/components/CnFormPage/CnFormPage.vue3.js +6 -3
  38. package/dist/esm/components/CnFormPage/CnFormPage.vue3.js.map +1 -1
  39. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +144 -6
  40. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  41. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +14 -13
  42. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  43. package/dist/esm/components/CnIndexPage/selfModeActions.js +90 -14
  44. package/dist/esm/components/CnIndexPage/selfModeActions.js.map +1 -1
  45. package/dist/esm/components/CnIndexPage/useSelfFetchList.js +15 -3
  46. package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
  47. package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js +26 -0
  48. package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js.map +1 -1
  49. package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js +26 -9
  50. package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js.map +1 -1
  51. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +19 -3
  52. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  53. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  54. package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js +18 -2
  55. package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js.map +1 -1
  56. package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js +2 -2
  57. package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js.map +1 -1
  58. package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js +153 -38
  59. package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js.map +1 -1
  60. package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js +74 -56
  61. package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js.map +1 -1
  62. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js +16 -0
  63. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js.map +1 -1
  64. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue3.js +2 -2
  65. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue3.js.map +1 -1
  66. package/dist/esm/composables/useObjectLock.js +41 -10
  67. package/dist/esm/composables/useObjectLock.js.map +1 -1
  68. package/dist/esm/directives/cnSelectAria.js +55 -0
  69. package/dist/esm/directives/cnSelectAria.js.map +1 -0
  70. package/dist/esm/index.js +1 -0
  71. package/dist/esm/index.js.map +1 -1
  72. package/dist/esm/l10n/en.json.js +7 -1
  73. package/dist/esm/l10n/en.json.js.map +1 -1
  74. package/dist/esm/l10n/nl.json.js +8 -2
  75. package/dist/esm/l10n/nl.json.js.map +1 -1
  76. package/dist/esm/nextcloud-vue.css +154 -2
  77. package/dist/esm/store/useObjectStore.js +37 -9
  78. package/dist/esm/store/useObjectStore.js.map +1 -1
  79. package/dist/esm/utils/cnFetch.js +17 -2
  80. package/dist/esm/utils/cnFetch.js.map +1 -1
  81. package/dist/esm/utils/objectSignals.js +44 -0
  82. package/dist/esm/utils/objectSignals.js.map +1 -0
  83. package/dist/esm/utils/resolveBrand.js +38 -0
  84. package/dist/esm/utils/resolveBrand.js.map +1 -0
  85. package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
  86. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  87. package/dist/nextcloud-vue.cjs.js +9640 -8649
  88. package/dist/nextcloud-vue.cjs.js.map +2 -2
  89. package/dist/nextcloud-vue.css +154 -2
  90. package/l10n/en.json +7 -1
  91. package/l10n/nl.json +8 -2
  92. package/package.json +1 -1
  93. package/src/components/CnAppNav/CnAppNav.vue +21 -16
  94. package/src/components/CnAppRoot/CnAppRoot.vue +53 -0
  95. package/src/components/CnBannerWidget/CnBannerWidget.vue +23 -4
  96. package/src/components/CnBrandBar/CnBrandBar.vue +230 -0
  97. package/src/components/CnCardGrid/CnCardGrid.md +1 -0
  98. package/src/components/CnCardGrid/CnCardGrid.vue +7 -0
  99. package/src/components/CnCredentials/CnCredentials.vue +17 -16
  100. package/src/components/CnDetailPage/CnDetailPage.vue +8 -5
  101. package/src/components/CnEnvironmentBanner/CnEnvironmentBanner.vue +4 -1
  102. package/src/components/CnFormDialog/CnFormDialog.vue +10 -0
  103. package/src/components/CnFormPage/CnFormPage.vue +33 -0
  104. package/src/components/CnIndexPage/CnIndexPage.md +15 -0
  105. package/src/components/CnIndexPage/CnIndexPage.vue +157 -18
  106. package/src/components/CnIndexPage/selfModeActions.js +89 -13
  107. package/src/components/CnIndexPage/useSelfFetchList.js +15 -3
  108. package/src/components/CnObjectCard/CnObjectCard.md +1 -0
  109. package/src/components/CnObjectCard/CnObjectCard.vue +89 -1
  110. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +19 -3
  111. package/src/components/CnQuickFilterBar/CnQuickFilterBar.vue +20 -4
  112. package/src/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue +181 -38
  113. package/src/components/CnStatsBlock/CnStatsBlock.vue +18 -2
  114. package/src/composables/__tests__/useObjectLock.endpoints.spec.js +83 -0
  115. package/src/composables/useObjectLock.js +41 -10
  116. package/src/css/form-field.css +1 -1
  117. package/src/css/look-board-index.css +35 -1
  118. package/src/directives/cnSelectAria.js +54 -0
  119. package/src/index.js +1 -0
  120. package/src/schemas/app-manifest-v2.schema.json +6 -1
  121. package/src/store/useObjectStore.js +37 -9
  122. package/src/utils/cnFetch.js +16 -1
  123. package/src/utils/index.js +1 -0
  124. package/src/utils/objectSignals.js +41 -0
  125. package/src/utils/resolveBrand.js +37 -0
  126. package/src/utils/validateManifestV2.compiled.js +2 -2
@@ -31,6 +31,7 @@ import { openRowTarget } from '../../utils/linkNavigation.js';
31
31
  import { resolveClaimedTeams, splitViewsIntoTabs, viewAsTab, resolveClaimTokens, viewIdOf } from '../../utils/listLenses.js';
32
32
  import { LIST_SHORTCUTS, listPaletteCommands, shortcutFor } from '../../utils/listShortcuts.js';
33
33
  import { multiKeySort } from '../../utils/multiKeySort.js';
34
+ import { OBJECTS_CHANGED_EVENT } from '../../utils/objectSignals.js';
34
35
  import { withPersonalLenses } from '../../utils/personalLenses.js';
35
36
  import { resolveDeepTokens, resolveFilterValue } from '../../utils/resolveFilterTokens.js';
36
37
  import { resolveRowActions } from '../../utils/resolveRowActions.js';
@@ -79,7 +80,7 @@ import { buildDefaultActions } from './defaultActions.js';
79
80
  import { dispatchAction } from './manifestActionDispatch.js';
80
81
  import { applyManualOrder, manualOrderKey, moveInOrder, visibleIdsOf, dropInOrder } from './manualOrder.js';
81
82
  import { reconcilePersonalColumns, orderColumns, personalColumnsKey } from './personalColumns.js';
82
- import { createSelfModeActions } from './selfModeActions.js';
83
+ import { createSelfModeActions, resolveRowTarget } from './selfModeActions.js';
83
84
  import { applyRowPatches, splitLayoutFor, normalisePaneWidth, rowIdOf } from './splitView.js';
84
85
  import { useNamedSource } from './useNamedSource.js';
85
86
  import { useSelfFetchList } from './useSelfFetchList.js';
@@ -539,6 +540,17 @@ var script = {
539
540
  default: null,
540
541
  },
541
542
 
543
+ /**
544
+ * Gives each card in the card view a status accent: a colored start
545
+ * border and icon. See CnObjectCard `accent`.
546
+ *
547
+ * @type {((object: object) => ({variant: string, icon: string, label: string}|null))|null}
548
+ */
549
+ cardAccent: {
550
+ type: Function,
551
+ default: null,
552
+ },
553
+
542
554
  /**
543
555
  * Board look: free text after the footer's count ("8 of 48 · click a
544
556
  * column header to sort"). Manifest key `config.footerNote`.
@@ -710,6 +722,21 @@ var script = {
710
722
  default: () => [],
711
723
  },
712
724
 
725
+ /**
726
+ * Self-fetch only: list from this endpoint instead of
727
+ * `/api/objects/{register}/{schema}`, e.g. an app endpoint that searches
728
+ * several register/schema pairs at once. `register` and `schema` stay the
729
+ * page's own pair (columns, create, export, import). Rows of another pair,
730
+ * read from their `@self.register` / `@self.schema`, are edited, copied and
731
+ * deleted against that pair, with its own form. The endpoint takes
732
+ * `_page`, `_limit`, `_search` and `_order[key]=dir` and answers
733
+ * `{ results, total, page, pages }`.
734
+ */
735
+ collectionUrl: {
736
+ type: String,
737
+ default: '',
738
+ },
739
+
713
740
  /**
714
741
  * Offer an "Also search inside files" switch beside the search box. On,
715
742
  * a search also matches words inside attached files (OpenRegister
@@ -2217,6 +2244,8 @@ var script = {
2217
2244
  */
2218
2245
  persistedFilterKeys: [...(this.initialQueryFilterKeys || [])],
2219
2246
  internalSelectedIds: [...this.selectedIds],
2247
+ // Rows seen in a collectionUrl list, so a selection kept across pages still resolves its own pair.
2248
+ collectionRowsById: markRaw(new Map()),
2220
2249
  // Folder-sidebar state: selected folder id + the register-fetched list.
2221
2250
  selectedFolderId: null,
2222
2251
  /**
@@ -2254,6 +2283,9 @@ var script = {
2254
2283
  // Dialog targets
2255
2284
  actionTargetItem: null,
2256
2285
  editItem: null,
2286
+ // The pair and schema of a row edited outside the page's own pair (collectionUrl).
2287
+ rowFormTarget: null,
2288
+ rowFormSchema: null,
2257
2289
  // Drives the Actions-menu Refresh spinner during a self-fetch
2258
2290
  // refresh, where the host has no promise to bind `:refreshing` to.
2259
2291
  internalRefreshing: false,
@@ -3535,6 +3567,16 @@ var script = {
3535
3567
  return (this.schema && typeof this.schema === 'object') ? this.schema : null
3536
3568
  },
3537
3569
 
3570
+ /** The form dialog's schema: the edited row's own when it is of another pair. */
3571
+ formSchema() {
3572
+ return this.rowFormTarget ? this.rowFormSchema : this.effectiveSchema
3573
+ },
3574
+
3575
+ /** The form dialog's register, following `formSchema`. */
3576
+ formRegister() {
3577
+ return this.rowFormTarget ? this.rowFormTarget.register : this.register
3578
+ },
3579
+
3538
3580
  /**
3539
3581
  * Schema slug for the export-leaf URL — the `schema` prop directly
3540
3582
  * when it's a string (self-fetch mode's precondition), else the
@@ -3921,8 +3963,7 @@ var script = {
3921
3963
  this.$emit('edit-open', row);
3922
3964
  return
3923
3965
  }
3924
- this.editItem = row;
3925
- this.showFormDialogVisible = true;
3966
+ this.openFormFor(row);
3926
3967
  },
3927
3968
  onCopy: (row) => {
3928
3969
  this.actionTargetItem = row;
@@ -4431,6 +4472,21 @@ var script = {
4431
4472
  },
4432
4473
 
4433
4474
  watch: {
4475
+ effectiveObjects: {
4476
+ immediate: true,
4477
+ handler(rows) {
4478
+ if (!this.collectionUrl || !this.isSelfFetchMode || !Array.isArray(rows)) {
4479
+ return
4480
+ }
4481
+ for (const row of rows) {
4482
+ const id = row?.id ?? row?.['@self']?.id;
4483
+ if (id !== undefined && id !== null) {
4484
+ this.collectionRowsById.set(id, row);
4485
+ }
4486
+ }
4487
+ },
4488
+ },
4489
+
4434
4490
  // A column or form field bound to a property the schema lacks is told to the host once.
4435
4491
  effectiveSchema: {
4436
4492
  immediate: true,
@@ -4623,6 +4679,9 @@ var script = {
4623
4679
  if (this.splitViewEnabled && typeof window !== 'undefined') {
4624
4680
  window.addEventListener('resize', this.measureSplitViewport);
4625
4681
  }
4682
+ if (typeof window !== 'undefined') {
4683
+ window.addEventListener(OBJECTS_CHANGED_EVENT, this.onObjectsChanged);
4684
+ }
4626
4685
  this.loadManualOrder();
4627
4686
  this.loadPersonalColumns();
4628
4687
  this.publishHoistedSidebar();
@@ -4647,6 +4706,8 @@ var script = {
4647
4706
  this.selfActions = createSelfModeActions({
4648
4707
  isSelfFetchMode: () => this.isSelfFetchMode,
4649
4708
  selfObjectStore: () => this.selfObjectStore,
4709
+ rowTarget: (row) => this.rowTypeTarget(row),
4710
+ knownRow: (id) => this.collectionRowsById.get(id),
4650
4711
  selfObjectType: () => this.selfObjectType,
4651
4712
  list: () => this.list,
4652
4713
  selectedIds: () => this.internalSelectedIds,
@@ -4672,13 +4733,14 @@ var script = {
4672
4733
  },
4673
4734
 
4674
4735
  /**
4675
- * Drop the resize listener and the hoisted sidebar.
4736
+ * Drop the window listeners and the hoisted sidebar.
4676
4737
  *
4677
4738
  * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md
4678
4739
  */
4679
4740
  beforeUnmount() {
4680
4741
  if (typeof window !== 'undefined') {
4681
4742
  window.removeEventListener('resize', this.measureSplitViewport);
4743
+ window.removeEventListener(OBJECTS_CHANGED_EVENT, this.onObjectsChanged);
4682
4744
  }
4683
4745
  // Clear the holder so the hoisted sidebar disappears when
4684
4746
  // the user navigates away from the index page.
@@ -6140,6 +6202,33 @@ var script = {
6140
6202
  }
6141
6203
  },
6142
6204
 
6205
+ /**
6206
+ * Refresh the list when `dispatchObjectsChanged` names this page's
6207
+ * register and schema, by slug or id. A part missing on either side matches.
6208
+ *
6209
+ * @param {CustomEvent} event The objects-changed event.
6210
+ * @return {void}
6211
+ */
6212
+ onObjectsChanged(event) {
6213
+ // A collection list can hold rows of any pair, so any change may show in it.
6214
+ if (this.isSelfFetchMode && this.collectionUrl) {
6215
+ this.onRefreshEvent();
6216
+ return
6217
+ }
6218
+ const detail = (event && event.detail) || {};
6219
+ const schema = this.effectiveSchema;
6220
+ const schemaIds = [this.schema, schema && schema.id, schema && schema.slug]
6221
+ .filter((v) => v !== undefined && v !== null && v !== '' && typeof v !== 'object')
6222
+ .map(String);
6223
+ if (detail.register && this.register && detail.register !== String(this.register)) {
6224
+ return
6225
+ }
6226
+ if (detail.schema && schemaIds.length > 0 && !schemaIds.includes(detail.schema)) {
6227
+ return
6228
+ }
6229
+ this.onRefreshEvent();
6230
+ },
6231
+
6143
6232
  /** @return {Promise<void>} */
6144
6233
  async onRefreshEvent() {
6145
6234
  this.$emit('refresh');
@@ -7282,6 +7371,8 @@ var script = {
7282
7371
  closeFormDialog() {
7283
7372
  this.showFormDialogVisible = false;
7284
7373
  this.editItem = null;
7374
+ this.rowFormTarget = null;
7375
+ this.rowFormSchema = null;
7285
7376
  },
7286
7377
 
7287
7378
  /**
@@ -7342,8 +7433,55 @@ var script = {
7342
7433
  * @public
7343
7434
  */
7344
7435
  openFormDialog(item = null) {
7345
- this.editItem = item;
7346
- this.showFormDialogVisible = true;
7436
+ return this.openFormFor(item)
7437
+ },
7438
+
7439
+ /**
7440
+ * Open the form dialog for an item. A row of another pair (collectionUrl)
7441
+ * opens with its own schema; everything else opens at once, as before.
7442
+ *
7443
+ * @param {object|null} item The row to edit, or null to create.
7444
+ * @return {Promise<void>|void}
7445
+ */
7446
+ openFormFor(item) {
7447
+ const target = item ? this.rowTypeTarget(item) : null;
7448
+ if (!target) {
7449
+ this.rowFormTarget = null;
7450
+ this.rowFormSchema = null;
7451
+ this.editItem = item;
7452
+ this.showFormDialogVisible = true;
7453
+ return
7454
+ }
7455
+ const store = this.selfObjectStore;
7456
+ return Promise.resolve(store.getSchema?.(target.type) || store.fetchSchema?.(target.type))
7457
+ .catch(() => null)
7458
+ .then((schema) => {
7459
+ if (!schema) {
7460
+ this.toastSavedView('error', translate('nextcloud-vue', 'Could not load the form for this item.'));
7461
+ return
7462
+ }
7463
+ this.rowFormTarget = target;
7464
+ this.rowFormSchema = schema;
7465
+ this.editItem = item;
7466
+ this.showFormDialogVisible = true;
7467
+ })
7468
+ },
7469
+
7470
+ /**
7471
+ * The row's own pair when it differs from the page's in a collectionUrl list.
7472
+ *
7473
+ * @param {object} row The row.
7474
+ * @return {{register: string, schema: string, type: string}|null} The pair, or null.
7475
+ */
7476
+ rowTypeTarget(row) {
7477
+ return resolveRowTarget({
7478
+ collectionUrl: this.isSelfFetchMode ? this.collectionUrl : '',
7479
+ register: this.register,
7480
+ schema: this.schema,
7481
+ primarySchema: this.effectiveSchema,
7482
+ primaryRegister: this.selfObjectStore?.getRegister?.(this.selfObjectType) || null,
7483
+ store: this.selfObjectStore,
7484
+ }, row)
7347
7485
  },
7348
7486
 
7349
7487
  /**