@ghentcdh/json-forms-vue 1.1.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/index.d.ts +6 -12
  2. package/index.js +8 -1891
  3. package/package.json +16 -30
  4. package/composables/useFormEvents.d.ts +0 -32
  5. package/form.store.d.ts +0 -8
  6. package/forms/Dispatch.vue.d.ts +0 -10
  7. package/forms/FormComponent.properties.d.ts +0 -48
  8. package/forms/FormComponent.vue.d.ts +0 -68
  9. package/forms/FormWithActions.properties.d.ts +0 -52
  10. package/forms/FormWithActions.vue.d.ts +0 -258
  11. package/forms/FormWithTable.properties.d.ts +0 -65
  12. package/forms/FormWithTable.vue.d.ts +0 -90
  13. package/forms/errorMessages.d.ts +0 -10
  14. package/forms/errorMode.d.ts +0 -4
  15. package/forms/modal/FormModal.properties.d.ts +0 -64
  16. package/forms/modal/FormModal.vue.d.ts +0 -275
  17. package/forms/modal/FormModalService.d.ts +0 -14
  18. package/forms/renderer-registry.d.ts +0 -7
  19. package/forms/renderers/array/ArrayRenderer.vue.d.ts +0 -7
  20. package/forms/renderers/array/ArrayRenderers.d.ts +0 -10
  21. package/forms/renderers/controls/AutocompleteControlRenderer.vue.d.ts +0 -7
  22. package/forms/renderers/controls/BooleanControlRenderer.vue.d.ts +0 -7
  23. package/forms/renderers/controls/MarkdownControlRenderer.vue.d.ts +0 -7
  24. package/forms/renderers/controls/MultiSelectControlRenderer.vue.d.ts +0 -7
  25. package/forms/renderers/controls/NumberControlRenderer.vue.d.ts +0 -7
  26. package/forms/renderers/controls/SelectControlRenderer.vue.d.ts +0 -7
  27. package/forms/renderers/controls/StringControlRenderer.vue.d.ts +0 -7
  28. package/forms/renderers/controls/TextAreaControlRenderer.vue.d.ts +0 -7
  29. package/forms/renderers/controls/composable/UseControlBinding.d.ts +0 -29
  30. package/forms/renderers/controls/composable/UseFetchOption.d.ts +0 -16
  31. package/forms/renderers/controls/composable/UseInput.d.ts +0 -24
  32. package/forms/renderers/controls/composable/UseSelectBinding.d.ts +0 -23
  33. package/forms/renderers/controls/composable/resource.d.ts +0 -187
  34. package/forms/renderers/controls/index.d.ts +0 -10
  35. package/forms/renderers/index.d.ts +0 -3
  36. package/forms/renderers/layout/CollapseLayoutRenderer.vue.d.ts +0 -7
  37. package/forms/renderers/layout/LayoutRenderer.vue.d.ts +0 -7
  38. package/forms/renderers/layout/LayoutRenders.d.ts +0 -10
  39. package/forms/renderers/layout/colspan.d.ts +0 -1
  40. package/forms/renderes.d.ts +0 -19
  41. package/forms/scope.d.ts +0 -4
  42. package/forms/types.d.ts +0 -36
  43. package/renderes/tester.d.ts +0 -11
  44. package/repository/crud.repository.d.ts +0 -32
  45. package/repository/index.d.ts +0 -1
  46. package/table/filter/table-filter.vue.d.ts +0 -13
  47. package/table/index.d.ts +0 -2
  48. package/table/table.component.properties.d.ts +0 -34
  49. package/table/table.component.vue.d.ts +0 -60
  50. package/table/table.store.d.ts +0 -29
  51. package/testing/index.d.ts +0 -0
  52. package/testing.js +0 -1
package/index.js CHANGED
@@ -1,1892 +1,9 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const vue = require("vue");
4
- const lodashEs = require("lodash-es");
5
- const jsonFormsCore = require("@ghentcdh/json-forms-core");
6
- const ui = require("@ghentcdh/ui");
7
- const core = require("@vueuse/core");
8
- const vueRouter = require("vue-router");
9
- const toolsVue = require("@ghentcdh/tools-vue");
10
- const zod = require("zod");
11
- const veeValidate = require("vee-validate");
12
- const core$1 = require("@jsonforms/core");
13
- const testers = require("@jsonforms/core/src/testers/testers");
14
- const axios = require("axios");
15
- const FormModalProperties = {
16
- /** Title displayed in the modal header. */
17
- modalTitle: { type: String, required: true },
18
- /** Label for the save button. */
19
- saveLabel: { type: String, default: "save" },
20
- /** Label for the cancel button. */
21
- cancelLabel: { type: String, default: "cancel" },
22
- /** JSON schema describing the shape of the form data. */
23
- schema: { type: Object, required: true },
24
- /** UI schema describing the layout and controls. */
25
- uiSchema: { type: Object, required: true },
26
- /** Modal width (`'xs'`, `'sm'`, `'md'`, `'lg'`, `'xl'`). */
27
- modalSize: { type: String, default: "md" },
28
- /** Callback invoked when the modal closes (with result or `null` on cancel). */
29
- onClose: {
30
- type: Function,
31
- required: true
32
- },
33
- /** Callback for form events dispatched by custom renderers. */
34
- onEvents: {
35
- type: Function
36
- },
37
- /** Initial form data to populate the form with. */
38
- data: { type: Object, required: true },
39
- /** When validation errors are shown. */
40
- errorMode: {
41
- type: String,
42
- default: "onBlur"
43
- }
44
- };
45
- const FormModalEmits = [
46
- /** Emitted when the modal is closed (submit or cancel). */
47
- "closeModal",
48
- /** Emitted when a custom renderer dispatches a form event. */
49
- "events",
50
- /** Emitted when validation errors change. */
51
- "errors",
52
- /** Emitted when form validity changes. */
53
- "valid"
54
- ];
55
- const _hoisted_1$8 = { class: "" };
56
- const _hoisted_2$2 = { class: "flex gap-2 items-center mb-2" };
57
- const _hoisted_3$1 = { class: "flex gap-2" };
58
- const _sfc_main$h = /* @__PURE__ */ vue.defineComponent({
59
- __name: "table-filter",
60
- props: {
61
- layout: {},
62
- filters: {}
63
- },
64
- emits: ["changeFilters", "removeFilter"],
65
- setup(__props, { emit: __emit }) {
66
- const formData = vue.ref();
67
- const properties = __props;
68
- const emits = __emit;
69
- vue.watch(
70
- () => properties.filters,
71
- () => {
72
- formData.value = {};
73
- properties.filters.forEach((filter) => {
74
- formData.value[filter.key] = filter.value;
75
- });
76
- },
77
- { immediate: true }
78
- );
79
- const onResetFilters = () => {
80
- emits("changeFilters", {});
81
- };
82
- const removeFilter = (filter) => {
83
- formData.value[filter.key] = void 0;
84
- emits("changeFilters", formData.value);
85
- };
86
- return (_ctx, _cache) => {
87
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$8, [
88
- vue.createElementVNode("div", _hoisted_2$2, [
89
- __props.filters.length ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Btn), {
90
- key: 0,
91
- size: "xs",
92
- outline: true,
93
- onClick: onResetFilters
94
- }, {
95
- default: vue.withCtx(() => [..._cache[0] || (_cache[0] = [
96
- vue.createTextVNode(" Reset all filters ", -1)
97
- ])]),
98
- _: 1
99
- })) : vue.createCommentVNode("", true)
100
- ]),
101
- vue.createElementVNode("div", _hoisted_3$1, [
102
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.filters, (filter) => {
103
- return vue.openBlock(), vue.createBlock(vue.unref(ui.BtnBadge), {
104
- key: filter.key,
105
- icon: vue.unref(ui.IconEnum).Close,
106
- onClick: ($event) => removeFilter(filter)
107
- }, {
108
- default: vue.withCtx(() => [
109
- vue.createTextVNode(vue.toDisplayString(filter.label) + ": " + vue.toDisplayString(filter.value), 1)
110
- ]),
111
- _: 2
112
- }, 1032, ["icon", "onClick"]);
113
- }), 128))
114
- ])
115
- ]);
116
- };
117
- }
1
+ var _ghentcdh_crouton_forms_vue = require("@ghentcdh/crouton-forms-vue");
2
+ Object.keys(_ghentcdh_crouton_forms_vue).forEach(function(k) {
3
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
4
+ enumerable: true,
5
+ get: function() {
6
+ return _ghentcdh_crouton_forms_vue[k];
7
+ }
8
+ });
118
9
  });
