@ai-matrx/records-ui 0.110.3 → 0.110.5

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog — @ai-matrx/records-ui
2
2
 
3
+ ## 0.110.5
4
+
5
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
6
+ `git diff npm/records-ui/v0.110.4..npm/records-ui/v0.110.5 -- apps/shared/records-ui`).
7
+ No source changes intended and no consumer action required.
8
+
9
+ ## 0.110.4
10
+ ### lane PERF-REVIEW-FIX
11
+
12
+ - A link's `?sort=` is one read, not two: when the saved view arrived and moved where the grid opens, the store was first asked in the new opening's order (a hand-ordered view: no sort, with the view id) and only then in the address's sort. Until the query is re-seated the read now goes out in the address's sort.
13
+
14
+ **Consumer action:** none.
15
+
3
16
  ## 0.110.2
4
17
 
5
18
  Automatic changed-only republish (docs/metadata drift since the last tag — see
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
3
  var core = require('@ai-matrx/records/core');
4
+ var uuid = require('@ai-matrx/kit/uuid');
4
5
  var records = require('@ai-matrx/records');
5
6
  require('@ai-matrx/kit/text-case');
6
7
  require('@ai-matrx/design-system/data-table');
7
8
  var tableStyle = require('@ai-matrx/design-system/data-table/table-style');
8
9
  require('@ai-matrx/design-system/field-formats');
9
- var uuid = require('@ai-matrx/kit/uuid');
10
10
  var realtime = require('@ai-matrx/realtime');
11
11
 
12
12
  // src/firstPage.ts
@@ -48,6 +48,20 @@ function defaultSortOf(table, fields) {
48
48
  const field = fields.find((f) => f.key === name) ?? fields.find((f) => f.id === name);
49
49
  return field ? { id: field.key, direction } : null;
50
50
  }
51
+ var MEASURE_LABEL = {
52
+ count: "Count",
53
+ sum: "Sum",
54
+ avg: "Average",
55
+ min: "Smallest",
56
+ max: "Largest",
57
+ median: "Median",
58
+ filled: "Filled",
59
+ empty: "Empty",
60
+ unique: "Unique",
61
+ percent_empty: "Percent empty",
62
+ percent_filled: "Percent filled",
63
+ range: "Range"
64
+ };
51
65
  function holdsNumbers(field) {
52
66
  const kind = String(editorKindFor(field));
53
67
  if (kind === "number" || kind === "currency" || kind === "percent") return true;
@@ -65,6 +79,26 @@ function pageSortFor(fields, sort) {
65
79
  if (!field) return [];
66
80
  return [{ field: field.key, direction: sort.direction === "desc" ? "desc" : "asc", as: sortAsFor(field) }];
67
81
  }
82
+
83
+ // src/groupReads.ts
84
+ function isPlainGrouping(grouping) {
85
+ return Boolean(grouping) && !(grouping.then && grouping.then.length > 0) && !grouping.across && !(grouping.trail && grouping.trail.length > 0);
86
+ }
87
+ function groupedPageSort(fields, groupKey, sort) {
88
+ if (!groupKey) return sort;
89
+ const field = fields.find((f) => f.key === groupKey);
90
+ if (!field) return sort;
91
+ return [{ field: groupKey, direction: "asc", as: sortAsFor(field) }, ...sort.filter((s) => s.field !== groupKey)];
92
+ }
93
+ function chosenEntries(chosen) {
94
+ return JSON.parse(JSON.stringify(Object.entries(chosen).sort())).filter(([, op]) => op in MEASURE_LABEL);
95
+ }
96
+ function groupFactMeasures(chosen) {
97
+ return [{ op: "count" }, ...chosenEntries(chosen).filter(([, op]) => op !== "count").map(([key, op]) => ({ op, key }))];
98
+ }
99
+ function summaryBarMeasures(chosen) {
100
+ return chosenEntries(chosen).map(([key, op]) => op === "count" ? { op: "count" } : { op, key });
101
+ }
68
102
  var MIN_ROW_HEIGHT = 24;
69
103
  var MAX_ROW_HEIGHT = 96;
70
104
  var AGGREGATE_KINDS = [
@@ -961,7 +995,8 @@ function firstGridPageArgs(input) {
961
995
  if (shown.ruleId) return null;
962
996
  if (shown.order === "manual") return null;
963
997
  if (shown.filters && Object.keys(shown.filters).length > 0) return null;
964
- if (shown.presentation?.grouping) return null;
998
+ const grouping = shown.presentation?.grouping;
999
+ if (grouping && !(input.merged && isPlainGrouping(grouping))) return null;
965
1000
  const first = (shown.sorts ?? [])[0];
966
1001
  const viewSort = first && fields.some((f) => f.key === first.field) ? { id: first.field, direction: first.direction } : null;
967
1002
  const opening = viewSort ?? defaultSortOf(input.table, fields);
@@ -969,13 +1004,16 @@ function firstGridPageArgs(input) {
969
1004
  p_table_id: input.tableId,
970
1005
  p_filter: {},
971
1006
  p_search: null,
972
- p_sort: pageSortFor(fields, opening),
1007
+ p_sort: groupedPageSort(fields, grouping?.field ?? null, pageSortFor(fields, opening)),
973
1008
  p_view_id: null,
974
1009
  p_limit: input.pageSize ?? TABLE_PAGE_SIZE,
975
1010
  p_offset: 0
976
1011
  };
977
1012
  }
978
1013
  async function firstGridPageRequest(client, tableId, options = {}) {
1014
+ return (await firstGridOpening(client, tableId, options))?.args ?? null;
1015
+ }
1016
+ async function firstGridOpening(client, tableId, options) {
979
1017
  const [table, fields, views, looks] = await Promise.all([
980
1018
  client.tableRead({ table_id: tableId }),
981
1019
  client.fields({ table_id: tableId }),
@@ -986,7 +1024,15 @@ async function firstGridPageRequest(client, tableId, options = {}) {
986
1024
  const mine = views.data.map(viewFromRow).filter((v) => v.subject === tableId);
987
1025
  const view = defaultViewOf(mine) ?? mine[0] ?? null;
988
1026
  const shown = view ? applyLook(view, looks.data[view.id]) : null;
989
- return firstGridPageArgs({ tableId, table: table.data, fields: fields.data, shown, ...options.pageSize ? { pageSize: options.pageSize } : {} });
1027
+ const args = firstGridPageArgs({
1028
+ tableId,
1029
+ table: table.data,
1030
+ fields: fields.data,
1031
+ shown,
1032
+ ...options.pageSize ? { pageSize: options.pageSize } : {},
1033
+ ...options.merged ? { merged: true } : {}
1034
+ });
1035
+ return args ? { args, shown, fields: fields.data } : null;
990
1036
  }
991
1037
  function serverRowsOf(seed) {
992
1038
  const found = seed?.answers.find((a) => a.door === "server_rows");
@@ -1008,10 +1054,11 @@ async function askTablePageSeed(input) {
1008
1054
  ).catch(() => null) : null;
1009
1055
  try {
1010
1056
  const pageSize = input.pageSize ?? (input.embedded ? EMBEDDED_PAGE_SIZE : TABLE_PAGE_SIZE);
1011
- const args = await firstGridPageRequest(client, input.tableId, { pageSize });
1057
+ const opening = await firstGridOpening(client, input.tableId, { pageSize, ...input.merged ? { merged: true } : {} });
1012
1058
  const wantRows = typeof input.rows === "function" ? input.rows(recording.seed()) : input.rows !== false;
1013
- if (args && wantRows) {
1014
- await client.listPage({
1059
+ if (opening && wantRows) {
1060
+ const { args, shown, fields } = opening;
1061
+ const page = await client.listPage({
1015
1062
  table_id: args.p_table_id,
1016
1063
  filter: args.p_filter,
1017
1064
  search: args.p_search,
@@ -1020,6 +1067,26 @@ async function askTablePageSeed(input) {
1020
1067
  limit: args.p_limit,
1021
1068
  offset: args.p_offset
1022
1069
  });
1070
+ if (page.ok) {
1071
+ const chosen = shown?.presentation?.summaries ?? {};
1072
+ const groupKey = shown?.presentation?.grouping?.field ?? null;
1073
+ const reads = [];
1074
+ if (groupKey) {
1075
+ reads.push(client.recordAggregate({ table_id: input.tableId, groupBy: [groupKey], measures: groupFactMeasures(chosen), limit: 1e3 }));
1076
+ }
1077
+ const bar = summaryBarMeasures(chosen);
1078
+ if (bar.length > 0) reads.push(client.recordAggregate({ table_id: input.tableId, measures: bar }));
1079
+ for (const field of fields) {
1080
+ if (field.type !== "list" && field.type !== "relation") continue;
1081
+ const ids = /* @__PURE__ */ new Set();
1082
+ for (const row of page.data.rows) {
1083
+ const value = row.document?.[field.key];
1084
+ for (const id of Array.isArray(value) ? value.map(String) : typeof value === "string" ? [value] : []) if (uuid.isUuidShape(id)) ids.add(id);
1085
+ }
1086
+ if (ids.size > 0) reads.push(client.relationWordsMany({ field_id: field.id, record_ids: [...ids] }));
1087
+ }
1088
+ await Promise.all(reads.map((read) => read.catch(() => null)));
1089
+ }
1023
1090
  }
1024
1091
  } catch {
1025
1092
  }