@conduction/nextcloud-vue 2.138.0 → 2.139.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 (46) hide show
  1. package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
  2. package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
  3. package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
  4. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
  5. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
  6. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
  7. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
  8. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  9. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  10. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +99 -4
  11. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  12. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +2 -2
  13. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  14. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js +2 -0
  15. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
  16. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js +13 -2
  17. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
  18. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue.js +1 -1
  19. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +1 -1
  20. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  21. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  22. package/dist/esm/composables/indexSources.js +43 -4
  23. package/dist/esm/composables/indexSources.js.map +1 -1
  24. package/dist/esm/l10n/en.json.js +3 -1
  25. package/dist/esm/l10n/en.json.js.map +1 -1
  26. package/dist/esm/l10n/nl.json.js +3 -1
  27. package/dist/esm/l10n/nl.json.js.map +1 -1
  28. package/dist/esm/library-style.js +1 -1
  29. package/dist/esm/nextcloud-vue.css +340 -238
  30. package/dist/nextcloud-vue.cjs.js +166 -19
  31. package/dist/nextcloud-vue.cjs.js.map +2 -2
  32. package/dist/nextcloud-vue.css +340 -238
  33. package/l10n/en.json +3 -1
  34. package/l10n/nl.json +3 -1
  35. package/package.json +1 -1
  36. package/src/components/CnChartWidget/CnChartWidget.vue +4 -0
  37. package/src/components/CnFactsWidget/CnFactsWidget.vue +6 -4
  38. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +11 -0
  39. package/src/components/CnIndexPage/CnIndexPage.vue +101 -6
  40. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +10 -2
  41. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +1 -1
  42. package/src/composables/indexSources.js +43 -4
  43. package/src/css/dialog.css +18 -0
  44. package/src/css/look-board-detail.css +24 -0
  45. package/src/css/look-board-index.css +21 -0
  46. package/src/css/look-board.css +21 -0
@@ -1,9 +1,11 @@
1
1
  import { translate, getCanonicalLocale } from '@nextcloud/l10n';
2
2
  import { generateUrl, generateOcsUrl } from '@nextcloud/router';
3
3
  import { reactive } from 'vue';
4
+ import AccountOutline from 'vue-material-design-icons/AccountOutline.vue';
4
5
  import CalendarClock from 'vue-material-design-icons/CalendarClock.vue';
5
6
  import Cancel from 'vue-material-design-icons/Cancel.vue';
6
7
  import Check from 'vue-material-design-icons/Check.vue';
8
+ import EmailOutline from 'vue-material-design-icons/EmailOutline.vue';
7
9
  import HandBackRight from 'vue-material-design-icons/HandBackRight.vue';
8
10
  import LightningBolt from 'vue-material-design-icons/LightningBolt.vue';
9
11
  import Pencil from 'vue-material-design-icons/Pencil.vue';
@@ -14,6 +16,7 @@ import { fillTemplate } from '../utils/fillTemplate.js';
14
16
  import { flowRunStatuses, FLOW_RUN_ERROR_STATUSES } from '../utils/flowRunStatus.js';
15
17
  import { fetchUsers, fetchGroupMembers, fetchStatuses, fetchPresence } from '../utils/nextcloudDirectory.js';
16
18
  import { readPath } from '../utils/readPath.js';
19
+ import { resolveNextcloudUser } from '../utils/userAutocomplete.js';
17
20
  import { useFlowStore } from './useFlowStore.js';
18
21
  import { useOrganisationStore, organisationRecord } from './useOrganisationStore.js';
19
22
  import { useTaskInboxStore } from './useTaskInboxStore.js';
