@conduction/nextcloud-vue 2.76.0 → 2.78.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 (173) hide show
  1. package/dist/esm/components/CnAiCompanion/CnAiCompanion.vue2.js +23 -0
  2. package/dist/esm/components/CnAiCompanion/CnAiCompanion.vue2.js.map +1 -1
  3. package/dist/esm/components/CnAiCompanion/CnAiCompanion.vue3.js.map +1 -1
  4. package/dist/esm/components/CnAppNav/CnAppNav.vue2.js +18 -3
  5. package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
  6. package/dist/esm/components/CnAppNav/CnAppNav.vue3.js +49 -3
  7. package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
  8. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js +2 -1
  9. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js.map +1 -1
  10. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js.map +1 -1
  11. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +79 -1
  12. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  13. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +229 -203
  14. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  15. package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue.js +9 -0
  16. package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue.js.map +1 -0
  17. package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue2.js +50 -0
  18. package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue2.js.map +1 -0
  19. package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue3.js +13 -0
  20. package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue3.js.map +1 -0
  21. package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +37 -0
  22. package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
  23. package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js +2 -2
  24. package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
  25. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +29 -4
  26. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  27. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  28. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +48 -6
  29. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  30. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +90 -51
  31. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  32. package/dist/esm/components/CnDateRangePicker/CnDateRangePicker.vue.js +1 -1
  33. package/dist/esm/components/CnDateRangePicker/CnDateRangePicker.vue2.js +45 -2
  34. package/dist/esm/components/CnDateRangePicker/CnDateRangePicker.vue2.js.map +1 -1
  35. package/dist/esm/components/CnDateRangePicker/CnDateRangePicker.vue3.js.map +1 -1
  36. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +16 -28
  37. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  38. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +12 -24
  39. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  40. package/dist/esm/components/CnFavouriteToggle/CnFavouriteToggle.vue2.js +7 -2
  41. package/dist/esm/components/CnFavouriteToggle/CnFavouriteToggle.vue2.js.map +1 -1
  42. package/dist/esm/components/CnFavouriteToggle/CnFavouriteToggle.vue3.js.map +1 -1
  43. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +114 -1
  44. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  45. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +115 -62
  46. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  47. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js +89 -7
  48. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js.map +1 -1
  49. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue3.js +62 -30
  50. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue3.js.map +1 -1
  51. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +7 -1
  52. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
  53. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
  54. package/dist/esm/components/CnFormPage/CnFormPage.vue2.js +4 -1
  55. package/dist/esm/components/CnFormPage/CnFormPage.vue2.js.map +1 -1
  56. package/dist/esm/components/CnFormPage/CnFormPage.vue3.js.map +1 -1
  57. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +104 -13
  58. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  59. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +13 -9
  60. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  61. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js +199 -7
  62. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js.map +1 -1
  63. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js +155 -119
  64. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js.map +1 -1
  65. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +6 -0
  66. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
  67. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +4 -1
  68. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
  69. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +36 -0
  70. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
  71. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +35 -23
  72. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
  73. package/dist/esm/components/CnStatusBadge/CnStatusBadge.vue2.js +6 -2
  74. package/dist/esm/components/CnStatusBadge/CnStatusBadge.vue2.js.map +1 -1
  75. package/dist/esm/components/CnStatusBadge/CnStatusBadge.vue3.js.map +1 -1
  76. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +13 -0
  77. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  78. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  79. package/dist/esm/composables/useFormDraft.js +11 -1
  80. package/dist/esm/composables/useFormDraft.js.map +1 -1
  81. package/dist/esm/composables/useListView.js +4 -0
  82. package/dist/esm/composables/useListView.js.map +1 -1
  83. package/dist/esm/composables/useObjectPresence.js +15 -4
  84. package/dist/esm/composables/useObjectPresence.js.map +1 -1
  85. package/dist/esm/index.js +2 -1
  86. package/dist/esm/index.js.map +1 -1
  87. package/dist/esm/l10n/en.json.js +32 -1
  88. package/dist/esm/l10n/en.json.js.map +1 -1
  89. package/dist/esm/l10n/nl.json.js +32 -1
  90. package/dist/esm/l10n/nl.json.js.map +1 -1
  91. package/dist/esm/nextcloud-vue.css +500 -75
  92. package/dist/esm/store/plugins/interactions.js +20 -10
  93. package/dist/esm/store/plugins/interactions.js.map +1 -1
  94. package/dist/esm/store/useObjectStore.js +17 -0
  95. package/dist/esm/store/useObjectStore.js.map +1 -1
  96. package/dist/esm/utils/badgeVariants.js +32 -0
  97. package/dist/esm/utils/badgeVariants.js.map +1 -0
  98. package/dist/esm/utils/builtInFormatters.js +15 -7
  99. package/dist/esm/utils/builtInFormatters.js.map +1 -1
  100. package/dist/esm/utils/groupAutocomplete.js +63 -1
  101. package/dist/esm/utils/groupAutocomplete.js.map +1 -1
  102. package/dist/esm/utils/lensAvailability.js +90 -0
  103. package/dist/esm/utils/lensAvailability.js.map +1 -0
  104. package/dist/esm/utils/personalLenses.js +13 -6
  105. package/dist/esm/utils/personalLenses.js.map +1 -1
  106. package/dist/esm/utils/recordInteractions.js +31 -13
  107. package/dist/esm/utils/recordInteractions.js.map +1 -1
  108. package/dist/esm/utils/resolveFilterTokens.js +46 -3
  109. package/dist/esm/utils/resolveFilterTokens.js.map +1 -1
  110. package/dist/esm/utils/schema.js +1 -1
  111. package/dist/esm/utils/schema.js.map +1 -1
  112. package/dist/esm/utils/sentinelTokens.js +4 -4
  113. package/dist/esm/utils/sentinelTokens.js.map +1 -1
  114. package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
  115. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  116. package/dist/esm/utils/widgetVisibility.js +46 -1
  117. package/dist/esm/utils/widgetVisibility.js.map +1 -1
  118. package/dist/nextcloud-vue.cjs.js +4389 -2890
  119. package/dist/nextcloud-vue.cjs.js.map +2 -2
  120. package/dist/nextcloud-vue.css +500 -75
  121. package/l10n/en.json +32 -1
  122. package/l10n/nl.json +32 -1
  123. package/package.json +1 -1
  124. package/src/components/CnAiCompanion/CnAiCompanion.vue +23 -0
  125. package/src/components/CnAppNav/CnAppNav.vue +44 -5
  126. package/src/components/CnBoardView/CnBoardView.vue +2 -1
  127. package/src/components/CnCellRenderer/CnCellRenderer.md +1 -0
  128. package/src/components/CnCellRenderer/CnCellRenderer.vue +106 -9
  129. package/src/components/CnCellRenderer/CnGroupNameCell.vue +61 -0
  130. package/src/components/CnChartWidget/CnChartWidget.vue +39 -2
  131. package/src/components/CnDashboardPage/CnDashboardPage.vue +29 -4
  132. package/src/components/CnDataTable/CnDataTable.md +9 -0
  133. package/src/components/CnDataTable/CnDataTable.vue +87 -22
  134. package/src/components/CnDateRangePicker/CnDateRangePicker.vue +44 -1
  135. package/src/components/CnDetailPage/CnDetailPage.vue +10 -27
  136. package/src/components/CnFavouriteToggle/CnFavouriteToggle.vue +7 -2
  137. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +204 -5
  138. package/src/components/CnFollowToggle/CnFollowToggle.vue +118 -13
  139. package/src/components/CnFormDialog/CnFormDialog.vue +7 -1
  140. package/src/components/CnFormPage/CnFormPage.vue +4 -1
  141. package/src/components/CnIndexPage/CnIndexPage.md +36 -0
  142. package/src/components/CnIndexPage/CnIndexPage.vue +112 -19
  143. package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +226 -2
  144. package/src/components/CnObjectSidebar/CnFilesTab.vue +9 -0
  145. package/src/components/CnStatWidget/CnStatWidget.vue +52 -2
  146. package/src/components/CnStatusBadge/CnStatusBadge.vue +6 -2
  147. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +13 -0
  148. package/src/composables/__tests__/useObjectPresence.spec.js +24 -0
  149. package/src/composables/useFormDraft.js +11 -1
  150. package/src/composables/useListView.js +4 -0
  151. package/src/composables/useObjectPresence.js +15 -4
  152. package/src/css/badge.css +31 -0
  153. package/src/css/kpi-card.css +51 -0
  154. package/src/css/look-board-detail.css +40 -2
  155. package/src/css/look-board-index.css +36 -0
  156. package/src/css/look-board.css +8 -0
  157. package/src/css/table.css +82 -17
  158. package/src/index.js +2 -1
  159. package/src/schemas/app-manifest-v2.schema.json +15 -11
  160. package/src/store/plugins/interactions.js +20 -10
  161. package/src/store/useObjectStore.js +17 -0
  162. package/src/utils/badgeVariants.js +29 -0
  163. package/src/utils/builtInFormatters.js +15 -7
  164. package/src/utils/groupAutocomplete.js +75 -0
  165. package/src/utils/index.js +1 -1
  166. package/src/utils/lensAvailability.js +86 -0
  167. package/src/utils/personalLenses.js +13 -6
  168. package/src/utils/recordInteractions.js +31 -13
  169. package/src/utils/resolveFilterTokens.js +45 -2
  170. package/src/utils/schema.js +1 -1
  171. package/src/utils/sentinelTokens.js +4 -4
  172. package/src/utils/validateManifestV2.compiled.js +2 -2
  173. package/src/utils/widgetVisibility.js +45 -0
