@conduction/nextcloud-vue 2.124.0 → 2.125.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 (66) hide show
  1. package/dist/esm/components/CnActionDialog/CnActionDialog.vue.js +1 -1
  2. package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js +120 -11
  3. package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js.map +1 -1
  4. package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js +78 -32
  5. package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js.map +1 -1
  6. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +8 -7
  7. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  8. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  9. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue.js +1 -1
  10. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js +2 -1
  11. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js.map +1 -1
  12. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js +2 -2
  13. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js.map +1 -1
  14. package/dist/esm/components/CnDialog/CnDialog.vue2.js +5 -0
  15. package/dist/esm/components/CnDialog/CnDialog.vue2.js.map +1 -1
  16. package/dist/esm/components/CnDialog/CnDialog.vue3.js +1 -1
  17. package/dist/esm/components/CnDialog/CnDialog.vue3.js.map +1 -1
  18. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +13 -0
  19. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  20. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +2 -1
  21. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  22. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue.js +1 -1
  23. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +7 -2
  24. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  25. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  26. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  27. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +159 -10
  28. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  29. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +151 -90
  30. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  31. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue2.js +12 -0
  32. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue2.js.map +1 -1
  33. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js +1 -1
  34. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js.map +1 -1
  35. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue.js +1 -1
  36. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js +39 -68
  37. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js.map +1 -1
  38. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js +70 -116
  39. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js.map +1 -1
  40. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
  41. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +19 -3
  42. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  43. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  44. package/dist/esm/l10n/en.json.js +8 -8
  45. package/dist/esm/l10n/nl.json.js +8 -8
  46. package/dist/esm/library-style.js +1 -1
  47. package/dist/esm/nextcloud-vue.css +316 -185
  48. package/dist/nextcloud-vue.cjs.js +1149 -808
  49. package/dist/nextcloud-vue.cjs.js.map +2 -2
  50. package/dist/nextcloud-vue.css +316 -185
  51. package/l10n/en.json +8 -8
  52. package/l10n/nl.json +8 -8
  53. package/package.json +1 -1
  54. package/src/components/CnActionDialog/CnActionDialog.vue +173 -14
  55. package/src/components/CnAppRoot/CnAppRoot.vue +8 -7
  56. package/src/components/CnAssignDialog/CnAssignDialog.vue +4 -3
  57. package/src/components/CnDialog/CnDialog.vue +6 -1
  58. package/src/components/CnIndexPage/CnIndexPage.vue +14 -0
  59. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +7 -2
  60. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +237 -23
  61. package/src/components/CnSavedViewsControl/CnSavedViewsControl.vue +13 -1
  62. package/src/components/CnUserSettingsDialog/CnUserSettingsDialog.vue +147 -145
  63. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +19 -3
  64. package/src/css/dialog.css +23 -0
  65. package/src/css/look-board-index.css +5 -1
  66. package/src/css/look-board.css +19 -0
@@ -2,7 +2,7 @@ import script from './CnRecordListWidget.vue2.js';
2
2
  import { render } from './CnRecordListWidget.vue3.js';
3
3
 
4
4
  script.render = render;
5
- script.__scopeId = "data-v-1484103e";
5
+ script.__scopeId = "data-v-0cb81a45";
6
6
  const __sfc_main = script;
7
7
 
8
8
  export { __sfc_main as default };
@@ -1,6 +1,6 @@
1
1
  import { subscribe, unsubscribe } from '@nextcloud/event-bus';
2
2
  import { translate } from '@nextcloud/l10n';
3
- import { NcActionButton, NcActions, NcButton, NcLoadingIcon } from '@nextcloud/vue';
3
+ import { NcActionButton, NcActionLink, NcActions, NcButton, NcLoadingIcon } from '@nextcloud/vue';
4
4
  import { inject, ref } from 'vue';
5
5
  import ChevronRight from 'vue-material-design-icons/ChevronRight.vue';
6
6
  import __sfc_main from '../CnIcon/CnIcon.vue.js';
@@ -19,7 +19,7 @@ import { lensUnavailableText, readLensReports } from '../../utils/lensAvailabili
19
19
  import { pageFilter, pageSort } from '../../utils/pageControls.js';
20
20
  import { readPath } from '../../utils/readPath.js';
