@ai-matrx/records-ui 0.110.4 → 0.110.6

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/dist/index.js CHANGED
@@ -1093,12 +1093,33 @@ function inColumnWords(error, fields) {
1093
1093
 
1094
1094
  // src/askOnce.ts
1095
1095
  var asked = /* @__PURE__ */ new WeakMap();
1096
- function askOnce(client, key, ask, freshMs) {
1096
+ var byPerson = /* @__PURE__ */ new WeakMap();
1097
+ function heldFor(client) {
1098
+ const config = client.config;
1099
+ const source = config?.dataSource;
1100
+ if (source && typeof source === "object" && config?.actor) {
1101
+ const who = [config.actor.actor ?? "-", config.actor.user_id ?? "-", config.actor.on_behalf_of ?? "-"].join("|");
1102
+ let persons = byPerson.get(source);
1103
+ if (!persons) {
1104
+ persons = /* @__PURE__ */ new Map();
1105
+ byPerson.set(source, persons);
1106
+ }
1107
+ let held2 = persons.get(who);
1108
+ if (!held2) {
1109
+ held2 = /* @__PURE__ */ new Map();
1110
+ persons.set(who, held2);
1111
+ }
1112
+ return held2;
1113
+ }
1097
1114
  let held = asked.get(client);
1098
1115
  if (!held) {
1099
1116
  held = /* @__PURE__ */ new Map();
1100
1117
  asked.set(client, held);
1101
1118
  }
1119
+ return held;
1120
+ }
1121
+ function askOnce(client, key, ask, freshMs) {
1122
+ const held = heldFor(client);
1102
1123
  const now = Date.now();
1103
1124
  const kept = held.get(key);
1104
1125
  if (kept && now - kept.at <= freshMs) return kept.answer;
@@ -1116,8 +1137,7 @@ function askOnce(client, key, ask, freshMs) {
1116
1137
  return answer;
1117
1138
  }
1118
1139
  function forgetAsked(client, prefix) {
1119
- const held = asked.get(client);
1120
- if (!held) return;
1140
+ const held = heldFor(client);
1121
1141
  for (const key of [...held.keys()]) if (key.startsWith(prefix)) held.delete(key);
1122
1142
  }
1123
1143
  var FIELD_OPTIONS_FRESH_MS = 2e3;
@@ -2773,6 +2793,12 @@ function asRefusal(thrown, sentence2, remedy, code = "internal") {
2773
2793
  return refusalFromThrown(thrown, sentence2, remedy, code);
2774
2794
  }
2775
2795
 
2796
+ // src/rowVersion.ts
2797
+ function ownVersion(row) {
2798
+ const v = row.version;
2799
+ return typeof v === "number" ? v : null;
2800
+ }
2801
+
2776
2802
  // src/recordVersions.ts
2777
2803
  var STALE_MOVE_LABEL = "Changed by someone else";
2778
2804
  var VERSION_UNREAD_LABEL = "Could not check for changes";
@@ -2789,10 +2815,6 @@ function isVersionUnread(error) {
2789
2815
  function isChangedElsewhere(error) {
2790
2816
  return error?.code === "stale_write";
2791
2817
  }
2792
- function ownVersion(row) {
2793
- const v = row.version;
2794
- return typeof v === "number" ? v : null;
2795
- }
2796
2818
  function signatureOf(row) {
2797
2819
  const own3 = ownVersion(row);
2798
2820
  if (own3 !== null) return `v${own3}`;
@@ -2802,6 +2824,7 @@ function signatureOf(row) {
2802
2824
  return String(Math.random());
2803
2825
  }
2804
2826
  }
2827
+ var HEADERS_SHARED_MS = 3e3;
2805
2828
  function useRecordVersions(client, rows, mayRead) {
2806
2829
  const versions = useRef4(/* @__PURE__ */ new Map());
2807
2830
  const drawn = useRef4(/* @__PURE__ */ new Map());
@@ -2819,7 +2842,7 @@ function useRecordVersions(client, rows, mayRead) {
2819
2842
  unread.current.delete(id);
2820
2843
  };
2821
2844
  const readHeaders = useCallback2(
2822
- (toRead) => {
2845
+ (toRead, shared = false) => {
2823
2846
  if (toRead.length === 0) return;
2824
2847
  generation.current += 1;
2825
2848
  const gen = generation.current;
@@ -2827,7 +2850,8 @@ function useRecordVersions(client, rows, mayRead) {
2827
2850
  versions.current.delete(id);
2828
2851
  unread.current.add(id);
2829
2852
  };
2830
- const read = client.recordHeaders({ ids: toRead }).then(
2853
+ const asking = shared ? askOnce(client, `record_headers:${toRead.join(",")}`, () => client.recordHeaders({ ids: toRead }), HEADERS_SHARED_MS) : client.recordHeaders({ ids: toRead });
2854
+ const read = asking.then(
2831
2855
  (res) => {
2832
2856
  const found = /* @__PURE__ */ new Set();
2833
2857
  if (res.ok) {
@@ -2860,7 +2884,7 @@ function useRecordVersions(client, rows, mayRead) {
2860
2884
  if (own3 !== null) raise(row.id, own3);
2861
2885
  else toRead.push(row.id);
2862
2886
  }
2863
- readHeaders(toRead);
2887
+ readHeaders(toRead, true);
2864
2888
  }, [readHeaders, key]);
2865
2889
  const refresh = useCallback2((ids) => readHeaders([...ids]), [readHeaders]);
2866
2890
  const seen = useCallback2(async (id) => {
@@ -6880,6 +6904,21 @@ import { createContext as createContext5, useContext as useContext5 } from "reac
6880
6904
 
6881
6905
  // src/firstPage.ts
6882
6906
  import { asRecordsDataSource as asRecordsDataSource2, createRecordsClient, recordingDataSource } from "@ai-matrx/records/core";
6907
+ import { isUuidShape as isUuidShape4 } from "@ai-matrx/kit/uuid";
6908
+
6909
+ // src/groupReads.ts
6910
+ function groupedPageSort(fields, groupKey, sort) {
6911
+ if (!groupKey) return sort;
6912
+ const field2 = fields.find((f) => f.key === groupKey);
6913
+ if (!field2) return sort;
6914
+ return [{ field: groupKey, direction: "asc", as: sortAsFor(field2) }, ...sort.filter((s) => s.field !== groupKey)];
6915
+ }
6916
+ function chosenEntries(chosen) {
6917
+ return JSON.parse(JSON.stringify(Object.entries(chosen).sort())).filter(([, op2]) => op2 in MEASURE_LABEL);
6918
+ }
6919
+ function groupFactMeasures(chosen) {
6920
+ return [{ op: "count" }, ...chosenEntries(chosen).filter(([, op2]) => op2 !== "count").map(([key, op2]) => ({ op: op2, key }))];
6921
+ }
6883
6922
 
6884
6923
  // src/viewKeys.ts
6885
6924
  var STORE_KEEPS_TIMELINE = true;
@@ -22132,12 +22171,6 @@ function groupValueKey(value) {
22132
22171
  if (Array.isArray(value)) return value.length === 0 ? "" : JSON.stringify(value);
22133
22172
  return typeof value === "object" ? JSON.stringify(value) : String(value);
22134
22173
  }
22135
- function groupedPageSort(fields, groupKey, sort) {
22136
- if (!groupKey) return sort;
22137
- const field2 = fields.find((f) => f.key === groupKey);
22138
- if (!field2) return sort;
22139
- return [{ field: groupKey, direction: "asc", as: sortAsFor(field2) }, ...sort.filter((s) => s.field !== groupKey)];
22140
- }
22141
22174
  function useGroupFacts(args) {
22142
22175
  const client = useRecordsClient35();
22143
22176
  const { tableId, groupKey, version } = args;
@@ -22153,10 +22186,7 @@ function useGroupFacts(args) {
22153
22186
  const entries = JSON.parse(chosenKey);
22154
22187
  const asked3 = JSON.parse(filterKey);
22155
22188
  const filter = Object.keys(asked3).length > 0 ? asked3 : void 0;
22156
- const measures = [
22157
- { op: "count" },
22158
- ...entries.filter(([, op2]) => op2 !== "count").map(([key, op2]) => ({ op: op2, key }))
22159
- ];
22189
+ const measures = groupFactMeasures(Object.fromEntries(entries));
22160
22190
  let cancelled = false;
22161
22191
  void client.recordAggregate({ table_id: tableId, groupBy: [groupKey], measures, limit: 1e3, ...filter ? { filter } : {} }).then((answered) => {
22162
22192
  if (cancelled) return;
@@ -49827,7 +49857,7 @@ function useSlotScroll(slot) {
49827
49857
  }
49828
49858
 
49829
49859
  // src/TablePage.tsx
49830
- import { isUuidShape as isUuidShape4 } from "@ai-matrx/kit/uuid";
49860
+ import { isUuidShape as isUuidShape5 } from "@ai-matrx/kit/uuid";
49831
49861
  import { Fragment as Fragment66, jsx as jsx158, jsxs as jsxs147 } from "react/jsx-runtime";
49832
49862
  var RAIL_TITLE = {
49833
49863
  settings: "Table settings",
@@ -50049,7 +50079,7 @@ function openingView(activeView, activeDashboardId) {
50049
50079
  }
50050
50080
  function savedViewFromParam(activeView) {
50051
50081
  const word = typeof activeView === "string" ? activeView.trim() : "";
50052
- return isUuidShape4(word) ? word.toLowerCase() : null;
50082
+ return isUuidShape5(word) ? word.toLowerCase() : null;
50053
50083
  }
50054
50084
  function addressForView(view, layout) {
50055
50085
  return view && !view.isDefault ? view.id : layout;
@@ -50874,7 +50904,7 @@ function TablePage({
50874
50904
  QuestionPanel,
50875
50905
  {
50876
50906
  tableId,
50877
- activeQuestionId: questionsFromLink && activeItemId && isUuidShape4(activeItemId) ? activeItemId : null,
50907
+ activeQuestionId: questionsFromLink && activeItemId && isUuidShape5(activeItemId) ? activeItemId : null,
50878
50908
  draft: questionDraft
50879
50909
  }
50880
50910
  ) : main === "archived" ? (
@@ -51104,7 +51134,7 @@ import { TapTargetSearchGroup as TapTargetSearchGroup2, TooltipProvider } from "
51104
51134
  import { MatrxTableCardShowMore as MatrxTableCardShowMore3 } from "@ai-matrx/design-system/data-table";
51105
51135
  import { useEffect as useEffect116, useMemo as useMemo79, useRef as useRef65, useState as useState136 } from "react";
51106
51136
  import { Button as Button108, ErrorBox as ErrorBox9, Input as Input12, cn as cn95 } from "@ai-matrx/design-system";
51107
- import { useRecordsClient as useRecordsClient98, useSeededAnswer as useSeededAnswer2 } from "@ai-matrx/records/react";
51137
+ import { SEED_FRESH_MS, useRecordsClient as useRecordsClient98, useSeededAnswerAt } from "@ai-matrx/records/react";
51108
51138
  import { Fragment as Fragment67, jsx as jsx159, jsxs as jsxs148 } from "react/jsx-runtime";
51109
51139
  var entityTitleColumn = entityNameColumn;
51110
51140
  function shown3(v) {
@@ -51207,15 +51237,13 @@ function EntityChartBlock({ source, kind, by, measure, title, where, organizatio
51207
51237
  const question = entityChartQuestion({ by, measure, where, organization });
51208
51238
  const measures = [m.op === "count" ? { op: "count" } : { op: m.op, key: m.of }];
51209
51239
  const base = { title: title ?? "", kind, measures, group_by: by ? [by] : [] };
51210
- const seeded = useSeededAnswer2(`entity-chart:${ask}`, (c) => c.drillAsk({ source, question }));
51211
- const [block, setBlock] = useState136(() => seeded ? blockOfAnswer({ ok: true, data: seeded }, base, by) : null);
51212
- const firstRead = useRef65(true);
51240
+ const seeded = useSeededAnswerAt(`entity-chart:${ask}`, (c) => c.drillAsk({ source, question }));
51241
+ const [block, setBlock] = useState136(() => seeded ? blockOfAnswer({ ok: true, data: seeded.data }, base, by) : null);
51242
+ const seededFor = useRef65(seeded ? { ask: `${ask}|${kind}|${title ?? ""}`, at: seeded.at } : null);
51213
51243
  useEffect116(() => {
51214
- if (firstRead.current && seeded) {
51215
- firstRead.current = false;
51216
- return;
51217
- }
51218
- firstRead.current = false;
51244
+ const held = seededFor.current;
51245
+ if (held && held.ask === `${ask}|${kind}|${title ?? ""}` && Date.now() - held.at < SEED_FRESH_MS) return;
51246
+ seededFor.current = null;
51219
51247
  let cancelled = false;
51220
51248
  void client.drillAsk({ source, question }).then((answer) => {
51221
51249
  if (cancelled) return;