119
- const TableComponentProperties = {
120
- id: { type: String, required: true },
121
- uiSchema: { type: Object, required: true },
122
- schema: { type: Object, required: true },
123
- filterUiSchema: { type: Object },
124
- filterSchema: { type: Object },
125
- uri: { type: String, required: true },
126
- reload: { type: Number },
127
- actions: { type: Array }
128
- };
129
- const TableComponentEmits = ["delete", "edit"];
130
- class TableStore {
131
- constructor() {
132
- this.route = vueRouter.useRoute();
133
- this.router = vueRouter.useRouter();
134
- this.requestData = vue.ref(jsonFormsCore.RequestSchema.parse(this.route.query));
135
- this._reload = vue.ref(Date.now());
136
- this.loading = vue.ref(true);
137
- this.uri = vue.ref("");
138
- this.data = core.computedAsync(async () => {
139
- this._reload.value;
140
- if (!this.uri.value) return null;
141
- this.loading.value = true;
142
- if (this.requestData.value.page < 1) {
143
- this.requestData.value.page = 1;
144
- }
145
- const response = await toolsVue.useApi().get(this.uri.value, {
146
- params: this.requestData.value
147
- }).catch((error) => {
148
- console.error(error);
149
- return { data: [], request: { totalPages: 1, page: 1 } };
150
- }).finally(() => this.loading.value = false);
151
- const data = response.data;
152
- if (data.request.totalPages < data.request.page) {
153
- this.updateRequest({ page: data.request.totalPages });
154
- }
155
- return data;
156
- });
157
- this.pageData = vue.computed(() => {
158
- const request = this.data.value?.request ?? {
159
- count: 0,
160
- pageSize: 1,
161
- page: 1
162
- };
163
- return {
164
- count: request.count,
165
- pageSize: request.pageSize,
166
- page: request.page
167
- };
168
- });
169
- this.tableData = vue.computed(() => {
170
- const d = this.data.value;
171
- if (!d) return [];
172
- if (this.loading.value) return [];
173
- return d.data ?? [];
174
- });
175
- this.init = (url) => {
176
- this.uri.value = url;
177
- };
178
- this.updateRequest = (data) => {
179
- this.requestData.value = { ...this.requestData.value, ...data };
180
- this.router.replace({
181
- query: {
182
- ...this.route.query,
183
- ...this.requestData.value
184
- }
185
- });
186
- };
187
- this.sort = (id) => {
188
- const sortDir = this.requestData.value.sort === id && this.requestData.value.sortDir === "asc" ? "desc" : "asc";
189
- this.updateRequest({ sort: id, sortDir });
190
- };
191
- this.updateFilters = (filters) => {
192
- const filter = [];
193
- Object.entries(filters).forEach(([key, value]) => {
194
- if (!value) return;
195
- const operator = value?.operator || "contains";
196
- filter.push(`${key}:${value}:${operator}`);
197
- });
198
- this.updateRequest({ filter });
199
- };
200
- this.sorting = vue.computed(() => {
201
- const requestData = this.requestData.value;
202
- return {
203
- sortColumn: requestData.sort,
204
- sortDirection: requestData.sortDir ?? "asc"
205
- };
206
- });
207
- this.filters = vue.computed(
208
- () => jsonFormsCore.extractFilters(this.requestData.value.filter)
209
- );
210
- }
211
- get httpRequest() {
212
- return toolsVue.useApi();
213
- }
214
- reload() {
215
- this._reload.value = Date.now();
216
- }
217
- updatePage(page) {
218
- this.updateRequest({ page });
219
- }
220
- }
221
- const tableCache = /* @__PURE__ */ new Map();
222
- const useTableStore = (name) => {
223
- const tableStore = tableCache.get(name);
224
- if (tableStore) {
225
- return tableStore;
226
- }
227
- const newTableStore = new TableStore();
228
- tableCache.set(name, newTableStore);
229
- return newTableStore;
230
- };
231
- const _hoisted_1$7 = {
232
- key: 0,
233
- class: "mb-2"
234
- };
235
- const _sfc_main$g = /* @__PURE__ */ vue.defineComponent({
236
- __name: "table.component",
237
- props: TableComponentProperties,
238
- emits: TableComponentEmits,
239
- setup(__props, { emit: __emit }) {
240
- const properties = __props;
241
- const emit = __emit;
242
- vue.watch(
243
- () => properties.reload,
244
- () => {
245
- store.reload();
246
- }
247
- );
248
- let store = useTableStore(properties.id);
249
- vue.watch(
250
- () => properties.uri,
251
- () => {
252
- store.init(properties.uri);
253
- },
254
- { immediate: true }
255
- );
256
- const edit = (data) => {
257
- emit("edit", data);
258
- };
259
- const deleteFn = (data) => {
260
- emit("delete", data);
261
- };
262
- const components = {
263
- TextCell: ui.TextCell,
264
- BooleanCell: ui.BooleanCell
265
- };
266
- const displayColumns = vue.computed(() => {
267
- return properties.uiSchema.elements.map((e) => {
268
- const element = e;
269
- const def = jsonFormsCore.findColumnDef(element, properties.schema);
270
- const type = lodashEs.isArray(def.type) ? def.type[0] : def.type;
271
- let component;
272
- if (element.options?.format && element.options.format in components) {
273
- component = components[element.options.format];
274
- } else {
275
- component = components[element.type];
276
- }
277
- if (!component) console.warn("No component found for type", element.type);
278
- return {
279
- ...def,
280
- type,
281
- component
282
- };
283
- });
284
- });
285
- const onChangeFilters = (filters) => {
286
- store.updateFilters(filters);
287
- };
288
- const onUpdatePage = (page) => {
289
- store.updatePage(page);
290
- };
291
- const onSort = (id) => {
292
- store.sort(id);
293
- };
294
- const sort = vue.computed(() => {
295
- return store.sorting.value ?? { orderBy: "", ascending: 1 };
296
- });
297
- return (_ctx, _cache) => {
298
- return vue.openBlock(), vue.createElementBlock("div", null, [
299
- _ctx.filterUiSchema && _ctx.filterSchema ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$7, [
300
- vue.createVNode(_sfc_main$h, {
301
- layout: { uiSchema: _ctx.filterUiSchema, schema: _ctx.filterSchema },
302
- filters: vue.unref(store).filters.value,
303
- onChangeFilters
304
- }, null, 8, ["layout", "filters"])
305
- ])) : vue.createCommentVNode("", true),
306
- vue.createElementVNode("div", null, [
307
- vue.createVNode(vue.unref(ui.Table), {
308
- "display-columns": displayColumns.value,
309
- sort: sort.value,
310
- page: vue.unref(store).pageData.value,
311
- loading: vue.unref(store).loading.value,
312
- data: vue.unref(store).tableData.value,
313
- actions: _ctx.actions,
314
- onUpdatePage,
315
- onDelete: deleteFn,
316
- onEdit: edit,
317
- onSort
318
- }, null, 8, ["display-columns", "sort", "page", "loading", "data", "actions"])
319
- ])
320
- ]);
321
- };
322
- }
323
- });
324
- const createRepository = (formSchemaModel, httpRequest, options = {}) => {
325
- const notificationEntity = options.notification?.entityType || "entity";
326
- const notificationStore = options.notification?.notification ?? null;
327
- const getDataUri = (...suffix) => {
328
- return [formSchemaModel.uri, ...suffix].join("/");
329
- };
330
- const handleSuccess = (message) => {
331
- notificationStore?.success(message);
332
- };
333
- const handleError = (error, message) => {
334
- console.error(error);
335
- notificationStore?.error(message);
336
- throw new Error(error);
337
- };
338
- const create = (object, options2) => {
339
- return httpRequest.post(getDataUri(), object, options2).then((response) => {
340
- handleSuccess(`Created ${notificationEntity}`);
341
- return response.data;
342
- }).catch((response) => {
343
- handleError(response, `Failed to create ${notificationEntity}`);
344
- });
345
- };
346
- const patch = (id, object, options2) => {
347
- return httpRequest.patch(getDataUri(id), object, options2).then((response) => {
348
- handleSuccess(`Saved ${notificationEntity}`);
349
- return response.data;
350
- }).catch((response) => {
351
- handleError(response, `Failed to save ${notificationEntity}`);
352
- });
353
- };
354
- const get = (id, options2) => {
355
- return httpRequest.get(getDataUri(id), options2).then((response) => {
356
- return response.data;
357
- }).catch((response) => {
358
- handleError(response, "Failed to load data");
359
- });
360
- };
361
- const _delete = (id, options2) => {
362
- return httpRequest.delete(getDataUri(id), options2).then((response) => {
363
- handleSuccess(`${notificationEntity} deleted`);
364
- return response;
365
- }).catch((response) => {
366
- handleError(response, `Failed to delete ${notificationEntity}`);
367
- });
368
- };
369
- const createMulti = (objects, options2) => {
370
- return Promise.all(
371
- objects.map((object) => httpRequest.post(getDataUri(), object, options2))
372
- ).then((response) => {
373
- handleSuccess(`Created ${notificationEntity}`);
374
- return response.data;
375
- }).catch((response) => {
376
- handleError(response, `Failed to save ${notificationEntity}`);
377
- });
378
- };
379
- return { create, patch, createMulti, delete: _delete, get };
380
- };
381
- const createFormEvents = (dispatch) => ({
382
- dispatch
383
- });
384
- const FORM_EVENTS_KEY = /* @__PURE__ */ Symbol("json-forms:events");
385
- const provideFormEvents = (dispatch) => {
386
- const events = createFormEvents(dispatch);
387
- vue.provide(FORM_EVENTS_KEY, events);
388
- return events;
389
- };
390
- const useFormEvents = () => {
391
- return vue.inject(
392
- FORM_EVENTS_KEY,
393
- createFormEvents(() => {
394
- })
395
- );
396
- };
397
- const errorPatterns = [
398
- [/^Invalid input: expected \w+, received undefined$/, "This field is required"],
399
- [/^Invalid input: expected \w+, received null$/, "This field is required"],
400
- [/^Expected string, received/, "Invalid value"],
401
- [/^String must contain at least (\d+)/, "Must be at least $1 characters"],
402
- [/^Number must be greater than or equal to (\d+)/, "Minimum value is $1"],
403
- [/^Number must be less than or equal to (\d+)/, "Maximum value is $1"]
404
- ];
405
- const formatError = (message) => {
406
- if (!message) return void 0;
407
- for (const [pattern, replacement] of errorPatterns) {
408
- if (pattern.test(message)) {
409
- return message.replace(pattern, replacement);
410
- }
411
- }
412
- return message;
413
- };
414
- const registerZodErrorMap = () => {
415
- zod.z.config({
416
- customError: (issue) => {
417
- if (issue.code === "invalid_type" && issue.received === "undefined") {
418
- return { message: "This field is required" };
419
- }
420
- if (issue.code === "invalid_type" && issue.received === "null") {
421
- return { message: "This field is required" };
422
- }
423
- if (issue.code === "too_small") {
424
- const i = issue;
425
- if (i.type === "string" && i.minimum === 1) {
426
- return { message: "This field is required" };
427
- }
428
- if (i.type === "string") {
429
- return { message: `Must be at least ${i.minimum} characters` };
430
- }
431
- }
432
- if (issue.code === "too_big") {
433
- const i = issue;
434
- if (i.type === "string") {
435
- return { message: `Must be at most ${i.maximum} characters` };
436
- }
437
- }
438
- return { message: issue.message };
439
- }
440
- });
441
- };
442
- function findRenderer(registry, uischema, schema) {
443
- let best = null;
444
- for (const entry of registry) {
445
- const rank = entry.tester(uischema, schema);
446
- if (rank > -1 && (!best || rank > best.rank)) {
447
- best = { rank, renderer: entry.renderer };
448
- }
449
- }
450
- return best?.renderer ?? null;
451
- }
452
- const scopeToPath = (scope) => {
453
- if (!scope) return "";
454
- return scope.replace(/^#\//, "").split("/").filter((s) => s !== "properties").join(".");
455
- };
456
- const resolveSchema = (root, scope) => {
457
- const segments = scope.replace(/^#\//, "").split("/").filter(Boolean);
458
- return segments.reduce((acc, key) => acc?.[key], root);
459
- };
460
- const _hoisted_1$6 = {
461
- key: 1,
462
- class: "text-error text-xs"
463
- };
464
- const _sfc_main$f = /* @__PURE__ */ vue.defineComponent({
465
- __name: "Dispatch",
466
- props: {
467
- uischema: {},
468
- schema: {},
469
- pathPrefix: { default: void 0 }
470
- },
471
- setup(__props) {
472
- const props = __props;
473
- const registry = vue.inject("renderers");
474
- const rootSchema = vue.inject("rootSchema");
475
- const parentPrefix = vue.inject("pathPrefix", "");
476
- const effectivePrefix = props.pathPrefix ?? parentPrefix;
477
- if (props.pathPrefix !== void 0) {
478
- vue.provide("pathPrefix", effectivePrefix);
479
- }
480
- const resolved = vue.computed(() => {
481
- const u = props.uischema;
482
- if (!u.scope) return props.schema;
483
- const fromRoot = resolveSchema(rootSchema, u.scope);
484
- if (fromRoot) return fromRoot;
485
- return resolveSchema(props.schema, u.scope) ?? props.schema;
486
- });
487
- const renderer = vue.computed(
488
- () => findRenderer(registry, props.uischema, resolved.value)
489
- );
490
- return (_ctx, _cache) => {
491
- return renderer.value ? (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(renderer.value), {
492
- key: 0,
493
- uischema: __props.uischema,
494
- schema: resolved.value
495
- }, null, 8, ["uischema", "schema"])) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$6, " No renderer for " + vue.toDisplayString(__props.uischema.scope ?? __props.uischema.type), 1));
496
- };
497
- }
498
- });
499
- const JsonFormComponentProperties = {
500
- /** Unique identifier used to namespace the form element. */
501
- id: { type: String, required: true },
502
- /** HTML name attribute for the form. */
503
- name: { type: String, default: "form" },
504
- /** JSON schema describing the shape of the form data. */
505
- schema: { type: Object, required: true },
506
- /** UI schema describing the layout and controls. */
507
- uiSchema: { type: Object, required: true },
508
- /** Disable all form controls. */
509
- disabled: { type: Boolean, default: false },
510
- /** Current form data object. */
511
- formData: { type: Object, default: () => ({}) },
512
- /** When validation errors are shown (`'onBlur'`, `'onChange'`, `'onSubmit'`, `'always'`). */
513
- errorMode: {
514
- type: String,
515
- default: "onChanges"
516
- }
517
- };
518
- const JsonFormComponentEmits = [
519
- /** Emitted when form data changes. */
520
- "change",
521
- /** Emitted on form submission. */
522
- "submit",
523
- /** Emitted when validation errors change. */
524
- "errors",
525
- /** Emitted when form validity changes. */
526
- "valid",
527
- /** Emitted when a custom renderer dispatches a form event. */
528
- "events"
529
- ];
530
- const ERROR_MODE_KEY = /* @__PURE__ */ Symbol("errorMode");
531
- const FORM_SUBMITTED_KEY = /* @__PURE__ */ Symbol("formSubmitted");
532
- const _hoisted_1$5 = { class: "flex-1" };
533
- const _hoisted_2$1 = { key: 0 };
534
- const _hoisted_3 = {
535
- key: 0,
536
- class: "text-sm text-base-content/50"
537
- };
538
- const _hoisted_4 = { key: 1 };
539
- const _sfc_main$e = /* @__PURE__ */ vue.defineComponent({
540
- __name: "ArrayRenderer",
541
- props: {
542
- uischema: {},
543
- schema: {}
544
- },
545
- setup(__props) {
546
- const props = __props;
547
- const parentPrefix = vue.inject("pathPrefix", "");
548
- const scope = props.uischema.scope;
549
- const scopePath = scopeToPath(scope);
550
- const path = parentPrefix ? `${parentPrefix}.${scopePath}` : scopePath;
551
- const rootSchema = vue.inject("rootSchema");
552
- const arraySchema = resolveSchema(rootSchema, scope);
553
- const itemSchema = arraySchema?.items ?? {};
554
- const { fields, push, remove } = veeValidate.useFieldArray(path);
555
- if (fields.value.length === 0) {
556
- push({});
557
- }
558
- const opts = props.uischema.options ?? {};
559
- const layout = opts.layout ?? "column";
560
- const showActions = vue.computed(() => !opts.hideActions);
561
- const detail = vue.computed(
562
- () => props.uischema._detail ?? opts.detail
563
- );
564
- const childElements = vue.computed(() => {
565
- if (!detail.value) {
566
- return props.uischema.elements ?? [];
567
- }
568
- const type = detail.value.type;
569
- if (type && type !== "Control") {
570
- return [detail.value];
571
- }
572
- return detail.value.elements ?? [detail.value];
573
- });
574
- return (_ctx, _cache) => {
575
- return vue.openBlock(), vue.createElementBlock("div", null, [
576
- vue.createElementVNode("div", {
577
- class: vue.normalizeClass([
578
- "flex gap-2",
579
- vue.unref(layout) === "row" ? "flex-row items-center" : "flex-col"
580
- ])
581
- }, [
582
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(fields), (entry, index2) => {
583
- return vue.openBlock(), vue.createElementBlock("div", {
584
- key: entry.key,
585
- class: "flex-1"
586
- }, [
587
- vue.createElementVNode("div", {
588
- class: vue.normalizeClass([
589
- "flex gap-2",
590
- vue.unref(layout) === "row" ? "flex-col" : "flex-row items-center"
591
- ])
592
- }, [
593
- vue.createElementVNode("div", _hoisted_1$5, [
594
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(childElements.value, (child, ci) => {
595
- return vue.openBlock(), vue.createBlock(_sfc_main$f, {
596
- key: ci,
597
- uischema: child,
598
- schema: vue.unref(itemSchema),
599
- "path-prefix": `${vue.unref(path)}[${index2}]`
600
- }, null, 8, ["uischema", "schema", "path-prefix"]);
601
- }), 128))
602
- ]),
603
- showActions.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$1, [
604
- vue.unref(fields).length > 1 ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Btn), {
605
- key: 0,
606
- icon: vue.unref(ui.IconEnum).Delete,
607
- outline: true,
608
- onClick: ($event) => vue.unref(remove)(index2)
609
- }, null, 8, ["icon", "onClick"])) : vue.createCommentVNode("", true)
610
- ])) : vue.createCommentVNode("", true)
611
- ], 2)
612
- ]);
613
- }), 128)),
614
- vue.unref(fields).length === 0 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3, " No data ")) : vue.createCommentVNode("", true),
615
- showActions.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4, [
616
- vue.createVNode(vue.unref(ui.Btn), {
617
- icon: vue.unref(ui.IconEnum).Plus,
618
- outline: true,
619
- onClick: _cache[0] || (_cache[0] = ($event) => vue.unref(push)({}))
620
- }, {
621
- default: vue.withCtx(() => [..._cache[1] || (_cache[1] = [
622
- vue.createTextVNode(" Add ", -1)
623
- ])]),
624
- _: 1
625
- }, 8, ["icon"])
626
- ])) : vue.createCommentVNode("", true)
627
- ], 2)
628
- ]);
629
- };
630
- }
631
- });
632
- const isAutoCompleteControl = testers.and(
633
- // uiTypeIs('Control'),
634
- testers.optionIs("format", jsonFormsCore.ControlType.autocomplete)
635
- );
636
- const isTextAreaControl = testers.and(
637
- core$1.uiTypeIs("Control"),
638
- testers.optionIs("format", jsonFormsCore.ControlType.textArea)
639
- );
640
- const isStringFormat = testers.and(
641
- core$1.uiTypeIs("Control"),
642
- testers.or(testers.optionIs("format", jsonFormsCore.ControlType.string), testers.schemaTypeIs("string"))
643
- );
644
- const isMarkdownControl = testers.and(
645
- core$1.uiTypeIs("Control"),
646
- testers.optionIs("format", jsonFormsCore.ControlType.markdown)
647
- );
648
- const isArrayRenderer = testers.and(
649
- testers.schemaTypeIs("array")
650
- // optionIs('format', ControlType.array),
651
- );
652
- const isMultiselectControl = testers.and(
653
- core$1.uiTypeIs("Control"),
654
- testers.optionIs("format", jsonFormsCore.ControlType.mutliSelect)
655
- );
656
- const isSelectControl = testers.and(
657
- core$1.uiTypeIs("Control"),
658
- testers.optionIs("format", jsonFormsCore.ControlType.select)
659
- );
660
- const isBooleanControl = testers.or(
661
- testers.isBooleanControl,
662
- testers.and(core$1.uiTypeIs("Control"), testers.optionIs("format", jsonFormsCore.ControlType.boolean))
663
- );
664
- const isNumberFormat = testers.and(
665
- core$1.uiTypeIs("Control"),
666
- testers.or(testers.optionIs("format", jsonFormsCore.ControlType.number), testers.schemaTypeIs("number"))
667
- );
668
- const isIntegerFormat = testers.and(
669
- core$1.uiTypeIs("Control"),
670
- testers.or(testers.optionIs("format", jsonFormsCore.ControlType.integer), testers.schemaTypeIs("integer"))
671
- );
672
- const arrayRenderers = [
673
- { tester: core$1.rankWith(12, isArrayRenderer), renderer: _sfc_main$e }
674
- ];
675
- const MethodSchema = zod.z.enum(["get", "post", "delete", "put", "patch"]);
676
- const OperationSchema = zod.z.object({
677
- uri: zod.z.string(),
678
- method: MethodSchema
679
- });
680
- const OperationsSchema = zod.z.string().or(OperationSchema);
681
- const BooleanOperationSchema = zod.z.boolean().or(OperationSchema).optional().default(false);
682
- const Operations = zod.z.object({
683
- findAll: BooleanOperationSchema,
684
- findOne: BooleanOperationSchema,
685
- create: BooleanOperationSchema,
686
- update: BooleanOperationSchema,
687
- delete: BooleanOperationSchema,
688
- lookup: OperationsSchema.optional()
689
- });
690
- const OperationMap = {
691
- create: "post",
692
- delete: "delete",
693
- findAll: "get",
694
- findOne: "get",
695
- lookup: "get",
696
- update: "get"
697
- };
698
- const ResourceSchema = zod.z.object({
699
- id: zod.z.string(),
700
- uri: zod.z.string(),
701
- operations: Operations,
702
- schema: zod.z.object({
703
- ui: zod.z.any().optional(),
704
- data: zod.z.any()
705
- }).optional()
706
- }).transform((data) => {
707
- const schema = data.schema;
708
- if (schema) {
709
- if (!schema.ui) {
710
- schema.ui = jsonFormsCore.uiFromJsonSchema(schema.data);
711
- }
712
- }
713
- const operations = {};
714
- for (const k in OperationMap) {
715
- const key = k;
716
- const defaultOperation = OperationMap[key];
717
- const operation = data.operations[key];
718
- const mapResourceSchema = () => {
719
- if (lodashEs.isUndefined(operation) || operation === false) return null;
720
- if (operation === true)
721
- return { uri: data.uri, method: defaultOperation };
722
- if (typeof operation === "string")
723
- return { uri: operation, method: "get" };
724
- return {
725
- uri: operation.uri,
726
- method: operation.method ?? defaultOperation
727
- };
728
- };
729
- operations[key] = mapResourceSchema();
730
- }
731
- return {
732
- ...data,
733
- schema,
734
- operations
735
- };
736
- });
737
- const getResourceSchema = async (resourceUri, skipAuth) => {
738
- const fetch = skipAuth ? axios : toolsVue.useApi();
739
- return fetch.get(resourceUri).then((response) => {
740
- const resource = ResourceSchema.safeParse(response.data);
741
- if (!resource.success)
742
- throw new Error(`Invalid resource schema: ${resource.error}`);
743
- return resource.data;
744
- });
745
- };
746
- const useRemoteOption = (options) => {
747
- return {
748
- fetchOptions: (searchTerm, signal) => {
749
- const fetch = options.skipAuth ? axios : toolsVue.useApi();
750
- return fetch.get(`${options.uri}${searchTerm}`, { signal }).then((data) => data.data[options.dataField ?? "data"]);
751
- }
752
- };
753
- };
754
- const useResourceOptions = async (options) => {
755
- const resource = await getResourceSchema(
756
- options.resource,
757
- options.skipAuth ?? false
758
- );
759
- const fetch = options.skipAuth ? axios : toolsVue.useApi();
760
- const lookup = resource.operations.lookup;
761
- return {
762
- fetchOptions: (searchTerm, signal) => {
763
- const uri = lookup.uri.replace("{text}", searchTerm);
764
- const method = lookup.method;
765
- return fetch[method](uri, { signal }).then(
766
- (data) => data.data[options.dataField ?? "data"]
767
- );
768
- },
769
- enableCreate: !!resource.operations.create,
770
- form: resource.operations.create ? {
771
- ui_schema: resource.schema.ui,
772
- json_schema: resource.schema.data,
773
- title: `Create new ${resource.id}`,
774
- create: async (data) => {
775
- const create = resource.operations.create;
776
- return fetch[create.method](create.uri, data).then(
777
- (result) => result.data
778
- );
779
- }
780
- } : null
781
- };
782
- };
783
- const useFetchOptions = async (options) => {
784
- let config = {};
785
- if (options.uri)
786
- config = useRemoteOption(options);
787
- if (options.resource)
788
- config = await useResourceOptions(options);
789
- return {
790
- fetchOptions: null,
791
- labelKey: options.labelKey,
792
- valueKey: options.valueKey,
793
- enableCreate: options.enableCreate ?? false,
794
- form: null,
795
- ...config
796
- };
797
- };
798
- const checkRequired = (rootSchema, scope, fieldName) => {
799
- const segments = scope.replace(/^#\//, "").split("/");
800
- const parentSegments = segments.slice(0, -2);
801
- if (parentSegments.length === 0) {
802
- const req2 = rootSchema?.required;
803
- return Array.isArray(req2) && req2.includes(fieldName);
804
- }
805
- const parentScope = `#/${parentSegments.join("/")}`;
806
- const parentSchema = resolveSchema(rootSchema, parentScope);
807
- const req = parentSchema?.required;
808
- return Array.isArray(req) && req.includes(fieldName);
809
- };
810
- const useInputProps = (uischema, schema, field, options = {}) => {
811
- const rootSchema = vue.inject("rootSchema");
812
- const path = scopeToPath(uischema.scope);
813
- const { errorMessage, meta } = field;
814
- const opts = uischema.options ?? {};
815
- const labelFromScope = path.split(".").pop() ?? "";
816
- const isRequired = rootSchema ? checkRequired(rootSchema, uischema.scope, labelFromScope) : false;
817
- const s = schema ?? {};
818
- const inferredType = (() => {
819
- if (opts.format === "text") return "text";
820
- if (s.format === "email") return "email";
821
- if (s.format === "uri") return "url";
822
- if (s.type === "number" || s.type === "integer") return "number";
823
- return options.defaultType ?? "text";
824
- })();
825
- const styles = ui.mergeStyles(opts.styles);
826
- const errorMode = vue.inject(ERROR_MODE_KEY, vue.ref("onBlur"));
827
- const submitted = vue.inject(FORM_SUBMITTED_KEY, vue.ref(false));
828
- const shouldShowError = vue.computed(() => {
829
- if (!errorMessage.value) return false;
830
- switch (errorMode.value) {
831
- case "always":
832
- return true;
833
- case "onChange":
834
- return meta.dirty;
835
- case "onSubmit":
836
- return submitted.value;
837
- case "onBlur":
838
- default:
839
- return meta.touched;
840
- }
841
- });
842
- const width = opts.colspan || styles?.width === "full" ? "w-full" : opts.width ?? "min-w-input";
843
- return vue.computed(() => ({
844
- id: path,
845
- placeholder: opts.placeholder,
846
- description: s.description,
847
- errors: shouldShowError.value ? opts.errorMessage ?? formatError(errorMessage.value) : void 0,
848
- label: opts.label ?? labelFromScope.charAt(0).toUpperCase() + labelFromScope.slice(1),
849
- visible: opts.visible ?? true,
850
- required: isRequired,
851
- enabled: opts.readonly !== true,
852
- isFocused: false,
853
- isTouched: shouldShowError.value,
854
- hideLabel: opts.hideLabel ?? false,
855
- styles,
856
- width,
857
- type: inferredType,
858
- ...options.overrides
859
- }));
860
- };
861
- const useCustomControlBinding = ({
862
- useProps,
863
- setDefaultValue
864
- } = {}) => {
865
- return (uischema, schema, options = {}) => {
866
- const pathPrefix = vue.inject("pathPrefix", "");
867
- const scopePath = scopeToPath(uischema.scope);
868
- const path = pathPrefix ? `${pathPrefix}.${scopePath}` : scopePath;
869
- const field = veeValidate.useField(() => path);
870
- setDefaultValue?.(field);
871
- const wrapper = useInputProps(uischema, schema, field, options);
872
- const customWrapper = useProps?.(uischema, schema, field, options) ?? {
873
- value: {}
874
- };
875
- const onBlur = () => field.handleBlur(new Event("blur"));
876
- const onChange = () => field.handleChange(field.value.value);
877
- let initialized = false;
878
- vue.watch(field.value, (val) => {
879
- if (!initialized) {
880
- initialized = true;
881
- return;
882
- }
883
- field.handleChange(val);
884
- });
885
- return {
886
- wrapper: vue.computed(() => ({ ...wrapper.value, ...customWrapper.value })),
887
- value: field.value,
888
- field,
889
- onBlur,
890
- onChange,
891
- appliedOptions: vue.computed(
892
- () => uischema.options ?? {}
893
- )
894
- };
895
- };
896
- };
897
- const useControlBinding = (uischema, schema, options = {}) => {
898
- return useCustomControlBinding()(uischema, schema, options);
899
- };
900
- const useSelectInput = (...fields) => (uischema, schema, field) => {
901
- const opts = uischema.options ?? {};
902
- return vue.computed(() => {
903
- return lodashEs.pick(opts, fields);
904
- });
905
- };
906
- const useSelectBinding = useCustomControlBinding({
907
- useProps: useSelectInput("options", "labelKey", "valueKey")
908
- });
909
- const useAutocompleteBinding = useCustomControlBinding({
910
- useProps: useSelectInput(
911
- "options",
912
- "labelKey",
913
- "valueKey",
914
- "uri",
915
- "freeText",
916
- "enableCreate",
917
- "dataField",
918
- "skipAuth"
919
- )
920
- });
921
- const _sfc_main$d = /* @__PURE__ */ vue.defineComponent({
922
- __name: "FormModal",
923
- props: /* @__PURE__ */ vue.mergeModels(FormModalProperties, {
924
- "modelValue": {},
925
- "modelModifiers": {}
926
- }),
927
- emits: /* @__PURE__ */ vue.mergeModels(FormModalEmits, ["update:modelValue"]),
928
- setup(__props, { emit: __emit }) {
929
- const properties = __props;
930
- const id = `modal_${Math.floor(Math.random() * 1e3)}`;
931
- const formRef = vue.ref();
932
- const valid = vue.ref(false);
933
- const formData = vue.useModel(__props, "modelValue");
934
- const emits = __emit;
935
- if (properties.data) {
936
- formData.value = properties.data;
937
- }
938
- const onCancel = () => {
939
- formData.value = {};
940
- emits("closeModal", null);
941
- };
942
- const onChange = (data) => {
943
- formData.value = data;
944
- };
945
- const onSubmit = () => {
946
- formRef.value?.markSubmitted();
947
- if (!valid.value) return;
948
- emits("closeModal", { data: formData.value, valid: valid.value });
949
- };
950
- const onErrors = (errors) => {
951
- emits("errors", errors);
952
- valid.value = lodashEs.isEmpty(errors);
953
- };
954
- vue.watch(valid, (newValid, oldValid) => {
955
- if (newValid !== oldValid) {
956
- emits("valid", newValid);
957
- }
958
- });
959
- return (_ctx, _cache) => {
960
- return vue.openBlock(), vue.createBlock(vue.unref(ui.Modal), vue.mergeProps(properties, {
961
- open: true,
962
- "disable-close": false,
963
- width: _ctx.modalSize,
964
- onCloseModal: onCancel
965
- }), {
966
- content: vue.withCtx(() => [
967
- vue.renderSlot(_ctx.$slots, "content-before"),
968
- vue.createVNode(_sfc_main$2, {
969
- id: `modal-${id}`,
970
- ref_key: "formRef",
971
- ref: formRef,
972
- "form-data": formData.value,
973
- schema: _ctx.schema,
974
- "ui-schema": _ctx.uiSchema,
975
- "error-mode": _ctx.errorMode,
976
- onErrors,
977
- onChange,
978
- onEvents: _cache[0] || (_cache[0] = ($event) => emits("events", $event))
979
- }, null, 8, ["id", "form-data", "schema", "ui-schema", "error-mode"]),
980
- vue.renderSlot(_ctx.$slots, "content-after")
981
- ]),
982
- actions: vue.withCtx(() => [
983
- vue.createVNode(vue.unref(ui.Btn), {
984
- color: vue.unref(ui.Color).secondary,
985
- outline: true,
986
- "aria-label": "Cancel",
987
- onClick: onCancel
988
- }, {
989
- default: vue.withCtx(() => [..._cache[1] || (_cache[1] = [
990
- vue.createTextVNode(" Cancel ", -1)
991
- ])]),
992
- _: 1
993
- }, 8, ["color"]),
994
- vue.createVNode(vue.unref(ui.Btn), {
995
- disabled: !valid.value,
996
- "aria-label": "Save",
997
- onClick: onSubmit
998
- }, {
999
- default: vue.withCtx(() => [..._cache[2] || (_cache[2] = [
1000
- vue.createTextVNode(" Save ", -1)
1001
- ])]),
1002
- _: 1
1003
- }, 8, ["disabled"])
1004
- ]),
1005
- _: 3
1006
- }, 16, ["width"]);
1007
- };
1008
- }
1009
- });
1010
- class JsonFormModalService {
1011
- static openModal({
1012
- initialData,
1013
- modalTitle,
1014
- schema,
1015
- uiSchema,
1016
- modalSize,
1017
- onClose,
1018
- onEvents
1019
- }) {
1020
- ui.ModalService.openModal({
1021
- component: _sfc_main$d,
1022
- props: {
1023
- schema,
1024
- uiSchema,
1025
- modalSize,
1026
- data: initialData ?? {},
1027
- modalTitle,
1028
- onClose,
1029
- onEvents
1030
- }
1031
- });
1032
- }
1033
- }
1034
- const _sfc_main$c = /* @__PURE__ */ vue.defineComponent({
1035
- __name: "AutocompleteControlRenderer",
1036
- props: {
1037
- uischema: {},
1038
- schema: {}
1039
- },
1040
- setup(__props) {
1041
- const props = __props;
1042
- const {
1043
- wrapper,
1044
- value,
1045
- field,
1046
- onBlur,
1047
- onChange: onFieldChange,
1048
- appliedOptions
1049
- } = useAutocompleteBinding(props.uischema, props.schema);
1050
- const fetchOptions = core.computedAsync(async () => {
1051
- const config = await useFetchOptions(
1052
- appliedOptions.value
1053
- );
1054
- return config;
1055
- });
1056
- const onChange = (val) => {
1057
- setValue(val);
1058
- onFieldChange();
1059
- };
1060
- const formEvents = useFormEvents();
1061
- const path = scopeToPath(props.uischema.scope);
1062
- const setValue = (result) => {
1063
- if (!result || !fetchOptions.value) {
1064
- field.setValue(result);
1065
- return;
1066
- }
1067
- const { valueKey, labelKey } = fetchOptions.value;
1068
- const keys = [valueKey, labelKey].filter(Boolean);
1069
- if (keys.length === 0) {
1070
- field.setValue(result);
1071
- return;
1072
- }
1073
- const stripped = lodashEs.pick(result, keys);
1074
- field.setValue(stripped);
1075
- };
1076
- const onCreate = () => {
1077
- if (fetchOptions.value?.enableCreate === false) return;
1078
- const form = fetchOptions.value.form;
1079
- if (form) {
1080
- JsonFormModalService.openModal({
1081
- schema: form.json_schema,
1082
- uiSchema: form.ui_schema,
1083
- modalTitle: `Create new ${wrapper.value.label}`,
1084
- onClose: (result) => {
1085
- if (!result || !result.valid) return;
1086
- form.create(result.data).then((res) => {
1087
- setValue(res);
1088
- });
1089
- }
1090
- });
1091
- return;
1092
- }
1093
- formEvents.dispatch({
1094
- event: "create",
1095
- type: path,
1096
- data: value.value,
1097
- onSuccess: setValue
1098
- });
1099
- };
1100
- return (_ctx, _cache) => {
1101
- return vue.unref(fetchOptions) ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Autocomplete), vue.mergeProps({ key: 0 }, vue.unref(wrapper), {
1102
- "model-value": vue.unref(value),
1103
- "fetch-options": vue.unref(fetchOptions).fetchOptions,
1104
- "label-key": vue.unref(fetchOptions).labelKey,
1105
- "value-key": vue.unref(fetchOptions).valueKey,
1106
- "enable-create": vue.unref(fetchOptions).enableCreate,
1107
- onChange,
1108
- onBlur: vue.unref(onBlur),
1109
- onCreate
1110
- }), null, 16, ["model-value", "fetch-options", "label-key", "value-key", "enable-create", "onBlur"])) : vue.createCommentVNode("", true);
1111
- };
1112
- }
1113
- });
1114
- const _sfc_main$b = /* @__PURE__ */ vue.defineComponent({
1115
- __name: "BooleanControlRenderer",
1116
- props: {
1117
- uischema: {},
1118
- schema: {}
1119
- },
1120
- setup(__props) {
1121
- const props = __props;
1122
- const useBooleanBinding = useCustomControlBinding({
1123
- setDefaultValue: (field2) => {
1124
- if (field2.value.value === void 0) field2.setValue(false);
1125
- }
1126
- });
1127
- const { wrapper, value, field, onBlur, onChange: onFieldChange } = useBooleanBinding(props.uischema, props.schema);
1128
- const onChange = (val) => {
1129
- field.setValue(Boolean(val) ?? false);
1130
- onFieldChange();
1131
- };
1132
- return (_ctx, _cache) => {
1133
- return vue.openBlock(), vue.createBlock(vue.unref(ui.Checkbox), vue.mergeProps(vue.unref(wrapper), {
1134
- "model-value": vue.unref(value),
1135
- onChange,
1136
- onBlur: vue.unref(onBlur)
1137
- }), null, 16, ["model-value", "onBlur"]);
1138
- };
1139
- }
1140
- });
1141
- const _sfc_main$a = /* @__PURE__ */ vue.defineComponent({
1142
- __name: "MarkdownControlRenderer",
1143
- props: {
1144
- uischema: {},
1145
- schema: {}
1146
- },
1147
- setup(__props) {
1148
- const props = __props;
1149
- const {
1150
- wrapper,
1151
- value,
1152
- field,
1153
- onBlur,
1154
- onChange: onFieldChange
1155
- } = useControlBinding(props.uischema, props.schema);
1156
- const onChange = (val) => {
1157
- field.setValue(val);
1158
- onFieldChange();
1159
- };
1160
- return (_ctx, _cache) => {
1161
- return vue.openBlock(), vue.createBlock(vue.unref(ui.Markdown), vue.mergeProps(vue.unref(wrapper), {
1162
- "model-value": vue.unref(value),
1163
- onChange,
1164
- onBlur: vue.unref(onBlur)
1165
- }), null, 16, ["model-value", "onBlur"]);
1166
- };
1167
- }
1168
- });
1169
- const _sfc_main$9 = /* @__PURE__ */ vue.defineComponent({
1170
- __name: "MultiSelectControlRenderer",
1171
- props: {
1172
- uischema: {},
1173
- schema: {}
1174
- },
1175
- setup(__props) {
1176
- const props = __props;
1177
- const {
1178
- wrapper,
1179
- value,
1180
- field,
1181
- onBlur,
1182
- onChange: onFieldChange
1183
- } = useSelectBinding(props.uischema, props.schema);
1184
- const onChange = (val) => {
1185
- field.setValue(val);
1186
- onFieldChange();
1187
- };
1188
- return (_ctx, _cache) => {
1189
- return vue.openBlock(), vue.createBlock(vue.unref(ui.MultiSelect), vue.mergeProps(vue.unref(wrapper), {
1190
- "model-value": vue.unref(value),
1191
- onChange,
1192
- onBlur: vue.unref(onBlur)
1193
- }), null, 16, ["model-value", "onBlur"]);
1194
- };
1195
- }
1196
- });
1197
- const _sfc_main$8 = /* @__PURE__ */ vue.defineComponent({
1198
- __name: "NumberControlRenderer",
1199
- props: {
1200
- uischema: {},
1201
- schema: {}
1202
- },
1203
- setup(__props) {
1204
- const props = __props;
1205
- const { wrapper, value, onBlur, onChange } = useControlBinding(
1206
- props.uischema,
1207
- props.schema,
1208
- { defaultType: "number" }
1209
- );
1210
- return (_ctx, _cache) => {
1211
- return vue.openBlock(), vue.createBlock(vue.unref(ui.InputNumber), vue.mergeProps(vue.unref(wrapper), {
1212
- modelValue: vue.unref(value),
1213
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.isRef(value) ? value.value = $event : null),
1214
- steps: 0.01,
1215
- onBlur: vue.unref(onBlur),
1216
- onChange: vue.unref(onChange)
1217
- }), null, 16, ["modelValue", "onBlur", "onChange"]);
1218
- };
1219
- }
1220
- });
1221
- const _sfc_main$7 = /* @__PURE__ */ vue.defineComponent({
1222
- __name: "SelectControlRenderer",
1223
- props: {
1224
- uischema: {},
1225
- schema: {}
1226
- },
1227
- setup(__props) {
1228
- const props = __props;
1229
- const {
1230
- wrapper,
1231
- value,
1232
- field,
1233
- onBlur,
1234
- onChange: onFieldChange,
1235
- appliedOptions
1236
- } = useSelectBinding(props.uischema, props.schema);
1237
- const selectOptions = vue.computed(() => {
1238
- return appliedOptions.options ?? [];
1239
- });
1240
- const onChange = (val) => {
1241
- field.setValue(val);
1242
- onFieldChange();
1243
- };
1244
- return (_ctx, _cache) => {
1245
- return vue.openBlock(), vue.createBlock(vue.unref(ui.SelectComponent), vue.mergeProps(vue.unref(wrapper), {
1246
- "model-value": vue.unref(value),
1247
- options: selectOptions.value,
1248
- onChange,
1249
- onBlur: vue.unref(onBlur)
1250
- }), null, 16, ["model-value", "options", "onBlur"]);
1251
- };
1252
- }
1253
- });
1254
- const _sfc_main$6 = /* @__PURE__ */ vue.defineComponent({
1255
- __name: "StringControlRenderer",
1256
- props: {
1257
- uischema: {},
1258
- schema: {}
1259
- },
1260
- setup(__props) {
1261
- const props = __props;
1262
- const { wrapper, value, onBlur, onChange } = useControlBinding(
1263
- props.uischema,
1264
- props.schema
1265
- );
1266
- return (_ctx, _cache) => {
1267
- return vue.openBlock(), vue.createBlock(vue.unref(ui.Input), vue.mergeProps(vue.unref(wrapper), {
1268
- modelValue: vue.unref(value),
1269
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.isRef(value) ? value.value = $event : null),
1270
- onBlur: vue.unref(onBlur),
1271
- onChange: vue.unref(onChange)
1272
- }), null, 16, ["modelValue", "onBlur", "onChange"]);
1273
- };
1274
- }
1275
- });
1276
- const _sfc_main$5 = /* @__PURE__ */ vue.defineComponent({
1277
- __name: "TextAreaControlRenderer",
1278
- props: {
1279
- uischema: {},
1280
- schema: {}
1281
- },
1282
- setup(__props) {
1283
- const props = __props;
1284
- const { wrapper, value, onBlur, onChange } = useControlBinding(
1285
- props.uischema,
1286
- props.schema
1287
- );
1288
- return (_ctx, _cache) => {
1289
- return vue.openBlock(), vue.createBlock(vue.unref(ui.Textarea), vue.mergeProps(vue.unref(wrapper), {
1290
- modelValue: vue.unref(value),
1291
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.isRef(value) ? value.value = $event : null),
1292
- onBlur: vue.unref(onBlur),
1293
- onChange: vue.unref(onChange)
1294
- }), null, 16, ["modelValue", "onBlur", "onChange"]);
1295
- };
1296
- }
1297
- });
1298
- const index = [
1299
- { tester: core$1.rankWith(10, isStringFormat), renderer: _sfc_main$6 },
1300
- {
1301
- tester: core$1.rankWith(11, isTextAreaControl),
1302
- renderer: _sfc_main$5
1303
- },
1304
- {
1305
- tester: core$1.rankWith(11, isMarkdownControl),
1306
- renderer: _sfc_main$a
1307
- },
1308
- { tester: core$1.rankWith(11, isBooleanControl), renderer: _sfc_main$b },
1309
- { tester: core$1.rankWith(11, isSelectControl), renderer: _sfc_main$7 },
1310
- {
1311
- tester: core$1.rankWith(11, isMultiselectControl),
1312
- renderer: _sfc_main$9
1313
- },
1314
- {
1315
- tester: core$1.rankWith(12, isAutoCompleteControl),
1316
- renderer: _sfc_main$c
1317
- },
1318
- {
1319
- tester: core$1.rankWith(12, isNumberFormat),
1320
- renderer: _sfc_main$8
1321
- },
1322
- {
1323
- tester: core$1.rankWith(12, isIntegerFormat),
1324
- renderer: _sfc_main$8
1325
- }
1326
- ];
1327
- const COLSPAN = {
1328
- 1: "col-span-1",
1329
- 2: "col-span-2",
1330
- 3: "col-span-3",
1331
- 4: "col-span-4",
1332
- 5: "col-span-5",
1333
- 6: "col-span-6",
1334
- 7: "col-span-7",
1335
- 8: "col-span-8",
1336
- 9: "col-span-9",
1337
- 10: "col-span-10",
1338
- 11: "col-span-11",
1339
- 12: "col-span-12"
1340
- };
1341
- const _hoisted_1$4 = { class: "flex flex-col gap-4" };
1342
- const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({
1343
- __name: "CollapseLayoutRenderer",
1344
- props: {
1345
- uischema: {},
1346
- schema: {}
1347
- },
1348
- setup(__props) {
1349
- const props = __props;
1350
- const pathPrefix = vue.inject("pathPrefix", "");
1351
- const opts = props.uischema.options ?? {};
1352
- const titleKeyField = opts.titleKey ? veeValidate.useFieldValue(
1353
- () => pathPrefix ? `${pathPrefix}.${opts.titleKey}` : opts.titleKey
1354
- ) : void 0;
1355
- const title = vue.computed(() => {
1356
- if (titleKeyField?.value) return titleKeyField.value;
1357
- return props.uischema.label ?? opts.title ?? "Details";
1358
- });
1359
- return (_ctx, _cache) => {
1360
- return vue.openBlock(), vue.createBlock(vue.unref(ui.Collapse), { title: title.value }, {
1361
- default: vue.withCtx(() => [
1362
- vue.createElementVNode("div", _hoisted_1$4, [
1363
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.uischema.elements, (child, i) => {
1364
- return vue.openBlock(), vue.createElementBlock("div", {
1365
- key: i,
1366
- class: vue.normalizeClass(vue.unref(COLSPAN)[child.options?.colspan ?? 12])
1367
- }, [
1368
- vue.createVNode(_sfc_main$f, {
1369
- uischema: child,
1370
- schema: __props.schema
1371
- }, null, 8, ["uischema", "schema"])
1372
- ], 2);
1373
- }), 128))
1374
- ])
1375
- ]),
1376
- _: 1
1377
- }, 8, ["title"]);
1378
- };
1379
- }
1380
- });
1381
- const _hoisted_1$3 = {
1382
- key: 1,
1383
- class: "flex flex-col gap-3"
1384
- };
1385
- const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({
1386
- __name: "LayoutRenderer",
1387
- props: {
1388
- uischema: {},
1389
- schema: {}
1390
- },
1391
- setup(__props) {
1392
- const props = __props;
1393
- const LAYOUT = {
1394
- GridLayout: "grid grid-cols-12 gap-3",
1395
- HorizontalLayout: "flex flex-row gap-3",
1396
- VerticalLayout: "flex flex-col gap-3"
1397
- };
1398
- const getLayout = vue.computed(() => LAYOUT[props.uischema.type]);
1399
- const isLayout = vue.computed(() => props.uischema.type in LAYOUT);
1400
- return (_ctx, _cache) => {
1401
- return isLayout.value ? (vue.openBlock(), vue.createElementBlock("div", {
1402
- key: 0,
1403
- class: vue.normalizeClass(getLayout.value)
1404
- }, [
1405
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.uischema.elements, (child, i) => {
1406
- return vue.openBlock(), vue.createElementBlock("div", {
1407
- key: i,
1408
- class: vue.normalizeClass(vue.unref(COLSPAN)[child.options?.colspan ?? 12])
1409
- }, [
1410
- vue.createVNode(_sfc_main$f, {
1411
- uischema: child,
1412
- schema: __props.schema
1413
- }, null, 8, ["uischema", "schema"])
1414
- ], 2);
1415
- }), 128))
1416
- ], 2)) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$3, " No Applicable Layout found "));
1417
- };
1418
- }
1419
- });
1420
- const isLayoutType = core$1.or(
1421
- core$1.uiTypeIs("GridLayout"),
1422
- core$1.uiTypeIs("HorizontalLayout"),
1423
- core$1.uiTypeIs("VerticalLayout")
1424
- );
1425
- const layoutRenderes = [
1426
- { tester: core$1.rankWith(10, isLayoutType), renderer: _sfc_main$3 },
1427
- {
1428
- tester: core$1.rankWith(10, core$1.uiTypeIs("CollapseLayout")),
1429
- renderer: _sfc_main$4
1430
- }
1431
- ];
1432
- const customRenderes = [layoutRenderes, index, arrayRenderers].flat();
1433
- const _hoisted_1$2 = ["id"];
1434
- const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
1435
- __name: "FormComponent",
1436
- props: JsonFormComponentProperties,
1437
- emits: JsonFormComponentEmits,
1438
- setup(__props, { expose: __expose, emit: __emit }) {
1439
- registerZodErrorMap();
1440
- const properties = __props;
1441
- const emits = __emit;
1442
- const zodSchema = vue.computed(() => {
1443
- if (!properties.schema) return void 0;
1444
- try {
1445
- const patched = jsonFormsCore.enforceRequiredStringMinLength(properties.schema);
1446
- return zod.fromJSONSchema(patched);
1447
- } catch {
1448
- return void 0;
1449
- }
1450
- });
1451
- const { values, errors, meta, setValues, validate } = veeValidate.useForm({
1452
- validationSchema: zodSchema,
1453
- initialValues: properties.formData
1454
- });
1455
- vue.provide("renderers", customRenderes);
1456
- vue.provide("rootSchema", properties.schema);
1457
- vue.provide("styles", ui.myStyles);
1458
- const submitted = vue.ref(false);
1459
- vue.provide(ERROR_MODE_KEY, vue.toRef(properties, "errorMode"));
1460
- vue.provide(FORM_SUBMITTED_KEY, submitted);
1461
- vue.onMounted(async () => {
1462
- const result = await validate();
1463
- emits("valid", result.valid);
1464
- });
1465
- provideFormEvents((payload) => {
1466
- emits("events", payload);
1467
- });
1468
- let syncing = false;
1469
- vue.watch(
1470
- () => properties.formData,
1471
- (newData) => {
1472
- if (!newData) return;
1473
- if (JSON.stringify(newData) === JSON.stringify(vue.toRaw(values))) return;
1474
- syncing = true;
1475
- setValues(newData);
1476
- vue.nextTick(() => {
1477
- syncing = false;
1478
- });
1479
- },
1480
- { deep: true }
1481
- );
1482
- vue.watch(
1483
- values,
1484
- (newValues) => {
1485
- if (syncing) return;
1486
- const isValid = meta.value.valid;
1487
- emits("valid", isValid);
1488
- emits("change", vue.toRaw(newValues));
1489
- },
1490
- { deep: true }
1491
- );
1492
- vue.watch(
1493
- errors,
1494
- (newErrors) => {
1495
- const errorList = Object.entries(newErrors).filter(([, msg]) => !!msg).map(([path, message]) => ({ path, message }));
1496
- emits("errors", errorList);
1497
- },
1498
- { deep: true }
1499
- );
1500
- const onSubmit = () => {
1501
- submitted.value = true;
1502
- emits("submit", {
1503
- data: vue.toRaw(values),
1504
- valid: meta.value.valid
1505
- });
1506
- };
1507
- const markSubmitted = () => {
1508
- submitted.value = true;
1509
- };
1510
- __expose({ markSubmitted });
1511
- return (_ctx, _cache) => {
1512
- return vue.openBlock(), vue.createElementBlock("form", {
1513
- id: _ctx.id,
1514
- onSubmit: vue.withModifiers(onSubmit, ["prevent"])
1515
- }, [
1516
- vue.createVNode(_sfc_main$f, {
1517
- uischema: _ctx.uiSchema,
1518
- schema: _ctx.schema
1519
- }, null, 8, ["uischema", "schema"])
1520
- ], 40, _hoisted_1$2);
1521
- };
1522
- }
1523
- });
1524
- const FormWithActionsProperties = {
1525
- /** Unique identifier used to namespace the inner form element. */
1526
- id: { type: String, required: true },
1527
- /** Title shown when creating a new record. */
1528
- createTitle: { type: String, required: true },
1529
- /** Title shown when editing an existing record. Falls back to `createTitle` when omitted. */
1530
- updateTitle: { type: String },
1531
- /** JSON schema describing the shape of the form data. */
1532
- schema: { type: Object },
1533
- /** UI schema describing the layout and controls. */
1534
- uiSchema: { type: Object },
1535
- /** REST endpoint used by `FormStore` to persist data. When omitted the form emits `submit` instead. */
1536
- uri: { type: String },
1537
- /** Enable vertical scrolling inside the form area. */
1538
- scrollable: { type: Boolean, default: false },
1539
- /** Stretch the collapse wrapper to full height. */
1540
- fullHeight: { type: Boolean, default: false },
1541
- /** Two-way bound form data object. */
1542
- modelValue: { type: Object, default: () => ({}) },
1543
- /** When validation errors are shown (`'onBlur'`, `'onChange'`, `'onSubmit'`, `'always'`). */
1544
- errorMode: {
1545
- type: String,
1546
- default: "onBlur"
1547
- }
1548
- };
1549
- const FormWithActionsEmits = [
1550
- /** Emitted when `modelValue` changes. */
1551
- "update:modelValue",
1552
- /** Emitted after a successful `FormStore.save()`. */
1553
- "success",
1554
- /** Emitted on submit when no `uri` is provided. */
1555
- "submit",
1556
- /** Emitted whenever form validity changes. */
1557
- "valid",
1558
- /** Emitted when a custom renderer dispatches a form event. */
1559
- "events",
1560
- /** Emitted when validation errors change. */
1561
- "errors",
1562
- /** Emitted when the user cancels editing an existing record. */
1563
- "cancel"
1564
- ];
1565
- class FormStore {
1566
- constructor(uri) {
1567
- this.uri = uri;
1568
- }
1569
- async delete(data) {
1570
- return toolsVue.useApi().delete(`${this.uri}/${data.id}`).then(() => {
1571
- ui.NotificationService.success("Data deleted");
1572
- }).catch((error) => {
1573
- console.error(error);
1574
- ui.NotificationService.error("Error deleting data");
1575
- });
1576
- }
1577
- async save(id, data) {
1578
- if (!this.uri) return;
1579
- const promise = id ? toolsVue.useApi().patch(`${this.uri}/${id}`, data) : toolsVue.useApi().post(this.uri, data);
1580
- return promise.then((response) => {
1581
- ui.NotificationService.success("Data saved");
1582
- return response.data;
1583
- }).catch((error) => {
1584
- console.error(error);
1585
- ui.NotificationService.error("Error saving data");
1586
- });
1587
- }
1588
- }
1589
- const _hoisted_1$1 = { class: "flex justify-end gap-2 p-2 mt-2 border-t border-gray-300 z-[30] shrink-0" };
1590
- const _hoisted_2 = { class: "flex justify-end gap-2" };
1591
- const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
1592
- __name: "FormWithActions",
1593
- props: FormWithActionsProperties,
1594
- emits: FormWithActionsEmits,
1595
- setup(__props, { emit: __emit }) {
1596
- const properties = __props;
1597
- const emits = __emit;
1598
- const formRef = vue.ref();
1599
- const formData = vue.ref(properties.modelValue);
1600
- const initialFormData = vue.ref(structuredClone(vue.toRaw(properties.modelValue)));
1601
- const recordId = vue.ref(properties.modelValue?.id ?? null);
1602
- const valid = vue.ref(false);
1603
- vue.watch(
1604
- () => properties.modelValue,
1605
- (newValue) => {
1606
- if (JSON.stringify(vue.toRaw(newValue)) === JSON.stringify(vue.toRaw(formData.value))) return;
1607
- recordId.value = newValue?.id ?? null;
1608
- initialFormData.value = structuredClone(vue.toRaw(newValue));
1609
- formData.value = newValue;
1610
- }
1611
- );
1612
- const store = vue.computed(
1613
- () => properties.uri ? new FormStore(properties.uri) : null
1614
- );
1615
- const updateValue = (data) => {
1616
- formData.value = data;
1617
- emits("update:modelValue", data);
1618
- };
1619
- const save = () => {
1620
- formRef.value?.markSubmitted();
1621
- if (!valid.value) return;
1622
- if (store.value) {
1623
- store.value.save(recordId.value, formData.value).then((response) => {
1624
- emits("success", response);
1625
- });
1626
- } else {
1627
- emits("submit", formData.value);
1628
- }
1629
- };
1630
- const clear = () => {
1631
- formData.value = { id: null };
1632
- emits("update:modelValue", formData.value);
1633
- };
1634
- const cancel = () => {
1635
- formData.value = structuredClone(vue.toRaw(initialFormData.value));
1636
- emits("update:modelValue", formData.value);
1637
- emits("cancel");
1638
- };
1639
- const title = vue.computed(() => {
1640
- if (!properties.updateTitle) return properties.createTitle;
1641
- return recordId.value ? properties.updateTitle : properties.createTitle;
1642
- });
1643
- const onErrors = (errors) => {
1644
- emits("errors", errors);
1645
- valid.value = lodashEs.isEmpty(errors);
1646
- };
1647
- vue.watch(valid, (newValid, oldValid) => {
1648
- if (newValid !== oldValid) {
1649
- emits("valid", newValid);
1650
- }
1651
- });
1652
- return (_ctx, _cache) => {
1653
- return vue.openBlock(), vue.createBlock(vue.unref(ui.Collapse), {
1654
- title: title.value,
1655
- "height-full": _ctx.fullHeight,
1656
- scrollable: true
1657
- }, {
1658
- default: vue.withCtx(() => [
1659
- vue.createElementVNode("div", {
1660
- class: vue.normalizeClass(["flex flex-col", { "overflow-hidden h-full": _ctx.scrollable }])
1661
- }, [
1662
- vue.createElementVNode("div", {
1663
- class: vue.normalizeClass(["flex-1", { "overflow-y-auto overflow-x-hidden": _ctx.scrollable }])
1664
- }, [
1665
- vue.createVNode(_sfc_main$2, {
1666
- id: `form_${_ctx.id}`,
1667
- ref_key: "formRef",
1668
- ref: formRef,
1669
- "form-data": formData.value,
1670
- schema: _ctx.schema,
1671
- "ui-schema": _ctx.uiSchema,
1672
- "error-mode": _ctx.errorMode,
1673
- onChange: updateValue,
1674
- onSubmit: save,
1675
- onErrors,
1676
- onEvents: _cache[0] || (_cache[0] = ($event) => emits("events", $event))
1677
- }, null, 8, ["id", "form-data", "schema", "ui-schema", "error-mode"])
1678
- ], 2),
1679
- vue.createElementVNode("div", _hoisted_1$1, [
1680
- vue.createElementVNode("div", _hoisted_2, [
1681
- vue.renderSlot(_ctx.$slots, "actions"),
1682
- recordId.value ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Btn), {
1683
- key: 0,
1684
- "aria-label": "Cancel",
1685
- outline: true,
1686
- onClick: cancel
1687
- }, {
1688
- default: vue.withCtx(() => [..._cache[1] || (_cache[1] = [
1689
- vue.createTextVNode(" Cancel ", -1)
1690
- ])]),
1691
- _: 1
1692
- })) : (vue.openBlock(), vue.createBlock(vue.unref(ui.Btn), {
1693
- key: 1,
1694
- "aria-label": "Clear",
1695
- outline: true,
1696
- onClick: clear
1697
- }, {
1698
- default: vue.withCtx(() => [..._cache[2] || (_cache[2] = [
1699
- vue.createTextVNode(" Clear ", -1)
1700
- ])]),
1701
- _: 1
1702
- })),
1703
- vue.createVNode(vue.unref(ui.Btn), {
1704
- "aria-label": "Save",
1705
- color: vue.unref(ui.Color).primary,
1706
- disabled: !valid.value,
1707
- onClick: save
1708
- }, {
1709
- default: vue.withCtx(() => [..._cache[3] || (_cache[3] = [
1710
- vue.createTextVNode(" Save ", -1)
1711
- ])]),
1712
- _: 1
1713
- }, 8, ["color", "disabled"])
1714
- ])
1715
- ])
1716
- ], 2)
1717
- ]),
1718
- _: 3
1719
- }, 8, ["title", "height-full"]);
1720
- };
1721
- }
1722
- });
1723
- const FormWithTableProperties = {
1724
- /** Unique identifier used to namespace the inner table element. */
1725
- id: { type: String, required: true },
1726
- /** Heading displayed above the table. */
1727
- tableTitle: { type: String, required: true },
1728
- /** Title shown in the modal when creating a new record. */
1729
- createTitle: { type: String, required: true },
1730
- /** Title shown in the modal when editing a record. Falls back to `createTitle` when omitted. */
1731
- updateTitle: { type: String },
1732
- /** Override URI used to fetch table data. Defaults to `uri` when omitted. */
1733
- dataUri: { type: String },
1734
- /** Custom row actions rendered in the table. */
1735
- tableActions: { type: Array },
1736
- /** JSON Forms layout for the create/edit modal form. */
1737
- form: { type: Object },
1738
- /** JSON Forms layout for the table. */
1739
- table: { type: Object },
1740
- /** JSON Forms layout for the table filter. */
1741
- filter: { type: Object },
1742
- /** REST endpoint used by `FormStore` for CRUD operations. */
1743
- uri: { type: String },
1744
- /** Default data pre-filled when creating a new record. */
1745
- initialData: { type: Object, default: () => ({}) },
1746
- /** When validation errors are shown in the modal form. */
1747
- errorMode: {
1748
- type: String,
1749
- default: "onBlur"
1750
- }
1751
- };
1752
- const FormWithTableEmits = [
1753
- /** Emitted when a row is selected for editing (listener-based routing). */
1754
- "editData",
1755
- /** Emitted after a record is saved through the modal. */
1756
- "save",
1757
- /** Emitted after a record is deleted. */
1758
- "delete",
1759
- /** Emitted when a custom renderer dispatches a form event. */
1760
- "events",
1761
- /** Emitted when a custom edit handler is registered. */
1762
- "custom:edit",
1763
- /** Emitted when a custom create handler is registered. */
1764
- "custom:create"
1765
- ];
1766
- const _hoisted_1 = { class: "flex justify-between items-center mb-2" };
1767
- const _sfc_main = /* @__PURE__ */ vue.defineComponent({
1768
- __name: "FormWithTable",
1769
- props: FormWithTableProperties,
1770
- emits: FormWithTableEmits,
1771
- setup(__props, { emit: __emit }) {
1772
- const properties = __props;
1773
- const emit = __emit;
1774
- const reload = vue.ref(0);
1775
- const resolvedForm = vue.computed(() => properties.form);
1776
- const resolvedTable = vue.computed(() => properties.table);
1777
- const resolvedFilter = vue.computed(() => properties.filter);
1778
- const resolvedUri = vue.computed(() => properties.uri);
1779
- let store = new FormStore(resolvedUri.value ?? "");
1780
- vue.watch(resolvedUri, (uri) => {
1781
- store = new FormStore(uri ?? "");
1782
- });
1783
- const hasEdit = ui.hasCustomEventListener("editData");
1784
- const customEdit = ui.hasCustomEventListener("custom:edit");
1785
- const customCreate = ui.hasCustomEventListener("custom:create");
1786
- const edit = (data) => {
1787
- if (customEdit) {
1788
- emit("custom:edit", data);
1789
- return;
1790
- }
1791
- if (hasEdit) {
1792
- emit("editData", data);
1793
- return;
1794
- }
1795
- openModal(data);
1796
- };
1797
- const create = () => {
1798
- if (customCreate) {
1799
- emit("custom:create");
1800
- return;
1801
- }
1802
- openModal();
1803
- };
1804
- const deleteFn = (data) => {
1805
- ui.ModalService.showConfirm({
1806
- title: "Delete record",
1807
- message: "Are you sure to delete, the data will be lost?",
1808
- onClose: (result) => {
1809
- if (result.confirmed) {
1810
- store.delete(data).then(() => {
1811
- reload.value = Date.now();
1812
- emit("delete", data);
1813
- });
1814
- }
1815
- }
1816
- });
1817
- };
1818
- const openModal = (formData) => {
1819
- if (!resolvedForm.value) return;
1820
- const isUpdate = !!formData?.id;
1821
- JsonFormModalService.openModal({
1822
- schema: resolvedForm.value.schema,
1823
- uiSchema: resolvedForm.value.uiSchema,
1824
- modalSize: resolvedForm.value.modalSize,
1825
- initialData: formData ?? properties.initialData,
1826
- modalTitle: (isUpdate ? properties.updateTitle ?? properties.createTitle : properties.createTitle) ?? "",
1827
- onClose: (result) => {
1828
- if (result && result.valid) {
1829
- store.save(formData?.id, result.data).then(() => {
1830
- reload.value = Date.now();
1831
- emit("save", { id: formData?.id, data: result.data });
1832
- });
1833
- }
1834
- },
1835
- onEvents: (payload) => emit("events", payload)
1836
- });
1837
- };
1838
- return (_ctx, _cache) => {
1839
- return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
1840
- vue.createElementVNode("div", _hoisted_1, [
1841
- vue.createElementVNode("h1", null, vue.toDisplayString(_ctx.tableTitle), 1),
1842
- vue.createElementVNode("div", null, [
1843
- vue.createVNode(vue.unref(ui.Btn), {
1844
- icon: vue.unref(ui.IconEnum).Plus,
1845
- outline: true,
1846
- onClick: create
1847
- }, {
1848
- default: vue.withCtx(() => [..._cache[0] || (_cache[0] = [
1849
- vue.createTextVNode(" Add new record ", -1)
1850
- ])]),
1851
- _: 1
1852
- }, 8, ["icon"])
1853
- ])
1854
- ]),
1855
- resolvedTable.value ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Card), { key: 0 }, {
1856
- default: vue.withCtx(() => [
1857
- resolvedUri.value ? (vue.openBlock(), vue.createBlock(vue.unref(_sfc_main$g), {
1858
- key: 0,
1859
- id: `form_table_${_ctx.id}`,
1860
- "ui-schema": resolvedTable.value.uiSchema,
1861
- schema: resolvedTable.value.schema,
1862
- "filter-ui-schema": resolvedFilter.value?.uiSchema,
1863
- "filter-schema": resolvedFilter.value?.schema,
1864
- uri: _ctx.dataUri ?? resolvedUri.value,
1865
- reload: reload.value,
1866
- actions: _ctx.tableActions,
1867
- onEdit: edit,
1868
- onDelete: deleteFn
1869
- }, null, 8, ["id", "ui-schema", "schema", "filter-ui-schema", "filter-schema", "uri", "reload", "actions"])) : vue.createCommentVNode("", true)
1870
- ]),
1871
- _: 1
1872
- })) : vue.createCommentVNode("", true)
1873
- ], 64);
1874
- };
1875
- }
1876
- });
1877
- exports.FormModalEmits = FormModalEmits;
1878
- exports.FormModalProperties = FormModalProperties;
1879
- exports.JsonForm = _sfc_main$2;
1880
- exports.JsonFormModal = _sfc_main$d;
1881
- exports.JsonFormModalService = JsonFormModalService;
1882
- exports.JsonFormWithActions = _sfc_main$1;
1883
- exports.JsonFormWithTable = _sfc_main;
1884
- exports.TableComponent = _sfc_main$g;
1885
- exports.TableComponentEmits = TableComponentEmits;
1886
- exports.TableComponentProperties = TableComponentProperties;
1887
- exports.createRepository = createRepository;
1888
- exports.formatError = formatError;
1889
- exports.provideFormEvents = provideFormEvents;
1890
- exports.registerZodErrorMap = registerZodErrorMap;
1891
- exports.useFormEvents = useFormEvents;
1892
- exports.veeRenderers = customRenderes;