21
21
  import { dropOptionalUnresolved, resolveFilterTokens, hasUnresolvedTokens, resolveDeepTokens } from '../../utils/resolveFilterTokens.js';
22
- import { evaluateVisibleWhen } from '../../utils/visibleWhen.js';
22
+ import { evaluateVisibleWhen, evaluateVisibleWhenLocal } from '../../utils/visibleWhen.js';
23
23
  import { interpolateUrlTokens } from '../../utils/interpolateUrlTokens.js';
24
24
 
25
25
  const PAGE_REFRESH_CHANNEL = 'cn:page:refresh';
@@ -28,6 +28,22 @@ const PAGE_REFRESH_CHANNEL = 'cn:page:refresh';
28
28
  let footerSeq = 0;
29
29
  const PRESENTATIONS = ['rows', 'feed', 'inline', 'cards', 'notice', 'table', 'notes'];
30
30
 
31
+ /**
32
+ * Compare two table cell texts: as numbers when both read as one, else as text.
33
+ *
34
+ * @param {string} a One cell text.
35
+ * @param {string} b The other.
36
+ * @return {number} Negative, zero or positive.
37
+ */
38
+ function compareCells(a, b) {
39
+ const x = Number(a);
40
+ const y = Number(b);
41
+ if (a !== '' && b !== '' && Number.isFinite(x) && Number.isFinite(y)) {
42
+ return x - y
43
+ }
44
+ return String(a).localeCompare(String(b))
45
+ }
46
+
31
47
  /** The tones a `notice` list takes. */
32
48
  const NOTICE_VARIANTS = ['info', 'warning', 'error'];
33
49
 
