@protobase/ui 0.65.1 → 0.66.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 (40) hide show
  1. package/dist/app/incoming-card.js +2 -2
  2. package/dist/app/incoming-relations.js +4 -4
  3. package/dist/app/record-lines.js +3 -3
  4. package/dist/app/record-page.js +14 -11
  5. package/dist/app/use-lines.js +6 -6
  6. package/dist/app/use-record-lines.js +38 -16
  7. package/dist/locale/en.js +0 -2
  8. package/dist/locale/nl.js +0 -2
  9. package/dist/package.js +1 -1
  10. package/dist/shell/assets/{app-XyM0p_d6.js → app-CdLhzPaH.js} +7 -7
  11. package/dist/shell/assets/{calls-DJW8sAaA.js → calls-fbu88Iwx.js} +2 -2
  12. package/dist/shell/assets/export-worker-Bux-6dp9.js +15 -0
  13. package/dist/shell/assets/{index-DMYBOMYl.js → index-Du6GlNEk.js} +2 -2
  14. package/dist/shell/assets/{maplibre-CRmpQfDl.js → maplibre-sUHB6Qig.js} +2 -2
  15. package/dist/shell/assets/parse-worker-ChfW_ehD.js +18 -0
  16. package/dist/shell/assets/preload-helper-BRlYOzPJ.js +2 -0
  17. package/dist/shell/assets/{record-map-DsP4sXes.js → record-map-CZ__Yamf.js} +2 -2
  18. package/dist/shell/assets/{records-map-BXh3aP0f.js → records-map-C1_HI-hA.js} +2 -2
  19. package/dist/shell/assets/{shared-protobase-ui-Bt5-cYRJ.js → shared-protobase-ui-o_KsAqf7.js} +2 -2
  20. package/dist/shell/index.html +4 -4
  21. package/dist/shell/protobase.shell.json +2 -2
  22. package/dist/shell/protobase.sw.js +2 -2
  23. package/dist/shell-source-maps/assets/app-CdLhzPaH.js.map +1 -0
  24. package/dist/shell-source-maps/assets/{calls-DJW8sAaA.js.map → calls-fbu88Iwx.js.map} +1 -1
  25. package/dist/shell-source-maps/assets/export-worker-Bux-6dp9.js.map +1 -0
  26. package/dist/shell-source-maps/assets/{index-DMYBOMYl.js.map → index-Du6GlNEk.js.map} +1 -1
  27. package/dist/shell-source-maps/assets/{maplibre-CRmpQfDl.js.map → maplibre-sUHB6Qig.js.map} +1 -1
  28. package/dist/shell-source-maps/assets/parse-worker-ChfW_ehD.js.map +1 -0
  29. package/dist/shell-source-maps/assets/preload-helper-BRlYOzPJ.js.map +1 -0
  30. package/dist/shell-source-maps/assets/{record-map-DsP4sXes.js.map → record-map-CZ__Yamf.js.map} +1 -1
  31. package/dist/shell-source-maps/assets/{records-map-BXh3aP0f.js.map → records-map-C1_HI-hA.js.map} +1 -1
  32. package/dist/shell-source-maps/assets/{shared-protobase-ui-Bt5-cYRJ.js.map → shared-protobase-ui-o_KsAqf7.js.map} +1 -1
  33. package/package.json +4 -4
  34. package/dist/shell/assets/export-worker-ClXdfeuq.js +0 -15
  35. package/dist/shell/assets/parse-worker-DxsmAjef.js +0 -18
  36. package/dist/shell/assets/preload-helper-BgLOXTzV.js +0 -2
  37. package/dist/shell-source-maps/assets/app-XyM0p_d6.js.map +0 -1
  38. package/dist/shell-source-maps/assets/export-worker-ClXdfeuq.js.map +0 -1
  39. package/dist/shell-source-maps/assets/parse-worker-DxsmAjef.js.map +0 -1
  40. package/dist/shell-source-maps/assets/preload-helper-BgLOXTzV.js.map +0 -1
@@ -10,9 +10,9 @@ import { ChevronRight } from "lucide-react";
10
10
  import { jsx, jsxs } from "react/jsx-runtime";
11
11
  //#region src/app/incoming-card.tsx
12
12
  /** The rail's card of the records pointing at this one: per resource and field, how many, linking to them in their list. */
