@burojs/ui-shadcn 0.6.0 → 0.7.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.
- package/README.md +9 -0
- package/dist/bulk-summary-BWSAS7k2.js +143 -0
- package/dist/bulk-summary-BWSAS7k2.js.map +1 -0
- package/dist/bulk-summary-CrEij5vq.cjs +143 -0
- package/dist/bulk-summary-CrEij5vq.cjs.map +1 -0
- package/dist/{candidates-relation-picker-B116Bmqi.js → candidates-relation-picker-CS_JZ4Fd.js} +3 -3
- package/dist/{candidates-relation-picker-B116Bmqi.js.map → candidates-relation-picker-CS_JZ4Fd.js.map} +1 -1
- package/dist/{candidates-relation-picker-Cy0rTxvI.cjs → candidates-relation-picker-y5M6_oe4.cjs} +4 -4
- package/dist/{candidates-relation-picker-Cy0rTxvI.cjs.map → candidates-relation-picker-y5M6_oe4.cjs.map} +1 -1
- package/dist/{check-confirm-dialog-bRT8lt0d.js → check-confirm-dialog-2j0gOd7x.js} +384 -108
- package/dist/check-confirm-dialog-2j0gOd7x.js.map +1 -0
- package/dist/{check-confirm-dialog--gPFnEeg.cjs → check-confirm-dialog-C-NHgMST.cjs} +468 -107
- package/dist/check-confirm-dialog-C-NHgMST.cjs.map +1 -0
- package/dist/{dialog-B_rt9S1c.js → dialog-C123sVQ8.js} +4 -4
- package/dist/dialog-C123sVQ8.js.map +1 -0
- package/dist/{dialog-DRNUq9EA.cjs → dialog-vmMdfUWs.cjs} +3 -3
- package/dist/dialog-vmMdfUWs.cjs.map +1 -0
- package/dist/{filter-builder-nXqtM_h4.cjs → filter-builder-DFu0JP-1.cjs} +923 -120
- package/dist/filter-builder-DFu0JP-1.cjs.map +1 -0
- package/dist/{filter-builder-Bhn-dhZV.js → filter-builder-DaWHUZuV.js} +839 -108
- package/dist/filter-builder-DaWHUZuV.js.map +1 -0
- package/dist/{flow-runtime-D3avVH0I.cjs → flow-runtime-BpmrIUb6.cjs} +61 -29
- package/dist/flow-runtime-BpmrIUb6.cjs.map +1 -0
- package/dist/{flow-runtime-s6lkRPKF.js → flow-runtime-DyqTmK3H.js} +62 -30
- package/dist/flow-runtime-DyqTmK3H.js.map +1 -0
- package/dist/{flow-screen-Ci_Sik4Y.cjs → flow-screen-Bcz9NF2V.cjs} +128 -87
- package/dist/flow-screen-Bcz9NF2V.cjs.map +1 -0
- package/dist/{flow-screen-CCvgDI9G.js → flow-screen-DCdli6Ha.js} +128 -87
- package/dist/flow-screen-DCdli6Ha.js.map +1 -0
- package/dist/index.cjs +731 -906
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +455 -247
- package/dist/index.d.ts +455 -247
- package/dist/index.js +647 -828
- package/dist/index.js.map +1 -1
- package/dist/{inline-flow-host-DV1et3c6.cjs → inline-flow-host-3vw7LzzD.cjs} +5 -5
- package/dist/inline-flow-host-3vw7LzzD.cjs.map +1 -0
- package/dist/{inline-flow-host-B6FI0ctQ.js → inline-flow-host-C0rI9B7f.js} +5 -5
- package/dist/inline-flow-host-C0rI9B7f.js.map +1 -0
- package/dist/{candidates-gate-D33jXLHO.cjs → lazy-relation-picker-dialog-Bt8lrEIu.cjs} +10 -10
- package/dist/lazy-relation-picker-dialog-Bt8lrEIu.cjs.map +1 -0
- package/dist/{candidates-gate-Bb70LPAy.js → lazy-relation-picker-dialog-CAScLPb2.js} +11 -11
- package/dist/lazy-relation-picker-dialog-CAScLPb2.js.map +1 -0
- package/dist/{page-flow-route-i3ZfJ1sd.js → page-flow-route-BHUEpn0I.js} +36 -23
- package/dist/page-flow-route-BHUEpn0I.js.map +1 -0
- package/dist/{page-flow-route-hdnULWqd.cjs → page-flow-route-DS8IVTVH.cjs} +41 -28
- package/dist/page-flow-route-DS8IVTVH.cjs.map +1 -0
- package/dist/{place-node-C5SmIAYU.cjs → place-node-CNb3w-c7.cjs} +1869 -947
- package/dist/place-node-CNb3w-c7.cjs.map +1 -0
- package/dist/{place-node-NraNYKPx.js → place-node-CfzQvh4Y.js} +1824 -926
- package/dist/place-node-CfzQvh4Y.js.map +1 -0
- package/dist/{related-list-cards-BWZ9GfOG.js → related-list-cards-BIqqY69Y.js} +9 -4
- package/dist/{related-list-cards-BWZ9GfOG.js.map → related-list-cards-BIqqY69Y.js.map} +1 -1
- package/dist/{related-list-cards-CFq3meUn.cjs → related-list-cards-CelMxl4q.cjs} +9 -4
- package/dist/{related-list-cards-CFq3meUn.cjs.map → related-list-cards-CelMxl4q.cjs.map} +1 -1
- package/dist/{related-list-timeline-yrPsjA3F.js → related-list-timeline-CRh7xwLD.js} +6 -7
- package/dist/related-list-timeline-CRh7xwLD.js.map +1 -0
- package/dist/{related-list-timeline-CCzl71aA.cjs → related-list-timeline-DsLdi8sv.cjs} +5 -6
- package/dist/related-list-timeline-DsLdi8sv.cjs.map +1 -0
- package/dist/{related-rows-o0_t-Yce.js → related-rows--uP2iKQC.js} +25 -14
- package/dist/related-rows--uP2iKQC.js.map +1 -0
- package/dist/{related-rows-ea43qhhy.cjs → related-rows-MPnLCmPF.cjs} +27 -16
- package/dist/related-rows-MPnLCmPF.cjs.map +1 -0
- package/dist/{search-access-CPPmfuvy.js → relation-create-C43cdPQt.js} +595 -13
- package/dist/relation-create-C43cdPQt.js.map +1 -0
- package/dist/{search-access-Dugvttlg.cjs → relation-create-DDEYcKfw.cjs} +633 -14
- package/dist/relation-create-DDEYcKfw.cjs.map +1 -0
- package/dist/{relation-many-picker-bvkjkv-k.js → relation-many-picker-BJhaEqxz.js} +203 -102
- package/dist/relation-many-picker-BJhaEqxz.js.map +1 -0
- package/dist/{relation-many-picker-C8zFEjwd.cjs → relation-many-picker-DzuGJpEl.cjs} +211 -110
- package/dist/relation-many-picker-DzuGJpEl.cjs.map +1 -0
- package/dist/{relation-picker-Z0ZJJ5uS.js → relation-picker-D-tBBZW_.js} +23 -59
- package/dist/relation-picker-D-tBBZW_.js.map +1 -0
- package/dist/{relation-picker-gag0qSR5.cjs → relation-picker-DaIMzf2H.cjs} +29 -71
- package/dist/relation-picker-DaIMzf2H.cjs.map +1 -0
- package/dist/{relation-picker-dialog-0IzkjmiA.cjs → relation-picker-dialog-9Vg5vvR1.cjs} +133 -35
- package/dist/relation-picker-dialog-9Vg5vvR1.cjs.map +1 -0
- package/dist/{relation-picker-dialog-B6nIiJBf.js → relation-picker-dialog-DoEY8EkH.js} +134 -36
- package/dist/relation-picker-dialog-DoEY8EkH.js.map +1 -0
- package/dist/relation-select-B8Fq4o-t.js +48 -0
- package/dist/relation-select-B8Fq4o-t.js.map +1 -0
- package/dist/relation-select-Cr3CfNLy.cjs +55 -0
- package/dist/relation-select-Cr3CfNLy.cjs.map +1 -0
- package/dist/{resource-page-router-PXfMW9nh.cjs → resource-page-router-C_kGW2o_.cjs} +543 -300
- package/dist/resource-page-router-C_kGW2o_.cjs.map +1 -0
- package/dist/{resource-page-router-3RUf9d1j.js → resource-page-router-Diw6S6TK.js} +498 -255
- package/dist/resource-page-router-Diw6S6TK.js.map +1 -0
- package/dist/{rich-text-vTyVjDoa.cjs → rich-text-C_7JCvRo.cjs} +2 -2
- package/dist/{rich-text-vTyVjDoa.cjs.map → rich-text-C_7JCvRo.cjs.map} +1 -1
- package/dist/{rich-text-DFerywgz.js → rich-text-RcPBf6hr.js} +2 -2
- package/dist/{rich-text-DFerywgz.js.map → rich-text-RcPBf6hr.js.map} +1 -1
- package/dist/success-notices-Dl3M1fZP.cjs +46 -0
- package/dist/success-notices-Dl3M1fZP.cjs.map +1 -0
- package/dist/success-notices-LDEgEkc4.js +41 -0
- package/dist/success-notices-LDEgEkc4.js.map +1 -0
- package/dist/{toaster-Cr51X7bz.cjs → toaster-BbByOytP.cjs} +60 -15
- package/dist/toaster-BbByOytP.cjs.map +1 -0
- package/dist/{toaster-C02XbB9r.js → toaster-Ct_YHGs6.js} +43 -16
- package/dist/toaster-Ct_YHGs6.js.map +1 -0
- package/dist/{use-dialog-filter-state-C--oMAZG.js → use-dialog-filter-state-B_MqzHaT.js} +5 -4
- package/dist/use-dialog-filter-state-B_MqzHaT.js.map +1 -0
- package/dist/{use-dialog-filter-state-Dhe8PcB5.cjs → use-dialog-filter-state-tNvqAAjh.cjs} +6 -5
- package/dist/use-dialog-filter-state-tNvqAAjh.cjs.map +1 -0
- package/package.json +11 -11
- package/dist/bulk-summary-CwSd6Yjb.cjs +0 -108
- package/dist/bulk-summary-CwSd6Yjb.cjs.map +0 -1
- package/dist/bulk-summary-GxMDP4bw.js +0 -108
- package/dist/bulk-summary-GxMDP4bw.js.map +0 -1
- package/dist/candidates-gate-Bb70LPAy.js.map +0 -1
- package/dist/candidates-gate-D33jXLHO.cjs.map +0 -1
- package/dist/check-confirm-dialog--gPFnEeg.cjs.map +0 -1
- package/dist/check-confirm-dialog-bRT8lt0d.js.map +0 -1
- package/dist/dialog-B_rt9S1c.js.map +0 -1
- package/dist/dialog-DRNUq9EA.cjs.map +0 -1
- package/dist/filter-builder-Bhn-dhZV.js.map +0 -1
- package/dist/filter-builder-nXqtM_h4.cjs.map +0 -1
- package/dist/flow-runtime-D3avVH0I.cjs.map +0 -1
- package/dist/flow-runtime-s6lkRPKF.js.map +0 -1
- package/dist/flow-screen-CCvgDI9G.js.map +0 -1
- package/dist/flow-screen-Ci_Sik4Y.cjs.map +0 -1
- package/dist/inline-flow-host-B6FI0ctQ.js.map +0 -1
- package/dist/inline-flow-host-DV1et3c6.cjs.map +0 -1
- package/dist/page-flow-route-hdnULWqd.cjs.map +0 -1
- package/dist/page-flow-route-i3ZfJ1sd.js.map +0 -1
- package/dist/place-node-C5SmIAYU.cjs.map +0 -1
- package/dist/place-node-NraNYKPx.js.map +0 -1
- package/dist/related-list-timeline-CCzl71aA.cjs.map +0 -1
- package/dist/related-list-timeline-yrPsjA3F.js.map +0 -1
- package/dist/related-rows-ea43qhhy.cjs.map +0 -1
- package/dist/related-rows-o0_t-Yce.js.map +0 -1
- package/dist/relation-create-IA40t1hi.cjs +0 -364
- package/dist/relation-create-IA40t1hi.cjs.map +0 -1
- package/dist/relation-create-h6F9B4C4.js +0 -339
- package/dist/relation-create-h6F9B4C4.js.map +0 -1
- package/dist/relation-many-picker-C8zFEjwd.cjs.map +0 -1
- package/dist/relation-many-picker-bvkjkv-k.js.map +0 -1
- package/dist/relation-picker-Z0ZJJ5uS.js.map +0 -1
- package/dist/relation-picker-dialog-0IzkjmiA.cjs.map +0 -1
- package/dist/relation-picker-dialog-B6nIiJBf.js.map +0 -1
- package/dist/relation-picker-gag0qSR5.cjs.map +0 -1
- package/dist/resource-page-router-3RUf9d1j.js.map +0 -1
- package/dist/resource-page-router-PXfMW9nh.cjs.map +0 -1
- package/dist/search-access-CPPmfuvy.js.map +0 -1
- package/dist/search-access-Dugvttlg.cjs.map +0 -1
- package/dist/shell-BPlk8hEa.js +0 -205
- package/dist/shell-BPlk8hEa.js.map +0 -1
- package/dist/shell-DxhlsPwm.cjs +0 -271
- package/dist/shell-DxhlsPwm.cjs.map +0 -1
- package/dist/toaster-C02XbB9r.js.map +0 -1
- package/dist/toaster-Cr51X7bz.cjs.map +0 -1
- package/dist/use-dialog-filter-state-C--oMAZG.js.map +0 -1
- package/dist/use-dialog-filter-state-Dhe8PcB5.cjs.map +0 -1
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
const require_use_theme = require("./use-theme-DFlpXils.cjs");
|
|
2
|
-
const require_toaster = require("./toaster-
|
|
3
|
-
const require_check_confirm_dialog = require("./check-confirm-dialog
|
|
2
|
+
const require_toaster = require("./toaster-BbByOytP.cjs");
|
|
3
|
+
const require_check_confirm_dialog = require("./check-confirm-dialog-C-NHgMST.cjs");
|
|
4
4
|
const require_button = require("./button-BxnnE28H.cjs");
|
|
5
5
|
const require_input = require("./input-BI0czGyI.cjs");
|
|
6
|
-
const require_dialog = require("./dialog-
|
|
7
|
-
const
|
|
6
|
+
const require_dialog = require("./dialog-vmMdfUWs.cjs");
|
|
7
|
+
const require_relation_create = require("./relation-create-DDEYcKfw.cjs");
|
|
8
8
|
const require_skeleton = require("./skeleton-_1gP7wan.cjs");
|
|
9
|
-
const require_filter_builder = require("./filter-builder-
|
|
9
|
+
const require_filter_builder = require("./filter-builder-DFu0JP-1.cjs");
|
|
10
10
|
const require_label = require("./label-w6JYf2cF.cjs");
|
|
11
|
+
const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-Bt8lrEIu.cjs");
|
|
12
|
+
const require_relation_select = require("./relation-select-Cr3CfNLy.cjs");
|
|
11
13
|
let _burojs_core = require("@burojs/core");
|
|
12
14
|
let _burojs_react = require("@burojs/react");
|
|
13
15
|
let _tabler_icons_react = require("@tabler/icons-react");
|
|
@@ -120,428 +122,91 @@ function toDisplayText(value) {
|
|
|
120
122
|
}
|
|
121
123
|
}
|
|
122
124
|
//#endregion
|
|
123
|
-
//#region src/
|
|
124
|
-
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
text
|
|
128
|
-
|
|
129
|
-
format: "text"
|
|
130
|
-
},
|
|
131
|
-
textarea: {
|
|
132
|
-
type: "string",
|
|
133
|
-
format: "textarea"
|
|
134
|
-
},
|
|
135
|
-
code: {
|
|
136
|
-
type: "string",
|
|
137
|
-
format: "code"
|
|
138
|
-
},
|
|
139
|
-
email: {
|
|
140
|
-
type: "string",
|
|
141
|
-
format: "email"
|
|
142
|
-
},
|
|
143
|
-
url: {
|
|
144
|
-
type: "string",
|
|
145
|
-
format: "url"
|
|
146
|
-
},
|
|
147
|
-
uuid: {
|
|
148
|
-
type: "string",
|
|
149
|
-
format: "uuid"
|
|
150
|
-
},
|
|
151
|
-
number: { type: "number" },
|
|
152
|
-
boolean: { type: "boolean" },
|
|
153
|
-
date: {
|
|
154
|
-
type: "string",
|
|
155
|
-
format: "date"
|
|
156
|
-
},
|
|
157
|
-
dateTime: {
|
|
158
|
-
type: "string",
|
|
159
|
-
format: "date-time"
|
|
160
|
-
},
|
|
161
|
-
enum: {
|
|
162
|
-
type: "string",
|
|
163
|
-
format: "enum"
|
|
164
|
-
},
|
|
165
|
-
json: {
|
|
166
|
-
type: "object",
|
|
167
|
-
format: "json"
|
|
168
|
-
},
|
|
169
|
-
richText: {
|
|
170
|
-
type: "string",
|
|
171
|
-
format: "rich-text"
|
|
172
|
-
},
|
|
173
|
-
file: {
|
|
174
|
-
type: "array",
|
|
175
|
-
format: "file",
|
|
176
|
-
items: STRING_ITEM
|
|
177
|
-
},
|
|
178
|
-
relation: { type: "relation" },
|
|
179
|
-
relationMany: {
|
|
180
|
-
type: "array",
|
|
181
|
-
format: "relation",
|
|
182
|
-
items: STRING_ITEM
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
|
-
const SEMANTIC_KEYS = Object.freeze([
|
|
186
|
-
"type",
|
|
187
|
-
"format",
|
|
188
|
-
"meta",
|
|
189
|
-
"required",
|
|
190
|
-
"nullable",
|
|
191
|
-
"empty",
|
|
192
|
-
"default",
|
|
193
|
-
"constraints",
|
|
194
|
-
"texts",
|
|
195
|
-
"options",
|
|
196
|
-
"items",
|
|
197
|
-
"properties",
|
|
198
|
-
"additionalProperties",
|
|
199
|
-
"variants"
|
|
200
|
-
]);
|
|
201
|
-
function ownData(value, key) {
|
|
202
|
-
if (value === null || typeof value !== "object" && typeof value !== "function") return { present: false };
|
|
203
|
-
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
204
|
-
if (descriptor === void 0 || !Object.prototype.propertyIsEnumerable.call(value, key) || !("value" in descriptor)) return { present: false };
|
|
205
|
-
return {
|
|
206
|
-
present: true,
|
|
207
|
-
value: descriptor.value
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
function ownString(value, key) {
|
|
211
|
-
const candidate = ownData(value, key).value;
|
|
212
|
-
return typeof candidate === "string" && candidate.length > 0 ? candidate : void 0;
|
|
213
|
-
}
|
|
214
|
-
function projectUiSelection(input) {
|
|
215
|
-
const selection = {};
|
|
216
|
-
const inputId = ownString(input, "input");
|
|
217
|
-
const displayId = ownString(input, "display");
|
|
218
|
-
if (inputId !== void 0) selection.input = inputId;
|
|
219
|
-
if (displayId !== void 0) selection.display = displayId;
|
|
220
|
-
return inputId === void 0 && displayId === void 0 ? void 0 : Object.freeze(selection);
|
|
221
|
-
}
|
|
222
|
-
function projectFieldDeclaration(input) {
|
|
223
|
-
const type = ownString(input, "type");
|
|
224
|
-
if (type === void 0) return void 0;
|
|
225
|
-
const projected = { type };
|
|
226
|
-
for (const key of SEMANTIC_KEYS) {
|
|
227
|
-
if (key === "type" || key === "items" || key === "properties" || key === "variants") continue;
|
|
228
|
-
const candidate = ownData(input, key);
|
|
229
|
-
if (candidate.present && candidate.value !== void 0) projected[key] = candidate.value;
|
|
230
|
-
}
|
|
231
|
-
const ui = projectUiSelection(ownData(input, "ui").value);
|
|
232
|
-
if (ui !== void 0) projected.ui = ui;
|
|
233
|
-
if (type === "array") {
|
|
234
|
-
const item = projectFieldDeclaration(ownData(input, "items").value);
|
|
235
|
-
if (item !== void 0) projected.items = item;
|
|
236
|
-
}
|
|
237
|
-
if (type === "object") {
|
|
238
|
-
const properties = ownData(input, "properties").value;
|
|
239
|
-
if (properties !== null && typeof properties === "object" && !Array.isArray(properties)) {
|
|
240
|
-
const output = {};
|
|
241
|
-
for (const key of Object.keys(properties)) {
|
|
242
|
-
const child = projectFieldDeclaration(ownData(properties, key).value);
|
|
243
|
-
if (child !== void 0) output[key] = child;
|
|
244
|
-
}
|
|
245
|
-
projected.properties = Object.freeze(output);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
if (type === "union") {
|
|
249
|
-
const variants = ownData(input, "variants").value;
|
|
250
|
-
if (Array.isArray(variants)) {
|
|
251
|
-
const output = [];
|
|
252
|
-
for (let index = 0; index < variants.length; index += 1) {
|
|
253
|
-
const child = projectFieldDeclaration(ownData(variants, index).value);
|
|
254
|
-
if (child !== void 0) output.push(child);
|
|
255
|
-
}
|
|
256
|
-
projected.variants = Object.freeze(output);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
return Object.freeze(projected);
|
|
260
|
-
}
|
|
261
|
-
function projectUiHints(input) {
|
|
262
|
-
if (input === null || typeof input !== "object" || Array.isArray(input)) return void 0;
|
|
263
|
-
const projected = {};
|
|
264
|
-
for (const key of Object.keys(input)) {
|
|
265
|
-
const candidate = ownData(input, key);
|
|
266
|
-
if (candidate.present) projected[key] = candidate.value;
|
|
267
|
-
}
|
|
268
|
-
return Object.freeze(projected);
|
|
269
|
-
}
|
|
270
|
-
function lowerLegacyField(field) {
|
|
271
|
-
const declaration = projectFieldDeclaration(ownData(field, "declaration").value);
|
|
272
|
-
if (declaration !== void 0) return declaration;
|
|
273
|
-
const direct = projectFieldDeclaration(field);
|
|
274
|
-
const kind = ownString(field, "kind");
|
|
275
|
-
const mapping = kind === void 0 ? void 0 : LEGACY_KIND_DECLARATIONS[kind];
|
|
276
|
-
if (direct !== void 0) {
|
|
277
|
-
const format = direct.format ?? mapping?.format ?? kind;
|
|
278
|
-
return format === void 0 ? direct : Object.freeze({
|
|
279
|
-
...direct,
|
|
280
|
-
format
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
const ui = projectUiHints(ownData(field, "ui").value);
|
|
284
|
-
const type = kind === "file" && ui?.multiple !== true ? "unknown" : mapping?.type ?? "unknown";
|
|
285
|
-
const format = ownString(field, "format") ?? mapping?.format ?? kind;
|
|
286
|
-
const items = type === "array" ? projectFieldDeclaration(ownData(field, "items").value) ?? mapping?.items ?? STRING_ITEM : void 0;
|
|
287
|
-
const meta = ownData(field, "meta");
|
|
288
|
-
const texts = ownData(field, "texts");
|
|
289
|
-
const required = ownData(field, "required");
|
|
290
|
-
const nullable = ownData(field, "nullable");
|
|
291
|
-
const opts = ownData(field, "opts").value;
|
|
292
|
-
const optionRequired = ownData(opts, "required");
|
|
293
|
-
const optionNullable = ownData(opts, "nullable");
|
|
294
|
-
const requiredValue = required.present ? required.value : optionRequired.value;
|
|
295
|
-
const nullableValue = nullable.present ? nullable.value : optionNullable.value;
|
|
296
|
-
return Object.freeze({
|
|
297
|
-
type,
|
|
298
|
-
...format === void 0 ? {} : { format },
|
|
299
|
-
...items === void 0 ? {} : { items },
|
|
300
|
-
...meta.present && meta.value !== void 0 ? { meta: meta.value } : {},
|
|
301
|
-
...texts.present && texts.value !== void 0 ? { texts: texts.value } : {},
|
|
302
|
-
...requiredValue === true ? { required: true } : {},
|
|
303
|
-
...nullableValue === true ? { nullable: true } : {}
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
function lowerLegacyFieldSource(field) {
|
|
307
|
-
const declaration = lowerLegacyField(field);
|
|
308
|
-
const ui = projectUiHints(ownData(field, "ui").value);
|
|
309
|
-
if (ui === void 0) return declaration;
|
|
310
|
-
return Object.freeze({
|
|
311
|
-
...declaration,
|
|
312
|
-
ui
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
function fieldDescription(field) {
|
|
316
|
-
const declaration = field?.declaration;
|
|
317
|
-
return (0, _burojs_core.declaredText)("field", declaration, "description") ?? (0, _burojs_core.declaredText)("field", field, "description");
|
|
125
|
+
//#region src/data-table/annotate-if-clipped.ts
|
|
126
|
+
function annotateIfClipped(e) {
|
|
127
|
+
const el = e.currentTarget;
|
|
128
|
+
const text = el.scrollWidth > el.clientWidth || Array.from(el.querySelectorAll("*")).some((c) => c.scrollWidth > c.clientWidth) ? (el.textContent ?? "").trim() : "";
|
|
129
|
+
if (text) el.setAttribute("title", text);
|
|
130
|
+
else el.removeAttribute("title");
|
|
318
131
|
}
|
|
319
132
|
//#endregion
|
|
320
|
-
//#region src/fields/
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
const
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (item === null || typeof item !== "object" || Array.isArray(item)) continue;
|
|
335
|
-
const raw = item;
|
|
336
|
-
if (typeof raw.value !== "string" && typeof raw.value !== "number" && typeof raw.value !== "boolean" && raw.value !== null) continue;
|
|
337
|
-
const { value, label, description, ...legacyMeta } = raw;
|
|
338
|
-
if (typeof label !== "string" && process.env.NODE_ENV !== "production" && !warnedObjectLabels.has(`${name}:${value}`)) {
|
|
339
|
-
warnedObjectLabels.add(`${name}:${value}`);
|
|
340
|
-
console.warn(`[buro/ui-shadcn] field '${name}': option '${value}' has a non-string label, so it renders its raw value. Declare a plain string label and put the translations under fields.${name}.options.${value} (see docs/i18n-guide.md).`);
|
|
341
|
-
}
|
|
342
|
-
output.push(Object.freeze({
|
|
343
|
-
value,
|
|
344
|
-
label: typeof label === "string" ? label : String(value),
|
|
345
|
-
...typeof description === "string" ? { description } : {},
|
|
346
|
-
...Object.keys(legacyMeta).length === 0 ? {} : { meta: Object.freeze(legacyMeta) }
|
|
347
|
-
}));
|
|
348
|
-
}
|
|
349
|
-
return Object.freeze(output);
|
|
350
|
-
}
|
|
351
|
-
const readScope = (ctx) => ctx.scope;
|
|
352
|
-
function useFieldRuntimeContext(resource, record, values, metaSources) {
|
|
353
|
-
const scope = (0, _burojs_react.useCtx)(readScope);
|
|
354
|
-
const locale = (0, _burojs_react.useLocale)();
|
|
355
|
-
const caps = (0, _burojs_react.useI18nCaps)((0, _burojs_core.formatEntityRef)(resource));
|
|
356
|
-
const metaSourcesOut = (0, _burojs_react.useFieldMetaSources)({
|
|
357
|
-
record,
|
|
358
|
-
values,
|
|
359
|
-
extra: metaSources
|
|
360
|
-
});
|
|
361
|
-
return (0, react.useMemo)(() => Object.freeze({
|
|
362
|
-
i18n: Object.freeze({
|
|
363
|
-
locale,
|
|
364
|
-
has: caps.has,
|
|
365
|
-
t: caps.t
|
|
366
|
-
}),
|
|
367
|
-
sources: Object.freeze({
|
|
368
|
-
record: record ?? EMPTY,
|
|
369
|
-
values: values ?? EMPTY,
|
|
370
|
-
scope: scope ?? EMPTY
|
|
371
|
-
}),
|
|
372
|
-
metaSources: metaSourcesOut
|
|
373
|
-
}), [
|
|
374
|
-
caps,
|
|
375
|
-
locale,
|
|
376
|
-
record,
|
|
377
|
-
scope,
|
|
378
|
-
values,
|
|
379
|
-
metaSourcesOut
|
|
380
|
-
]);
|
|
381
|
-
}
|
|
382
|
-
function useFieldMetaDiagnostic(state, resource, name, field, surface) {
|
|
383
|
-
const reported = (0, react.useRef)(void 0);
|
|
384
|
-
const reason = state.status === "failed" ? state.reason : void 0;
|
|
385
|
-
(0, react.useEffect)(() => {
|
|
386
|
-
if (reason === void 0 || reported.current === reason || process.env.NODE_ENV === "production") return;
|
|
387
|
-
reported.current = reason;
|
|
388
|
-
const named = field.ui?.[surface];
|
|
389
|
-
const implementation = typeof named === "string" ? named : field.format ?? field.type;
|
|
390
|
-
console.error(`[burojs] field.meta-invalid: ${(0, _burojs_core.formatEntityRef)(resource)}.${name} (${implementation}): ${reason}`);
|
|
391
|
-
}, [
|
|
392
|
-
reason,
|
|
393
|
-
resource,
|
|
394
|
-
name,
|
|
395
|
-
field,
|
|
396
|
-
surface
|
|
397
|
-
]);
|
|
398
|
-
}
|
|
399
|
-
function MetaPlaceholder({ state }) {
|
|
133
|
+
//#region src/fields/field-value-frame.tsx
|
|
134
|
+
const COPY_CLASSES = [
|
|
135
|
+
"string",
|
|
136
|
+
"number",
|
|
137
|
+
"date"
|
|
138
|
+
];
|
|
139
|
+
const COPIED_MS = 2e3;
|
|
140
|
+
const isRecord$1 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
141
|
+
const isEmpty = (value) => value === null || value === void 0 || value === "";
|
|
142
|
+
function copyText(value) {
|
|
143
|
+
if (value instanceof Date) return value.toISOString();
|
|
144
|
+
return typeof value === "string" ? value : String(value);
|
|
145
|
+
}
|
|
146
|
+
function FieldValueFrame({ field, value, surface, entry, children }) {
|
|
400
147
|
const t = (0, _burojs_react.useOptionalT)();
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
"data-buro-field-meta": "pending",
|
|
404
|
-
className: "h-9 w-full"
|
|
405
|
-
});
|
|
406
|
-
return (0, react_jsx_runtime.jsx)("div", {
|
|
407
|
-
role: "alert",
|
|
408
|
-
"data-buro-field-meta": "failed",
|
|
409
|
-
className: "rounded-md border border-dashed px-3 py-2 text-sm text-muted-foreground",
|
|
410
|
-
children: t("field.misconfigured", { defaultValue: "This field is misconfigured" })
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
function useFieldImplementationDiagnostic(diagnostic) {
|
|
414
|
-
const reported = (0, react.useRef)(void 0);
|
|
148
|
+
const clipboard = (0, _burojs_react.useClipboard)();
|
|
149
|
+
const [copied, setCopied] = (0, react.useState)(false);
|
|
415
150
|
(0, react.useEffect)(() => {
|
|
416
|
-
if (
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
}, [
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
const
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
});
|
|
428
|
-
const runtimeContext = useFieldRuntimeContext(resource, record, record, metaSources);
|
|
429
|
-
const metaState = (0, _burojs_react.useFieldMeta)(field, resolved.implementation, runtimeContext.metaSources);
|
|
430
|
-
useFieldMetaDiagnostic(metaState, resource, name, field, "display");
|
|
431
|
-
useFieldImplementationDiagnostic(resolved.diagnostic);
|
|
432
|
-
if (resolved.Component === void 0) return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: fallback });
|
|
433
|
-
if (metaState.status !== "ready") return (0, react_jsx_runtime.jsx)(MetaPlaceholder, { state: metaState });
|
|
434
|
-
const Component = resolved.Component;
|
|
435
|
-
const context = {
|
|
436
|
-
owner: resource,
|
|
437
|
-
resource,
|
|
151
|
+
if (!copied) return;
|
|
152
|
+
const timer = setTimeout(() => setCopied(false), COPIED_MS);
|
|
153
|
+
return () => clearTimeout(timer);
|
|
154
|
+
}, [copied]);
|
|
155
|
+
const ui = isRecord$1(field.ui) ? field.ui : void 0;
|
|
156
|
+
const asksCopy = ui?.copy === true;
|
|
157
|
+
const valueClass = (0, react.useMemo)(() => asksCopy ? (0, _burojs_core.displayClassOf)({
|
|
158
|
+
...require_filter_builder.lowerLegacyField(field),
|
|
159
|
+
...ui === void 0 ? {} : { ui }
|
|
160
|
+
}) : void 0, [
|
|
161
|
+
asksCopy,
|
|
438
162
|
field,
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
};
|
|
454
|
-
if (resolved.multiple) return (0, react.createElement)(Component, {
|
|
455
|
-
...context,
|
|
456
|
-
multiple: true,
|
|
457
|
-
value: Array.isArray(value) ? value : []
|
|
458
|
-
});
|
|
459
|
-
return (0, react.createElement)(Component, {
|
|
460
|
-
...context,
|
|
461
|
-
multiple: false,
|
|
462
|
-
value
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
function ResolvedFieldInput({ resource, name, field: source, value, record, form, testId, inputId, onChange, onBlur, disabled, required, placeholder, descriptionId, errorId, errorMessage, pending = false, touched = errorMessage != null, issues: suppliedIssues, relationSeeds, fixedFilters, metaSources, fallback }) {
|
|
466
|
-
const sourceAtEdge = lowerLegacyFieldSource(source);
|
|
467
|
-
const base = canonical(sourceAtEdge);
|
|
468
|
-
const field = required === void 0 || required === base.required ? base : Object.freeze({
|
|
469
|
-
...base,
|
|
470
|
-
required
|
|
471
|
-
});
|
|
472
|
-
const ui = Object.freeze({
|
|
473
|
-
...sourceAtEdge.ui ?? EMPTY,
|
|
474
|
-
...placeholder === void 0 ? {} : { placeholder }
|
|
475
|
-
});
|
|
476
|
-
const resolved = (0, _burojs_react.useFieldImplementation)({
|
|
477
|
-
field: {
|
|
478
|
-
...field,
|
|
479
|
-
ui
|
|
480
|
-
},
|
|
481
|
-
surface: "input"
|
|
163
|
+
ui
|
|
164
|
+
]);
|
|
165
|
+
const { overflow: declared } = (0, _burojs_core.resolveSurfaceUi)(field, surface, entry);
|
|
166
|
+
const copyable = asksCopy && clipboard !== void 0 && !isEmpty(value) && valueClass !== void 0 && COPY_CLASSES.includes(valueClass);
|
|
167
|
+
if (!copyable && declared === void 0) return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children });
|
|
168
|
+
const body = (declared ?? (surface === "column" ? "truncate" : "wrap")) === "wrap" ? (0, react_jsx_runtime.jsx)("span", {
|
|
169
|
+
className: "min-w-0 whitespace-normal [overflow-wrap:anywhere]",
|
|
170
|
+
"data-buro-overflow": "wrap",
|
|
171
|
+
children
|
|
172
|
+
}) : (0, react_jsx_runtime.jsx)("span", {
|
|
173
|
+
className: "inline-block min-w-0 max-w-full truncate align-bottom",
|
|
174
|
+
"data-buro-overflow": "truncate",
|
|
175
|
+
onPointerEnter: annotateIfClipped,
|
|
176
|
+
children
|
|
482
177
|
});
|
|
483
|
-
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
const Component = resolved.Component;
|
|
490
|
-
const issues = suppliedIssues ?? (errorMessage == null ? EMPTY_ISSUES$1 : Object.freeze([Object.freeze({
|
|
491
|
-
code: "ui.field-error",
|
|
492
|
-
message: {
|
|
493
|
-
key: "ui.field-error",
|
|
494
|
-
default: errorMessage
|
|
495
|
-
},
|
|
496
|
-
path: Object.freeze([]),
|
|
497
|
-
source: "field",
|
|
498
|
-
severity: "error"
|
|
499
|
-
})]));
|
|
500
|
-
const context = {
|
|
501
|
-
owner: resource,
|
|
502
|
-
resource,
|
|
503
|
-
field,
|
|
504
|
-
path: Object.freeze([name]),
|
|
505
|
-
surface: "input",
|
|
506
|
-
presentation: "default",
|
|
507
|
-
record,
|
|
508
|
-
form,
|
|
509
|
-
meta: metaState.meta,
|
|
510
|
-
ui,
|
|
511
|
-
options: optionsFor(field, name),
|
|
512
|
-
i18n: runtimeContext.i18n,
|
|
513
|
-
sources: runtimeContext.sources,
|
|
514
|
-
pending,
|
|
515
|
-
touched,
|
|
516
|
-
issues,
|
|
517
|
-
accessibility: Object.freeze({
|
|
518
|
-
input: inputId ?? name,
|
|
519
|
-
description: descriptionId,
|
|
520
|
-
error: errorId
|
|
521
|
-
}),
|
|
522
|
-
testIds: testId === void 0 ? EMPTY : Object.freeze({ input: testId })
|
|
178
|
+
if (!copyable) return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: body });
|
|
179
|
+
const label = t("field.copy", { defaultValue: "Copy" });
|
|
180
|
+
const copy = (event) => {
|
|
181
|
+
event.preventDefault();
|
|
182
|
+
event.stopPropagation();
|
|
183
|
+
clipboard(copyText(value)).then(() => setCopied(true), () => void 0);
|
|
523
184
|
};
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
185
|
+
return (0, react_jsx_runtime.jsxs)("span", {
|
|
186
|
+
className: "inline-flex min-w-0 max-w-full items-center gap-1 align-bottom",
|
|
187
|
+
children: [
|
|
188
|
+
body,
|
|
189
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
190
|
+
type: "button",
|
|
191
|
+
"data-testid": `field-copy:${field.name}`,
|
|
192
|
+
"aria-label": label,
|
|
193
|
+
title: label,
|
|
194
|
+
onClick: copy,
|
|
195
|
+
className: "inline-flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
196
|
+
children: copied ? (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconCheck, {
|
|
197
|
+
"aria-hidden": "true",
|
|
198
|
+
className: "size-3.5"
|
|
199
|
+
}) : (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconCopy, {
|
|
200
|
+
"aria-hidden": "true",
|
|
201
|
+
className: "size-3.5"
|
|
202
|
+
})
|
|
203
|
+
}),
|
|
204
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
205
|
+
"aria-live": "polite",
|
|
206
|
+
className: "sr-only",
|
|
207
|
+
children: copied ? t("field.copied", { defaultValue: "Copied" }) : ""
|
|
208
|
+
})
|
|
209
|
+
]
|
|
545
210
|
});
|
|
546
211
|
}
|
|
547
212
|
//#endregion
|
|
@@ -555,7 +220,7 @@ function resolveRef(resource, i18nPrefix) {
|
|
|
555
220
|
};
|
|
556
221
|
}
|
|
557
222
|
function Field({ resource, i18nPrefix, fallback, fixedFilters, field, doc, ...rest }) {
|
|
558
|
-
const input = (0, react_jsx_runtime.jsx)(ResolvedFieldInput, {
|
|
223
|
+
const input = (0, react_jsx_runtime.jsx)(require_filter_builder.ResolvedFieldInput, {
|
|
559
224
|
...rest,
|
|
560
225
|
field,
|
|
561
226
|
...fixedFilters === void 0 ? {} : { fixedFilters },
|
|
@@ -581,20 +246,30 @@ function Field({ resource, i18nPrefix, fallback, fixedFilters, field, doc, ...re
|
|
|
581
246
|
});
|
|
582
247
|
}
|
|
583
248
|
function FieldDisplay({ resource, i18nPrefix, fallback, value, ...rest }) {
|
|
584
|
-
|
|
585
|
-
...rest,
|
|
249
|
+
const frameField = (0, react.useMemo)(() => ({
|
|
250
|
+
...rest.field,
|
|
251
|
+
name: rest.name
|
|
252
|
+
}), [rest.field, rest.name]);
|
|
253
|
+
return (0, react_jsx_runtime.jsx)(FieldValueFrame, {
|
|
254
|
+
field: frameField,
|
|
586
255
|
value,
|
|
587
|
-
|
|
588
|
-
|
|
256
|
+
surface: "display",
|
|
257
|
+
children: (0, react_jsx_runtime.jsx)(require_filter_builder.ResolvedFieldDisplay, {
|
|
258
|
+
...rest,
|
|
259
|
+
value,
|
|
260
|
+
resource: resolveRef(resource, i18nPrefix),
|
|
261
|
+
fallback: fallback ?? (0, react_jsx_runtime.jsx)("span", { children: value == null || value === "" ? "—" : String(value) })
|
|
262
|
+
})
|
|
589
263
|
});
|
|
590
264
|
}
|
|
591
265
|
//#endregion
|
|
592
266
|
//#region src/screen/field-leaf.tsx
|
|
593
267
|
const SIZES = new Set(_burojs_core.LAYOUT_SIZES);
|
|
268
|
+
const SHOWN_ISSUES = 3;
|
|
594
269
|
const FOCUSABLE = "input:not([type=\"hidden\"]):not([disabled]), textarea:not([disabled]), select:not([disabled]), button:not([disabled]), [contenteditable=\"true\"], [tabindex]:not([tabindex=\"-1\"])";
|
|
595
270
|
function useLeafSize(field) {
|
|
596
271
|
const implementation = (0, _burojs_react.useFieldImplementation)({
|
|
597
|
-
field: lowerLegacyField(field),
|
|
272
|
+
field: require_filter_builder.lowerLegacyField(field),
|
|
598
273
|
surface: "input"
|
|
599
274
|
});
|
|
600
275
|
const declared = field.ui?.size;
|
|
@@ -625,7 +300,7 @@ function MisconfiguredLeaf({ node }) {
|
|
|
625
300
|
const binding = controller.field(name);
|
|
626
301
|
const caps = (0, _burojs_react.useI18nCaps)(resource);
|
|
627
302
|
const tid = (0, _burojs_react.useTestIds)();
|
|
628
|
-
const field = lowerLegacyField(binding.field);
|
|
303
|
+
const field = require_filter_builder.lowerLegacyField(binding.field);
|
|
629
304
|
const surface = mode === "show" ? "display" : "input";
|
|
630
305
|
const resolved = (0, _burojs_react.useFieldImplementation)({
|
|
631
306
|
field,
|
|
@@ -636,8 +311,8 @@ function MisconfiguredLeaf({ node }) {
|
|
|
636
311
|
values: controller.values,
|
|
637
312
|
extra: controller.sources
|
|
638
313
|
});
|
|
639
|
-
const state = (0, _burojs_react.useFieldMeta)(field, resolved.implementation, sources);
|
|
640
|
-
useFieldMetaDiagnostic(state, binding.resource, name, field, surface);
|
|
314
|
+
const state = (0, _burojs_react.useFieldMeta)(field, resolved.implementation, sources, resolved.params);
|
|
315
|
+
require_filter_builder.useFieldMetaDiagnostic(state, binding.resource, name, field, surface);
|
|
641
316
|
const label = (0, _burojs_core.resolveFieldLabel)(caps, name, (0, _burojs_core.declaredText)("field", binding.field, "label"));
|
|
642
317
|
const testId = leafIds === "record" ? tid.formField(resource, mode, name) : `${leafIds.prefix}:field:${name}`;
|
|
643
318
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -651,7 +326,7 @@ function MisconfiguredLeaf({ node }) {
|
|
|
651
326
|
children: label
|
|
652
327
|
}), (0, react_jsx_runtime.jsx)("div", {
|
|
653
328
|
"data-buro-region": "field-control",
|
|
654
|
-
children: (0, react_jsx_runtime.jsx)(MetaPlaceholder, { state })
|
|
329
|
+
children: (0, react_jsx_runtime.jsx)(require_filter_builder.MetaPlaceholder, { state })
|
|
655
330
|
})]
|
|
656
331
|
});
|
|
657
332
|
}
|
|
@@ -668,10 +343,7 @@ function RecordLeaf({ node }) {
|
|
|
668
343
|
const t = (0, _burojs_react.useOptionalT)();
|
|
669
344
|
if (node.restricted === true) {
|
|
670
345
|
const rawReason = node.restrictedReason;
|
|
671
|
-
const reason = rawReason === void 0 || rawReason === "" ? void 0 :
|
|
672
|
-
resource,
|
|
673
|
-
default: rawReason
|
|
674
|
-
});
|
|
346
|
+
const reason = rawReason === void 0 || rawReason === "" ? void 0 : require_check_confirm_dialog.reasonText(caps, rawReason, resource);
|
|
675
347
|
const restrictedId = tid.formFieldRestricted(resource, mode, name);
|
|
676
348
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
677
349
|
...attributes,
|
|
@@ -734,10 +406,7 @@ function RecordLeaf({ node }) {
|
|
|
734
406
|
});
|
|
735
407
|
if (node.editable !== true) {
|
|
736
408
|
const rawReason = node.lockReason;
|
|
737
|
-
const reason = rawReason === void 0 ? void 0 :
|
|
738
|
-
resource,
|
|
739
|
-
default: rawReason
|
|
740
|
-
});
|
|
409
|
+
const reason = rawReason === void 0 ? void 0 : require_check_confirm_dialog.reasonText(caps, rawReason, resource);
|
|
741
410
|
const locked = tid.formFieldLocked(resource, mode, name);
|
|
742
411
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
743
412
|
...attributes,
|
|
@@ -789,7 +458,6 @@ function RecordLeaf({ node }) {
|
|
|
789
458
|
function ActiveLeaf({ node, binding, label, attributes, inputId }) {
|
|
790
459
|
const { resource, mode, controller, disabled: locked } = useScreenTree();
|
|
791
460
|
const caps = (0, _burojs_react.useI18nCaps)(resource);
|
|
792
|
-
const t = (0, _burojs_react.useOptionalT)();
|
|
793
461
|
const tid = (0, _burojs_react.useTestIds)();
|
|
794
462
|
const name = binding.name;
|
|
795
463
|
const record = controller.record;
|
|
@@ -804,25 +472,22 @@ function ActiveLeaf({ node, binding, label, attributes, inputId }) {
|
|
|
804
472
|
});
|
|
805
473
|
const messageId = `${mode}-${name}-msg`;
|
|
806
474
|
const placeholder = (0, _burojs_core.resolveFieldSlot)(caps, name, "placeholder");
|
|
807
|
-
const hint = (0, _burojs_core.resolveFieldSlot)(caps, name, "description", fieldDescription(binding.field));
|
|
475
|
+
const hint = (0, _burojs_core.resolveFieldSlot)(caps, name, "description", require_filter_builder.fieldDescription(binding.field));
|
|
476
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
808
477
|
const fieldKey = `resources.${resource}.fields.${name}`;
|
|
809
|
-
const
|
|
810
|
-
code:
|
|
811
|
-
message:
|
|
812
|
-
...
|
|
813
|
-
}, {
|
|
814
|
-
t,
|
|
815
|
-
fieldKey
|
|
816
|
-
});
|
|
817
|
-
const warning = errorText === null ? binding.warnings[0] : void 0;
|
|
818
|
-
const warningText = warning === void 0 ? null : (0, _burojs_react.resolveValidationMessage)({
|
|
819
|
-
code: warning.code ?? "",
|
|
820
|
-
message: warning.message,
|
|
821
|
-
...warning.params === void 0 ? {} : { params: warning.params }
|
|
478
|
+
const text = (issue) => (0, _burojs_react.resolveValidationMessage)({
|
|
479
|
+
code: issue.code ?? "",
|
|
480
|
+
message: issue.message,
|
|
481
|
+
...issue.check === void 0 ? {} : { check: issue.check }
|
|
822
482
|
}, {
|
|
823
|
-
|
|
483
|
+
has: caps.has,
|
|
484
|
+
t: caps.t,
|
|
824
485
|
fieldKey
|
|
825
486
|
});
|
|
487
|
+
const shown = binding.issues.slice(0, SHOWN_ISSUES);
|
|
488
|
+
const more = binding.issues.length - shown.length;
|
|
489
|
+
const firstError = shown.find((issue) => issue.severity === "error");
|
|
490
|
+
const errorText = firstError === void 0 ? null : text(firstError);
|
|
826
491
|
const disabled = binding.disabled || controller.isSubmitting || locked === true;
|
|
827
492
|
const describedBy = errorText === null && hint ? messageId : void 0;
|
|
828
493
|
const errorMessageId = errorText === null ? void 0 : messageId;
|
|
@@ -836,6 +501,7 @@ function ActiveLeaf({ node, binding, label, attributes, inputId }) {
|
|
|
836
501
|
"data-buro-region": "field-label",
|
|
837
502
|
className: "flex items-center gap-2",
|
|
838
503
|
children: [(0, react_jsx_runtime.jsx)(require_label.Label, {
|
|
504
|
+
id: `${inputId}-label`,
|
|
839
505
|
htmlFor: inputId,
|
|
840
506
|
required: binding.required,
|
|
841
507
|
children: label
|
|
@@ -851,6 +517,7 @@ function ActiveLeaf({ node, binding, label, attributes, inputId }) {
|
|
|
851
517
|
resource: binding.resource,
|
|
852
518
|
name,
|
|
853
519
|
inputId,
|
|
520
|
+
labelId: `${inputId}-label`,
|
|
854
521
|
field: binding.field,
|
|
855
522
|
value: binding.value,
|
|
856
523
|
onChange: binding.onChange,
|
|
@@ -864,8 +531,10 @@ function ActiveLeaf({ node, binding, label, attributes, inputId }) {
|
|
|
864
531
|
...describedBy === void 0 ? {} : { descriptionId: describedBy },
|
|
865
532
|
...errorMessageId === void 0 ? {} : { errorId: errorMessageId },
|
|
866
533
|
errorMessage: errorText,
|
|
534
|
+
issues: binding.issues,
|
|
867
535
|
...binding.fixedFilters === void 0 ? {} : { fixedFilters: binding.fixedFilters },
|
|
868
536
|
...binding.relationSeeds === void 0 ? {} : { relationSeeds: binding.relationSeeds },
|
|
537
|
+
...binding.link === void 0 ? {} : { link: binding.link },
|
|
869
538
|
fallback: (0, react_jsx_runtime.jsx)(require_input.Input, {
|
|
870
539
|
id: inputId,
|
|
871
540
|
name: inputId,
|
|
@@ -880,18 +549,23 @@ function ActiveLeaf({ node, binding, label, attributes, inputId }) {
|
|
|
880
549
|
...errorMessageId === void 0 ? {} : { "aria-errormessage": errorMessageId },
|
|
881
550
|
onChange: (event) => binding.onChange(event.target.value)
|
|
882
551
|
})
|
|
883
|
-
}),
|
|
552
|
+
}), shown.length > 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
884
553
|
id: messageId,
|
|
885
554
|
"aria-live": "polite",
|
|
886
|
-
className: "text-sm text-destructive",
|
|
887
|
-
"data-testid": tid.formFieldError(resource, mode, name),
|
|
888
|
-
children:
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
555
|
+
className: require_use_theme.cn("space-y-0.5 text-sm", errorText === null ? "text-warning-emphasis" : "text-destructive"),
|
|
556
|
+
"data-testid": errorText === null ? `form-field-warning:${resource}:${mode}:${name}` : tid.formFieldError(resource, mode, name),
|
|
557
|
+
children: [shown.map((issue, index) => (0, react_jsx_runtime.jsx)("p", {
|
|
558
|
+
"data-buro-severity": issue.severity,
|
|
559
|
+
className: issue.severity === "error" ? "text-destructive" : "text-warning-emphasis",
|
|
560
|
+
children: text(issue)
|
|
561
|
+
}, index)), more > 0 ? (0, react_jsx_runtime.jsx)("p", {
|
|
562
|
+
className: "text-muted-foreground",
|
|
563
|
+
"data-testid": `form-field-more:${resource}:${mode}:${name}`,
|
|
564
|
+
children: chromeT("validation.moreIssues", {
|
|
565
|
+
count: more,
|
|
566
|
+
defaultValue: "+{{count}} more"
|
|
567
|
+
})
|
|
568
|
+
}) : null]
|
|
895
569
|
}) : hint ? (0, react_jsx_runtime.jsx)("p", {
|
|
896
570
|
id: messageId,
|
|
897
571
|
"data-testid": tid.formFieldHelp(resource, mode, name),
|
|
@@ -911,7 +585,7 @@ function DeclarativeLeaf({ node, prefix, inputIds }) {
|
|
|
911
585
|
const docRef = (0, _burojs_core.i18nPrefixToRef)(prefix);
|
|
912
586
|
const docScope = docRef.namespace === "default" ? docRef.id : (0, _burojs_core.formatEntityRef)(docRef);
|
|
913
587
|
const caps = (0, _burojs_react.useI18nCaps)(docScope);
|
|
914
|
-
const
|
|
588
|
+
const issueCaps = (0, _burojs_react.useI18nCaps)();
|
|
915
589
|
const uid = (0, react.useId)();
|
|
916
590
|
const root = (0, react.useRef)(null);
|
|
917
591
|
const inputId = `${inputIds ?? uid}-${name}`;
|
|
@@ -924,7 +598,7 @@ function DeclarativeLeaf({ node, prefix, inputIds }) {
|
|
|
924
598
|
element.querySelector(FOCUSABLE)?.focus();
|
|
925
599
|
});
|
|
926
600
|
const label = (0, _burojs_core.resolveFieldLabel)(caps, name, (0, _burojs_core.declaredText)("field", binding.field, "label"));
|
|
927
|
-
const hint = (0, _burojs_core.resolveFieldSlot)(caps, name, "description", fieldDescription(binding.field));
|
|
601
|
+
const hint = (0, _burojs_core.resolveFieldSlot)(caps, name, "description", require_filter_builder.fieldDescription(binding.field));
|
|
928
602
|
const info = (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.DocInfo, {
|
|
929
603
|
address: `${docScope}/fields/${name}`,
|
|
930
604
|
name: label,
|
|
@@ -965,9 +639,10 @@ function DeclarativeLeaf({ node, prefix, inputIds }) {
|
|
|
965
639
|
const text = (issue) => (0, _burojs_react.resolveValidationMessage)({
|
|
966
640
|
code: issue.code ?? "",
|
|
967
641
|
message: issue.message,
|
|
968
|
-
...issue.
|
|
642
|
+
...issue.check === void 0 ? {} : { check: issue.check }
|
|
969
643
|
}, {
|
|
970
|
-
|
|
644
|
+
has: issueCaps.has,
|
|
645
|
+
t: issueCaps.t,
|
|
971
646
|
fieldKey
|
|
972
647
|
});
|
|
973
648
|
const defaultNode = (0, react_jsx_runtime.jsx)(Field, {
|
|
@@ -975,6 +650,7 @@ function DeclarativeLeaf({ node, prefix, inputIds }) {
|
|
|
975
650
|
field: binding.field,
|
|
976
651
|
metaSources: controller.sources,
|
|
977
652
|
inputId,
|
|
653
|
+
labelId: `${inputId}-label`,
|
|
978
654
|
i18nPrefix: prefix,
|
|
979
655
|
disabled: disabled === true || binding.disabled
|
|
980
656
|
});
|
|
@@ -990,6 +666,7 @@ function DeclarativeLeaf({ node, prefix, inputIds }) {
|
|
|
990
666
|
"data-buro-region": "field-label",
|
|
991
667
|
className: "flex items-center gap-2",
|
|
992
668
|
children: [(0, react_jsx_runtime.jsx)(require_label.Label, {
|
|
669
|
+
id: `${inputId}-label`,
|
|
993
670
|
htmlFor: inputId,
|
|
994
671
|
required: binding.required,
|
|
995
672
|
children: label
|
|
@@ -1030,9 +707,10 @@ function Notice({ children }) {
|
|
|
1030
707
|
children
|
|
1031
708
|
});
|
|
1032
709
|
}
|
|
1033
|
-
function FactsView({ props }) {
|
|
710
|
+
function FactsView({ props, empty }) {
|
|
1034
711
|
const own = props;
|
|
1035
712
|
const t = (0, _burojs_react.useOptionalT)();
|
|
713
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
1036
714
|
const snapshot = (0, _burojs_react.useApplicationSnapshot)();
|
|
1037
715
|
const queryId = (0, _burojs_core.formatEntityRef)(own.query);
|
|
1038
716
|
const caps = (0, _burojs_react.useI18nCaps)();
|
|
@@ -1049,7 +727,10 @@ function FactsView({ props }) {
|
|
|
1049
727
|
kind: "custom-query",
|
|
1050
728
|
ref: own.query
|
|
1051
729
|
}), [own.query]);
|
|
1052
|
-
const result = (0, _burojs_react.useCustomQuery)(handle, blocked ? {} : input, {
|
|
730
|
+
const result = (0, _burojs_react.useCustomQuery)(handle, blocked ? {} : input, {
|
|
731
|
+
enabled: !blocked,
|
|
732
|
+
...own.refetchInterval === void 0 ? {} : { refetchInterval: own.refetchInterval }
|
|
733
|
+
});
|
|
1053
734
|
const shown = (0, react.useMemo)(() => {
|
|
1054
735
|
const byName = new Map(fields.map((field) => [field.name, field]));
|
|
1055
736
|
return (own.rows ?? fields.map((field) => field.name)).flatMap((name) => {
|
|
@@ -1057,7 +738,7 @@ function FactsView({ props }) {
|
|
|
1057
738
|
return field === void 0 ? [] : [field];
|
|
1058
739
|
});
|
|
1059
740
|
}, [fields, own.rows]);
|
|
1060
|
-
if (blocked) return (0, react_jsx_runtime.jsx)(Notice, { children: own.missing ?? t("facts.empty", { defaultValue: "No data" }) });
|
|
741
|
+
if (blocked) return (0, react_jsx_runtime.jsx)(Notice, { children: own.missing ?? empty ?? t("facts.empty", { defaultValue: "No data" }) });
|
|
1061
742
|
if (result.isError) return (0, react_jsx_runtime.jsxs)("div", {
|
|
1062
743
|
role: "alert",
|
|
1063
744
|
className: "flex flex-wrap items-center gap-2 rounded-md border border-dashed px-3 py-2 text-sm text-muted-foreground",
|
|
@@ -1066,7 +747,7 @@ function FactsView({ props }) {
|
|
|
1066
747
|
variant: "outline",
|
|
1067
748
|
size: "sm",
|
|
1068
749
|
onClick: () => void result.refetch(),
|
|
1069
|
-
children:
|
|
750
|
+
children: chromeT("actions.retry", { defaultValue: "Retry" })
|
|
1070
751
|
})]
|
|
1071
752
|
});
|
|
1072
753
|
if (result.data === void 0) return own.view === "list" ? (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, {
|
|
@@ -1080,7 +761,7 @@ function FactsView({ props }) {
|
|
|
1080
761
|
}, field.name))
|
|
1081
762
|
});
|
|
1082
763
|
const data = result.data;
|
|
1083
|
-
if (data === null || typeof data !== "object" || shown.length === 0) return (0, react_jsx_runtime.jsx)(Notice, { children: own.missing ?? t("facts.empty", { defaultValue: "No data" }) });
|
|
764
|
+
if (data === null || typeof data !== "object" || shown.length === 0) return (0, react_jsx_runtime.jsx)(Notice, { children: own.missing ?? empty ?? t("facts.empty", { defaultValue: "No data" }) });
|
|
1084
765
|
const pairs = shown.map((field) => {
|
|
1085
766
|
const value = data[field.name];
|
|
1086
767
|
const label = (0, _burojs_core.resolveContentSlot)(caps, [`queries.${queryId}.fields.${field.name}.label`, `queries.${queryId}.fields.${field.name}`], {
|
|
@@ -1090,13 +771,18 @@ function FactsView({ props }) {
|
|
|
1090
771
|
const body = value === null || value === void 0 ? (0, react_jsx_runtime.jsx)("span", {
|
|
1091
772
|
className: "text-muted-foreground",
|
|
1092
773
|
children: "—"
|
|
1093
|
-
}) : (0, react_jsx_runtime.jsx)(
|
|
1094
|
-
resource: own.query,
|
|
1095
|
-
name: field.name,
|
|
774
|
+
}) : (0, react_jsx_runtime.jsx)(FieldValueFrame, {
|
|
1096
775
|
field,
|
|
1097
776
|
value,
|
|
1098
|
-
|
|
1099
|
-
|
|
777
|
+
surface: "display",
|
|
778
|
+
children: (0, react_jsx_runtime.jsx)(require_filter_builder.ResolvedFieldDisplay, {
|
|
779
|
+
resource: own.query,
|
|
780
|
+
name: field.name,
|
|
781
|
+
field,
|
|
782
|
+
value,
|
|
783
|
+
record: data,
|
|
784
|
+
fallback: toDisplayText(value).text
|
|
785
|
+
})
|
|
1100
786
|
});
|
|
1101
787
|
return {
|
|
1102
788
|
name: field.name,
|
|
@@ -1150,6 +836,9 @@ const PlacementFrameContext = (0, react.createContext)(null);
|
|
|
1150
836
|
function usePlacementFrame() {
|
|
1151
837
|
return (0, react.useContext)(PlacementFrameContext);
|
|
1152
838
|
}
|
|
839
|
+
function placementLayoutId(frame) {
|
|
840
|
+
return frame?.owner === void 0 ? void 0 : `${frame.owner}/${frame.key.split(".").join("/")}`;
|
|
841
|
+
}
|
|
1153
842
|
//#endregion
|
|
1154
843
|
//#region src/flows/app-flow-button.tsx
|
|
1155
844
|
function AppFlowButton({ action, variant = "ghost", size = "sm", className }) {
|
|
@@ -1269,7 +958,7 @@ function RecordInlineFlow({ name }) {
|
|
|
1269
958
|
return (0, react_jsx_runtime.jsx)(InlineHostLoader, {
|
|
1270
959
|
resource,
|
|
1271
960
|
name: flowName,
|
|
1272
|
-
|
|
961
|
+
...hostRecord((0, _burojs_core.flowRecordOf)(compiled, row)),
|
|
1273
962
|
placementKey: key,
|
|
1274
963
|
lease: kept,
|
|
1275
964
|
stale: true,
|
|
@@ -1285,7 +974,7 @@ function RecordInlineFlow({ name }) {
|
|
|
1285
974
|
if (control.state === "disabled" && kept !== void 0 && kept.dirty) return (0, react_jsx_runtime.jsx)(InlineHostLoader, {
|
|
1286
975
|
resource,
|
|
1287
976
|
name: flowName,
|
|
1288
|
-
|
|
977
|
+
...hostRecord((0, _burojs_core.flowRecordOf)(compiled, row)),
|
|
1289
978
|
placementKey: key,
|
|
1290
979
|
lease: kept,
|
|
1291
980
|
stale: true,
|
|
@@ -1297,11 +986,12 @@ function RecordInlineFlow({ name }) {
|
|
|
1297
986
|
return (0, react_jsx_runtime.jsx)(InlineHostLoader, {
|
|
1298
987
|
resource,
|
|
1299
988
|
name: flowName,
|
|
1300
|
-
|
|
989
|
+
...hostRecord((0, _burojs_core.flowRecordOf)(compiled, control.record ?? row)),
|
|
1301
990
|
placementKey: key,
|
|
1302
991
|
...lease === void 0 ? {} : { lease }
|
|
1303
992
|
});
|
|
1304
993
|
}
|
|
994
|
+
const hostRecord = (record) => record === void 0 ? {} : { record };
|
|
1305
995
|
function InlineHostLoader(props) {
|
|
1306
996
|
const loaded = require_check_confirm_dialog.useLoaded(require_check_confirm_dialog.loadInlineFlowHost);
|
|
1307
997
|
if (loaded.error !== void 0) return (0, react_jsx_runtime.jsx)("p", {
|
|
@@ -1517,6 +1207,7 @@ function placementSeeds(where, resolved, closure) {
|
|
|
1517
1207
|
where.forEach((entry, index) => {
|
|
1518
1208
|
const value = resolved[index]?.value;
|
|
1519
1209
|
if (entry.op !== "eq" || value === null || value === void 0) return;
|
|
1210
|
+
if (typeof entry.field !== "string" || entry.field.includes(".")) return;
|
|
1520
1211
|
if (resolved[index]?.field !== entry.field) return;
|
|
1521
1212
|
const source = refSource(entry.value);
|
|
1522
1213
|
if (source === null ? isLiteral(entry.value) : source === "record" || source === "user" || !UNTRUSTED.includes(source) && Object.hasOwn(closure, source) && !(closure[source] ?? []).some((input) => UNTRUSTED.includes(input))) seeds[entry.field] = value;
|
|
@@ -1534,7 +1225,8 @@ function BadgeBody({ icon, label }) {
|
|
|
1534
1225
|
}) : null, label]
|
|
1535
1226
|
});
|
|
1536
1227
|
}
|
|
1537
|
-
function EnumBadge({ enumName, value, testid, className, presentation }) {
|
|
1228
|
+
function EnumBadge({ enumName: enumInput, value, testid, className, presentation }) {
|
|
1229
|
+
const enumName = (0, _burojs_core_internal.enumBindingKey)(enumInput) ?? "";
|
|
1538
1230
|
const app = (0, _burojs_react.useApp)();
|
|
1539
1231
|
const caps = (0, _burojs_react.useI18nCaps)();
|
|
1540
1232
|
const def = app.registry.enums.get(enumName);
|
|
@@ -1680,6 +1372,7 @@ function useExportRunWatcher() {
|
|
|
1680
1372
|
const runtime = (0, _burojs_react.useDataRuntime)();
|
|
1681
1373
|
const runs = (0, _burojs_react.useExportRuns)();
|
|
1682
1374
|
const t = (0, _burojs_react.useOptionalT)();
|
|
1375
|
+
const caps = (0, _burojs_react.useI18nCaps)();
|
|
1683
1376
|
react.useEffect(() => {
|
|
1684
1377
|
const announced = announcedRunsFor(runtime);
|
|
1685
1378
|
const unsubscribes = runs.map((run) => {
|
|
@@ -1698,7 +1391,7 @@ function useExportRunWatcher() {
|
|
|
1698
1391
|
label: t("export.toast.download"),
|
|
1699
1392
|
onClick: () => downloadArtifact(artifact)
|
|
1700
1393
|
} });
|
|
1701
|
-
} else if (state.status === "failed") sonner.toast.error(t("export.toast.failed", { params: { message: state.error
|
|
1394
|
+
} else if (state.status === "failed") sonner.toast.error(t("export.toast.failed", { params: { message: (0, _burojs_react.resolveErrorText)(state.error, caps) } }));
|
|
1702
1395
|
};
|
|
1703
1396
|
check();
|
|
1704
1397
|
return run.handle.subscribe(check);
|
|
@@ -1709,24 +1402,27 @@ function useExportRunWatcher() {
|
|
|
1709
1402
|
}, [
|
|
1710
1403
|
runs,
|
|
1711
1404
|
runtime,
|
|
1712
|
-
t
|
|
1405
|
+
t,
|
|
1406
|
+
caps
|
|
1713
1407
|
]);
|
|
1714
1408
|
}
|
|
1715
1409
|
//#endregion
|
|
1716
1410
|
//#region src/actions/action-overflow.tsx
|
|
1717
1411
|
const RowActionsCollapseContext = (0, react.createContext)(false);
|
|
1718
|
-
function ActionOverflow({ resource, record, surface, className, hideFlows, collapse }) {
|
|
1719
|
-
const
|
|
1412
|
+
function ActionOverflow({ resource: resourceInput, record, surface, className, hideFlows, collapse, sources }) {
|
|
1413
|
+
const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
|
|
1414
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
1720
1415
|
const tid = (0, _burojs_react.useTestIds)();
|
|
1416
|
+
const recordKey = String((0, _burojs_react.recordKeyOf)((0, _burojs_react.useApp)().registry.get(resource), record) ?? "");
|
|
1721
1417
|
const collapsedRows = (0, react.useContext)(RowActionsCollapseContext);
|
|
1722
1418
|
const [flowFor, setFlowFor] = (0, react.useState)(null);
|
|
1723
|
-
const actions = useShownItemActions(resource, record, surface, hideFlows);
|
|
1419
|
+
const actions = useShownItemActions(resource, record, surface, hideFlows, sources);
|
|
1724
1420
|
if (actions.length === 0) return null;
|
|
1725
1421
|
const isRow = surface === "row";
|
|
1726
1422
|
const folded = isRow && (collapse ?? collapsedRows);
|
|
1727
1423
|
const standalone = folded ? [] : actions.filter((a) => a.placement === "standalone");
|
|
1728
1424
|
const menu = folded ? actions : actions.filter((a) => a.placement === "menu");
|
|
1729
|
-
const menuTestId = isRow ? tid.listRowActionsMenu(resource,
|
|
1425
|
+
const menuTestId = isRow ? tid.listRowActionsMenu(resource, recordKey) : tid.formActionsMenu(resource, surface);
|
|
1730
1426
|
const firstDestructive = menu.findIndex((a) => a.variant === "destructive");
|
|
1731
1427
|
const overlays = (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: flowFor != null ? (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.RuntimeFlowRunner, {
|
|
1732
1428
|
resource,
|
|
@@ -1740,6 +1436,7 @@ function ActionOverflow({ resource, record, surface, className, hideFlows, colla
|
|
|
1740
1436
|
actionName: a.name,
|
|
1741
1437
|
record,
|
|
1742
1438
|
scope: surface,
|
|
1439
|
+
...sources === void 0 ? {} : { sources },
|
|
1743
1440
|
density: a.density
|
|
1744
1441
|
}, a.name));
|
|
1745
1442
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -1763,7 +1460,7 @@ function ActionOverflow({ resource, record, surface, className, hideFlows, colla
|
|
|
1763
1460
|
size: "icon",
|
|
1764
1461
|
className: "size-7",
|
|
1765
1462
|
"data-testid": menuTestId,
|
|
1766
|
-
"aria-label":
|
|
1463
|
+
"aria-label": chromeT("actions.more", { defaultValue: "More" }),
|
|
1767
1464
|
children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconDots, {
|
|
1768
1465
|
className: "h-4 w-4",
|
|
1769
1466
|
"aria-hidden": "true"
|
|
@@ -1777,15 +1474,16 @@ function ActionOverflow({ resource, record, surface, className, hideFlows, colla
|
|
|
1777
1474
|
children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconDots, {
|
|
1778
1475
|
className: "h-4 w-4",
|
|
1779
1476
|
"aria-hidden": "true"
|
|
1780
|
-
}),
|
|
1477
|
+
}), chromeT("actions.more", { defaultValue: "More" })]
|
|
1781
1478
|
})
|
|
1782
1479
|
}), (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.DropdownMenuContent, {
|
|
1783
1480
|
align: "end",
|
|
1784
|
-
children: menu.map((a, index) => (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [index === firstDestructive && index > 0 && (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.DropdownMenuSeparator, { "data-testid": isRow ? `list-row-actions-separator:${resource}:${
|
|
1481
|
+
children: menu.map((a, index) => (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [index === firstDestructive && index > 0 && (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.DropdownMenuSeparator, { "data-testid": isRow ? `list-row-actions-separator:${resource}:${recordKey}` : `form-actions-separator:${resource}:${surface}` }), a.flow === void 0 ? (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.ActionButton, {
|
|
1785
1482
|
resource,
|
|
1786
1483
|
actionName: a.name,
|
|
1787
1484
|
record,
|
|
1788
1485
|
scope: surface,
|
|
1486
|
+
...sources === void 0 ? {} : { sources },
|
|
1789
1487
|
asMenuItem: true
|
|
1790
1488
|
}) : (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.FlowMenuItem, {
|
|
1791
1489
|
resource,
|
|
@@ -1805,11 +1503,12 @@ function ActionOverflow({ resource, record, surface, className, hideFlows, colla
|
|
|
1805
1503
|
]
|
|
1806
1504
|
});
|
|
1807
1505
|
}
|
|
1808
|
-
function useShownItemActions(resource, record, surface, hideFlows) {
|
|
1506
|
+
function useShownItemActions(resource, record, surface, hideFlows, sources) {
|
|
1809
1507
|
const resolved = (0, _burojs_react.useItemActions)({
|
|
1810
1508
|
resource,
|
|
1811
1509
|
record,
|
|
1812
|
-
surface
|
|
1510
|
+
surface,
|
|
1511
|
+
...sources === void 0 ? {} : { sources }
|
|
1813
1512
|
});
|
|
1814
1513
|
const def = (0, _burojs_react.useApp)().registry.get(resource);
|
|
1815
1514
|
const shown = def !== void 0 && (0, _burojs_core.isBuiltinItemAction)((def.actions?.item)?.find((action) => action.name === "edit"), "edit") && !(0, _burojs_core.recordEntries)(def).page.edit && (0, _burojs_core.recordEntries)(def).quick.edit === null ? resolved.filter((a) => a.name !== "edit") : resolved;
|
|
@@ -1902,8 +1601,14 @@ function DocumentTitleProvider({ routeKey, children }) {
|
|
|
1902
1601
|
});
|
|
1903
1602
|
}
|
|
1904
1603
|
//#endregion
|
|
1604
|
+
//#region src/resource/resource-title.ts
|
|
1605
|
+
function resolveResourceTitle(caps, t, resource, slot, params) {
|
|
1606
|
+
return (0, _burojs_core.resolveContentSlot)(caps, [`resources.${resource}.${slot}`], { params: { ...params } }) ?? t(`pageHeader.${slot}`, { params: { ...params } });
|
|
1607
|
+
}
|
|
1608
|
+
//#endregion
|
|
1905
1609
|
//#region src/resource/page-header.tsx
|
|
1906
|
-
function PageHeader({ resource, mode, recordName, backHref, backLabel, actions, title, breadcrumbs, backLink = false, visibleTitle = false, labelOverride, className }) {
|
|
1610
|
+
function PageHeader({ resource: resourceInput, mode, recordName, backHref, backLabel, actions, title, breadcrumbs, backLink = false, visibleTitle = false, labelOverride, className }) {
|
|
1611
|
+
const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
|
|
1907
1612
|
const app = (0, _burojs_react.useApp)();
|
|
1908
1613
|
const t = (0, _burojs_react.useT)();
|
|
1909
1614
|
const def = app.registry.get(resource);
|
|
@@ -1912,10 +1617,10 @@ function PageHeader({ resource, mode, recordName, backHref, backLabel, actions,
|
|
|
1912
1617
|
const resourceSingle = (0, _burojs_core.resolveResourceLabel)(caps, resource, "single", def);
|
|
1913
1618
|
const labelSingle = labelOverride ?? resourceSingle;
|
|
1914
1619
|
const labelPlural = (0, _burojs_core.resolveResourceLabel)(caps, resource, "plural", def);
|
|
1915
|
-
const computedTitle = title ?? (mode === "list" ? labelPlural : mode === "show" ? recordName ?? labelSingle : mode === "edit" ? recordName ? t
|
|
1620
|
+
const computedTitle = title ?? (mode === "list" ? labelPlural : mode === "show" ? recordName ?? labelSingle : mode === "edit" ? recordName ? resolveResourceTitle(caps, t, resource, "editTitleNamed", {
|
|
1916
1621
|
label: labelSingle,
|
|
1917
1622
|
name: recordName
|
|
1918
|
-
}
|
|
1623
|
+
}) : resolveResourceTitle(caps, t, resource, "editTitle", { label: labelSingle }) : resolveResourceTitle(caps, t, resource, "createTitle", { label: labelSingle }));
|
|
1919
1624
|
useDocumentTitle(app?.name ? `${computedTitle} · ${app.name}` : computedTitle);
|
|
1920
1625
|
const showBack = backLink && mode !== "list" && !breadcrumbs;
|
|
1921
1626
|
const computedBackHref = backHref ?? def?.basePath ?? `/${resource}`;
|
|
@@ -1946,9 +1651,10 @@ function PageHeader({ resource, mode, recordName, backHref, backLabel, actions,
|
|
|
1946
1651
|
]
|
|
1947
1652
|
});
|
|
1948
1653
|
}
|
|
1949
|
-
function ShowPageHeader({ resource, record, extraActions, breadcrumbs }) {
|
|
1654
|
+
function ShowPageHeader({ resource: resourceInput, record, extraActions, breadcrumbs }) {
|
|
1655
|
+
const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
|
|
1950
1656
|
const def = (0, _burojs_react.useApp)().registry.get(resource);
|
|
1951
|
-
const recordName = (0, _burojs_react.useProjectedTitle)(resource, record
|
|
1657
|
+
const recordName = (0, _burojs_react.useProjectedTitle)(resource, (0, _burojs_react.recordKeyOf)(def, record), record);
|
|
1952
1658
|
(0, _burojs_react.usePublishDocVariant)(resource, record);
|
|
1953
1659
|
if (!def) return null;
|
|
1954
1660
|
return (0, react_jsx_runtime.jsx)(PageHeader, {
|
|
@@ -1963,16 +1669,18 @@ function ShowPageHeader({ resource, record, extraActions, breadcrumbs }) {
|
|
|
1963
1669
|
}), extraActions] })
|
|
1964
1670
|
});
|
|
1965
1671
|
}
|
|
1966
|
-
function EditPageHeader({ resource, record, backHref, breadcrumbs }) {
|
|
1672
|
+
function EditPageHeader({ resource: resourceInput, record, backHref, breadcrumbs }) {
|
|
1673
|
+
const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
|
|
1967
1674
|
const app = (0, _burojs_react.useApp)();
|
|
1968
1675
|
const def = app.registry.get(resource);
|
|
1969
1676
|
const caps = (0, _burojs_react.useI18nCaps)(resource);
|
|
1970
|
-
const
|
|
1677
|
+
const recordKey = (0, _burojs_react.recordKeyOf)(def, record);
|
|
1678
|
+
const recordName = (0, _burojs_react.useProjectedTitle)(resource, recordKey, record);
|
|
1971
1679
|
return (0, react_jsx_runtime.jsx)(PageHeader, {
|
|
1972
1680
|
resource,
|
|
1973
1681
|
mode: "edit",
|
|
1974
1682
|
recordName,
|
|
1975
|
-
backHref: editBackHref(app.registry, resource, String(
|
|
1683
|
+
backHref: editBackHref(app.registry, resource, String(recordKey ?? ""), backHref),
|
|
1976
1684
|
breadcrumbs,
|
|
1977
1685
|
backLabel: recordName ? `${(0, _burojs_core.resolveResourceLabel)(caps, resource, "single", def)}: ${recordName}` : void 0,
|
|
1978
1686
|
actions: (0, react_jsx_runtime.jsx)(ActionOverflow, {
|
|
@@ -2172,7 +1880,8 @@ function ItemNode({ node, row, fallback }) {
|
|
|
2172
1880
|
const viewProps = {
|
|
2173
1881
|
props,
|
|
2174
1882
|
data: {},
|
|
2175
|
-
t: placement.viewProps?.t ?? ((name) => name)
|
|
1883
|
+
t: placement.viewProps?.t ?? ((name) => name),
|
|
1884
|
+
...placement.viewProps?.empty === void 0 ? {} : { empty: placement.viewProps.empty }
|
|
2176
1885
|
};
|
|
2177
1886
|
return (0, react_jsx_runtime.jsx)(View, { ...viewProps });
|
|
2178
1887
|
}
|
|
@@ -2254,6 +1963,7 @@ function BuroPanelFrame({ body, title, description, collapsible, open, onToggle,
|
|
|
2254
1963
|
const t = (0, _burojs_react.useOptionalT)();
|
|
2255
1964
|
return (0, react_jsx_runtime.jsxs)("section", {
|
|
2256
1965
|
...nodeAttributes,
|
|
1966
|
+
...title === void 0 ? {} : { "aria-labelledby": titleId },
|
|
2257
1967
|
children: [
|
|
2258
1968
|
title === void 0 && info === null && !collapsible ? null : (0, react_jsx_runtime.jsxs)("div", {
|
|
2259
1969
|
"data-buro-region": "panel-title",
|
|
@@ -2313,7 +2023,6 @@ function BuroTabsFrame({ tabs, active, onSelect, info, nodeAttributes }) {
|
|
|
2313
2023
|
}), info]
|
|
2314
2024
|
}), tabs.map((tab) => (0, react_jsx_runtime.jsx)(TabsContent, {
|
|
2315
2025
|
value: tab.key,
|
|
2316
|
-
forceMount: true,
|
|
2317
2026
|
"data-buro-region": "tab-panel",
|
|
2318
2027
|
"data-buro-key": tab.key,
|
|
2319
2028
|
children: tab.panel
|
|
@@ -2401,17 +2110,17 @@ function BuroStepsFrame({ wizard, steps, goTo, back, next, headingRef, info, nod
|
|
|
2401
2110
|
//#region src/primitives/checkbox.tsx
|
|
2402
2111
|
const Checkbox = react.forwardRef(({ className, checked, ...props }, ref) => (0, react_jsx_runtime.jsx)(_radix_ui_react_checkbox.Root, {
|
|
2403
2112
|
ref,
|
|
2404
|
-
className: require_use_theme.cn("peer h-4 w-4 shrink-0 rounded-
|
|
2113
|
+
className: require_use_theme.cn("peer inline-flex h-4 w-4 shrink-0 items-center justify-center align-middle rounded-[4px] border border-primary ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground", className),
|
|
2405
2114
|
checked,
|
|
2406
2115
|
...props,
|
|
2407
2116
|
children: (0, react_jsx_runtime.jsx)(_radix_ui_react_checkbox.Indicator, {
|
|
2408
2117
|
className: require_use_theme.cn("flex items-center justify-center text-current"),
|
|
2409
2118
|
children: checked === "indeterminate" ? (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconMinus, {
|
|
2410
2119
|
"data-icon": "minus",
|
|
2411
|
-
className: "
|
|
2120
|
+
className: "size-3.5"
|
|
2412
2121
|
}) : (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconCheck, {
|
|
2413
2122
|
"data-icon": "check",
|
|
2414
|
-
className: "
|
|
2123
|
+
className: "size-3.5"
|
|
2415
2124
|
})
|
|
2416
2125
|
})
|
|
2417
2126
|
}));
|
|
@@ -2436,6 +2145,17 @@ function useContainerNarrow(maxRem = 40) {
|
|
|
2436
2145
|
return [setElement, narrow];
|
|
2437
2146
|
}
|
|
2438
2147
|
//#endregion
|
|
2148
|
+
//#region src/data-table/fill-column.ts
|
|
2149
|
+
function fillColumnId(columns) {
|
|
2150
|
+
const eligible = columns.filter((c) => !c.pinned && !c.service);
|
|
2151
|
+
const declared = eligible.find((c) => c.fill);
|
|
2152
|
+
if (declared !== void 0) return declared.id;
|
|
2153
|
+
for (let i = eligible.length - 1; i >= 0; i--) {
|
|
2154
|
+
const c = eligible[i];
|
|
2155
|
+
if (c.resize && c.max === void 0) return c.id;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
//#endregion
|
|
2439
2159
|
//#region src/data-table/data-table.tsx
|
|
2440
2160
|
function pinEdgeClass(isLastLeft, isFirstRight) {
|
|
2441
2161
|
if (isLastLeft) return "after:pointer-events-none after:absolute after:inset-y-0 after:left-full after:z-10 after:w-1.5 after:bg-gradient-to-r after:from-overlay/[0.07] after:to-transparent dark:after:from-overlay/30";
|
|
@@ -2447,7 +2167,8 @@ function pinEdgeClassFor(column, overflowing) {
|
|
|
2447
2167
|
if (!pinned || !overflowing) return "";
|
|
2448
2168
|
return pinEdgeClass(pinned === "left" && column.getIsLastColumn("left"), pinned === "right" && column.getIsFirstColumn("right"));
|
|
2449
2169
|
}
|
|
2450
|
-
function getPinStyles(column, overflowing) {
|
|
2170
|
+
function getPinStyles(column, overflowing, fill = false) {
|
|
2171
|
+
if (fill) return {};
|
|
2451
2172
|
const explicitWidth = { width: `calc(var(--col-${column.id}-size) * 1px)` };
|
|
2452
2173
|
const pinned = column.getIsPinned();
|
|
2453
2174
|
if (!pinned || !overflowing) return explicitWidth;
|
|
@@ -2472,21 +2193,35 @@ function columnMetaNoRowNav(meta) {
|
|
|
2472
2193
|
function columnMetaNoClip(meta) {
|
|
2473
2194
|
return meta?.noClip === true;
|
|
2474
2195
|
}
|
|
2475
|
-
function
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2196
|
+
function columnMetaWrap(meta) {
|
|
2197
|
+
return meta?.wrap === true;
|
|
2198
|
+
}
|
|
2199
|
+
function columnMetaFill(meta) {
|
|
2200
|
+
return meta?.fill === true;
|
|
2201
|
+
}
|
|
2202
|
+
function tableFillColumnId(table) {
|
|
2203
|
+
if (table.options.enableColumnResizing !== true) return void 0;
|
|
2204
|
+
return fillColumnId(table.getVisibleLeafColumns().map((c) => {
|
|
2205
|
+
const max = c.columnDef.maxSize;
|
|
2206
|
+
return {
|
|
2207
|
+
id: c.id,
|
|
2208
|
+
fill: columnMetaFill(c.columnDef.meta),
|
|
2209
|
+
resize: c.getCanResize(),
|
|
2210
|
+
...max !== void 0 && max < Number.MAX_SAFE_INTEGER ? { max } : {},
|
|
2211
|
+
pinned: c.getIsPinned() !== false,
|
|
2212
|
+
service: c.id.startsWith("__")
|
|
2213
|
+
};
|
|
2214
|
+
}));
|
|
2480
2215
|
}
|
|
2481
|
-
function renderCellMarkup({ cell, resizable, overflowing, testId, onCellClick, noRowNav }) {
|
|
2216
|
+
function renderCellMarkup({ cell, resizable, overflowing, fill, testId, onCellClick, noRowNav }) {
|
|
2482
2217
|
const liveColumn = cell.getContext().table.getColumn(cell.column.id) ?? cell.column;
|
|
2483
2218
|
const pinEdge = pinEdgeClassFor(liveColumn, overflowing);
|
|
2484
|
-
const noClip = columnMetaNoClip(cell.column.columnDef.meta);
|
|
2219
|
+
const noClip = columnMetaNoClip(cell.column.columnDef.meta) || columnMetaWrap(cell.column.columnDef.meta);
|
|
2485
2220
|
return (0, react_jsx_runtime.jsx)(require_filter_builder.TableCell, {
|
|
2486
2221
|
"data-testid": testId,
|
|
2487
2222
|
"data-no-row-nav": columnMetaNoRowNav(cell.column.columnDef.meta) || noRowNav ? "" : void 0,
|
|
2488
2223
|
onClick: onCellClick,
|
|
2489
|
-
style: getPinStyles(liveColumn, overflowing),
|
|
2224
|
+
style: getPinStyles(liveColumn, overflowing, fill),
|
|
2490
2225
|
className: require_use_theme.cn(resizable && !pinEdge && !noClip && "overflow-hidden", pinEdge && "relative", pinEdge, columnMetaClassName(cell.column.columnDef.meta), onCellClick && "cursor-pointer"),
|
|
2491
2226
|
children: resizable && !noClip ? (0, react_jsx_runtime.jsx)("div", {
|
|
2492
2227
|
className: "truncate",
|
|
@@ -2498,7 +2233,7 @@ function renderCellMarkup({ cell, resizable, overflowing, testId, onCellClick, n
|
|
|
2498
2233
|
function MemoCellInner(props) {
|
|
2499
2234
|
return renderCellMarkup(props);
|
|
2500
2235
|
}
|
|
2501
|
-
const MemoCell = (0, react.memo)(MemoCellInner, (prev, next) => prev.rowOriginal === next.rowOriginal && prev.cell.column.id === next.cell.column.id && prev.resizable === next.resizable && (!prev.pinned && !next.pinned || prev.overflowing === next.overflowing) && prev.pinned === next.pinned && prev.testId === next.testId);
|
|
2236
|
+
const MemoCell = (0, react.memo)(MemoCellInner, (prev, next) => prev.rowOriginal === next.rowOriginal && prev.cell.column.id === next.cell.column.id && prev.resizable === next.resizable && (!prev.pinned && !next.pinned || prev.overflowing === next.overflowing) && prev.pinned === next.pinned && prev.fill === next.fill && prev.testId === next.testId);
|
|
2502
2237
|
function SelectionCellInner(props) {
|
|
2503
2238
|
const row = props.cell.row;
|
|
2504
2239
|
const toggle = (e) => {
|
|
@@ -2512,7 +2247,7 @@ function SelectionCellInner(props) {
|
|
|
2512
2247
|
});
|
|
2513
2248
|
}
|
|
2514
2249
|
const SelectionCell = (0, react.memo)(SelectionCellInner);
|
|
2515
|
-
function DataRowInner({ row, isSelected, resizable, overflowing, selectionColumnId, getCellTestId, getRowTestId, rowHref, onRowOpen, activateRow, rowClassName }) {
|
|
2250
|
+
function DataRowInner({ row, isSelected, resizable, overflowing, fillColumnId, selectionColumnId, getCellTestId, getRowTestId, rowHref, onRowOpen, activateRow, rowClassName }) {
|
|
2516
2251
|
const clickable = rowHref !== void 0 || onRowOpen !== void 0;
|
|
2517
2252
|
return (0, react_jsx_runtime.jsx)(require_filter_builder.TableRow, {
|
|
2518
2253
|
"data-state": isSelected ? "selected" : void 0,
|
|
@@ -2525,6 +2260,7 @@ function DataRowInner({ row, isSelected, resizable, overflowing, selectionColumn
|
|
|
2525
2260
|
isSelected,
|
|
2526
2261
|
resizable,
|
|
2527
2262
|
overflowing,
|
|
2263
|
+
fill: cell.column.id === fillColumnId,
|
|
2528
2264
|
pinned: cell.getContext().table.getColumn(cell.column.id)?.getIsPinned() ?? false,
|
|
2529
2265
|
testId: getCellTestId?.(row.original, cell.column.id)
|
|
2530
2266
|
}, cell.id) : (0, react_jsx_runtime.jsx)(MemoCell, {
|
|
@@ -2532,13 +2268,14 @@ function DataRowInner({ row, isSelected, resizable, overflowing, selectionColumn
|
|
|
2532
2268
|
rowOriginal: row.original,
|
|
2533
2269
|
resizable,
|
|
2534
2270
|
overflowing,
|
|
2271
|
+
fill: cell.column.id === fillColumnId,
|
|
2535
2272
|
pinned: cell.getContext().table.getColumn(cell.column.id)?.getIsPinned() ?? false,
|
|
2536
2273
|
testId: getCellTestId?.(row.original, cell.column.id)
|
|
2537
2274
|
}, cell.id))
|
|
2538
2275
|
});
|
|
2539
2276
|
}
|
|
2540
|
-
const MemoRow = (0, react.memo)(DataRowInner, (prev, next) => prev.row.original === next.row.original && prev.row.id === next.row.id && prev.isSelected === next.isSelected && prev.resizable === next.resizable && prev.overflowing === next.overflowing && prev.columnLayoutKey === next.columnLayoutKey && prev.selectionColumnId === next.selectionColumnId && prev.getCellTestId === next.getCellTestId && prev.getRowTestId === next.getRowTestId && prev.rowHref === next.rowHref && prev.onRowOpen === next.onRowOpen && prev.activateRow === next.activateRow && prev.rowClassName === next.rowClassName);
|
|
2541
|
-
function DataTableBodyInner({ rows, isLoading, loadingRowCount, visibleColumnCount, emptyState, emptyText, resizable, overflowing, columnLayoutKey, selectionColumnId, getCellTestId, getRowTestId, rowHref, onRowOpen, activateRow, rowClassName }) {
|
|
2277
|
+
const MemoRow = (0, react.memo)(DataRowInner, (prev, next) => prev.row.original === next.row.original && prev.row.id === next.row.id && prev.isSelected === next.isSelected && prev.resizable === next.resizable && prev.overflowing === next.overflowing && prev.columnLayoutKey === next.columnLayoutKey && prev.fillColumnId === next.fillColumnId && prev.selectionColumnId === next.selectionColumnId && prev.getCellTestId === next.getCellTestId && prev.getRowTestId === next.getRowTestId && prev.rowHref === next.rowHref && prev.onRowOpen === next.onRowOpen && prev.activateRow === next.activateRow && prev.rowClassName === next.rowClassName);
|
|
2278
|
+
function DataTableBodyInner({ rows, isLoading, loadingRowCount, visibleColumnCount, emptyState, emptyText, resizable, overflowing, columnLayoutKey, fillColumnId, selectionColumnId, getCellTestId, getRowTestId, rowHref, onRowOpen, activateRow, rowClassName }) {
|
|
2542
2279
|
return (0, react_jsx_runtime.jsx)(require_filter_builder.TableBody, { children: isLoading ? Array.from({ length: loadingRowCount }).map((_, i) => (0, react_jsx_runtime.jsx)(require_filter_builder.TableRow, {
|
|
2543
2280
|
"aria-busy": "true",
|
|
2544
2281
|
children: Array.from({ length: Math.max(1, visibleColumnCount) }).map((__, j) => (0, react_jsx_runtime.jsx)(require_filter_builder.TableCell, { children: (0, react_jsx_runtime.jsx)("div", { className: "h-4 w-3/4 animate-pulse rounded bg-muted" }) }, `skeleton-${i}-${j}`))
|
|
@@ -2555,6 +2292,7 @@ function DataTableBodyInner({ rows, isLoading, loadingRowCount, visibleColumnCou
|
|
|
2555
2292
|
resizable,
|
|
2556
2293
|
overflowing,
|
|
2557
2294
|
columnLayoutKey,
|
|
2295
|
+
fillColumnId,
|
|
2558
2296
|
selectionColumnId,
|
|
2559
2297
|
getCellTestId,
|
|
2560
2298
|
getRowTestId,
|
|
@@ -2566,7 +2304,7 @@ function DataTableBodyInner({ rows, isLoading, loadingRowCount, visibleColumnCou
|
|
|
2566
2304
|
}
|
|
2567
2305
|
const DataTableBody = (0, react.memo)(DataTableBodyInner, (prev, next) => {
|
|
2568
2306
|
if (!next.isResizing) return false;
|
|
2569
|
-
return prev.rows === next.rows && prev.overflowing === next.overflowing && prev.isLoading === next.isLoading && prev.columnLayoutKey === next.columnLayoutKey && prev.selectionColumnId === next.selectionColumnId;
|
|
2307
|
+
return prev.rows === next.rows && prev.overflowing === next.overflowing && prev.isLoading === next.isLoading && prev.columnLayoutKey === next.columnLayoutKey && prev.fillColumnId === next.fillColumnId && prev.selectionColumnId === next.selectionColumnId;
|
|
2570
2308
|
});
|
|
2571
2309
|
function DataTable({ table, tableTestId, getRowTestId, getCellTestId, isLoading = false, loadingRowCount = 5, emptyState, errorState, rowClassName, ariaLabel, onColumnReorder, rowHref, onRowOpen, selectionColumnId, className }) {
|
|
2572
2310
|
const t = (0, _burojs_react.useOptionalT)();
|
|
@@ -2596,8 +2334,10 @@ function DataTable({ table, tableTestId, getRowTestId, getCellTestId, isLoading
|
|
|
2596
2334
|
const rows = table.getRowModel().rows;
|
|
2597
2335
|
const headerGroups = table.getHeaderGroups();
|
|
2598
2336
|
const visibleColumnCount = table.getVisibleLeafColumns().length;
|
|
2337
|
+
const fillId = tableFillColumnId(table);
|
|
2599
2338
|
const columnLayoutKey = table.getVisibleLeafColumns().map((c) => `${c.id}:${c.getIsPinned() || ""}`).join("|");
|
|
2600
2339
|
const resizable = table.options.enableColumnResizing === true;
|
|
2340
|
+
const widthSum = resizable ? table.getVisibleLeafColumns().reduce((sum, c) => sum + c.getSize(), 0) : 0;
|
|
2601
2341
|
const hasPinned = table.getState().columnPinning != null && (table.getState().columnPinning.left?.length || table.getState().columnPinning.right?.length);
|
|
2602
2342
|
const sizingState = table.getState().columnSizing;
|
|
2603
2343
|
const sizingInfo = table.getState().columnSizingInfo;
|
|
@@ -2689,7 +2429,7 @@ function DataTable({ table, tableTestId, getRowTestId, getCellTestId, isLoading
|
|
|
2689
2429
|
className,
|
|
2690
2430
|
style: resizable ? {
|
|
2691
2431
|
...columnSizeVars,
|
|
2692
|
-
|
|
2432
|
+
width: fillId !== void 0 ? `max(100%, ${widthSum}px)` : `${widthSum}px`,
|
|
2693
2433
|
tableLayout: "fixed"
|
|
2694
2434
|
} : void 0,
|
|
2695
2435
|
children: [(0, react_jsx_runtime.jsx)(require_filter_builder.TableHeader, { children: headerGroups.map((hg) => (0, react_jsx_runtime.jsx)(require_filter_builder.TableRow, { children: hg.headers.map((header) => {
|
|
@@ -2700,7 +2440,7 @@ function DataTable({ table, tableTestId, getRowTestId, getCellTestId, isLoading
|
|
|
2700
2440
|
return (0, react_jsx_runtime.jsxs)(require_filter_builder.TableHead, {
|
|
2701
2441
|
colSpan: header.colSpan,
|
|
2702
2442
|
"aria-sort": ariaSort,
|
|
2703
|
-
style: getPinStyles(header.column, overflowing),
|
|
2443
|
+
style: getPinStyles(header.column, overflowing, header.column.id === fillId),
|
|
2704
2444
|
className: require_use_theme.cn("relative", resizable && !columnMetaNoClip(header.column.columnDef.meta) && (pinEdgeClassFor(header.column, overflowing) ? "[&>*:not([data-testid^=col-resize])]:truncate" : "overflow-hidden [&>*:not([data-testid^=col-resize])]:truncate"), canReorder && "cursor-grab", pinEdgeClassFor(header.column, overflowing), columnMetaClassName(header.column.columnDef.meta)),
|
|
2705
2445
|
draggable: canReorder || void 0,
|
|
2706
2446
|
onDragStart: canReorder ? (e) => {
|
|
@@ -2759,6 +2499,7 @@ function DataTable({ table, tableTestId, getRowTestId, getCellTestId, isLoading
|
|
|
2759
2499
|
resizable,
|
|
2760
2500
|
overflowing,
|
|
2761
2501
|
columnLayoutKey,
|
|
2502
|
+
fillColumnId: fillId,
|
|
2762
2503
|
selectionColumnId,
|
|
2763
2504
|
isResizing: Boolean(sizingInfo.isResizingColumn),
|
|
2764
2505
|
getCellTestId,
|
|
@@ -2982,63 +2723,247 @@ function resolveUpdater(updater, prev) {
|
|
|
2982
2723
|
}
|
|
2983
2724
|
//#endregion
|
|
2984
2725
|
//#region src/resource/list-error-state.tsx
|
|
2985
|
-
function ListErrorState(
|
|
2986
|
-
const
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
children: [
|
|
2995
|
-
(0, react_jsx_runtime.jsx)("div", {
|
|
2996
|
-
className: "rounded-full bg-destructive/10 p-3 text-destructive",
|
|
2997
|
-
children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconAlertCircle, {
|
|
2998
|
-
className: "size-6",
|
|
2999
|
-
"aria-hidden": "true"
|
|
3000
|
-
})
|
|
3001
|
-
}),
|
|
3002
|
-
(0, react_jsx_runtime.jsxs)("div", {
|
|
3003
|
-
className: "space-y-1",
|
|
3004
|
-
children: [(0, react_jsx_runtime.jsx)("h3", {
|
|
3005
|
-
className: "text-base font-semibold tracking-tight text-destructive",
|
|
3006
|
-
children: title ?? t("list.errorTitle")
|
|
3007
|
-
}), (0, react_jsx_runtime.jsx)("p", {
|
|
3008
|
-
className: "max-w-md text-sm text-muted-foreground",
|
|
3009
|
-
children: friendlyError || t("list.errorBody")
|
|
3010
|
-
})]
|
|
3011
|
-
}),
|
|
3012
|
-
raw && raw !== friendlyError ? (0, react_jsx_runtime.jsxs)("details", {
|
|
3013
|
-
className: "max-w-md text-left",
|
|
3014
|
-
children: [(0, react_jsx_runtime.jsx)("summary", {
|
|
3015
|
-
className: "cursor-pointer text-xs text-muted-foreground hover:text-foreground",
|
|
3016
|
-
children: t("list.errorDetails")
|
|
3017
|
-
}), (0, react_jsx_runtime.jsx)("p", {
|
|
3018
|
-
className: "mt-1.5 break-all font-mono text-xs text-muted-foreground",
|
|
3019
|
-
"data-testid": "list-error-detail",
|
|
3020
|
-
children: raw
|
|
3021
|
-
})]
|
|
3022
|
-
}) : null,
|
|
3023
|
-
onRetry && (0, react_jsx_runtime.jsx)("div", {
|
|
3024
|
-
className: "flex justify-center pt-2",
|
|
3025
|
-
children: (0, react_jsx_runtime.jsxs)(require_button.Button, {
|
|
3026
|
-
type: "button",
|
|
3027
|
-
variant: "outline",
|
|
3028
|
-
size: "sm",
|
|
3029
|
-
"data-testid": resource ? `list-error-retry:${resource}` : "list-error-retry",
|
|
3030
|
-
onClick: onRetry,
|
|
3031
|
-
className: "gap-1.5",
|
|
3032
|
-
children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconRefresh, {
|
|
3033
|
-
className: "size-3.5",
|
|
3034
|
-
"aria-hidden": "true"
|
|
3035
|
-
}), t("actions.retry")]
|
|
3036
|
-
})
|
|
3037
|
-
})
|
|
3038
|
-
]
|
|
2726
|
+
function ListErrorState(props) {
|
|
2727
|
+
const { error, onRetry, resource, title, className } = props;
|
|
2728
|
+
return (0, react_jsx_runtime.jsx)(require_relation_create.LoadError, {
|
|
2729
|
+
surface: "list",
|
|
2730
|
+
error,
|
|
2731
|
+
...onRetry === void 0 ? {} : { retry: onRetry },
|
|
2732
|
+
...resource === void 0 ? {} : { resource },
|
|
2733
|
+
...title === void 0 ? {} : { title },
|
|
2734
|
+
...className === void 0 ? {} : { className }
|
|
3039
2735
|
});
|
|
3040
2736
|
}
|
|
3041
2737
|
//#endregion
|
|
2738
|
+
//#region src/resource/use-table-layout.ts
|
|
2739
|
+
const WRITE_DEBOUNCE_MS = 200;
|
|
2740
|
+
function mutate(run, ok, then) {
|
|
2741
|
+
try {
|
|
2742
|
+
run().then((result) => {
|
|
2743
|
+
if (ok(result.status)) then();
|
|
2744
|
+
}, () => void 0);
|
|
2745
|
+
} catch {}
|
|
2746
|
+
}
|
|
2747
|
+
function resolve(updater, current) {
|
|
2748
|
+
return typeof updater === "function" ? updater(current) : updater;
|
|
2749
|
+
}
|
|
2750
|
+
function sameNames(a, b) {
|
|
2751
|
+
return a.length === b.length && a.every((name, index) => name === b[index]);
|
|
2752
|
+
}
|
|
2753
|
+
function readSizes(sizes, rule) {
|
|
2754
|
+
const out = {};
|
|
2755
|
+
for (const [column, size] of Object.entries(sizes)) {
|
|
2756
|
+
const of = rule(column);
|
|
2757
|
+
if (of === void 0 || !of.resize) continue;
|
|
2758
|
+
out[column] = Math.min(Math.max(size, of.min), of.max ?? Number.POSITIVE_INFINITY);
|
|
2759
|
+
}
|
|
2760
|
+
return out;
|
|
2761
|
+
}
|
|
2762
|
+
function useTableLayout({ resource, layoutId, rule, defaultPinning, resetLayout }) {
|
|
2763
|
+
const params = (0, react.useMemo)(() => layoutId === void 0 ? null : {
|
|
2764
|
+
resource,
|
|
2765
|
+
list: layoutId
|
|
2766
|
+
}, [resource, layoutId]);
|
|
2767
|
+
const settings = (0, _burojs_react.useOptionalUiSettings)(_burojs_react.tableLayoutSetting, params);
|
|
2768
|
+
const settingsRef = (0, react.useRef)(settings);
|
|
2769
|
+
settingsRef.current = settings;
|
|
2770
|
+
const key = layoutId === void 0 ? void 0 : `${resource}\u0000${layoutId}`;
|
|
2771
|
+
const fallback = (0, react.useMemo)(() => ({
|
|
2772
|
+
sizes: {},
|
|
2773
|
+
order: [],
|
|
2774
|
+
pinning: defaultPinning
|
|
2775
|
+
}), [defaultPinning]);
|
|
2776
|
+
const [local, setLocal] = (0, react.useState)();
|
|
2777
|
+
const stored = settings?.snapshot.entries[0]?.value;
|
|
2778
|
+
const settled = settings === void 0 || !settings.snapshot.pending;
|
|
2779
|
+
const held = (0, react.useRef)(null);
|
|
2780
|
+
const layout = (local !== void 0 && local.key === key ? local.value : void 0) ?? stored ?? fallback;
|
|
2781
|
+
const latest = (0, react.useRef)(layout);
|
|
2782
|
+
latest.current = layout;
|
|
2783
|
+
const sizing = (0, react.useMemo)(() => readSizes(layout.sizes, rule), [layout.sizes, rule]);
|
|
2784
|
+
const sizingRef = (0, react.useRef)(sizing);
|
|
2785
|
+
sizingRef.current = sizing;
|
|
2786
|
+
const generation = (0, react.useRef)(0);
|
|
2787
|
+
const timer = (0, react.useRef)(null);
|
|
2788
|
+
const pending = (0, react.useRef)(null);
|
|
2789
|
+
const confirm = (0, react.useCallback)((sent) => {
|
|
2790
|
+
if (generation.current === sent && pending.current === null) setLocal(void 0);
|
|
2791
|
+
}, []);
|
|
2792
|
+
const write = (0, react.useCallback)((target, value) => {
|
|
2793
|
+
const scopeId = target.snapshot.entries[0]?.scope.id ?? target.snapshot.writeScopes[0]?.id;
|
|
2794
|
+
if (scopeId === void 0) return;
|
|
2795
|
+
const sent = generation.current;
|
|
2796
|
+
mutate(() => target.set({
|
|
2797
|
+
scopeId,
|
|
2798
|
+
value
|
|
2799
|
+
}), (status) => status === "created" || status === "updated", () => confirm(sent));
|
|
2800
|
+
}, [confirm]);
|
|
2801
|
+
const store = (0, react.useCallback)((target, next) => {
|
|
2802
|
+
if (!(Object.keys(next.sizes).length === 0 && next.order.length === 0 && sameNames(next.pinning.left, defaultPinning.left) && sameNames(next.pinning.right, defaultPinning.right))) {
|
|
2803
|
+
write(target, next);
|
|
2804
|
+
return;
|
|
2805
|
+
}
|
|
2806
|
+
const entry = target.snapshot.entries[0];
|
|
2807
|
+
if (entry === void 0) {
|
|
2808
|
+
setLocal(void 0);
|
|
2809
|
+
return;
|
|
2810
|
+
}
|
|
2811
|
+
const sent = generation.current;
|
|
2812
|
+
mutate(() => target.remove({ id: entry.id }), (status) => status === "removed", () => confirm(sent));
|
|
2813
|
+
}, [
|
|
2814
|
+
defaultPinning,
|
|
2815
|
+
write,
|
|
2816
|
+
confirm
|
|
2817
|
+
]);
|
|
2818
|
+
const flush = (0, react.useCallback)(() => {
|
|
2819
|
+
if (timer.current !== null) clearTimeout(timer.current);
|
|
2820
|
+
timer.current = null;
|
|
2821
|
+
const due = pending.current;
|
|
2822
|
+
pending.current = null;
|
|
2823
|
+
if (due !== null) write(due.target, due.value);
|
|
2824
|
+
}, [write]);
|
|
2825
|
+
const change = (0, react.useCallback)((next, debounced, touch) => {
|
|
2826
|
+
latest.current = next;
|
|
2827
|
+
generation.current += 1;
|
|
2828
|
+
setLocal({
|
|
2829
|
+
key,
|
|
2830
|
+
value: next
|
|
2831
|
+
});
|
|
2832
|
+
const target = settingsRef.current;
|
|
2833
|
+
if (target === void 0) return;
|
|
2834
|
+
if (target.snapshot.pending || held.current !== null && held.current.key === key) {
|
|
2835
|
+
const edits = held.current !== null && held.current.key === key ? held.current : {
|
|
2836
|
+
key,
|
|
2837
|
+
resetAll: false,
|
|
2838
|
+
resetSizes: false,
|
|
2839
|
+
sizes: new Map()
|
|
2840
|
+
};
|
|
2841
|
+
held.current = edits;
|
|
2842
|
+
touch(edits);
|
|
2843
|
+
return;
|
|
2844
|
+
}
|
|
2845
|
+
pending.current = {
|
|
2846
|
+
target,
|
|
2847
|
+
value: next
|
|
2848
|
+
};
|
|
2849
|
+
if (!debounced) {
|
|
2850
|
+
flush();
|
|
2851
|
+
return;
|
|
2852
|
+
}
|
|
2853
|
+
if (timer.current !== null) clearTimeout(timer.current);
|
|
2854
|
+
timer.current = setTimeout(flush, WRITE_DEBOUNCE_MS);
|
|
2855
|
+
}, [key, flush]);
|
|
2856
|
+
(0, react.useEffect)(() => flush, [key]);
|
|
2857
|
+
(0, react.useEffect)(() => {
|
|
2858
|
+
const edits = held.current;
|
|
2859
|
+
if (edits === null) return;
|
|
2860
|
+
if (edits.key !== key) {
|
|
2861
|
+
held.current = null;
|
|
2862
|
+
return;
|
|
2863
|
+
}
|
|
2864
|
+
const target = settingsRef.current;
|
|
2865
|
+
if (!settled || target === void 0) return;
|
|
2866
|
+
held.current = null;
|
|
2867
|
+
const base = edits.resetAll ? fallback : stored ?? fallback;
|
|
2868
|
+
const sizes = edits.resetAll || edits.resetSizes ? {} : { ...readSizes(base.sizes, rule) };
|
|
2869
|
+
for (const [column, size] of edits.sizes) if (size === void 0) delete sizes[column];
|
|
2870
|
+
else sizes[column] = size;
|
|
2871
|
+
const next = {
|
|
2872
|
+
sizes,
|
|
2873
|
+
order: edits.order ?? base.order,
|
|
2874
|
+
pinning: edits.pinning ?? base.pinning
|
|
2875
|
+
};
|
|
2876
|
+
latest.current = next;
|
|
2877
|
+
generation.current += 1;
|
|
2878
|
+
setLocal({
|
|
2879
|
+
key,
|
|
2880
|
+
value: next
|
|
2881
|
+
});
|
|
2882
|
+
store(target, next);
|
|
2883
|
+
}, [settled, key]);
|
|
2884
|
+
const resetToken = resetLayout?.token ?? 0;
|
|
2885
|
+
const seenToken = (0, react.useRef)(resetToken);
|
|
2886
|
+
(0, react.useEffect)(() => {
|
|
2887
|
+
if (resetToken === seenToken.current) return;
|
|
2888
|
+
seenToken.current = resetToken;
|
|
2889
|
+
const all = resetLayout?.mode === "all";
|
|
2890
|
+
const next = all ? fallback : {
|
|
2891
|
+
...latest.current,
|
|
2892
|
+
sizes: {}
|
|
2893
|
+
};
|
|
2894
|
+
if (timer.current !== null) clearTimeout(timer.current);
|
|
2895
|
+
timer.current = null;
|
|
2896
|
+
pending.current = null;
|
|
2897
|
+
latest.current = next;
|
|
2898
|
+
generation.current += 1;
|
|
2899
|
+
setLocal({
|
|
2900
|
+
key,
|
|
2901
|
+
value: next
|
|
2902
|
+
});
|
|
2903
|
+
const target = settingsRef.current;
|
|
2904
|
+
if (target === void 0) return;
|
|
2905
|
+
if (target.snapshot.pending || held.current !== null && held.current.key === key) {
|
|
2906
|
+
const prior = held.current !== null && held.current.key === key ? held.current : void 0;
|
|
2907
|
+
held.current = all ? {
|
|
2908
|
+
key,
|
|
2909
|
+
resetAll: true,
|
|
2910
|
+
resetSizes: false,
|
|
2911
|
+
sizes: new Map()
|
|
2912
|
+
} : {
|
|
2913
|
+
key,
|
|
2914
|
+
resetAll: prior?.resetAll ?? false,
|
|
2915
|
+
resetSizes: true,
|
|
2916
|
+
sizes: new Map(),
|
|
2917
|
+
...prior?.order === void 0 ? {} : { order: prior.order },
|
|
2918
|
+
...prior?.pinning === void 0 ? {} : { pinning: prior.pinning }
|
|
2919
|
+
};
|
|
2920
|
+
return;
|
|
2921
|
+
}
|
|
2922
|
+
store(target, next);
|
|
2923
|
+
}, [resetToken]);
|
|
2924
|
+
const setColumnSizing = (0, react.useCallback)((updater) => {
|
|
2925
|
+
const before = sizingRef.current;
|
|
2926
|
+
const sizes = resolve(updater, before);
|
|
2927
|
+
sizingRef.current = sizes;
|
|
2928
|
+
change({
|
|
2929
|
+
...latest.current,
|
|
2930
|
+
sizes
|
|
2931
|
+
}, true, (edits) => {
|
|
2932
|
+
for (const column of new Set([...Object.keys(before), ...Object.keys(sizes)])) if (before[column] !== sizes[column]) edits.sizes.set(column, sizes[column]);
|
|
2933
|
+
});
|
|
2934
|
+
}, [change]);
|
|
2935
|
+
const setColumnOrder = (0, react.useCallback)((updater) => {
|
|
2936
|
+
const order = resolve(updater, latest.current.order);
|
|
2937
|
+
change({
|
|
2938
|
+
...latest.current,
|
|
2939
|
+
order
|
|
2940
|
+
}, false, (edits) => {
|
|
2941
|
+
edits.order = order;
|
|
2942
|
+
});
|
|
2943
|
+
}, [change]);
|
|
2944
|
+
const setColumnPinning = (0, react.useCallback)((updater) => {
|
|
2945
|
+
const resolved = resolve(updater, latest.current.pinning);
|
|
2946
|
+
const pinning = {
|
|
2947
|
+
left: resolved.left ?? [],
|
|
2948
|
+
right: resolved.right ?? []
|
|
2949
|
+
};
|
|
2950
|
+
change({
|
|
2951
|
+
...latest.current,
|
|
2952
|
+
pinning
|
|
2953
|
+
}, false, (edits) => {
|
|
2954
|
+
edits.pinning = pinning;
|
|
2955
|
+
});
|
|
2956
|
+
}, [change]);
|
|
2957
|
+
return {
|
|
2958
|
+
columnSizing: sizing,
|
|
2959
|
+
setColumnSizing,
|
|
2960
|
+
columnOrder: layout.order,
|
|
2961
|
+
setColumnOrder,
|
|
2962
|
+
columnPinning: layout.pinning,
|
|
2963
|
+
setColumnPinning
|
|
2964
|
+
};
|
|
2965
|
+
}
|
|
2966
|
+
//#endregion
|
|
3042
2967
|
//#region src/list-kit/cursor-load-more.tsx
|
|
3043
2968
|
function CursorLoadMore({ hasMore, loading, onMore }) {
|
|
3044
2969
|
const t = (0, _burojs_react.useT)();
|
|
@@ -3080,6 +3005,10 @@ function CountRowsTrigger({ label, loading, onClick, testid, variant, className
|
|
|
3080
3005
|
}
|
|
3081
3006
|
const SELECT_COL_ID = "__select__";
|
|
3082
3007
|
const ACTIONS_COL_ID = "__actions__";
|
|
3008
|
+
const DEFAULT_PINNING = Object.freeze({
|
|
3009
|
+
left: Object.freeze([SELECT_COL_ID, "id"]),
|
|
3010
|
+
right: Object.freeze([ACTIONS_COL_ID])
|
|
3011
|
+
});
|
|
3083
3012
|
const ROW_ACTION_CONTROL_PX = 28;
|
|
3084
3013
|
const ROW_ACTION_GAP_PX = 4;
|
|
3085
3014
|
const ACTIONS_CELL_PADDING_PX = 16;
|
|
@@ -3091,29 +3020,30 @@ function actionsColumnSize(items) {
|
|
|
3091
3020
|
const strip = controls * ROW_ACTION_CONTROL_PX + (controls - 1) * ROW_ACTION_GAP_PX + ACTIONS_CELL_PADDING_PX;
|
|
3092
3021
|
return Math.max(ACTIONS_COL_MIN_PX, strip);
|
|
3093
3022
|
}
|
|
3094
|
-
const
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
const COLUMN_SIZE_BY_FORMAT = {
|
|
3099
|
-
date: 132,
|
|
3100
|
-
"date-time": 132
|
|
3023
|
+
const ALIGN_CLASS = {
|
|
3024
|
+
start: "text-start",
|
|
3025
|
+
center: "text-center",
|
|
3026
|
+
end: "text-end"
|
|
3101
3027
|
};
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3028
|
+
const STANDALONE_COLUMN_UI = Object.freeze({
|
|
3029
|
+
default: 160,
|
|
3030
|
+
min: 90,
|
|
3031
|
+
align: "start",
|
|
3032
|
+
resize: true,
|
|
3033
|
+
fill: false,
|
|
3034
|
+
display: Object.freeze({ params: Object.freeze({}) })
|
|
3035
|
+
});
|
|
3036
|
+
function ResourceList({ resource: resourceInput, data, total, page = 1, pageSize = 10, onPageSize, onRequestCount, isCountingRows = false, pageSizeOptions = [
|
|
3109
3037
|
10,
|
|
3110
3038
|
25,
|
|
3111
3039
|
50,
|
|
3112
3040
|
100
|
|
3113
|
-
], onPage, loadMore, selectable = false, rowActions = true, selectedIds, onSelectionChange, className, isLoading = false, error = null, onRetry, createHref, isFiltered = false, onClearFilter, emptyState, rowsView, rowHref, rowQuick, rowLinkKey, renderCell, sort, onSort, onHideColumn, requiredColumns, resetLayout, columns: columnsOverride, tableRef }) {
|
|
3041
|
+
], onPage, loadMore, selectable = false, rowActions = true, selectedIds, onSelectionChange, className, isLoading = false, error = null, onRetry, createHref, isFiltered = false, onClearFilter, emptyState, rowsView, rowHref, rowQuick, rowLinkKey, renderCell, sort, onSort, sortable, onHideColumn, requiredColumns, resetLayout, columns: columnsOverride, columnUi, layoutId, tableRef }) {
|
|
3042
|
+
const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
|
|
3114
3043
|
const app = (0, _burojs_react.useApp)();
|
|
3115
3044
|
const tid = (0, _burojs_react.useTestIds)();
|
|
3116
3045
|
const t = (0, _burojs_react.useOptionalT)();
|
|
3046
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
3117
3047
|
const locale = (0, _burojs_react.useLocale)();
|
|
3118
3048
|
const nf = (0, react.useMemo)(() => new Intl.NumberFormat(locale), [locale]);
|
|
3119
3049
|
const i18nCaps = (0, _burojs_react.useI18nCaps)(resource);
|
|
@@ -3135,23 +3065,6 @@ function ResourceList({ resource, data, total, page = 1, pageSize = 10, onPageSi
|
|
|
3135
3065
|
(0, react.useEffect)(() => {
|
|
3136
3066
|
emittedRef.current = null;
|
|
3137
3067
|
}, [controlledSelection]);
|
|
3138
|
-
const layoutKey = `buro:table-layout:${resource}`;
|
|
3139
|
-
const [columnSizing, setColumnSizing] = usePersistedState(`${layoutKey}:sizing`, {}, 200);
|
|
3140
|
-
const [columnOrder, setColumnOrder] = usePersistedState(`${layoutKey}:order`, []);
|
|
3141
|
-
const DEFAULT_PINNING = {
|
|
3142
|
-
left: [SELECT_COL_ID, "id"],
|
|
3143
|
-
right: [ACTIONS_COL_ID]
|
|
3144
|
-
};
|
|
3145
|
-
const [columnPinning, setColumnPinning] = usePersistedState(`${layoutKey}:pinning`, DEFAULT_PINNING);
|
|
3146
|
-
const resetToken = resetLayout?.token ?? 0;
|
|
3147
|
-
(0, react.useEffect)(() => {
|
|
3148
|
-
if (!resetToken) return;
|
|
3149
|
-
setColumnSizing({});
|
|
3150
|
-
if (resetLayout?.mode === "all") {
|
|
3151
|
-
setColumnOrder([]);
|
|
3152
|
-
setColumnPinning(DEFAULT_PINNING);
|
|
3153
|
-
}
|
|
3154
|
-
}, [resetToken]);
|
|
3155
3068
|
(0, react.useEffect)(() => {
|
|
3156
3069
|
if (controlled) return;
|
|
3157
3070
|
setOwnSelection({});
|
|
@@ -3161,7 +3074,7 @@ function ResourceList({ resource, data, total, page = 1, pageSize = 10, onPageSi
|
|
|
3161
3074
|
const accessPending = listAccess.status === "pending" || pathAccess.pending;
|
|
3162
3075
|
const declaredColumnKeys = (0, react.useMemo)(() => {
|
|
3163
3076
|
if (!def) return [];
|
|
3164
|
-
return [...columnsOverride ?? def.views?.list?.columns ?? Object.keys(def.fields)];
|
|
3077
|
+
return [...columnsOverride ?? def.views?.list?.columns?.map(_burojs_core.columnName) ?? Object.keys(def.fields)];
|
|
3165
3078
|
}, [def, columnsOverride]);
|
|
3166
3079
|
const visibleColumnKeys = (0, react.useMemo)(() => accessPending ? [] : declaredColumnKeys.filter((col) => listAccess.columnVisible(col) && (columnTarget(app.registry, resource, col) === void 0 || listAccess.columnVisible(col.split(".")[0]) && pathAccess.visible(col))), [
|
|
3167
3080
|
accessPending,
|
|
@@ -3211,10 +3124,11 @@ function ResourceList({ resource, data, total, page = 1, pageSize = 10, onPageSi
|
|
|
3211
3124
|
const resourceLabel = (0, _burojs_core.resolveResourceLabel)(i18nCaps, resource, "plural", def);
|
|
3212
3125
|
const recordSingular = (0, _burojs_core.resolveResourceLabel)(i18nCaps, resource, "single", def);
|
|
3213
3126
|
const ariaLabel = resourceLabel;
|
|
3214
|
-
const actionsHeader =
|
|
3127
|
+
const actionsHeader = chromeT("actions.column", { defaultValue: "Actions" });
|
|
3215
3128
|
const viewRow = (0, _burojs_react.useViewRow)(resource);
|
|
3216
3129
|
const volatileRef = (0, react.useRef)({
|
|
3217
3130
|
onSort,
|
|
3131
|
+
sortable,
|
|
3218
3132
|
onHideColumn,
|
|
3219
3133
|
requiredColumns,
|
|
3220
3134
|
renderCell,
|
|
@@ -3226,6 +3140,7 @@ function ResourceList({ resource, data, total, page = 1, pageSize = 10, onPageSi
|
|
|
3226
3140
|
});
|
|
3227
3141
|
volatileRef.current = {
|
|
3228
3142
|
onSort,
|
|
3143
|
+
sortable,
|
|
3229
3144
|
onHideColumn,
|
|
3230
3145
|
requiredColumns,
|
|
3231
3146
|
renderCell,
|
|
@@ -3249,6 +3164,45 @@ function ResourceList({ resource, data, total, page = 1, pageSize = 10, onPageSi
|
|
|
3249
3164
|
}, [rowLinkKey]);
|
|
3250
3165
|
const stableRowClassName = (0, react.useCallback)((row) => volatileRef.current.rowHref?.(volatileRef.current.viewRow(row.original)) || (volatileRef.current.rowQuick?.(row.original) ?? null) !== null ? "cursor-pointer" : void 0, [rowLinkKey]);
|
|
3251
3166
|
const [listRoot, narrow] = useContainerNarrow();
|
|
3167
|
+
const columnUiOf = (0, react.useMemo)(() => {
|
|
3168
|
+
const entries = new Map();
|
|
3169
|
+
for (const entry of [...def?.views?.list?.columns ?? [], ...def?.views?.list?.optionalColumns ?? []]) {
|
|
3170
|
+
const name = (0, _burojs_core.columnName)(entry);
|
|
3171
|
+
if (!entries.has(name)) entries.set(name, entry);
|
|
3172
|
+
}
|
|
3173
|
+
return (col) => columnUi?.[col] ?? (def === void 0 ? STANDALONE_COLUMN_UI : (0, _burojs_core.resolveColumnUi)(def, entries.get(col) ?? col, app.registry, _burojs_react.columnTypeWidth));
|
|
3174
|
+
}, [
|
|
3175
|
+
app,
|
|
3176
|
+
def,
|
|
3177
|
+
columnUi
|
|
3178
|
+
]);
|
|
3179
|
+
const { columnSizing, setColumnSizing, columnOrder, setColumnOrder, columnPinning, setColumnPinning } = useTableLayout({
|
|
3180
|
+
resource,
|
|
3181
|
+
layoutId,
|
|
3182
|
+
rule: (0, react.useMemo)(() => {
|
|
3183
|
+
const known = new Set([
|
|
3184
|
+
...declaredColumnKeys,
|
|
3185
|
+
...(def?.views?.list?.columns ?? []).map(_burojs_core.columnName),
|
|
3186
|
+
...(def?.views?.list?.optionalColumns ?? []).map(_burojs_core.columnName),
|
|
3187
|
+
...Object.keys(def?.fields ?? {})
|
|
3188
|
+
]);
|
|
3189
|
+
return (col) => {
|
|
3190
|
+
if (!known.has(col)) return void 0;
|
|
3191
|
+
const ui = columnUiOf(col);
|
|
3192
|
+
return {
|
|
3193
|
+
min: ui.min,
|
|
3194
|
+
max: ui.max,
|
|
3195
|
+
resize: ui.resize
|
|
3196
|
+
};
|
|
3197
|
+
};
|
|
3198
|
+
}, [
|
|
3199
|
+
declaredColumnKeys,
|
|
3200
|
+
def,
|
|
3201
|
+
columnUiOf
|
|
3202
|
+
]),
|
|
3203
|
+
defaultPinning: DEFAULT_PINNING,
|
|
3204
|
+
resetLayout
|
|
3205
|
+
});
|
|
3252
3206
|
const tableColumns = (0, react.useMemo)(() => {
|
|
3253
3207
|
const cols = [];
|
|
3254
3208
|
if (selectable) cols.push({
|
|
@@ -3271,19 +3225,32 @@ function ResourceList({ resource, data, total, page = 1, pageSize = 10, onPageSi
|
|
|
3271
3225
|
});
|
|
3272
3226
|
for (const col of visibleColumnKeys) {
|
|
3273
3227
|
const target = columnTarget(app.registry, resource, col);
|
|
3274
|
-
const field = target
|
|
3228
|
+
const field = target !== void 0 ? target.field : def === void 0 ? void 0 : (0, _burojs_core.declaredField)(def, col);
|
|
3275
3229
|
const declaredLabel = (0, _burojs_core.declaredText)("field", field, "label");
|
|
3276
3230
|
const headerLabel = target === void 0 ? (0, _burojs_core.resolveFieldLabel)(volatileRef.current.i18nCaps, col, declaredLabel) : (0, _burojs_core.resolveFieldLabel)(capsOf(volatileRef.current.i18nCaps, target.resource), target.name, declaredLabel);
|
|
3277
|
-
const
|
|
3278
|
-
const
|
|
3279
|
-
|
|
3231
|
+
const ui = columnUiOf(col);
|
|
3232
|
+
const frameField = {
|
|
3233
|
+
...field ?? { type: "unknown" },
|
|
3234
|
+
name: target === void 0 ? col : target.name
|
|
3235
|
+
};
|
|
3236
|
+
const cellEntry = { display: ui.display };
|
|
3237
|
+
const wraps = ui.display.overflow === "wrap";
|
|
3238
|
+
const columnSortable = volatileRef.current.sortable?.(col) ?? (def !== void 0 && (0, _burojs_core.isColumnSortable)(def, col, app, app.registry));
|
|
3280
3239
|
cols.push({
|
|
3281
3240
|
id: col,
|
|
3282
3241
|
...columnAccessor(col),
|
|
3283
|
-
|
|
3284
|
-
|
|
3242
|
+
size: ui.default,
|
|
3243
|
+
minSize: ui.min,
|
|
3244
|
+
maxSize: ui.max ?? Number.MAX_SAFE_INTEGER,
|
|
3245
|
+
enableResizing: ui.resize,
|
|
3246
|
+
enableSorting: columnSortable && Boolean(volatileRef.current.onSort),
|
|
3285
3247
|
enableHiding: true,
|
|
3286
|
-
meta: {
|
|
3248
|
+
meta: {
|
|
3249
|
+
testid: col,
|
|
3250
|
+
className: ALIGN_CLASS[ui.align],
|
|
3251
|
+
...wraps ? { wrap: true } : {},
|
|
3252
|
+
...ui.fill ? { fill: true } : {}
|
|
3253
|
+
},
|
|
3287
3254
|
header: ({ column, table }) => {
|
|
3288
3255
|
const v = volatileRef.current;
|
|
3289
3256
|
const pinSide = column.getIsPinned();
|
|
@@ -3314,9 +3281,9 @@ function ResourceList({ resource, data, total, page = 1, pageSize = 10, onPageSi
|
|
|
3314
3281
|
};
|
|
3315
3282
|
return (0, react_jsx_runtime.jsx)(ColumnHeaderMenu, {
|
|
3316
3283
|
label: headerLabel,
|
|
3317
|
-
sortable:
|
|
3284
|
+
sortable: columnSortable && Boolean(v.onSort),
|
|
3318
3285
|
sortDirection: v.sort?.[0]?.field === col ? v.sort[0].direction : null,
|
|
3319
|
-
onSort:
|
|
3286
|
+
onSort: columnSortable && v.onSort ? (dir) => v.onSort?.(col, dir) : void 0,
|
|
3320
3287
|
pinned: column.getIsPinned(),
|
|
3321
3288
|
onPin: (side) => column.pin(side),
|
|
3322
3289
|
canHide: Boolean(v.onHideColumn) && !v.requiredColumns?.includes(col),
|
|
@@ -3332,38 +3299,47 @@ function ResourceList({ resource, data, total, page = 1, pageSize = 10, onPageSi
|
|
|
3332
3299
|
const record = volatileRef.current.viewRow(raw);
|
|
3333
3300
|
const value = record[col];
|
|
3334
3301
|
const customCell = volatileRef.current.renderCell?.(col, value, record);
|
|
3335
|
-
const cellInner = customCell !== void 0 ? customCell : (0, react_jsx_runtime.jsx)(ResolvedFieldDisplay, {
|
|
3302
|
+
const cellInner = customCell !== void 0 ? customCell : (0, react_jsx_runtime.jsx)(require_filter_builder.ResolvedFieldDisplay, {
|
|
3336
3303
|
resource: target === void 0 ? resourceRef : target.ref,
|
|
3337
3304
|
name: target === void 0 ? col : target.name,
|
|
3338
3305
|
field: field ?? { type: "unknown" },
|
|
3339
3306
|
value,
|
|
3340
3307
|
record,
|
|
3308
|
+
uiSurface: "column",
|
|
3309
|
+
columnEntry: cellEntry,
|
|
3341
3310
|
fallback: (0, react_jsx_runtime.jsx)("span", { children: String(value ?? "") })
|
|
3342
3311
|
});
|
|
3312
|
+
const framed = (node) => customCell !== void 0 ? node : (0, react_jsx_runtime.jsx)(FieldValueFrame, {
|
|
3313
|
+
field: frameField,
|
|
3314
|
+
value,
|
|
3315
|
+
surface: "column",
|
|
3316
|
+
entry: cellEntry,
|
|
3317
|
+
children: node
|
|
3318
|
+
});
|
|
3343
3319
|
const href = volatileRef.current.rowHref?.(record);
|
|
3344
3320
|
const isFirstContentCell = visibleColumnKeys.indexOf(col) === 0;
|
|
3345
3321
|
const quick = isFirstContentCell ? volatileRef.current.rowQuick?.(raw) ?? null : null;
|
|
3346
|
-
if (quick !== null) return href ? (0, react_jsx_runtime.jsx)(
|
|
3322
|
+
if (quick !== null) return framed(href ? (0, react_jsx_runtime.jsx)(require_relation_create.ClaimedQuickLink, {
|
|
3347
3323
|
href,
|
|
3348
|
-
className:
|
|
3324
|
+
className: require_relation_create.relationLinkClassName,
|
|
3349
3325
|
onOpen: quick,
|
|
3350
3326
|
children: cellInner
|
|
3351
3327
|
}) : (0, react_jsx_runtime.jsx)("button", {
|
|
3352
3328
|
type: "button",
|
|
3353
3329
|
[_burojs_react.QUICK_ANCHOR_ATTRIBUTE]: "",
|
|
3354
|
-
className: `${
|
|
3330
|
+
className: `${require_relation_create.relationLinkClassName} text-left`,
|
|
3355
3331
|
onClick: (e) => {
|
|
3356
3332
|
e.stopPropagation();
|
|
3357
3333
|
quick();
|
|
3358
3334
|
},
|
|
3359
3335
|
children: cellInner
|
|
3360
|
-
});
|
|
3361
|
-
return isFirstContentCell && href ? (0, react_jsx_runtime.jsx)(RouterLink, {
|
|
3336
|
+
}));
|
|
3337
|
+
return framed(isFirstContentCell && href ? (0, react_jsx_runtime.jsx)(RouterLink, {
|
|
3362
3338
|
href,
|
|
3363
|
-
className:
|
|
3339
|
+
className: require_relation_create.relationLinkClassName,
|
|
3364
3340
|
onClick: (e) => e.stopPropagation(),
|
|
3365
3341
|
children: cellInner
|
|
3366
|
-
}) : cellInner;
|
|
3342
|
+
}) : cellInner);
|
|
3367
3343
|
}
|
|
3368
3344
|
});
|
|
3369
3345
|
}
|
|
@@ -3372,7 +3348,7 @@ function ResourceList({ resource, data, total, page = 1, pageSize = 10, onPageSi
|
|
|
3372
3348
|
id: ACTIONS_COL_ID,
|
|
3373
3349
|
enableSorting: false,
|
|
3374
3350
|
enableResizing: false,
|
|
3375
|
-
size: narrow ? 44 : actionsColumnSize(def?.actions?.item),
|
|
3351
|
+
size: narrow || typeof rowActions === "function" ? 44 : actionsColumnSize(def?.actions?.item),
|
|
3376
3352
|
enableHiding: false,
|
|
3377
3353
|
header: () => (0, react_jsx_runtime.jsx)("span", {
|
|
3378
3354
|
className: "sr-only",
|
|
@@ -3383,7 +3359,7 @@ function ResourceList({ resource, data, total, page = 1, pageSize = 10, onPageSi
|
|
|
3383
3359
|
noRowNav: true,
|
|
3384
3360
|
noClip: true
|
|
3385
3361
|
},
|
|
3386
|
-
cell: ({ row }) => (0, react_jsx_runtime.jsx)(ActionOverflow, {
|
|
3362
|
+
cell: ({ row }) => typeof rowActions === "function" ? rowActions(row.original) : (0, react_jsx_runtime.jsx)(ActionOverflow, {
|
|
3387
3363
|
resource,
|
|
3388
3364
|
record: row.original,
|
|
3389
3365
|
surface: "row"
|
|
@@ -3403,7 +3379,8 @@ function ResourceList({ resource, data, total, page = 1, pageSize = 10, onPageSi
|
|
|
3403
3379
|
actionsHeader,
|
|
3404
3380
|
i18nCaps,
|
|
3405
3381
|
rowLinkKey,
|
|
3406
|
-
narrow
|
|
3382
|
+
narrow,
|
|
3383
|
+
columnUiOf
|
|
3407
3384
|
]);
|
|
3408
3385
|
const handleSelectionChange = (updater) => {
|
|
3409
3386
|
if (controlled) {
|
|
@@ -3506,13 +3483,28 @@ function ResourceList({ resource, data, total, page = 1, pageSize = 10, onPageSi
|
|
|
3506
3483
|
const isWrongPage = page > 1;
|
|
3507
3484
|
const EmptyIcon = isFiltered ? _tabler_icons_react.IconFilterX : _tabler_icons_react.IconInbox;
|
|
3508
3485
|
const items = resourceLabel.toLowerCase();
|
|
3509
|
-
const heading = isWrongPage ? t("pagination.emptyPage") : isFiltered ? t("list.emptyFilteredTitle", {
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3486
|
+
const heading = isWrongPage ? t("pagination.emptyPage") : isFiltered ? t("list.emptyFilteredTitle", {
|
|
3487
|
+
resource,
|
|
3488
|
+
params: { items }
|
|
3489
|
+
}) : t("list.emptyTitle", {
|
|
3490
|
+
resource,
|
|
3491
|
+
params: { items }
|
|
3492
|
+
});
|
|
3493
|
+
const body = isWrongPage ? null : isFiltered ? t("list.emptyFilteredBody", {
|
|
3494
|
+
resource,
|
|
3495
|
+
params: { items }
|
|
3496
|
+
}) : createHref ? t("list.emptyBody", {
|
|
3497
|
+
resource,
|
|
3498
|
+
params: { item: recordSingular.toLowerCase() }
|
|
3499
|
+
}) : t("list.emptyBodyReadOnly", {
|
|
3500
|
+
resource,
|
|
3501
|
+
params: { items }
|
|
3502
|
+
});
|
|
3503
|
+
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
3504
|
+
className: require_use_theme.cn("flex flex-col items-center justify-center gap-3 px-6 py-16 rounded-lg border border-dashed text-center", className),
|
|
3505
|
+
"data-testid": tid.listEmpty(resource),
|
|
3506
|
+
children: [
|
|
3507
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
3516
3508
|
className: "rounded-full bg-muted p-3 text-muted-foreground",
|
|
3517
3509
|
children: (0, react_jsx_runtime.jsx)(EmptyIcon, {
|
|
3518
3510
|
className: "size-6",
|
|
@@ -3532,7 +3524,7 @@ function ResourceList({ resource, data, total, page = 1, pageSize = 10, onPageSi
|
|
|
3532
3524
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
3533
3525
|
className: "flex justify-center gap-2 pt-2",
|
|
3534
3526
|
children: [
|
|
3535
|
-
|
|
3527
|
+
onClearFilter && (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
3536
3528
|
type: "button",
|
|
3537
3529
|
variant: "outline",
|
|
3538
3530
|
size: "sm",
|
|
@@ -3720,43 +3712,46 @@ function ResourceList({ resource, data, total, page = 1, pageSize = 10, onPageSi
|
|
|
3720
3712
|
})
|
|
3721
3713
|
});
|
|
3722
3714
|
}
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3715
|
+
//#endregion
|
|
3716
|
+
//#region src/blocks/related-list-unbound.tsx
|
|
3717
|
+
function UnboundRelatedList(props) {
|
|
3718
|
+
const t = (0, _burojs_react.useOptionalT)();
|
|
3719
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
3720
|
+
className: "flex flex-col gap-2",
|
|
3721
|
+
"data-testid": `list-unbound:${props.resource}`,
|
|
3722
|
+
children: [props.title === void 0 ? null : (0, react_jsx_runtime.jsx)("h3", {
|
|
3723
|
+
className: "text-sm font-semibold",
|
|
3724
|
+
children: props.title
|
|
3725
|
+
}), (0, react_jsx_runtime.jsx)("p", {
|
|
3726
|
+
className: "text-sm text-muted-foreground",
|
|
3727
|
+
children: props.empty ?? t("table.empty", { defaultValue: "No records" })
|
|
3728
|
+
})]
|
|
3732
3729
|
});
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
};
|
|
3759
|
-
return [state, set];
|
|
3730
|
+
}
|
|
3731
|
+
function placementScope(scope, owner) {
|
|
3732
|
+
return scope ?? (owner === void 0 ? "session" : "none");
|
|
3733
|
+
}
|
|
3734
|
+
//#endregion
|
|
3735
|
+
//#region src/list-kit/pieces/bulk-reach.tsx
|
|
3736
|
+
function useBulkFlowReachable(resource) {
|
|
3737
|
+
const app = (0, _burojs_react.useApp)();
|
|
3738
|
+
const control = (0, _burojs_react.useFlowRowResolver)(resource);
|
|
3739
|
+
return (app.registry.get(resource)?.actions.bulk ?? []).some((action) => (0, _burojs_core_internal.isFlowAction)(action) && control(action.name, void 0).state !== "absent");
|
|
3740
|
+
}
|
|
3741
|
+
function ExportReach(props) {
|
|
3742
|
+
const { available } = (0, _burojs_react.useResourceExport)(props.resource);
|
|
3743
|
+
const capability = (0, _burojs_react.useCapability)("run", {
|
|
3744
|
+
resource: props.resource,
|
|
3745
|
+
target: {
|
|
3746
|
+
kind: "action",
|
|
3747
|
+
name: "export"
|
|
3748
|
+
},
|
|
3749
|
+
mode: "list"
|
|
3750
|
+
});
|
|
3751
|
+
return props.children(available && capability.allowed);
|
|
3752
|
+
}
|
|
3753
|
+
function BulkExportReach(props) {
|
|
3754
|
+
return (0, _burojs_react.useOptionalDataRuntime)() !== null ? (0, react_jsx_runtime.jsx)(ExportReach, { ...props }) : props.children(false);
|
|
3760
3755
|
}
|
|
3761
3756
|
//#endregion
|
|
3762
3757
|
//#region src/list-kit/pieces/piece.tsx
|
|
@@ -3824,15 +3819,47 @@ function ForceTableView(props) {
|
|
|
3824
3819
|
}
|
|
3825
3820
|
//#endregion
|
|
3826
3821
|
//#region src/list-kit/pieces/list-body.tsx
|
|
3822
|
+
function LinkDetachRowButton(props) {
|
|
3823
|
+
const { resource, linkEditing } = useListSurface();
|
|
3824
|
+
const t = (0, _burojs_react.useOptionalT)();
|
|
3825
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
3826
|
+
const detach = linkEditing?.detach;
|
|
3827
|
+
if (detach === void 0) return null;
|
|
3828
|
+
const label = t("field.link.detach", { defaultValue: "Detach" });
|
|
3829
|
+
return (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
3830
|
+
type: "button",
|
|
3831
|
+
size: "icon",
|
|
3832
|
+
variant: "ghost",
|
|
3833
|
+
className: "size-7",
|
|
3834
|
+
"aria-label": label,
|
|
3835
|
+
title: label,
|
|
3836
|
+
disabled: busy,
|
|
3837
|
+
"data-testid": `list-link-detach:${resource}:${props.row.id}`,
|
|
3838
|
+
onClick: (event) => {
|
|
3839
|
+
event.stopPropagation();
|
|
3840
|
+
setBusy(true);
|
|
3841
|
+
detach.onDetach([props.row]).finally(() => setBusy(false));
|
|
3842
|
+
},
|
|
3843
|
+
children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconUnlink, {
|
|
3844
|
+
className: "size-4",
|
|
3845
|
+
"aria-hidden": "true"
|
|
3846
|
+
})
|
|
3847
|
+
});
|
|
3848
|
+
}
|
|
3849
|
+
const linkDetachRow = (row) => (0, react_jsx_runtime.jsx)(LinkDetachRowButton, { row });
|
|
3827
3850
|
function ListBodyView() {
|
|
3828
3851
|
usePieceMount("body");
|
|
3829
3852
|
const list = (0, _burojs_react.useResourceListContext)();
|
|
3830
|
-
const { resource, route, tableView, createAvailable, createPage, rowProps, rowsViewFor, emptyState, renderCell, readOnly } = useListSurface();
|
|
3853
|
+
const { resource, route, tableView, createAvailable, createPage, rowProps, rowsViewFor, emptyState, renderCell, readOnly, linkEditing, layoutId } = useListSurface();
|
|
3854
|
+
const detachable = readOnly && linkEditing?.detach !== void 0;
|
|
3855
|
+
const flowReachable = useBulkFlowReachable(resource);
|
|
3856
|
+
const selectable = (exportReachable) => tableView && (detachable || !readOnly && (flowReachable || exportReachable));
|
|
3831
3857
|
const item = (0, react.useContext)(ListItemContext);
|
|
3832
3858
|
const rowsView = (0, react.useMemo)(() => rowsViewFor?.(item), [rowsViewFor, item]);
|
|
3833
3859
|
const { query, pagination, cursor, count, columns, selection, filters, sorting, routing } = list;
|
|
3834
3860
|
const rows = (0, _burojs_react.policyRowsOf)(list, list.rows);
|
|
3835
|
-
return (0, react_jsx_runtime.jsx)(
|
|
3861
|
+
if (query.unbound) return (0, react_jsx_runtime.jsx)(UnboundRelatedList, { resource });
|
|
3862
|
+
const view = (exportReachable) => (0, react_jsx_runtime.jsx)(ResourceList, {
|
|
3836
3863
|
resource,
|
|
3837
3864
|
data: rows,
|
|
3838
3865
|
total: pagination.total,
|
|
@@ -3849,29 +3876,50 @@ function ListBodyView() {
|
|
|
3849
3876
|
onRequestCount: count.available ? count.request : void 0,
|
|
3850
3877
|
isCountingRows: count.isLoading,
|
|
3851
3878
|
columns: columns.visible,
|
|
3879
|
+
columnUi: columns.ui,
|
|
3852
3880
|
isLoading: query.isLoading,
|
|
3853
3881
|
error: query.error,
|
|
3854
3882
|
onRetry: query.refetch,
|
|
3855
3883
|
createHref: route && createAvailable && createPage ? routing.createHref : void 0,
|
|
3856
3884
|
...rowProps,
|
|
3857
3885
|
...rowsView === void 0 ? {} : { rowsView },
|
|
3858
|
-
selectable:
|
|
3859
|
-
rowActions: !readOnly,
|
|
3886
|
+
selectable: selectable(exportReachable),
|
|
3887
|
+
rowActions: detachable ? linkDetachRow : !readOnly,
|
|
3860
3888
|
selectedIds: selection.ids,
|
|
3861
3889
|
onSelectionChange: selection.set,
|
|
3862
3890
|
isFiltered: filters.isFiltered,
|
|
3863
|
-
onClearFilter: filters.
|
|
3891
|
+
onClearFilter: filters.canReset ? filters.reset : void 0,
|
|
3864
3892
|
emptyState,
|
|
3865
3893
|
sort: sorting.value ?? [],
|
|
3866
3894
|
requiredColumns: columns.required,
|
|
3867
3895
|
resetLayout: columns.resetLayout,
|
|
3896
|
+
layoutId,
|
|
3868
3897
|
onHideColumn: columns.hide,
|
|
3869
3898
|
onSort: sorting.toggle,
|
|
3899
|
+
sortable: sorting.sortable,
|
|
3870
3900
|
renderCell
|
|
3871
3901
|
});
|
|
3902
|
+
return (0, react_jsx_runtime.jsx)(BulkExportReach, {
|
|
3903
|
+
resource,
|
|
3904
|
+
children: view
|
|
3905
|
+
});
|
|
3872
3906
|
}
|
|
3873
3907
|
const ListBody = listPiece("ListBody", ListBodyView);
|
|
3874
3908
|
//#endregion
|
|
3909
|
+
//#region src/resource/form-context.tsx
|
|
3910
|
+
const FormControlContext = (0, react.createContext)(null);
|
|
3911
|
+
const FormControlProvider = FormControlContext.Provider;
|
|
3912
|
+
function useFormControlOf(controller) {
|
|
3913
|
+
const latest = (0, react.useRef)(controller);
|
|
3914
|
+
latest.current = controller;
|
|
3915
|
+
return (0, react.useMemo)(() => ({ setValues: (patch) => {
|
|
3916
|
+
for (const [name, value] of Object.entries(patch)) latest.current.setValue(name, value);
|
|
3917
|
+
} }), []);
|
|
3918
|
+
}
|
|
3919
|
+
function useFormControl() {
|
|
3920
|
+
return (0, react.useContext)(FormControlContext);
|
|
3921
|
+
}
|
|
3922
|
+
//#endregion
|
|
3875
3923
|
//#region src/record/route-screen-context.ts
|
|
3876
3924
|
const RouteScreenClaimContext = (0, react.createContext)(false);
|
|
3877
3925
|
const RouteScreenContext = (0, react.createContext)(false);
|
|
@@ -3995,7 +4043,7 @@ function PanelHost({ node, region = "panel-body", renderChildren }) {
|
|
|
3995
4043
|
region,
|
|
3996
4044
|
form,
|
|
3997
4045
|
labelledBy: title === void 0 ? void 0 : titleId,
|
|
3998
|
-
children: renderChildren(node.children)
|
|
4046
|
+
children: renderChildren(node.children, node)
|
|
3999
4047
|
}) : null,
|
|
4000
4048
|
...title === void 0 ? {} : { title },
|
|
4001
4049
|
...description === void 0 ? {} : { description },
|
|
@@ -4030,10 +4078,12 @@ function TabsHost({ node, renderChildren }) {
|
|
|
4030
4078
|
const state = (0, _burojs_react.useScreenState)();
|
|
4031
4079
|
const text = useNodeText();
|
|
4032
4080
|
const panels = node.children.filter((child) => child.state !== "absent");
|
|
4033
|
-
const
|
|
4081
|
+
const declared = compiled.nodes[node.index].options.default;
|
|
4082
|
+
const effectiveDefault = (declared === void 0 ? void 0 : panels.find((child) => child.key === declared)) ?? panels[0];
|
|
4083
|
+
const open = panels.find((child) => child.open === true) ?? effectiveDefault;
|
|
4034
4084
|
const urlSelect = useTabsUrlSelect();
|
|
4035
4085
|
const select = (panel, reveal) => {
|
|
4036
|
-
if (urlSelect !== null && node.key !== void 0 && panel.key !== void 0) urlSelect(node.key, panel.key, panel ===
|
|
4086
|
+
if (urlSelect !== null && node.key !== void 0 && panel.key !== void 0) urlSelect(node.key, panel.key, panel === effectiveDefault, reveal);
|
|
4037
4087
|
else state?.openPanel(node.id, panelValue(panel));
|
|
4038
4088
|
};
|
|
4039
4089
|
const onSelect = (key) => {
|
|
@@ -4045,7 +4095,7 @@ function TabsHost({ node, renderChildren }) {
|
|
|
4045
4095
|
key: panelValue(panel),
|
|
4046
4096
|
title: titleOf(panel),
|
|
4047
4097
|
errorCount: panel.key === void 0 ? 0 : controller.errorsIn(panel.key),
|
|
4048
|
-
panel: panels.length === 1 || panel.open === true ? (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: renderChildren(panel.children) }) : null
|
|
4098
|
+
panel: panels.length === 1 || panel.open === true ? (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: renderChildren(panel.children, panel) }) : null
|
|
4049
4099
|
}));
|
|
4050
4100
|
const { view: View, id } = useNodeView(node, "tabs");
|
|
4051
4101
|
const t = (0, _burojs_react.useFrameT)(id);
|
|
@@ -4156,7 +4206,7 @@ function WizardHost({ node, renderChildren }) {
|
|
|
4156
4206
|
region: "step-panel",
|
|
4157
4207
|
form,
|
|
4158
4208
|
labelledBy: titleId,
|
|
4159
|
-
children: renderChildren(panel.children)
|
|
4209
|
+
children: renderChildren(panel.children, panel)
|
|
4160
4210
|
}),
|
|
4161
4211
|
...description === void 0 ? {} : { description },
|
|
4162
4212
|
titleId,
|
|
@@ -4202,18 +4252,23 @@ function WizardHost({ node, renderChildren }) {
|
|
|
4202
4252
|
//#region src/screen/nodes.tsx
|
|
4203
4253
|
function FailedNode({ node }) {
|
|
4204
4254
|
const { controller } = useScreenTree();
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4255
|
+
let error;
|
|
4256
|
+
for (const name of node.failedOn) {
|
|
4257
|
+
const source = controller.sources[name];
|
|
4258
|
+
if (source?.status === "failed") {
|
|
4259
|
+
error = source.error;
|
|
4260
|
+
break;
|
|
4261
|
+
}
|
|
4262
|
+
}
|
|
4263
|
+
return (0, react_jsx_runtime.jsx)(require_relation_create.LoadError, {
|
|
4264
|
+
surface: "tab",
|
|
4265
|
+
error,
|
|
4266
|
+
retry: () => controller.retry(node.failedOn),
|
|
4267
|
+
fallback: {
|
|
4268
|
+
key: "screen.failed",
|
|
4269
|
+
default: "This section could not be loaded."
|
|
4270
|
+
},
|
|
4271
|
+
attributes: nodeAttributes(node)
|
|
4217
4272
|
});
|
|
4218
4273
|
}
|
|
4219
4274
|
function failedOnlyOnMeta(node) {
|
|
@@ -4226,8 +4281,17 @@ function drawn(node, hiddenFields) {
|
|
|
4226
4281
|
if (node.state === "absent") return false;
|
|
4227
4282
|
return !(node.kind === "field" && node.field !== void 0 && hiddenFields?.has(node.field));
|
|
4228
4283
|
}
|
|
4229
|
-
function SectionChildren({ nodes }) {
|
|
4230
|
-
const { hiddenFields } = useScreenTree();
|
|
4284
|
+
function SectionChildren({ nodes, owner }) {
|
|
4285
|
+
const { compiled, hiddenFields } = useScreenTree();
|
|
4286
|
+
const text = useNodeText();
|
|
4287
|
+
if (owner !== void 0 && !nodes.some((node) => drawn(node, hiddenFields))) {
|
|
4288
|
+
const empty = text(compiled.nodes[owner.index]?.options.empty);
|
|
4289
|
+
return empty === void 0 || empty === "" ? null : (0, react_jsx_runtime.jsx)("p", {
|
|
4290
|
+
"data-buro-region": "empty",
|
|
4291
|
+
className: "text-sm text-muted-foreground",
|
|
4292
|
+
children: empty
|
|
4293
|
+
});
|
|
4294
|
+
}
|
|
4231
4295
|
const out = [];
|
|
4232
4296
|
let run = [];
|
|
4233
4297
|
const flush = () => {
|
|
@@ -4249,8 +4313,11 @@ function SectionChildren({ nodes }) {
|
|
|
4249
4313
|
flush();
|
|
4250
4314
|
return out;
|
|
4251
4315
|
}
|
|
4252
|
-
function renderSection(nodes) {
|
|
4253
|
-
return (0, react_jsx_runtime.jsx)(SectionChildren, {
|
|
4316
|
+
function renderSection(nodes, owner) {
|
|
4317
|
+
return (0, react_jsx_runtime.jsx)(SectionChildren, {
|
|
4318
|
+
nodes,
|
|
4319
|
+
owner
|
|
4320
|
+
});
|
|
4254
4321
|
}
|
|
4255
4322
|
function Layout({ node }) {
|
|
4256
4323
|
return (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -4372,17 +4439,14 @@ function pageHost(page) {
|
|
|
4372
4439
|
}
|
|
4373
4440
|
//#endregion
|
|
4374
4441
|
//#region src/forms/declarative-form.tsx
|
|
4375
|
-
function
|
|
4376
|
-
const translated = t(key);
|
|
4377
|
-
return translated === key ? fallback : translated;
|
|
4378
|
-
}
|
|
4379
|
-
function issueText(issue, t, i18nPrefix) {
|
|
4442
|
+
function issueText(issue, caps, i18nPrefix) {
|
|
4380
4443
|
return (0, _burojs_react.resolveValidationMessage)({
|
|
4381
4444
|
code: issue.code ?? "",
|
|
4382
4445
|
message: issue.message,
|
|
4383
|
-
...issue.
|
|
4446
|
+
...issue.check === void 0 ? {} : { check: issue.check }
|
|
4384
4447
|
}, {
|
|
4385
|
-
|
|
4448
|
+
has: caps.has,
|
|
4449
|
+
t: caps.t,
|
|
4386
4450
|
...issue.field === "_form" ? {} : { fieldKey: `resources.${i18nPrefix}.fields.${issue.field}` }
|
|
4387
4451
|
});
|
|
4388
4452
|
}
|
|
@@ -4449,7 +4513,9 @@ function DeclarativeFormBody(props) {
|
|
|
4449
4513
|
...props.surface === void 0 ? {} : { surface: props.surface },
|
|
4450
4514
|
...props.onSubmit === void 0 ? {} : { onSubmit: props.onSubmit }
|
|
4451
4515
|
});
|
|
4452
|
-
const
|
|
4516
|
+
const formControl = useFormControlOf(form);
|
|
4517
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
4518
|
+
const caps = (0, _burojs_react.useI18nCaps)();
|
|
4453
4519
|
const disabled = props.disabled === true;
|
|
4454
4520
|
const uid = (0, react.useId)();
|
|
4455
4521
|
const leafIds = (0, react.useMemo)(() => ({
|
|
@@ -4459,8 +4525,8 @@ function DeclarativeFormBody(props) {
|
|
|
4459
4525
|
const formErrors = form.errors.filter((issue) => issue.field === "_form");
|
|
4460
4526
|
const retryableChecks = [];
|
|
4461
4527
|
for (const issue of form.checkOutcome?.blockers ?? []) {
|
|
4462
|
-
const checkId = issue.
|
|
4463
|
-
if (issue.
|
|
4528
|
+
const checkId = issue.check?.id;
|
|
4529
|
+
if (issue.check?.cause === void 0 || typeof checkId !== "string") continue;
|
|
4464
4530
|
if (!retryableChecks.includes(checkId)) retryableChecks.push(checkId);
|
|
4465
4531
|
}
|
|
4466
4532
|
const formWarnings = form.warnings.filter((issue) => issue.field === "_form");
|
|
@@ -4473,7 +4539,7 @@ function DeclarativeFormBody(props) {
|
|
|
4473
4539
|
formErrors.length > 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
4474
4540
|
role: "alert",
|
|
4475
4541
|
className: "mb-4 flex flex-col gap-1 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive",
|
|
4476
|
-
children: formErrors.map((issue, index) => (0, react_jsx_runtime.jsx)("p", { children: issueText(issue,
|
|
4542
|
+
children: formErrors.map((issue, index) => (0, react_jsx_runtime.jsx)("p", { children: issueText(issue, caps, prefix) }, index))
|
|
4477
4543
|
}),
|
|
4478
4544
|
retryableChecks.length > 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
4479
4545
|
className: "mb-4 flex flex-wrap gap-2",
|
|
@@ -4483,25 +4549,28 @@ function DeclarativeFormBody(props) {
|
|
|
4483
4549
|
size: "sm",
|
|
4484
4550
|
"data-testid": `form-check-retry:${checkId}`,
|
|
4485
4551
|
onClick: () => void form.revalidate(),
|
|
4486
|
-
children:
|
|
4552
|
+
children: chromeT("actions.retry", { defaultValue: "Retry" })
|
|
4487
4553
|
}, checkId))
|
|
4488
4554
|
}),
|
|
4489
4555
|
formWarnings.length > 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
4490
4556
|
role: "status",
|
|
4491
4557
|
"aria-live": "polite",
|
|
4492
4558
|
className: "mb-4 flex flex-col gap-1 rounded-md border border-warning/50 bg-warning/10 px-3 py-2 text-sm text-warning-emphasis",
|
|
4493
|
-
children: formWarnings.map((issue, index) => (0, react_jsx_runtime.jsx)("p", { children: issueText(issue,
|
|
4559
|
+
children: formWarnings.map((issue, index) => (0, react_jsx_runtime.jsx)("p", { children: issueText(issue, caps, prefix) }, index))
|
|
4494
4560
|
}),
|
|
4495
|
-
(0, react_jsx_runtime.jsx)(
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4561
|
+
(0, react_jsx_runtime.jsx)(FormControlProvider, {
|
|
4562
|
+
value: formControl,
|
|
4563
|
+
children: (0, react_jsx_runtime.jsx)(ScreenTree, {
|
|
4564
|
+
region: "form-body",
|
|
4565
|
+
resource: prefix,
|
|
4566
|
+
mode: "create",
|
|
4567
|
+
compiled: form.screen,
|
|
4568
|
+
controller: form,
|
|
4569
|
+
leafIds,
|
|
4570
|
+
...props.renderField === void 0 ? {} : { renderField: props.renderField },
|
|
4571
|
+
disabled,
|
|
4572
|
+
...props.bodyClassName === void 0 ? {} : { className: props.bodyClassName }
|
|
4573
|
+
})
|
|
4505
4574
|
}),
|
|
4506
4575
|
props.slots?.footer === void 0 ? (0, react_jsx_runtime.jsx)("div", {
|
|
4507
4576
|
className: "mt-4 flex justify-end",
|
|
@@ -4509,7 +4578,7 @@ function DeclarativeFormBody(props) {
|
|
|
4509
4578
|
type: "submit",
|
|
4510
4579
|
disabled: !form.canSubmit || disabled,
|
|
4511
4580
|
onMouseDown: (event) => event.preventDefault(),
|
|
4512
|
-
children: props.submitLabel ??
|
|
4581
|
+
children: props.submitLabel ?? chromeT("actions.save", { defaultValue: "Save" })
|
|
4513
4582
|
})
|
|
4514
4583
|
}) : typeof props.slots.footer === "function" ? props.slots.footer({ canSubmit: form.canSubmit && !disabled }) : props.slots.footer
|
|
4515
4584
|
]
|
|
@@ -4594,7 +4663,8 @@ function ExportOptionsDirty({ dirty }) {
|
|
|
4594
4663
|
return null;
|
|
4595
4664
|
}
|
|
4596
4665
|
function getNoRunState() {}
|
|
4597
|
-
function ExportDialog({ open, onOpenChange, resource, target, visibleColumns, estimatedCount, scope }) {
|
|
4666
|
+
function ExportDialog({ open, onOpenChange, resource: resourceInput, target, visibleColumns, estimatedCount, scope }) {
|
|
4667
|
+
const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
|
|
4598
4668
|
const t = (0, _burojs_react.useOptionalT)();
|
|
4599
4669
|
const dialogTestId = (0, _burojs_react.useTestIds)().exportDialog(resource);
|
|
4600
4670
|
const { formats, start, exporter, available, error, loading } = (0, _burojs_react.useResourceExport)(resource, {
|
|
@@ -4716,14 +4786,15 @@ function ExportDialog({ open, onOpenChange, resource, target, visibleColumns, es
|
|
|
4716
4786
|
})] }), (0, react_jsx_runtime.jsx)(ExportProgressView, {
|
|
4717
4787
|
state: runState,
|
|
4718
4788
|
dialogTestId,
|
|
4719
|
-
t
|
|
4789
|
+
t,
|
|
4790
|
+
caps
|
|
4720
4791
|
})] }) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)(require_dialog.DialogHeader, { children: [(0, react_jsx_runtime.jsx)(require_dialog.DialogTitle, { children: titleText }), (0, react_jsx_runtime.jsx)(require_dialog.DialogDescription, {
|
|
4721
4792
|
className: "sr-only",
|
|
4722
4793
|
children: titleText
|
|
4723
4794
|
})] }), !available ? (0, react_jsx_runtime.jsx)("p", {
|
|
4724
4795
|
role: "alert",
|
|
4725
4796
|
"data-testid": `${dialogTestId}:unavailable`,
|
|
4726
|
-
children: error
|
|
4797
|
+
children: error === void 0 || error === null ? t("export.dialog.unavailable") : (0, _burojs_react.resolveErrorText)(error, caps)
|
|
4727
4798
|
}) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
4728
4799
|
loading ? (0, react_jsx_runtime.jsx)("p", {
|
|
4729
4800
|
role: "status",
|
|
@@ -4802,7 +4873,7 @@ function ExportDialog({ open, onOpenChange, resource, target, visibleColumns, es
|
|
|
4802
4873
|
})
|
|
4803
4874
|
});
|
|
4804
4875
|
}
|
|
4805
|
-
function ExportProgressView({ state, dialogTestId, t }) {
|
|
4876
|
+
function ExportProgressView({ state, dialogTestId, t, caps }) {
|
|
4806
4877
|
if (state === void 0) return null;
|
|
4807
4878
|
if (state.status === "running") {
|
|
4808
4879
|
const total = state.progress?.total;
|
|
@@ -4823,7 +4894,7 @@ function ExportProgressView({ state, dialogTestId, t }) {
|
|
|
4823
4894
|
if (state.status === "failed") return (0, react_jsx_runtime.jsx)("p", {
|
|
4824
4895
|
role: "alert",
|
|
4825
4896
|
"data-testid": `${dialogTestId}:error`,
|
|
4826
|
-
children: `${t("export.dialog.failed")}: ${state.error
|
|
4897
|
+
children: `${t("export.dialog.failed")}: ${(0, _burojs_react.resolveErrorText)(state.error, caps)}`
|
|
4827
4898
|
});
|
|
4828
4899
|
if (state.status === "canceled") return (0, react_jsx_runtime.jsx)("p", {
|
|
4829
4900
|
"data-testid": `${dialogTestId}:canceled`,
|
|
@@ -4836,6 +4907,7 @@ function ExportProgressView({ state, dialogTestId, t }) {
|
|
|
4836
4907
|
function BulkSummary(props) {
|
|
4837
4908
|
const loaded = require_check_confirm_dialog.useLoaded(require_check_confirm_dialog.loadBulkSummary);
|
|
4838
4909
|
const t = (0, _burojs_react.useOptionalT)();
|
|
4910
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
4839
4911
|
const failed = (retry) => (0, react_jsx_runtime.jsxs)("div", {
|
|
4840
4912
|
role: "alert",
|
|
4841
4913
|
className: "flex items-center gap-2 text-sm",
|
|
@@ -4844,7 +4916,7 @@ function BulkSummary(props) {
|
|
|
4844
4916
|
size: "sm",
|
|
4845
4917
|
variant: "outline",
|
|
4846
4918
|
onClick: retry,
|
|
4847
|
-
children:
|
|
4919
|
+
children: chromeT("actions.retry", { defaultValue: "Retry" })
|
|
4848
4920
|
})]
|
|
4849
4921
|
});
|
|
4850
4922
|
if (loaded.error !== void 0) return failed(loaded.retry);
|
|
@@ -4862,13 +4934,14 @@ function BulkFlowButton({ resource, actionName, ids, onSelectionChange }) {
|
|
|
4862
4934
|
const control = (0, _burojs_react.useFlowRowResolver)(resource)(actionName, void 0);
|
|
4863
4935
|
const chrome = require_check_confirm_dialog.useFlowChrome(resource, actionName);
|
|
4864
4936
|
const def = app.registry.get(resource);
|
|
4865
|
-
const
|
|
4937
|
+
const compiled = (0, react.useMemo)(() => {
|
|
4866
4938
|
try {
|
|
4867
|
-
return def === void 0 ?
|
|
4939
|
+
return def === void 0 ? void 0 : (0, _burojs_core.compileFlow)(def, actionName);
|
|
4868
4940
|
} catch {
|
|
4869
|
-
return
|
|
4941
|
+
return;
|
|
4870
4942
|
}
|
|
4871
4943
|
}, [def, actionName]);
|
|
4944
|
+
const each = compiled?.each ?? false;
|
|
4872
4945
|
const [running, setRunning] = (0, react.useState)(false);
|
|
4873
4946
|
const [summary, setSummary] = (0, react.useState)(null);
|
|
4874
4947
|
const testid = tid.bulkAction(resource, actionName);
|
|
@@ -4876,7 +4949,10 @@ function BulkFlowButton({ resource, actionName, ids, onSelectionChange }) {
|
|
|
4876
4949
|
const variant = chrome.destructive ? "destructive" : "outline";
|
|
4877
4950
|
const overLimit = each && ids.length > _burojs_core.BULK_EACH_LIMIT;
|
|
4878
4951
|
if (overLimit || control.state === "disabled") return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.DisabledAction, {
|
|
4879
|
-
reason: overLimit ?
|
|
4952
|
+
reason: overLimit ? t("flow.bulkLimit", {
|
|
4953
|
+
defaultValue: `Select at most ${_burojs_core.BULK_EACH_LIMIT}.`,
|
|
4954
|
+
count: _burojs_core.BULK_EACH_LIMIT
|
|
4955
|
+
}) : control.reason,
|
|
4880
4956
|
label: chrome.label,
|
|
4881
4957
|
icon: chrome.icon,
|
|
4882
4958
|
testid,
|
|
@@ -4938,14 +5014,15 @@ function BulkFlowButton({ resource, actionName, ids, onSelectionChange }) {
|
|
|
4938
5014
|
actionName,
|
|
4939
5015
|
label: chrome.labelText,
|
|
4940
5016
|
total: summary.total,
|
|
4941
|
-
progress: summary.progress
|
|
5017
|
+
progress: summary.progress,
|
|
5018
|
+
texts: compiled?.flow.texts
|
|
4942
5019
|
}),
|
|
4943
5020
|
(0, react_jsx_runtime.jsx)(require_dialog.DialogFooter, { children: (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
4944
5021
|
type: "button",
|
|
4945
5022
|
variant: "outline",
|
|
4946
5023
|
"data-testid": `${tid.bulkSummary(resource, actionName)}:close`,
|
|
4947
5024
|
onClick: () => setSummary(null),
|
|
4948
|
-
children:
|
|
5025
|
+
children: t("flow.close", { defaultValue: "Close" })
|
|
4949
5026
|
}) })
|
|
4950
5027
|
]
|
|
4951
5028
|
})
|
|
@@ -4961,10 +5038,12 @@ function orderBulkActions(actions) {
|
|
|
4961
5038
|
seq: index
|
|
4962
5039
|
})).sort((a, b) => a.weight - b.weight || a.seq - b.seq).map(({ action }) => action);
|
|
4963
5040
|
}
|
|
4964
|
-
function BulkActionToolbar({ resource, table, selectedRecords, selectedIds, onClearSelection, onSelectionChange, className, visibleColumns, scope }) {
|
|
5041
|
+
function BulkActionToolbar({ resource: resourceInput, table, selectedRecords, selectedIds, onClearSelection, onSelectionChange, className, visibleColumns, scope, actions }) {
|
|
5042
|
+
const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
|
|
4965
5043
|
const app = (0, _burojs_react.useApp)();
|
|
4966
5044
|
const tid = (0, _burojs_react.useTestIds)();
|
|
4967
5045
|
const t = (0, _burojs_react.useOptionalT)();
|
|
5046
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
4968
5047
|
const def = app.registry.get(resource);
|
|
4969
5048
|
const records = selectedRecords ?? (table ? table.getFilteredSelectedRowModel().rows.map((r) => r.original) : []);
|
|
4970
5049
|
const ids = selectedIds ?? records.map((record) => record.id);
|
|
@@ -4997,7 +5076,8 @@ function BulkActionToolbar({ resource, table, selectedRecords, selectedIds, onCl
|
|
|
4997
5076
|
className: "mx-0.5 h-6 w-px bg-border",
|
|
4998
5077
|
"aria-hidden": "true"
|
|
4999
5078
|
}),
|
|
5000
|
-
|
|
5079
|
+
actions !== void 0 ? actions : null,
|
|
5080
|
+
actions === void 0 && bulkActions.map((action) => (0, react_jsx_runtime.jsx)(BulkFlowButton, {
|
|
5001
5081
|
resource,
|
|
5002
5082
|
actionName: action.name,
|
|
5003
5083
|
ids,
|
|
@@ -5006,7 +5086,7 @@ function BulkActionToolbar({ resource, table, selectedRecords, selectedIds, onCl
|
|
|
5006
5086
|
else if (next.length === 0) handleClear();
|
|
5007
5087
|
}
|
|
5008
5088
|
}, action.name)),
|
|
5009
|
-
(0, react_jsx_runtime.jsx)(BulkExportButton, {
|
|
5089
|
+
actions === void 0 && (0, react_jsx_runtime.jsx)(BulkExportButton, {
|
|
5010
5090
|
resource,
|
|
5011
5091
|
ids,
|
|
5012
5092
|
visibleColumns: visibleColumns ?? [],
|
|
@@ -5023,7 +5103,7 @@ function BulkActionToolbar({ resource, table, selectedRecords, selectedIds, onCl
|
|
|
5023
5103
|
"aria-hidden": "true"
|
|
5024
5104
|
}), (0, react_jsx_runtime.jsx)("span", {
|
|
5025
5105
|
className: "hidden sm:inline",
|
|
5026
|
-
children:
|
|
5106
|
+
children: chromeT("actions.clearSelection", { defaultValue: "Clear" })
|
|
5027
5107
|
})]
|
|
5028
5108
|
})
|
|
5029
5109
|
]
|
|
@@ -5083,12 +5163,36 @@ function BulkExportButtonActive({ resource, ids, visibleColumns, scope }) {
|
|
|
5083
5163
|
}
|
|
5084
5164
|
//#endregion
|
|
5085
5165
|
//#region src/list-kit/pieces/list-bulk-bar.tsx
|
|
5166
|
+
function LinkDetachBulkButton(props) {
|
|
5167
|
+
const { selection } = (0, _burojs_react.useResourceListContext)();
|
|
5168
|
+
const { resource } = useListSurface();
|
|
5169
|
+
const t = (0, _burojs_react.useOptionalT)();
|
|
5170
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
5171
|
+
return (0, react_jsx_runtime.jsxs)(require_button.Button, {
|
|
5172
|
+
type: "button",
|
|
5173
|
+
size: "sm",
|
|
5174
|
+
variant: "ghost",
|
|
5175
|
+
className: "h-8 gap-1.5 rounded-full px-2.5 text-destructive",
|
|
5176
|
+
disabled: busy,
|
|
5177
|
+
"data-testid": `list-link-detach-bulk:${resource}`,
|
|
5178
|
+
onClick: () => {
|
|
5179
|
+
setBusy(true);
|
|
5180
|
+
props.onDetach(selection.records).finally(() => setBusy(false));
|
|
5181
|
+
},
|
|
5182
|
+
children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconUnlink, {
|
|
5183
|
+
className: "size-4",
|
|
5184
|
+
"aria-hidden": "true"
|
|
5185
|
+
}), t("field.link.detach", { defaultValue: "Detach" })]
|
|
5186
|
+
});
|
|
5187
|
+
}
|
|
5086
5188
|
function ListBulkBarView() {
|
|
5087
5189
|
usePieceMount("bulk-bar");
|
|
5088
5190
|
const { selection, columns, scope } = (0, _burojs_react.useResourceListContext)();
|
|
5089
|
-
const { resource, tableView, readOnly } = useListSurface();
|
|
5090
|
-
|
|
5191
|
+
const { resource, tableView, readOnly, linkEditing } = useListSurface();
|
|
5192
|
+
const detach = readOnly ? linkEditing?.detach : void 0;
|
|
5193
|
+
if (!tableView || readOnly && detach === void 0 || selection.ids.length === 0) return null;
|
|
5091
5194
|
return (0, react_jsx_runtime.jsx)(BulkActionToolbar, {
|
|
5195
|
+
...detach === void 0 ? {} : { actions: (0, react_jsx_runtime.jsx)(LinkDetachBulkButton, { onDetach: detach.onDetach }) },
|
|
5092
5196
|
resource,
|
|
5093
5197
|
selectedRecords: selection.records,
|
|
5094
5198
|
selectedIds: selection.ids,
|
|
@@ -5177,7 +5281,8 @@ function DataTableViewOptions({ table, getColumnLabel, isColumnRequired, getTest
|
|
|
5177
5281
|
}
|
|
5178
5282
|
//#endregion
|
|
5179
5283
|
//#region src/list-kit/columns-toggle.tsx
|
|
5180
|
-
function ColumnsToggle({ resource, def, allAvailable, required, visibleColumns, defaultVisible, onChange, onResetSizes, onRestoreDefaults }) {
|
|
5284
|
+
function ColumnsToggle({ resource: resourceInput, def, allAvailable, required, visibleColumns, defaultVisible, onChange, onResetSizes, onRestoreDefaults }) {
|
|
5285
|
+
const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
|
|
5181
5286
|
const t = (0, _burojs_react.useT)();
|
|
5182
5287
|
const columnsCaps = (0, _burojs_react.useI18nCaps)(resource);
|
|
5183
5288
|
const app = (0, _burojs_react.useApp)();
|
|
@@ -5284,12 +5389,16 @@ function ListColumnsView() {
|
|
|
5284
5389
|
const ListColumns = listPiece("ListColumns", ListColumnsView);
|
|
5285
5390
|
//#endregion
|
|
5286
5391
|
//#region src/resource/create-button.tsx
|
|
5287
|
-
function CreateButton({ resource, href, testid, size = "sm", variant, label, className, onOpen }) {
|
|
5392
|
+
function CreateButton({ resource: resourceInput, href, testid, size = "sm", variant, label, className, onOpen }) {
|
|
5393
|
+
const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
|
|
5288
5394
|
const t = (0, _burojs_react.useOptionalT)();
|
|
5289
5395
|
const Link = require_toaster.useLinkComponent();
|
|
5290
5396
|
const availability = (0, _burojs_react.useAvailability)(resource, "create");
|
|
5291
5397
|
const gate = (0, _burojs_react.useEntryGate)();
|
|
5292
|
-
const text = label ?? t("actions.create", {
|
|
5398
|
+
const text = label ?? t("actions.create", {
|
|
5399
|
+
resource,
|
|
5400
|
+
defaultValue: "Create"
|
|
5401
|
+
});
|
|
5293
5402
|
if (onOpen !== void 0) {
|
|
5294
5403
|
const answer = gate(resource, "create");
|
|
5295
5404
|
if (answer.state === "disabled") return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.DisabledAction, {
|
|
@@ -5360,7 +5469,8 @@ const ListCreate = listPiece("ListCreate", ListCreateView);
|
|
|
5360
5469
|
//#endregion
|
|
5361
5470
|
//#region src/export/export-button.tsx
|
|
5362
5471
|
const warnedProviderQueryResources = new Set();
|
|
5363
|
-
function ExportButton({ resource, className }) {
|
|
5472
|
+
function ExportButton({ resource: resourceInput, className }) {
|
|
5473
|
+
const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
|
|
5364
5474
|
if (!((0, _burojs_react.useOptionalDataRuntime)() !== null)) return null;
|
|
5365
5475
|
return (0, react_jsx_runtime.jsx)(ExportButtonActive, {
|
|
5366
5476
|
resource,
|
|
@@ -5381,36 +5491,19 @@ function ExportButtonActive({ resource, className }) {
|
|
|
5381
5491
|
const tid = (0, _burojs_react.useTestIds)();
|
|
5382
5492
|
const t = (0, _burojs_react.useOptionalT)();
|
|
5383
5493
|
const [open, setOpen] = react.useState(false);
|
|
5384
|
-
const
|
|
5385
|
-
resource,
|
|
5386
|
-
def: list.def
|
|
5387
|
-
}), [resource, list.def]);
|
|
5494
|
+
const sent = list.query.sent;
|
|
5388
5495
|
const target = react.useMemo(() => {
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
pinned: list.filters.value,
|
|
5392
|
-
group: list.filters.group,
|
|
5393
|
-
search: list.filters.search,
|
|
5394
|
-
searchDecl: list.filters.searchEnabled ? list.filters.searchDecl ?? list.def?.views?.list?.search : void 0,
|
|
5395
|
-
searchContext
|
|
5396
|
-
});
|
|
5397
|
-
const sort = list.sorting.value;
|
|
5496
|
+
if (sent === null) return null;
|
|
5497
|
+
const { filter, sort } = sent;
|
|
5398
5498
|
return {
|
|
5399
5499
|
kind: "filter",
|
|
5400
5500
|
...filter === void 0 ? {} : { filter },
|
|
5401
5501
|
...sort.length > 0 ? { sort } : {}
|
|
5402
5502
|
};
|
|
5403
|
-
}, [
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
list.filters.search,
|
|
5408
|
-
list.filters.searchDecl,
|
|
5409
|
-
list.filters.searchEnabled,
|
|
5410
|
-
list.def,
|
|
5411
|
-
searchContext,
|
|
5412
|
-
list.sorting.value
|
|
5413
|
-
]);
|
|
5503
|
+
}, [sent]);
|
|
5504
|
+
const lastTarget = react.useRef(target);
|
|
5505
|
+
if (target !== null) lastTarget.current = target;
|
|
5506
|
+
const dialogTarget = target ?? lastTarget.current;
|
|
5414
5507
|
react.useEffect(() => {
|
|
5415
5508
|
if (!available || !capability.allowed) return;
|
|
5416
5509
|
if (list.providerQuery.value === void 0) return;
|
|
@@ -5424,7 +5517,9 @@ function ExportButtonActive({ resource, className }) {
|
|
|
5424
5517
|
resource
|
|
5425
5518
|
]);
|
|
5426
5519
|
if (!available || !capability.allowed || list.isForbidden) return null;
|
|
5427
|
-
|
|
5520
|
+
if (target === null && !open) return null;
|
|
5521
|
+
if (dialogTarget === null) return null;
|
|
5522
|
+
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [target === null ? null : (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
5428
5523
|
type: "button",
|
|
5429
5524
|
variant: "outline",
|
|
5430
5525
|
size: "icon",
|
|
@@ -5443,7 +5538,7 @@ function ExportButtonActive({ resource, className }) {
|
|
|
5443
5538
|
open,
|
|
5444
5539
|
onOpenChange: setOpen,
|
|
5445
5540
|
resource,
|
|
5446
|
-
target,
|
|
5541
|
+
target: dialogTarget,
|
|
5447
5542
|
visibleColumns: list.columns.visible,
|
|
5448
5543
|
estimatedCount: list.pagination.total,
|
|
5449
5544
|
scope: list.scope
|
|
@@ -5461,8 +5556,9 @@ function ListExportView() {
|
|
|
5461
5556
|
const ListExport = listPiece("ListExport", ListExportView);
|
|
5462
5557
|
//#endregion
|
|
5463
5558
|
//#region src/list-kit/list-search-input.tsx
|
|
5464
|
-
function ListSearchInput({ resource
|
|
5465
|
-
const
|
|
5559
|
+
function ListSearchInput({ resource: resourceInput, value, onCommit, placeholder }) {
|
|
5560
|
+
const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
|
|
5561
|
+
const caps = (0, _burojs_react.useI18nCaps)(resource);
|
|
5466
5562
|
const [text, setText] = (0, react.useState)(value);
|
|
5467
5563
|
const lastPushedRef = (0, react.useRef)(value);
|
|
5468
5564
|
const timerRef = (0, react.useRef)(null);
|
|
@@ -5477,7 +5573,7 @@ function ListSearchInput({ resource, label, value, onCommit, placeholder }) {
|
|
|
5477
5573
|
}, []);
|
|
5478
5574
|
return (0, react_jsx_runtime.jsx)(require_input.Input, {
|
|
5479
5575
|
type: "search",
|
|
5480
|
-
placeholder: placeholder ??
|
|
5576
|
+
placeholder: placeholder ?? (0, _burojs_core.resolveContentSlot)(caps, ["list.search"]) ?? "Search",
|
|
5481
5577
|
value: text,
|
|
5482
5578
|
"data-testid": `list-search:${resource}`,
|
|
5483
5579
|
className: "h-8 w-full min-[420px]:w-72",
|
|
@@ -5495,24 +5591,18 @@ function ListSearchInput({ resource, label, value, onCommit, placeholder }) {
|
|
|
5495
5591
|
//#endregion
|
|
5496
5592
|
//#region src/list-kit/filter-builder/filter-region.tsx
|
|
5497
5593
|
function FilterRegion({ search } = {}) {
|
|
5498
|
-
const { resource, def, filters, pagination
|
|
5499
|
-
const
|
|
5500
|
-
const listCaps = (0, _burojs_react.useI18nCaps)(resource);
|
|
5594
|
+
const { resource, def, filters, pagination } = (0, _burojs_react.useResourceListContext)();
|
|
5595
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
5501
5596
|
const testIdBase = `list-filter:${resource}`;
|
|
5597
|
+
const caps = (0, _burojs_react.useI18nCaps)(resource);
|
|
5598
|
+
const placeholder = search === void 0 ? (0, _burojs_core.resolveContentSlot)(caps, ["list.searchPlaceholder", "list.search"]) ?? "Search" : void 0;
|
|
5502
5599
|
const searchDecl = search === void 0 ? def?.views?.list?.search : search ?? void 0;
|
|
5503
|
-
const searchField = searchDecl !== void 0 && typeof searchDecl !== "function" ? (() => {
|
|
5504
|
-
return searchDecl.fields.map((entry) => typeof entry === "string" ? entry : entry.field).find((name) => access.fieldVisible(name));
|
|
5505
|
-
})() : void 0;
|
|
5506
|
-
const searchGenericLabel = (0, _burojs_core.resolveContentSlot)(listCaps, ["list.search"]) ?? "Search";
|
|
5507
|
-
const searchLabel = searchField ? (0, _burojs_core.resolveFieldLabel)(listCaps, searchField, (0, _burojs_core.declaredText)("field", def?.fields[searchField], "label")) : searchGenericLabel;
|
|
5508
|
-
const searchPlaceholder = searchField ? t("toolbar.searchBy", { params: { name: searchLabel } }) : searchGenericLabel;
|
|
5509
5600
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
5510
5601
|
className: "flex flex-wrap items-center gap-2",
|
|
5511
5602
|
children: [
|
|
5512
5603
|
searchDecl !== void 0 && filters.searchEnabled && (0, react_jsx_runtime.jsx)(ListSearchInput, {
|
|
5513
5604
|
resource,
|
|
5514
|
-
|
|
5515
|
-
placeholder: searchPlaceholder,
|
|
5605
|
+
...placeholder === void 0 ? {} : { placeholder },
|
|
5516
5606
|
value: filters.search,
|
|
5517
5607
|
onCommit: (v) => {
|
|
5518
5608
|
pagination.setPage(1);
|
|
@@ -5524,19 +5614,21 @@ function FilterRegion({ search } = {}) {
|
|
|
5524
5614
|
setGroup: filters.setGroup,
|
|
5525
5615
|
available: filters.available,
|
|
5526
5616
|
fixed: filters.fixed,
|
|
5617
|
+
presets: filters.presets,
|
|
5618
|
+
setPreset: filters.setPreset,
|
|
5527
5619
|
pinnedFields: filters.pinnedFields,
|
|
5528
5620
|
pinnedValue: filters.value,
|
|
5529
5621
|
setPinnedValue: filters.set,
|
|
5530
5622
|
setPage: pagination.setPage,
|
|
5531
5623
|
testIdBase
|
|
5532
5624
|
}),
|
|
5533
|
-
filters.
|
|
5625
|
+
filters.canReset && (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
5534
5626
|
type: "button",
|
|
5535
5627
|
variant: "ghost",
|
|
5536
5628
|
size: "sm",
|
|
5537
5629
|
"data-testid": `${testIdBase}:clear-all`,
|
|
5538
|
-
onClick: filters.
|
|
5539
|
-
children:
|
|
5630
|
+
onClick: filters.reset,
|
|
5631
|
+
children: chromeT("filters.clearAll")
|
|
5540
5632
|
})
|
|
5541
5633
|
]
|
|
5542
5634
|
});
|
|
@@ -5666,6 +5758,7 @@ function ViewItem({ view, caps, resource, onClick, testid }) {
|
|
|
5666
5758
|
});
|
|
5667
5759
|
}
|
|
5668
5760
|
function EntryRow({ entry, onApply, onRename, onFork, onDelete, forkAvailable, applyTestId, renameTestId, forkTestId, deleteTestId, tr }) {
|
|
5761
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
5669
5762
|
const canRename = entry.permissions.update && onRename !== void 0;
|
|
5670
5763
|
const canFork = forkAvailable && entry.permissions.fork && onFork !== void 0;
|
|
5671
5764
|
const canDelete = entry.permissions.remove && onDelete !== void 0;
|
|
@@ -5711,8 +5804,8 @@ function EntryRow({ entry, onApply, onRename, onFork, onDelete, forkAvailable, a
|
|
|
5711
5804
|
canDelete && (0, react_jsx_runtime.jsx)("button", {
|
|
5712
5805
|
type: "button",
|
|
5713
5806
|
onClick: onDelete,
|
|
5714
|
-
"aria-label":
|
|
5715
|
-
title:
|
|
5807
|
+
"aria-label": chromeT("actions.delete", { defaultValue: "Delete" }),
|
|
5808
|
+
title: chromeT("actions.delete", { defaultValue: "Delete" }),
|
|
5716
5809
|
"data-testid": deleteTestId,
|
|
5717
5810
|
className: "shrink-0 rounded-sm p-1 text-muted-foreground hover:bg-accent hover:text-accent-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
|
|
5718
5811
|
children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconTrash, {
|
|
@@ -5752,7 +5845,8 @@ function groupByScope(entries) {
|
|
|
5752
5845
|
}
|
|
5753
5846
|
return order.map((id) => byId.get(id));
|
|
5754
5847
|
}
|
|
5755
|
-
function SavedViewsDropdown({ resource, adopterViews, entries, issues = [], onApply, onSaveCurrent, canSaveCurrent = true, onManage, onRenameEntry, onDeleteEntry, onForkEntry, canFork = true, getTestId, triggerLabel = "Views", iconOnly = false, triggerClassName = "h-9", popoverContentClassName = "w-64 p-1", popoverAlign = "start" }) {
|
|
5848
|
+
function SavedViewsDropdown({ resource: resourceInput, adopterViews, entries, issues = [], onApply, onSaveCurrent, canSaveCurrent = true, onManage, onRenameEntry, onDeleteEntry, onForkEntry, canFork = true, getTestId, triggerLabel = "Views", iconOnly = false, triggerClassName = "h-9", popoverContentClassName = "w-64 p-1", popoverAlign = "start" }) {
|
|
5849
|
+
const resource = resourceInput === void 0 ? void 0 : (0, _burojs_core.routeResourceKey)(resourceInput);
|
|
5756
5850
|
const t = (0, _burojs_react.useOptionalT)();
|
|
5757
5851
|
const caps = (0, _burojs_react.useI18nCaps)(resource);
|
|
5758
5852
|
const tr = (key, fallback) => t?.(key, { defaultValue: fallback }) ?? fallback;
|
|
@@ -5966,9 +6060,10 @@ function useOptionalFrameChrome() {
|
|
|
5966
6060
|
//#endregion
|
|
5967
6061
|
//#region src/record/frame-pieces.tsx
|
|
5968
6062
|
function useFrameId() {
|
|
5969
|
-
const { recordId, record } = (0, _burojs_react.useRecordFrame)();
|
|
6063
|
+
const { resource, recordId, record } = (0, _burojs_react.useRecordFrame)();
|
|
6064
|
+
const def = (0, _burojs_react.useApp)().registry.get(resource);
|
|
5970
6065
|
if (recordId !== void 0) return recordId;
|
|
5971
|
-
const id = record
|
|
6066
|
+
const id = (0, _burojs_react.recordKeyOf)(def, record);
|
|
5972
6067
|
return typeof id === "string" || typeof id === "number" ? String(id) : void 0;
|
|
5973
6068
|
}
|
|
5974
6069
|
function RecordTitleView() {
|
|
@@ -5979,7 +6074,7 @@ function RecordTitleView() {
|
|
|
5979
6074
|
const t = (0, _burojs_react.useOptionalT)();
|
|
5980
6075
|
const title = (0, _burojs_react.useRecordTitle)(resource, mode === "create" ? void 0 : id, record);
|
|
5981
6076
|
if (useFrameChrome().hostTitle === true) return null;
|
|
5982
|
-
const text = mode === "create" ? t
|
|
6077
|
+
const text = mode === "create" ? resolveResourceTitle(caps, t, resource, "createTitle", { label: (0, _burojs_core.resolveResourceLabel)(caps, resource, "single", app.registry.get(resource)) }) : title;
|
|
5983
6078
|
if (text === "") return null;
|
|
5984
6079
|
return (0, react_jsx_runtime.jsx)("h2", {
|
|
5985
6080
|
className: "min-w-0 break-words text-xl font-semibold tracking-tight",
|
|
@@ -6003,6 +6098,7 @@ function RecordActionsView() {
|
|
|
6003
6098
|
resource,
|
|
6004
6099
|
record: row,
|
|
6005
6100
|
surface: mode,
|
|
6101
|
+
sources: controller.sources,
|
|
6006
6102
|
...holder === void 0 ? {} : { hideFlows: (name) => holder.suppressed(name) }
|
|
6007
6103
|
}), mode === "show" ? extraActions : null]
|
|
6008
6104
|
});
|
|
@@ -6032,8 +6128,15 @@ function FormActionsView() {
|
|
|
6032
6128
|
const app = (0, _burojs_react.useApp)();
|
|
6033
6129
|
const navigate = (0, _burojs_react.useRouteNavigate)();
|
|
6034
6130
|
const t = (0, _burojs_react.useOptionalT)();
|
|
6131
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
6132
|
+
const caps = (0, _burojs_react.useI18nCaps)();
|
|
6133
|
+
const labelCaps = (0, _burojs_react.useI18nCaps)(resource);
|
|
6035
6134
|
const tid = (0, _burojs_react.useTestIds)();
|
|
6036
6135
|
const id = useFrameId();
|
|
6136
|
+
const failedIssues = chrome.serverIssues;
|
|
6137
|
+
const livePlan = controller.plan;
|
|
6138
|
+
const alertIssues = (0, react.useMemo)(() => failedIssues === void 0 || failedIssues.length === 0 ? NO_ALERT_ISSUES : (0, _burojs_core.routeServerIssues)({ issues: failedIssues }, (segment) => segment, (field) => field !== "_form" && (livePlan === null || livePlan.fields[field] === "active")).form, [failedIssues, livePlan]);
|
|
6139
|
+
const fieldDefs = app.registry.get(resource)?.fields;
|
|
6037
6140
|
if (mode === "show") return null;
|
|
6038
6141
|
const busy = controller.isSubmitting;
|
|
6039
6142
|
const cancel = () => {
|
|
@@ -6057,21 +6160,43 @@ function FormActionsView() {
|
|
|
6057
6160
|
const text = (issue) => (0, _burojs_react.resolveValidationMessage)({
|
|
6058
6161
|
code: issue.code ?? "",
|
|
6059
6162
|
message: issue.message,
|
|
6060
|
-
...issue.
|
|
6061
|
-
}, {
|
|
6163
|
+
...issue.check === void 0 ? {} : { check: issue.check }
|
|
6164
|
+
}, {
|
|
6165
|
+
has: caps.has,
|
|
6166
|
+
t: caps.t
|
|
6167
|
+
});
|
|
6062
6168
|
const retryable = [];
|
|
6063
6169
|
for (const issue of controller.checkOutcome?.blockers ?? []) {
|
|
6064
|
-
const checkId = issue.
|
|
6065
|
-
if (issue.
|
|
6170
|
+
const checkId = issue.check?.id;
|
|
6171
|
+
if (issue.check?.cause === void 0 || typeof checkId !== "string") continue;
|
|
6066
6172
|
if (!retryable.includes(checkId)) retryable.push(checkId);
|
|
6067
6173
|
}
|
|
6068
|
-
const failure = chrome.submitError === void 0 ? void 0 : failureText(chrome.submitError, t);
|
|
6174
|
+
const failure = chrome.submitError === void 0 ? void 0 : failureText(chrome.submitError, chrome.submitApplied, t, caps);
|
|
6175
|
+
const serverIssues = bySeverity(alertIssues).map((issue) => {
|
|
6176
|
+
const head = issue.path[0];
|
|
6177
|
+
const name = typeof head === "string" ? head : void 0;
|
|
6178
|
+
const declared = name === void 0 ? void 0 : fieldDefs?.[name];
|
|
6179
|
+
const message = (0, _burojs_react.resolveValidationMessage)({
|
|
6180
|
+
code: issue.code,
|
|
6181
|
+
message: issue.message,
|
|
6182
|
+
...issue.check === void 0 ? {} : { check: issue.check }
|
|
6183
|
+
}, {
|
|
6184
|
+
has: caps.has,
|
|
6185
|
+
t: caps.t,
|
|
6186
|
+
...declared === void 0 ? {} : { fieldKey: `resources.${resource}.fields.${name}` }
|
|
6187
|
+
});
|
|
6188
|
+
return {
|
|
6189
|
+
label: declared === void 0 || name === void 0 ? void 0 : (0, _burojs_core.resolveFieldLabel)(labelCaps, name, (0, _burojs_core.declaredText)("field", declared, "label")),
|
|
6190
|
+
message,
|
|
6191
|
+
severity: issue.severity
|
|
6192
|
+
};
|
|
6193
|
+
});
|
|
6069
6194
|
const steps = controller.steps;
|
|
6070
6195
|
const midSteps = steps !== null && steps.ids.length > 1 && steps.current !== void 0 && steps.current !== steps.ids[steps.ids.length - 1];
|
|
6071
6196
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
6072
6197
|
className: "flex flex-col gap-3",
|
|
6073
6198
|
children: [
|
|
6074
|
-
failure === void 0 && formErrors.length === 0 ? null : (0, react_jsx_runtime.jsxs)("div", {
|
|
6199
|
+
failure === void 0 && formErrors.length === 0 && serverIssues.length === 0 ? null : (0, react_jsx_runtime.jsxs)("div", {
|
|
6075
6200
|
role: "alert",
|
|
6076
6201
|
className: "flex items-start gap-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive",
|
|
6077
6202
|
children: [
|
|
@@ -6081,10 +6206,22 @@ function FormActionsView() {
|
|
|
6081
6206
|
}),
|
|
6082
6207
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
6083
6208
|
className: "leading-snug",
|
|
6084
|
-
children: [
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6209
|
+
children: [
|
|
6210
|
+
failure === void 0 ? null : (0, react_jsx_runtime.jsx)("p", {
|
|
6211
|
+
className: "font-medium",
|
|
6212
|
+
children: failure
|
|
6213
|
+
}),
|
|
6214
|
+
serverIssues.map((issue, index) => (0, react_jsx_runtime.jsxs)("p", {
|
|
6215
|
+
"data-testid": `form-server-issue:${resource}:${mode}:${index}`,
|
|
6216
|
+
"data-buro-severity": issue.severity,
|
|
6217
|
+
className: issue.severity === "error" ? void 0 : "text-warning-emphasis",
|
|
6218
|
+
children: [issue.label === void 0 ? null : (0, react_jsx_runtime.jsxs)("span", {
|
|
6219
|
+
className: "font-medium",
|
|
6220
|
+
children: [issue.label, ": "]
|
|
6221
|
+
}), issue.message]
|
|
6222
|
+
}, index)),
|
|
6223
|
+
formErrors.map((issue) => (0, react_jsx_runtime.jsx)("p", { children: text(issue) }, issueKey(issue)))
|
|
6224
|
+
]
|
|
6088
6225
|
}),
|
|
6089
6226
|
failure !== void 0 && steps !== null ? (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
6090
6227
|
type: "button",
|
|
@@ -6093,7 +6230,7 @@ function FormActionsView() {
|
|
|
6093
6230
|
className: "ml-auto",
|
|
6094
6231
|
onMouseDown: (event) => event.preventDefault(),
|
|
6095
6232
|
onClick: () => void chrome.submit(),
|
|
6096
|
-
children:
|
|
6233
|
+
children: chromeT("actions.retry", { defaultValue: "Retry" })
|
|
6097
6234
|
}) : null
|
|
6098
6235
|
]
|
|
6099
6236
|
}),
|
|
@@ -6105,7 +6242,7 @@ function FormActionsView() {
|
|
|
6105
6242
|
size: "sm",
|
|
6106
6243
|
"data-testid": `form-check-retry:${checkId}`,
|
|
6107
6244
|
onClick: () => void controller.revalidate(),
|
|
6108
|
-
children:
|
|
6245
|
+
children: chromeT("actions.retry", { defaultValue: "Retry" })
|
|
6109
6246
|
}, checkId))
|
|
6110
6247
|
}),
|
|
6111
6248
|
formWarnings.length === 0 ? null : (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -6131,7 +6268,7 @@ function FormActionsView() {
|
|
|
6131
6268
|
children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconLoader2, {
|
|
6132
6269
|
className: "h-3.5 w-3.5 animate-spin",
|
|
6133
6270
|
"aria-hidden": "true"
|
|
6134
|
-
}), (0, react_jsx_runtime.jsx)("span", { children:
|
|
6271
|
+
}), (0, react_jsx_runtime.jsx)("span", { children: chromeT("actions.validating", { defaultValue: "Validating…" }) })]
|
|
6135
6272
|
}) : null,
|
|
6136
6273
|
(0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
6137
6274
|
type: "button",
|
|
@@ -6139,7 +6276,7 @@ function FormActionsView() {
|
|
|
6139
6276
|
onClick: cancel,
|
|
6140
6277
|
onMouseDown: (event) => event.preventDefault(),
|
|
6141
6278
|
"data-testid": tid.formCancel(resource, mode),
|
|
6142
|
-
children:
|
|
6279
|
+
children: chromeT("actions.cancel", { defaultValue: "Cancel" })
|
|
6143
6280
|
}),
|
|
6144
6281
|
midSteps ? null : (0, react_jsx_runtime.jsxs)(require_button.Button, {
|
|
6145
6282
|
type: "submit",
|
|
@@ -6156,37 +6293,71 @@ function FormActionsView() {
|
|
|
6156
6293
|
children: [busy ? (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconLoader2, {
|
|
6157
6294
|
className: "mr-2 h-4 w-4 animate-spin",
|
|
6158
6295
|
"aria-hidden": "true"
|
|
6159
|
-
}) : null, busy ? mode === "edit" ?
|
|
6296
|
+
}) : null, busy ? mode === "edit" ? chromeT("actions.saving", { defaultValue: "Saving…" }) : chromeT("actions.creating", { defaultValue: "Creating…" }) : chrome.submitLabel ?? (mode === "edit" ? chromeT("actions.save", { defaultValue: "Save" }) : chromeT("actions.create", { defaultValue: "Create" }))]
|
|
6160
6297
|
})
|
|
6161
6298
|
]
|
|
6162
6299
|
})
|
|
6163
6300
|
]
|
|
6164
6301
|
});
|
|
6165
6302
|
}
|
|
6303
|
+
const NO_ALERT_ISSUES = Object.freeze([]);
|
|
6304
|
+
const SEVERITY_RANK = {
|
|
6305
|
+
error: 0,
|
|
6306
|
+
warning: 1,
|
|
6307
|
+
info: 2
|
|
6308
|
+
};
|
|
6309
|
+
function bySeverity(issues) {
|
|
6310
|
+
return [...issues].sort((a, b) => (SEVERITY_RANK[a.severity] ?? 3) - (SEVERITY_RANK[b.severity] ?? 3));
|
|
6311
|
+
}
|
|
6166
6312
|
function firstPreferred(issues) {
|
|
6167
|
-
const first = issues.find((issue) => issue.
|
|
6313
|
+
const first = issues.find((issue) => issue.check?.id === void 0) ?? issues[0];
|
|
6168
6314
|
return first === void 0 ? [] : [first];
|
|
6169
6315
|
}
|
|
6170
6316
|
function issueKey(issue) {
|
|
6171
6317
|
return JSON.stringify([
|
|
6172
6318
|
issue.code ?? "",
|
|
6173
6319
|
issue.message.key,
|
|
6174
|
-
issue.
|
|
6320
|
+
issue.check?.id ?? null
|
|
6175
6321
|
]);
|
|
6176
6322
|
}
|
|
6177
|
-
function failureText(error, t) {
|
|
6178
|
-
const
|
|
6179
|
-
|
|
6323
|
+
function failureText(error, settled, t, caps) {
|
|
6324
|
+
const texts = require_toaster.technicalTexts(error).filter((text) => text.length <= 1024);
|
|
6325
|
+
const strings = require_toaster.friendlyStringsFrom(t);
|
|
6326
|
+
const friendly = texts.map((text) => require_toaster.toFriendlyError(text, void 0, strings)).find((f) => f.replaced) ?? require_toaster.toFriendlyError(texts[0], void 0, strings);
|
|
6327
|
+
const applied = settled ?? ownDataProperty(error, "applied");
|
|
6328
|
+
if (applied === "partial" || applied === "unknown") {
|
|
6329
|
+
const key = applied === "partial" ? "errors.partlyApplied" : "errors.mayHaveBeenApplied";
|
|
6330
|
+
const sentence = caps.has(key) ? caps.t(key) : applied === "partial" ? "Part of this may have been saved. Check the record before trying again." : "It may have been saved. Check the record before trying again.";
|
|
6331
|
+
const lead = texts.some(require_toaster.isNetworkFailure) ? strings.offline : "";
|
|
6332
|
+
return lead === "" ? sentence : `${lead} ${sentence}`;
|
|
6333
|
+
}
|
|
6334
|
+
const code = ownDataProperty(error, "code");
|
|
6335
|
+
const kind = ownDataProperty(error, "kind");
|
|
6336
|
+
const hasOwnSentence = typeof code === "string" && typeof kind === "string" && kind !== "transport" && Object.hasOwn(_burojs_react.RECORD_KIND_KEYS, kind);
|
|
6337
|
+
const message = ownDataProperty(error, "message");
|
|
6338
|
+
if (friendly.replaced && !hasOwnSentence) return (typeof code === "string" ? (0, _burojs_react.specificErrorText)({
|
|
6339
|
+
code,
|
|
6340
|
+
...isMessageReference(message) ? { message } : {}
|
|
6341
|
+
}, caps, { record: true }) : void 0) ?? friendly.title;
|
|
6342
|
+
if (typeof code !== "string") return strings.title;
|
|
6343
|
+
const reference = {
|
|
6344
|
+
code,
|
|
6345
|
+
...isMessageReference(message) ? { message } : {}
|
|
6346
|
+
};
|
|
6347
|
+
return (0, _burojs_react.specificErrorText)(reference, caps, { record: true }) ?? (typeof kind === "string" ? (0, _burojs_react.kindErrorText)(kind, caps, { record: true }) : void 0) ?? strings.title;
|
|
6180
6348
|
}
|
|
6181
|
-
function
|
|
6349
|
+
function ownDataProperty(error, name) {
|
|
6182
6350
|
if (error === null || typeof error !== "object") return void 0;
|
|
6183
6351
|
try {
|
|
6184
|
-
const descriptor = Object.getOwnPropertyDescriptor(error,
|
|
6185
|
-
return descriptor !== void 0 && "value" in descriptor
|
|
6352
|
+
const descriptor = Object.getOwnPropertyDescriptor(error, name);
|
|
6353
|
+
return descriptor !== void 0 && "value" in descriptor ? descriptor.value : void 0;
|
|
6186
6354
|
} catch {
|
|
6187
6355
|
return;
|
|
6188
6356
|
}
|
|
6189
6357
|
}
|
|
6358
|
+
function isMessageReference(value) {
|
|
6359
|
+
return value !== null && typeof value === "object" && typeof value.key === "string";
|
|
6360
|
+
}
|
|
6190
6361
|
function inlineFlowNames(screen, plan) {
|
|
6191
6362
|
if (screen === null) return [];
|
|
6192
6363
|
const names = [];
|
|
@@ -6459,31 +6630,35 @@ function PlannedFrame(props) {
|
|
|
6459
6630
|
})
|
|
6460
6631
|
}, name);
|
|
6461
6632
|
const { PlacementScope } = page;
|
|
6633
|
+
const claimedRoute = (0, react.useContext)(_burojs_react.RouteSourceContext);
|
|
6462
6634
|
const itemNode = page.plan.slots.item?.[0];
|
|
6463
6635
|
const item = (0, react.useMemo)(() => itemNode === void 0 ? void 0 : itemHandle(itemNode), [itemNode]);
|
|
6464
6636
|
return (0, react_jsx_runtime.jsx)(_burojs_react.RouteSourceContext.Provider, {
|
|
6465
6637
|
value: null,
|
|
6466
|
-
children: (0, react_jsx_runtime.jsx)(
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
children: (0, react_jsx_runtime.jsx)(
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6638
|
+
children: (0, react_jsx_runtime.jsx)(_burojs_react.ActionRouteContext.Provider, {
|
|
6639
|
+
value: claimedRoute,
|
|
6640
|
+
children: (0, react_jsx_runtime.jsx)(PlacementScope, { children: (0, react_jsx_runtime.jsx)(ScreenTreeScope, {
|
|
6641
|
+
resource,
|
|
6642
|
+
mode: "show",
|
|
6643
|
+
compiled,
|
|
6644
|
+
page,
|
|
6645
|
+
children: (0, react_jsx_runtime.jsx)(ListItemContext.Provider, {
|
|
6646
|
+
value: item,
|
|
6647
|
+
children: (0, react_jsx_runtime.jsx)(FrameView, {
|
|
6648
|
+
resource,
|
|
6649
|
+
compiled,
|
|
6650
|
+
slots
|
|
6651
|
+
})
|
|
6477
6652
|
})
|
|
6478
|
-
})
|
|
6479
|
-
})
|
|
6653
|
+
}) })
|
|
6654
|
+
})
|
|
6480
6655
|
});
|
|
6481
6656
|
}
|
|
6482
6657
|
function ListFrameHost({ resource }) {
|
|
6483
6658
|
const compiled = useCompiledListScreen(resource);
|
|
6484
6659
|
const hasDataRuntime = (0, _burojs_react.useOptionalDataRuntime)() !== null;
|
|
6485
6660
|
const { def } = (0, _burojs_react.useResourceListContext)();
|
|
6486
|
-
const rowsView =
|
|
6661
|
+
const rowsView = def?.views?.list?.initial?.view ?? "table";
|
|
6487
6662
|
if (compiled === null) return (0, react_jsx_runtime.jsx)(Arrangement, {});
|
|
6488
6663
|
if (compiled.nodes.length === 0 && rowsView === "table") {
|
|
6489
6664
|
const empty = {};
|
|
@@ -6502,8 +6677,12 @@ function ListFrameHost({ resource }) {
|
|
|
6502
6677
|
}
|
|
6503
6678
|
//#endregion
|
|
6504
6679
|
//#region src/list-kit/resource-list-surface.tsx
|
|
6505
|
-
|
|
6506
|
-
|
|
6680
|
+
function declaresDisplay(field) {
|
|
6681
|
+
return field !== void 0 && (0, _burojs_core.resolveSurfaceUi)(field, "column").use !== void 0;
|
|
6682
|
+
}
|
|
6683
|
+
const NO_INITIAL_FILTERS = Object.freeze({});
|
|
6684
|
+
const RelatedCards = (0, react.lazy)(async () => ({ default: (await Promise.resolve().then(() => require("./related-list-cards-CelMxl4q.cjs"))).RelatedCards }));
|
|
6685
|
+
const RelatedTimeline = (0, react.lazy)(async () => ({ default: (await Promise.resolve().then(() => require("./related-list-timeline-DsLdi8sv.cjs"))).RelatedTimeline }));
|
|
6507
6686
|
function discriminatorOptionLabel(field, value) {
|
|
6508
6687
|
const text = (0, _burojs_core.fieldOptionText)(field, value);
|
|
6509
6688
|
if (text !== void 0) return text;
|
|
@@ -6511,10 +6690,17 @@ function discriminatorOptionLabel(field, value) {
|
|
|
6511
6690
|
const label = (Array.isArray(declared?.options) ? declared.options : Array.isArray(declared?.meta?.options) ? declared.meta.options : []).find((option) => option?.value === value)?.label;
|
|
6512
6691
|
return typeof label === "string" ? label : value;
|
|
6513
6692
|
}
|
|
6514
|
-
function
|
|
6693
|
+
function declaredInitialSort(def) {
|
|
6694
|
+
return def?.views?.list?.initial?.sort;
|
|
6695
|
+
}
|
|
6696
|
+
function declaredRouteView(def) {
|
|
6697
|
+
return def?.views?.list?.initial?.view;
|
|
6698
|
+
}
|
|
6699
|
+
function ResourceListSurface({ resource, variant, state, fixedFilters, initial, search: searchField, columns: columnEntries, open, title, empty, scope, view, item, placementKey, onCreate, count: countPolicy, rowTarget, readOnly, linkEditing, exportable, layoutId, meta, renderCell, emptyState }) {
|
|
6515
6700
|
const route = variant === "route";
|
|
6516
6701
|
const t = (0, _burojs_react.useT)();
|
|
6517
6702
|
const optionalT = (0, _burojs_react.useOptionalT)();
|
|
6703
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
6518
6704
|
const tid = (0, _burojs_react.useTestIds)();
|
|
6519
6705
|
const listCaps = (0, _burojs_react.useI18nCaps)(resource);
|
|
6520
6706
|
const RouteFiltersSlot = require_check_confirm_dialog.useListSlot("filters", resource);
|
|
@@ -6529,17 +6715,45 @@ function ResourceListSurface({ resource, variant, state, fixedFilters, pageSize,
|
|
|
6529
6715
|
console.error(`[burojs] list.body-removed: list.body.${require_check_confirm_dialog.canonicalResourceName(resource)} is no longer rendered; a whole-body override is a list frame (views.list.frame).`);
|
|
6530
6716
|
}, [removedBody, resource]);
|
|
6531
6717
|
const searchDecl = (0, react.useMemo)(() => searchField === void 0 ? void 0 : { fields: [searchField] }, [searchField]);
|
|
6532
|
-
const
|
|
6718
|
+
const appRegistry = (0, _burojs_react.useApp)().registry;
|
|
6719
|
+
const effectiveView = route ? declaredRouteView(appRegistry.get(resource)) ?? "table" : view ?? "table";
|
|
6720
|
+
const timeline = effectiveView === "timeline";
|
|
6721
|
+
const initialKey = JSON.stringify(initial ?? null);
|
|
6722
|
+
const placementInitial = (0, react.useMemo)(() => route ? void 0 : {
|
|
6723
|
+
...initial,
|
|
6724
|
+
filters: initial?.filters ?? NO_INITIAL_FILTERS
|
|
6725
|
+
}, [route, initialKey]);
|
|
6726
|
+
const timelineAxis = (placementInitial?.sort ?? declaredInitialSort(appRegistry.get(resource)))?.[0]?.field;
|
|
6727
|
+
const columnNames = (0, react.useMemo)(() => columnEntries?.map(_burojs_core.columnName), [columnEntries]);
|
|
6728
|
+
const list = (0, _burojs_react.useResourceList)(resource, route ? {
|
|
6729
|
+
meta,
|
|
6730
|
+
...timeline ? { timeline } : {}
|
|
6731
|
+
} : {
|
|
6732
|
+
...timeline ? { timeline } : {},
|
|
6533
6733
|
...state === void 0 ? {} : { state },
|
|
6534
6734
|
...fixedFilters === void 0 ? {} : { fixedFilters },
|
|
6535
|
-
...
|
|
6735
|
+
...placementInitial === void 0 ? {} : { initial: placementInitial },
|
|
6536
6736
|
...searchDecl === void 0 ? {} : { search: searchDecl },
|
|
6537
|
-
...
|
|
6737
|
+
...columnEntries === void 0 ? {} : { columns: columnEntries },
|
|
6538
6738
|
...scope === void 0 ? {} : { scope },
|
|
6539
6739
|
...countPolicy === void 0 ? {} : { countPolicy }
|
|
6540
6740
|
});
|
|
6541
6741
|
const { def, query, pagination, cursor, count, filters, sorting, columns, selection, savedViews, routing, live, droppedPredicates } = list;
|
|
6542
6742
|
(0, _burojs_react.policyRowsOf)(list, list.rows);
|
|
6743
|
+
const selectionRef = (0, react.useRef)(selection);
|
|
6744
|
+
selectionRef.current = selection;
|
|
6745
|
+
const onDetach = linkEditing?.detach?.onDetach;
|
|
6746
|
+
const surfaceLinkEditing = (0, react.useMemo)(() => onDetach === void 0 ? void 0 : { detach: { onDetach: async (detached) => {
|
|
6747
|
+
const left = await onDetach(detached);
|
|
6748
|
+
if (left.length > 0) {
|
|
6749
|
+
const gone = new Set(left);
|
|
6750
|
+
const current = selectionRef.current;
|
|
6751
|
+
if (current.ids.some((id) => gone.has(id))) current.set(current.ids.filter((id) => !gone.has(id)));
|
|
6752
|
+
}
|
|
6753
|
+
return left;
|
|
6754
|
+
} } }, [onDetach]);
|
|
6755
|
+
const onAttach = linkEditing?.attach?.onAttach;
|
|
6756
|
+
const attachBusy = linkEditing?.attach?.busy === true;
|
|
6543
6757
|
const hasDataRuntime = (0, _burojs_react.useOptionalDataRuntime)() !== null;
|
|
6544
6758
|
const scopeLabel = (scope) => scope.id === _burojs_react.LOCAL_USER_SCOPE_ID ? t("toolbar.viewsMyScope") : scope.label;
|
|
6545
6759
|
const createAvailable = (0, _burojs_react.useAvailability)(resource, "create").state === "available";
|
|
@@ -6587,7 +6801,6 @@ function ResourceListSurface({ resource, variant, state, fixedFilters, pageSize,
|
|
|
6587
6801
|
resource,
|
|
6588
6802
|
routing.rowHref
|
|
6589
6803
|
]);
|
|
6590
|
-
const effectiveView = route ? (def?.views?.list)?.view ?? "table" : view ?? "table";
|
|
6591
6804
|
const tableView = effectiveView === "table";
|
|
6592
6805
|
const rowsViewFor = (0, react.useMemo)(() => tableView ? void 0 : (planned) => ({
|
|
6593
6806
|
skeleton: effectiveView === "cards" ? (0, react_jsx_runtime.jsx)(RelatedCardsSkeleton, {}) : (0, react_jsx_runtime.jsx)(RelatedTimelineSkeleton, {}),
|
|
@@ -6599,11 +6812,15 @@ function ResourceListSurface({ resource, variant, state, fixedFilters, pageSize,
|
|
|
6599
6812
|
item: route ? planned : item,
|
|
6600
6813
|
columns: route ? columns.visible : columnNames,
|
|
6601
6814
|
rowQuick,
|
|
6602
|
-
rowHref
|
|
6815
|
+
rowHref,
|
|
6816
|
+
...empty === void 0 ? {} : { empty }
|
|
6603
6817
|
};
|
|
6604
6818
|
return (0, react_jsx_runtime.jsx)(react.Suspense, {
|
|
6605
6819
|
fallback: effectiveView === "cards" ? (0, react_jsx_runtime.jsx)(RelatedCardsSkeleton, {}) : (0, react_jsx_runtime.jsx)(RelatedTimelineSkeleton, {}),
|
|
6606
|
-
children: effectiveView === "cards" ? (0, react_jsx_runtime.jsx)(RelatedCards, { ...common }) : (0, react_jsx_runtime.jsx)(RelatedTimeline, {
|
|
6820
|
+
children: effectiveView === "cards" ? (0, react_jsx_runtime.jsx)(RelatedCards, { ...common }) : (0, react_jsx_runtime.jsx)(RelatedTimeline, {
|
|
6821
|
+
...common,
|
|
6822
|
+
axis: timelineAxis
|
|
6823
|
+
})
|
|
6607
6824
|
});
|
|
6608
6825
|
}
|
|
6609
6826
|
}), [
|
|
@@ -6616,7 +6833,9 @@ function ResourceListSurface({ resource, variant, state, fixedFilters, pageSize,
|
|
|
6616
6833
|
columns.visible,
|
|
6617
6834
|
columnNames,
|
|
6618
6835
|
rowQuick,
|
|
6619
|
-
rowHref
|
|
6836
|
+
rowHref,
|
|
6837
|
+
empty,
|
|
6838
|
+
timelineAxis
|
|
6620
6839
|
]);
|
|
6621
6840
|
const pageTitle = (0, _burojs_core.resolveResourceLabel)(listCaps, resource, "plural", def);
|
|
6622
6841
|
const [saveOpen, setSaveOpen] = (0, react.useState)(false);
|
|
@@ -6698,6 +6917,10 @@ function ResourceListSurface({ resource, variant, state, fixedFilters, pageSize,
|
|
|
6698
6917
|
sonner.toast.error(t("toolbar.viewsForkFailed"));
|
|
6699
6918
|
}
|
|
6700
6919
|
};
|
|
6920
|
+
const columnNamesDisplay = (col, field) => {
|
|
6921
|
+
const resolved = list.columns.ui[col];
|
|
6922
|
+
return resolved === void 0 ? declaresDisplay(field) : resolved.display.use !== void 0;
|
|
6923
|
+
};
|
|
6701
6924
|
const renderCellLadder = (col, value, row) => {
|
|
6702
6925
|
if (def?.types && col === def.types.by) {
|
|
6703
6926
|
const raw = typeof value === "string" ? value : "";
|
|
@@ -6716,13 +6939,14 @@ function ResourceListSurface({ resource, variant, state, fixedFilters, pageSize,
|
|
|
6716
6939
|
children: label
|
|
6717
6940
|
});
|
|
6718
6941
|
}
|
|
6942
|
+
const custom = (renderCell ?? CellSlot)?.(col, value, row);
|
|
6943
|
+
if (custom !== void 0) return custom;
|
|
6719
6944
|
const fieldDef = def?.fields[col];
|
|
6720
|
-
const enumName = fieldDef?.opts?.enum ?? fieldDef?.ui?.enum;
|
|
6721
|
-
if (enumName && typeof value === "string") return (0, react_jsx_runtime.jsx)(EnumBadge, {
|
|
6945
|
+
const enumName = (0, _burojs_core_internal.enumBindingKey)(fieldDef?.opts?.enum ?? fieldDef?.ui?.enum);
|
|
6946
|
+
if (enumName && typeof value === "string" && !columnNamesDisplay(col, fieldDef)) return (0, react_jsx_runtime.jsx)(EnumBadge, {
|
|
6722
6947
|
enumName,
|
|
6723
6948
|
value
|
|
6724
6949
|
});
|
|
6725
|
-
return (renderCell ?? CellSlot)?.(col, value, row);
|
|
6726
6950
|
};
|
|
6727
6951
|
const surface = {
|
|
6728
6952
|
resource,
|
|
@@ -6750,10 +6974,16 @@ function ResourceListSurface({ resource, variant, state, fixedFilters, pageSize,
|
|
|
6750
6974
|
}
|
|
6751
6975
|
},
|
|
6752
6976
|
rowsViewFor,
|
|
6753
|
-
emptyState,
|
|
6977
|
+
emptyState: empty !== void 0 && !list.filters.isFiltered && list.pagination.page <= 1 && (list.cursor === null || list.cursor.next === null) ? (0, react_jsx_runtime.jsx)("p", {
|
|
6978
|
+
"data-buro-region": "empty",
|
|
6979
|
+
className: "text-sm text-muted-foreground",
|
|
6980
|
+
children: empty
|
|
6981
|
+
}) : emptyState,
|
|
6754
6982
|
renderCell: renderCellLadder,
|
|
6755
6983
|
readOnly: readOnly === true,
|
|
6756
|
-
exportable: exportable !== false
|
|
6984
|
+
exportable: exportable !== false,
|
|
6985
|
+
...layoutId === void 0 ? {} : { layoutId },
|
|
6986
|
+
...surfaceLinkEditing === void 0 ? {} : { linkEditing: surfaceLinkEditing }
|
|
6757
6987
|
};
|
|
6758
6988
|
return (0, react_jsx_runtime.jsx)(_burojs_react.ResourceListProvider, {
|
|
6759
6989
|
value: list,
|
|
@@ -6766,22 +6996,44 @@ function ResourceListSurface({ resource, variant, state, fixedFilters, pageSize,
|
|
|
6766
6996
|
resource,
|
|
6767
6997
|
mode: "list",
|
|
6768
6998
|
title: pageTitle
|
|
6769
|
-
}) : title === void 0 && onCreate === void 0 ? null : (0, react_jsx_runtime.jsxs)("div", {
|
|
6999
|
+
}) : title === void 0 && onCreate === void 0 && onAttach === void 0 ? null : (0, react_jsx_runtime.jsxs)("div", {
|
|
6770
7000
|
className: "flex items-center justify-between gap-2",
|
|
6771
|
-
children: [
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
7001
|
+
children: [
|
|
7002
|
+
title === void 0 ? (0, react_jsx_runtime.jsx)("span", {}) : (0, react_jsx_runtime.jsx)("h3", {
|
|
7003
|
+
className: "text-sm font-semibold",
|
|
7004
|
+
children: title
|
|
7005
|
+
}),
|
|
7006
|
+
onAttach === void 0 ? null : (0, react_jsx_runtime.jsxs)(require_button.Button, {
|
|
7007
|
+
type: "button",
|
|
7008
|
+
size: "sm",
|
|
7009
|
+
variant: "outline",
|
|
7010
|
+
"data-testid": `list-link-attach:${resource}`,
|
|
7011
|
+
onClick: onAttach,
|
|
7012
|
+
disabled: attachBusy,
|
|
7013
|
+
"aria-busy": attachBusy,
|
|
7014
|
+
children: [attachBusy ? (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconLoader2, {
|
|
7015
|
+
className: "mr-1 h-4 w-4 animate-spin",
|
|
7016
|
+
"aria-hidden": "true"
|
|
7017
|
+
}) : (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconLink, {
|
|
7018
|
+
className: "mr-1 h-4 w-4",
|
|
7019
|
+
"aria-hidden": "true"
|
|
7020
|
+
}), optionalT("field.link.attach", { defaultValue: "Attach" })]
|
|
7021
|
+
}),
|
|
7022
|
+
onCreate === void 0 ? null : (0, react_jsx_runtime.jsxs)(require_button.Button, {
|
|
7023
|
+
type: "button",
|
|
7024
|
+
size: "sm",
|
|
7025
|
+
variant: "outline",
|
|
7026
|
+
"data-testid": `list-create:${resource}`,
|
|
7027
|
+
onClick: onCreate,
|
|
7028
|
+
children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconPlus, {
|
|
7029
|
+
className: "mr-1 h-4 w-4",
|
|
7030
|
+
"aria-hidden": "true"
|
|
7031
|
+
}), optionalT("actions.create", {
|
|
7032
|
+
resource,
|
|
7033
|
+
defaultValue: "Create"
|
|
7034
|
+
})]
|
|
7035
|
+
})
|
|
7036
|
+
]
|
|
6785
7037
|
}),
|
|
6786
7038
|
hasDataRuntime && (0, react_jsx_runtime.jsx)(ExportRunWatcherMount, {}),
|
|
6787
7039
|
droppedPredicates > 0 && (0, react_jsx_runtime.jsx)("p", {
|
|
@@ -6830,13 +7082,13 @@ function ResourceListSurface({ resource, variant, state, fixedFilters, pageSize,
|
|
|
6830
7082
|
variant: "outline",
|
|
6831
7083
|
onClick: () => setSaveOpen(false),
|
|
6832
7084
|
"data-testid": `list-saved-view-save-cancel:${resource}`,
|
|
6833
|
-
children:
|
|
7085
|
+
children: chromeT("actions.cancel")
|
|
6834
7086
|
}), (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
6835
7087
|
type: "button",
|
|
6836
7088
|
onClick: handleSaveConfirm,
|
|
6837
7089
|
disabled: saveLabel.trim().length === 0,
|
|
6838
7090
|
"data-testid": `list-saved-view-save-confirm:${resource}`,
|
|
6839
|
-
children:
|
|
7091
|
+
children: chromeT("actions.save")
|
|
6840
7092
|
})] })
|
|
6841
7093
|
]
|
|
6842
7094
|
})
|
|
@@ -6873,7 +7125,7 @@ function ResourceListSurface({ resource, variant, state, fixedFilters, pageSize,
|
|
|
6873
7125
|
variant: "outline",
|
|
6874
7126
|
onClick: () => handleDeleteUserView(entry.id),
|
|
6875
7127
|
"data-testid": `list-saved-view-manage-delete:${resource}:${entry.id}`,
|
|
6876
|
-
children:
|
|
7128
|
+
children: chromeT("actions.delete")
|
|
6877
7129
|
}) : (0, react_jsx_runtime.jsx)("span", {
|
|
6878
7130
|
className: "shrink-0 text-xs text-muted-foreground",
|
|
6879
7131
|
children: t("toolbar.viewsReadOnly")
|
|
@@ -6885,7 +7137,7 @@ function ResourceListSurface({ resource, variant, state, fixedFilters, pageSize,
|
|
|
6885
7137
|
variant: "outline",
|
|
6886
7138
|
onClick: () => setManageOpen(false),
|
|
6887
7139
|
"data-testid": `list-saved-view-manage-close:${resource}`,
|
|
6888
|
-
children:
|
|
7140
|
+
children: chromeT("actions.close")
|
|
6889
7141
|
}) })
|
|
6890
7142
|
]
|
|
6891
7143
|
})
|
|
@@ -6918,13 +7170,13 @@ function ResourceListSurface({ resource, variant, state, fixedFilters, pageSize,
|
|
|
6918
7170
|
setRenameTarget(null);
|
|
6919
7171
|
},
|
|
6920
7172
|
"data-testid": `list-saved-view-rename-cancel:${resource}`,
|
|
6921
|
-
children:
|
|
7173
|
+
children: chromeT("actions.cancel")
|
|
6922
7174
|
}), (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
6923
7175
|
type: "button",
|
|
6924
7176
|
onClick: handleRenameConfirm,
|
|
6925
7177
|
disabled: renameLabel.trim().length === 0,
|
|
6926
7178
|
"data-testid": `list-saved-view-rename-confirm:${resource}`,
|
|
6927
|
-
children:
|
|
7179
|
+
children: chromeT("actions.save")
|
|
6928
7180
|
})] })
|
|
6929
7181
|
]
|
|
6930
7182
|
})
|
|
@@ -6959,7 +7211,7 @@ function ResourceListSurface({ resource, variant, state, fixedFilters, pageSize,
|
|
|
6959
7211
|
setForkTarget(null);
|
|
6960
7212
|
},
|
|
6961
7213
|
"data-testid": `list-saved-view-fork-cancel:${resource}`,
|
|
6962
|
-
children:
|
|
7214
|
+
children: chromeT("actions.cancel")
|
|
6963
7215
|
}), (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
6964
7216
|
type: "button",
|
|
6965
7217
|
onClick: handleForkConfirm,
|
|
@@ -6982,6 +7234,582 @@ function ExportRunWatcherMount() {
|
|
|
6982
7234
|
return null;
|
|
6983
7235
|
}
|
|
6984
7236
|
//#endregion
|
|
7237
|
+
//#region src/fields/use-relation-picker.tsx
|
|
7238
|
+
const noop = () => void 0;
|
|
7239
|
+
function safeKey(input) {
|
|
7240
|
+
if (input === void 0 || input === null) return void 0;
|
|
7241
|
+
try {
|
|
7242
|
+
return (0, _burojs_core.resourceKey)(input);
|
|
7243
|
+
} catch {
|
|
7244
|
+
return;
|
|
7245
|
+
}
|
|
7246
|
+
}
|
|
7247
|
+
function sessionIdentity(runtime) {
|
|
7248
|
+
const state = runtime.dataSession.getState();
|
|
7249
|
+
const snapshot = state.status === "ready" ? state.snapshot : state.target;
|
|
7250
|
+
const selection = snapshot.scope?.selection;
|
|
7251
|
+
const partition = selection === void 0 ? snapshot.scopeKey : [snapshot.scopeKey, selection];
|
|
7252
|
+
let scopeKey;
|
|
7253
|
+
try {
|
|
7254
|
+
scopeKey = JSON.stringify(partition) ?? "";
|
|
7255
|
+
} catch {
|
|
7256
|
+
scopeKey = String(snapshot.scopeKey);
|
|
7257
|
+
}
|
|
7258
|
+
return {
|
|
7259
|
+
sessionKey: snapshot.sessionKey,
|
|
7260
|
+
scopeKey
|
|
7261
|
+
};
|
|
7262
|
+
}
|
|
7263
|
+
function PickerHost(props) {
|
|
7264
|
+
const { register } = props;
|
|
7265
|
+
react.useEffect(() => register(), [register]);
|
|
7266
|
+
return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: props.children });
|
|
7267
|
+
}
|
|
7268
|
+
function useRelationPicker(options) {
|
|
7269
|
+
const app = (0, _burojs_react.useApp)();
|
|
7270
|
+
const runtime = (0, _burojs_react.useDataRuntime)();
|
|
7271
|
+
const frame = (0, _burojs_react.useOptionalRecordFrame)();
|
|
7272
|
+
const frames = (0, _burojs_react.useRecordScopeFrames)();
|
|
7273
|
+
const multiple = options.multiple === true;
|
|
7274
|
+
const fieldName = options.field;
|
|
7275
|
+
let to;
|
|
7276
|
+
let declaredBy;
|
|
7277
|
+
let declaredCandidates;
|
|
7278
|
+
if (fieldName !== void 0) {
|
|
7279
|
+
const meta = ((frame === null ? void 0 : app.registry.get(frame.resource)?.fields)?.[fieldName])?.meta;
|
|
7280
|
+
to = safeKey(meta?.to);
|
|
7281
|
+
declaredBy = typeof meta?.by === "string" ? meta.by : void 0;
|
|
7282
|
+
declaredCandidates = Array.isArray(meta?.candidates) ? meta.candidates : void 0;
|
|
7283
|
+
} else to = safeKey(options.to);
|
|
7284
|
+
const target = to ?? "";
|
|
7285
|
+
const by = options.valueField ?? declaredBy;
|
|
7286
|
+
const scope = options.scope ?? "context";
|
|
7287
|
+
const selection = require_lazy_relation_picker_dialog.useCandidateSelection({
|
|
7288
|
+
to,
|
|
7289
|
+
candidates: options.candidates ?? declaredCandidates,
|
|
7290
|
+
sources: frame?.controller.sources,
|
|
7291
|
+
resource: frame?.resource ?? "",
|
|
7292
|
+
fieldName: fieldName ?? target,
|
|
7293
|
+
fixedFilters: options.fixedFilters
|
|
7294
|
+
});
|
|
7295
|
+
const held = selection.gate !== void 0;
|
|
7296
|
+
const pendingRef = react.useRef(null);
|
|
7297
|
+
const [active, setActive] = react.useState(null);
|
|
7298
|
+
const activeRef = react.useRef(null);
|
|
7299
|
+
activeRef.current = active;
|
|
7300
|
+
const rowsRef = react.useRef(new Map());
|
|
7301
|
+
const createdRowRef = react.useRef(void 0);
|
|
7302
|
+
const alive = react.useRef(true);
|
|
7303
|
+
const mounts = react.useRef(0);
|
|
7304
|
+
const sequence = react.useRef(0);
|
|
7305
|
+
const latest = react.useRef({
|
|
7306
|
+
multiple,
|
|
7307
|
+
select: options.select,
|
|
7308
|
+
idField: "id",
|
|
7309
|
+
valueField: "id",
|
|
7310
|
+
available: false,
|
|
7311
|
+
frames
|
|
7312
|
+
});
|
|
7313
|
+
const project = react.useCallback((row) => {
|
|
7314
|
+
const select = latest.current.select;
|
|
7315
|
+
if (select === void 0) return { ...row };
|
|
7316
|
+
const out = {};
|
|
7317
|
+
const key = row[latest.current.idField] !== void 0 ? row[latest.current.idField] : row.id;
|
|
7318
|
+
if (key !== void 0) out.id = key;
|
|
7319
|
+
const { valueField } = latest.current;
|
|
7320
|
+
if (Object.hasOwn(row, valueField)) out[valueField] = row[valueField];
|
|
7321
|
+
for (const name of select) if (Object.hasOwn(row, name)) out[name] = row[name];
|
|
7322
|
+
return out;
|
|
7323
|
+
}, []);
|
|
7324
|
+
const settle = react.useCallback((result) => {
|
|
7325
|
+
const pending = pendingRef.current;
|
|
7326
|
+
if (pending === null) return;
|
|
7327
|
+
pendingRef.current = null;
|
|
7328
|
+
pending.detach();
|
|
7329
|
+
if (alive.current) setActive(null);
|
|
7330
|
+
pending.resolve(result);
|
|
7331
|
+
}, []);
|
|
7332
|
+
const toggle = react.useCallback((key, row) => {
|
|
7333
|
+
setActive((current) => {
|
|
7334
|
+
if (current === null) return current;
|
|
7335
|
+
const has = current.selected.some((k) => String(k) === String(key));
|
|
7336
|
+
if (has) rowsRef.current.delete(String(key));
|
|
7337
|
+
else if (row !== void 0) rowsRef.current.set(String(key), row);
|
|
7338
|
+
const selected = has ? current.selected.filter((k) => String(k) !== String(key)) : [...current.selected, key];
|
|
7339
|
+
const next = {
|
|
7340
|
+
...current,
|
|
7341
|
+
selected
|
|
7342
|
+
};
|
|
7343
|
+
activeRef.current = next;
|
|
7344
|
+
return next;
|
|
7345
|
+
});
|
|
7346
|
+
}, []);
|
|
7347
|
+
const onValue = react.useCallback((value) => {
|
|
7348
|
+
const row = createdRowRef.current;
|
|
7349
|
+
createdRowRef.current = void 0;
|
|
7350
|
+
if (latest.current.multiple) {
|
|
7351
|
+
const current = activeRef.current;
|
|
7352
|
+
if (current !== null && !current.selected.some((k) => String(k) === String(value))) toggle(value, row);
|
|
7353
|
+
return;
|
|
7354
|
+
}
|
|
7355
|
+
settle({
|
|
7356
|
+
kind: "selected",
|
|
7357
|
+
keys: [value],
|
|
7358
|
+
rows: row === void 0 ? [] : [project(row)]
|
|
7359
|
+
});
|
|
7360
|
+
}, [
|
|
7361
|
+
project,
|
|
7362
|
+
settle,
|
|
7363
|
+
toggle
|
|
7364
|
+
]);
|
|
7365
|
+
const wiring = require_relation_select.useRelationSelect({
|
|
7366
|
+
to: target,
|
|
7367
|
+
by,
|
|
7368
|
+
fixedFilters: selection.fixedFilters,
|
|
7369
|
+
scope,
|
|
7370
|
+
...fieldName === void 0 ? {} : { scopeField: fieldName },
|
|
7371
|
+
held,
|
|
7372
|
+
onValue
|
|
7373
|
+
});
|
|
7374
|
+
latest.current = {
|
|
7375
|
+
multiple,
|
|
7376
|
+
select: options.select,
|
|
7377
|
+
idField: wiring.idField,
|
|
7378
|
+
valueField: wiring.valueField,
|
|
7379
|
+
available: to !== void 0 && wiring.targetDef !== void 0 && !held,
|
|
7380
|
+
frames
|
|
7381
|
+
};
|
|
7382
|
+
const { create: shared } = wiring;
|
|
7383
|
+
const create = react.useMemo(() => ({
|
|
7384
|
+
...shared,
|
|
7385
|
+
start: (openCreate) => shared.start(() => {
|
|
7386
|
+
const opened = openCreate();
|
|
7387
|
+
opened.then((row) => {
|
|
7388
|
+
createdRowRef.current = row === null ? void 0 : { ...row };
|
|
7389
|
+
}, noop);
|
|
7390
|
+
return opened;
|
|
7391
|
+
})
|
|
7392
|
+
}), [shared]);
|
|
7393
|
+
react.useEffect(() => runtime.dataSession.subscribe(() => {
|
|
7394
|
+
const pending = pendingRef.current;
|
|
7395
|
+
if (pending === null) return;
|
|
7396
|
+
const now = sessionIdentity(runtime);
|
|
7397
|
+
if (now.sessionKey !== pending.sessionKey || now.scopeKey !== pending.scopeKey) settle({
|
|
7398
|
+
kind: "cancelled",
|
|
7399
|
+
reason: "session-changed"
|
|
7400
|
+
});
|
|
7401
|
+
}), [runtime, settle]);
|
|
7402
|
+
react.useEffect(() => {
|
|
7403
|
+
alive.current = true;
|
|
7404
|
+
return () => {
|
|
7405
|
+
alive.current = false;
|
|
7406
|
+
settle({
|
|
7407
|
+
kind: "cancelled",
|
|
7408
|
+
reason: "unmounted"
|
|
7409
|
+
});
|
|
7410
|
+
};
|
|
7411
|
+
}, [settle]);
|
|
7412
|
+
react.useEffect(() => {
|
|
7413
|
+
if (held) settle({
|
|
7414
|
+
kind: "cancelled",
|
|
7415
|
+
reason: "unavailable"
|
|
7416
|
+
});
|
|
7417
|
+
}, [held, settle]);
|
|
7418
|
+
const register = react.useCallback(() => {
|
|
7419
|
+
mounts.current += 1;
|
|
7420
|
+
return () => {
|
|
7421
|
+
mounts.current -= 1;
|
|
7422
|
+
if (mounts.current === 0) settle({
|
|
7423
|
+
kind: "cancelled",
|
|
7424
|
+
reason: "unmounted"
|
|
7425
|
+
});
|
|
7426
|
+
};
|
|
7427
|
+
}, [settle]);
|
|
7428
|
+
const open = react.useCallback((opts = {}) => new Promise((resolve) => {
|
|
7429
|
+
settle({
|
|
7430
|
+
kind: "cancelled",
|
|
7431
|
+
reason: "superseded"
|
|
7432
|
+
});
|
|
7433
|
+
if (mounts.current === 0) {
|
|
7434
|
+
if (process.env.NODE_ENV !== "production") console.error("[burojs] useRelationPicker: open() was called but its element is not rendered — render `handle.element` once in your tree.");
|
|
7435
|
+
resolve({
|
|
7436
|
+
kind: "cancelled",
|
|
7437
|
+
reason: "not-mounted"
|
|
7438
|
+
});
|
|
7439
|
+
return;
|
|
7440
|
+
}
|
|
7441
|
+
const { signal } = opts;
|
|
7442
|
+
if (signal?.aborted === true) {
|
|
7443
|
+
resolve({
|
|
7444
|
+
kind: "cancelled",
|
|
7445
|
+
reason: "aborted"
|
|
7446
|
+
});
|
|
7447
|
+
return;
|
|
7448
|
+
}
|
|
7449
|
+
if (!latest.current.available) {
|
|
7450
|
+
resolve({
|
|
7451
|
+
kind: "cancelled",
|
|
7452
|
+
reason: "unavailable"
|
|
7453
|
+
});
|
|
7454
|
+
return;
|
|
7455
|
+
}
|
|
7456
|
+
sequence.current += 1;
|
|
7457
|
+
const id = sequence.current;
|
|
7458
|
+
const onAbort = () => {
|
|
7459
|
+
if (pendingRef.current?.id === id) settle({
|
|
7460
|
+
kind: "cancelled",
|
|
7461
|
+
reason: "aborted"
|
|
7462
|
+
});
|
|
7463
|
+
};
|
|
7464
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
7465
|
+
pendingRef.current = {
|
|
7466
|
+
id,
|
|
7467
|
+
...sessionIdentity(runtime),
|
|
7468
|
+
resolve,
|
|
7469
|
+
detach: () => signal?.removeEventListener("abort", onAbort)
|
|
7470
|
+
};
|
|
7471
|
+
rowsRef.current = new Map();
|
|
7472
|
+
createdRowRef.current = void 0;
|
|
7473
|
+
const next = {
|
|
7474
|
+
id,
|
|
7475
|
+
frames: latest.current.frames,
|
|
7476
|
+
selected: opts.selected ?? []
|
|
7477
|
+
};
|
|
7478
|
+
activeRef.current = next;
|
|
7479
|
+
setActive(next);
|
|
7480
|
+
}), [runtime, settle]);
|
|
7481
|
+
const onSelectRow = react.useCallback((row) => {
|
|
7482
|
+
const field = wiring.valueField;
|
|
7483
|
+
const value = field === "id" ? row.id : row[field];
|
|
7484
|
+
if (typeof value !== "string" && typeof value !== "number") return;
|
|
7485
|
+
settle({
|
|
7486
|
+
kind: "selected",
|
|
7487
|
+
keys: [value],
|
|
7488
|
+
rows: [project(row)]
|
|
7489
|
+
});
|
|
7490
|
+
}, [
|
|
7491
|
+
wiring.valueField,
|
|
7492
|
+
settle,
|
|
7493
|
+
project
|
|
7494
|
+
]);
|
|
7495
|
+
const onDone = react.useCallback(() => {
|
|
7496
|
+
const keys = activeRef.current?.selected ?? [];
|
|
7497
|
+
const rows = keys.flatMap((key) => {
|
|
7498
|
+
const row = rowsRef.current.get(String(key));
|
|
7499
|
+
return row === void 0 ? [] : [project(row)];
|
|
7500
|
+
});
|
|
7501
|
+
settle({
|
|
7502
|
+
kind: "selected",
|
|
7503
|
+
keys,
|
|
7504
|
+
rows
|
|
7505
|
+
});
|
|
7506
|
+
}, [settle, project]);
|
|
7507
|
+
const onOpenChange = react.useCallback((next) => {
|
|
7508
|
+
if (!next) settle({
|
|
7509
|
+
kind: "cancelled",
|
|
7510
|
+
reason: "dismissed"
|
|
7511
|
+
});
|
|
7512
|
+
}, [settle]);
|
|
7513
|
+
return {
|
|
7514
|
+
open,
|
|
7515
|
+
element: (0, react_jsx_runtime.jsx)(PickerHost, {
|
|
7516
|
+
register,
|
|
7517
|
+
children: active === null || held ? null : (0, react_jsx_runtime.jsxs)(_burojs_react.RecordScopeChain, {
|
|
7518
|
+
frames: active.frames,
|
|
7519
|
+
children: [(0, react_jsx_runtime.jsx)(require_lazy_relation_picker_dialog.LazyRelationPickerDialog, {
|
|
7520
|
+
to: target,
|
|
7521
|
+
open: true,
|
|
7522
|
+
onOpenChange,
|
|
7523
|
+
onSelect: noop,
|
|
7524
|
+
onSelectRow,
|
|
7525
|
+
valueField: wiring.valueField,
|
|
7526
|
+
...selection.fixedFilters === void 0 ? {} : { fixedFilters: selection.fixedFilters },
|
|
7527
|
+
scope,
|
|
7528
|
+
...fieldName === void 0 ? {} : { scopeField: fieldName },
|
|
7529
|
+
...options.create === void 0 ? {} : {
|
|
7530
|
+
create,
|
|
7531
|
+
...options.create.seeds === void 0 ? {} : { createSeeds: options.create.seeds }
|
|
7532
|
+
},
|
|
7533
|
+
fieldName: fieldName ?? target,
|
|
7534
|
+
...options.disabledKeys === void 0 ? {} : { disabledKeys: options.disabledKeys },
|
|
7535
|
+
...options.disabledLabel === void 0 ? {} : { disabledLabel: options.disabledLabel },
|
|
7536
|
+
...multiple ? {
|
|
7537
|
+
multiple: true,
|
|
7538
|
+
selected: active.selected,
|
|
7539
|
+
onToggle: (value, row) => toggle(value, row),
|
|
7540
|
+
onDone
|
|
7541
|
+
} : {}
|
|
7542
|
+
}), wiring.reader]
|
|
7543
|
+
}, active.id)
|
|
7544
|
+
})
|
|
7545
|
+
};
|
|
7546
|
+
}
|
|
7547
|
+
//#endregion
|
|
7548
|
+
//#region src/blocks/link-write-summary.tsx
|
|
7549
|
+
function LinkWriteSummary(props) {
|
|
7550
|
+
const { report, titles, onClose } = props;
|
|
7551
|
+
const testid = props.testid ?? "link-write-summary";
|
|
7552
|
+
const t = (0, _burojs_react.useOptionalT)();
|
|
7553
|
+
const caps = (0, _burojs_react.useI18nCaps)();
|
|
7554
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
7555
|
+
const heading = t("field.link.partial", { defaultValue: "Some links were not changed" });
|
|
7556
|
+
return (0, react_jsx_runtime.jsx)(require_dialog.Dialog, {
|
|
7557
|
+
open: true,
|
|
7558
|
+
onOpenChange: (open) => {
|
|
7559
|
+
if (!open) onClose();
|
|
7560
|
+
},
|
|
7561
|
+
children: (0, react_jsx_runtime.jsxs)(require_dialog.DialogContent, {
|
|
7562
|
+
"data-testid": testid,
|
|
7563
|
+
className: "flex max-h-[85vh] flex-col overflow-hidden",
|
|
7564
|
+
children: [
|
|
7565
|
+
(0, react_jsx_runtime.jsxs)(require_dialog.DialogHeader, { children: [(0, react_jsx_runtime.jsx)(require_dialog.DialogTitle, { children: heading }), (0, react_jsx_runtime.jsx)(require_dialog.DialogDescription, {
|
|
7566
|
+
className: "sr-only",
|
|
7567
|
+
children: heading
|
|
7568
|
+
})] }),
|
|
7569
|
+
(0, react_jsx_runtime.jsx)("ul", {
|
|
7570
|
+
className: "flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto overscroll-contain",
|
|
7571
|
+
children: report.failed.map(({ id, error }) => (0, react_jsx_runtime.jsxs)("li", {
|
|
7572
|
+
"data-testid": `${testid}:item:${id}`,
|
|
7573
|
+
className: "text-sm",
|
|
7574
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
7575
|
+
className: "font-medium",
|
|
7576
|
+
children: titles[id] ?? id
|
|
7577
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
7578
|
+
className: "text-destructive",
|
|
7579
|
+
children: `: ${(0, _burojs_react.resolveErrorText)(error, caps)}`
|
|
7580
|
+
})]
|
|
7581
|
+
}, id))
|
|
7582
|
+
}),
|
|
7583
|
+
(0, react_jsx_runtime.jsx)(require_dialog.DialogFooter, { children: (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
7584
|
+
type: "button",
|
|
7585
|
+
onClick: onClose,
|
|
7586
|
+
"data-testid": `${testid}:close`,
|
|
7587
|
+
children: chromeT("actions.close", { defaultValue: "Close" })
|
|
7588
|
+
}) })
|
|
7589
|
+
]
|
|
7590
|
+
})
|
|
7591
|
+
});
|
|
7592
|
+
}
|
|
7593
|
+
//#endregion
|
|
7594
|
+
//#region src/blocks/link-attach.tsx
|
|
7595
|
+
const NO_ISSUES = Object.freeze([]);
|
|
7596
|
+
function useLinkPanelWrites(options) {
|
|
7597
|
+
const { owner, junction, target, link, targetKey, valueField, junctionIdField, displayField, scope, record, ownerKey, placement } = options;
|
|
7598
|
+
const app = (0, _burojs_react.useApp)();
|
|
7599
|
+
const runtime = (0, _burojs_react.useDataRuntime)();
|
|
7600
|
+
const t = (0, _burojs_react.useOptionalT)();
|
|
7601
|
+
const rights = (0, _burojs_react.useLinkRights)(owner, link, {
|
|
7602
|
+
surface: "panel",
|
|
7603
|
+
record,
|
|
7604
|
+
...placement === void 0 ? {} : { placement }
|
|
7605
|
+
});
|
|
7606
|
+
const writer = (0, _burojs_react.useLinkWriter)(owner, link);
|
|
7607
|
+
const linkedKeys = (0, _burojs_react.useLinkedKeys)(owner, link);
|
|
7608
|
+
const reverse = (0, react.useMemo)(() => (0, _burojs_core.reverseLinkOf)((name) => app.registry.get(name)?.fields, owner, link), [
|
|
7609
|
+
app.registry,
|
|
7610
|
+
owner,
|
|
7611
|
+
link
|
|
7612
|
+
]);
|
|
7613
|
+
let liveHides = false;
|
|
7614
|
+
if (reverse !== void 0) try {
|
|
7615
|
+
const { providerId } = runtime.app.resolveDataBinding(target);
|
|
7616
|
+
liveHides = runtime.providers.resolve(providerId).provider.readRelations?.links === true && (0, _burojs_react.linkCapabilitiesOf)(runtime, providerId)?.links?.filter.none !== false;
|
|
7617
|
+
} catch {
|
|
7618
|
+
liveHides = false;
|
|
7619
|
+
}
|
|
7620
|
+
const liveHidesRef = (0, react.useRef)(liveHides);
|
|
7621
|
+
liveHidesRef.current = liveHides;
|
|
7622
|
+
const [frozenHides, setFrozenHides] = (0, react.useState)(null);
|
|
7623
|
+
const hides = frozenHides ?? liveHides;
|
|
7624
|
+
const ownerKeyId = JSON.stringify(ownerKey ?? null);
|
|
7625
|
+
const hidden = (0, react.useMemo)(() => hides && reverse !== void 0 ? [{
|
|
7626
|
+
field: reverse,
|
|
7627
|
+
op: "hasNone",
|
|
7628
|
+
value: [ownerKey]
|
|
7629
|
+
}] : void 0, [
|
|
7630
|
+
hides,
|
|
7631
|
+
reverse,
|
|
7632
|
+
ownerKeyId
|
|
7633
|
+
]);
|
|
7634
|
+
const disabledKeys = (0, react.useCallback)((keys, signal) => linkedKeys(record, keys, signal), [linkedKeys, record]);
|
|
7635
|
+
const disabledLabel = (0, react.useCallback)((count) => t("field.link.alreadyLinked", {
|
|
7636
|
+
count,
|
|
7637
|
+
defaultValue: `${count} already linked`
|
|
7638
|
+
}), [t]);
|
|
7639
|
+
const picker = useRelationPicker({
|
|
7640
|
+
to: target,
|
|
7641
|
+
multiple: true,
|
|
7642
|
+
valueField,
|
|
7643
|
+
scope,
|
|
7644
|
+
...hidden === void 0 ? {
|
|
7645
|
+
disabledKeys,
|
|
7646
|
+
disabledLabel
|
|
7647
|
+
} : { fixedFilters: hidden }
|
|
7648
|
+
});
|
|
7649
|
+
const openPicker = picker.open;
|
|
7650
|
+
const [summary, setSummary] = (0, react.useState)(null);
|
|
7651
|
+
const finish = (0, react.useCallback)((report, titles, done) => {
|
|
7652
|
+
if (report.outcome !== "success") {
|
|
7653
|
+
setSummary({
|
|
7654
|
+
report,
|
|
7655
|
+
titles
|
|
7656
|
+
});
|
|
7657
|
+
return;
|
|
7658
|
+
}
|
|
7659
|
+
const count = report.succeeded.length;
|
|
7660
|
+
if (count === 0) return;
|
|
7661
|
+
sonner.toast.success(t(`field.link.${done}`, {
|
|
7662
|
+
count,
|
|
7663
|
+
defaultValue: `${count} ${count === 1 ? "link" : "links"} ${done}`
|
|
7664
|
+
}));
|
|
7665
|
+
}, [t]);
|
|
7666
|
+
const attaching = (0, react.useRef)(false);
|
|
7667
|
+
const [attachWriting, setAttachWriting] = (0, react.useState)(false);
|
|
7668
|
+
const onAttach = (0, react.useCallback)(() => {
|
|
7669
|
+
if (attaching.current) return;
|
|
7670
|
+
attaching.current = true;
|
|
7671
|
+
(async () => {
|
|
7672
|
+
try {
|
|
7673
|
+
setFrozenHides(liveHidesRef.current);
|
|
7674
|
+
let result;
|
|
7675
|
+
try {
|
|
7676
|
+
result = await openPicker();
|
|
7677
|
+
} finally {
|
|
7678
|
+
setFrozenHides(null);
|
|
7679
|
+
}
|
|
7680
|
+
if (result.kind !== "selected" || result.keys.length === 0) return;
|
|
7681
|
+
const titles = {};
|
|
7682
|
+
for (const row of result.rows) {
|
|
7683
|
+
const key = valueField === "id" ? row.id : row[valueField];
|
|
7684
|
+
const title = row[displayField];
|
|
7685
|
+
if (key !== void 0 && key !== null && title !== void 0 && title !== null) titles[String(key)] = String(title);
|
|
7686
|
+
}
|
|
7687
|
+
setAttachWriting(true);
|
|
7688
|
+
try {
|
|
7689
|
+
finish(await writer.attach(result.keys, record), titles, "attached");
|
|
7690
|
+
} finally {
|
|
7691
|
+
setAttachWriting(false);
|
|
7692
|
+
}
|
|
7693
|
+
} finally {
|
|
7694
|
+
attaching.current = false;
|
|
7695
|
+
}
|
|
7696
|
+
})();
|
|
7697
|
+
}, [
|
|
7698
|
+
displayField,
|
|
7699
|
+
finish,
|
|
7700
|
+
openPicker,
|
|
7701
|
+
record,
|
|
7702
|
+
valueField,
|
|
7703
|
+
writer
|
|
7704
|
+
]);
|
|
7705
|
+
const pending = (0, react.useRef)(null);
|
|
7706
|
+
const [confirming, setConfirming] = (0, react.useState)(null);
|
|
7707
|
+
const detaching = (0, react.useRef)(false);
|
|
7708
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
7709
|
+
const onDetach = (0, react.useCallback)((rows) => new Promise((resolve) => {
|
|
7710
|
+
pending.current?.resolve([]);
|
|
7711
|
+
pending.current = {
|
|
7712
|
+
rows,
|
|
7713
|
+
resolve
|
|
7714
|
+
};
|
|
7715
|
+
setConfirming(rows.length);
|
|
7716
|
+
}), []);
|
|
7717
|
+
(0, react.useEffect)(() => () => {
|
|
7718
|
+
pending.current?.resolve([]);
|
|
7719
|
+
pending.current = null;
|
|
7720
|
+
}, []);
|
|
7721
|
+
const cancel = (0, react.useCallback)(() => {
|
|
7722
|
+
if (detaching.current) return;
|
|
7723
|
+
pending.current?.resolve([]);
|
|
7724
|
+
pending.current = null;
|
|
7725
|
+
setConfirming(null);
|
|
7726
|
+
}, []);
|
|
7727
|
+
const proceed = (0, react.useCallback)(() => {
|
|
7728
|
+
const current = pending.current;
|
|
7729
|
+
if (current === null || detaching.current) return;
|
|
7730
|
+
detaching.current = true;
|
|
7731
|
+
setBusy(true);
|
|
7732
|
+
(async () => {
|
|
7733
|
+
try {
|
|
7734
|
+
const titles = {};
|
|
7735
|
+
for (const row of current.rows) {
|
|
7736
|
+
const id = row[junctionIdField];
|
|
7737
|
+
if (id === void 0 || id === null) continue;
|
|
7738
|
+
const title = row[`${targetKey}.${displayField}`] ?? row[targetKey];
|
|
7739
|
+
if (title !== void 0 && title !== null) titles[String(id)] = String(title);
|
|
7740
|
+
}
|
|
7741
|
+
const report = await writer.detach(current.rows, record);
|
|
7742
|
+
pending.current = null;
|
|
7743
|
+
setConfirming(null);
|
|
7744
|
+
finish(report, titles, "detached");
|
|
7745
|
+
const left = new Set(report.succeeded);
|
|
7746
|
+
current.resolve(current.rows.filter((row) => {
|
|
7747
|
+
const id = row[junctionIdField];
|
|
7748
|
+
return id !== void 0 && id !== null && left.has(String(id));
|
|
7749
|
+
}).map((row) => String(row.id)));
|
|
7750
|
+
} finally {
|
|
7751
|
+
detaching.current = false;
|
|
7752
|
+
setBusy(false);
|
|
7753
|
+
}
|
|
7754
|
+
})();
|
|
7755
|
+
}, [
|
|
7756
|
+
displayField,
|
|
7757
|
+
finish,
|
|
7758
|
+
junctionIdField,
|
|
7759
|
+
record,
|
|
7760
|
+
targetKey,
|
|
7761
|
+
writer
|
|
7762
|
+
]);
|
|
7763
|
+
const detachLabel = t("field.link.detach", { defaultValue: "Detach" });
|
|
7764
|
+
const count = confirming ?? 0;
|
|
7765
|
+
const gate = {
|
|
7766
|
+
resource: junction,
|
|
7767
|
+
open: confirming !== null,
|
|
7768
|
+
busy,
|
|
7769
|
+
header: t("field.link.confirmDetach", {
|
|
7770
|
+
count,
|
|
7771
|
+
defaultValue: `Detach ${count} ${count === 1 ? "link" : "links"}? The linked records themselves are not deleted.`
|
|
7772
|
+
}),
|
|
7773
|
+
blockers: NO_ISSUES,
|
|
7774
|
+
confirmable: NO_ISSUES,
|
|
7775
|
+
proceed,
|
|
7776
|
+
cancel
|
|
7777
|
+
};
|
|
7778
|
+
const attachAllowed = rights.attach.allowed;
|
|
7779
|
+
const detachAllowed = rights.detach.allowed;
|
|
7780
|
+
return {
|
|
7781
|
+
linkEditing: (0, react.useMemo)(() => !attachAllowed && !detachAllowed ? void 0 : {
|
|
7782
|
+
...attachAllowed ? { attach: {
|
|
7783
|
+
onAttach,
|
|
7784
|
+
busy: attachWriting
|
|
7785
|
+
} } : {},
|
|
7786
|
+
...detachAllowed ? { detach: { onDetach } } : {}
|
|
7787
|
+
}, [
|
|
7788
|
+
attachAllowed,
|
|
7789
|
+
attachWriting,
|
|
7790
|
+
detachAllowed,
|
|
7791
|
+
onAttach,
|
|
7792
|
+
onDetach
|
|
7793
|
+
]),
|
|
7794
|
+
element: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
7795
|
+
picker.element,
|
|
7796
|
+
(0, react_jsx_runtime.jsx)(require_check_confirm_dialog.CheckConfirmDialog, {
|
|
7797
|
+
state: gate,
|
|
7798
|
+
testid: `link-detach-confirm:${junction}`,
|
|
7799
|
+
title: detachLabel,
|
|
7800
|
+
proceedLabel: detachLabel,
|
|
7801
|
+
tone: "destructive"
|
|
7802
|
+
}),
|
|
7803
|
+
summary === null ? null : (0, react_jsx_runtime.jsx)(LinkWriteSummary, {
|
|
7804
|
+
report: summary.report,
|
|
7805
|
+
titles: summary.titles,
|
|
7806
|
+
onClose: () => setSummary(null),
|
|
7807
|
+
testid: `link-write-summary:${junction}`
|
|
7808
|
+
})
|
|
7809
|
+
] })
|
|
7810
|
+
};
|
|
7811
|
+
}
|
|
7812
|
+
//#endregion
|
|
6985
7813
|
//#region src/quick/peek-filter.ts
|
|
6986
7814
|
function peekFieldDefinition(def, name) {
|
|
6987
7815
|
return (0, _burojs_core.declaredField)(def, name);
|
|
@@ -7005,32 +7833,12 @@ function peekRecord(def, row, idField, capabilityFor, fieldVisible) {
|
|
|
7005
7833
|
return peekRow(def, row, idField, capabilityFor, fieldVisible);
|
|
7006
7834
|
}
|
|
7007
7835
|
//#endregion
|
|
7008
|
-
//#region src/blocks/related-list-unbound.tsx
|
|
7009
|
-
function UnboundRelatedList(props) {
|
|
7010
|
-
const t = (0, _burojs_react.useOptionalT)();
|
|
7011
|
-
return (0, react_jsx_runtime.jsxs)("div", {
|
|
7012
|
-
className: "flex flex-col gap-2",
|
|
7013
|
-
"data-testid": `list-unbound:${props.resource}`,
|
|
7014
|
-
children: [props.title === void 0 ? null : (0, react_jsx_runtime.jsx)("h3", {
|
|
7015
|
-
className: "text-sm font-semibold",
|
|
7016
|
-
children: props.title
|
|
7017
|
-
}), (0, react_jsx_runtime.jsx)("p", {
|
|
7018
|
-
className: "text-sm text-muted-foreground",
|
|
7019
|
-
children: t("table.empty", { defaultValue: "No records" })
|
|
7020
|
-
})]
|
|
7021
|
-
});
|
|
7022
|
-
}
|
|
7023
|
-
function placementScope(scope, owner) {
|
|
7024
|
-
return scope ?? (owner === void 0 ? "session" : "none");
|
|
7025
|
-
}
|
|
7026
|
-
//#endregion
|
|
7027
7836
|
//#region src/blocks/link-panel.tsx
|
|
7028
7837
|
const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
7029
7838
|
const isResourceHandle = (value) => isRecord(value) && value.kind === "resource";
|
|
7030
|
-
function qualify(ref
|
|
7839
|
+
function qualify(ref) {
|
|
7031
7840
|
try {
|
|
7032
|
-
|
|
7033
|
-
return (0, _burojs_core.resourceKey)((0, _burojs_core.normalizeEntityRef)(isResourceHandle(ref) ? ref.ref : ref, { defaultNamespace: namespace }));
|
|
7841
|
+
return (0, _burojs_core.resourceKey)((0, _burojs_core.normalizeEntityRef)(isResourceHandle(ref) ? ref.ref : ref));
|
|
7034
7842
|
} catch {
|
|
7035
7843
|
return;
|
|
7036
7844
|
}
|
|
@@ -7049,7 +7857,7 @@ function linkField(registry, owner, link) {
|
|
|
7049
7857
|
function linkTarget(registry, owner, link) {
|
|
7050
7858
|
const found = linkField(registry, owner, link);
|
|
7051
7859
|
if (found === void 0 || owner === void 0) return void 0;
|
|
7052
|
-
return qualify(found.field.meta?.to
|
|
7860
|
+
return qualify(found.field.meta?.to);
|
|
7053
7861
|
}
|
|
7054
7862
|
function idFieldOf(def) {
|
|
7055
7863
|
const declared = isRecord(def) && isRecord(def.data) ? def.data.idField : void 0;
|
|
@@ -7065,37 +7873,47 @@ function targetColumns(registry, target, def) {
|
|
|
7065
7873
|
const source = def;
|
|
7066
7874
|
const views = isRecord(def.views) ? def.views : void 0;
|
|
7067
7875
|
const list = views !== void 0 && isRecord(views.list) ? views.list : void 0;
|
|
7068
|
-
return (list !== void 0 && Array.isArray(list.columns) ? list.columns.
|
|
7876
|
+
return (list !== void 0 && Array.isArray(list.columns) ? list.columns.flatMap((entry) => {
|
|
7877
|
+
const name = isRecord(entry) ? entry.field : entry;
|
|
7878
|
+
return typeof name === "string" ? [name] : [];
|
|
7879
|
+
}) : (0, _burojs_core.dtoFields)(source, "list")).filter((name) => {
|
|
7069
7880
|
if (name.includes(".")) return name.split(".").length - 1 <= MAX_TARGET_HOPS && (0, _burojs_react.resolveColumnField)(registry, target, name) !== void 0;
|
|
7070
7881
|
const field = peekFieldDefinition(source, name);
|
|
7071
7882
|
return isRecord(field) && !(0, _burojs_core.isRelationField)(field) && (0, _burojs_core.fieldSensitivity)(field) === void 0;
|
|
7072
7883
|
});
|
|
7073
7884
|
}
|
|
7074
7885
|
function LinkPanel(props) {
|
|
7075
|
-
const { link, owner, own } = props;
|
|
7886
|
+
const { link, owner, own, empty } = props;
|
|
7076
7887
|
const app = (0, _burojs_react.useApp)();
|
|
7077
7888
|
const frame = usePlacementFrame();
|
|
7078
7889
|
const routeScreen = useIsRouteScreen();
|
|
7079
7890
|
const record = (0, _burojs_react.useOptionalRecordFrame)()?.record;
|
|
7891
|
+
const runtime = (0, _burojs_react.useOptionalDataRuntime)();
|
|
7080
7892
|
const storage = (0, react.useMemo)(() => {
|
|
7081
7893
|
const found = linkField(app.registry, owner, link);
|
|
7082
7894
|
if (found === void 0) return void 0;
|
|
7083
7895
|
const { declaration } = found;
|
|
7084
|
-
const junction = qualify(declaration.junction
|
|
7085
|
-
const target = qualify(found.field.meta?.to
|
|
7896
|
+
const junction = qualify(declaration.junction);
|
|
7897
|
+
const target = qualify(found.field.meta?.to);
|
|
7086
7898
|
if (junction === void 0 || target === void 0) return void 0;
|
|
7087
7899
|
const junctionDef = app.registry.get(junction);
|
|
7088
7900
|
if (junctionDef === void 0) return void 0;
|
|
7089
7901
|
const junctionFields = junctionDef.fields;
|
|
7902
|
+
const targetDef = app.registry.get(target);
|
|
7903
|
+
const targetBy = byOf(junctionFields[declaration.targetKey]);
|
|
7904
|
+
const declaredScope = found.field.meta?.scope;
|
|
7090
7905
|
return {
|
|
7091
7906
|
junction,
|
|
7092
7907
|
target,
|
|
7093
7908
|
sourceKey: declaration.sourceKey,
|
|
7094
7909
|
targetKey: declaration.targetKey,
|
|
7095
7910
|
ownerField: byOf(junctionFields[declaration.sourceKey]) ?? idFieldOf(app.registry.get(owner)),
|
|
7096
|
-
targetKeyedBy:
|
|
7911
|
+
targetKeyedBy: targetBy !== void 0,
|
|
7912
|
+
targetValueField: targetBy ?? idFieldOf(targetDef),
|
|
7913
|
+
junctionIdField: idFieldOf(junctionDef),
|
|
7097
7914
|
where: declaration.where,
|
|
7098
|
-
targetDef
|
|
7915
|
+
targetDef,
|
|
7916
|
+
pickerScope: declaredScope === "context" || declaredScope === "session" || declaredScope === "none" ? declaredScope : void 0
|
|
7099
7917
|
};
|
|
7100
7918
|
}, [
|
|
7101
7919
|
app.registry,
|
|
@@ -7107,10 +7925,11 @@ function LinkPanel(props) {
|
|
|
7107
7925
|
const fixedFilters = (0, react.useMemo)(() => {
|
|
7108
7926
|
if (storage === void 0 || ownerKey === null || ownerKey === void 0) return void 0;
|
|
7109
7927
|
const { sourceKey, targetKey } = storage;
|
|
7928
|
+
const placed = (0, _burojs_core_internal.whereToFilter)(own.where ?? [], (field) => `${targetKey}.${field}`);
|
|
7110
7929
|
return [
|
|
7111
7930
|
(0, _burojs_core.whereEntryToFilter)(sourceKey, "eq", ownerKey),
|
|
7112
7931
|
...storage.where.map((entry) => (0, _burojs_core.whereEntryToFilter)(entry.field, entry.op, entry.value)),
|
|
7113
|
-
...
|
|
7932
|
+
...placed === void 0 ? [] : [placed]
|
|
7114
7933
|
];
|
|
7115
7934
|
}, [
|
|
7116
7935
|
storage,
|
|
@@ -7120,7 +7939,12 @@ function LinkPanel(props) {
|
|
|
7120
7939
|
const columnsKey = JSON.stringify([own.columns ?? null, own.linkColumns ?? null]);
|
|
7121
7940
|
const columns = (0, react.useMemo)(() => {
|
|
7122
7941
|
if (storage === void 0) return void 0;
|
|
7123
|
-
|
|
7942
|
+
const shown = own.columns ?? targetColumns(app.registry, storage.target, storage.targetDef);
|
|
7943
|
+
const across = (entry) => typeof entry === "string" ? `${storage.targetKey}.${entry}` : {
|
|
7944
|
+
...entry,
|
|
7945
|
+
field: `${storage.targetKey}.${entry.field}`
|
|
7946
|
+
};
|
|
7947
|
+
return [...shown.map(across), ...own.linkColumns ?? []];
|
|
7124
7948
|
}, [
|
|
7125
7949
|
storage,
|
|
7126
7950
|
columnsKey,
|
|
@@ -7130,30 +7954,75 @@ function LinkPanel(props) {
|
|
|
7130
7954
|
resource: storage.target,
|
|
7131
7955
|
field: storage.targetKey
|
|
7132
7956
|
}, [storage]);
|
|
7133
|
-
const unbound = fixedFilters === void 0 || own.where
|
|
7957
|
+
const unbound = fixedFilters === void 0 || own.where !== void 0 && (0, _burojs_core_internal.hasNullRef)(own.where);
|
|
7134
7958
|
if (storage === void 0 || unbound) return (0, react_jsx_runtime.jsx)(UnboundRelatedList, {
|
|
7135
7959
|
resource: storage?.target ?? "",
|
|
7136
|
-
title: own.title
|
|
7960
|
+
title: own.title,
|
|
7961
|
+
...empty === void 0 ? {} : { empty }
|
|
7137
7962
|
});
|
|
7138
7963
|
const state = frame?.state === "url" && routeScreen && !frame.nested ? { url: frame.key } : "memory";
|
|
7139
|
-
|
|
7140
|
-
|
|
7964
|
+
let providerCounts;
|
|
7965
|
+
if (runtime !== null) try {
|
|
7966
|
+
providerCounts = (0, _burojs_react.linkCapabilitiesOf)(runtime, runtime.app.resolveDataBinding(storage.junction).providerId)?.links?.count;
|
|
7967
|
+
} catch {
|
|
7968
|
+
providerCounts = void 0;
|
|
7969
|
+
}
|
|
7970
|
+
const count = own.count === false ? "off" : own.count ?? (providerCounts === false ? "off" : void 0);
|
|
7971
|
+
const layoutId = frame === null ? void 0 : placementLayoutId({
|
|
7972
|
+
owner,
|
|
7973
|
+
key: frame.key
|
|
7974
|
+
});
|
|
7975
|
+
const surface = {
|
|
7141
7976
|
resource: storage.junction,
|
|
7142
7977
|
variant: "placement",
|
|
7143
7978
|
state,
|
|
7144
7979
|
fixedFilters,
|
|
7145
|
-
...own.pageSize === void 0 ? {} : { pageSize: own.pageSize },
|
|
7980
|
+
...own.initial?.pageSize === void 0 ? {} : { initial: { pageSize: own.initial.pageSize } },
|
|
7146
7981
|
...own.search === void 0 ? {} : { search: `${storage.targetKey}.${own.search}` },
|
|
7147
7982
|
...columns === void 0 ? {} : { columns },
|
|
7148
7983
|
open: rowTarget === void 0 || own.open === "none" ? "none" : "page",
|
|
7149
7984
|
...rowTarget === void 0 ? {} : { rowTarget },
|
|
7150
7985
|
...frame === null ? {} : { placementKey: frame.key },
|
|
7986
|
+
...layoutId === void 0 ? {} : { layoutId },
|
|
7151
7987
|
...own.title === void 0 ? {} : { title: own.title },
|
|
7988
|
+
...empty === void 0 ? {} : { empty },
|
|
7152
7989
|
scope: placementScope(own.scope, owner),
|
|
7153
7990
|
...count === void 0 ? {} : { count },
|
|
7154
7991
|
readOnly: true,
|
|
7155
7992
|
exportable: false
|
|
7993
|
+
};
|
|
7994
|
+
if (runtime === null || record === void 0) return (0, react_jsx_runtime.jsx)(ResourceListSurface, { ...surface });
|
|
7995
|
+
return (0, react_jsx_runtime.jsx)(WritableLinkPanel, {
|
|
7996
|
+
surface,
|
|
7997
|
+
owner,
|
|
7998
|
+
link,
|
|
7999
|
+
storage,
|
|
8000
|
+
record,
|
|
8001
|
+
ownerKey,
|
|
8002
|
+
placement: own.linkActions
|
|
8003
|
+
});
|
|
8004
|
+
}
|
|
8005
|
+
function WritableLinkPanel(props) {
|
|
8006
|
+
const { surface, owner, link, storage, record, ownerKey, placement } = props;
|
|
8007
|
+
const displayField = isRecord(storage.targetDef) && typeof storage.targetDef.displayField === "string" ? storage.targetDef.displayField : storage.targetValueField;
|
|
8008
|
+
const { linkEditing, element } = useLinkPanelWrites({
|
|
8009
|
+
owner,
|
|
8010
|
+
junction: storage.junction,
|
|
8011
|
+
target: storage.target,
|
|
8012
|
+
link,
|
|
8013
|
+
targetKey: storage.targetKey,
|
|
8014
|
+
valueField: storage.targetValueField,
|
|
8015
|
+
junctionIdField: storage.junctionIdField,
|
|
8016
|
+
displayField,
|
|
8017
|
+
scope: storage.pickerScope ?? "context",
|
|
8018
|
+
record,
|
|
8019
|
+
ownerKey,
|
|
8020
|
+
placement
|
|
7156
8021
|
});
|
|
8022
|
+
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(ResourceListSurface, {
|
|
8023
|
+
...surface,
|
|
8024
|
+
...linkEditing === void 0 ? {} : { linkEditing }
|
|
8025
|
+
}), element] });
|
|
7157
8026
|
}
|
|
7158
8027
|
//#endregion
|
|
7159
8028
|
//#region src/blocks/route-list-context.ts
|
|
@@ -7163,7 +8032,7 @@ function useRouteList() {
|
|
|
7163
8032
|
}
|
|
7164
8033
|
//#endregion
|
|
7165
8034
|
//#region src/blocks/related-list-view.tsx
|
|
7166
|
-
function RelatedListView({ props }) {
|
|
8035
|
+
function RelatedListView({ props, empty }) {
|
|
7167
8036
|
const own = props;
|
|
7168
8037
|
const route = useRouteList();
|
|
7169
8038
|
const frame = usePlacementFrame();
|
|
@@ -7171,7 +8040,7 @@ function RelatedListView({ props }) {
|
|
|
7171
8040
|
const linked = own.link !== void 0;
|
|
7172
8041
|
const resource = linked ? linkTarget(app.registry, frame?.owner, own.link) ?? "" : (0, _burojs_core.resourceKey)(own.resource);
|
|
7173
8042
|
const whereKey = JSON.stringify(own.where ?? []);
|
|
7174
|
-
const fixedFilters = (0, react.useMemo)(() => own.where === void 0
|
|
8043
|
+
const fixedFilters = (0, react.useMemo)(() => own.where === void 0 || own.where.length === 0 ? void 0 : [(0, _burojs_core_internal.whereToFilter)(own.where)], [whereKey]);
|
|
7175
8044
|
const columnsKey = JSON.stringify(own.columns ?? null);
|
|
7176
8045
|
const columns = (0, react.useMemo)(() => own.columns, [columnsKey]);
|
|
7177
8046
|
const routeScreen = useIsRouteScreen();
|
|
@@ -7183,20 +8052,23 @@ function RelatedListView({ props }) {
|
|
|
7183
8052
|
const ownerDef = frame?.owner === void 0 ? void 0 : app.registry.get(frame.owner);
|
|
7184
8053
|
const granted = ownerDef === void 0 ? "unknown" : (0, _burojs_core.grantedPlacementKeys)(ownerDef);
|
|
7185
8054
|
const trusted = frame !== null && !frame.nested && granted !== "unknown" && !granted.has(frame.key);
|
|
7186
|
-
const onCreate = route === null && !linked && trusted && gate(resource, "create").state === "open" && frame !== null ? () => void quick.create(resource, { defaults: placementSeeds(frame.where ?? [], own.where ?? [], frame.closure ?? {}) }) : void 0;
|
|
8055
|
+
const onCreate = route === null && !linked && trusted && gate(resource, "create").state === "open" && own.create !== false && (own.create === void 0 || (0, _burojs_core_internal.actionWhenHolds)(own.create, frame?.sources ?? {})) && frame !== null ? () => void quick.create(resource, { defaults: placementSeeds(frame.where ?? [], own.where ?? [], frame.closure ?? {}) }) : void 0;
|
|
7187
8056
|
useDeepLinkOpen(frame?.key ?? null, resource, route === null && !linked && frame !== null && !frame.nested && routeScreen && (own.open ?? "quick") === "quick");
|
|
7188
|
-
const unbound = own.where
|
|
8057
|
+
const unbound = own.where !== void 0 && (0, _burojs_core_internal.hasNullRef)(own.where);
|
|
7189
8058
|
if (linked) return frame?.owner === void 0 ? (0, react_jsx_runtime.jsx)(UnboundRelatedList, {
|
|
7190
8059
|
resource,
|
|
7191
|
-
title: own.title
|
|
8060
|
+
title: own.title,
|
|
8061
|
+
...empty === void 0 ? {} : { empty }
|
|
7192
8062
|
}) : (0, react_jsx_runtime.jsx)(LinkPanel, {
|
|
7193
8063
|
link: own.link,
|
|
7194
8064
|
owner: frame.owner,
|
|
7195
|
-
own
|
|
8065
|
+
own,
|
|
8066
|
+
...empty === void 0 ? {} : { empty }
|
|
7196
8067
|
});
|
|
7197
8068
|
if (route !== null) return (0, react_jsx_runtime.jsx)(ResourceListSurface, {
|
|
7198
8069
|
resource,
|
|
7199
8070
|
variant: "route",
|
|
8071
|
+
layoutId: "route",
|
|
7200
8072
|
...route.meta === void 0 ? {} : { meta: route.meta },
|
|
7201
8073
|
...route.renderCell === void 0 ? {} : { renderCell: route.renderCell },
|
|
7202
8074
|
...route.emptyState === void 0 ? {} : { emptyState: route.emptyState }
|
|
@@ -7209,24 +8081,28 @@ function RelatedListView({ props }) {
|
|
|
7209
8081
|
});
|
|
7210
8082
|
if (unbound) return (0, react_jsx_runtime.jsx)(UnboundRelatedList, {
|
|
7211
8083
|
resource,
|
|
7212
|
-
title: own.title
|
|
8084
|
+
title: own.title,
|
|
8085
|
+
...empty === void 0 ? {} : { empty }
|
|
7213
8086
|
});
|
|
7214
8087
|
const state = frame?.state === "url" && routeScreen && !frame.nested ? { url: frame.key } : "memory";
|
|
7215
8088
|
const scope = placementScope(own.scope, frame?.owner);
|
|
7216
8089
|
const count = own.count === false ? "off" : own.count;
|
|
8090
|
+
const layoutId = placementLayoutId(frame);
|
|
7217
8091
|
return (0, react_jsx_runtime.jsx)(ResourceListSurface, {
|
|
7218
8092
|
resource,
|
|
7219
8093
|
variant: "placement",
|
|
7220
8094
|
state,
|
|
7221
8095
|
...fixedFilters === void 0 ? {} : { fixedFilters },
|
|
7222
|
-
...own.
|
|
8096
|
+
...own.initial === void 0 ? {} : { initial: own.initial },
|
|
7223
8097
|
...own.search === void 0 ? {} : { search: own.search },
|
|
7224
8098
|
...columns === void 0 ? {} : { columns },
|
|
7225
8099
|
open: own.open ?? "quick",
|
|
7226
8100
|
...own.view === void 0 ? {} : { view: own.view },
|
|
7227
8101
|
...isItemHandle(own.item) ? { item: own.item } : {},
|
|
7228
8102
|
...frame === null ? {} : { placementKey: frame.key },
|
|
8103
|
+
...layoutId === void 0 ? {} : { layoutId },
|
|
7229
8104
|
...own.title === void 0 ? {} : { title: own.title },
|
|
8105
|
+
...empty === void 0 ? {} : { empty },
|
|
7230
8106
|
scope,
|
|
7231
8107
|
...count === void 0 ? {} : { count },
|
|
7232
8108
|
...onCreate === void 0 ? {} : { onCreate }
|
|
@@ -7261,7 +8137,7 @@ function Missing({ text }) {
|
|
|
7261
8137
|
children: text ?? t("table.empty", { defaultValue: "No records" })
|
|
7262
8138
|
});
|
|
7263
8139
|
}
|
|
7264
|
-
function RelatedRecordView({ props }) {
|
|
8140
|
+
function RelatedRecordView({ props, empty }) {
|
|
7265
8141
|
const own = props;
|
|
7266
8142
|
const app = (0, _burojs_react.useApp)();
|
|
7267
8143
|
const resource = (0, _burojs_core.resourceKey)(own.resource);
|
|
@@ -7295,15 +8171,15 @@ function RelatedRecordView({ props }) {
|
|
|
7295
8171
|
capabilityFor,
|
|
7296
8172
|
access
|
|
7297
8173
|
]);
|
|
7298
|
-
if (id === null) return (0, react_jsx_runtime.jsx)(Missing, { text: own.missing });
|
|
8174
|
+
if (id === null) return (0, react_jsx_runtime.jsx)(Missing, { text: own.missing ?? empty });
|
|
7299
8175
|
if (result === void 0) {
|
|
7300
|
-
if (query.error != null) return (0, react_jsx_runtime.jsx)(Missing, { text: own.missing });
|
|
8176
|
+
if (query.error != null) return (0, react_jsx_runtime.jsx)(Missing, { text: own.missing ?? empty });
|
|
7301
8177
|
return (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, {
|
|
7302
8178
|
"data-buro-skeleton": "",
|
|
7303
8179
|
className: "h-9 w-full"
|
|
7304
8180
|
});
|
|
7305
8181
|
}
|
|
7306
|
-
if (dtoRow === void 0) return (0, react_jsx_runtime.jsx)(Missing, { text: own.missing });
|
|
8182
|
+
if (dtoRow === void 0) return (0, react_jsx_runtime.jsx)(Missing, { text: own.missing ?? empty });
|
|
7307
8183
|
if (projected.status === "pending" || projected.value === null) return (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, {
|
|
7308
8184
|
"data-buro-skeleton": "",
|
|
7309
8185
|
className: "h-9 w-full"
|
|
@@ -7336,13 +8212,21 @@ function RelatedRecordView({ props }) {
|
|
|
7336
8212
|
children: (0, _burojs_core.resolveFieldLabel)(caps, name, (0, _burojs_core.declaredText)("field", field, "label"))
|
|
7337
8213
|
}), (0, react_jsx_runtime.jsx)("dd", {
|
|
7338
8214
|
className: "min-w-0 break-words text-sm",
|
|
7339
|
-
children: (0, react_jsx_runtime.jsx)(
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
8215
|
+
children: (0, react_jsx_runtime.jsx)(FieldValueFrame, {
|
|
8216
|
+
field: {
|
|
8217
|
+
...field ?? {},
|
|
8218
|
+
name
|
|
8219
|
+
},
|
|
7343
8220
|
value,
|
|
7344
|
-
|
|
7345
|
-
|
|
8221
|
+
surface: "display",
|
|
8222
|
+
children: (0, react_jsx_runtime.jsx)(require_filter_builder.ResolvedFieldDisplay, {
|
|
8223
|
+
resource: own.resource,
|
|
8224
|
+
name,
|
|
8225
|
+
field,
|
|
8226
|
+
value,
|
|
8227
|
+
record: row,
|
|
8228
|
+
fallback: toDisplayText(value).text
|
|
8229
|
+
})
|
|
7346
8230
|
})
|
|
7347
8231
|
})]
|
|
7348
8232
|
}, name);
|
|
@@ -7413,28 +8297,39 @@ function Chrome({ node, size, state, children }) {
|
|
|
7413
8297
|
});
|
|
7414
8298
|
}
|
|
7415
8299
|
function isAuthError(error) {
|
|
7416
|
-
return (0, _burojs_core.
|
|
8300
|
+
return (0, _burojs_core.normalizeDataError)(error).kind === "auth";
|
|
7417
8301
|
}
|
|
7418
|
-
|
|
8302
|
+
const PLACE_NODE_MESSAGES = {
|
|
8303
|
+
failed: "This section could not be loaded.",
|
|
8304
|
+
sessionExpired: "Your session has expired. Sign in again to continue.",
|
|
8305
|
+
notImplemented: "This section is not available."
|
|
8306
|
+
};
|
|
8307
|
+
function FailedPlacement({ node, size, message, retry, error }) {
|
|
7419
8308
|
const t = (0, _burojs_react.useOptionalT)();
|
|
8309
|
+
const chromeT = (0, _burojs_react.useChromeT)();
|
|
8310
|
+
const fallback = {
|
|
8311
|
+
key: `block.${message}`,
|
|
8312
|
+
default: PLACE_NODE_MESSAGES[message]
|
|
8313
|
+
};
|
|
7420
8314
|
return (0, react_jsx_runtime.jsx)(Chrome, {
|
|
7421
8315
|
node,
|
|
7422
8316
|
size,
|
|
7423
8317
|
state: "failed",
|
|
7424
|
-
children: (0, react_jsx_runtime.jsxs)("div", {
|
|
8318
|
+
children: message === "notImplemented" ? (0, react_jsx_runtime.jsxs)("div", {
|
|
7425
8319
|
role: "alert",
|
|
7426
8320
|
className: "flex flex-wrap items-center gap-2 rounded-md border border-dashed px-3 py-2 text-sm text-muted-foreground",
|
|
7427
|
-
children: [(0, react_jsx_runtime.jsx)("span", { children: t(
|
|
7428
|
-
failed: "This section could not be loaded.",
|
|
7429
|
-
sessionExpired: "Your session has expired. Sign in again to continue.",
|
|
7430
|
-
notImplemented: "This section is not available."
|
|
7431
|
-
}[message] }) }), retry === void 0 ? null : (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
8321
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: t(fallback.key, { defaultValue: fallback.default }) }), retry === void 0 ? null : (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
7432
8322
|
type: "button",
|
|
7433
8323
|
variant: "outline",
|
|
7434
8324
|
size: "sm",
|
|
7435
8325
|
onClick: retry,
|
|
7436
|
-
children:
|
|
8326
|
+
children: chromeT("actions.retry", { defaultValue: "Retry" })
|
|
7437
8327
|
})]
|
|
8328
|
+
}) : (0, react_jsx_runtime.jsx)(require_relation_create.LoadError, {
|
|
8329
|
+
surface: "block",
|
|
8330
|
+
error,
|
|
8331
|
+
...retry === void 0 ? {} : { retry },
|
|
8332
|
+
fallback
|
|
7438
8333
|
})
|
|
7439
8334
|
});
|
|
7440
8335
|
}
|
|
@@ -7514,7 +8409,8 @@ function ReadyPlacement({ node, size, placement, implementation }) {
|
|
|
7514
8409
|
nested,
|
|
7515
8410
|
...Array.isArray(declaredWhere) ? { where: declaredWhere } : {},
|
|
7516
8411
|
closure: compiled.sourceClosure,
|
|
7517
|
-
...owner === void 0 ? {} : { owner }
|
|
8412
|
+
...owner === void 0 ? {} : { owner },
|
|
8413
|
+
sources: controller.sources
|
|
7518
8414
|
}), [
|
|
7519
8415
|
node.key,
|
|
7520
8416
|
node.id,
|
|
@@ -7522,7 +8418,8 @@ function ReadyPlacement({ node, size, placement, implementation }) {
|
|
|
7522
8418
|
nested,
|
|
7523
8419
|
declaredWhere,
|
|
7524
8420
|
compiled.sourceClosure,
|
|
7525
|
-
owner
|
|
8421
|
+
owner,
|
|
8422
|
+
controller.sources
|
|
7526
8423
|
]);
|
|
7527
8424
|
return (0, react_jsx_runtime.jsx)(PlacementBoundary, {
|
|
7528
8425
|
node,
|
|
@@ -7580,6 +8477,7 @@ function PlaceNode({ node }) {
|
|
|
7580
8477
|
node,
|
|
7581
8478
|
size,
|
|
7582
8479
|
message: isAuthError(placement.error) ? "sessionExpired" : "failed",
|
|
8480
|
+
error: placement.error,
|
|
7583
8481
|
...placement.retry === void 0 ? {} : { retry: placement.retry }
|
|
7584
8482
|
});
|
|
7585
8483
|
if (implementation === void 0) return (0, react_jsx_runtime.jsx)(FailedPlacement, {
|
|
@@ -7715,6 +8613,12 @@ Object.defineProperty(exports, "FieldDisplay", {
|
|
|
7715
8613
|
return FieldDisplay;
|
|
7716
8614
|
}
|
|
7717
8615
|
});
|
|
8616
|
+
Object.defineProperty(exports, "FieldValueFrame", {
|
|
8617
|
+
enumerable: true,
|
|
8618
|
+
get: function() {
|
|
8619
|
+
return FieldValueFrame;
|
|
8620
|
+
}
|
|
8621
|
+
});
|
|
7718
8622
|
Object.defineProperty(exports, "FilterRegion", {
|
|
7719
8623
|
enumerable: true,
|
|
7720
8624
|
get: function() {
|
|
@@ -7727,6 +8631,12 @@ Object.defineProperty(exports, "FormActions", {
|
|
|
7727
8631
|
return FormActions;
|
|
7728
8632
|
}
|
|
7729
8633
|
});
|
|
8634
|
+
Object.defineProperty(exports, "FormControlProvider", {
|
|
8635
|
+
enumerable: true,
|
|
8636
|
+
get: function() {
|
|
8637
|
+
return FormControlProvider;
|
|
8638
|
+
}
|
|
8639
|
+
});
|
|
7730
8640
|
Object.defineProperty(exports, "FrameChromeContext", {
|
|
7731
8641
|
enumerable: true,
|
|
7732
8642
|
get: function() {
|
|
@@ -7847,12 +8757,6 @@ Object.defineProperty(exports, "RelatedItem", {
|
|
|
7847
8757
|
return RelatedItem;
|
|
7848
8758
|
}
|
|
7849
8759
|
});
|
|
7850
|
-
Object.defineProperty(exports, "ResolvedFieldDisplay", {
|
|
7851
|
-
enumerable: true,
|
|
7852
|
-
get: function() {
|
|
7853
|
-
return ResolvedFieldDisplay;
|
|
7854
|
-
}
|
|
7855
|
-
});
|
|
7856
8760
|
Object.defineProperty(exports, "ResourceList", {
|
|
7857
8761
|
enumerable: true,
|
|
7858
8762
|
get: function() {
|
|
@@ -7973,12 +8877,6 @@ Object.defineProperty(exports, "listTarget", {
|
|
|
7973
8877
|
return listTarget;
|
|
7974
8878
|
}
|
|
7975
8879
|
});
|
|
7976
|
-
Object.defineProperty(exports, "lowerLegacyField", {
|
|
7977
|
-
enumerable: true,
|
|
7978
|
-
get: function() {
|
|
7979
|
-
return lowerLegacyField;
|
|
7980
|
-
}
|
|
7981
|
-
});
|
|
7982
8880
|
Object.defineProperty(exports, "peekFieldDefinition", {
|
|
7983
8881
|
enumerable: true,
|
|
7984
8882
|
get: function() {
|
|
@@ -8021,6 +8919,12 @@ Object.defineProperty(exports, "resolveFrameView", {
|
|
|
8021
8919
|
return resolveFrameView;
|
|
8022
8920
|
}
|
|
8023
8921
|
});
|
|
8922
|
+
Object.defineProperty(exports, "resolveResourceTitle", {
|
|
8923
|
+
enumerable: true,
|
|
8924
|
+
get: function() {
|
|
8925
|
+
return resolveResourceTitle;
|
|
8926
|
+
}
|
|
8927
|
+
});
|
|
8024
8928
|
Object.defineProperty(exports, "resolveUpdater", {
|
|
8025
8929
|
enumerable: true,
|
|
8026
8930
|
get: function() {
|
|
@@ -8087,6 +8991,18 @@ Object.defineProperty(exports, "useExportRunWatcher", {
|
|
|
8087
8991
|
return useExportRunWatcher;
|
|
8088
8992
|
}
|
|
8089
8993
|
});
|
|
8994
|
+
Object.defineProperty(exports, "useFormControl", {
|
|
8995
|
+
enumerable: true,
|
|
8996
|
+
get: function() {
|
|
8997
|
+
return useFormControl;
|
|
8998
|
+
}
|
|
8999
|
+
});
|
|
9000
|
+
Object.defineProperty(exports, "useFormControlOf", {
|
|
9001
|
+
enumerable: true,
|
|
9002
|
+
get: function() {
|
|
9003
|
+
return useFormControlOf;
|
|
9004
|
+
}
|
|
9005
|
+
});
|
|
8090
9006
|
Object.defineProperty(exports, "useFrameChrome", {
|
|
8091
9007
|
enumerable: true,
|
|
8092
9008
|
get: function() {
|
|
@@ -8111,6 +9027,12 @@ Object.defineProperty(exports, "usePaletteState", {
|
|
|
8111
9027
|
return usePaletteState;
|
|
8112
9028
|
}
|
|
8113
9029
|
});
|
|
9030
|
+
Object.defineProperty(exports, "useRelationPicker", {
|
|
9031
|
+
enumerable: true,
|
|
9032
|
+
get: function() {
|
|
9033
|
+
return useRelationPicker;
|
|
9034
|
+
}
|
|
9035
|
+
});
|
|
8114
9036
|
Object.defineProperty(exports, "useShell", {
|
|
8115
9037
|
enumerable: true,
|
|
8116
9038
|
get: function() {
|
|
@@ -8136,4 +9058,4 @@ Object.defineProperty(exports, "viewOf", {
|
|
|
8136
9058
|
}
|
|
8137
9059
|
});
|
|
8138
9060
|
|
|
8139
|
-
//# sourceMappingURL=place-node-
|
|
9061
|
+
//# sourceMappingURL=place-node-CNb3w-c7.cjs.map
|