@@ -79,7 +95,7 @@ function unwrap(value) {
79
95
  var script = {
80
96
  name: 'CnRecordListWidget',
81
97
 
82
- components: { ChevronRight, CnIcon: __sfc_main, CnRecordNoteRows: __sfc_main$1, CnStatusBadge: __sfc_main$2, NcActionButton, NcActions, NcButton, NcLoadingIcon },
98
+ components: { ChevronRight, CnIcon: __sfc_main, CnRecordNoteRows: __sfc_main$1, CnStatusBadge: __sfc_main$2, NcActionButton, NcActionLink, NcActions, NcButton, NcLoadingIcon },
83
99
 
84
100
  inject: {
85
101
  /** Detail-page object context (`{ objectId, object, register, schema }`). */
@@ -125,6 +141,8 @@ var script = {
125
141
  * per value, headed by the field's `valueLabels` entry; `groupOrder`
126
142
  * (values) orders the groups and `groupEmptyLabel` heads the rows
127
143
  * without a value.
144
+ * `density: "compact"` draws the rows 10px above and below, at least
145
+ * 56px tall, with the title at 500 (DqProcesanalyse).
128
146
  *
129
147
  * @type {object}
130
148
  */
@@ -175,6 +193,8 @@ var script = {
175
193
 
176
194
  data() {
177
195
  return {
196
+ /** The reader's sort of a `table`: the column key and `ascending` or `descending`. */
197
+ tableSort: { key: '', dir: '' },
178
198
  rows: [],
179
199
  total: 0,
180
200
  loading: false,
@@ -376,6 +396,7 @@ var script = {
376
396
  dot: this.dotOf(row),
377
397
  flag: this.flagOf(row),
378
398
  links: this.linksOf(row),
399
+ rowActions: this.rowActionsOf(row),
379
400
  }
380
401
  })
381
402
  },
@@ -454,8 +475,11 @@ var script = {
454
475
  * @spec openspec/changes/record-list-table/specs/record-list-table/spec.md#requirement-a-record-list-can-draw-its-rows-as-a-small-table
455
476
  */
456
477
  tableRows() {
457
- return this.items.map((item) => ({
478
+ const indentPath = this.content?.indentPath;
479
+ const rows = this.items.map((item) => ({
458
480
  key: item.key,
481
+ to: item.attrs.to || null,
482
+ depth: indentPath ? Math.max(0, Math.floor(Number(readPath(item.row, indentPath)) || 0)) : 0,
459
483
  cells: this.tableColumns.map((col) => {
460
484
  const text = this.fill(col.value, item.row);
461
485
  const limit = Number(col.alertAbove);
@@ -465,9 +489,17 @@ var script = {
465
489
  text,
466
490
  align: col.align,
467
491
  alert: col.alertAbove !== undefined && Number.isFinite(limit) && text !== '' && Number.isFinite(value) && value > limit,
492
+ tone: this.cellToneOf(col, item.row, text),
468
493
  }
469
494
  }),
470
- }))
495
+ }));
496
+ const { key, dir } = this.tableSort;
497
+ const index = this.tableColumns.findIndex((col) => col.key === key);
498
+ if (index < 0 || !dir) {
499
+ return rows
500
+ }
501
+ const sign = dir === 'descending' ? -1 : 1;
502
+ return [...rows].sort((a, b) => sign * compareCells(a.cells[index].text, b.cells[index].text))
471
503
  },
472
504
 
473
505
  /** @return {string} The note under the list (`footnote`), translated. */
@@ -1129,6 +1161,123 @@ var script = {
1129
1161
  }
1130
1162
  },
1131
1163
 
1164
+ /**
1165
+ * The badge variant of a `table` cell with a `tone`
1166
+ * (`{ field?, map, default?, override?: { when, tone } }`): the value at
1167
+ * `field` (else the cell text) looked up in `map`, else `default`. While
1168
+ * `override.when` (a condition over the row) holds, the cell takes
1169
+ * `override.tone` instead, so a verdict is never green unless a second
1170
+ * field allows it.
1171
+ *
1172
+ * @param {object} col The column.
1173
+ * @param {object} row The row.
1174
+ * @param {string} text The cell text.
1175
+ * @return {string} A badge variant, or '' for a plain cell.
1176
+ * @spec openspec/changes/record-list-table-shape/specs/record-list-table-shape/spec.md#requirement-a-record-list-table-takes-its-shape-from-the-rows
1177
+ */
1178
+ cellToneOf(col, row, text) {
1179
+ const tone = col.tone;
1180
+ if (!tone || typeof tone !== 'object') {
1181
+ return ''
1182
+ }
1183
+ let variant;
1184
+ if (tone.override && typeof tone.override === 'object' && evaluateVisibleWhenLocal(tone.override.when, row || {})) {
1185
+ variant = tone.override.tone;
1186
+ } else {
1187
+ const value = tone.field ? readPath(row, tone.field) : text;
1188
+ const map = tone.map && typeof tone.map === 'object' ? tone.map : {};
1189
+ variant = Object.hasOwn(map, String(value)) ? map[String(value)] : tone.default;
1190
+ }
1191
+ return isBadgeVariant(variant) ? variant : 'default'
1192
+ },
1193
+
1194
+ /**
1195
+ * The `aria-sort` of a sortable `table` column.
1196
+ *
1197
+ * @param {string} key The column key.
1198
+ * @return {string} `ascending`, `descending` or `none`.
1199
+ */
1200
+ sortStateOf(key) {
1201
+ return this.tableSort.key === key && this.tableSort.dir ? this.tableSort.dir : 'none'
1202
+ },
1203
+
1204
+ /**
1205
+ * The arrow after a sortable column's label.
1206
+ *
1207
+ * @param {string} key The column key.
1208
+ * @return {string} An up or down arrow, or '' while the column is not the sort.
1209
+ */
1210
+ sortMarkOf(key) {
1211
+ const state = this.sortStateOf(key);
1212
+ if (state === 'ascending') {
1213
+ return '▲'
1214
+ }
1215
+ return state === 'descending' ? '▼' : ''
1216
+ },
1217
+
1218
+ /**
1219
+ * Sort the `table` by a column: ascending first, then descending.
1220
+ *
1221
+ * @param {string} key The column key.
1222
+ * @spec openspec/changes/record-list-table-shape/specs/record-list-table-shape/spec.md#requirement-a-record-list-table-takes-its-shape-from-the-rows
1223
+ */
1224
+ toggleTableSort(key) {
1225
+ const dir = this.tableSort.key === key && this.tableSort.dir === 'ascending' ? 'descending' : 'ascending';
1226
+ this.tableSort = { key, dir };
1227
+ },
1228
+
1229
+ /**
1230
+ * The rows of a read with `flattenPath` set: each entry of the list at
1231
+ * that path on a record becomes a row, with the record at `@parent`.
1232
+ * A record without the list adds no row. Without `flattenPath` the
1233
+ * records are the rows.
1234
+ *
1235
+ * @param {Array<object>} records The records read.
1236
+ * @return {Array<object>} The rows.
1237
+ * @spec openspec/changes/record-list-table-shape/specs/record-list-table-shape/spec.md#requirement-a-record-list-table-takes-its-shape-from-the-rows
1238
+ */
1239
+ flattenRows(records) {
1240
+ const path = this.content?.flattenPath;
1241
+ if (typeof path !== 'string' || path === '') {
1242
+ return records
1243
+ }
1244
+ return records.flatMap((record) => {
1245
+ const list = readPath(record, path);
1246
+ return Array.isArray(list)
1247
+ ? list.filter((entry) => entry && typeof entry === 'object').map((entry) => ({ ...entry, '@parent': record }))
1248
+ : []
1249
+ })
1250
+ },
1251
+
1252
+ /**
1253
+ * The row actions shown on one row: those whose `visibleWhen` (a
1254
+ * condition over the row) holds. An `href` action is a template over
1255
+ * the row and shows only when it fills to a web address or an
1256
+ * instance path; a web address opens in a new tab.
1257
+ *
1258
+ * @param {object} row The row.
1259
+ * @return {Array<{action: object, index: number, href: string, external: boolean}>} The visible actions, with their place in `rowActions`.
1260
+ * @spec openspec/changes/record-list-row-rules/specs/record-list-row-rules/spec.md#requirement-a-row-action-can-depend-on-the-row
1261
+ */
1262
+ rowActionsOf(row) {
1263
+ const shown = [];
1264
+ this.rowActions.forEach((action, index) => {
1265
+ if (action.visibleWhen && !evaluateVisibleWhenLocal(action.visibleWhen, row || {})) {
1266
+ return
1267
+ }
1268
+ if (typeof action.href !== 'string') {
1269
+ shown.push({ action, index, href: '', external: false });
1270
+ return
1271
+ }
1272
+ const href = this.fill(action.href, row).trim();
1273
+ const external = /^https?:\/\//i.test(href);
1274
+ if (external || (href.startsWith('/') && !href.startsWith('//'))) {
1275
+ shown.push({ action, index, href, external });
1276
+ }
1277
+ });
1278
+ return shown
1279
+ },
1280
+
1132
1281
  /**
1133
1282
  * A row's `links` line: the ids at `links.field`, each labelled from
1134
1283
  * `links.labelSource` (`{ register, schema, template }`) once read, else
@@ -1456,7 +1605,7 @@ var script = {
1456
1605
  * @spec openspec/changes/endpoint-source-card-grid-record-list/specs/dashboard-page/spec.md#requirement-a-record-list-and-a-card-grid-can-read-an-endpoint
1457
1606
  */
1458
1607
  takeEndpointRows() {
1459
- this.rows = Array.isArray(this.epData) ? this.epData : [];
1608
+ this.rows = this.flattenRows(Array.isArray(this.epData) ? this.epData : []);
1460
1609
  this.total = this.rows.length;
1461
1610
  this.loading = this.epLoading === true;
1462
1611
  this.error = Boolean(this.epError);
@@ -1533,14 +1682,14 @@ var script = {
1533
1682
  if (run !== this.fetchRun) {
1534
1683
  return
1535
1684
  }
1536
- this.rows = ranked.rows;
1537
- this.total = ranked.total;
1685
+ this.rows = this.flattenRows(ranked.rows);
1686
+ this.total = this.content?.flattenPath ? this.rows.length : ranked.total;
1538
1687
  return
1539
1688
  }
1540
1689
  const response = await axios.get(url, { params });
1541
1690
  const data = response && response.data ? response.data : {};
1542
- this.rows = Array.isArray(data.results) ? data.results : [];
1543
- this.total = typeof data.total === 'number' ? data.total : this.rows.length;
1691
+ this.rows = this.flattenRows(Array.isArray(data.results) ? data.results : []);
1692
+ this.total = typeof data.total === 'number' && !this.content?.flattenPath ? data.total : this.rows.length;
1544
1693
  this.lenses = readLensReports(data);
1545
1694
  } catch (e) {
1546
1695
  // eslint-disable-next-line no-console