@ghentcdh/json-forms-vue 2.0.0 → 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.
- package/index.d.ts +6 -19
- package/index.js +8 -2516
- package/package.json +5 -11
- package/composables/useFormEvents.d.ts +0 -34
- package/composables/useHttpClient.d.ts +0 -12
- package/forms/Dispatch.vue.d.ts +0 -10
- package/forms/FormComponent.properties.d.ts +0 -64
- package/forms/FormComponent.vue.d.ts +0 -95
- package/forms/errorMessages.d.ts +0 -10
- package/forms/errorMode.d.ts +0 -5
- package/forms/modal/FormModal.properties.d.ts +0 -75
- package/forms/modal/FormModal.vue.d.ts +0 -353
- package/forms/modal/FormModalService.d.ts +0 -42
- package/forms/renderers/array/ArrayRenderer.vue.d.ts +0 -7
- package/forms/renderers/array/ArrayRenderers.d.ts +0 -10
- package/forms/renderers/controls/AutocompleteControlRenderer.vue.d.ts +0 -7
- package/forms/renderers/controls/BooleanControlRenderer.vue.d.ts +0 -7
- package/forms/renderers/controls/MarkdownControlRenderer.vue.d.ts +0 -7
- package/forms/renderers/controls/MultiSelectControlRenderer.vue.d.ts +0 -7
- package/forms/renderers/controls/NumberControlRenderer.vue.d.ts +0 -7
- package/forms/renderers/controls/SelectControlRenderer.vue.d.ts +0 -7
- package/forms/renderers/controls/StringControlRenderer.vue.d.ts +0 -7
- package/forms/renderers/controls/TextAreaControlRenderer.vue.d.ts +0 -7
- package/forms/renderers/controls/composables/useControlBinding.d.ts +0 -36
- package/forms/renderers/controls/composables/useFetchOption.d.ts +0 -17
- package/forms/renderers/controls/composables/useInput.d.ts +0 -24
- package/forms/renderers/controls/composables/useReadonlyBinding.d.ts +0 -135
- package/forms/renderers/controls/composables/useSelectBinding.d.ts +0 -29
- package/forms/renderers/controls/index.d.ts +0 -10
- package/forms/renderers/controls/readonly/ControlReadonlyRenderer.vue.d.ts +0 -7
- package/forms/renderers/controls/readonly/ReadonlyLabel.vue.d.ts +0 -254
- package/forms/renderers/controls/readonly/__tests__/formatDate.spec.d.ts +0 -1
- package/forms/renderers/controls/readonly/constants.d.ts +0 -2
- package/forms/renderers/controls/readonly/displayValue/BooleanValue.vue.d.ts +0 -46
- package/forms/renderers/controls/readonly/displayValue/DateValue.vue.d.ts +0 -46
- package/forms/renderers/controls/readonly/displayValue/LinkValue.vue.d.ts +0 -46
- package/forms/renderers/controls/readonly/displayValue/MarkdownValue.vue.d.ts +0 -46
- package/forms/renderers/controls/readonly/displayValue/NotSetValue.vue.d.ts +0 -46
- package/forms/renderers/controls/readonly/displayValue/NumberValue.vue.d.ts +0 -46
- package/forms/renderers/controls/readonly/displayValue/ObjectValue.vue.d.ts +0 -46
- package/forms/renderers/controls/readonly/displayValue/StringValue.vue.d.ts +0 -46
- package/forms/renderers/controls/readonly/displayValue/ViewDetailValue.vue.d.ts +0 -46
- package/forms/renderers/controls/readonly/displayValue/displayValue.properties.d.ts +0 -23
- package/forms/renderers/controls/readonly/displayValue/formatDate.d.ts +0 -25
- package/forms/renderers/controls/readonly/displayValue/index.d.ts +0 -1
- package/forms/renderers/controls/readonly/index.d.ts +0 -10
- package/forms/renderers/controls/readonly/useDisplayValue.d.ts +0 -1
- package/forms/renderers/controls/resource.d.ts +0 -262
- package/forms/renderers/index.d.ts +0 -43
- package/forms/renderers/layout/CollapseLayoutRenderer.vue.d.ts +0 -7
- package/forms/renderers/layout/LayoutRenderer.vue.d.ts +0 -7
- package/forms/renderers/layout/LayoutRenderers.d.ts +0 -20
- package/forms/renderers/layout/ReadOnlyLayoutRenderer.vue.d.ts +0 -7
- package/forms/renderers/layout/colspan.d.ts +0 -1
- package/forms/renderers/registry.d.ts +0 -7
- package/forms/scope.d.ts +0 -4
- package/forms/types.d.ts +0 -36
- package/http-client.d.ts +0 -14
- package/repository/CrudRepository.d.ts +0 -34
- package/repository/index.d.ts +0 -1
- package/table/TableComponent.properties.d.ts +0 -49
- package/table/TableComponent.vue.d.ts +0 -92
- package/table/TableToolbar.vue.d.ts +0 -36
- package/table/cells/index.d.ts +0 -10
- package/table/filter/FilterRowInput.vue.d.ts +0 -17
- package/table/filter/TableFilter.vue.d.ts +0 -16
- package/table/index.d.ts +0 -6
- package/testers/__tests__/jsonforms-testers.spec.d.ts +0 -1
- package/testers/__tests__/tester.spec.d.ts +0 -1
- package/testers/jsonforms-testers.d.ts +0 -27
- package/testers/tester.d.ts +0 -16
- package/testing/index.d.ts +0 -0
- package/testing.js +0 -1
- package/view/modal/ViewModal.properties.d.ts +0 -82
- package/view/modal/ViewModal.vue.d.ts +0 -357
package/index.js
CHANGED
|
@@ -1,2517 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
Object.
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const _hoisted_2$8 = { class: "h-full p-2 whitespace-pre-wrap break-words overflow-hidden min-w-0 text-sm" };
|
|
10
|
-
const _sfc_main$u = /* @__PURE__ */ vue.defineComponent({
|
|
11
|
-
__name: "ReadonlyLabel",
|
|
12
|
-
props: ui.ControlWrapperProperties,
|
|
13
|
-
setup(__props) {
|
|
14
|
-
return (_ctx, _cache) => {
|
|
15
|
-
return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
|
|
16
|
-
vue.createElementVNode("div", _hoisted_1$k, [
|
|
17
|
-
vue.createElementVNode("span", null, vue.toDisplayString(_ctx.label), 1)
|
|
18
|
-
]),
|
|
19
|
-
vue.createElementVNode("div", _hoisted_2$8, [
|
|
20
|
-
vue.renderSlot(_ctx.$slots, "default")
|
|
21
|
-
])
|
|
22
|
-
], 64);
|
|
23
|
-
};
|
|
24
|
-
}
|
|
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
|
+
});
|
|
25
9
|
});
|
|
26
|
-
const errorPatterns = [
|
|
27
|
-
[/^Invalid input: expected \w+, received undefined$/, "This field is required"],
|
|
28
|
-
[/^Invalid input: expected \w+, received null$/, "This field is required"],
|
|
29
|
-
[/^Expected string, received/, "Invalid value"],
|
|
30
|
-
[/^String must contain at least (\d+)/, "Must be at least $1 characters"],
|
|
31
|
-
[/^Number must be greater than or equal to (\d+)/, "Minimum value is $1"],
|
|
32
|
-
[/^Number must be less than or equal to (\d+)/, "Maximum value is $1"]
|
|
33
|
-
];
|
|
34
|
-
const formatError = (message) => {
|
|
35
|
-
if (!message) return void 0;
|
|
36
|
-
for (const [pattern, replacement] of errorPatterns) {
|
|
37
|
-
if (pattern.test(message)) {
|
|
38
|
-
return message.replace(pattern, replacement);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return message;
|
|
42
|
-
};
|
|
43
|
-
const registerZodErrorMap = () => {
|
|
44
|
-
zod.z.config({
|
|
45
|
-
customError: (issue) => {
|
|
46
|
-
if (issue.code === "invalid_type" && issue.received === "undefined") {
|
|
47
|
-
return { message: "This field is required" };
|
|
48
|
-
}
|
|
49
|
-
if (issue.code === "invalid_type" && issue.received === "null") {
|
|
50
|
-
return { message: "This field is required" };
|
|
51
|
-
}
|
|
52
|
-
if (issue.code === "too_small") {
|
|
53
|
-
const i = issue;
|
|
54
|
-
if (i.type === "string" && i.minimum === 1) {
|
|
55
|
-
return { message: "This field is required" };
|
|
56
|
-
}
|
|
57
|
-
if (i.type === "string") {
|
|
58
|
-
return { message: `Must be at least ${i.minimum} characters` };
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (issue.code === "too_big") {
|
|
62
|
-
const i = issue;
|
|
63
|
-
if (i.type === "string") {
|
|
64
|
-
return { message: `Must be at most ${i.maximum} characters` };
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return { message: issue.message ?? "" };
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
};
|
|
71
|
-
const ERROR_MODE_KEY = /* @__PURE__ */ Symbol("errorMode");
|
|
72
|
-
const FORM_SUBMITTED_KEY = /* @__PURE__ */ Symbol("formSubmitted");
|
|
73
|
-
const FORM_READONLY_KEY = /* @__PURE__ */ Symbol("formReadonly");
|
|
74
|
-
const scopeToPath = (scope) => {
|
|
75
|
-
if (!scope) return "";
|
|
76
|
-
return scope.replace(/^#\//, "").split("/").filter((s) => s !== "properties").join(".");
|
|
77
|
-
};
|
|
78
|
-
const resolveSchema = (root, scope) => {
|
|
79
|
-
const segments = scope.replace(/^#\//, "").split("/").filter(Boolean);
|
|
80
|
-
return segments.reduce((acc, key) => acc?.[key], root);
|
|
81
|
-
};
|
|
82
|
-
const checkRequired = (rootSchema, scope, fieldName) => {
|
|
83
|
-
const segments = scope.replace(/^#\//, "").split("/");
|
|
84
|
-
const parentSegments = segments.slice(0, -2);
|
|
85
|
-
if (parentSegments.length === 0) {
|
|
86
|
-
const req2 = rootSchema?.required;
|
|
87
|
-
return Array.isArray(req2) && req2.includes(fieldName);
|
|
88
|
-
}
|
|
89
|
-
const parentScope = `#/${parentSegments.join("/")}`;
|
|
90
|
-
const parentSchema = resolveSchema(rootSchema, parentScope);
|
|
91
|
-
const req = parentSchema?.required;
|
|
92
|
-
return Array.isArray(req) && req.includes(fieldName);
|
|
93
|
-
};
|
|
94
|
-
const useInputProps = (uischema, schema, field, options = {}) => {
|
|
95
|
-
const rootSchema = vue.inject("rootSchema");
|
|
96
|
-
const path = scopeToPath(uischema.scope);
|
|
97
|
-
const { errorMessage, meta } = field;
|
|
98
|
-
const opts = uischema.options ?? {};
|
|
99
|
-
const labelFromScope = path.split(".").pop() ?? "";
|
|
100
|
-
const isRequired = rootSchema ? checkRequired(rootSchema, uischema.scope, labelFromScope) : false;
|
|
101
|
-
const s = schema ?? {};
|
|
102
|
-
const inferredType = (() => {
|
|
103
|
-
if (opts.format === "text") return "text";
|
|
104
|
-
if (s.format === "email") return "email";
|
|
105
|
-
if (s.format === "uri") return "url";
|
|
106
|
-
if (s.type === "number" || s.type === "integer") return "number";
|
|
107
|
-
return options.defaultType ?? "text";
|
|
108
|
-
})();
|
|
109
|
-
const styles = ui.mergeStyles(opts.styles);
|
|
110
|
-
const errorMode = vue.inject(ERROR_MODE_KEY, vue.ref("onBlur"));
|
|
111
|
-
const submitted = vue.inject(FORM_SUBMITTED_KEY, vue.ref(false));
|
|
112
|
-
const formReadonly = vue.inject(FORM_READONLY_KEY, vue.ref(false));
|
|
113
|
-
const shouldShowError = vue.computed(() => {
|
|
114
|
-
if (!errorMessage.value) return false;
|
|
115
|
-
switch (errorMode.value) {
|
|
116
|
-
case "always":
|
|
117
|
-
return true;
|
|
118
|
-
case "onChange":
|
|
119
|
-
return meta.dirty;
|
|
120
|
-
case "onSubmit":
|
|
121
|
-
return submitted.value;
|
|
122
|
-
case "onBlur":
|
|
123
|
-
default:
|
|
124
|
-
return meta.touched;
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
const width = opts.colspan || styles?.width === "full" ? "w-full" : opts.width ?? "min-w-input";
|
|
128
|
-
return vue.computed(() => ({
|
|
129
|
-
id: path,
|
|
130
|
-
placeholder: opts.placeholder,
|
|
131
|
-
description: s.description,
|
|
132
|
-
errors: shouldShowError.value ? opts.errorMessage ?? formatError(errorMessage.value) : void 0,
|
|
133
|
-
label: opts.label ?? labelFromScope.charAt(0).toUpperCase() + labelFromScope.slice(1),
|
|
134
|
-
visible: opts.visible ?? true,
|
|
135
|
-
required: isRequired,
|
|
136
|
-
enabled: opts.readonly !== true && !formReadonly.value,
|
|
137
|
-
isFocused: false,
|
|
138
|
-
isTouched: shouldShowError.value,
|
|
139
|
-
hideLabel: opts.hideLabel ?? false,
|
|
140
|
-
styles,
|
|
141
|
-
width,
|
|
142
|
-
type: inferredType,
|
|
143
|
-
...options.overrides
|
|
144
|
-
}));
|
|
145
|
-
};
|
|
146
|
-
const useCustomControlBinding = ({
|
|
147
|
-
useProps,
|
|
148
|
-
setDefaultValue
|
|
149
|
-
} = {}) => {
|
|
150
|
-
return (uischema, schema, options = {}) => {
|
|
151
|
-
const { values: formValues } = veeValidate.useFormContext();
|
|
152
|
-
const pathPrefix = vue.inject("pathPrefix", "");
|
|
153
|
-
const scopePath = scopeToPath(uischema.scope);
|
|
154
|
-
const path = pathPrefix ? `${pathPrefix}.${scopePath}` : scopePath;
|
|
155
|
-
const field = veeValidate.useField(() => path);
|
|
156
|
-
setDefaultValue?.(field);
|
|
157
|
-
const wrapper = useInputProps(uischema, schema, field, options);
|
|
158
|
-
const customWrapper = useProps?.(uischema, schema, field, options) ?? {
|
|
159
|
-
value: {}
|
|
160
|
-
};
|
|
161
|
-
const onBlur = () => field.handleBlur(new Event("blur"));
|
|
162
|
-
const onChange = () => field.handleChange(field.value.value);
|
|
163
|
-
let initialized = false;
|
|
164
|
-
vue.watch(field.value, (val) => {
|
|
165
|
-
if (!initialized) {
|
|
166
|
-
initialized = true;
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
field.handleChange(val);
|
|
170
|
-
});
|
|
171
|
-
return {
|
|
172
|
-
formValues,
|
|
173
|
-
uischema,
|
|
174
|
-
schema,
|
|
175
|
-
wrapper: vue.computed(() => ({ ...wrapper.value, ...customWrapper.value })),
|
|
176
|
-
value: field.value,
|
|
177
|
-
field,
|
|
178
|
-
onBlur,
|
|
179
|
-
onChange,
|
|
180
|
-
appliedOptions: vue.computed(
|
|
181
|
-
() => uischema.options ?? {}
|
|
182
|
-
)
|
|
183
|
-
};
|
|
184
|
-
};
|
|
185
|
-
};
|
|
186
|
-
const useControlBinding = (uischema, schema, options = {}) => {
|
|
187
|
-
return useCustomControlBinding()(uischema, schema, options);
|
|
188
|
-
};
|
|
189
|
-
const NOT_APPLICABLE = -1;
|
|
190
|
-
const rankWith = (rank, tester) => (uischema, schema, context) => tester(uischema, schema, context) ? rank : NOT_APPLICABLE;
|
|
191
|
-
const and = (...testers) => (uischema, schema, context) => testers.every((tester) => tester(uischema, schema, context));
|
|
192
|
-
const or = (...testers) => (uischema, schema, context) => testers.some((tester) => tester(uischema, schema, context));
|
|
193
|
-
const uiTypeIs = (expected) => (uischema) => !!uischema && uischema.type === expected;
|
|
194
|
-
const isControl = (uischema) => !!uischema && uischema.type === "Control";
|
|
195
|
-
const schemaTypeIs = (expected) => (uischema, schema) => isControl(uischema) && !!schema && schema.type === expected;
|
|
196
|
-
const optionIsIgnoreCase = (optionName, optionValue) => (uischema) => {
|
|
197
|
-
const options = uischema.options;
|
|
198
|
-
if (!options) return false;
|
|
199
|
-
const val = options[optionName];
|
|
200
|
-
return val?.toLowerCase() === optionValue?.toLowerCase();
|
|
201
|
-
};
|
|
202
|
-
const schemaFormatIsOneOf = (...formats) => (_uischema, schema) => {
|
|
203
|
-
const fmt = schema?.format;
|
|
204
|
-
return typeof fmt === "string" && formats.includes(fmt);
|
|
205
|
-
};
|
|
206
|
-
const anyOfTypeIs = (type) => (_uischema, schema) => {
|
|
207
|
-
const s = schema;
|
|
208
|
-
if (!Array.isArray(s?.anyOf)) return false;
|
|
209
|
-
return s.anyOf.some((sub) => sub?.type === type);
|
|
210
|
-
};
|
|
211
|
-
const isAutoCompleteControl = and(
|
|
212
|
-
// uiTypeIs('Control'),
|
|
213
|
-
optionIsIgnoreCase("format", jsonFormsCore.ControlType.autocomplete)
|
|
214
|
-
);
|
|
215
|
-
const isTextAreaControl = and(
|
|
216
|
-
uiTypeIs("Control"),
|
|
217
|
-
optionIsIgnoreCase("format", jsonFormsCore.ControlType.textArea)
|
|
218
|
-
);
|
|
219
|
-
const isStringFormat = and(
|
|
220
|
-
uiTypeIs("Control"),
|
|
221
|
-
or(
|
|
222
|
-
optionIsIgnoreCase("format", jsonFormsCore.ControlType.string),
|
|
223
|
-
schemaTypeIs("string"),
|
|
224
|
-
anyOfTypeIs("string")
|
|
225
|
-
)
|
|
226
|
-
);
|
|
227
|
-
const isMarkdownControl = and(
|
|
228
|
-
uiTypeIs("Control"),
|
|
229
|
-
optionIsIgnoreCase("format", jsonFormsCore.ControlType.markdown)
|
|
230
|
-
);
|
|
231
|
-
and(
|
|
232
|
-
uiTypeIs("Control"),
|
|
233
|
-
// schemaTypeIs('object'),
|
|
234
|
-
(uischema) => !uischema.options?.format
|
|
235
|
-
);
|
|
236
|
-
const isArrayRenderer = and(
|
|
237
|
-
schemaTypeIs("array")
|
|
238
|
-
// optionIsIgnoreCase('format', ControlType.array),
|
|
239
|
-
);
|
|
240
|
-
const isMultiselectControl = and(
|
|
241
|
-
uiTypeIs("Control"),
|
|
242
|
-
optionIsIgnoreCase("format", jsonFormsCore.ControlType.mutliSelect)
|
|
243
|
-
);
|
|
244
|
-
const isSelectControl = and(
|
|
245
|
-
uiTypeIs("Control"),
|
|
246
|
-
optionIsIgnoreCase("format", jsonFormsCore.ControlType.select)
|
|
247
|
-
);
|
|
248
|
-
const isBooleanControl = or(
|
|
249
|
-
and(uiTypeIs("Control"), schemaTypeIs("boolean")),
|
|
250
|
-
and(uiTypeIs("Control"), optionIsIgnoreCase("format", jsonFormsCore.ControlType.boolean))
|
|
251
|
-
);
|
|
252
|
-
const isNumberFormat = and(
|
|
253
|
-
uiTypeIs("Control"),
|
|
254
|
-
or(optionIsIgnoreCase("format", jsonFormsCore.ControlType.number), schemaTypeIs("number"))
|
|
255
|
-
);
|
|
256
|
-
const isIntegerFormat = and(
|
|
257
|
-
uiTypeIs("Control"),
|
|
258
|
-
or(
|
|
259
|
-
optionIsIgnoreCase("format", jsonFormsCore.ControlType.integer),
|
|
260
|
-
schemaTypeIs("integer")
|
|
261
|
-
)
|
|
262
|
-
);
|
|
263
|
-
and(
|
|
264
|
-
uiTypeIs("Control"),
|
|
265
|
-
or(
|
|
266
|
-
optionIsIgnoreCase("format", jsonFormsCore.ControlType.date),
|
|
267
|
-
optionIsIgnoreCase("format", jsonFormsCore.ControlType.dateTime),
|
|
268
|
-
schemaFormatIsOneOf("date", "date-time")
|
|
269
|
-
)
|
|
270
|
-
);
|
|
271
|
-
and(
|
|
272
|
-
uiTypeIs("Control"),
|
|
273
|
-
optionIsIgnoreCase("format", jsonFormsCore.ControlType.relation)
|
|
274
|
-
);
|
|
275
|
-
const EMPTY_VALUE = "—";
|
|
276
|
-
const DisplayValueProperties = {
|
|
277
|
-
direction: { type: String, default: "ltr" },
|
|
278
|
-
path: { type: String, required: true },
|
|
279
|
-
displayValue: { type: Object, required: true },
|
|
280
|
-
options: { type: Object, required: true },
|
|
281
|
-
value: { type: Object, required: true }
|
|
282
|
-
};
|
|
283
|
-
const _hoisted_1$j = { class: "text-gray-500 text-sm" };
|
|
284
|
-
const _sfc_main$t = /* @__PURE__ */ vue.defineComponent({
|
|
285
|
-
__name: "NotSetValue",
|
|
286
|
-
props: DisplayValueProperties,
|
|
287
|
-
setup(__props) {
|
|
288
|
-
return (_ctx, _cache) => {
|
|
289
|
-
return vue.openBlock(), vue.createElementBlock("p", _hoisted_1$j, [
|
|
290
|
-
vue.createTextVNode(vue.toDisplayString(vue.unref(EMPTY_VALUE)) + " · ", 1),
|
|
291
|
-
_cache[0] || (_cache[0] = vue.createElementVNode("small", null, "Not set", -1))
|
|
292
|
-
]);
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
});
|
|
296
|
-
const _hoisted_1$i = {
|
|
297
|
-
key: 0,
|
|
298
|
-
class: "inline-flex items-center gap-1 text-success"
|
|
299
|
-
};
|
|
300
|
-
const _hoisted_2$7 = {
|
|
301
|
-
key: 1,
|
|
302
|
-
class: "inline-flex items-center gap-1 text-base-content/50"
|
|
303
|
-
};
|
|
304
|
-
const _sfc_main$s = /* @__PURE__ */ vue.defineComponent({
|
|
305
|
-
__name: "BooleanValue",
|
|
306
|
-
props: DisplayValueProperties,
|
|
307
|
-
setup(__props) {
|
|
308
|
-
return (_ctx, _cache) => {
|
|
309
|
-
return _ctx.displayValue === true ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_1$i, [
|
|
310
|
-
vue.createVNode(vue.unref(ui.Icon), {
|
|
311
|
-
icon: vue.unref(ui.IconEnum).Check,
|
|
312
|
-
size: "sm"
|
|
313
|
-
}, null, 8, ["icon"]),
|
|
314
|
-
_cache[0] || (_cache[0] = vue.createElementVNode("span", null, "Yes", -1))
|
|
315
|
-
])) : _ctx.displayValue === false ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_2$7, [
|
|
316
|
-
vue.createVNode(vue.unref(ui.Icon), {
|
|
317
|
-
icon: vue.unref(ui.IconEnum).Close,
|
|
318
|
-
size: "sm"
|
|
319
|
-
}, null, 8, ["icon"]),
|
|
320
|
-
_cache[1] || (_cache[1] = vue.createElementVNode("span", null, "No", -1))
|
|
321
|
-
])) : (vue.openBlock(), vue.createBlock(_sfc_main$t, { key: 2 }));
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
});
|
|
325
|
-
const UNITS = [
|
|
326
|
-
["year", 60 * 60 * 24 * 365],
|
|
327
|
-
["month", 60 * 60 * 24 * 30],
|
|
328
|
-
["day", 60 * 60 * 24],
|
|
329
|
-
["hour", 60 * 60],
|
|
330
|
-
["minute", 60],
|
|
331
|
-
["second", 1]
|
|
332
|
-
];
|
|
333
|
-
const relativeFromNow = (date, now, locale) => {
|
|
334
|
-
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });
|
|
335
|
-
const diffSeconds = Math.round((date.getTime() - now.getTime()) / 1e3);
|
|
336
|
-
const abs = Math.abs(diffSeconds);
|
|
337
|
-
for (const [unit, secondsInUnit] of UNITS) {
|
|
338
|
-
if (abs >= secondsInUnit || unit === "second") {
|
|
339
|
-
return rtf.format(Math.round(diffSeconds / secondsInUnit), unit);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
return rtf.format(0, "second");
|
|
343
|
-
};
|
|
344
|
-
const formatDate = (value, {
|
|
345
|
-
withTime = true,
|
|
346
|
-
locale = "en-GB",
|
|
347
|
-
timeZone = "UTC"
|
|
348
|
-
} = {}) => {
|
|
349
|
-
const date = parseDate(value);
|
|
350
|
-
if (!date) return null;
|
|
351
|
-
const datePart = new Intl.DateTimeFormat(locale, {
|
|
352
|
-
day: "numeric",
|
|
353
|
-
month: "short",
|
|
354
|
-
year: "numeric",
|
|
355
|
-
timeZone
|
|
356
|
-
}).format(date);
|
|
357
|
-
let out = datePart;
|
|
358
|
-
if (withTime) {
|
|
359
|
-
const timePart = new Intl.DateTimeFormat(locale, {
|
|
360
|
-
hour: "2-digit",
|
|
361
|
-
minute: "2-digit",
|
|
362
|
-
timeZone
|
|
363
|
-
}).format(date);
|
|
364
|
-
out = `${datePart}, ${timePart}`;
|
|
365
|
-
}
|
|
366
|
-
return out;
|
|
367
|
-
};
|
|
368
|
-
const relativeDate = (value, { locale = "en-GB", now } = {}) => {
|
|
369
|
-
const date = parseDate(value);
|
|
370
|
-
if (!date) return;
|
|
371
|
-
return relativeFromNow(date, now ?? /* @__PURE__ */ new Date(), locale);
|
|
372
|
-
};
|
|
373
|
-
const parseDate = (value) => {
|
|
374
|
-
if (value == null || value === "") return null;
|
|
375
|
-
const date = value instanceof Date ? value : new Date(String(value));
|
|
376
|
-
if (Number.isNaN(date.getTime())) return null;
|
|
377
|
-
return date;
|
|
378
|
-
};
|
|
379
|
-
const isDate = (value) => {
|
|
380
|
-
return !!parseDate(value);
|
|
381
|
-
};
|
|
382
|
-
const _hoisted_1$h = ["dir"];
|
|
383
|
-
const _hoisted_2$6 = { class: "text-gray-500" };
|
|
384
|
-
const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
|
|
385
|
-
__name: "DateValue",
|
|
386
|
-
props: DisplayValueProperties,
|
|
387
|
-
setup(__props) {
|
|
388
|
-
return (_ctx, _cache) => {
|
|
389
|
-
return vue.openBlock(), vue.createElementBlock("p", { dir: _ctx.direction }, [
|
|
390
|
-
vue.createTextVNode(vue.toDisplayString(vue.unref(formatDate)(_ctx.displayValue)) + " · ", 1),
|
|
391
|
-
vue.createElementVNode("small", _hoisted_2$6, vue.toDisplayString(vue.unref(relativeDate)(_ctx.displayValue)), 1)
|
|
392
|
-
], 8, _hoisted_1$h);
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
});
|
|
396
|
-
const _hoisted_1$g = ["href"];
|
|
397
|
-
const _sfc_main$q = /* @__PURE__ */ vue.defineComponent({
|
|
398
|
-
__name: "LinkValue",
|
|
399
|
-
props: DisplayValueProperties,
|
|
400
|
-
setup(__props) {
|
|
401
|
-
return (_ctx, _cache) => {
|
|
402
|
-
return vue.openBlock(), vue.createElementBlock("a", {
|
|
403
|
-
href: _ctx.displayValue,
|
|
404
|
-
target: "_blank",
|
|
405
|
-
rel: "noopener noreferrer"
|
|
406
|
-
}, vue.toDisplayString(_ctx.displayValue), 9, _hoisted_1$g);
|
|
407
|
-
};
|
|
408
|
-
}
|
|
409
|
-
});
|
|
410
|
-
const _hoisted_1$f = ["innerHTML"];
|
|
411
|
-
const _sfc_main$p = /* @__PURE__ */ vue.defineComponent({
|
|
412
|
-
__name: "MarkdownValue",
|
|
413
|
-
props: DisplayValueProperties,
|
|
414
|
-
setup(__props) {
|
|
415
|
-
const props = __props;
|
|
416
|
-
const renderedHtml = vue.computed(() => {
|
|
417
|
-
const raw = props.value;
|
|
418
|
-
if (!raw) return "";
|
|
419
|
-
return raw.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\n/g, "<br>");
|
|
420
|
-
});
|
|
421
|
-
return (_ctx, _cache) => {
|
|
422
|
-
return vue.openBlock(), vue.createElementBlock("div", {
|
|
423
|
-
class: "prose prose-sm max-w-none",
|
|
424
|
-
innerHTML: renderedHtml.value
|
|
425
|
-
}, null, 8, _hoisted_1$f);
|
|
426
|
-
};
|
|
427
|
-
}
|
|
428
|
-
});
|
|
429
|
-
const _hoisted_1$e = { key: 0 };
|
|
430
|
-
const _sfc_main$o = /* @__PURE__ */ vue.defineComponent({
|
|
431
|
-
__name: "NumberValue",
|
|
432
|
-
props: DisplayValueProperties,
|
|
433
|
-
setup(__props) {
|
|
434
|
-
return (_ctx, _cache) => {
|
|
435
|
-
return _ctx.displayValue ? (vue.openBlock(), vue.createElementBlock("p", _hoisted_1$e, vue.toDisplayString(_ctx.displayValue), 1)) : (vue.openBlock(), vue.createBlock(_sfc_main$t, { key: 1 }));
|
|
436
|
-
};
|
|
437
|
-
}
|
|
438
|
-
});
|
|
439
|
-
const _hoisted_1$d = {
|
|
440
|
-
class: "block overflow-auto text-sm",
|
|
441
|
-
style: { "max-height": "200px" }
|
|
442
|
-
};
|
|
443
|
-
const _sfc_main$n = /* @__PURE__ */ vue.defineComponent({
|
|
444
|
-
__name: "ObjectValue",
|
|
445
|
-
props: DisplayValueProperties,
|
|
446
|
-
setup(__props) {
|
|
447
|
-
return (_ctx, _cache) => {
|
|
448
|
-
return vue.openBlock(), vue.createElementBlock("pre", _hoisted_1$d, " " + vue.toDisplayString(_ctx.displayValue) + "\n\n\n ", 1);
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
});
|
|
452
|
-
const _hoisted_1$c = ["dir"];
|
|
453
|
-
const _sfc_main$m = /* @__PURE__ */ vue.defineComponent({
|
|
454
|
-
__name: "StringValue",
|
|
455
|
-
props: DisplayValueProperties,
|
|
456
|
-
setup(__props) {
|
|
457
|
-
return (_ctx, _cache) => {
|
|
458
|
-
return _ctx.displayValue ? (vue.openBlock(), vue.createElementBlock("p", {
|
|
459
|
-
key: 0,
|
|
460
|
-
dir: _ctx.direction
|
|
461
|
-
}, vue.toDisplayString(_ctx.displayValue), 9, _hoisted_1$c)) : (vue.openBlock(), vue.createBlock(_sfc_main$t, { key: 1 }));
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
});
|
|
465
|
-
const createFormEvents = (dispatch) => ({
|
|
466
|
-
dispatch
|
|
467
|
-
});
|
|
468
|
-
const FORM_EVENTS_KEY = /* @__PURE__ */ Symbol("json-forms:events");
|
|
469
|
-
const provideFormEvents = (dispatch) => {
|
|
470
|
-
const events = createFormEvents(dispatch);
|
|
471
|
-
vue.provide(FORM_EVENTS_KEY, events);
|
|
472
|
-
return events;
|
|
473
|
-
};
|
|
474
|
-
const useFormEvents = () => {
|
|
475
|
-
return vue.inject(
|
|
476
|
-
FORM_EVENTS_KEY,
|
|
477
|
-
createFormEvents(() => {
|
|
478
|
-
})
|
|
479
|
-
);
|
|
480
|
-
};
|
|
481
|
-
const _hoisted_1$b = { class: "px-2 flex gap-2 items-center" };
|
|
482
|
-
const _hoisted_2$5 = { class: "truncate" };
|
|
483
|
-
const _sfc_main$l = /* @__PURE__ */ vue.defineComponent({
|
|
484
|
-
__name: "ViewDetailValue",
|
|
485
|
-
props: DisplayValueProperties,
|
|
486
|
-
setup(__props) {
|
|
487
|
-
const props = __props;
|
|
488
|
-
const formEvents = useFormEvents();
|
|
489
|
-
const view = () => {
|
|
490
|
-
formEvents.dispatch({
|
|
491
|
-
event: "view",
|
|
492
|
-
type: props.path,
|
|
493
|
-
data: props.value,
|
|
494
|
-
options: props.options
|
|
495
|
-
});
|
|
496
|
-
};
|
|
497
|
-
return (_ctx, _cache) => {
|
|
498
|
-
return vue.openBlock(), vue.createBlock(vue.unref(ui.Btn), {
|
|
499
|
-
color: "ghost",
|
|
500
|
-
class: "border-gray-300 text-primary h-8",
|
|
501
|
-
tooltip: "View",
|
|
502
|
-
onClick: view
|
|
503
|
-
}, {
|
|
504
|
-
default: vue.withCtx(() => [
|
|
505
|
-
vue.createElementVNode("span", _hoisted_1$b, [
|
|
506
|
-
vue.createElementVNode("span", _hoisted_2$5, vue.toDisplayString(_ctx.displayValue), 1),
|
|
507
|
-
vue.createVNode(vue.unref(ui.Icon), {
|
|
508
|
-
icon: vue.unref(ui.IconEnum).View,
|
|
509
|
-
size: "sm"
|
|
510
|
-
}, null, 8, ["icon"])
|
|
511
|
-
])
|
|
512
|
-
]),
|
|
513
|
-
_: 1
|
|
514
|
-
});
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
});
|
|
518
|
-
const isLink = (value) => value?.startsWith?.("http");
|
|
519
|
-
const getDirection = (options, formValues) => {
|
|
520
|
-
const pathPrefix = vue.inject("pathPrefix", "");
|
|
521
|
-
const opts = options ?? {};
|
|
522
|
-
if (!opts.directionField) return opts.direction ?? "ltr";
|
|
523
|
-
const key = pathPrefix ? `${pathPrefix}.${opts.directionField}` : opts.directionField;
|
|
524
|
-
const val = key.split(".").reduce((o, k) => o?.[k], formValues);
|
|
525
|
-
return val ?? "ltr";
|
|
526
|
-
};
|
|
527
|
-
const getSelectValue = (value, opts) => {
|
|
528
|
-
const labelKey = opts.labelKey ?? "label";
|
|
529
|
-
const valueKey = opts.valueKey ?? "value";
|
|
530
|
-
const resolvedKey = value?.[valueKey] ?? value;
|
|
531
|
-
if (typeof resolvedKey === "string" && opts.values)
|
|
532
|
-
return opts.values?.find((o) => o[valueKey] === resolvedKey)?.[labelKey] ?? resolvedKey;
|
|
533
|
-
const resolved = value && typeof value === "object" ? value?.[labelKey] ?? value[valueKey] : value;
|
|
534
|
-
if (!resolved) return null;
|
|
535
|
-
return resolved;
|
|
536
|
-
};
|
|
537
|
-
const getNestedValue = (value, opts, formValues) => {
|
|
538
|
-
if (opts.dataPath) {
|
|
539
|
-
const nested = opts.dataPath.split(".").reduce((o, k) => o?.[k], formValues);
|
|
540
|
-
if (opts.key && nested && typeof nested === "object")
|
|
541
|
-
return nested[opts.key] ?? null;
|
|
542
|
-
return nested ?? null;
|
|
543
|
-
}
|
|
544
|
-
if (value !== null && typeof value === "object" && opts.key) {
|
|
545
|
-
return value[opts.key] ?? null;
|
|
546
|
-
}
|
|
547
|
-
return value ?? null;
|
|
548
|
-
};
|
|
549
|
-
const getDisplayValue = (value, formValues, opts) => {
|
|
550
|
-
const format = opts.format ?? "date";
|
|
551
|
-
if (format === "select") return getSelectValue(value, opts);
|
|
552
|
-
if (format === "autocomplete") return getSelectValue(value, opts);
|
|
553
|
-
if (typeof value !== "object") {
|
|
554
|
-
return value ?? null;
|
|
555
|
-
}
|
|
556
|
-
return getNestedValue(value, opts, formValues);
|
|
557
|
-
};
|
|
558
|
-
const _getComponent = (value, options, schema, uiSchema) => {
|
|
559
|
-
if (isNumberFormat(uiSchema, schema)) return _sfc_main$o;
|
|
560
|
-
if (isIntegerFormat(uiSchema, schema)) return _sfc_main$o;
|
|
561
|
-
if (isMarkdownControl(uiSchema, schema)) return _sfc_main$p;
|
|
562
|
-
if (value === null || value === void 0) return _sfc_main$t;
|
|
563
|
-
if (options.resource) return _sfc_main$l;
|
|
564
|
-
if (isDate(value)) return _sfc_main$r;
|
|
565
|
-
if (isLink(value)) return _sfc_main$q;
|
|
566
|
-
if (typeof value === "boolean") return _sfc_main$s;
|
|
567
|
-
if (typeof value === "object") return _sfc_main$n;
|
|
568
|
-
return _sfc_main$m;
|
|
569
|
-
};
|
|
570
|
-
const getComponent = (path, uischema, schema, field, formValues) => {
|
|
571
|
-
return vue.computed(() => {
|
|
572
|
-
const value = field.value?.value;
|
|
573
|
-
const options = uischema.options ?? {};
|
|
574
|
-
const displayValue = getDisplayValue(value, formValues, options);
|
|
575
|
-
return {
|
|
576
|
-
component: _getComponent(value, options, schema, uischema),
|
|
577
|
-
value: {
|
|
578
|
-
value,
|
|
579
|
-
path,
|
|
580
|
-
displayValue,
|
|
581
|
-
options,
|
|
582
|
-
direction: getDirection(options, formValues)
|
|
583
|
-
}
|
|
584
|
-
};
|
|
585
|
-
});
|
|
586
|
-
};
|
|
587
|
-
const useCustomReadonlyControlBinding = ({
|
|
588
|
-
useProps,
|
|
589
|
-
setDefaultValue
|
|
590
|
-
} = {}) => {
|
|
591
|
-
return (uischema, schema, options = {}) => {
|
|
592
|
-
const { values: formValues } = veeValidate.useFormContext();
|
|
593
|
-
const pathPrefix = vue.inject("pathPrefix", "");
|
|
594
|
-
const scopePath = scopeToPath(uischema.scope);
|
|
595
|
-
const path = pathPrefix ? `${pathPrefix}.${scopePath}` : scopePath;
|
|
596
|
-
const field = veeValidate.useField(() => path);
|
|
597
|
-
const wrapper = useInputProps(uischema, schema, field, options);
|
|
598
|
-
const customWrapper = useProps?.(uischema, schema, field, options) ?? {
|
|
599
|
-
value: {}
|
|
600
|
-
};
|
|
601
|
-
return {
|
|
602
|
-
wrapper: vue.computed(() => ({ ...wrapper.value, ...customWrapper.value })),
|
|
603
|
-
appliedOptions: vue.computed(
|
|
604
|
-
() => uischema.options ?? {}
|
|
605
|
-
),
|
|
606
|
-
displayWrapper: getComponent(path, uischema, schema, field, formValues)
|
|
607
|
-
};
|
|
608
|
-
};
|
|
609
|
-
};
|
|
610
|
-
const useReadonlyControlBinding = (uischema, schema, options = {}) => {
|
|
611
|
-
return useCustomReadonlyControlBinding()(uischema, schema, options);
|
|
612
|
-
};
|
|
613
|
-
const useDisplayValue = (value, formValues, opts) => {
|
|
614
|
-
const raw = value;
|
|
615
|
-
if (typeof raw !== "object") {
|
|
616
|
-
return raw ?? null;
|
|
617
|
-
}
|
|
618
|
-
if (opts.dataPath) {
|
|
619
|
-
const nested = opts.dataPath.split(".").reduce((o, k) => o?.[k], formValues);
|
|
620
|
-
if (opts.key && nested && typeof nested === "object")
|
|
621
|
-
return nested[opts.key] ?? null;
|
|
622
|
-
return nested ?? null;
|
|
623
|
-
}
|
|
624
|
-
if (raw !== null && typeof raw === "object" && opts.key) {
|
|
625
|
-
return raw[opts.key] ?? null;
|
|
626
|
-
}
|
|
627
|
-
return raw ?? null;
|
|
628
|
-
};
|
|
629
|
-
const HTTP_CLIENT_KEY = /* @__PURE__ */ Symbol("json-forms:http-client");
|
|
630
|
-
const provideHttpClient = (http) => {
|
|
631
|
-
vue.provide(HTTP_CLIENT_KEY, http);
|
|
632
|
-
};
|
|
633
|
-
const useHttpClient = () => {
|
|
634
|
-
const http = vue.inject(HTTP_CLIENT_KEY);
|
|
635
|
-
if (!http) {
|
|
636
|
-
throw new Error(
|
|
637
|
-
"[json-forms] No HttpClient provided. Pass an `http` prop to <JsonForm> or call provideHttpClient() in a parent component."
|
|
638
|
-
);
|
|
639
|
-
}
|
|
640
|
-
return http;
|
|
641
|
-
};
|
|
642
|
-
const _hoisted_1$a = { class: "flex-1" };
|
|
643
|
-
const _hoisted_2$4 = { key: 0 };
|
|
644
|
-
const _hoisted_3$2 = {
|
|
645
|
-
key: 0,
|
|
646
|
-
class: "text-sm text-base-content/50"
|
|
647
|
-
};
|
|
648
|
-
const _hoisted_4$2 = { key: 1 };
|
|
649
|
-
const _sfc_main$k = /* @__PURE__ */ vue.defineComponent({
|
|
650
|
-
__name: "ArrayRenderer",
|
|
651
|
-
props: {
|
|
652
|
-
uischema: {},
|
|
653
|
-
schema: {}
|
|
654
|
-
},
|
|
655
|
-
setup(__props) {
|
|
656
|
-
const props = __props;
|
|
657
|
-
const parentPrefix = vue.inject("pathPrefix", "");
|
|
658
|
-
const scope = props.uischema.scope;
|
|
659
|
-
const scopePath = scopeToPath(scope);
|
|
660
|
-
const path = parentPrefix ? `${parentPrefix}.${scopePath}` : scopePath;
|
|
661
|
-
const rootSchema = vue.inject("rootSchema");
|
|
662
|
-
const arraySchema = resolveSchema(rootSchema, scope);
|
|
663
|
-
const itemSchema = arraySchema?.items ?? {};
|
|
664
|
-
const { fields, push, remove } = veeValidate.useFieldArray(path);
|
|
665
|
-
if (fields.value.length === 0) {
|
|
666
|
-
push({});
|
|
667
|
-
}
|
|
668
|
-
const opts = props.uischema.options ?? {};
|
|
669
|
-
const layout = opts.layout ?? "column";
|
|
670
|
-
const showActions = vue.computed(() => !opts.hideActions);
|
|
671
|
-
const detail = vue.computed(
|
|
672
|
-
() => props.uischema._detail ?? opts.detail
|
|
673
|
-
);
|
|
674
|
-
const childElements = vue.computed(() => {
|
|
675
|
-
if (!detail.value) {
|
|
676
|
-
return props.uischema.elements ?? [];
|
|
677
|
-
}
|
|
678
|
-
const type = detail.value.type;
|
|
679
|
-
if (type && type !== "Control") {
|
|
680
|
-
return [detail.value];
|
|
681
|
-
}
|
|
682
|
-
return detail.value.elements ?? [detail.value];
|
|
683
|
-
});
|
|
684
|
-
return (_ctx, _cache) => {
|
|
685
|
-
return vue.openBlock(), vue.createElementBlock("div", null, [
|
|
686
|
-
vue.createElementVNode("div", {
|
|
687
|
-
class: vue.normalizeClass([
|
|
688
|
-
"flex gap-2",
|
|
689
|
-
vue.unref(layout) === "row" ? "flex-row items-center" : "flex-col"
|
|
690
|
-
])
|
|
691
|
-
}, [
|
|
692
|
-
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(fields), (entry, index) => {
|
|
693
|
-
return vue.openBlock(), vue.createElementBlock("div", {
|
|
694
|
-
key: entry.key,
|
|
695
|
-
class: "flex-1"
|
|
696
|
-
}, [
|
|
697
|
-
vue.createElementVNode("div", {
|
|
698
|
-
class: vue.normalizeClass([
|
|
699
|
-
"flex gap-2",
|
|
700
|
-
vue.unref(layout) === "row" ? "flex-col" : "flex-row items-center"
|
|
701
|
-
])
|
|
702
|
-
}, [
|
|
703
|
-
vue.createElementVNode("div", _hoisted_1$a, [
|
|
704
|
-
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(childElements.value, (child, ci) => {
|
|
705
|
-
return vue.openBlock(), vue.createBlock(_sfc_main$5, {
|
|
706
|
-
key: ci,
|
|
707
|
-
uischema: child,
|
|
708
|
-
schema: vue.unref(itemSchema),
|
|
709
|
-
"path-prefix": `${vue.unref(path)}[${index}]`
|
|
710
|
-
}, null, 8, ["uischema", "schema", "path-prefix"]);
|
|
711
|
-
}), 128))
|
|
712
|
-
]),
|
|
713
|
-
showActions.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$4, [
|
|
714
|
-
vue.unref(fields).length > 1 ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Btn), {
|
|
715
|
-
key: 0,
|
|
716
|
-
icon: vue.unref(ui.IconEnum).Delete,
|
|
717
|
-
outline: true,
|
|
718
|
-
onClick: ($event) => vue.unref(remove)(index)
|
|
719
|
-
}, null, 8, ["icon", "onClick"])) : vue.createCommentVNode("", true)
|
|
720
|
-
])) : vue.createCommentVNode("", true)
|
|
721
|
-
], 2)
|
|
722
|
-
]);
|
|
723
|
-
}), 128)),
|
|
724
|
-
vue.unref(fields).length === 0 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$2, " No data ")) : vue.createCommentVNode("", true),
|
|
725
|
-
showActions.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4$2, [
|
|
726
|
-
vue.createVNode(vue.unref(ui.Btn), {
|
|
727
|
-
icon: vue.unref(ui.IconEnum).Plus,
|
|
728
|
-
outline: true,
|
|
729
|
-
onClick: _cache[0] || (_cache[0] = ($event) => vue.unref(push)({}))
|
|
730
|
-
}, {
|
|
731
|
-
default: vue.withCtx(() => [..._cache[1] || (_cache[1] = [
|
|
732
|
-
vue.createTextVNode(" Add ", -1)
|
|
733
|
-
])]),
|
|
734
|
-
_: 1
|
|
735
|
-
}, 8, ["icon"])
|
|
736
|
-
])) : vue.createCommentVNode("", true)
|
|
737
|
-
], 2)
|
|
738
|
-
]);
|
|
739
|
-
};
|
|
740
|
-
}
|
|
741
|
-
});
|
|
742
|
-
const arrayRenderers = [
|
|
743
|
-
{ tester: rankWith(12, isArrayRenderer), renderer: _sfc_main$k }
|
|
744
|
-
];
|
|
745
|
-
const MethodSchema = zod.z.enum([
|
|
746
|
-
"get",
|
|
747
|
-
"post",
|
|
748
|
-
"delete",
|
|
749
|
-
"put",
|
|
750
|
-
"patch",
|
|
751
|
-
"GET",
|
|
752
|
-
"POST",
|
|
753
|
-
"DELETE",
|
|
754
|
-
"PUT",
|
|
755
|
-
"PATCH"
|
|
756
|
-
]);
|
|
757
|
-
const OperationSchema = zod.z.object({
|
|
758
|
-
uri: zod.z.string(),
|
|
759
|
-
method: MethodSchema
|
|
760
|
-
});
|
|
761
|
-
const OperationsSchema = zod.z.string().or(OperationSchema);
|
|
762
|
-
const BooleanOperationSchema = zod.z.boolean().or(OperationSchema).optional().default(false);
|
|
763
|
-
const Operations = zod.z.object({
|
|
764
|
-
findAll: BooleanOperationSchema,
|
|
765
|
-
findOne: BooleanOperationSchema,
|
|
766
|
-
create: BooleanOperationSchema,
|
|
767
|
-
update: BooleanOperationSchema,
|
|
768
|
-
delete: BooleanOperationSchema,
|
|
769
|
-
lookup: OperationsSchema.optional()
|
|
770
|
-
});
|
|
771
|
-
const OperationMap = {
|
|
772
|
-
create: "post",
|
|
773
|
-
delete: "delete",
|
|
774
|
-
findAll: "get",
|
|
775
|
-
findOne: "get",
|
|
776
|
-
lookup: "get",
|
|
777
|
-
update: "patch"
|
|
778
|
-
};
|
|
779
|
-
const schemaDef = zod.z.object({
|
|
780
|
-
ui: zod.z.any().optional(),
|
|
781
|
-
data: zod.z.any()
|
|
782
|
-
});
|
|
783
|
-
const ResourceSchema = zod.z.object({
|
|
784
|
-
id: zod.z.string(),
|
|
785
|
-
uri: zod.z.string(),
|
|
786
|
-
operations: Operations,
|
|
787
|
-
schema: schemaDef.optional(),
|
|
788
|
-
schemas: zod.z.object({
|
|
789
|
-
form: schemaDef.optional()
|
|
790
|
-
}).optional()
|
|
791
|
-
}).transform((data) => {
|
|
792
|
-
const schema = data.schema ?? data.schemas?.form ?? { ui: void 0, data: void 0 };
|
|
793
|
-
if (!schema.ui && schema.data) {
|
|
794
|
-
schema.ui = jsonFormsCore.uiFromJsonSchema(schema.data);
|
|
795
|
-
}
|
|
796
|
-
const operations = {};
|
|
797
|
-
for (const k in OperationMap) {
|
|
798
|
-
const key = k;
|
|
799
|
-
const defaultOperation = OperationMap[key];
|
|
800
|
-
const operation = data.operations[key];
|
|
801
|
-
const mapResourceSchema = () => {
|
|
802
|
-
if (operation === void 0 || operation === false) return null;
|
|
803
|
-
if (operation === true)
|
|
804
|
-
return { uri: data.uri, method: defaultOperation };
|
|
805
|
-
if (typeof operation === "string")
|
|
806
|
-
return { uri: operation, method: "get" };
|
|
807
|
-
return {
|
|
808
|
-
uri: operation.uri,
|
|
809
|
-
method: operation.method?.toLowerCase() ?? defaultOperation
|
|
810
|
-
};
|
|
811
|
-
};
|
|
812
|
-
operations[key] = mapResourceSchema();
|
|
813
|
-
}
|
|
814
|
-
return {
|
|
815
|
-
...data,
|
|
816
|
-
schema,
|
|
817
|
-
operations
|
|
818
|
-
};
|
|
819
|
-
});
|
|
820
|
-
const getResourceSchema = async (resourceUri, http) => {
|
|
821
|
-
return http.get(resourceUri).then((response) => {
|
|
822
|
-
const resource = ResourceSchema.safeParse(response.data);
|
|
823
|
-
if (!resource.success)
|
|
824
|
-
throw new Error(`Invalid resource schema: ${resource.error}`);
|
|
825
|
-
return resource.data;
|
|
826
|
-
});
|
|
827
|
-
};
|
|
828
|
-
const resolvePlaceholders = (uri, formValues, searchTerm) => {
|
|
829
|
-
const resolved = uri.replace(/\{form\.([^}]+)\}/g, (_, key) => {
|
|
830
|
-
const value = key.split(".").reduce((o, k) => o?.[k], formValues);
|
|
831
|
-
return encodeURIComponent(value ?? "");
|
|
832
|
-
});
|
|
833
|
-
if (resolved.includes("{q}"))
|
|
834
|
-
return resolved.replace("{q}", encodeURIComponent(searchTerm));
|
|
835
|
-
if (resolved.includes("{text}"))
|
|
836
|
-
return resolved.replace("{text}", searchTerm);
|
|
837
|
-
return `${resolved}${encodeURIComponent(searchTerm)}`;
|
|
838
|
-
};
|
|
839
|
-
const useRemoteOption = (options, http, formValues) => {
|
|
840
|
-
return {
|
|
841
|
-
fetchOptions: (searchTerm, signal) => {
|
|
842
|
-
const uri = resolvePlaceholders(options.uri, formValues, searchTerm);
|
|
843
|
-
return http.get(uri, { signal }).then((data) => {
|
|
844
|
-
const body = data.data;
|
|
845
|
-
if (Array.isArray(body)) return body;
|
|
846
|
-
return body[options.dataField ?? "data"];
|
|
847
|
-
});
|
|
848
|
-
}
|
|
849
|
-
};
|
|
850
|
-
};
|
|
851
|
-
const useResourceOptions = async (options, http, formValues) => {
|
|
852
|
-
const resource = await getResourceSchema(options.resource, http);
|
|
853
|
-
const lookup = resource.operations.lookup;
|
|
854
|
-
return {
|
|
855
|
-
fetchOptions: (searchTerm, signal) => {
|
|
856
|
-
const uri = resolvePlaceholders(lookup.uri, formValues, searchTerm);
|
|
857
|
-
const method = lookup.method;
|
|
858
|
-
return http[method](uri, { signal }).then((data) => data.data[options.dataField ?? "data"]);
|
|
859
|
-
},
|
|
860
|
-
enableCreate: !!resource.operations.create && resource.schema.ui,
|
|
861
|
-
form: resource.operations.create ? {
|
|
862
|
-
ui_schema: resource.schema.ui,
|
|
863
|
-
json_schema: resource.schema.data,
|
|
864
|
-
title: `Create new ${resource.id}`,
|
|
865
|
-
create: async (data) => {
|
|
866
|
-
const create = resource.operations.create;
|
|
867
|
-
return http[create.method](create.uri, data).then((result) => result.data);
|
|
868
|
-
}
|
|
869
|
-
} : null
|
|
870
|
-
};
|
|
871
|
-
};
|
|
872
|
-
const useFetchOptions = async (options, http, formValues = {}) => {
|
|
873
|
-
let config = {};
|
|
874
|
-
if ("uri" in options && options.uri)
|
|
875
|
-
config = useRemoteOption(
|
|
876
|
-
options,
|
|
877
|
-
http,
|
|
878
|
-
formValues
|
|
879
|
-
);
|
|
880
|
-
if ("resource" in options && options.resource)
|
|
881
|
-
config = await useResourceOptions(
|
|
882
|
-
options,
|
|
883
|
-
http,
|
|
884
|
-
formValues
|
|
885
|
-
);
|
|
886
|
-
return {
|
|
887
|
-
fetchOptions: null,
|
|
888
|
-
labelKey: options.labelKey,
|
|
889
|
-
valueKey: options.valueKey,
|
|
890
|
-
enableCreate: options.enableCreate ?? false,
|
|
891
|
-
form: null,
|
|
892
|
-
...config
|
|
893
|
-
};
|
|
894
|
-
};
|
|
895
|
-
const loadDisplayValue = (options, value) => {
|
|
896
|
-
const values = options.values;
|
|
897
|
-
if (!values) return value;
|
|
898
|
-
const valueKey = options.valueKey;
|
|
899
|
-
const id = value?.[valueKey] ?? value;
|
|
900
|
-
const findValue = values.find((o) => o[valueKey] === id);
|
|
901
|
-
return findValue;
|
|
902
|
-
};
|
|
903
|
-
const useSelectInput = (...fields) => (uischema, schema, field) => {
|
|
904
|
-
const opts = uischema.options ?? {};
|
|
905
|
-
return vue.computed(() => {
|
|
906
|
-
const options = Object.fromEntries(
|
|
907
|
-
fields.filter((f) => f in opts).map((f) => [f, opts[f]])
|
|
908
|
-
);
|
|
909
|
-
if (!options.labelKey) options.labelKey = "label";
|
|
910
|
-
if (!options.valueKey) options.valueKey = "value";
|
|
911
|
-
options.displayValue = loadDisplayValue(
|
|
912
|
-
options,
|
|
913
|
-
field.value.value
|
|
914
|
-
);
|
|
915
|
-
return options;
|
|
916
|
-
});
|
|
917
|
-
};
|
|
918
|
-
const useSelectBinding = useCustomControlBinding({
|
|
919
|
-
useProps: useSelectInput(
|
|
920
|
-
"options",
|
|
921
|
-
"values",
|
|
922
|
-
"uri",
|
|
923
|
-
"resource",
|
|
924
|
-
"dataField",
|
|
925
|
-
"labelKey",
|
|
926
|
-
"valueKey",
|
|
927
|
-
"clearable",
|
|
928
|
-
"storeValue"
|
|
929
|
-
)
|
|
930
|
-
});
|
|
931
|
-
const useAutocompleteBinding = useCustomControlBinding({
|
|
932
|
-
useProps: useSelectInput(
|
|
933
|
-
"options",
|
|
934
|
-
"labelKey",
|
|
935
|
-
"valueKey",
|
|
936
|
-
"uri",
|
|
937
|
-
"freeText",
|
|
938
|
-
"enableCreate",
|
|
939
|
-
"dataField",
|
|
940
|
-
"skipAuth"
|
|
941
|
-
)
|
|
942
|
-
});
|
|
943
|
-
const FormModalProperties = {
|
|
944
|
-
/** Title displayed in the modal header. */
|
|
945
|
-
modalTitle: { type: String, required: true },
|
|
946
|
-
/** Label for the save button. */
|
|
947
|
-
saveLabel: { type: String, default: "Save" },
|
|
948
|
-
/** Label for the cancel button. */
|
|
949
|
-
cancelLabel: { type: String, default: "Cancel" },
|
|
950
|
-
/** JSON schema describing the shape of the form data. */
|
|
951
|
-
schema: { type: Object, required: true },
|
|
952
|
-
/** UI schema describing the layout and controls. */
|
|
953
|
-
uiSchema: { type: Object, required: true },
|
|
954
|
-
/** Modal width (`'xs'`, `'sm'`, `'md'`, `'lg'`, `'xl'`). */
|
|
955
|
-
modalSize: { type: String, default: "md" },
|
|
956
|
-
/** Callback invoked when the modal closes (with result or `null` on cancel). */
|
|
957
|
-
onClose: {
|
|
958
|
-
type: Function,
|
|
959
|
-
required: true
|
|
960
|
-
},
|
|
961
|
-
/** Callback for form events dispatched by custom renderers. */
|
|
962
|
-
onEvents: {
|
|
963
|
-
type: Function
|
|
964
|
-
},
|
|
965
|
-
/** Initial form data to populate the form with. */
|
|
966
|
-
data: { type: Object, required: true },
|
|
967
|
-
/** When validation errors are shown. */
|
|
968
|
-
errorMode: {
|
|
969
|
-
type: String,
|
|
970
|
-
default: "onBlur"
|
|
971
|
-
},
|
|
972
|
-
/** HTTP client passed through to the inner JsonForm for remote renderers (e.g. autocomplete). */
|
|
973
|
-
http: {
|
|
974
|
-
type: Object,
|
|
975
|
-
default: null
|
|
976
|
-
},
|
|
977
|
-
/** Custom renderer registry passed to the inner JsonForm. */
|
|
978
|
-
renderers: {
|
|
979
|
-
type: Array,
|
|
980
|
-
default: null
|
|
981
|
-
}
|
|
982
|
-
};
|
|
983
|
-
const FormModalEmits = [
|
|
984
|
-
/** Emitted when the modal is closed (submit or cancel). */
|
|
985
|
-
"closeModal",
|
|
986
|
-
/** Emitted when a custom renderer dispatches a form event. */
|
|
987
|
-
"events",
|
|
988
|
-
/** Emitted when validation errors change. */
|
|
989
|
-
"errors",
|
|
990
|
-
/** Emitted when form validity changes. */
|
|
991
|
-
"valid"
|
|
992
|
-
];
|
|
993
|
-
const _hoisted_1$9 = { class: "overflow-auto" };
|
|
994
|
-
const _sfc_main$j = /* @__PURE__ */ vue.defineComponent({
|
|
995
|
-
__name: "FormModal",
|
|
996
|
-
props: /* @__PURE__ */ vue.mergeModels(FormModalProperties, {
|
|
997
|
-
"modelValue": {},
|
|
998
|
-
"modelModifiers": {}
|
|
999
|
-
}),
|
|
1000
|
-
emits: /* @__PURE__ */ vue.mergeModels(FormModalEmits, ["update:modelValue"]),
|
|
1001
|
-
setup(__props, { emit: __emit }) {
|
|
1002
|
-
const properties = __props;
|
|
1003
|
-
const id = `edit_${Math.floor(Math.random() * 1e3)}`;
|
|
1004
|
-
const formRef = vue.ref();
|
|
1005
|
-
const valid = vue.ref(false);
|
|
1006
|
-
const formData = vue.useModel(__props, "modelValue");
|
|
1007
|
-
const emits = __emit;
|
|
1008
|
-
if (properties.data) {
|
|
1009
|
-
formData.value = properties.data;
|
|
1010
|
-
}
|
|
1011
|
-
const onCancel = () => {
|
|
1012
|
-
formData.value = {};
|
|
1013
|
-
emits("closeModal", null);
|
|
1014
|
-
};
|
|
1015
|
-
const onChange = (data) => {
|
|
1016
|
-
formData.value = data;
|
|
1017
|
-
};
|
|
1018
|
-
const onSubmit = () => {
|
|
1019
|
-
formRef.value?.markSubmitted();
|
|
1020
|
-
if (!valid.value) return;
|
|
1021
|
-
emits("closeModal", { data: formData.value, valid: valid.value });
|
|
1022
|
-
};
|
|
1023
|
-
const onErrors = (errors) => {
|
|
1024
|
-
emits("errors", errors);
|
|
1025
|
-
valid.value = !errors || (Array.isArray(errors) ? errors.length === 0 : Object.keys(errors).length === 0);
|
|
1026
|
-
};
|
|
1027
|
-
vue.watch(valid, (newValid, oldValid) => {
|
|
1028
|
-
if (newValid !== oldValid) {
|
|
1029
|
-
emits("valid", newValid);
|
|
1030
|
-
}
|
|
1031
|
-
});
|
|
1032
|
-
return (_ctx, _cache) => {
|
|
1033
|
-
return vue.openBlock(), vue.createBlock(vue.unref(ui.Modal), vue.mergeProps(properties, {
|
|
1034
|
-
open: true,
|
|
1035
|
-
"disable-close": false,
|
|
1036
|
-
width: _ctx.modalSize,
|
|
1037
|
-
onCloseModal: onCancel
|
|
1038
|
-
}), {
|
|
1039
|
-
content: vue.withCtx(() => [
|
|
1040
|
-
vue.createElementVNode("div", _hoisted_1$9, [
|
|
1041
|
-
vue.renderSlot(_ctx.$slots, "content-before"),
|
|
1042
|
-
vue.createVNode(_sfc_main$4, {
|
|
1043
|
-
id: `modal-${id}`,
|
|
1044
|
-
ref_key: "formRef",
|
|
1045
|
-
ref: formRef,
|
|
1046
|
-
"form-data": formData.value,
|
|
1047
|
-
schema: _ctx.schema,
|
|
1048
|
-
"ui-schema": _ctx.uiSchema,
|
|
1049
|
-
"error-mode": _ctx.errorMode,
|
|
1050
|
-
http: properties.http,
|
|
1051
|
-
renderers: properties.renderers,
|
|
1052
|
-
onErrors,
|
|
1053
|
-
onChange,
|
|
1054
|
-
onEvents: _cache[0] || (_cache[0] = ($event) => emits("events", $event))
|
|
1055
|
-
}, null, 8, ["id", "form-data", "schema", "ui-schema", "error-mode", "http", "renderers"]),
|
|
1056
|
-
vue.renderSlot(_ctx.$slots, "content-after")
|
|
1057
|
-
])
|
|
1058
|
-
]),
|
|
1059
|
-
actions: vue.withCtx(() => [
|
|
1060
|
-
vue.createVNode(vue.unref(ui.Btn), {
|
|
1061
|
-
color: vue.unref(ui.Color).secondary,
|
|
1062
|
-
outline: true,
|
|
1063
|
-
"aria-label": _ctx.cancelLabel,
|
|
1064
|
-
onClick: onCancel
|
|
1065
|
-
}, {
|
|
1066
|
-
default: vue.withCtx(() => [
|
|
1067
|
-
vue.createTextVNode(vue.toDisplayString(_ctx.cancelLabel), 1)
|
|
1068
|
-
]),
|
|
1069
|
-
_: 1
|
|
1070
|
-
}, 8, ["color", "aria-label"]),
|
|
1071
|
-
vue.createVNode(vue.unref(ui.Btn), {
|
|
1072
|
-
disabled: !valid.value,
|
|
1073
|
-
"aria-label": _ctx.saveLabel,
|
|
1074
|
-
onClick: onSubmit
|
|
1075
|
-
}, {
|
|
1076
|
-
default: vue.withCtx(() => [
|
|
1077
|
-
vue.createTextVNode(vue.toDisplayString(_ctx.saveLabel), 1)
|
|
1078
|
-
]),
|
|
1079
|
-
_: 1
|
|
1080
|
-
}, 8, ["disabled", "aria-label"])
|
|
1081
|
-
]),
|
|
1082
|
-
_: 3
|
|
1083
|
-
}, 16, ["width"]);
|
|
1084
|
-
};
|
|
1085
|
-
}
|
|
1086
|
-
});
|
|
1087
|
-
const ViewModalProperties = {
|
|
1088
|
-
/** Title displayed in the modal header. */
|
|
1089
|
-
modalTitle: { type: String, required: true },
|
|
1090
|
-
/** Label for the close button. */
|
|
1091
|
-
closeLabel: { type: String, default: "Close" },
|
|
1092
|
-
/** Label for the edit button. Only rendered when `canEdit` is true. */
|
|
1093
|
-
editLabel: { type: String, default: "Edit" },
|
|
1094
|
-
/** Label for the delete button. Only rendered when `canDelete` is true. */
|
|
1095
|
-
deleteLabel: { type: String, default: "Delete" },
|
|
1096
|
-
/** JSON schema describing the shape of the form data. */
|
|
1097
|
-
schema: { type: Object, required: true },
|
|
1098
|
-
/** UI schema describing the layout and controls. */
|
|
1099
|
-
uiSchema: { type: Object, required: true },
|
|
1100
|
-
/** Modal width (`'xs'`, `'sm'`, `'md'`, `'lg'`, `'xl'`). */
|
|
1101
|
-
modalSize: { type: String, default: "md" },
|
|
1102
|
-
/** Callback invoked when the modal closes (with result or `null` on cancel). */
|
|
1103
|
-
onClose: {
|
|
1104
|
-
type: Function,
|
|
1105
|
-
default: () => {
|
|
1106
|
-
}
|
|
1107
|
-
},
|
|
1108
|
-
/**
|
|
1109
|
-
* Show the Edit button.
|
|
1110
|
-
* The caller wires the action by listening to the `edit` event via `onEdit`
|
|
1111
|
-
* in the props object — Vue's v-bind spread in modalWrapper converts onXxx
|
|
1112
|
-
* keys into event handlers automatically.
|
|
1113
|
-
*/
|
|
1114
|
-
canEdit: { type: Boolean, default: false },
|
|
1115
|
-
/**
|
|
1116
|
-
* Show the Delete button.
|
|
1117
|
-
* The caller wires the action by listening to the `delete` event via `onDelete`
|
|
1118
|
-
* in the props object.
|
|
1119
|
-
*/
|
|
1120
|
-
canDelete: { type: Boolean, default: false },
|
|
1121
|
-
/** Initial form data to populate the form with. */
|
|
1122
|
-
data: { type: Object, required: true },
|
|
1123
|
-
/** Custom renderer registry passed to the inner JsonForm. */
|
|
1124
|
-
renderers: {
|
|
1125
|
-
type: Array,
|
|
1126
|
-
default: null
|
|
1127
|
-
}
|
|
1128
|
-
};
|
|
1129
|
-
const ViewModalEmits = [
|
|
1130
|
-
/** Emitted when the modal is closed. */
|
|
1131
|
-
"closeModal",
|
|
1132
|
-
/** Emitted when the Edit button is clicked. Payload: current form data. */
|
|
1133
|
-
"edit",
|
|
1134
|
-
/** Emitted when the Delete button is clicked. Payload: current form data. */
|
|
1135
|
-
"delete",
|
|
1136
|
-
/** Emitted when the view event is fired from the form. Payload: payload of the form event */
|
|
1137
|
-
"view"
|
|
1138
|
-
];
|
|
1139
|
-
const _hoisted_1$8 = { class: "text-gray-500 text-xs mb-2" };
|
|
1140
|
-
const _hoisted_2$3 = { class: "overflow-y-auto" };
|
|
1141
|
-
const _sfc_main$i = /* @__PURE__ */ vue.defineComponent({
|
|
1142
|
-
__name: "ViewModal",
|
|
1143
|
-
props: /* @__PURE__ */ vue.mergeModels(ViewModalProperties, {
|
|
1144
|
-
"modelValue": {},
|
|
1145
|
-
"modelModifiers": {}
|
|
1146
|
-
}),
|
|
1147
|
-
emits: /* @__PURE__ */ vue.mergeModels(ViewModalEmits, ["update:modelValue"]),
|
|
1148
|
-
setup(__props, { emit: __emit }) {
|
|
1149
|
-
const properties = __props;
|
|
1150
|
-
const id = `view_${Math.floor(Math.random() * 1e3)}`;
|
|
1151
|
-
const valid = vue.ref(false);
|
|
1152
|
-
const formData = vue.useModel(__props, "modelValue");
|
|
1153
|
-
const emits = __emit;
|
|
1154
|
-
if (properties.data) {
|
|
1155
|
-
formData.value = properties.data;
|
|
1156
|
-
}
|
|
1157
|
-
vue.provide(
|
|
1158
|
-
"renderers",
|
|
1159
|
-
properties.renderers?.length ? [...customRenderers, ...properties.renderers] : customRenderers
|
|
1160
|
-
);
|
|
1161
|
-
vue.provide("readonlyRenderers", properties.renderers ?? []);
|
|
1162
|
-
vue.provide("rootSchema", properties.schema);
|
|
1163
|
-
vue.provide("styles", ui.myStyles);
|
|
1164
|
-
const onCancel = () => {
|
|
1165
|
-
formData.value = {};
|
|
1166
|
-
emits("closeModal", null);
|
|
1167
|
-
};
|
|
1168
|
-
const onEditClick = () => {
|
|
1169
|
-
const data = formData.value;
|
|
1170
|
-
emits("edit", data);
|
|
1171
|
-
emits("closeModal", null);
|
|
1172
|
-
};
|
|
1173
|
-
const onDeleteClick = () => {
|
|
1174
|
-
const data = formData.value;
|
|
1175
|
-
emits("delete", data);
|
|
1176
|
-
emits("closeModal", null);
|
|
1177
|
-
};
|
|
1178
|
-
vue.watch(valid, (newValid, oldValid) => {
|
|
1179
|
-
if (newValid !== oldValid) {
|
|
1180
|
-
emits("valid", newValid);
|
|
1181
|
-
}
|
|
1182
|
-
});
|
|
1183
|
-
const handleEvent = (event) => {
|
|
1184
|
-
if (event.event !== "view") return;
|
|
1185
|
-
emits("view", event);
|
|
1186
|
-
};
|
|
1187
|
-
return (_ctx, _cache) => {
|
|
1188
|
-
return vue.openBlock(), vue.createBlock(vue.unref(ui.Modal), vue.mergeProps(properties, {
|
|
1189
|
-
open: true,
|
|
1190
|
-
"disable-close": false,
|
|
1191
|
-
width: _ctx.modalSize,
|
|
1192
|
-
onCloseModal: onCancel
|
|
1193
|
-
}), {
|
|
1194
|
-
title: vue.withCtx(() => [
|
|
1195
|
-
vue.createElementVNode("h3", null, vue.toDisplayString(_ctx.modalTitle), 1),
|
|
1196
|
-
vue.createElementVNode("div", _hoisted_1$8, vue.toDisplayString(formData.value.id), 1)
|
|
1197
|
-
]),
|
|
1198
|
-
content: vue.withCtx(() => [
|
|
1199
|
-
vue.renderSlot(_ctx.$slots, "content-before"),
|
|
1200
|
-
vue.createElementVNode("div", _hoisted_2$3, [
|
|
1201
|
-
vue.createVNode(_sfc_main$4, {
|
|
1202
|
-
id: `modal-${id}`,
|
|
1203
|
-
ref: "formRef",
|
|
1204
|
-
"form-data": formData.value,
|
|
1205
|
-
schema: _ctx.schema,
|
|
1206
|
-
readonly: true,
|
|
1207
|
-
"ui-schema": _ctx.uiSchema,
|
|
1208
|
-
renderers: properties.renderers,
|
|
1209
|
-
onEvents: handleEvent
|
|
1210
|
-
}, null, 8, ["id", "form-data", "schema", "ui-schema", "renderers"])
|
|
1211
|
-
]),
|
|
1212
|
-
vue.renderSlot(_ctx.$slots, "content-after")
|
|
1213
|
-
]),
|
|
1214
|
-
actions: vue.withCtx(() => [
|
|
1215
|
-
_ctx.canEdit ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Btn), {
|
|
1216
|
-
key: 0,
|
|
1217
|
-
"aria-label": _ctx.editLabel,
|
|
1218
|
-
onClick: onEditClick
|
|
1219
|
-
}, {
|
|
1220
|
-
default: vue.withCtx(() => [
|
|
1221
|
-
vue.createTextVNode(vue.toDisplayString(_ctx.editLabel), 1)
|
|
1222
|
-
]),
|
|
1223
|
-
_: 1
|
|
1224
|
-
}, 8, ["aria-label"])) : vue.createCommentVNode("", true),
|
|
1225
|
-
vue.createVNode(vue.unref(ui.Btn), {
|
|
1226
|
-
color: vue.unref(ui.Color).secondary,
|
|
1227
|
-
outline: true,
|
|
1228
|
-
"aria-label": _ctx.closeLabel,
|
|
1229
|
-
onClick: onCancel
|
|
1230
|
-
}, {
|
|
1231
|
-
default: vue.withCtx(() => [
|
|
1232
|
-
vue.createTextVNode(vue.toDisplayString(_ctx.closeLabel), 1)
|
|
1233
|
-
]),
|
|
1234
|
-
_: 1
|
|
1235
|
-
}, 8, ["color", "aria-label"]),
|
|
1236
|
-
_ctx.canDelete ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Btn), {
|
|
1237
|
-
key: 1,
|
|
1238
|
-
color: vue.unref(ui.Color).error,
|
|
1239
|
-
outline: true,
|
|
1240
|
-
"aria-label": _ctx.deleteLabel,
|
|
1241
|
-
icon: vue.unref(ui.IconEnum).Delete,
|
|
1242
|
-
onClick: onDeleteClick
|
|
1243
|
-
}, {
|
|
1244
|
-
default: vue.withCtx(() => [
|
|
1245
|
-
vue.createTextVNode(vue.toDisplayString(_ctx.deleteLabel), 1)
|
|
1246
|
-
]),
|
|
1247
|
-
_: 1
|
|
1248
|
-
}, 8, ["color", "aria-label", "icon"])) : vue.createCommentVNode("", true)
|
|
1249
|
-
]),
|
|
1250
|
-
_: 3
|
|
1251
|
-
}, 16, ["width"]);
|
|
1252
|
-
};
|
|
1253
|
-
}
|
|
1254
|
-
});
|
|
1255
|
-
class JsonFormModalService {
|
|
1256
|
-
static openModal({
|
|
1257
|
-
initialData,
|
|
1258
|
-
modalTitle,
|
|
1259
|
-
schema,
|
|
1260
|
-
uiSchema,
|
|
1261
|
-
modalSize,
|
|
1262
|
-
onClose,
|
|
1263
|
-
onEvents,
|
|
1264
|
-
http,
|
|
1265
|
-
renderers
|
|
1266
|
-
}) {
|
|
1267
|
-
ui.ModalService.openModal({
|
|
1268
|
-
component: _sfc_main$j,
|
|
1269
|
-
props: {
|
|
1270
|
-
schema,
|
|
1271
|
-
uiSchema,
|
|
1272
|
-
modalSize,
|
|
1273
|
-
data: initialData ?? {},
|
|
1274
|
-
modalTitle,
|
|
1275
|
-
onClose,
|
|
1276
|
-
onEvents,
|
|
1277
|
-
http,
|
|
1278
|
-
renderers
|
|
1279
|
-
}
|
|
1280
|
-
});
|
|
1281
|
-
}
|
|
1282
|
-
static openViewModal({
|
|
1283
|
-
data,
|
|
1284
|
-
modalTitle,
|
|
1285
|
-
schema,
|
|
1286
|
-
uiSchema,
|
|
1287
|
-
modalSize,
|
|
1288
|
-
onClose,
|
|
1289
|
-
onEdit,
|
|
1290
|
-
onDelete,
|
|
1291
|
-
renderers,
|
|
1292
|
-
onView
|
|
1293
|
-
}) {
|
|
1294
|
-
ui.ModalService.openModal({
|
|
1295
|
-
component: _sfc_main$i,
|
|
1296
|
-
props: {
|
|
1297
|
-
schema,
|
|
1298
|
-
uiSchema,
|
|
1299
|
-
modalSize,
|
|
1300
|
-
data,
|
|
1301
|
-
modalTitle,
|
|
1302
|
-
onClose: onClose ?? (() => {
|
|
1303
|
-
}),
|
|
1304
|
-
// Boolean props drive button visibility — no `on` prefix so Vue passes
|
|
1305
|
-
// them as regular props, not event listeners.
|
|
1306
|
-
canEdit: !!onEdit,
|
|
1307
|
-
canDelete: !!onDelete,
|
|
1308
|
-
// `onEdit`/`onDelete` are intercepted by Vue's v-bind spread as event
|
|
1309
|
-
// handlers for ViewModal's declared 'edit'/'delete' emits.
|
|
1310
|
-
onEdit,
|
|
1311
|
-
onDelete,
|
|
1312
|
-
renderers,
|
|
1313
|
-
onView
|
|
1314
|
-
}
|
|
1315
|
-
});
|
|
1316
|
-
}
|
|
1317
|
-
}
|
|
1318
|
-
const _sfc_main$h = /* @__PURE__ */ vue.defineComponent({
|
|
1319
|
-
__name: "AutocompleteControlRenderer",
|
|
1320
|
-
props: {
|
|
1321
|
-
uischema: {},
|
|
1322
|
-
schema: {}
|
|
1323
|
-
},
|
|
1324
|
-
setup(__props) {
|
|
1325
|
-
const props = __props;
|
|
1326
|
-
const {
|
|
1327
|
-
wrapper,
|
|
1328
|
-
value,
|
|
1329
|
-
field,
|
|
1330
|
-
onBlur,
|
|
1331
|
-
onChange: onFieldChange,
|
|
1332
|
-
appliedOptions
|
|
1333
|
-
} = useAutocompleteBinding(props.uischema, props.schema);
|
|
1334
|
-
const http = useHttpClient();
|
|
1335
|
-
const { values: formValues } = veeValidate.useFormContext();
|
|
1336
|
-
const fetchOptions = vue.ref(null);
|
|
1337
|
-
vue.watch(
|
|
1338
|
-
[appliedOptions, formValues],
|
|
1339
|
-
async ([opts]) => {
|
|
1340
|
-
fetchOptions.value = await useFetchOptions(opts, http, formValues);
|
|
1341
|
-
},
|
|
1342
|
-
{ immediate: true, deep: true }
|
|
1343
|
-
);
|
|
1344
|
-
const onChange = (val) => {
|
|
1345
|
-
setValue(val);
|
|
1346
|
-
onFieldChange();
|
|
1347
|
-
};
|
|
1348
|
-
const formEvents = useFormEvents();
|
|
1349
|
-
const path = scopeToPath(props.uischema.scope);
|
|
1350
|
-
const setValue = (result) => {
|
|
1351
|
-
if (!result || !fetchOptions.value) {
|
|
1352
|
-
field.setValue(result);
|
|
1353
|
-
return;
|
|
1354
|
-
}
|
|
1355
|
-
const { valueKey, labelKey } = fetchOptions.value;
|
|
1356
|
-
const opts = appliedOptions.value;
|
|
1357
|
-
if (opts.storeValue && valueKey && valueKey in result) {
|
|
1358
|
-
field.setValue(result[valueKey]);
|
|
1359
|
-
return;
|
|
1360
|
-
}
|
|
1361
|
-
const keys = [valueKey, labelKey].filter(Boolean);
|
|
1362
|
-
if (keys.length === 0) {
|
|
1363
|
-
field.setValue(result);
|
|
1364
|
-
return;
|
|
1365
|
-
}
|
|
1366
|
-
const stripped = Object.fromEntries(keys.filter((k) => k in result).map((k) => [k, result[k]]));
|
|
1367
|
-
field.setValue(stripped);
|
|
1368
|
-
};
|
|
1369
|
-
const onCreate = () => {
|
|
1370
|
-
if (fetchOptions.value?.enableCreate === false) return;
|
|
1371
|
-
const form = fetchOptions.value.form;
|
|
1372
|
-
if (form) {
|
|
1373
|
-
JsonFormModalService.openModal({
|
|
1374
|
-
schema: form.json_schema,
|
|
1375
|
-
uiSchema: form.ui_schema,
|
|
1376
|
-
modalTitle: `Create new ${wrapper.value.label}`,
|
|
1377
|
-
http,
|
|
1378
|
-
onClose: (result) => {
|
|
1379
|
-
if (!result || !result.valid) return;
|
|
1380
|
-
form.create(result.data).then((res) => {
|
|
1381
|
-
setValue(res);
|
|
1382
|
-
});
|
|
1383
|
-
}
|
|
1384
|
-
});
|
|
1385
|
-
return;
|
|
1386
|
-
}
|
|
1387
|
-
formEvents.dispatch({
|
|
1388
|
-
event: "create",
|
|
1389
|
-
type: path,
|
|
1390
|
-
data: value.value,
|
|
1391
|
-
onSuccess: setValue
|
|
1392
|
-
});
|
|
1393
|
-
};
|
|
1394
|
-
return (_ctx, _cache) => {
|
|
1395
|
-
return fetchOptions.value ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Autocomplete), vue.mergeProps({ key: 0 }, vue.unref(wrapper), {
|
|
1396
|
-
"model-value": vue.unref(value),
|
|
1397
|
-
"fetch-options": fetchOptions.value.fetchOptions,
|
|
1398
|
-
"label-key": fetchOptions.value.labelKey,
|
|
1399
|
-
"value-key": fetchOptions.value.valueKey,
|
|
1400
|
-
"enable-create": fetchOptions.value.enableCreate,
|
|
1401
|
-
onChange,
|
|
1402
|
-
onBlur: vue.unref(onBlur),
|
|
1403
|
-
onCreate
|
|
1404
|
-
}), null, 16, ["model-value", "fetch-options", "label-key", "value-key", "enable-create", "onBlur"])) : vue.createCommentVNode("", true);
|
|
1405
|
-
};
|
|
1406
|
-
}
|
|
1407
|
-
});
|
|
1408
|
-
const _sfc_main$g = /* @__PURE__ */ vue.defineComponent({
|
|
1409
|
-
__name: "BooleanControlRenderer",
|
|
1410
|
-
props: {
|
|
1411
|
-
uischema: {},
|
|
1412
|
-
schema: {}
|
|
1413
|
-
},
|
|
1414
|
-
setup(__props) {
|
|
1415
|
-
const props = __props;
|
|
1416
|
-
const useBooleanBinding = useCustomControlBinding({
|
|
1417
|
-
setDefaultValue: (field2) => {
|
|
1418
|
-
if (field2.value.value === void 0) field2.setValue(false);
|
|
1419
|
-
}
|
|
1420
|
-
});
|
|
1421
|
-
const { wrapper, value, field, onBlur, onChange: onFieldChange } = useBooleanBinding(props.uischema, props.schema);
|
|
1422
|
-
const onChange = (val) => {
|
|
1423
|
-
field.setValue(Boolean(val) ?? false);
|
|
1424
|
-
onFieldChange();
|
|
1425
|
-
};
|
|
1426
|
-
return (_ctx, _cache) => {
|
|
1427
|
-
return vue.openBlock(), vue.createBlock(vue.unref(ui.Checkbox), vue.mergeProps(vue.unref(wrapper), {
|
|
1428
|
-
"model-value": vue.unref(value),
|
|
1429
|
-
onChange,
|
|
1430
|
-
onBlur: vue.unref(onBlur)
|
|
1431
|
-
}), null, 16, ["model-value", "onBlur"]);
|
|
1432
|
-
};
|
|
1433
|
-
}
|
|
1434
|
-
});
|
|
1435
|
-
const _sfc_main$f = /* @__PURE__ */ vue.defineComponent({
|
|
1436
|
-
__name: "MarkdownControlRenderer",
|
|
1437
|
-
props: {
|
|
1438
|
-
uischema: {},
|
|
1439
|
-
schema: {}
|
|
1440
|
-
},
|
|
1441
|
-
setup(__props) {
|
|
1442
|
-
const props = __props;
|
|
1443
|
-
const {
|
|
1444
|
-
wrapper,
|
|
1445
|
-
value,
|
|
1446
|
-
field,
|
|
1447
|
-
onBlur,
|
|
1448
|
-
onChange: onFieldChange
|
|
1449
|
-
} = useControlBinding(props.uischema, props.schema);
|
|
1450
|
-
const onChange = (val) => {
|
|
1451
|
-
field.setValue(val);
|
|
1452
|
-
onFieldChange();
|
|
1453
|
-
};
|
|
1454
|
-
return (_ctx, _cache) => {
|
|
1455
|
-
return vue.openBlock(), vue.createBlock(vue.unref(ui.Markdown), vue.mergeProps(vue.unref(wrapper), {
|
|
1456
|
-
"model-value": vue.unref(value),
|
|
1457
|
-
onChange,
|
|
1458
|
-
onBlur: vue.unref(onBlur)
|
|
1459
|
-
}), null, 16, ["model-value", "onBlur"]);
|
|
1460
|
-
};
|
|
1461
|
-
}
|
|
1462
|
-
});
|
|
1463
|
-
const _sfc_main$e = /* @__PURE__ */ vue.defineComponent({
|
|
1464
|
-
__name: "MultiSelectControlRenderer",
|
|
1465
|
-
props: {
|
|
1466
|
-
uischema: {},
|
|
1467
|
-
schema: {}
|
|
1468
|
-
},
|
|
1469
|
-
setup(__props) {
|
|
1470
|
-
const props = __props;
|
|
1471
|
-
const {
|
|
1472
|
-
wrapper,
|
|
1473
|
-
value,
|
|
1474
|
-
field,
|
|
1475
|
-
onBlur,
|
|
1476
|
-
onChange: onFieldChange,
|
|
1477
|
-
appliedOptions
|
|
1478
|
-
} = useSelectBinding(props.uischema, props.schema);
|
|
1479
|
-
const onChange = (val) => {
|
|
1480
|
-
const opts = appliedOptions.value;
|
|
1481
|
-
const valueKey = opts.valueKey ?? "value";
|
|
1482
|
-
const stored = opts.storeValue && Array.isArray(val) ? val.map((item) => item && typeof item === "object" ? item[valueKey] : item) : val;
|
|
1483
|
-
field.setValue(stored);
|
|
1484
|
-
onFieldChange();
|
|
1485
|
-
};
|
|
1486
|
-
return (_ctx, _cache) => {
|
|
1487
|
-
return vue.openBlock(), vue.createBlock(vue.unref(ui.MultiSelect), vue.mergeProps(vue.unref(wrapper), {
|
|
1488
|
-
"model-value": vue.unref(value),
|
|
1489
|
-
onChange,
|
|
1490
|
-
onBlur: vue.unref(onBlur)
|
|
1491
|
-
}), null, 16, ["model-value", "onBlur"]);
|
|
1492
|
-
};
|
|
1493
|
-
}
|
|
1494
|
-
});
|
|
1495
|
-
const _sfc_main$d = /* @__PURE__ */ vue.defineComponent({
|
|
1496
|
-
__name: "NumberControlRenderer",
|
|
1497
|
-
props: {
|
|
1498
|
-
uischema: {},
|
|
1499
|
-
schema: {}
|
|
1500
|
-
},
|
|
1501
|
-
setup(__props) {
|
|
1502
|
-
const props = __props;
|
|
1503
|
-
const { wrapper, value, onBlur, onChange } = useControlBinding(
|
|
1504
|
-
props.uischema,
|
|
1505
|
-
props.schema,
|
|
1506
|
-
{ defaultType: "number" }
|
|
1507
|
-
);
|
|
1508
|
-
return (_ctx, _cache) => {
|
|
1509
|
-
return vue.openBlock(), vue.createBlock(vue.unref(ui.InputNumber), vue.mergeProps(vue.unref(wrapper), {
|
|
1510
|
-
modelValue: vue.unref(value),
|
|
1511
|
-
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.isRef(value) ? value.value = $event : null),
|
|
1512
|
-
steps: 0.01,
|
|
1513
|
-
onBlur: vue.unref(onBlur),
|
|
1514
|
-
onChange: vue.unref(onChange)
|
|
1515
|
-
}), null, 16, ["modelValue", "onBlur", "onChange"]);
|
|
1516
|
-
};
|
|
1517
|
-
}
|
|
1518
|
-
});
|
|
1519
|
-
const _sfc_main$c = /* @__PURE__ */ vue.defineComponent({
|
|
1520
|
-
__name: "SelectControlRenderer",
|
|
1521
|
-
props: {
|
|
1522
|
-
uischema: {},
|
|
1523
|
-
schema: {}
|
|
1524
|
-
},
|
|
1525
|
-
setup(__props) {
|
|
1526
|
-
const props = __props;
|
|
1527
|
-
const {
|
|
1528
|
-
wrapper,
|
|
1529
|
-
value,
|
|
1530
|
-
field,
|
|
1531
|
-
onBlur,
|
|
1532
|
-
onChange: onFieldChange,
|
|
1533
|
-
appliedOptions
|
|
1534
|
-
} = useSelectBinding(props.uischema, props.schema);
|
|
1535
|
-
const http = useHttpClient();
|
|
1536
|
-
const { values: formValues } = veeValidate.useFormContext();
|
|
1537
|
-
const valueKey = vue.computed(
|
|
1538
|
-
() => appliedOptions.value.valueKey ?? "value"
|
|
1539
|
-
);
|
|
1540
|
-
const isRemote = vue.computed(
|
|
1541
|
-
() => !!appliedOptions.value.uri || !!appliedOptions.value.resource
|
|
1542
|
-
);
|
|
1543
|
-
const remoteOptions = vue.ref([]);
|
|
1544
|
-
vue.watch(
|
|
1545
|
-
[appliedOptions, formValues],
|
|
1546
|
-
async ([opts]) => {
|
|
1547
|
-
if (!isRemote.value) return;
|
|
1548
|
-
const fetcher = await useFetchOptions(
|
|
1549
|
-
opts,
|
|
1550
|
-
http,
|
|
1551
|
-
formValues
|
|
1552
|
-
);
|
|
1553
|
-
if (!fetcher.fetchOptions) return;
|
|
1554
|
-
try {
|
|
1555
|
-
const results = await fetcher.fetchOptions(
|
|
1556
|
-
"",
|
|
1557
|
-
new AbortController().signal
|
|
1558
|
-
);
|
|
1559
|
-
remoteOptions.value = Array.isArray(results) ? results : [];
|
|
1560
|
-
} catch {
|
|
1561
|
-
remoteOptions.value = [];
|
|
1562
|
-
}
|
|
1563
|
-
},
|
|
1564
|
-
{ immediate: true, deep: true }
|
|
1565
|
-
);
|
|
1566
|
-
const selectOptions = vue.computed(() => {
|
|
1567
|
-
if (isRemote.value) return remoteOptions.value;
|
|
1568
|
-
const opts = appliedOptions.value;
|
|
1569
|
-
return opts.options ?? opts.values ?? [];
|
|
1570
|
-
});
|
|
1571
|
-
const onChange = (val) => {
|
|
1572
|
-
const opts = appliedOptions.value;
|
|
1573
|
-
const stored = opts.storeValue && val && typeof val === "object" ? val[valueKey.value] : val;
|
|
1574
|
-
field.setValue(stored);
|
|
1575
|
-
onFieldChange();
|
|
1576
|
-
};
|
|
1577
|
-
return (_ctx, _cache) => {
|
|
1578
|
-
return vue.openBlock(), vue.createBlock(vue.unref(ui.SelectComponent), vue.mergeProps(vue.unref(wrapper), {
|
|
1579
|
-
"model-value": vue.unref(value),
|
|
1580
|
-
options: selectOptions.value,
|
|
1581
|
-
clearable: vue.unref(appliedOptions).clearable ?? true,
|
|
1582
|
-
onChange,
|
|
1583
|
-
onBlur: vue.unref(onBlur)
|
|
1584
|
-
}), null, 16, ["model-value", "options", "clearable", "onBlur"]);
|
|
1585
|
-
};
|
|
1586
|
-
}
|
|
1587
|
-
});
|
|
1588
|
-
const _sfc_main$b = /* @__PURE__ */ vue.defineComponent({
|
|
1589
|
-
__name: "StringControlRenderer",
|
|
1590
|
-
props: {
|
|
1591
|
-
uischema: {},
|
|
1592
|
-
schema: {}
|
|
1593
|
-
},
|
|
1594
|
-
setup(__props) {
|
|
1595
|
-
const props = __props;
|
|
1596
|
-
const { wrapper, value, onBlur, onChange } = useControlBinding(
|
|
1597
|
-
props.uischema,
|
|
1598
|
-
props.schema
|
|
1599
|
-
);
|
|
1600
|
-
return (_ctx, _cache) => {
|
|
1601
|
-
return vue.openBlock(), vue.createBlock(vue.unref(ui.Input), vue.mergeProps(vue.unref(wrapper), {
|
|
1602
|
-
modelValue: vue.unref(value),
|
|
1603
|
-
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.isRef(value) ? value.value = $event : null),
|
|
1604
|
-
onBlur: vue.unref(onBlur),
|
|
1605
|
-
onChange: vue.unref(onChange)
|
|
1606
|
-
}), null, 16, ["modelValue", "onBlur", "onChange"]);
|
|
1607
|
-
};
|
|
1608
|
-
}
|
|
1609
|
-
});
|
|
1610
|
-
const _sfc_main$a = /* @__PURE__ */ vue.defineComponent({
|
|
1611
|
-
__name: "TextAreaControlRenderer",
|
|
1612
|
-
props: {
|
|
1613
|
-
uischema: {},
|
|
1614
|
-
schema: {}
|
|
1615
|
-
},
|
|
1616
|
-
setup(__props) {
|
|
1617
|
-
const props = __props;
|
|
1618
|
-
const { wrapper, value, onBlur, onChange, appliedOptions } = useControlBinding(
|
|
1619
|
-
props.uischema,
|
|
1620
|
-
props.schema
|
|
1621
|
-
);
|
|
1622
|
-
const pathPrefix = vue.inject("pathPrefix", "");
|
|
1623
|
-
const opts = props.uischema.options ?? {};
|
|
1624
|
-
const { values: formValues } = veeValidate.useFormContext();
|
|
1625
|
-
const dir = vue.computed(() => {
|
|
1626
|
-
if (!opts.directionField) return opts.direction ?? "ltr";
|
|
1627
|
-
const key = pathPrefix ? `${pathPrefix}.${opts.directionField}` : opts.directionField;
|
|
1628
|
-
const val = key.split(".").reduce((o, k) => o?.[k], formValues);
|
|
1629
|
-
return val ?? "ltr";
|
|
1630
|
-
});
|
|
1631
|
-
return (_ctx, _cache) => {
|
|
1632
|
-
return vue.openBlock(), vue.createBlock(vue.unref(ui.Textarea), vue.mergeProps(vue.unref(wrapper), {
|
|
1633
|
-
modelValue: vue.unref(value),
|
|
1634
|
-
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.isRef(value) ? value.value = $event : null),
|
|
1635
|
-
dir: dir.value,
|
|
1636
|
-
height: vue.unref(appliedOptions).height,
|
|
1637
|
-
"min-height": vue.unref(appliedOptions).minHeight,
|
|
1638
|
-
onBlur: vue.unref(onBlur),
|
|
1639
|
-
onChange: vue.unref(onChange)
|
|
1640
|
-
}), null, 16, ["modelValue", "dir", "height", "min-height", "onBlur", "onChange"]);
|
|
1641
|
-
};
|
|
1642
|
-
}
|
|
1643
|
-
});
|
|
1644
|
-
const controlRenderers = [
|
|
1645
|
-
{ tester: rankWith(10, isStringFormat), renderer: _sfc_main$b },
|
|
1646
|
-
{
|
|
1647
|
-
tester: rankWith(11, isTextAreaControl),
|
|
1648
|
-
renderer: _sfc_main$a
|
|
1649
|
-
},
|
|
1650
|
-
{
|
|
1651
|
-
tester: rankWith(11, isMarkdownControl),
|
|
1652
|
-
renderer: _sfc_main$f
|
|
1653
|
-
},
|
|
1654
|
-
{ tester: rankWith(11, isBooleanControl), renderer: _sfc_main$g },
|
|
1655
|
-
{ tester: rankWith(11, isSelectControl), renderer: _sfc_main$c },
|
|
1656
|
-
{
|
|
1657
|
-
tester: rankWith(11, isMultiselectControl),
|
|
1658
|
-
renderer: _sfc_main$e
|
|
1659
|
-
},
|
|
1660
|
-
{
|
|
1661
|
-
tester: rankWith(12, isAutoCompleteControl),
|
|
1662
|
-
renderer: _sfc_main$h
|
|
1663
|
-
},
|
|
1664
|
-
{
|
|
1665
|
-
tester: rankWith(12, isNumberFormat),
|
|
1666
|
-
renderer: _sfc_main$d
|
|
1667
|
-
},
|
|
1668
|
-
{
|
|
1669
|
-
tester: rankWith(12, isIntegerFormat),
|
|
1670
|
-
renderer: _sfc_main$d
|
|
1671
|
-
}
|
|
1672
|
-
];
|
|
1673
|
-
const _sfc_main$9 = /* @__PURE__ */ vue.defineComponent({
|
|
1674
|
-
__name: "ControlReadonlyRenderer",
|
|
1675
|
-
props: {
|
|
1676
|
-
uischema: {},
|
|
1677
|
-
schema: {}
|
|
1678
|
-
},
|
|
1679
|
-
setup(__props) {
|
|
1680
|
-
const props = __props;
|
|
1681
|
-
const { wrapper, displayWrapper } = useReadonlyControlBinding(
|
|
1682
|
-
props.uischema,
|
|
1683
|
-
props.schema
|
|
1684
|
-
);
|
|
1685
|
-
return (_ctx, _cache) => {
|
|
1686
|
-
return vue.openBlock(), vue.createBlock(_sfc_main$u, vue.normalizeProps(vue.guardReactiveProps(vue.unref(wrapper))), {
|
|
1687
|
-
default: vue.withCtx(() => [
|
|
1688
|
-
(vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(vue.unref(displayWrapper).component), vue.normalizeProps(vue.guardReactiveProps(vue.unref(displayWrapper).value)), null, 16))
|
|
1689
|
-
]),
|
|
1690
|
-
_: 1
|
|
1691
|
-
}, 16);
|
|
1692
|
-
};
|
|
1693
|
-
}
|
|
1694
|
-
});
|
|
1695
|
-
const readonlyControlRenderers = [
|
|
1696
|
-
{
|
|
1697
|
-
tester: rankWith(10, uiTypeIs("Control")),
|
|
1698
|
-
renderer: _sfc_main$9
|
|
1699
|
-
}
|
|
1700
|
-
];
|
|
1701
|
-
const COLSPAN = {
|
|
1702
|
-
1: "col-span-1",
|
|
1703
|
-
2: "col-span-2",
|
|
1704
|
-
3: "col-span-3",
|
|
1705
|
-
4: "col-span-4",
|
|
1706
|
-
5: "col-span-5",
|
|
1707
|
-
6: "col-span-6",
|
|
1708
|
-
7: "col-span-7",
|
|
1709
|
-
8: "col-span-8",
|
|
1710
|
-
9: "col-span-9",
|
|
1711
|
-
10: "col-span-10",
|
|
1712
|
-
11: "col-span-11",
|
|
1713
|
-
12: "col-span-12"
|
|
1714
|
-
};
|
|
1715
|
-
const _hoisted_1$7 = { class: "flex flex-col gap-4" };
|
|
1716
|
-
const _sfc_main$8 = /* @__PURE__ */ vue.defineComponent({
|
|
1717
|
-
__name: "CollapseLayoutRenderer",
|
|
1718
|
-
props: {
|
|
1719
|
-
uischema: {},
|
|
1720
|
-
schema: {}
|
|
1721
|
-
},
|
|
1722
|
-
setup(__props) {
|
|
1723
|
-
const props = __props;
|
|
1724
|
-
const pathPrefix = vue.inject("pathPrefix", "");
|
|
1725
|
-
const opts = props.uischema.options ?? {};
|
|
1726
|
-
const titleKeyField = opts.titleKey ? veeValidate.useFieldValue(
|
|
1727
|
-
() => pathPrefix ? `${pathPrefix}.${opts.titleKey}` : opts.titleKey
|
|
1728
|
-
) : void 0;
|
|
1729
|
-
const title = vue.computed(() => {
|
|
1730
|
-
if (titleKeyField?.value) return titleKeyField.value;
|
|
1731
|
-
return props.uischema.label ?? opts.title ?? "Details";
|
|
1732
|
-
});
|
|
1733
|
-
return (_ctx, _cache) => {
|
|
1734
|
-
return vue.openBlock(), vue.createBlock(vue.unref(ui.Collapse), { title: title.value }, {
|
|
1735
|
-
default: vue.withCtx(() => [
|
|
1736
|
-
vue.createElementVNode("div", _hoisted_1$7, [
|
|
1737
|
-
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.uischema.elements, (child, i) => {
|
|
1738
|
-
return vue.openBlock(), vue.createElementBlock("div", {
|
|
1739
|
-
key: i,
|
|
1740
|
-
class: vue.normalizeClass(vue.unref(COLSPAN)[child.options?.colspan ?? 12])
|
|
1741
|
-
}, [
|
|
1742
|
-
vue.createVNode(_sfc_main$5, {
|
|
1743
|
-
uischema: child,
|
|
1744
|
-
schema: __props.schema
|
|
1745
|
-
}, null, 8, ["uischema", "schema"])
|
|
1746
|
-
], 2);
|
|
1747
|
-
}), 128))
|
|
1748
|
-
])
|
|
1749
|
-
]),
|
|
1750
|
-
_: 1
|
|
1751
|
-
}, 8, ["title"]);
|
|
1752
|
-
};
|
|
1753
|
-
}
|
|
1754
|
-
});
|
|
1755
|
-
const _hoisted_1$6 = {
|
|
1756
|
-
key: 1,
|
|
1757
|
-
class: "flex flex-col gap-3"
|
|
1758
|
-
};
|
|
1759
|
-
const _sfc_main$7 = /* @__PURE__ */ vue.defineComponent({
|
|
1760
|
-
__name: "LayoutRenderer",
|
|
1761
|
-
props: {
|
|
1762
|
-
uischema: {},
|
|
1763
|
-
schema: {}
|
|
1764
|
-
},
|
|
1765
|
-
setup(__props) {
|
|
1766
|
-
const props = __props;
|
|
1767
|
-
const LAYOUT = {
|
|
1768
|
-
// Stack on narrow viewports (e.g. small modals), switch to the 12-column
|
|
1769
|
-
// grid at md+. Children keep their `col-span-*`; with a single column the
|
|
1770
|
-
// span clamps to full width, so fields stack cleanly.
|
|
1771
|
-
GridLayout: "grid grid-cols-1 gap-x-3 md:grid-cols-12",
|
|
1772
|
-
HorizontalLayout: "flex flex-col gap-y-3 md:flex-row",
|
|
1773
|
-
VerticalLayout: "flex flex-col gap-3"
|
|
1774
|
-
};
|
|
1775
|
-
const getLayout = vue.computed(() => LAYOUT[props.uischema.type]);
|
|
1776
|
-
const isLayout = vue.computed(() => props.uischema.type in LAYOUT);
|
|
1777
|
-
return (_ctx, _cache) => {
|
|
1778
|
-
return isLayout.value ? (vue.openBlock(), vue.createElementBlock("div", {
|
|
1779
|
-
key: 0,
|
|
1780
|
-
class: vue.normalizeClass(getLayout.value)
|
|
1781
|
-
}, [
|
|
1782
|
-
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.uischema.elements, (child, i) => {
|
|
1783
|
-
return vue.openBlock(), vue.createElementBlock("div", {
|
|
1784
|
-
key: i,
|
|
1785
|
-
class: vue.normalizeClass(vue.unref(COLSPAN)[child.options?.colspan ?? 12])
|
|
1786
|
-
}, [
|
|
1787
|
-
vue.createVNode(_sfc_main$5, {
|
|
1788
|
-
uischema: child,
|
|
1789
|
-
schema: __props.schema
|
|
1790
|
-
}, null, 8, ["uischema", "schema"])
|
|
1791
|
-
], 2);
|
|
1792
|
-
}), 128))
|
|
1793
|
-
], 2)) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$6, " No Applicable Layout found "));
|
|
1794
|
-
};
|
|
1795
|
-
}
|
|
1796
|
-
});
|
|
1797
|
-
const _hoisted_1$5 = {
|
|
1798
|
-
class: "grid items-center overflow-hidden",
|
|
1799
|
-
style: { "grid-template-columns": "minmax(150px, auto) minmax(0, 1fr)" }
|
|
1800
|
-
};
|
|
1801
|
-
const _sfc_main$6 = /* @__PURE__ */ vue.defineComponent({
|
|
1802
|
-
__name: "ReadOnlyLayoutRenderer",
|
|
1803
|
-
props: {
|
|
1804
|
-
uischema: {},
|
|
1805
|
-
schema: {}
|
|
1806
|
-
},
|
|
1807
|
-
setup(__props) {
|
|
1808
|
-
return (_ctx, _cache) => {
|
|
1809
|
-
return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$5, [
|
|
1810
|
-
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.uischema.elements, (child, i) => {
|
|
1811
|
-
return vue.openBlock(), vue.createBlock(_sfc_main$5, {
|
|
1812
|
-
key: i,
|
|
1813
|
-
uischema: child,
|
|
1814
|
-
schema: __props.schema
|
|
1815
|
-
}, null, 8, ["uischema", "schema"]);
|
|
1816
|
-
}), 128))
|
|
1817
|
-
]);
|
|
1818
|
-
};
|
|
1819
|
-
}
|
|
1820
|
-
});
|
|
1821
|
-
const isLayoutType = or(
|
|
1822
|
-
uiTypeIs("GridLayout"),
|
|
1823
|
-
uiTypeIs("HorizontalLayout"),
|
|
1824
|
-
uiTypeIs("VerticalLayout")
|
|
1825
|
-
);
|
|
1826
|
-
const layoutRenderers = [
|
|
1827
|
-
{ tester: rankWith(10, isLayoutType), renderer: _sfc_main$7 },
|
|
1828
|
-
{
|
|
1829
|
-
tester: rankWith(10, uiTypeIs("CollapseLayout")),
|
|
1830
|
-
renderer: _sfc_main$8
|
|
1831
|
-
}
|
|
1832
|
-
];
|
|
1833
|
-
const readonlyLayoutRenderers = [
|
|
1834
|
-
{ tester: rankWith(10, isLayoutType), renderer: _sfc_main$6 },
|
|
1835
|
-
{
|
|
1836
|
-
tester: rankWith(10, uiTypeIs("CollapseLayout")),
|
|
1837
|
-
renderer: _sfc_main$8
|
|
1838
|
-
}
|
|
1839
|
-
];
|
|
1840
|
-
const customRenderers = [
|
|
1841
|
-
layoutRenderers,
|
|
1842
|
-
controlRenderers,
|
|
1843
|
-
arrayRenderers
|
|
1844
|
-
].flat();
|
|
1845
|
-
const readonlyRenderers = [
|
|
1846
|
-
readonlyLayoutRenderers,
|
|
1847
|
-
readonlyControlRenderers,
|
|
1848
|
-
arrayRenderers
|
|
1849
|
-
].flat();
|
|
1850
|
-
function findRenderer(registry, uischema, schema) {
|
|
1851
|
-
let best = null;
|
|
1852
|
-
for (const entry of registry) {
|
|
1853
|
-
const rank = entry.tester(uischema, schema);
|
|
1854
|
-
if (rank > -1 && (!best || rank > best.rank)) {
|
|
1855
|
-
best = { rank, renderer: entry.renderer };
|
|
1856
|
-
}
|
|
1857
|
-
}
|
|
1858
|
-
return best?.renderer ?? null;
|
|
1859
|
-
}
|
|
1860
|
-
const _hoisted_1$4 = {
|
|
1861
|
-
key: 1,
|
|
1862
|
-
class: "text-error text-xs"
|
|
1863
|
-
};
|
|
1864
|
-
const _sfc_main$5 = /* @__PURE__ */ vue.defineComponent({
|
|
1865
|
-
__name: "Dispatch",
|
|
1866
|
-
props: {
|
|
1867
|
-
uischema: {},
|
|
1868
|
-
schema: {},
|
|
1869
|
-
pathPrefix: { default: void 0 }
|
|
1870
|
-
},
|
|
1871
|
-
setup(__props) {
|
|
1872
|
-
const props = __props;
|
|
1873
|
-
const editableRegistry = vue.inject("renderers");
|
|
1874
|
-
const extraReadonlyRenderers = vue.inject("readonlyRenderers", []);
|
|
1875
|
-
const formReadonly = vue.inject(FORM_READONLY_KEY, vue.ref(false));
|
|
1876
|
-
const effectiveReadonlyRenderers = vue.computed(
|
|
1877
|
-
() => extraReadonlyRenderers.length ? [...readonlyRenderers, ...extraReadonlyRenderers] : readonlyRenderers
|
|
1878
|
-
);
|
|
1879
|
-
const registry = vue.computed(
|
|
1880
|
-
() => formReadonly.value ? effectiveReadonlyRenderers.value : editableRegistry
|
|
1881
|
-
);
|
|
1882
|
-
const rootSchema = vue.inject("rootSchema");
|
|
1883
|
-
const parentPrefix = vue.inject("pathPrefix", "");
|
|
1884
|
-
const effectivePrefix = props.pathPrefix ?? parentPrefix;
|
|
1885
|
-
if (props.pathPrefix !== void 0) {
|
|
1886
|
-
vue.provide("pathPrefix", effectivePrefix);
|
|
1887
|
-
}
|
|
1888
|
-
const resolved = vue.computed(() => {
|
|
1889
|
-
const u = props.uischema;
|
|
1890
|
-
if (!u.scope) return props.schema;
|
|
1891
|
-
const fromRoot = resolveSchema(rootSchema, u.scope);
|
|
1892
|
-
if (fromRoot) return fromRoot;
|
|
1893
|
-
return resolveSchema(props.schema, u.scope) ?? props.schema;
|
|
1894
|
-
});
|
|
1895
|
-
const renderer = vue.computed(
|
|
1896
|
-
() => findRenderer(
|
|
1897
|
-
registry.value,
|
|
1898
|
-
props.uischema,
|
|
1899
|
-
resolved.value
|
|
1900
|
-
)
|
|
1901
|
-
);
|
|
1902
|
-
return (_ctx, _cache) => {
|
|
1903
|
-
return renderer.value ? (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(renderer.value), {
|
|
1904
|
-
key: 0,
|
|
1905
|
-
uischema: __props.uischema,
|
|
1906
|
-
schema: resolved.value
|
|
1907
|
-
}, null, 8, ["uischema", "schema"])) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$4, " No renderer for " + vue.toDisplayString(__props.uischema.scope) + " type: " + vue.toDisplayString(__props.uischema.type), 1));
|
|
1908
|
-
};
|
|
1909
|
-
}
|
|
1910
|
-
});
|
|
1911
|
-
const JsonFormComponentProperties = {
|
|
1912
|
-
/** Unique identifier used to namespace the form element. */
|
|
1913
|
-
id: { type: String, required: true },
|
|
1914
|
-
/** HTML name attribute for the form. */
|
|
1915
|
-
name: { type: String, default: "form" },
|
|
1916
|
-
/** JSON schema describing the shape of the form data. */
|
|
1917
|
-
schema: { type: Object, required: true },
|
|
1918
|
-
/** UI schema describing the layout and controls. */
|
|
1919
|
-
uiSchema: { type: Object, required: true },
|
|
1920
|
-
/** Disable all form controls. */
|
|
1921
|
-
disabled: { type: Boolean, default: false },
|
|
1922
|
-
/** Make all form controls readonly. */
|
|
1923
|
-
readonly: { type: Boolean, default: false },
|
|
1924
|
-
/** Current form data object. */
|
|
1925
|
-
formData: { type: Object, default: () => ({}) },
|
|
1926
|
-
/** When validation errors are shown (`'onBlur'`, `'onChange'`, `'onSubmit'`, `'always'`). */
|
|
1927
|
-
errorMode: {
|
|
1928
|
-
type: String,
|
|
1929
|
-
default: "onChanges"
|
|
1930
|
-
},
|
|
1931
|
-
/** HTTP client used by renderers that fetch remote data (e.g. autocomplete). */
|
|
1932
|
-
http: {
|
|
1933
|
-
type: Object,
|
|
1934
|
-
default: null
|
|
1935
|
-
},
|
|
1936
|
-
/** Custom renderer registry. Overrides the default `customRenderers` when provided. */
|
|
1937
|
-
renderers: {
|
|
1938
|
-
type: Array,
|
|
1939
|
-
default: null
|
|
1940
|
-
}
|
|
1941
|
-
};
|
|
1942
|
-
const JsonFormComponentEmits = [
|
|
1943
|
-
/** Emitted when form data changes. */
|
|
1944
|
-
"change",
|
|
1945
|
-
/** Emitted on form submission. */
|
|
1946
|
-
"submit",
|
|
1947
|
-
/** Emitted when validation errors change. */
|
|
1948
|
-
"errors",
|
|
1949
|
-
/** Emitted when form validity changes. */
|
|
1950
|
-
"valid",
|
|
1951
|
-
/** Emitted when a custom renderer dispatches a form event. */
|
|
1952
|
-
"events"
|
|
1953
|
-
];
|
|
1954
|
-
const _hoisted_1$3 = ["id"];
|
|
1955
|
-
const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({
|
|
1956
|
-
__name: "FormComponent",
|
|
1957
|
-
props: JsonFormComponentProperties,
|
|
1958
|
-
emits: JsonFormComponentEmits,
|
|
1959
|
-
setup(__props, { expose: __expose, emit: __emit }) {
|
|
1960
|
-
registerZodErrorMap();
|
|
1961
|
-
const properties = __props;
|
|
1962
|
-
const emits = __emit;
|
|
1963
|
-
const zodSchema = vue.computed(() => {
|
|
1964
|
-
if (!properties.schema) return void 0;
|
|
1965
|
-
try {
|
|
1966
|
-
const patched = jsonFormsCore.enforceRequiredStringMinLength(properties.schema);
|
|
1967
|
-
return zod.fromJSONSchema(patched);
|
|
1968
|
-
} catch {
|
|
1969
|
-
return void 0;
|
|
1970
|
-
}
|
|
1971
|
-
});
|
|
1972
|
-
const { values, errors, meta, setValues, validate } = veeValidate.useForm({
|
|
1973
|
-
validationSchema: zodSchema,
|
|
1974
|
-
initialValues: properties.formData
|
|
1975
|
-
});
|
|
1976
|
-
vue.provide(
|
|
1977
|
-
"renderers",
|
|
1978
|
-
properties.renderers?.length ? [...customRenderers, ...properties.renderers] : customRenderers
|
|
1979
|
-
);
|
|
1980
|
-
vue.provide("readonlyRenderers", properties.renderers ?? []);
|
|
1981
|
-
vue.provide("rootSchema", properties.schema);
|
|
1982
|
-
vue.provide("styles", ui.myStyles);
|
|
1983
|
-
const submitted = vue.ref(false);
|
|
1984
|
-
vue.provide(ERROR_MODE_KEY, vue.toRef(properties, "errorMode"));
|
|
1985
|
-
vue.provide(FORM_SUBMITTED_KEY, submitted);
|
|
1986
|
-
vue.provide(FORM_READONLY_KEY, vue.toRef(properties, "readonly"));
|
|
1987
|
-
vue.onMounted(async () => {
|
|
1988
|
-
const result = await validate();
|
|
1989
|
-
emits("valid", result.valid);
|
|
1990
|
-
});
|
|
1991
|
-
provideFormEvents((payload) => {
|
|
1992
|
-
emits("events", payload);
|
|
1993
|
-
});
|
|
1994
|
-
if (properties.http) {
|
|
1995
|
-
provideHttpClient(properties.http);
|
|
1996
|
-
}
|
|
1997
|
-
let syncing = false;
|
|
1998
|
-
vue.watch(
|
|
1999
|
-
() => properties.formData,
|
|
2000
|
-
(newData) => {
|
|
2001
|
-
if (!newData) return;
|
|
2002
|
-
if (JSON.stringify(newData) === JSON.stringify(vue.toRaw(values))) return;
|
|
2003
|
-
syncing = true;
|
|
2004
|
-
setValues(newData);
|
|
2005
|
-
vue.nextTick(() => {
|
|
2006
|
-
syncing = false;
|
|
2007
|
-
});
|
|
2008
|
-
},
|
|
2009
|
-
{ deep: true }
|
|
2010
|
-
);
|
|
2011
|
-
vue.watch(
|
|
2012
|
-
values,
|
|
2013
|
-
(newValues) => {
|
|
2014
|
-
if (syncing) return;
|
|
2015
|
-
const isValid = meta.value.valid;
|
|
2016
|
-
emits("valid", isValid);
|
|
2017
|
-
emits("change", vue.toRaw(newValues));
|
|
2018
|
-
},
|
|
2019
|
-
{ deep: true }
|
|
2020
|
-
);
|
|
2021
|
-
vue.watch(
|
|
2022
|
-
errors,
|
|
2023
|
-
(newErrors) => {
|
|
2024
|
-
const errorList = Object.entries(newErrors).filter(([, msg]) => !!msg).map(([path, message]) => ({ path, message }));
|
|
2025
|
-
emits("errors", errorList);
|
|
2026
|
-
},
|
|
2027
|
-
{ deep: true }
|
|
2028
|
-
);
|
|
2029
|
-
const onSubmit = () => {
|
|
2030
|
-
submitted.value = true;
|
|
2031
|
-
emits("submit", {
|
|
2032
|
-
data: vue.toRaw(values),
|
|
2033
|
-
valid: meta.value.valid
|
|
2034
|
-
});
|
|
2035
|
-
};
|
|
2036
|
-
const markSubmitted = () => {
|
|
2037
|
-
submitted.value = true;
|
|
2038
|
-
};
|
|
2039
|
-
__expose({ markSubmitted });
|
|
2040
|
-
return (_ctx, _cache) => {
|
|
2041
|
-
return vue.openBlock(), vue.createElementBlock("form", {
|
|
2042
|
-
id: _ctx.id,
|
|
2043
|
-
onSubmit: vue.withModifiers(onSubmit, ["prevent"])
|
|
2044
|
-
}, [
|
|
2045
|
-
vue.createVNode(_sfc_main$5, {
|
|
2046
|
-
uischema: _ctx.uiSchema,
|
|
2047
|
-
schema: _ctx.schema
|
|
2048
|
-
}, null, 8, ["uischema", "schema"])
|
|
2049
|
-
], 40, _hoisted_1$3);
|
|
2050
|
-
};
|
|
2051
|
-
}
|
|
2052
|
-
});
|
|
2053
|
-
const createRepository = (formSchemaModel, httpRequest, options = {}) => {
|
|
2054
|
-
const notificationEntity = options.notification?.entityType || "entity";
|
|
2055
|
-
const notificationStore = options.notification?.notification ?? null;
|
|
2056
|
-
const getDataUri = (...suffix) => {
|
|
2057
|
-
return [formSchemaModel.uri, ...suffix].join("/");
|
|
2058
|
-
};
|
|
2059
|
-
const handleSuccess = (message) => {
|
|
2060
|
-
notificationStore?.success(message);
|
|
2061
|
-
};
|
|
2062
|
-
const handleError = (error, message) => {
|
|
2063
|
-
console.error(error);
|
|
2064
|
-
notificationStore?.error(message);
|
|
2065
|
-
throw new Error(error);
|
|
2066
|
-
};
|
|
2067
|
-
const create = (object, options2) => {
|
|
2068
|
-
return httpRequest.post(getDataUri(), object, options2).then((response) => {
|
|
2069
|
-
handleSuccess(`Created ${notificationEntity}`);
|
|
2070
|
-
return response.data;
|
|
2071
|
-
}).catch((response) => {
|
|
2072
|
-
handleError(response, `Failed to create ${notificationEntity}`);
|
|
2073
|
-
});
|
|
2074
|
-
};
|
|
2075
|
-
const patch = (id, object, options2) => {
|
|
2076
|
-
return httpRequest.patch(getDataUri(id), object, options2).then((response) => {
|
|
2077
|
-
handleSuccess(`Saved ${notificationEntity}`);
|
|
2078
|
-
return response.data;
|
|
2079
|
-
}).catch((response) => {
|
|
2080
|
-
handleError(response, `Failed to save ${notificationEntity}`);
|
|
2081
|
-
});
|
|
2082
|
-
};
|
|
2083
|
-
const get = (id, options2) => {
|
|
2084
|
-
return httpRequest.get(getDataUri(id), options2).then((response) => {
|
|
2085
|
-
return response.data;
|
|
2086
|
-
}).catch((response) => {
|
|
2087
|
-
handleError(response, "Failed to load data");
|
|
2088
|
-
});
|
|
2089
|
-
};
|
|
2090
|
-
const _delete = (id, options2) => {
|
|
2091
|
-
return httpRequest.delete(getDataUri(id), options2).then((response) => {
|
|
2092
|
-
handleSuccess(`${notificationEntity} deleted`);
|
|
2093
|
-
return response;
|
|
2094
|
-
}).catch((response) => {
|
|
2095
|
-
handleError(response, `Failed to delete ${notificationEntity}`);
|
|
2096
|
-
});
|
|
2097
|
-
};
|
|
2098
|
-
const createMulti = (objects, options2) => {
|
|
2099
|
-
return Promise.all(
|
|
2100
|
-
objects.map((object) => httpRequest.post(getDataUri(), object, options2))
|
|
2101
|
-
).then((responses) => {
|
|
2102
|
-
handleSuccess(`Created ${notificationEntity}`);
|
|
2103
|
-
return responses.map((r) => r.data);
|
|
2104
|
-
}).catch((response) => {
|
|
2105
|
-
handleError(response, `Failed to save ${notificationEntity}`);
|
|
2106
|
-
});
|
|
2107
|
-
};
|
|
2108
|
-
return { create, patch, createMulti, delete: _delete, get };
|
|
2109
|
-
};
|
|
2110
|
-
const TableComponentProperties = {
|
|
2111
|
-
id: { type: String, required: true },
|
|
2112
|
-
uiSchema: { type: Object, required: true },
|
|
2113
|
-
schema: { type: Object, required: true },
|
|
2114
|
-
reload: { type: Number },
|
|
2115
|
-
loading: { type: Boolean, default: false },
|
|
2116
|
-
multiselect: { type: Boolean, default: false },
|
|
2117
|
-
actions: { type: Array },
|
|
2118
|
-
data: { type: Array },
|
|
2119
|
-
page: { type: Object },
|
|
2120
|
-
sort: { type: Object },
|
|
2121
|
-
cellRenderers: { type: Array },
|
|
2122
|
-
hidePagination: { type: Boolean, default: false }
|
|
2123
|
-
};
|
|
2124
|
-
const TableComponentEmits = [
|
|
2125
|
-
"updatePage",
|
|
2126
|
-
"updatePageSize",
|
|
2127
|
-
"sort",
|
|
2128
|
-
"selectionChange"
|
|
2129
|
-
];
|
|
2130
|
-
const cellTypeIs = (type, rank) => (element) => element.type === type ? rank : -1;
|
|
2131
|
-
const cellFormatIs = (format, rank) => (element) => element.options?.format === format ? rank : -1;
|
|
2132
|
-
const findCellRenderer = (registry, element) => {
|
|
2133
|
-
let best;
|
|
2134
|
-
for (const entry of registry) {
|
|
2135
|
-
const rank = entry.tester(element);
|
|
2136
|
-
if (rank > -1 && (!best || rank > best.rank)) {
|
|
2137
|
-
best = { rank, renderer: entry.renderer };
|
|
2138
|
-
}
|
|
2139
|
-
}
|
|
2140
|
-
return best?.renderer;
|
|
2141
|
-
};
|
|
2142
|
-
const defaultCellRenderers = [
|
|
2143
|
-
{ tester: cellTypeIs("TextCell", 10), renderer: ui.TextCell },
|
|
2144
|
-
{ tester: cellTypeIs("BooleanCell", 10), renderer: ui.BooleanCell }
|
|
2145
|
-
];
|
|
2146
|
-
const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({
|
|
2147
|
-
__name: "TableComponent",
|
|
2148
|
-
props: TableComponentProperties,
|
|
2149
|
-
emits: TableComponentEmits,
|
|
2150
|
-
setup(__props, { emit: __emit }) {
|
|
2151
|
-
const properties = __props;
|
|
2152
|
-
const emits = __emit;
|
|
2153
|
-
const allRenderers = vue.computed(() => [
|
|
2154
|
-
...properties.cellRenderers ?? [],
|
|
2155
|
-
...defaultCellRenderers
|
|
2156
|
-
]);
|
|
2157
|
-
const displayColumns = vue.computed(
|
|
2158
|
-
() => properties.uiSchema.elements.map((e) => {
|
|
2159
|
-
const element = e;
|
|
2160
|
-
const def = jsonFormsCore.findColumnDef(element, properties.schema);
|
|
2161
|
-
const type = Array.isArray(def.type) ? def.type[0] : def.type;
|
|
2162
|
-
const component = findCellRenderer(allRenderers.value, element);
|
|
2163
|
-
if (!component)
|
|
2164
|
-
console.warn("No cell renderer found for", element.type, element.options?.format);
|
|
2165
|
-
return {
|
|
2166
|
-
...def,
|
|
2167
|
-
label: e.options?.label ?? def.id,
|
|
2168
|
-
type,
|
|
2169
|
-
component
|
|
2170
|
-
};
|
|
2171
|
-
})
|
|
2172
|
-
);
|
|
2173
|
-
return (_ctx, _cache) => {
|
|
2174
|
-
return vue.openBlock(), vue.createBlock(vue.unref(ui.Table), vue.mergeProps(properties, {
|
|
2175
|
-
"display-columns": displayColumns.value,
|
|
2176
|
-
page: _ctx.hidePagination ? void 0 : _ctx.page,
|
|
2177
|
-
onSort: _cache[0] || (_cache[0] = (id) => emits("sort", id)),
|
|
2178
|
-
onUpdatePage: _cache[1] || (_cache[1] = (page) => emits("updatePage", page)),
|
|
2179
|
-
onUpdatePageSize: _cache[2] || (_cache[2] = (size) => emits("updatePageSize", size)),
|
|
2180
|
-
onSelectionChange: _cache[3] || (_cache[3] = (e) => emits("selectionChange", e))
|
|
2181
|
-
}), null, 16, ["display-columns", "page"]);
|
|
2182
|
-
};
|
|
2183
|
-
}
|
|
2184
|
-
});
|
|
2185
|
-
const _hoisted_1$2 = { class: "flex gap-2 items-center" };
|
|
2186
|
-
const _hoisted_2$2 = {
|
|
2187
|
-
key: 1,
|
|
2188
|
-
class: "flex-1 min-w-0"
|
|
2189
|
-
};
|
|
2190
|
-
const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
|
|
2191
|
-
__name: "FilterRowInput",
|
|
2192
|
-
props: {
|
|
2193
|
-
modelValue: {},
|
|
2194
|
-
fields: {}
|
|
2195
|
-
},
|
|
2196
|
-
emits: ["update:modelValue", "remove"],
|
|
2197
|
-
setup(__props, { emit: __emit }) {
|
|
2198
|
-
const props = __props;
|
|
2199
|
-
const emit = __emit;
|
|
2200
|
-
const noValue = vue.computed(() => jsonFormsCore.OperatorNoValue.has(props.modelValue.operator));
|
|
2201
|
-
const update = (key, value) => {
|
|
2202
|
-
emit("update:modelValue", { ...props.modelValue, [key]: value });
|
|
2203
|
-
};
|
|
2204
|
-
const onOperatorChange = (op) => {
|
|
2205
|
-
emit("update:modelValue", {
|
|
2206
|
-
...props.modelValue,
|
|
2207
|
-
operator: op,
|
|
2208
|
-
value: jsonFormsCore.OperatorNoValue.has(op) ? "" : props.modelValue.value
|
|
2209
|
-
});
|
|
2210
|
-
};
|
|
2211
|
-
return (_ctx, _cache) => {
|
|
2212
|
-
return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$2, [
|
|
2213
|
-
vue.createVNode(vue.unref(ui.SelectComponent), {
|
|
2214
|
-
size: "sm",
|
|
2215
|
-
value: __props.modelValue.key,
|
|
2216
|
-
options: __props.fields,
|
|
2217
|
-
clearable: false,
|
|
2218
|
-
onChange: _cache[0] || (_cache[0] = ($event) => update("key", $event.value))
|
|
2219
|
-
}, null, 8, ["value", "options"]),
|
|
2220
|
-
vue.createVNode(vue.unref(ui.SelectComponent), {
|
|
2221
|
-
size: "sm",
|
|
2222
|
-
value: __props.modelValue.operator,
|
|
2223
|
-
options: vue.unref(jsonFormsCore.OperatorOptions),
|
|
2224
|
-
clearable: false,
|
|
2225
|
-
onChange: _cache[1] || (_cache[1] = ($event) => onOperatorChange($event.value))
|
|
2226
|
-
}, null, 8, ["value", "options"]),
|
|
2227
|
-
!noValue.value ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Input), {
|
|
2228
|
-
key: 0,
|
|
2229
|
-
size: "sm",
|
|
2230
|
-
placeholder: "Enter a value",
|
|
2231
|
-
value: __props.modelValue.value,
|
|
2232
|
-
clearable: true,
|
|
2233
|
-
onInput: _cache[2] || (_cache[2] = ($event) => update("value", $event.target.value))
|
|
2234
|
-
}, null, 8, ["value"])) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$2)),
|
|
2235
|
-
vue.createVNode(vue.unref(ui.Btn), {
|
|
2236
|
-
icon: vue.unref(ui.IconEnum).Delete,
|
|
2237
|
-
size: "xs",
|
|
2238
|
-
outline: true,
|
|
2239
|
-
color: "error",
|
|
2240
|
-
"no-border": true,
|
|
2241
|
-
tooltip: "Remove filter",
|
|
2242
|
-
onClick: _cache[3] || (_cache[3] = ($event) => _ctx.$emit("remove"))
|
|
2243
|
-
}, null, 8, ["icon"])
|
|
2244
|
-
]);
|
|
2245
|
-
};
|
|
2246
|
-
}
|
|
2247
|
-
});
|
|
2248
|
-
const _hoisted_1$1 = { class: "px-2 flex gap-2 items-center" };
|
|
2249
|
-
const _hoisted_2$1 = {
|
|
2250
|
-
key: 0,
|
|
2251
|
-
class: "badge badge-sm bg-base-300 text-base-700"
|
|
2252
|
-
};
|
|
2253
|
-
const _hoisted_3$1 = {
|
|
2254
|
-
key: 0,
|
|
2255
|
-
class: "absolute left-1/2 -translate-x-1/2 top-full mt-1 z-50 min-w-[560px] border border-base-200 rounded-xl bg-base-100 shadow-lg p-4"
|
|
2256
|
-
};
|
|
2257
|
-
const _hoisted_4$1 = { class: "flex flex-col gap-2" };
|
|
2258
|
-
const _hoisted_5$1 = { class: "flex items-center justify-between" };
|
|
2259
|
-
const _hoisted_6$1 = { class: "flex gap-2" };
|
|
2260
|
-
const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
|
|
2261
|
-
__name: "TableFilter",
|
|
2262
|
-
props: {
|
|
2263
|
-
filters: {},
|
|
2264
|
-
filterSchema: {}
|
|
2265
|
-
},
|
|
2266
|
-
emits: ["changeFilters", "close"],
|
|
2267
|
-
setup(__props, { emit: __emit }) {
|
|
2268
|
-
const showFilters = vue.ref(false);
|
|
2269
|
-
const appliedCount = vue.ref(0);
|
|
2270
|
-
const containerRef = vue.ref(null);
|
|
2271
|
-
const onClickOutside = (event) => {
|
|
2272
|
-
const target = event.target;
|
|
2273
|
-
if (containerRef.value?.contains(target)) return;
|
|
2274
|
-
if (target.closest?.("[data-select-listbox]")) return;
|
|
2275
|
-
showFilters.value = false;
|
|
2276
|
-
};
|
|
2277
|
-
vue.onMounted(() => document.addEventListener("mousedown", onClickOutside));
|
|
2278
|
-
vue.onBeforeUnmount(
|
|
2279
|
-
() => document.removeEventListener("mousedown", onClickOutside)
|
|
2280
|
-
);
|
|
2281
|
-
const props = __props;
|
|
2282
|
-
const emit = __emit;
|
|
2283
|
-
const fields = vue.computed(() => {
|
|
2284
|
-
const properties = props.filterSchema?.properties;
|
|
2285
|
-
if (!properties) return [];
|
|
2286
|
-
return Object.entries(properties).map(([key, schema]) => ({
|
|
2287
|
-
value: key,
|
|
2288
|
-
label: schema.title ?? key
|
|
2289
|
-
}));
|
|
2290
|
-
});
|
|
2291
|
-
const defaultField = vue.computed(() => fields.value[0]?.value ?? "");
|
|
2292
|
-
const rows = vue.ref([]);
|
|
2293
|
-
const emptyRow = () => ({
|
|
2294
|
-
key: defaultField.value,
|
|
2295
|
-
value: "",
|
|
2296
|
-
operator: "contains"
|
|
2297
|
-
});
|
|
2298
|
-
vue.watch(
|
|
2299
|
-
() => props.filters,
|
|
2300
|
-
(newFilters) => {
|
|
2301
|
-
const parsed = jsonFormsCore.extractFilters(newFilters ?? []);
|
|
2302
|
-
rows.value = parsed.length > 0 ? parsed : [emptyRow()];
|
|
2303
|
-
appliedCount.value = parsed.length;
|
|
2304
|
-
},
|
|
2305
|
-
{ immediate: true }
|
|
2306
|
-
);
|
|
2307
|
-
const addRow = () => {
|
|
2308
|
-
rows.value = [
|
|
2309
|
-
...rows.value,
|
|
2310
|
-
{ key: defaultField.value, value: "", operator: "contains" }
|
|
2311
|
-
];
|
|
2312
|
-
};
|
|
2313
|
-
const removeRow = (index) => {
|
|
2314
|
-
const updated = rows.value.filter((_, i) => i !== index);
|
|
2315
|
-
rows.value = updated.length > 0 ? updated : [emptyRow()];
|
|
2316
|
-
};
|
|
2317
|
-
const onApply = () => {
|
|
2318
|
-
const serialized = rows.value.filter((r) => r.key && r.value).map(jsonFormsCore.filterToString);
|
|
2319
|
-
appliedCount.value = serialized.length;
|
|
2320
|
-
emit("changeFilters", serialized);
|
|
2321
|
-
showFilters.value = false;
|
|
2322
|
-
};
|
|
2323
|
-
const onReset = () => {
|
|
2324
|
-
rows.value = [emptyRow()];
|
|
2325
|
-
appliedCount.value = 0;
|
|
2326
|
-
emit("changeFilters", []);
|
|
2327
|
-
showFilters.value = false;
|
|
2328
|
-
};
|
|
2329
|
-
return (_ctx, _cache) => {
|
|
2330
|
-
return vue.openBlock(), vue.createElementBlock("div", {
|
|
2331
|
-
ref_key: "containerRef",
|
|
2332
|
-
ref: containerRef,
|
|
2333
|
-
class: "relative inline-flex"
|
|
2334
|
-
}, [
|
|
2335
|
-
vue.createVNode(vue.unref(ui.Btn), {
|
|
2336
|
-
size: "xs",
|
|
2337
|
-
color: "ghost",
|
|
2338
|
-
class: "border-gray-300 text-base-content/50 h-8",
|
|
2339
|
-
onClick: _cache[0] || (_cache[0] = ($event) => showFilters.value = !showFilters.value)
|
|
2340
|
-
}, {
|
|
2341
|
-
default: vue.withCtx(() => [
|
|
2342
|
-
vue.createElementVNode("span", _hoisted_1$1, [
|
|
2343
|
-
vue.createVNode(vue.unref(ui.Icon), {
|
|
2344
|
-
icon: vue.unref(ui.IconEnum).Filter,
|
|
2345
|
-
size: "sm",
|
|
2346
|
-
class: "text-base-500"
|
|
2347
|
-
}, null, 8, ["icon"]),
|
|
2348
|
-
_cache[1] || (_cache[1] = vue.createTextVNode(" Filters ", -1)),
|
|
2349
|
-
appliedCount.value ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_2$1, vue.toDisplayString(appliedCount.value), 1)) : vue.createCommentVNode("", true)
|
|
2350
|
-
])
|
|
2351
|
-
]),
|
|
2352
|
-
_: 1
|
|
2353
|
-
}),
|
|
2354
|
-
showFilters.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$1, [
|
|
2355
|
-
vue.createElementVNode("div", _hoisted_4$1, [
|
|
2356
|
-
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(rows.value, (row, index) => {
|
|
2357
|
-
return vue.openBlock(), vue.createBlock(_sfc_main$2, {
|
|
2358
|
-
key: index,
|
|
2359
|
-
modelValue: rows.value[index],
|
|
2360
|
-
"onUpdate:modelValue": ($event) => rows.value[index] = $event,
|
|
2361
|
-
fields: fields.value,
|
|
2362
|
-
onRemove: ($event) => removeRow(index)
|
|
2363
|
-
}, null, 8, ["modelValue", "onUpdate:modelValue", "fields", "onRemove"]);
|
|
2364
|
-
}), 128))
|
|
2365
|
-
]),
|
|
2366
|
-
_cache[5] || (_cache[5] = vue.createElementVNode("div", { class: "divider my-3" }, null, -1)),
|
|
2367
|
-
vue.createElementVNode("div", _hoisted_5$1, [
|
|
2368
|
-
vue.createVNode(vue.unref(ui.Btn), {
|
|
2369
|
-
icon: vue.unref(ui.IconEnum).Plus,
|
|
2370
|
-
color: "ghost",
|
|
2371
|
-
onClick: addRow
|
|
2372
|
-
}, {
|
|
2373
|
-
default: vue.withCtx(() => [..._cache[2] || (_cache[2] = [
|
|
2374
|
-
vue.createTextVNode(" Add filter ", -1)
|
|
2375
|
-
])]),
|
|
2376
|
-
_: 1
|
|
2377
|
-
}, 8, ["icon"]),
|
|
2378
|
-
vue.createElementVNode("div", _hoisted_6$1, [
|
|
2379
|
-
vue.createVNode(vue.unref(ui.Btn), {
|
|
2380
|
-
color: "ghost",
|
|
2381
|
-
onClick: onReset
|
|
2382
|
-
}, {
|
|
2383
|
-
default: vue.withCtx(() => [..._cache[3] || (_cache[3] = [
|
|
2384
|
-
vue.createTextVNode(" Reset ", -1)
|
|
2385
|
-
])]),
|
|
2386
|
-
_: 1
|
|
2387
|
-
}),
|
|
2388
|
-
vue.createVNode(vue.unref(ui.Btn), { onClick: onApply }, {
|
|
2389
|
-
default: vue.withCtx(() => [..._cache[4] || (_cache[4] = [
|
|
2390
|
-
vue.createTextVNode(" Apply ", -1)
|
|
2391
|
-
])]),
|
|
2392
|
-
_: 1
|
|
2393
|
-
})
|
|
2394
|
-
])
|
|
2395
|
-
])
|
|
2396
|
-
])) : vue.createCommentVNode("", true)
|
|
2397
|
-
], 512);
|
|
2398
|
-
};
|
|
2399
|
-
}
|
|
2400
|
-
});
|
|
2401
|
-
const _hoisted_1 = { class: "navbar bg-base-100" };
|
|
2402
|
-
const _hoisted_2 = { class: "navbar-start" };
|
|
2403
|
-
const _hoisted_3 = { key: 0 };
|
|
2404
|
-
const _hoisted_4 = { class: "navbar-center flex gap-2 items-center" };
|
|
2405
|
-
const _hoisted_5 = {
|
|
2406
|
-
key: 1,
|
|
2407
|
-
class: "flex gap-2"
|
|
2408
|
-
};
|
|
2409
|
-
const _hoisted_6 = { key: 0 };
|
|
2410
|
-
const _hoisted_7 = { class: "navbar-end" };
|
|
2411
|
-
const _hoisted_8 = { key: 0 };
|
|
2412
|
-
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
2413
|
-
__name: "TableToolbar",
|
|
2414
|
-
props: {
|
|
2415
|
-
filterSchema: {},
|
|
2416
|
-
filters: {},
|
|
2417
|
-
search: {},
|
|
2418
|
-
actions: {}
|
|
2419
|
-
},
|
|
2420
|
-
emits: ["updateSearch", "updateFilters", "action"],
|
|
2421
|
-
setup(__props, { emit: __emit }) {
|
|
2422
|
-
const props = __props;
|
|
2423
|
-
const emit = __emit;
|
|
2424
|
-
const searchQuery = vue.ref(props.search ?? "");
|
|
2425
|
-
let searchTimeout = null;
|
|
2426
|
-
const onSearchInput = (value) => {
|
|
2427
|
-
searchQuery.value = value;
|
|
2428
|
-
if (searchTimeout) clearTimeout(searchTimeout);
|
|
2429
|
-
searchTimeout = setTimeout(() => emit("updateSearch", value), 300);
|
|
2430
|
-
};
|
|
2431
|
-
const onChangeFilters = (filters) => {
|
|
2432
|
-
emit("updateFilters", filters);
|
|
2433
|
-
};
|
|
2434
|
-
return (_ctx, _cache) => {
|
|
2435
|
-
return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
|
|
2436
|
-
vue.createElementVNode("div", _hoisted_2, [
|
|
2437
|
-
_ctx.$slots.left ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3, [
|
|
2438
|
-
vue.renderSlot(_ctx.$slots, "left")
|
|
2439
|
-
])) : vue.createCommentVNode("", true)
|
|
2440
|
-
]),
|
|
2441
|
-
vue.createElementVNode("div", _hoisted_4, [
|
|
2442
|
-
vue.createVNode(vue.unref(ui.Input), {
|
|
2443
|
-
placeholder: "Search...",
|
|
2444
|
-
value: searchQuery.value,
|
|
2445
|
-
size: "sm",
|
|
2446
|
-
width: "w-48",
|
|
2447
|
-
clearable: true,
|
|
2448
|
-
onInput: _cache[0] || (_cache[0] = ($event) => onSearchInput($event.target.value))
|
|
2449
|
-
}, null, 8, ["value"]),
|
|
2450
|
-
__props.filterSchema ? (vue.openBlock(), vue.createBlock(_sfc_main$1, {
|
|
2451
|
-
key: 0,
|
|
2452
|
-
filters: __props.filters ?? [],
|
|
2453
|
-
"filter-schema": __props.filterSchema,
|
|
2454
|
-
onChangeFilters
|
|
2455
|
-
}, null, 8, ["filters", "filter-schema"])) : vue.createCommentVNode("", true),
|
|
2456
|
-
__props.actions ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5, [
|
|
2457
|
-
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.actions, (action) => {
|
|
2458
|
-
return vue.openBlock(), vue.createBlock(vue.unref(ui.Btn), {
|
|
2459
|
-
key: action.label ?? action.tooltip,
|
|
2460
|
-
size: "xs",
|
|
2461
|
-
color: "ghost",
|
|
2462
|
-
class: "border-gray-300 text-base-content/50 h-8",
|
|
2463
|
-
icon: action.icon,
|
|
2464
|
-
tooltip: action.tooltip,
|
|
2465
|
-
onClick: action.action
|
|
2466
|
-
}, {
|
|
2467
|
-
default: vue.withCtx(() => [
|
|
2468
|
-
action.label ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_6, vue.toDisplayString(action.label), 1)) : vue.createCommentVNode("", true)
|
|
2469
|
-
]),
|
|
2470
|
-
_: 2
|
|
2471
|
-
}, 1032, ["icon", "tooltip", "onClick"]);
|
|
2472
|
-
}), 128))
|
|
2473
|
-
])) : vue.createCommentVNode("", true)
|
|
2474
|
-
]),
|
|
2475
|
-
vue.createElementVNode("div", _hoisted_7, [
|
|
2476
|
-
_ctx.$slots.right ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_8, [
|
|
2477
|
-
vue.renderSlot(_ctx.$slots, "right")
|
|
2478
|
-
])) : vue.createCommentVNode("", true)
|
|
2479
|
-
])
|
|
2480
|
-
]);
|
|
2481
|
-
};
|
|
2482
|
-
}
|
|
2483
|
-
});
|
|
2484
|
-
exports.FilterRowInput = _sfc_main$2;
|
|
2485
|
-
exports.FormModalEmits = FormModalEmits;
|
|
2486
|
-
exports.FormModalProperties = FormModalProperties;
|
|
2487
|
-
exports.JsonForm = _sfc_main$4;
|
|
2488
|
-
exports.JsonFormModal = _sfc_main$j;
|
|
2489
|
-
exports.JsonFormModalService = JsonFormModalService;
|
|
2490
|
-
exports.ReadonlyLabel = _sfc_main$u;
|
|
2491
|
-
exports.TableComponent = _sfc_main$3;
|
|
2492
|
-
exports.TableComponentEmits = TableComponentEmits;
|
|
2493
|
-
exports.TableComponentProperties = TableComponentProperties;
|
|
2494
|
-
exports.TableFilter = _sfc_main$1;
|
|
2495
|
-
exports.TableToolbar = _sfc_main;
|
|
2496
|
-
exports.ViewDetailValue = _sfc_main$l;
|
|
2497
|
-
exports.cellFormatIs = cellFormatIs;
|
|
2498
|
-
exports.cellTypeIs = cellTypeIs;
|
|
2499
|
-
exports.createRepository = createRepository;
|
|
2500
|
-
exports.customRenderers = customRenderers;
|
|
2501
|
-
exports.defaultCellRenderers = defaultCellRenderers;
|
|
2502
|
-
exports.findCellRenderer = findCellRenderer;
|
|
2503
|
-
exports.formatError = formatError;
|
|
2504
|
-
exports.getNestedValue = getNestedValue;
|
|
2505
|
-
exports.isLink = isLink;
|
|
2506
|
-
exports.optionIsIgnoreCase = optionIsIgnoreCase;
|
|
2507
|
-
exports.provideFormEvents = provideFormEvents;
|
|
2508
|
-
exports.provideHttpClient = provideHttpClient;
|
|
2509
|
-
exports.readonlyRenderers = readonlyRenderers;
|
|
2510
|
-
exports.registerZodErrorMap = registerZodErrorMap;
|
|
2511
|
-
exports.useControlBinding = useControlBinding;
|
|
2512
|
-
exports.useCustomControlBinding = useCustomControlBinding;
|
|
2513
|
-
exports.useCustomReadonlyControlBinding = useCustomReadonlyControlBinding;
|
|
2514
|
-
exports.useDisplayValue = useDisplayValue;
|
|
2515
|
-
exports.useFormEvents = useFormEvents;
|
|
2516
|
-
exports.useHttpClient = useHttpClient;
|
|
2517
|
-
exports.useReadonlyControlBinding = useReadonlyControlBinding;
|