@@ -3,7 +3,8 @@ import { setFavourite, setReadState, setWatching, listWatchers, setWatcher } fro
3
3
  /**
4
4
  * Interactions plugin for the object store.
5
5
  *
6
- * Per-user interaction calls on a record: favourite, follow (watch) and the
6
+ * Per-user interaction calls on a record: follow (watch, with its
7
+ * notifications switch), the deprecated favourite (a quiet follow), and the
7
8
  * followers list. Each write puts the server's answer into the stored object's
8
9
  * `@self`, so a list showing the same object agrees with the toggle.
9
10
  *
@@ -55,7 +56,10 @@ function interactionsPlugin() {
55
56
  },
56
57
 
57
58
  /**
58
- * Star a record.
59
+ * Star a record: a quiet follow on the server.
60
+ *
61
+ * @deprecated A favourite is a follow with notifications off since
62
+ * OpenRegister's `merge-follow-and-favourites`; use `watch(type, id, { notify: false })`.
59
63
  *
60
64
  * @param {string} type The registered object type slug
61
65
  * @param {string} objectId The object ID
@@ -65,13 +69,15 @@ function interactionsPlugin() {
65
69
  const { register, schema } = this._interactionTarget(type);
66
70
  const result = await setFavourite(register, schema, objectId, true);
67
71
  if (result.ok) {
68
- this._patchSelf(type, objectId, { favourite: true });
72
+ this._patchSelf(type, objectId, { favourite: true, watching: true });
69
73
  }
70
74
  return result
71
75
  },
72
76
 
73
77
  /**
74
- * Unstar a record.
78
+ * Unstar a record: unfollow it.
79
+ *
80
+ * @deprecated Use `unwatch`.
75
81
  *
76
82
  * @param {string} type The registered object type slug
77
83
  * @param {string} objectId The object ID
@@ -81,7 +87,7 @@ function interactionsPlugin() {
81
87
  const { register, schema } = this._interactionTarget(type);
82
88
  const result = await setFavourite(register, schema, objectId, false);
83
89
  if (result.ok) {
84
- this._patchSelf(type, objectId, { favourite: false });
90
+ this._patchSelf(type, objectId, { favourite: false, watching: false, watchNotify: undefined });
85
91
  }
86
92
  return result
87
93
  },
@@ -119,17 +125,21 @@ function interactionsPlugin() {
119
125
  },
120
126
 
121
127
  /**
122
- * Follow a record.
128
+ * Follow a record, optionally setting its notifications switch.
123
129
  *
124
130
  * @param {string} type The registered object type slug
125
131
  * @param {string} objectId The object ID
132
+ * @param {object} [options] Options
133
+ * @param {boolean} [options.notify] The notifications switch; left out, a new follow notifies
126
134
  * @return {Promise<object>} The outcome
135
+ * @spec openspec/changes/one-follow-control/specs/record-follow/spec.md#requirement-one-follow-control-with-a-notifications-switch
127
136
  */