@@ -1089,7 +1092,7 @@ function fillRowTemplate(template, row) {
1089
1092
  * and its count (DqZoekresultaten).
1090
1093
  *
1091
1094
  * `sourceConfig.kinds` lists what is searched:
1092
- * `{ id, label, register, schema, titleField?, subtitleField?, subtitleTemplate?, statusField?, statusResolve?, linkedField?, linkedTemplate?, href?, limit? }`
1095
+ * `{ id, label, register, schema, titleField?, subtitleField?, subtitleTemplate?, statusField?, statusResolve?, linkedField?, linkedTemplate?, linkedUser?, href?, limit? }`
1093
1096
  * for objects (OpenRegister's `_search`, so the reader sees what they may
1094
1097
  * read), or `{ id, label, files: true, limit? }` for the reader's files
1095
1098
  * (Nextcloud's unified search). The term is `sourceConfig.term`, else the
@@ -1105,6 +1108,8 @@ function fillRowTemplate(template, row) {
1105
1108
  * column, drawn when a kind declares one; `sourceConfig.linkedLabel` names it.
1106
1109
  * `subtitleTemplate` ("Case {identifier}", translated) fills the line under a
1107
1110
  * result, else `subtitleField`.
1111
+ * `linkedUser: true` reads that value as a user id and shows the user's
1112
+ * display name. `sourceConfig.columnWidths` sets a width per column key.
1108
1113
  * The page's title and count line can name the term as `{term}`, and the
1109
1114
  * count is the active kind's total. Kind, link and status are filterable.
1110
1115
  *
@@ -1114,6 +1119,23 @@ function fillRowTemplate(template, row) {
1114
1119
  * @return {object} The source adapter.
1115
1120
  * @spec openspec/changes/index-search-source/specs/index-page/spec.md#requirement-an-index-page-can-search-several-schemas-and-files
1116
1121
  */
1122
+ /**
1123
+ * Columns with the widths a page names per column key
1124
+ * (`sourceConfig.columnWidths`, `{ title: '250px' }`); a column it does not
1125
+ * name keeps none.
1126
+ *
1127
+ * @param {Array<object>} columns The columns.
1128
+ * @param {object|undefined} widths The widths by key.
1129
+ * @return {Array<object>} The columns.
1130
+ * @spec openspec/changes/search-linked-user-and-widths/specs/search-linked-user-and-widths/spec.md
1131
+ */
1132
+ function withColumnWidths(columns, widths) {
1133
+ if (!widths || typeof widths !== 'object') {
1134
+ return columns
1135
+ }
1136
+ return columns.map((col) => (typeof widths[col.key] === 'string' && widths[col.key] !== '' ? { ...col, width: widths[col.key] } : col))
1137
+ }
1138
+
1117
1139
  function searchSource(config = {}, context = {}) {
1118
1140
  const translate$1 = typeof context.translate === 'function' ? context.translate : (text) => text;
1119
1141
  const kinds = (Array.isArray(config && config.kinds) ? config.kinds : [])
@@ -1209,12 +1231,20 @@ function searchSource(config = {}, context = {}) {
1209
1231
  return kind.subtitleField ? String(readPath(object, kind.subtitleField) ?? '') : ''
1210
1232
  };
1211
1233
 
1234
+ // `linkedUser`: the Linked cell holds a user id; name the user instead.
1235
+ const linkedUserNames = async (kind, objects) => {
1236
+ const ids = [...new Set(objects.map((object) => linkedOf(kind, object)).filter((id) => id !== ''))];
1237
+ const options = await Promise.all(ids.map((id) => resolveNextcloudUser(id).catch(() => null)));
1238
+ return new Map(ids.map((id, index) => [id, (options[index] && options[index].label) || id]))
1239
+ };
1240
+
1212
1241
  const searchObjects = async (axios, kind, term) => {
1213
1242
  const url = generateUrl('/apps/openregister/api/objects/{register}/{schema}', { register: kind.register, schema: kind.schema });
1214
1243
  const res = await axios.get(url, { params: { _search: term, _limit: kind.limit || 20 } });
1215
1244
  const body = (res && res.data) || {};
1216
1245
  const results = Array.isArray(body.results) ? body.results : (Array.isArray(body) ? body : []);
1217
1246
  const labels = kind.statusResolve && kind.statusField ? await statusLabels(kind) : null;
1247
+ const userNames = kind.linkedUser === true ? await linkedUserNames(kind, results) : null;
1218
1248
  return {
1219
1249
  total: typeof body.total === 'number' ? body.total : results.length,
1220
1250
  rows: results.map((object) => {
@@ -1231,7 +1261,7 @@ function searchSource(config = {}, context = {}) {
1231
1261
  title: String(readPath(object, kind.titleField || 'title') ?? object.name ?? id ?? ''),
1232
1262
  subtitle: subtitleOf(kind, object),
1233
1263
  status,
1234
- linked: linkedOf(kind, object),
1264
+ linked: userNames ? (userNames.get(linkedOf(kind, object)) || linkedOf(kind, object)) : linkedOf(kind, object),
1235
1265
  href: kind.href ? generateUrl(fillRowTemplate(kind.href, { ...object, id })) : '',
1236
1266
  object,
1237
1267
  }
@@ -1339,7 +1369,7 @@ function searchSource(config = {}, context = {}) {
1339
1369
  */
1340
1370
  loading: () => state.loading,
1341
1371
 
1342
- columns: [
1372
+ columns: withColumnWidths([
1343
1373
  { key: 'title', label: translate('nextcloud-vue', 'Result'), secondary: 'subtitle', sortable: true },
1344
1374
  // `kindAsText`: what one row is, as plain text ("Zaak", "Lantaarnpaal",
1345
1375
  // DqZoekresultaten), instead of the plural kind as a pill.
@@ -1354,7 +1384,7 @@ function searchSource(config = {}, context = {}) {
1354
1384
  widgetProps: { colorMap: (config && config.statusColorMap) || {} },
1355
1385
  sortable: true,
1356
1386
  },
1357
- ],
1387
+ ], config && config.columnWidths),
1358
1388
 
1359
1389
  /**
1360
1390
  * Every column header carries a filter button (DqZoekresultaten); the
@@ -1604,6 +1634,15 @@ function usersSource() {
1604
1634
  /** A filter button on every head (DqAfdelingen); the members read are narrowed here. */
1605
1635
  headerFilters: true,
1606
1636
 
1637
+ /**
1638
+ * A member's row menu (DqAfdelingen): their Nextcloud profile, and an
1639
+ * e-mail when they have an address. Both are links.
1640
+ */
1641
+ rowActions: [
1642
+ { id: 'open-profile', label: translate('nextcloud-vue', 'Open profile'), icon: AccountOutline, href: (row) => generateUrl(`/u/${encodeURIComponent(row.id)}`) },
1643
+ { id: 'send-email', label: translate('nextcloud-vue', 'Send email'), icon: EmailOutline, href: (row) => `mailto:${row.email}`, visible: (row) => Boolean(row && row.email) },
1644
+ ],
1645
+
1607
1646
  showAdd: false,
1608
1647
  }
1609
1648
  }