@protobase/ui 0.25.1 → 0.25.3
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/account/account-pages.js +3 -2
- package/dist/account/account-security-page.js +9 -4
- package/dist/account/backup-codes.js +7 -6
- package/dist/account/messages.js +214 -0
- package/dist/account/passkeys-section.js +23 -22
- package/dist/account/password-dialog.js +3 -2
- package/dist/account/sign-in-policy-form.js +11 -10
- package/dist/account/sign-in-policy-labels.js +30 -29
- package/dist/account/sign-in-policy-page.js +11 -6
- package/dist/account/sign-in-providers-section.js +6 -5
- package/dist/account/staff-sign-in-log.js +11 -10
- package/dist/account/totp-qr.js +2 -1
- package/dist/account/two-factor-section.js +24 -23
- package/dist/account/two-factor-setup.js +18 -17
- package/dist/action-card/action-card.js +2 -1
- package/dist/action-card/messages.js +8 -0
- package/dist/activity-chart/activity-chart.js +3 -2
- package/dist/activity-chart/messages.js +14 -0
- package/dist/app/app.d.ts +1 -1
- package/dist/app/app.js +20 -21
- package/dist/app/assistant-shell.js +2 -1
- package/dist/app/batch-failure.js +2 -1
- package/dist/app/breadcrumb-for.js +4 -3
- package/dist/app/charts/chart-groups.js +3 -2
- package/dist/app/charts/chart-view.js +3 -2
- package/dist/app/charts/group-bars.js +2 -1
- package/dist/app/charts/messages.js +26 -0
- package/dist/app/charts/period-chart.js +3 -2
- package/dist/app/charts/split-points.js +2 -1
- package/dist/app/comments/comment-composer.js +19 -18
- package/dist/app/comments/comments-section.js +4 -3
- package/dist/app/comments/messages.js +26 -0
- package/dist/app/create/create-page.js +11 -18
- package/dist/app/custom-section.js +4 -6
- package/dist/app/displays/board-column.js +6 -5
- package/dist/app/displays/board-columns.js +3 -2
- package/dist/app/displays/board-display.js +13 -15
- package/dist/app/displays/calendar-controls.js +3 -2
- package/dist/app/displays/calendar-display.js +12 -17
- package/dist/app/displays/card-carousel.js +4 -3
- package/dist/app/displays/cards-display.js +2 -1
- package/dist/app/displays/custom-display.js +4 -6
- package/dist/app/displays/display-frame.js +3 -2
- package/dist/app/displays/list-cards.js +5 -8
- package/dist/app/displays/list-displays.js +3 -3
- package/dist/app/displays/map-display.js +15 -14
- package/dist/app/displays/messages.js +128 -2
- package/dist/app/displays/period-controls.js +4 -3
- package/dist/app/displays/record-card.js +7 -6
- package/dist/app/displays/timeline-display.js +17 -26
- package/dist/app/displays/timeline-range.js +2 -1
- package/dist/app/displays/use-board-move.js +2 -2
- package/dist/app/displays/use-calendar-move.js +2 -1
- package/dist/app/document-title.js +2 -1
- package/dist/app/export/builder-port.js +2 -1
- package/dist/app/export/export-dialog.js +36 -40
- package/dist/app/export/export-worker.js +2 -0
- package/dist/app/export/messages.js +78 -0
- package/dist/app/export/run-export.js +5 -2
- package/dist/app/export/sink.js +4 -3
- package/dist/app/export/use-export-flow.js +4 -3
- package/dist/app/field-editor.js +4 -3
- package/dist/app/field-types/messages.js +8 -0
- package/dist/app/field-types/widget-part.js +2 -1
- package/dist/app/file-field.js +11 -14
- package/dist/app/gallery/gallery-section.js +4 -3
- package/dist/app/gallery/lightbox.js +5 -4
- package/dist/app/gallery/messages.js +30 -0
- package/dist/app/gallery/photo-details.js +3 -2
- package/dist/app/hand-order/hand-sorted-list.js +3 -6
- package/dist/app/hand-order/messages.js +4 -2
- package/dist/app/history/describe-change.js +3 -8
- package/dist/app/history/messages.js +32 -0
- package/dist/app/import/convert.js +20 -19
- package/dist/app/import/failed-rows.js +3 -2
- package/dist/app/import/import-button.js +2 -1
- package/dist/app/import/import-check-step.js +19 -35
- package/dist/app/import/import-dialog.js +13 -17
- package/dist/app/import/import-file-step.js +5 -9
- package/dist/app/import/import-mapping-step.js +32 -35
- package/dist/app/import/import-result-step.js +13 -12
- package/dist/app/import/messages.js +200 -0
- package/dist/app/import/parse-worker.js +2 -0
- package/dist/app/import/prepare-rows.js +5 -4
- package/dist/app/import/sheet-cell.js +2 -1
- package/dist/app/import/sheet-file.js +3 -2
- package/dist/app/import/sheet-source.js +7 -3
- package/dist/app/import/xlsx-reader.js +4 -3
- package/dist/app/import/xlsx-xml.js +2 -1
- package/dist/app/import/zip-reader.js +4 -3
- package/dist/app/list-edit/use-list-edits.js +1 -1
- package/dist/app/list-group-chart.js +2 -1
- package/dist/app/list-page.js +1 -1
- package/dist/app/map/map-layer-switch.js +3 -2
- package/dist/app/map/messages.js +14 -0
- package/dist/app/messages.js +116 -2
- package/dist/app/meta-gate.js +1 -1
- package/dist/app/nav-from-meta.js +11 -10
- package/dist/app/pages/action-inputs/action-inputs-dialog.js +3 -2
- package/dist/app/pages/action-inputs/input-answers.js +6 -5
- package/dist/app/pages/blocks/card-row.js +3 -2
- package/dist/app/pages/blocks/modal-form.js +5 -4
- package/dist/app/pages/blocks/record-card.js +3 -2
- package/dist/app/pages/blocks/stat.js +2 -1
- package/dist/app/pages/composed-page.js +6 -8
- package/dist/app/pages/confirm-action.js +2 -1
- package/dist/app/pages/custom-boundary.js +4 -2
- package/dist/app/pages/messages.js +64 -0
- package/dist/app/pages/render-node.js +5 -7
- package/dist/app/pages/use-run-action.js +11 -10
- package/dist/app/record-page.js +1 -1
- package/dist/app/record-row/messages.js +26 -0
- package/dist/app/record-row/record-row-body.js +12 -7
- package/dist/app/record-row/record-row.js +4 -3
- package/dist/app/record-row/saved-record-row.js +3 -2
- package/dist/app/related-dots/dots-summary.js +2 -1
- package/dist/app/related-dots/messages.js +8 -0
- package/dist/app/relation-picker.js +9 -8
- package/dist/app/router.js +5 -4
- package/dist/app/runtime/messages.js +58 -0
- package/dist/app/runtime/runtime-status.js +10 -23
- package/dist/app/runtime/runtime-update-dialog.js +7 -6
- package/dist/app/runtime/runtime-update.js +4 -3
- package/dist/app/saved/favorite-button.js +2 -1
- package/dist/app/saved/messages.js +22 -0
- package/dist/app/saved/saved-list.js +4 -7
- package/dist/app/saved/use-favorite.js +3 -2
- package/dist/app/search/messages.js +6 -2
- package/dist/app/search/navigation-hits.js +9 -7
- package/dist/app/searches/filter-chip-list.js +2 -1
- package/dist/app/searches/messages.js +96 -0
- package/dist/app/searches/save-search-button.js +5 -4
- package/dist/app/searches/saved-search-rows.js +3 -2
- package/dist/app/searches/saved-search-section.js +6 -5
- package/dist/app/searches/saved-search.js +4 -3
- package/dist/app/searches/saved-searches.js +15 -25
- package/dist/app/searches/search-controls.js +5 -4
- package/dist/app/searches/search-diff.js +4 -2
- package/dist/app/searches/search-name-dialog.js +4 -3
- package/dist/app/searches/update-search-dialog.js +15 -30
- package/dist/app/searches/use-save-search.js +8 -7
- package/dist/app/searches/use-search-row.js +4 -3
- package/dist/app/sensitive-field.js +5 -4
- package/dist/app/source-notice.js +13 -8
- package/dist/app/staff-banner.js +12 -19
- package/dist/app-shell/global-search.js +2 -2
- package/dist/app-shell/messages.js +4 -2
- package/dist/assistant-dock/assistant-dock.js +5 -5
- package/dist/assistant-dock/messages.js +26 -0
- package/dist/assistant-dock/use-assistant.js +2 -1
- package/dist/assistant-dock/use-backend-data.js +2 -1
- package/dist/assistant-dock/widget-view.js +3 -2
- package/dist/auth/auth-gate.js +10 -5
- package/dist/auth/auth-locale.js +14 -0
- package/dist/auth/auth-messages.js +122 -43
- package/dist/auth/auth-provider.js +6 -1
- package/dist/auth/code-form.js +2 -1
- package/dist/auth/email-code-form.js +11 -13
- package/dist/auth/email-code-page.js +2 -1
- package/dist/auth/first-run-page.js +6 -5
- package/dist/auth/forgot-password-form.js +14 -16
- package/dist/auth/forgot-password-page.js +2 -1
- package/dist/auth/messages.js +200 -0
- package/dist/auth/provider-sign-in-page.js +5 -5
- package/dist/auth/resend-code-button.js +2 -1
- package/dist/auth/reset-password-form.js +11 -10
- package/dist/auth/reset-password-page.js +4 -3
- package/dist/auth/setup-required-form.js +7 -9
- package/dist/auth/setup-required-page.js +7 -2
- package/dist/auth/sign-in-form.js +15 -18
- package/dist/auth/sign-in-prompt.js +4 -3
- package/dist/auth/sign-up-code-form.js +11 -13
- package/dist/auth/sign-up-details-form.js +14 -21
- package/dist/auth/sign-up-email-form.js +8 -7
- package/dist/auth/sign-up-page.js +2 -1
- package/dist/auth/staff-sign-in-form.js +14 -17
- package/dist/auth/two-factor-form.js +17 -16
- package/dist/auth/user-to-shell.js +2 -1
- package/dist/chat/composer.js +8 -7
- package/dist/chat/messages.js +14 -0
- package/dist/compact-table/compact-table.js +4 -8
- package/dist/compact-table/messages.js +18 -0
- package/dist/data/meta-data.d.ts +1 -1
- package/dist/data/use-update-record.js +1 -1
- package/dist/inline-child-table/inline-child-table.js +12 -12
- package/dist/inline-child-table/line-row.js +10 -9
- package/dist/inline-child-table/messages.js +52 -0
- package/dist/inline-child-table/totals-footer.js +5 -8
- package/dist/invitations/invite-form.js +3 -2
- package/dist/invitations/link-notice.js +6 -4
- package/dist/invitations/messages.js +24 -0
- package/dist/invitations/pending-invitation-row.js +4 -3
- package/dist/lists/messages.js +8 -0
- package/dist/lists/paged-search-list.js +2 -1
- package/dist/locale/slotted.js +14 -0
- package/dist/markdown/markdown-editor.js +6 -5
- package/dist/markdown/messages.js +16 -0
- package/dist/organizations/all-organizations.js +6 -5
- package/dist/organizations/app-roles-picker.js +2 -1
- package/dist/organizations/invitation-page.js +39 -49
- package/dist/organizations/invitations-page.js +11 -10
- package/dist/organizations/members-page.js +15 -10
- package/dist/organizations/messages.js +180 -0
- package/dist/organizations/organization-page.js +27 -26
- package/dist/organizations/organization-paths.js +16 -13
- package/dist/organizations/organization-row.js +3 -2
- package/dist/organizations/organizations-page.js +17 -16
- package/dist/organizations/use-organizations.js +2 -1
- package/dist/package.js +1 -1
- package/dist/plugins/before-sign-in.js +6 -1
- package/dist/plugins/load-plugin.d.ts +1 -1
- package/dist/plugins/load-plugin.js +3 -2
- package/dist/plugins/messages.js +36 -0
- package/dist/plugins/plugin-gate.js +6 -1
- package/dist/plugins/plugin-manifest.js +8 -7
- package/dist/plugins/plugin-notice.js +8 -12
- package/dist/primitives/messages.js +16 -0
- package/dist/primitives/sheet.js +2 -1
- package/dist/primitives/spinner.js +2 -1
- package/dist/primitives/token.js +2 -1
- package/dist/record-view/messages.js +4 -2
- package/dist/record-view/record-tabs.js +2 -1
- package/dist/roles/messages.js +14 -0
- package/dist/roles/use-active-role.js +3 -2
- package/dist/shell/assets/app-CW3U56yM.js +69 -0
- package/dist/shell/assets/cn-Bi0ZEjD9.js +1 -0
- package/dist/shell/assets/export-worker-ClACk00b.js +2 -0
- package/dist/shell/assets/{index-BuKnJ48y.js → index-B7cIjCuz.js} +2 -2
- package/dist/shell/assets/maplibre-CVG5L9FD.js +814 -0
- package/dist/shell/assets/{markdown-content-CvNiaqsy.js → markdown-content-CtGUP4W6.js} +1 -1
- package/dist/shell/assets/parse-worker-UhbwEjS0.js +5 -0
- package/dist/shell/assets/preload-helper-BX9CcZkY.js +1 -0
- package/dist/shell/assets/{record-map-BmPHHEMK.js → record-map-Cw3_NcUl.js} +1 -1
- package/dist/shell/assets/records-map-D4f3ZeDL.js +1 -0
- package/dist/shell/assets/shared-protobase-ui-CB_i50NP.js +1 -0
- package/dist/shell/index.html +5 -3
- package/dist/shell/protobase.shell.json +1 -1
- package/dist/shell/protobase.sw.js +2 -2
- package/dist/side-panel/messages.js +8 -0
- package/dist/side-panel/side-panel.js +2 -1
- package/dist/toasts/messages.js +8 -0
- package/dist/toasts/toast.js +2 -1
- package/dist/users/app-invitations.js +5 -4
- package/dist/users/create-user-form.js +9 -8
- package/dist/users/messages.js +52 -0
- package/dist/users/use-user-roles.js +2 -1
- package/dist/users/user-list.js +6 -5
- package/dist/users/user-row.js +5 -4
- package/package.json +4 -4
- package/dist/shell/assets/app-BPHSSo4E.js +0 -69
- package/dist/shell/assets/export-worker-Bz57Pf5g.js +0 -2
- package/dist/shell/assets/maplibre-C2VkKdp3.js +0 -814
- package/dist/shell/assets/parse-worker-BtcY0dQw.js +0 -5
- package/dist/shell/assets/records-map-BvUD1Fqc.js +0 -1
- package/dist/shell/assets/shared-protobase-ui-B-pEBDQf.js +0 -1
|
@@ -3,33 +3,34 @@ import { formatApproxRows, formatInt } from "../../format/number.js";
|
|
|
3
3
|
import { Button } from "../../primitives/button.js";
|
|
4
4
|
import { Checkbox } from "../../primitives/checkbox.js";
|
|
5
5
|
import { ResponsiveDialog } from "../../primitives/responsive-dialog.js";
|
|
6
|
+
import { text } from "./messages.js";
|
|
6
7
|
import { exportLimit } from "./export-options.js";
|
|
7
8
|
import { useState } from "react";
|
|
8
9
|
import { ArrowDown, ArrowUp } from "lucide-react";
|
|
9
10
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
11
|
//#region src/app/export/export-dialog.tsx
|
|
11
|
-
const formatOptions = [{
|
|
12
|
+
const formatOptions = () => [{
|
|
12
13
|
value: "xlsx",
|
|
13
|
-
label: "
|
|
14
|
+
label: text("excel")
|
|
14
15
|
}, {
|
|
15
16
|
value: "csv",
|
|
16
|
-
label: "
|
|
17
|
+
label: text("csv")
|
|
17
18
|
}];
|
|
18
|
-
const modeOptions = [{
|
|
19
|
+
const modeOptions = () => [{
|
|
19
20
|
value: "shown",
|
|
20
|
-
label: "
|
|
21
|
+
label: text("asShown")
|
|
21
22
|
}, {
|
|
22
23
|
value: "raw",
|
|
23
|
-
label: "
|
|
24
|
+
label: text("rawValues")
|
|
24
25
|
}];
|
|
25
26
|
const modeHelp = {
|
|
26
|
-
shown: "
|
|
27
|
-
raw: "
|
|
27
|
+
shown: "shownHint",
|
|
28
|
+
raw: "rawHint"
|
|
28
29
|
};
|
|
29
30
|
const countText = (count) => {
|
|
30
|
-
if (count.kind === "counting") return "
|
|
31
|
+
if (count.kind === "counting") return text("counting");
|
|
31
32
|
if (count.kind === "exact") return formatApproxRows(count.rows);
|
|
32
|
-
return count.rows > 1e4 ? formatApproxRows(count.rows) : "
|
|
33
|
+
return count.rows > 1e4 ? formatApproxRows(count.rows) : text("moreThan");
|
|
33
34
|
};
|
|
34
35
|
/** The fewest rows the list finds, as far as the count tells: an estimate stands only above 10,000. */
|
|
35
36
|
const countedRows = (count) => {
|
|
@@ -66,7 +67,7 @@ const ColumnPicker = ({ fields, columns, onChange }) => {
|
|
|
66
67
|
const ordered = [...columns, ...fields.map((field) => field.name).filter((name) => !columns.includes(name))];
|
|
67
68
|
return /* @__PURE__ */ jsx("ul", {
|
|
68
69
|
className: "divide-y self-stretch rounded-md border",
|
|
69
|
-
"aria-label": "
|
|
70
|
+
"aria-label": text("columns"),
|
|
70
71
|
children: ordered.map((name) => {
|
|
71
72
|
const chosen = columns.includes(name);
|
|
72
73
|
const index = columns.indexOf(name);
|
|
@@ -88,7 +89,7 @@ const ColumnPicker = ({ fields, columns, onChange }) => {
|
|
|
88
89
|
size: "sm",
|
|
89
90
|
variant: "ghost",
|
|
90
91
|
className: "min-h-8 px-2",
|
|
91
|
-
"aria-label":
|
|
92
|
+
"aria-label": text("moveUp", labels[name]),
|
|
92
93
|
disabled: index === 0,
|
|
93
94
|
onClick: () => onChange(move(columns, name, -1)),
|
|
94
95
|
children: /* @__PURE__ */ jsx(ArrowUp, { className: "size-3.5" })
|
|
@@ -96,7 +97,7 @@ const ColumnPicker = ({ fields, columns, onChange }) => {
|
|
|
96
97
|
size: "sm",
|
|
97
98
|
variant: "ghost",
|
|
98
99
|
className: "min-h-8 px-2",
|
|
99
|
-
"aria-label":
|
|
100
|
+
"aria-label": text("moveDown", labels[name]),
|
|
100
101
|
disabled: index === columns.length - 1,
|
|
101
102
|
onClick: () => onChange(move(columns, name, 1)),
|
|
102
103
|
children: /* @__PURE__ */ jsx(ArrowDown, { className: "size-3.5" })
|
|
@@ -116,22 +117,22 @@ const ExportDialog = ({ plural, view, fields, initialColumns, count, selected, o
|
|
|
116
117
|
const [columns, setColumns] = useState(initialColumns);
|
|
117
118
|
const [mode, setMode] = useState("shown");
|
|
118
119
|
const limit = exportLimit(view, format);
|
|
119
|
-
const rows = scope === "selected" ?
|
|
120
|
+
const rows = scope === "selected" ? text("selectedRows", formatInt(selected ?? 0), selected ?? 0) : countText(count);
|
|
120
121
|
const overLimit = (scope === "selected" ? selected ?? 0 : countedRows(count) ?? 0) > limit;
|
|
121
122
|
const scopeOptions = [{
|
|
122
123
|
value: "list",
|
|
123
|
-
label: "
|
|
124
|
+
label: text("rowsInList")
|
|
124
125
|
}, {
|
|
125
126
|
value: "selected",
|
|
126
|
-
label:
|
|
127
|
+
label: text("selected", formatInt(selected ?? 0))
|
|
127
128
|
}];
|
|
128
129
|
return /* @__PURE__ */ jsx(ResponsiveDialog, {
|
|
129
|
-
title:
|
|
130
|
+
title: text("exportPlural", plural),
|
|
130
131
|
open,
|
|
131
132
|
onClose,
|
|
132
133
|
actions: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Button, {
|
|
133
134
|
onClick: onClose,
|
|
134
|
-
children: "
|
|
135
|
+
children: text("cancel")
|
|
135
136
|
}), /* @__PURE__ */ jsx(Button, {
|
|
136
137
|
variant: "primary",
|
|
137
138
|
disabled: columns.length === 0,
|
|
@@ -141,45 +142,45 @@ const ExportDialog = ({ plural, view, fields, initialColumns, count, selected, o
|
|
|
141
142
|
columns,
|
|
142
143
|
mode
|
|
143
144
|
}),
|
|
144
|
-
children: "
|
|
145
|
+
children: text("export")
|
|
145
146
|
})] }),
|
|
146
147
|
children: /* @__PURE__ */ jsxs("div", {
|
|
147
148
|
className: "flex flex-col gap-4 text-[13px]",
|
|
148
149
|
children: [
|
|
149
150
|
/* @__PURE__ */ jsx(Setting, {
|
|
150
|
-
label: "
|
|
151
|
+
label: text("format"),
|
|
151
152
|
children: /* @__PURE__ */ jsx(Segmented, {
|
|
152
153
|
size: "md",
|
|
153
|
-
label: "
|
|
154
|
+
label: text("format"),
|
|
154
155
|
value: format,
|
|
155
|
-
options: formatOptions,
|
|
156
|
+
options: formatOptions(),
|
|
156
157
|
onChange: setFormat
|
|
157
158
|
})
|
|
158
159
|
}),
|
|
159
160
|
selected !== void 0 && selected > 0 && /* @__PURE__ */ jsx(Setting, {
|
|
160
|
-
label: "
|
|
161
|
-
help: scope === "list" ? "
|
|
161
|
+
label: text("rows"),
|
|
162
|
+
help: scope === "list" ? text("listHint") : void 0,
|
|
162
163
|
children: /* @__PURE__ */ jsx(Segmented, {
|
|
163
164
|
size: "md",
|
|
164
|
-
label: "
|
|
165
|
+
label: text("rows"),
|
|
165
166
|
value: scope,
|
|
166
167
|
options: scopeOptions,
|
|
167
168
|
onChange: setScope
|
|
168
169
|
})
|
|
169
170
|
}),
|
|
170
171
|
/* @__PURE__ */ jsx(Setting, {
|
|
171
|
-
label: "
|
|
172
|
-
help: modeHelp[mode],
|
|
172
|
+
label: text("values"),
|
|
173
|
+
help: text(modeHelp[mode]),
|
|
173
174
|
children: /* @__PURE__ */ jsx(Segmented, {
|
|
174
175
|
size: "md",
|
|
175
|
-
label: "
|
|
176
|
+
label: text("values"),
|
|
176
177
|
value: mode,
|
|
177
|
-
options: modeOptions,
|
|
178
|
+
options: modeOptions(),
|
|
178
179
|
onChange: setMode
|
|
179
180
|
})
|
|
180
181
|
}),
|
|
181
182
|
/* @__PURE__ */ jsx(Setting, {
|
|
182
|
-
label: "
|
|
183
|
+
label: text("columns"),
|
|
183
184
|
children: /* @__PURE__ */ jsx(ColumnPicker, {
|
|
184
185
|
fields,
|
|
185
186
|
columns,
|
|
@@ -189,12 +190,7 @@ const ExportDialog = ({ plural, view, fields, initialColumns, count, selected, o
|
|
|
189
190
|
/* @__PURE__ */ jsxs("p", {
|
|
190
191
|
role: "status",
|
|
191
192
|
className: "text-muted-foreground",
|
|
192
|
-
children: [
|
|
193
|
-
"Exports ",
|
|
194
|
-
rows,
|
|
195
|
-
".",
|
|
196
|
-
overLimit && ` A file holds at most ${formatInt(limit)} rows; the rest are left out.`
|
|
197
|
-
]
|
|
193
|
+
children: [text("exports", rows), overLimit && text("overLimit", formatInt(limit))]
|
|
198
194
|
})
|
|
199
195
|
]
|
|
200
196
|
})
|
|
@@ -204,18 +200,18 @@ const ExportDialog = ({ plural, view, fields, initialColumns, count, selected, o
|
|
|
204
200
|
const ExportProgressDialog = ({ plural, done, total, onCancel }) => {
|
|
205
201
|
const share = total ? Math.min(1, done / total) : void 0;
|
|
206
202
|
return /* @__PURE__ */ jsx(ResponsiveDialog, {
|
|
207
|
-
title:
|
|
203
|
+
title: text("exporting", plural),
|
|
208
204
|
open: true,
|
|
209
205
|
onClose: onCancel,
|
|
210
206
|
actions: /* @__PURE__ */ jsx(Button, {
|
|
211
207
|
onClick: onCancel,
|
|
212
|
-
children: "
|
|
208
|
+
children: text("cancel")
|
|
213
209
|
}),
|
|
214
210
|
children: /* @__PURE__ */ jsxs("div", {
|
|
215
211
|
className: "flex flex-col gap-2 text-[13px]",
|
|
216
212
|
children: [/* @__PURE__ */ jsx("div", {
|
|
217
213
|
role: "progressbar",
|
|
218
|
-
"aria-label": "
|
|
214
|
+
"aria-label": text("rowsExported"),
|
|
219
215
|
"aria-valuemin": 0,
|
|
220
216
|
"aria-valuemax": total,
|
|
221
217
|
"aria-valuenow": done,
|
|
@@ -226,7 +222,7 @@ const ExportProgressDialog = ({ plural, done, total, onCancel }) => {
|
|
|
226
222
|
})
|
|
227
223
|
}), /* @__PURE__ */ jsx("p", {
|
|
228
224
|
className: "text-muted-foreground",
|
|
229
|
-
children: total ?
|
|
225
|
+
children: total ? text("doneOf", formatInt(done), formatInt(total)) : text("done", formatInt(done))
|
|
230
226
|
})]
|
|
231
227
|
})
|
|
232
228
|
});
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { setFallbackLocale } from "../../locale/active-locale.js";
|
|
1
2
|
import { createBuilderHandler } from "./builder-port.js";
|
|
2
3
|
//#region src/app/export/export-worker.ts
|
|
3
4
|
const handle = createBuilderHandler();
|
|
4
5
|
const scope = self;
|
|
5
6
|
scope.onmessage = (event) => {
|
|
7
|
+
if (event.data.kind === "start") setFallbackLocale(event.data.locale);
|
|
6
8
|
const bytes = handle(event.data);
|
|
7
9
|
scope.postMessage({ bytes }, [bytes.buffer]);
|
|
8
10
|
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { defineMessages } from "../../locale/messages.js";
|
|
2
|
+
//#region src/app/export/messages.ts
|
|
3
|
+
const text = defineMessages({
|
|
4
|
+
en: {
|
|
5
|
+
excel: "Excel (.xlsx)",
|
|
6
|
+
csv: "CSV",
|
|
7
|
+
asShown: "As shown",
|
|
8
|
+
rawValues: "Raw values",
|
|
9
|
+
shownHint: "Labels, dates and numbers as the list shows them.",
|
|
10
|
+
rawHint: "Values as they are stored, such as keys and codes.",
|
|
11
|
+
counting: "Counting rows…",
|
|
12
|
+
moreThan: "more than 10,000 rows",
|
|
13
|
+
columns: "Columns",
|
|
14
|
+
moveUp: (label) => `Move ${label} up`,
|
|
15
|
+
moveDown: (label) => `Move ${label} down`,
|
|
16
|
+
selectedRows: (count, rows) => `${count} selected ${rows === 1 ? "row" : "rows"}`,
|
|
17
|
+
rowsInList: "Rows in the list",
|
|
18
|
+
selected: (count) => `Selected (${count})`,
|
|
19
|
+
exportPlural: (plural) => `Export ${plural.toLowerCase()}`,
|
|
20
|
+
cancel: "Cancel",
|
|
21
|
+
export: "Export",
|
|
22
|
+
format: "Format",
|
|
23
|
+
rows: "Rows",
|
|
24
|
+
listHint: "With the list’s filters, search and sort.",
|
|
25
|
+
values: "Values",
|
|
26
|
+
exports: (rows) => `Exports ${rows}.`,
|
|
27
|
+
overLimit: (limit) => ` A file holds at most ${limit} rows; the rest are left out.`,
|
|
28
|
+
exporting: (plural) => `Exporting ${plural.toLowerCase()}`,
|
|
29
|
+
rowsExported: "Rows exported",
|
|
30
|
+
doneOf: (done, total) => `${done} of ${total} rows`,
|
|
31
|
+
done: (done) => `${done} rows`,
|
|
32
|
+
exported: (count, plural) => `Exported ${count} ${plural.toLowerCase()}`,
|
|
33
|
+
truncated: (name, count) => `${name}: the first ${count} rows, as many as a file holds.`,
|
|
34
|
+
couldNotExport: (plural) => `Could not export ${plural.toLowerCase()}`,
|
|
35
|
+
cancelled: "The export was cancelled",
|
|
36
|
+
couldNotBuild: (message) => `The export could not be built: ${message}`,
|
|
37
|
+
workbook: "Excel workbook",
|
|
38
|
+
csvFile: "CSV file"
|
|
39
|
+
},
|
|
40
|
+
nl: {
|
|
41
|
+
excel: "Excel (.xlsx)",
|
|
42
|
+
csv: "CSV",
|
|
43
|
+
asShown: "Zoals getoond",
|
|
44
|
+
rawValues: "Ruwe waarden",
|
|
45
|
+
shownHint: "Labels, datums en getallen zoals de lijst ze toont.",
|
|
46
|
+
rawHint: "Waarden zoals ze zijn opgeslagen, zoals sleutels en codes.",
|
|
47
|
+
counting: "Rijen tellen…",
|
|
48
|
+
moreThan: "meer dan 10.000 rijen",
|
|
49
|
+
columns: "Kolommen",
|
|
50
|
+
moveUp: (label) => `${label} omhoog`,
|
|
51
|
+
moveDown: (label) => `${label} omlaag`,
|
|
52
|
+
selectedRows: (count, rows) => `${count} geselecteerde ${rows === 1 ? "rij" : "rijen"}`,
|
|
53
|
+
rowsInList: "Rijen in de lijst",
|
|
54
|
+
selected: (count) => `Geselecteerd (${count})`,
|
|
55
|
+
exportPlural: (plural) => `${plural} exporteren`,
|
|
56
|
+
cancel: "Annuleren",
|
|
57
|
+
export: "Exporteren",
|
|
58
|
+
format: "Formaat",
|
|
59
|
+
rows: "Rijen",
|
|
60
|
+
listHint: "Met de filters, zoekopdracht en sortering van de lijst.",
|
|
61
|
+
values: "Waarden",
|
|
62
|
+
exports: (rows) => `Exporteert ${rows}.`,
|
|
63
|
+
overLimit: (limit) => ` Een bestand bevat hoogstens ${limit} rijen; de rest blijft weg.`,
|
|
64
|
+
exporting: (plural) => `${plural} exporteren`,
|
|
65
|
+
rowsExported: "Geëxporteerde rijen",
|
|
66
|
+
doneOf: (done, total) => `${done} van ${total} rijen`,
|
|
67
|
+
done: (done) => `${done} rijen`,
|
|
68
|
+
exported: (count, plural) => `${count} ${plural.toLowerCase()} geëxporteerd`,
|
|
69
|
+
truncated: (name, count) => `${name}: de eerste ${count} rijen, zoveel als een bestand bevat.`,
|
|
70
|
+
couldNotExport: (plural) => `Kon ${plural.toLowerCase()} niet exporteren`,
|
|
71
|
+
cancelled: "De export is geannuleerd",
|
|
72
|
+
couldNotBuild: (message) => `De export kon niet worden gemaakt: ${message}`,
|
|
73
|
+
workbook: "Excel-werkmap",
|
|
74
|
+
csvFile: "CSV-bestand"
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
//#endregion
|
|
78
|
+
export { text };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { activeLocale } from "../../locale/active-locale.js";
|
|
2
|
+
import { text } from "./messages.js";
|
|
3
|
+
const aborted = () => new DOMException(text("cancelled"), "AbortError");
|
|
2
4
|
/**
|
|
3
5
|
* Reads the rows through the list API, page by page with its page tokens, and has the port build the file from each;
|
|
4
6
|
* each piece is written to the sink as it is built, so only a page is held at a time. A cancel stops at the next page
|
|
@@ -10,7 +12,8 @@ const runExport = async ({ client, resource, filters, orderBy, plan, labels, lim
|
|
|
10
12
|
try {
|
|
11
13
|
await sink.write(await port.send({
|
|
12
14
|
kind: "start",
|
|
13
|
-
plan
|
|
15
|
+
plan,
|
|
16
|
+
locale: activeLocale()
|
|
14
17
|
}));
|
|
15
18
|
for (const [index, filter] of filters.entries()) {
|
|
16
19
|
let pageToken = "";
|
package/dist/app/export/sink.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import { text } from "./messages.js";
|
|
1
2
|
//#region src/app/export/sink.ts
|
|
2
3
|
const types = {
|
|
3
4
|
xlsx: {
|
|
4
5
|
mime: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
5
6
|
extension: ".xlsx",
|
|
6
|
-
description: "
|
|
7
|
+
description: "workbook"
|
|
7
8
|
},
|
|
8
9
|
csv: {
|
|
9
10
|
mime: "text/csv",
|
|
10
11
|
extension: ".csv",
|
|
11
|
-
description: "
|
|
12
|
+
description: "csvFile"
|
|
12
13
|
}
|
|
13
14
|
};
|
|
14
15
|
const unsafeName = /[\\/:*?"<>|\u0000-\u001f]/g;
|
|
@@ -70,7 +71,7 @@ const pickFileSink = async (name, format) => {
|
|
|
70
71
|
handle = await pick({
|
|
71
72
|
suggestedName: name,
|
|
72
73
|
types: [{
|
|
73
|
-
description: type.description,
|
|
74
|
+
description: text(type.description),
|
|
74
75
|
accept: { [type.mime]: [type.extension] }
|
|
75
76
|
}]
|
|
76
77
|
});
|
|
@@ -3,6 +3,7 @@ import { keys } from "../../data/query-keys.js";
|
|
|
3
3
|
import { useClient } from "../../data/api-provider.js";
|
|
4
4
|
import { useToast } from "../../toasts/toast-provider.js";
|
|
5
5
|
import { listLabels } from "../../live/relation-labels.js";
|
|
6
|
+
import { text } from "./messages.js";
|
|
6
7
|
import { runExport } from "./run-export.js";
|
|
7
8
|
import { defaultExportColumns, exportColumns, exportHeaders, exportLimit, exportableFields, exportsSelection, selectionFilters } from "./export-options.js";
|
|
8
9
|
import { createWorkerPort } from "./builder-port.js";
|
|
@@ -90,15 +91,15 @@ const useExportFlow = ({ model, view, resources, views, plural, filter, orderBy,
|
|
|
90
91
|
});
|
|
91
92
|
toast.show({
|
|
92
93
|
state: "success",
|
|
93
|
-
title:
|
|
94
|
-
description: result.truncated ?
|
|
94
|
+
title: text("exported", formatInt(result.rows), plural),
|
|
95
|
+
description: result.truncated ? text("truncated", name, formatInt(result.rows)) : name
|
|
95
96
|
});
|
|
96
97
|
} catch (error) {
|
|
97
98
|
if (error instanceof DOMException && error.name === "AbortError") return;
|
|
98
99
|
if (!isApiError(error)) throw error;
|
|
99
100
|
toast.show({
|
|
100
101
|
state: "error",
|
|
101
|
-
title:
|
|
102
|
+
title: text("couldNotExport", plural),
|
|
102
103
|
description: error.message
|
|
103
104
|
});
|
|
104
105
|
} finally {
|
package/dist/app/field-editor.js
CHANGED
|
@@ -2,6 +2,7 @@ import { cn } from "../lib/cn.js";
|
|
|
2
2
|
import { useFieldControl } from "../primitives/field-control.js";
|
|
3
3
|
import { Input } from "../primitives/input.js";
|
|
4
4
|
import { buttonClass } from "../primitives/button.js";
|
|
5
|
+
import { text } from "./messages.js";
|
|
5
6
|
import { humanize } from "../live/naming.js";
|
|
6
7
|
import { isMarkdown } from "../markdown/markdown-hint.js";
|
|
7
8
|
import { contactFormat, contactInputProps } from "../live/contact-links.js";
|
|
@@ -64,8 +65,8 @@ const BuiltInEditor = ({ field, hints, value, stored, relationLabel, relationTo,
|
|
|
64
65
|
children: picker
|
|
65
66
|
}), /* @__PURE__ */ jsx(AppLink, {
|
|
66
67
|
to: relationTo,
|
|
67
|
-
"aria-label":
|
|
68
|
-
title: "
|
|
68
|
+
"aria-label": text("openLabel", relationLabel ?? String(value)),
|
|
69
|
+
title: text("open"),
|
|
69
70
|
className: cn(buttonClass({ variant: "ghost" }), "w-8 px-0"),
|
|
70
71
|
children: /* @__PURE__ */ jsx(ArrowUpRight, { className: "size-4" })
|
|
71
72
|
})]
|
|
@@ -118,7 +119,7 @@ const BuiltInEditor = ({ field, hints, value, stored, relationLabel, relationTo,
|
|
|
118
119
|
className: "h-8 w-full rounded-md border border-border-strong bg-background px-2 shadow-sm focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20",
|
|
119
120
|
children: [value === "" && /* @__PURE__ */ jsx("option", {
|
|
120
121
|
value: "",
|
|
121
|
-
children: "
|
|
122
|
+
children: text("choose")
|
|
122
123
|
}), (field.enumValues ?? []).map((option) => /* @__PURE__ */ jsx("option", {
|
|
123
124
|
value: option,
|
|
124
125
|
children: enumLabel(option, hints?.valueLabels)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { defineMessages } from "../../locale/messages.js";
|
|
2
|
+
//#region src/app/field-types/messages.ts
|
|
3
|
+
const text = defineMessages({
|
|
4
|
+
en: { fieldType: (name) => `The field type ${name}` },
|
|
5
|
+
nl: { fieldType: (name) => `Het veldtype ${name}` }
|
|
6
|
+
});
|
|
7
|
+
//#endregion
|
|
8
|
+
export { text };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CustomBoundary } from "../pages/custom-boundary.js";
|
|
2
|
+
import { text } from "./messages.js";
|
|
2
3
|
import { jsx } from "react/jsx-runtime";
|
|
3
4
|
//#region src/app/field-types/widget-part.tsx
|
|
4
5
|
const partOf = ({ shown, part, field, value, onChange, invalid = false }) => {
|
|
@@ -24,7 +25,7 @@ const WidgetPart = ({ fallback, ...rest }) => {
|
|
|
24
25
|
const element = partOf(rest);
|
|
25
26
|
if (!element) return fallback;
|
|
26
27
|
return /* @__PURE__ */ jsx(CustomBoundary, {
|
|
27
|
-
name:
|
|
28
|
+
name: text("fieldType", rest.shown.name),
|
|
28
29
|
fallback,
|
|
29
30
|
children: element
|
|
30
31
|
});
|
package/dist/app/file-field.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cn } from "../lib/cn.js";
|
|
2
2
|
import { Button } from "../primitives/button.js";
|
|
3
3
|
import { useClient } from "../data/api-provider.js";
|
|
4
|
+
import { text } from "./messages.js";
|
|
4
5
|
import { humanize } from "../live/naming.js";
|
|
5
6
|
import { acceptOf, fileShown, formatSize, isPreviewable, shownImage } from "../live/file-values.js";
|
|
6
7
|
import { ErrorBanner } from "./error-banner.js";
|
|
@@ -32,7 +33,7 @@ const FileSummary = ({ value }) => {
|
|
|
32
33
|
});
|
|
33
34
|
if ("missing" in shown) return /* @__PURE__ */ jsx("div", {
|
|
34
35
|
className: "py-1.5 text-danger-text",
|
|
35
|
-
children: "
|
|
36
|
+
children: text("fileMissing")
|
|
36
37
|
});
|
|
37
38
|
const url = "url" in shown ? shown.url : void 0;
|
|
38
39
|
const corrected = "corrected" in shown ? shown.corrected : void 0;
|
|
@@ -97,33 +98,29 @@ const FileField = ({ field, hints, resource, value, locked, invalid, onChange })
|
|
|
97
98
|
type: "file",
|
|
98
99
|
hidden: true,
|
|
99
100
|
accept: acceptOf(field),
|
|
100
|
-
"aria-label":
|
|
101
|
+
"aria-label": text("chooseFileFor", label),
|
|
101
102
|
onChange: (event) => choose(event.target.files)
|
|
102
103
|
});
|
|
103
104
|
const error = upload.error && /* @__PURE__ */ jsx("div", {
|
|
104
105
|
className: "mt-2",
|
|
105
106
|
children: /* @__PURE__ */ jsx(ErrorBanner, {
|
|
106
|
-
title: "
|
|
107
|
+
title: text("notUploaded"),
|
|
107
108
|
error: upload.error
|
|
108
109
|
})
|
|
109
110
|
});
|
|
110
111
|
if (upload.isPending) return /* @__PURE__ */ jsxs("div", {
|
|
111
112
|
className: "py-1.5",
|
|
112
113
|
role: "status",
|
|
113
|
-
"aria-label":
|
|
114
|
+
"aria-label": text("uploadingLabel", label),
|
|
114
115
|
children: [/* @__PURE__ */ jsx("div", {
|
|
115
116
|
className: "h-1.5 overflow-hidden rounded-full bg-muted",
|
|
116
117
|
children: /* @__PURE__ */ jsx("div", {
|
|
117
118
|
className: "h-full rounded-full bg-primary transition-[width]",
|
|
118
119
|
style: { width: `${Math.round((progress ?? 0) * 100)}%` }
|
|
119
120
|
})
|
|
120
|
-
}), /* @__PURE__ */
|
|
121
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
121
122
|
className: "text-xs text-muted-foreground",
|
|
122
|
-
children:
|
|
123
|
-
"Uploading… ",
|
|
124
|
-
Math.round((progress ?? 0) * 100),
|
|
125
|
-
"%"
|
|
126
|
-
]
|
|
123
|
+
children: text("uploading", Math.round((progress ?? 0) * 100))
|
|
127
124
|
})]
|
|
128
125
|
});
|
|
129
126
|
if (fileShown(value)) return /* @__PURE__ */ jsxs("div", { children: [
|
|
@@ -137,13 +134,13 @@ const FileField = ({ field, hints, resource, value, locked, invalid, onChange })
|
|
|
137
134
|
/* @__PURE__ */ jsx(Button, {
|
|
138
135
|
size: "sm",
|
|
139
136
|
onClick: () => input.current?.click(),
|
|
140
|
-
children: "
|
|
137
|
+
children: text("replace")
|
|
141
138
|
}),
|
|
142
139
|
field.nullable && /* @__PURE__ */ jsx(Button, {
|
|
143
140
|
size: "sm",
|
|
144
141
|
variant: "ghost",
|
|
145
142
|
onClick: () => onChange(null),
|
|
146
|
-
children: "
|
|
143
|
+
children: text("remove")
|
|
147
144
|
})
|
|
148
145
|
]
|
|
149
146
|
}),
|
|
@@ -163,12 +160,12 @@ const FileField = ({ field, hints, resource, value, locked, invalid, onChange })
|
|
|
163
160
|
/* @__PURE__ */ jsx(Upload, { className: "size-4 shrink-0" }),
|
|
164
161
|
/* @__PURE__ */ jsx("span", {
|
|
165
162
|
className: "flex-1",
|
|
166
|
-
children: "
|
|
163
|
+
children: text("dropFile")
|
|
167
164
|
}),
|
|
168
165
|
/* @__PURE__ */ jsxs(Button, {
|
|
169
166
|
size: "sm",
|
|
170
167
|
onClick: () => input.current?.click(),
|
|
171
|
-
children: [/* @__PURE__ */ jsx(Paperclip, { className: "size-3.5" }), "
|
|
168
|
+
children: [/* @__PURE__ */ jsx(Paperclip, { className: "size-3.5" }), text("chooseFile")]
|
|
172
169
|
})
|
|
173
170
|
]
|
|
174
171
|
}),
|
|
@@ -7,6 +7,7 @@ import { useAdminMeta, usePermissions } from "../meta-gate.js";
|
|
|
7
7
|
import { ErrorBanner } from "../error-banner.js";
|
|
8
8
|
import { FileImage } from "../../live/file-image.js";
|
|
9
9
|
import { galleryTiles } from "./gallery-layout.js";
|
|
10
|
+
import { text } from "./messages.js";
|
|
10
11
|
import { Lightbox } from "./lightbox.js";
|
|
11
12
|
import { detailFields } from "./detail-fields.js";
|
|
12
13
|
import { PhotoDetails } from "./photo-details.js";
|
|
@@ -63,7 +64,7 @@ const GallerySection = ({ item, record, recordKey }) => {
|
|
|
63
64
|
if (photos.error) return /* @__PURE__ */ jsx(Section, {
|
|
64
65
|
title: item.title,
|
|
65
66
|
children: /* @__PURE__ */ jsx(ErrorBanner, {
|
|
66
|
-
title: "
|
|
67
|
+
title: text("couldNotLoad"),
|
|
67
68
|
error: photos.error
|
|
68
69
|
})
|
|
69
70
|
});
|
|
@@ -91,7 +92,7 @@ const GallerySection = ({ item, record, recordKey }) => {
|
|
|
91
92
|
const last = index === shown - 1 && more > 0;
|
|
92
93
|
return /* @__PURE__ */ jsxs("button", {
|
|
93
94
|
type: "button",
|
|
94
|
-
"aria-label": last ?
|
|
95
|
+
"aria-label": last ? text("showAll", count) : text("showPhoto", index + 1, count),
|
|
95
96
|
onClick: () => setOpen(index),
|
|
96
97
|
className: cn("group/tile relative overflow-hidden bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary", index === 0 ? "col-span-4 row-span-2" : "max-md:hidden", spans[shown][index]),
|
|
97
98
|
children: [
|
|
@@ -119,7 +120,7 @@ const GallerySection = ({ item, record, recordKey }) => {
|
|
|
119
120
|
onIndex: setOpen,
|
|
120
121
|
onClose: () => setOpen(void 0),
|
|
121
122
|
details,
|
|
122
|
-
detailsTitle: holder &&
|
|
123
|
+
detailsTitle: holder && text("holderDetails", holderView?.names?.singular ?? humanize(holder.name))
|
|
123
124
|
})]
|
|
124
125
|
});
|
|
125
126
|
};
|
|
@@ -6,6 +6,7 @@ import { FileImage } from "../../live/file-image.js";
|
|
|
6
6
|
import { Sheet } from "../../primitives/sheet.js";
|
|
7
7
|
import { keyStep, steppedPhoto, swipeStep, togglesDetails } from "./gallery-layout.js";
|
|
8
8
|
import { readDetailsOpen, writeDetailsOpen } from "./details-open-storage.js";
|
|
9
|
+
import { text } from "./messages.js";
|
|
9
10
|
import { useEffect, useId, useRef, useState } from "react";
|
|
10
11
|
import { ChevronLeft, ChevronRight, Info, X } from "lucide-react";
|
|
11
12
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -18,7 +19,7 @@ const control = "flex size-10 shrink-0 items-center justify-center rounded-full
|
|
|
18
19
|
* lower part of a mobile screen; this browser remembers whether they were left shown. The page does not scroll behind
|
|
19
20
|
* it, and focus returns to what opened it.
|
|
20
21
|
*/
|
|
21
|
-
const Lightbox = ({ title, photos, index, onIndex, onClose, details, detailsTitle = "
|
|
22
|
+
const Lightbox = ({ title, photos, index, onIndex, onClose, details, detailsTitle = text("details") }) => {
|
|
22
23
|
const panel = useRef(null);
|
|
23
24
|
const start = useRef(void 0);
|
|
24
25
|
const sidebarId = useId();
|
|
@@ -97,7 +98,7 @@ const Lightbox = ({ title, photos, index, onIndex, onClose, details, detailsTitl
|
|
|
97
98
|
}), /* @__PURE__ */ jsx("button", {
|
|
98
99
|
type: "button",
|
|
99
100
|
className: control,
|
|
100
|
-
"aria-label": "
|
|
101
|
+
"aria-label": text("close"),
|
|
101
102
|
onClick: onClose,
|
|
102
103
|
children: /* @__PURE__ */ jsx(X, {
|
|
103
104
|
className: "size-4",
|
|
@@ -116,7 +117,7 @@ const Lightbox = ({ title, photos, index, onIndex, onClose, details, detailsTitl
|
|
|
116
117
|
}, image.url), count > 1 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("button", {
|
|
117
118
|
type: "button",
|
|
118
119
|
className: cn(control, "absolute left-3 top-1/2 -translate-y-1/2 aria-disabled:cursor-default aria-disabled:opacity-40"),
|
|
119
|
-
"aria-label": "
|
|
120
|
+
"aria-label": text("previousPhoto"),
|
|
120
121
|
"aria-disabled": index === 0,
|
|
121
122
|
onClick: () => step(-1),
|
|
122
123
|
children: /* @__PURE__ */ jsx(ChevronLeft, {
|
|
@@ -126,7 +127,7 @@ const Lightbox = ({ title, photos, index, onIndex, onClose, details, detailsTitl
|
|
|
126
127
|
}), /* @__PURE__ */ jsx("button", {
|
|
127
128
|
type: "button",
|
|
128
129
|
className: cn(control, "absolute right-3 top-1/2 -translate-y-1/2 aria-disabled:cursor-default aria-disabled:opacity-40"),
|
|
129
|
-
"aria-label": "
|
|
130
|
+
"aria-label": text("nextPhoto"),
|
|
130
131
|
"aria-disabled": index === count - 1,
|
|
131
132
|
onClick: () => step(1),
|
|
132
133
|
children: /* @__PURE__ */ jsx(ChevronRight, {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { defineMessages } from "../../locale/messages.js";
|
|
2
|
+
//#region src/app/gallery/messages.ts
|
|
3
|
+
const text = defineMessages({
|
|
4
|
+
en: {
|
|
5
|
+
couldNotLoad: "Could not load the photos",
|
|
6
|
+
showAll: (count) => `Show all ${count} photos`,
|
|
7
|
+
showPhoto: (index, count) => `Show photo ${index} of ${count}`,
|
|
8
|
+
details: "Details",
|
|
9
|
+
holderDetails: (singular) => `${singular} details`,
|
|
10
|
+
close: "Close",
|
|
11
|
+
previousPhoto: "Previous photo",
|
|
12
|
+
nextPhoto: "Next photo",
|
|
13
|
+
couldNotLoadOne: (singular) => `Could not load the ${singular}`,
|
|
14
|
+
open: (singular) => `Open ${singular}`
|
|
15
|
+
},
|
|
16
|
+
nl: {
|
|
17
|
+
couldNotLoad: "Kon de foto’s niet laden",
|
|
18
|
+
showAll: (count) => `Alle ${count} foto’s tonen`,
|
|
19
|
+
showPhoto: (index, count) => `Foto ${index} van ${count} tonen`,
|
|
20
|
+
details: "Gegevens",
|
|
21
|
+
holderDetails: (singular) => `Gegevens van ${singular.toLowerCase()}`,
|
|
22
|
+
close: "Sluiten",
|
|
23
|
+
previousPhoto: "Vorige foto",
|
|
24
|
+
nextPhoto: "Volgende foto",
|
|
25
|
+
couldNotLoadOne: (singular) => `Kon ${singular} niet laden`,
|
|
26
|
+
open: (singular) => `${singular} openen`
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
//#endregion
|
|
30
|
+
export { text };
|
|
@@ -6,6 +6,7 @@ import { SpecTable } from "../../record-view/spec-table.js";
|
|
|
6
6
|
import { ErrorBanner } from "../error-banner.js";
|
|
7
7
|
import { fieldAccess } from "../permissions.js";
|
|
8
8
|
import { FieldValue } from "../pages/field-value.js";
|
|
9
|
+
import { text } from "./messages.js";
|
|
9
10
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
10
11
|
//#region src/app/gallery/photo-details.tsx
|
|
11
12
|
/**
|
|
@@ -17,7 +18,7 @@ const PhotoDetails = ({ model, view, photoKey, fields }) => {
|
|
|
17
18
|
const singular = (view?.names?.singular ?? humanize(model.name)).toLowerCase();
|
|
18
19
|
if (record.isPending) return /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-48" });
|
|
19
20
|
if (record.error) return /* @__PURE__ */ jsx(ErrorBanner, {
|
|
20
|
-
title:
|
|
21
|
+
title: text("couldNotLoadOne", singular),
|
|
21
22
|
error: record.error
|
|
22
23
|
});
|
|
23
24
|
const shown = fields.filter((name) => fieldAccess(record.data.permissions, name) !== "hidden");
|
|
@@ -35,7 +36,7 @@ const PhotoDetails = ({ model, view, photoKey, fields }) => {
|
|
|
35
36
|
key: photoKey
|
|
36
37
|
},
|
|
37
38
|
className: "mt-3 inline-block font-medium text-primary-text hover:underline",
|
|
38
|
-
children:
|
|
39
|
+
children: text("open", singular)
|
|
39
40
|
})] });
|
|
40
41
|
};
|
|
41
42
|
//#endregion
|