128
- async watch(type, objectId) {
137
+ async watch(type, objectId, options = {}) {
129
138
  const { register, schema } = this._interactionTarget(type);
130
- const result = await setWatching(register, schema, objectId, true);
139
+ const result = await setWatching(register, schema, objectId, true, options);
131
140
  if (result.ok) {
132
- this._patchSelf(type, objectId, { watching: true });
141
+ const notify = result.data && typeof result.data.notify === 'boolean' ? result.data.notify : true;
142
+ this._patchSelf(type, objectId, { watching: true, favourite: true, watchNotify: notify });
133
143
  }
134
144
  return result
135
145
  },
@@ -145,7 +155,7 @@ function interactionsPlugin() {
145
155
  const { register, schema } = this._interactionTarget(type);
146
156
  const result = await setWatching(register, schema, objectId, false);
147
157
  if (result.ok) {
148
- this._patchSelf(type, objectId, { watching: false });
158
+ this._patchSelf(type, objectId, { watching: false, favourite: false, watchNotify: undefined });
149
159
  }
150
160
  return result
151
161
  },
@@ -1 +1 @@
1
- {"version":3,"file":"interactions.js","sources":["../../../../src/store/plugins/interactions.js"],"sourcesContent":["import { listWatchers, setFavourite, setReadState, setWatcher, setWatching } from '../../utils/recordInteractions.js'\n\n/**\n * Interactions plugin for the object store.\n *\n * Per-user interaction calls on a record: favourite, follow (watch) and the\n * followers list. Each write puts the server's answer into the stored object's\n * `@self`, so a list showing the same object agrees with the toggle.\n *\n * Actions: favourite, unfavourite, watch, unwatch, fetchWatchers, addWatcher, removeWatcher, markRead, markUnread.\n * Each returns the outcome `{ ok, status, data, message }` and never throws.\n *\n * @return {object} The plugin definition (name, state, getters, actions)\n *\n * @example\n * const useStore = createObjectStore('object', { plugins: [interactionsPlugin()] })\n * const store = useStore()\n * await store.watch('case', caseId)\n * const { data } = await store.fetchWatchers('case', caseId)\n */\nexport function interactionsPlugin() {\n\treturn {\n\t\tname: 'Interactions',\n\n\t\tstate: () => ({}),\n\n\t\tgetters: {},\n\n\t\tactions: {\n\t\t\t/**\n\t\t\t * Merge a patch into the stored object's `@self`.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @param {object} patch Keys to merge into `@self`\n\t\t\t */\n\t\t\t_patchSelf(type, objectId, patch) {\n\t\t\t\tconst stored = this.objects && this.objects[type] && this.objects[type][objectId]\n\t\t\t\tif (!stored) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst next = { ...stored, '@self': { ...(stored['@self'] || {}), ...patch } }\n\t\t\t\tthis.objects = { ...this.objects, [type]: { ...this.objects[type], [objectId]: next } }\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Resolve a type slug to its register and schema.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @return {{register: string, schema: string}} The path segments\n\t\t\t */\n\t\t\t_interactionTarget(type) {\n\t\t\t\tconst config = this._getTypeConfig(type)\n\t\t\t\treturn { register: config.register, schema: config.schema }\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Star a record.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync favourite(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setFavourite(register, schema, objectId, true)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { favourite: true })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Unstar a record.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync unfavourite(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setFavourite(register, schema, objectId, false)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { favourite: false })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Mark a record read (`PUT .../read-state`).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync markRead(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setReadState(register, schema, objectId, true)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { unread: false })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Mark a record unread (`DELETE .../read-state`).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync markUnread(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setReadState(register, schema, objectId, false)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { unread: true })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Follow a record.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync watch(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setWatching(register, schema, objectId, true)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { watching: true })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Unfollow a record.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync unwatch(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setWatching(register, schema, objectId, false)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { watching: false })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * List the followers of a record (needs `update` on it).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome; `data` is `{ results, total }`\n\t\t\t */\n\t\t\tasync fetchWatchers(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\treturn listWatchers(register, schema, objectId)\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Add a colleague as a follower (needs `manage`).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @param {string} userId The colleague's user id\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync addWatcher(type, objectId, userId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\treturn setWatcher(register, schema, objectId, userId, true)\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Remove a follower (needs `manage`, or be the user yourself).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @param {string} userId The follower's user id\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync removeWatcher(type, objectId, userId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\treturn setWatcher(register, schema, objectId, userId, false)\n\t\t\t},\n\t\t},\n\t}\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"interactions.js","sources":["../../../../src/store/plugins/interactions.js"],"sourcesContent":["import { listWatchers, setFavourite, setReadState, setWatcher, setWatching } from '../../utils/recordInteractions.js'\n\n/**\n * Interactions plugin for the object store.\n *\n * Per-user interaction calls on a record: follow (watch, with its\n * notifications switch), the deprecated favourite (a quiet follow), and the\n * followers list. Each write puts the server's answer into the stored object's\n * `@self`, so a list showing the same object agrees with the toggle.\n *\n * Actions: favourite, unfavourite, watch, unwatch, fetchWatchers, addWatcher, removeWatcher, markRead, markUnread.\n * Each returns the outcome `{ ok, status, data, message }` and never throws.\n *\n * @return {object} The plugin definition (name, state, getters, actions)\n *\n * @example\n * const useStore = createObjectStore('object', { plugins: [interactionsPlugin()] })\n * const store = useStore()\n * await store.watch('case', caseId)\n * const { data } = await store.fetchWatchers('case', caseId)\n */\nexport function interactionsPlugin() {\n\treturn {\n\t\tname: 'Interactions',\n\n\t\tstate: () => ({}),\n\n\t\tgetters: {},\n\n\t\tactions: {\n\t\t\t/**\n\t\t\t * Merge a patch into the stored object's `@self`.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @param {object} patch Keys to merge into `@self`\n\t\t\t */\n\t\t\t_patchSelf(type, objectId, patch) {\n\t\t\t\tconst stored = this.objects && this.objects[type] && this.objects[type][objectId]\n\t\t\t\tif (!stored) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst next = { ...stored, '@self': { ...(stored['@self'] || {}), ...patch } }\n\t\t\t\tthis.objects = { ...this.objects, [type]: { ...this.objects[type], [objectId]: next } }\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Resolve a type slug to its register and schema.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @return {{register: string, schema: string}} The path segments\n\t\t\t */\n\t\t\t_interactionTarget(type) {\n\t\t\t\tconst config = this._getTypeConfig(type)\n\t\t\t\treturn { register: config.register, schema: config.schema }\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Star a record: a quiet follow on the server.\n\t\t\t *\n\t\t\t * @deprecated A favourite is a follow with notifications off since\n\t\t\t * OpenRegister's `merge-follow-and-favourites`; use `watch(type, id, { notify: false })`.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync favourite(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setFavourite(register, schema, objectId, true)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { favourite: true, watching: true })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Unstar a record: unfollow it.\n\t\t\t *\n\t\t\t * @deprecated Use `unwatch`.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync unfavourite(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setFavourite(register, schema, objectId, false)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { favourite: false, watching: false, watchNotify: undefined })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Mark a record read (`PUT .../read-state`).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync markRead(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setReadState(register, schema, objectId, true)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { unread: false })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Mark a record unread (`DELETE .../read-state`).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync markUnread(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setReadState(register, schema, objectId, false)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { unread: true })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Follow a record, optionally setting its notifications switch.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @param {object} [options] Options\n\t\t\t * @param {boolean} [options.notify] The notifications switch; left out, a new follow notifies\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t * @spec openspec/changes/one-follow-control/specs/record-follow/spec.md#requirement-one-follow-control-with-a-notifications-switch\n\t\t\t */\n\t\t\tasync watch(type, objectId, options = {}) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setWatching(register, schema, objectId, true, options)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tconst notify = result.data && typeof result.data.notify === 'boolean' ? result.data.notify : true\n\t\t\t\t\tthis._patchSelf(type, objectId, { watching: true, favourite: true, watchNotify: notify })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Unfollow a record.\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync unwatch(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\tconst result = await setWatching(register, schema, objectId, false)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\tthis._patchSelf(type, objectId, { watching: false, favourite: false, watchNotify: undefined })\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * List the followers of a record (needs `update` on it).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @return {Promise<object>} The outcome; `data` is `{ results, total }`\n\t\t\t */\n\t\t\tasync fetchWatchers(type, objectId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\treturn listWatchers(register, schema, objectId)\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Add a colleague as a follower (needs `manage`).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @param {string} userId The colleague's user id\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync addWatcher(type, objectId, userId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\treturn setWatcher(register, schema, objectId, userId, true)\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Remove a follower (needs `manage`, or be the user yourself).\n\t\t\t *\n\t\t\t * @param {string} type The registered object type slug\n\t\t\t * @param {string} objectId The object ID\n\t\t\t * @param {string} userId The follower's user id\n\t\t\t * @return {Promise<object>} The outcome\n\t\t\t */\n\t\t\tasync removeWatcher(type, objectId, userId) {\n\t\t\t\tconst { register, schema } = this._interactionTarget(type)\n\t\t\t\treturn setWatcher(register, schema, objectId, userId, false)\n\t\t\t},\n\t\t},\n\t}\n}\n"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ import { parseResponseError, networkError, genericError } from '../utils/errors.
6
6
  import { normalizeFacets } from '../utils/facets.js';
7
7
  import { prefixUrl, capitalize, buildHeaders, buildQueryString } from '../utils/headers.js';
8
8
  import { extractId } from '../utils/id.js';
9
+ import { readLensReports } from '../utils/lensAvailability.js';
9
10
  import { dispatchObjectCreated } from '../utils/walkthroughSignals.js';
10
11
  import { mergePluginState, mergePluginGetters, mergePluginActions } from './pluginMerge.js';
11
12
  import { liveUpdatesPlugin } from './plugins/liveUpdates.js';
@@ -86,6 +87,16 @@ function baseState(baseUrl = DEFAULT_BASE_URL) {
86
87
  * @type {{string: object}}
87
88
  */
88
89
  facets: {},
90
+ /**
91
+ * Personal-lens reports of the latest collection response per type:
92
+ * the body's `@self.lenses` (`{ recent: { available, reason } }`),
93
+ * `{}` when it carried none. Written with the rows, so it always
94
+ * describes the page on screen.
95
+ *
96
+ * @type {{string: object}}
97
+ * @spec openspec/changes/lens-says-why-it-is-empty/specs/personal-lens-availability/spec.md#requirement-a-list-response-carries-the-report-of-the-lenses-it-was-asked-for
98
+ */
99
+ lenses: {},
89
100
  /** @type {{baseUrl: string, organisationUuidGetter: (() => string|null)|null, languageGetter: (() => string|null)|null, targetLanguageGetter: (() => string|null)|null}} */
90
101
  _options: {
91
102
  baseUrl: prefixedBaseUrl,
@@ -195,6 +206,7 @@ const baseGetters = {
195
206
  * @return {(type: string) => object}
196
207
  */
197
208
  getFacets: (state) => (type) => state.facets[type] || {},
209
+ getLenses: (state) => (type) => state.lenses[type] || {},
198
210
  };
199
211
 
200
212
  // ── Base actions ────────────────────────────────────────────────────────
@@ -265,6 +277,7 @@ const baseActions = {
265
277
  this.schemas = { ...this.schemas, [slug]: null };
266
278
  this.registers = { ...this.registers, [slug]: null };
267
279
  this.facets = { ...this.facets, [slug]: {} };
280
+ this.lenses = { ...this.lenses, [slug]: {} };
268
281
  },
269
282
 
270
283
  /**
@@ -308,6 +321,7 @@ const baseActions = {
308
321
  this.schemas = omit(this.schemas, slug);
309
322
  this.registers = omit(this.registers, slug);
310
323
  this.facets = omit(this.facets, slug);
324
+ this.lenses = omit(this.lenses, slug);
311
325
  },
312
326
 
313
327
  /**
@@ -441,6 +455,7 @@ const baseActions = {
441
455
  this.collections = {};
442
456
  this.objects = {};
443
457
  this.facets = {};
458
+ this.lenses = {};
444
459
  this.pagination = {};
445
460
  // Errors + loading flags are per-fetch and don't need a reset.
446
461
  },
@@ -737,6 +752,8 @@ const baseActions = {
737
752
  const results = data.results || data;
738
753
 
739
754
  this.collections = { ...this.collections, [type]: results };
755
+ // Why a personal lens came back empty, if it says (openregister#4514).
756
+ this.lenses = { ...this.lenses, [type]: readLensReports(data) };
740
757
  this.pagination = {
741
758
  ...this.pagination,
742
759
  [type]: {