13
- const IncomingCard = ({ model, recordKey, layout, lines }) => {
13
+ const IncomingCard = ({ model, recordKey, layout }) => {
14
14
  const { resources, views } = useAdminMeta();
15
- const counts = useIncomingCounts(incomingRelations(model, resources, views, layout, lines), resources, recordKey);
15
+ const counts = useIncomingCounts(incomingRelations(model, resources, views, layout), resources, recordKey);
16
16
  if (counts.length === 0) return null;
17
17
  return /* @__PURE__ */ jsx(SidebarCard, {
18
18
  title: text("relatedRecords"),
@@ -6,13 +6,13 @@ const where$1 = createWhere();
6
6
  /**
7
7
  * The relations that point at records of `model`, as the rail lists them by default: each filterable relation of
8
8
  * another resource the user can see (a hidden resource or field is not in the meta), to a record of one key column.
9
- * Left out are a resource's tenant, which every record holds, the lines drawn on the page, and what an `l.related`
10
- * section of the page already lists. Two fields of one resource are told apart by their labels.
9
+ * Left out are a resource's tenant, which every record holds, and what an `l.related` section of the page already
10
+ * lists, the record's lines included. Two fields of one resource are told apart by their labels.
11
11
  */
12
- const incomingRelations = (model, resources, views, layout, lines) => {
12
+ const incomingRelations = (model, resources, views, layout) => {
13
13
  if (model.primaryKey.length !== 1) return [];
14
14
  const listed = new Set(layoutItems(layout).flatMap((item) => item.kind === "related" && !item.through && !item.from ? [`${item.resource}.${item.field}`] : []));
15
- const found = Object.values(resources).flatMap((source) => Object.values(source.fields).filter((field) => field.type === "relation" && field.relation?.resource === model.name && field.relation.columns.length === 1 && field.filterable).filter((field) => field.name !== source.tenant && source.name !== lines?.name && !listed.has(`${source.name}.${field.name}`)).map((field) => ({
15
+ const found = Object.values(resources).flatMap((source) => Object.values(source.fields).filter((field) => field.type === "relation" && field.relation?.resource === model.name && field.relation.columns.length === 1 && field.filterable).filter((field) => field.name !== source.tenant && !listed.has(`${source.name}.${field.name}`)).map((field) => ({
16
16
  source,
17
17
  field: field.name
18
18
  })));
@@ -20,7 +20,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
20
20
  */
21
21
  const RecordLines = ({ lines, editable, saving }) => {
22
22
  const { resources, views } = useAdminMeta();
23
- const { model, columns, data, draft } = lines;
23
+ const { item, model, columns, data, draft } = lines;
24
24
  const permissions = usePermissions(model.name);
25
25
  const view = views[model.name];
26
26
  const [picked, setPicked] = useState({});
@@ -89,8 +89,8 @@ const RecordLines = ({ lines, editable, saving }) => {
89
89
  return rejection.message;
90
90
  };
91
91
  return /* @__PURE__ */ jsxs(Section, {
92
- title: text("lines"),
93
- help: text("linesHelp"),
92
+ title: item.title,
93
+ help: item.help,
94
94
  children: [!data.complete && /* @__PURE__ */ jsx("p", {
95
95
  className: "mb-2 text-muted-foreground",
96
96
  children: text("tooManyLines", { limit: formatInt(1e3) })
@@ -412,6 +412,18 @@ const LoadedRecord = ({ model, recordKey, stored, preview }) => {
412
412
  children
413
413
  }, `group:${item.title}`)];
414
414
  }
415
+ if (item.kind === "related" && item.lines) {
416
+ if (!lines.model || !lines.item || preview) return [];
417
+ return [/* @__PURE__ */ jsx(RecordLines, {
418
+ lines: {
419
+ ...lines,
420
+ model: lines.model,
421
+ item: lines.item
422
+ },
423
+ editable: shown === "form",
424
+ saving: editor.saving
425
+ }, `lines:${item.title}`)];
426
+ }
415
427
  if (item.kind === "related") {
416
428
  if (item.from !== void 0 && !known(item.from)) return [];
417
429
  return [/* @__PURE__ */ jsx(RelatedSection, {
@@ -548,15 +560,7 @@ const LoadedRecord = ({ model, recordKey, stored, preview }) => {
548
560
  className: "divide-y divide-border",
549
561
  children: tab.items.flatMap(mainItem)
550
562
  }, `tab:${tab.title}`),
551
- after.flatMap(mainItem),
552
- lines.model && !preview && /* @__PURE__ */ jsx(RecordLines, {
553
- lines: {
554
- ...lines,
555
- model: lines.model
556
- },
557
- editable: shown === "form",
558
- saving: editor.saving
559
- })
563
+ after.flatMap(mainItem)
560
564
  ]
561
565
  }), /* @__PURE__ */ jsxs("aside", {
562
566
  className: "space-y-4 md:sticky md:top-[var(--pb-sticky-top,0px)] md:max-h-[calc(100dvh-var(--pb-sticky-top,0px)-var(--pb-sticky-bottom,0px))] md:self-start md:overflow-y-auto md:pb-4 md:pt-8",
@@ -601,8 +605,7 @@ const LoadedRecord = ({ model, recordKey, stored, preview }) => {
601
605
  !preview && /* @__PURE__ */ jsx(IncomingCard, {
602
606
  model,
603
607
  recordKey,
604
- layout,
605
- lines: lines.model
608
+ layout
606
609
  })
607
610
  ]
608
611
  })]
@@ -3,20 +3,20 @@ import { useEffect, useMemo } from "react";
3
3
  //#region src/app/use-lines.ts
4
4
  /** The most lines a record's line editor loads; a record with more shows them read-only, as it cannot save them as a whole. */
5
5
  const linesLimit = 1e3;
6
- const byPosition = (a, b) => Number(a.position) - Number(b.position);
7
6
  /**
8
- * The numbered lines of a record, in position order, as the server has them: every page, up to `linesLimit`, each as
9
- * large as the API gives. `labels` names the records their relations point at. Nothing is fetched without a lines resource.
7
+ * The numbered lines of a record, in the order of their `position` field, as the server has them: every page, up to
8
+ * `linesLimit`, each as large as the API gives. `labels` names the records their relations point at. Nothing is
9
+ * fetched without a lines resource.
10
10
  */
11
- const useLines = (lines, link, parentKey, labels) => {
11
+ const useLines = (lines, link, position, parentKey, labels) => {
12
12
  const list = useList(lines?.name ?? "", {
13
13
  enabled: Boolean(lines && link),
14
14
  filter: link ? `${link.name} = "${parentKey}"` : void 0,
15
15
  pageSize: 500,
16
16
  labels,
17
- ...lines?.fields.position?.sortable && { orderBy: "position asc" }
17
+ ...position && lines?.fields[position]?.sortable && { orderBy: `${position} asc` }
18
18
  });
19
- const items = useMemo(() => [...list.items].sort(byPosition), [list.data]);
19
+ const items = useMemo(() => position ? [...list.items].sort((a, b) => Number(a[position]) - Number(b[position])) : list.items, [list.data, position]);
20
20
  const more = list.hasNextPage && list.items.length < 1e3;
21
21
  useEffect(() => {
22
22
  if (more && !list.isFetchingNextPage) list.fetchNextPage();
@@ -5,42 +5,64 @@ import { listLabels } from "../live/relation-labels.js";
5
5
  import { useLines } from "./use-lines.js";
6
6
  import { useLinesDraft } from "./use-lines-draft.js";
7
7
  import { useMemo } from "react";
8
+ import { layoutItems } from "@protobase/schema/internal";
8
9
  //#region src/app/use-record-lines.ts
9
- /** A resource that holds numbered lines of this one: it points at the parent and has `position` and `quantity`. */
10
- const findLinesResource = (resources, parent) => Object.values(resources).find((candidate) => candidate.name !== parent.name && candidate.fields.position && candidate.fields.quantity && Object.values(candidate.fields).some((field) => field.type === "relation" && field.relation?.resource === parent.name));
10
+ /**
11
+ * The record's lines, as its view declares them with `l.related(..., { lines: true })`: the section, the lines'
12
+ * resource, the relation that points at the record and the field that orders them.
13
+ */
14
+ const findLinesResource = (resources, view) => {
15
+ const item = layoutItems(view?.layout ?? []).find((each) => each.kind === "related" && each.lines === true);
16
+ if (item?.kind !== "related") return;
17
+ const model = resources[item.resource];
18
+ const link = model?.fields[item.field];
19
+ const position = model?.position?.field;
20
+ if (!model || !link || !position || model.position?.within !== item.field) return;
21
+ return {
22
+ item,
23
+ model,
24
+ link,
25
+ position
26
+ };
27
+ };
11
28
  /**
12
29
  * The lines' columns: the list columns of their view, or its first fields, without what the editor fills in itself:
13
30
  * the key, the tenant, the relation to the record and the position, which is the order of the rows.
14
31
  */
15
- const lineColumnNames = (lines, view, link) => listColumnNames(lines, view).filter((name) => {
32
+ const lineColumnNames = (lines, view, link, position) => listColumnNames(lines, view).filter((name) => {
16
33
  const field = lines.fields[name];
17
- return field && !field.writeOnly && name !== link && name !== "position" && name !== lines.tenant && !lines.primaryKey.includes(name);
34
+ return field && !field.writeOnly && name !== link && name !== position && name !== lines.tenant && !lines.primaryKey.includes(name);
18
35
  });
19
- /** The record's lines when it has a lines resource: the resource, its columns, the lines as stored and the changes made to them. */
36
+ /** The record's lines when its view declares them: the section, the resource, its columns, the lines as stored and the changes made to them. */
20
37
  const useRecordLines = (parent, parentKey) => {
21
38
  const { resources, views } = useAdminMeta();
22
- const model = useMemo(() => findLinesResource(resources, parent), [resources, parent]);
23
- const link = model && Object.values(model.fields).find((field) => field.type === "relation" && field.relation?.resource === parent.name);
24
- const columns = model && link ? lineColumnNames(model, views[model.name], link.name) : [];
25
- const data = useLines(model, link, parentKey, model ? listLabels(resources, views, model, columns) : void 0);
26
- const target = useMemo(() => model && link ? {
27
- model,
28
- position: "position",
39
+ const found = useMemo(() => findLinesResource(resources, views[parent.name]), [
40
+ resources,
41
+ views,
42
+ parent
43
+ ]);
44
+ const model = found?.model;
45
+ const columns = found ? lineColumnNames(found.model, views[found.model.name], found.link.name, found.position) : [];
46
+ const data = useLines(model, found?.link, found?.position, parentKey, model ? listLabels(resources, views, model, columns) : void 0);
47
+ const target = useMemo(() => found ? {
48
+ model: found.model,
49
+ position: found.position,
29
50
  link: {
30
- field: link.name,
51
+ field: found.link.name,
31
52
  value: keyValue(parent, parentKey)
32
53
  }
33
54
  } : void 0, [
34
- model,
35
- link,
55
+ found,
36
56
  parent,
37
57
  parentKey
38
58
  ]);
59
+ const draft = useLinesDraft(target, data.items);
39
60
  return {
61
+ item: found?.item,
40
62
  model,
41
63
  columns,
42
64
  data,
43
- draft: useLinesDraft(target, data.items)
65
+ draft
44
66
  };
45
67
  };
46
68
  //#endregion
package/dist/locale/en.js CHANGED
@@ -734,8 +734,6 @@ var en_default = {
734
734
  "nothingYet": "Nothing here yet.",
735
735
  "couldNotLoadRelated": "Could not load",
736
736
  "relatedRecords": "Related records",
737
- "lines": "Lines",
738
- "linesHelp": "What the document bills for. Edit a line in place, add one, or drag the handle to change the order; Save applies it all.",
739
737
  "lineNumber": "Line {place}",
740
738
  "lineField": "{label}, line {place}",
741
739
  "tooManyLines": "This record has more than {limit} lines, so they show here read-only."
package/dist/locale/nl.js CHANGED
@@ -734,8 +734,6 @@ var nl_default = {
734
734
  "nothingYet": "Hier staat nog niets.",
735
735
  "couldNotLoadRelated": "Kon niet laden",
736
736
  "relatedRecords": "Gerelateerde records",
737
- "lines": "Regels",
738
- "linesHelp": "Waar het document voor factureert. Wijzig een regel ter plekke, voeg er een toe, of sleep de greep om de volgorde te wijzigen; Bewaren past alles toe.",
739
737
  "lineNumber": "Regel {place}",
740
738
  "lineField": "{label}, regel {place}",
741
739
  "tooManyLines": "Dit record heeft meer dan {limit} regels, dus ze staan hier alleen ter inzage."
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.65.1";
2
+ var version = "0.66.0";
3
3
  var protobase = { "pluginApi": 1 };
4
4
  //#endregion
5
5
  export { protobase, version };