@ramathibodi/nuxt-commons 4.0.11 → 4.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/runtime/components/dialog/ImportProgress.d.vue.ts +35 -0
- package/dist/runtime/components/dialog/ImportProgress.vue +53 -0
- package/dist/runtime/components/dialog/ImportProgress.vue.d.ts +35 -0
- package/dist/runtime/components/document/TemplateBuilder.d.vue.ts +2 -2
- package/dist/runtime/components/document/TemplateBuilder.vue +113 -8
- package/dist/runtime/components/document/TemplateBuilder.vue.d.ts +2 -2
- package/dist/runtime/components/form/ActionPad.vue +1 -0
- package/dist/runtime/components/form/Birthdate.d.vue.ts +3 -3
- package/dist/runtime/components/form/Birthdate.vue.d.ts +3 -3
- package/dist/runtime/components/form/Date.vue +11 -6
- package/dist/runtime/components/form/Dialog.d.vue.ts +1 -5
- package/dist/runtime/components/form/Dialog.vue +1 -0
- package/dist/runtime/components/form/Dialog.vue.d.ts +1 -5
- package/dist/runtime/components/form/EditPad.vue +1 -0
- package/dist/runtime/components/form/Pad.d.vue.ts +24 -0
- package/dist/runtime/components/form/Pad.vue +11 -6
- package/dist/runtime/components/form/Pad.vue.d.ts +24 -0
- package/dist/runtime/components/form/Time.vue +10 -5
- package/dist/runtime/components/form/images/Edit.d.vue.ts +1 -3
- package/dist/runtime/components/form/images/Edit.vue.d.ts +1 -3
- package/dist/runtime/components/model/AutoRefreshChip.d.vue.ts +16 -0
- package/dist/runtime/components/model/AutoRefreshChip.vue +34 -0
- package/dist/runtime/components/model/AutoRefreshChip.vue.d.ts +16 -0
- package/dist/runtime/components/model/Pad.vue +2 -1
- package/dist/runtime/components/model/Table.d.vue.ts +158 -61
- package/dist/runtime/components/model/Table.vue +129 -7
- package/dist/runtime/components/model/Table.vue.d.ts +158 -61
- package/dist/runtime/components/model/iterator.d.vue.ts +198 -78
- package/dist/runtime/components/model/iterator.vue +140 -9
- package/dist/runtime/components/model/iterator.vue.d.ts +198 -78
- package/dist/runtime/composables/apiModel.d.ts +22 -3
- package/dist/runtime/composables/apiModel.js +27 -19
- package/dist/runtime/composables/autoRefresh.d.ts +42 -0
- package/dist/runtime/composables/autoRefresh.js +57 -0
- package/dist/runtime/composables/document/template.d.ts +61 -0
- package/dist/runtime/composables/document/template.js +60 -1
- package/dist/runtime/composables/document/validateTemplate.d.ts +62 -0
- package/dist/runtime/composables/document/validateTemplate.js +378 -0
- package/dist/runtime/composables/graphqlModel.d.ts +22 -3
- package/dist/runtime/composables/graphqlModel.js +27 -19
- package/dist/runtime/composables/graphqlModelOperation.d.ts +1 -0
- package/dist/runtime/composables/importProgress.d.ts +34 -0
- package/dist/runtime/composables/importProgress.js +50 -0
- package/dist/runtime/composables/modelAutoRefresh.d.ts +29 -0
- package/dist/runtime/composables/modelAutoRefresh.js +16 -0
- package/dist/runtime/composables/utils/validation.d.ts +4 -0
- package/dist/runtime/composables/utils/validation.js +2 -0
- package/dist/runtime/utils/virtualize.d.ts +15 -0
- package/dist/runtime/utils/virtualize.js +10 -0
- package/package.json +3 -2
- package/scripts/validate-document-template.mjs +158 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { computed, ref, toValue, watch } from "vue";
|
|
2
|
+
import { useDocumentVisibility, useIntervalFn } from "@vueuse/core";
|
|
3
|
+
function resolveInterval(raw, def) {
|
|
4
|
+
if (raw === true) return def;
|
|
5
|
+
if (typeof raw === "number" && raw > 0) return raw;
|
|
6
|
+
return 0;
|
|
7
|
+
}
|
|
8
|
+
export function useAutoRefresh(opts) {
|
|
9
|
+
const documentVisibility = useDocumentVisibility();
|
|
10
|
+
const defaultSeconds = opts.defaultSeconds ?? 60;
|
|
11
|
+
const intervalSeconds = computed(() => resolveInterval(toValue(opts.interval), defaultSeconds));
|
|
12
|
+
const enabled = computed(() => intervalSeconds.value > 0);
|
|
13
|
+
const isUserPaused = ref(false);
|
|
14
|
+
const remainingSeconds = ref(0);
|
|
15
|
+
const isLoadingMirror = computed(() => opts.isLoading?.value === true);
|
|
16
|
+
const paused = computed(
|
|
17
|
+
() => !enabled.value || isUserPaused.value || documentVisibility.value === "hidden" || opts.paused?.value === true || isLoadingMirror.value
|
|
18
|
+
);
|
|
19
|
+
const isActive = computed(() => enabled.value && !paused.value);
|
|
20
|
+
const ticker = useIntervalFn(async () => {
|
|
21
|
+
if (paused.value) return;
|
|
22
|
+
if (remainingSeconds.value <= 1) {
|
|
23
|
+
try {
|
|
24
|
+
await opts.reload();
|
|
25
|
+
} finally {
|
|
26
|
+
remainingSeconds.value = intervalSeconds.value;
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
remainingSeconds.value -= 1;
|
|
30
|
+
}
|
|
31
|
+
}, 1e3, { immediate: false });
|
|
32
|
+
watch(enabled, (on) => {
|
|
33
|
+
remainingSeconds.value = on ? intervalSeconds.value : 0;
|
|
34
|
+
}, { immediate: true });
|
|
35
|
+
watch(isActive, (active) => {
|
|
36
|
+
if (active && typeof document !== "undefined") ticker.resume();
|
|
37
|
+
else ticker.pause();
|
|
38
|
+
}, { immediate: true });
|
|
39
|
+
watch(intervalSeconds, (s) => {
|
|
40
|
+
if (enabled.value && remainingSeconds.value > s) remainingSeconds.value = s;
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
43
|
+
enabled,
|
|
44
|
+
isActive,
|
|
45
|
+
isLoading: isLoadingMirror,
|
|
46
|
+
intervalSeconds,
|
|
47
|
+
remainingSeconds,
|
|
48
|
+
isUserPaused,
|
|
49
|
+
togglePause: () => {
|
|
50
|
+
isUserPaused.value = !isUserPaused.value;
|
|
51
|
+
},
|
|
52
|
+
reset: () => {
|
|
53
|
+
remainingSeconds.value = intervalSeconds.value;
|
|
54
|
+
},
|
|
55
|
+
reload: opts.reload
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -13,6 +13,26 @@ export interface DocumentTemplateItem {
|
|
|
13
13
|
retrievedValue?: string;
|
|
14
14
|
customClass?: string;
|
|
15
15
|
customStyle?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Print/docx-only hook attributes appended to the generated `{{placeholder}}`
|
|
18
|
+
* by the backend docx renderer (rama-spring-starter `DocumentTemplateJsonRenderer`).
|
|
19
|
+
* Ignored by the Vue form renderer ({@link useDocumentTemplate}).
|
|
20
|
+
*
|
|
21
|
+
* Two accepted shapes:
|
|
22
|
+
* - object map — each entry becomes a placeholder attribute
|
|
23
|
+
* (`{ width: 2 }` → `;width=2`); a `true`/blank value becomes a bare flag
|
|
24
|
+
* (`{ qrcode: true }` → `;qrcode`). Entry order is preserved.
|
|
25
|
+
* - raw string — appended verbatim as attributes
|
|
26
|
+
* (`"format=dd/MM/yyyy"` → `;format=dd/MM/yyyy`).
|
|
27
|
+
*
|
|
28
|
+
* See {@link printConfigToAttributes} for the exact append semantics.
|
|
29
|
+
*/
|
|
30
|
+
printConfig?: Record<string, string | number | boolean> | string;
|
|
31
|
+
}
|
|
32
|
+
/** A single key/value row of a {@link DocumentTemplateItem.printConfig} object map, used by the builder editor. */
|
|
33
|
+
export interface PrintConfigRow {
|
|
34
|
+
key: string;
|
|
35
|
+
value: string | number | boolean;
|
|
16
36
|
}
|
|
17
37
|
export interface ChoiceItem {
|
|
18
38
|
label: string;
|
|
@@ -23,5 +43,46 @@ export declare function useDocumentTemplate(items: string | object, parentTempla
|
|
|
23
43
|
export declare function templateItemToString(inputItem: DocumentTemplateItem, parentTemplates: string | string[], dataVariable?: string): string;
|
|
24
44
|
export declare function optionStringToChoiceObject(option: string | object): ChoiceItem[];
|
|
25
45
|
export declare function escapeObjectForInlineBinding(obj: object): string;
|
|
46
|
+
/**
|
|
47
|
+
* Explode a {@link DocumentTemplateItem.printConfig} object map into ordered
|
|
48
|
+
* key/value rows for the builder editor. Returns an empty array for the
|
|
49
|
+
* raw-string form or any non-object value (those are edited as a plain string).
|
|
50
|
+
*/
|
|
51
|
+
export declare function printConfigToRows(printConfig: DocumentTemplateItem['printConfig'] | undefined): PrintConfigRow[];
|
|
52
|
+
/**
|
|
53
|
+
* Collapse builder rows back into a `printConfig` object map. Blank keys are
|
|
54
|
+
* dropped; string values are coerced so the stored JSON matches the backend's
|
|
55
|
+
* expected primitives: `'true'`/`'false'` → boolean, numeric strings → number,
|
|
56
|
+
* and a blank value → `true` (a bare flag). Entry order is preserved.
|
|
57
|
+
*/
|
|
58
|
+
export declare function rowsToPrintConfig(rows: PrintConfigRow[] | undefined): Record<string, string | number | boolean>;
|
|
59
|
+
/**
|
|
60
|
+
* Parse a human raw-attribute string (`"width=2; qrcode; locale=th_TH"`, an
|
|
61
|
+
* optional leading `;` is tolerated) into builder rows. Each `;`-separated
|
|
62
|
+
* token splits on the first `=`; a token without `=` becomes a bare-flag row
|
|
63
|
+
* (blank value). Blank tokens and blank keys are dropped. Inverse of
|
|
64
|
+
* {@link rowsToConfigString}; used when toggling the builder from raw-string to
|
|
65
|
+
* key/value mode.
|
|
66
|
+
*/
|
|
67
|
+
export declare function configStringToRows(configString: string | undefined): PrintConfigRow[];
|
|
68
|
+
/**
|
|
69
|
+
* Render builder rows into a human raw-attribute string
|
|
70
|
+
* (`"width=2; qrcode"`). A `true`/blank value becomes a bare flag. Inverse of
|
|
71
|
+
* {@link configStringToRows}; used when toggling the builder from key/value to
|
|
72
|
+
* raw-string mode.
|
|
73
|
+
*/
|
|
74
|
+
export declare function rowsToConfigString(rows: PrintConfigRow[] | undefined): string;
|
|
75
|
+
/**
|
|
76
|
+
* Resolve a {@link DocumentTemplateItem.printConfig} to the attribute string the
|
|
77
|
+
* backend docx renderer appends to a `{{placeholder}}`. This is the single
|
|
78
|
+
* source of truth for the append semantics (object map and raw string).
|
|
79
|
+
*
|
|
80
|
+
* - object map — `{ width: 2 }` → `;width=2`; a `true`/blank value becomes a
|
|
81
|
+
* bare flag (`{ qrcode: true }` → `;qrcode`); a `false` value is omitted.
|
|
82
|
+
* - raw string — appended verbatim with exactly one leading `;`.
|
|
83
|
+
*
|
|
84
|
+
* The Vue form renderer never calls this — `printConfig` is print-target-only.
|
|
85
|
+
*/
|
|
86
|
+
export declare function printConfigToAttributes(printConfig: DocumentTemplateItem['printConfig'] | undefined): string;
|
|
26
87
|
export declare function buildValidationRules(validationString: string): string;
|
|
27
88
|
export declare function processDefaultTemplate(item: DocumentTemplateItem, insideTemplate?: string, optionString?: string, validationRules?: string, dataVariable?: string): string;
|
|
@@ -4,7 +4,7 @@ import { processTemplateFormHidden } from "./templateFormHidden.js";
|
|
|
4
4
|
import { some, includes, cloneDeep } from "lodash-es";
|
|
5
5
|
import { migrateInputAttributes, migrateTemplateString } from "./templateMigrate.js";
|
|
6
6
|
import { getDocumentTemplateInputTypeEntry } from "./templateInputTypes.js";
|
|
7
|
-
export const validationRulesRegex = /^(require(?:\([^)]*\))?|requireIf\([^)]*\)|requireTrue(?:\([^)]*\))?|requireTrueIf\([^)]*\)|numeric(?:\([^)]*\))?|range\([^)]*\)|integer(?:\([^)]*\))?|unique\([^)]*\)|length(?:\([^)]*\))?|lengthGreater\([^)]*\)|lengthLess\([^)]*\)|telephone(?:\([^)]*\))?|email(?:\([^)]*\))?|regex\([^)]*\)|idcard(?:\([^)]*\))?|DateFuture(?:\([^)]*\))?|DatetimeFuture(?:\([^)]*\))?|DateHappen(?:\([^)]*\))?|DatetimeHappen(?:\([^)]*\))?|DateAfter\([^)]*\)|DateBefore\([^)]*\)|DateEqual\([^)]*\))(,(require(?:\([^)]*\))?|requireIf\([^)]*\)|requireTrue(?:\([^)]*\))?|requireTrueIf\([^)]*\)|numeric(?:\([^)]*\))?|range\([^)]*\)|integer(?:\([^)]*\))?|unique\([^)]*\)|length(?:\([^)]*\))?|lengthGreater\([^)]*\)|lengthLess\([^)]*\)|telephone(?:\([^)]*\))?|email(?:\([^)]*\))?|regex\([^)]*\)|idcard(?:\([^)]*\))?|DateFuture(?:\([^)]*\))?|DatetimeFuture(?:\([^)]*\))?|DateHappen(?:\([^)]*\))?|DatetimeHappen(?:\([^)]*\))?|DateAfter\([^)]*\)|DateBefore\([^)]*\)|DateEqual\([^)]*\)))*$/;
|
|
7
|
+
export const validationRulesRegex = /^(require(?:\([^)]*\))?|requireIf\([^)]*\)|requireTrue(?:\([^)]*\))?|requireTrueIf\([^)]*\)|requireNotEmpty(?:\([^)]*\))?|numeric(?:\([^)]*\))?|range\([^)]*\)|integer(?:\([^)]*\))?|unique\([^)]*\)|length(?:\([^)]*\))?|lengthGreater\([^)]*\)|lengthLess\([^)]*\)|telephone(?:\([^)]*\))?|email(?:\([^)]*\))?|regex\([^)]*\)|idcard(?:\([^)]*\))?|DateFuture(?:\([^)]*\))?|DatetimeFuture(?:\([^)]*\))?|DateHappen(?:\([^)]*\))?|DatetimeHappen(?:\([^)]*\))?|DateAfter\([^)]*\)|DateBefore\([^)]*\)|DateEqual\([^)]*\))(,(require(?:\([^)]*\))?|requireIf\([^)]*\)|requireTrue(?:\([^)]*\))?|requireTrueIf\([^)]*\)|requireNotEmpty(?:\([^)]*\))?|numeric(?:\([^)]*\))?|range\([^)]*\)|integer(?:\([^)]*\))?|unique\([^)]*\)|length(?:\([^)]*\))?|lengthGreater\([^)]*\)|lengthLess\([^)]*\)|telephone(?:\([^)]*\))?|email(?:\([^)]*\))?|regex\([^)]*\)|idcard(?:\([^)]*\))?|DateFuture(?:\([^)]*\))?|DatetimeFuture(?:\([^)]*\))?|DateHappen(?:\([^)]*\))?|DatetimeHappen(?:\([^)]*\))?|DateAfter\([^)]*\)|DateBefore\([^)]*\)|DateEqual\([^)]*\)))*$/;
|
|
8
8
|
export function useDocumentTemplate(items, parentTemplates) {
|
|
9
9
|
if (!items) return "";
|
|
10
10
|
if (typeof items === "string") {
|
|
@@ -130,6 +130,65 @@ export function optionStringToChoiceObject(option) {
|
|
|
130
130
|
export function escapeObjectForInlineBinding(obj) {
|
|
131
131
|
return JSON.stringify(obj).replace(/'/g, "'");
|
|
132
132
|
}
|
|
133
|
+
export function printConfigToRows(printConfig) {
|
|
134
|
+
if (!printConfig || typeof printConfig !== "object" || Array.isArray(printConfig)) return [];
|
|
135
|
+
return Object.entries(printConfig).map(([key, value]) => ({ key, value }));
|
|
136
|
+
}
|
|
137
|
+
export function rowsToPrintConfig(rows) {
|
|
138
|
+
const out = {};
|
|
139
|
+
for (const row of rows || []) {
|
|
140
|
+
const key = typeof row?.key === "string" ? row.key.trim() : "";
|
|
141
|
+
if (!key) continue;
|
|
142
|
+
out[key] = coercePrintConfigValue(row.value);
|
|
143
|
+
}
|
|
144
|
+
return out;
|
|
145
|
+
}
|
|
146
|
+
function coercePrintConfigValue(value) {
|
|
147
|
+
if (typeof value === "boolean" || typeof value === "number") return value;
|
|
148
|
+
const str = typeof value === "string" ? value.trim() : "";
|
|
149
|
+
if (str === "") return true;
|
|
150
|
+
if (str === "true") return true;
|
|
151
|
+
if (str === "false") return false;
|
|
152
|
+
if (/^-?\d+(\.\d+)?$/.test(str)) return Number(str);
|
|
153
|
+
return str;
|
|
154
|
+
}
|
|
155
|
+
export function configStringToRows(configString) {
|
|
156
|
+
if (typeof configString !== "string") return [];
|
|
157
|
+
const rows = [];
|
|
158
|
+
for (const token of configString.split(";")) {
|
|
159
|
+
const trimmed = token.trim();
|
|
160
|
+
if (!trimmed) continue;
|
|
161
|
+
const eq = trimmed.indexOf("=");
|
|
162
|
+
const key = (eq === -1 ? trimmed : trimmed.slice(0, eq)).trim();
|
|
163
|
+
if (!key) continue;
|
|
164
|
+
rows.push({ key, value: eq === -1 ? "" : trimmed.slice(eq + 1).trim() });
|
|
165
|
+
}
|
|
166
|
+
return rows;
|
|
167
|
+
}
|
|
168
|
+
export function rowsToConfigString(rows) {
|
|
169
|
+
return (rows || []).map((row) => {
|
|
170
|
+
const key = typeof row?.key === "string" ? row.key.trim() : "";
|
|
171
|
+
if (!key) return "";
|
|
172
|
+
return row.value === true || row.value === "" ? key : `${key}=${row.value}`;
|
|
173
|
+
}).filter(Boolean).join("; ");
|
|
174
|
+
}
|
|
175
|
+
export function printConfigToAttributes(printConfig) {
|
|
176
|
+
if (!printConfig) return "";
|
|
177
|
+
if (typeof printConfig === "string") {
|
|
178
|
+
const trimmed = printConfig.trim();
|
|
179
|
+
return trimmed ? `;${trimmed.replace(/^;+/, "")}` : "";
|
|
180
|
+
}
|
|
181
|
+
if (typeof printConfig !== "object" || Array.isArray(printConfig)) return "";
|
|
182
|
+
let attributes = "";
|
|
183
|
+
for (const [key, value] of Object.entries(printConfig)) {
|
|
184
|
+
const name = String(key).trim();
|
|
185
|
+
if (!name) continue;
|
|
186
|
+
if (value === false) continue;
|
|
187
|
+
if (value === true || value === "") attributes += `;${name}`;
|
|
188
|
+
else attributes += `;${name}=${value}`;
|
|
189
|
+
}
|
|
190
|
+
return attributes;
|
|
191
|
+
}
|
|
133
192
|
export function buildValidationRules(validationString) {
|
|
134
193
|
validationString = validationString.replace(/^\[|]$/g, "").trim();
|
|
135
194
|
if (!validationRulesRegex.test(validationString)) return "";
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation for Document Template JSON — the array of `DocumentTemplateItem`
|
|
3
|
+
* objects consumed by {@link useDocumentTemplate} and produced by
|
|
4
|
+
* `<DocumentTemplateBuilder>`.
|
|
5
|
+
*
|
|
6
|
+
* The validator reuses the renderer's own single-sources-of-truth so it can
|
|
7
|
+
* never drift from runtime behaviour:
|
|
8
|
+
*
|
|
9
|
+
* - `validationRulesRegex` — the exact gate the runtime (`buildValidationRules`)
|
|
10
|
+
* and the builder UI both apply to `validationRules`.
|
|
11
|
+
* - the choice-format regex `^[^'",]+(,[^'",]+)*$` — the same one
|
|
12
|
+
* `optionStringToChoiceObject` and the builder's `ruleOptions` use.
|
|
13
|
+
* - the built-in input-type registry — for per-type flags (`requiresOptions`,
|
|
14
|
+
* `needsVariableName`, `needsLabel`, `needsWidth`, `optionsAsChoice`,
|
|
15
|
+
* `hasSpecificOptionEditor`).
|
|
16
|
+
*
|
|
17
|
+
* Two strictness levels share one core via the `strict` option:
|
|
18
|
+
*
|
|
19
|
+
* - `error` — render-breaking. Invalid in both modes.
|
|
20
|
+
* - `warning` — builder-unsafe, but the runtime still renders without crashing.
|
|
21
|
+
* Promoted to `error` when `strict: true`.
|
|
22
|
+
* - `info` — advisory only; never affects `valid`.
|
|
23
|
+
*
|
|
24
|
+
* This doc block is consumed by vue-docgen for generated API documentation.
|
|
25
|
+
*/
|
|
26
|
+
import { type ComputedRef, type MaybeRefOrGetter } from 'vue';
|
|
27
|
+
export type ValidationSeverity = 'error' | 'warning' | 'info';
|
|
28
|
+
export interface ValidationIssue {
|
|
29
|
+
/** JSON-ish path to the offending node, e.g. `[2].inputOptions.formTemplate[0].variableName`. */
|
|
30
|
+
path: string;
|
|
31
|
+
/** Stable machine code, e.g. `INPUT_TYPE_MISSING`. */
|
|
32
|
+
code: string;
|
|
33
|
+
/** Human-readable explanation. */
|
|
34
|
+
message: string;
|
|
35
|
+
/** Effective severity (already reflects `strict` promotion). */
|
|
36
|
+
severity: ValidationSeverity;
|
|
37
|
+
}
|
|
38
|
+
export interface ValidationResult {
|
|
39
|
+
valid: boolean;
|
|
40
|
+
errors: ValidationIssue[];
|
|
41
|
+
warnings: ValidationIssue[];
|
|
42
|
+
infos: ValidationIssue[];
|
|
43
|
+
/** All issues in document order. */
|
|
44
|
+
issues: ValidationIssue[];
|
|
45
|
+
}
|
|
46
|
+
export interface ValidateOptions {
|
|
47
|
+
/** Promote builder-unsafe `warning`s to `error`s. Default `false`. */
|
|
48
|
+
strict?: boolean;
|
|
49
|
+
/** Forwarded ancestor-template context (advisory; mirrors `useDocumentTemplate`). */
|
|
50
|
+
parentTemplates?: string | string[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Validate a Document Template. Accepts the same inputs as `useDocumentTemplate`:
|
|
54
|
+
* a JSON string or an already-parsed array of items.
|
|
55
|
+
*/
|
|
56
|
+
export declare function validateDocumentTemplate(items: string | object, options?: ValidateOptions): ValidationResult;
|
|
57
|
+
/**
|
|
58
|
+
* Reactive wrapper. Re-validates whenever `source` (a ref, getter, JSON string,
|
|
59
|
+
* or item array) changes. Use in `<DocumentTemplateBuilder>`-adjacent UIs to
|
|
60
|
+
* surface per-field issues live.
|
|
61
|
+
*/
|
|
62
|
+
export declare function useDocumentTemplateValidate(source: MaybeRefOrGetter<string | object>, options?: ValidateOptions): ComputedRef<ValidationResult>;
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { computed, toValue } from "vue";
|
|
2
|
+
import { isPlainObject } from "lodash-es";
|
|
3
|
+
import { validationRulesRegex } from "./template.js";
|
|
4
|
+
import {
|
|
5
|
+
getDocumentTemplateInputTypeEntry
|
|
6
|
+
} from "./templateInputTypes.js";
|
|
7
|
+
const CHOICE_STRING_REGEX = /^[^'",]+(,[^'",]+)*$/;
|
|
8
|
+
const VARIABLE_NAME_REGEX = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*)*$/;
|
|
9
|
+
const KNOWN_ITEM_KEYS = /* @__PURE__ */ new Set([
|
|
10
|
+
"inputType",
|
|
11
|
+
"width",
|
|
12
|
+
"inputLabel",
|
|
13
|
+
"variableName",
|
|
14
|
+
"validationRules",
|
|
15
|
+
"inputOptions",
|
|
16
|
+
"inputAttributes",
|
|
17
|
+
"inputCustomCode",
|
|
18
|
+
"columnAttributes",
|
|
19
|
+
"conditionalDisplay",
|
|
20
|
+
"computedValue",
|
|
21
|
+
"retrievedValue",
|
|
22
|
+
"customClass",
|
|
23
|
+
"customStyle",
|
|
24
|
+
"printConfig"
|
|
25
|
+
]);
|
|
26
|
+
export function validateDocumentTemplate(items, options = {}) {
|
|
27
|
+
const raw = [];
|
|
28
|
+
const push = (path, code, message, base) => raw.push({ path, code, message, base });
|
|
29
|
+
let parsed = items;
|
|
30
|
+
if (typeof items === "string") {
|
|
31
|
+
try {
|
|
32
|
+
parsed = JSON.parse(items);
|
|
33
|
+
} catch {
|
|
34
|
+
push("", "NOT_ARRAY", "Template is a string but not valid JSON; expected an array of items.", "error");
|
|
35
|
+
return finalize(raw, options.strict);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
validateItemArray(parsed, "", push);
|
|
39
|
+
return finalize(raw, options.strict);
|
|
40
|
+
}
|
|
41
|
+
function validateItemArray(node, basePath, push) {
|
|
42
|
+
if (!Array.isArray(node) || !node.every((it) => isPlainObject(it))) {
|
|
43
|
+
push(basePath || "", "NOT_ARRAY", `Expected an array of template item objects at ${basePath || "top level"}.`, "error");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (node.length === 0) {
|
|
47
|
+
push(basePath || "", "EMPTY_TEMPLATE", "Template array is empty; it renders an empty container.", "info");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const seen = /* @__PURE__ */ new Map();
|
|
51
|
+
for (const item of node) {
|
|
52
|
+
const v = typeof item.variableName === "string" ? item.variableName.trim() : "";
|
|
53
|
+
if (v) seen.set(v, (seen.get(v) ?? 0) + 1);
|
|
54
|
+
}
|
|
55
|
+
node.forEach((item, index) => {
|
|
56
|
+
validateItem(item, `${basePath}[${index}]`, seen, push);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function validateItem(item, path, siblingVarCounts, push) {
|
|
60
|
+
for (const key of Object.keys(item)) {
|
|
61
|
+
if (!KNOWN_ITEM_KEYS.has(key)) {
|
|
62
|
+
push(`${path}.${key}`, "UNKNOWN_KEY", `Unknown key "${key}" is ignored by the renderer (possible typo).`, "info");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (typeof item.inputType !== "string" || item.inputType.trim() === "") {
|
|
66
|
+
push(`${path}.inputType`, "INPUT_TYPE_MISSING", "inputType is required and must be a non-empty string.", "error");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const inputType = item.inputType;
|
|
70
|
+
const entry = getDocumentTemplateInputTypeEntry(inputType);
|
|
71
|
+
if (!entry) {
|
|
72
|
+
push(
|
|
73
|
+
`${path}.inputType`,
|
|
74
|
+
"INPUT_TYPE_UNKNOWN",
|
|
75
|
+
`inputType "${inputType}" is not a built-in type; it will render as a raw <${inputType}> component tag.`,
|
|
76
|
+
"warning"
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
const needsVariableName = entry?.needsVariableName !== false;
|
|
80
|
+
const needsLabel = entry?.needsLabel !== false;
|
|
81
|
+
const needsWidth = entry?.needsWidth !== false;
|
|
82
|
+
const requiresOptions = entry?.requiresOptions === true;
|
|
83
|
+
const optionsAsChoice = entry?.optionsAsChoice === true;
|
|
84
|
+
const hasSpecificOptionEditor = entry?.hasSpecificOptionEditor === true;
|
|
85
|
+
const variableName = typeof item.variableName === "string" ? item.variableName.trim() : "";
|
|
86
|
+
if (needsVariableName) {
|
|
87
|
+
if (!variableName) {
|
|
88
|
+
push(`${path}.variableName`, "VARIABLE_NAME_REQUIRED", `${inputType} requires a variableName.`, "warning");
|
|
89
|
+
} else if (!VARIABLE_NAME_REGEX.test(variableName)) {
|
|
90
|
+
push(
|
|
91
|
+
`${path}.variableName`,
|
|
92
|
+
"VARIABLE_NAME_MALFORMED",
|
|
93
|
+
`variableName "${variableName}" is not a valid data path; it breaks v-model="data.${variableName}".`,
|
|
94
|
+
"error"
|
|
95
|
+
);
|
|
96
|
+
} else if ((siblingVarCounts.get(variableName) ?? 0) > 1) {
|
|
97
|
+
push(
|
|
98
|
+
`${path}.variableName`,
|
|
99
|
+
"VARIABLE_NAME_DUPLICATE",
|
|
100
|
+
`variableName "${variableName}" is used by more than one sibling field; they bind to the same data property.`,
|
|
101
|
+
"warning"
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (needsLabel && (typeof item.inputLabel !== "string" || item.inputLabel.trim() === "")) {
|
|
106
|
+
push(`${path}.inputLabel`, "LABEL_REQUIRED", `${inputType} expects an inputLabel.`, "warning");
|
|
107
|
+
}
|
|
108
|
+
if (needsWidth) {
|
|
109
|
+
if (item.width === void 0 || item.width === null || item.width === "") {
|
|
110
|
+
push(`${path}.width`, "WIDTH_REQUIRED", `${inputType} expects a width (1\u201312).`, "warning");
|
|
111
|
+
} else {
|
|
112
|
+
const n = Number(item.width);
|
|
113
|
+
if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1 || n > 12) {
|
|
114
|
+
push(`${path}.width`, "WIDTH_OUT_OF_RANGE", `width "${item.width}" should be an integer from 1 to 12.`, "warning");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (item.validationRules !== void 0 && item.validationRules !== null && item.validationRules !== "") {
|
|
119
|
+
if (typeof item.validationRules !== "string") {
|
|
120
|
+
push(`${path}.validationRules`, "RULES_INVALID", "validationRules must be a string.", "warning");
|
|
121
|
+
} else {
|
|
122
|
+
const stripped = item.validationRules.replace(/^\[|]$/g, "").trim();
|
|
123
|
+
if (stripped && !validationRulesRegex.test(stripped)) {
|
|
124
|
+
push(
|
|
125
|
+
`${path}.validationRules`,
|
|
126
|
+
"RULES_INVALID",
|
|
127
|
+
`validationRules "${item.validationRules}" fail the rules regex; the renderer drops them silently.`,
|
|
128
|
+
"warning"
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (item.computedValue && !variableName) {
|
|
134
|
+
push(
|
|
135
|
+
`${path}.computedValue`,
|
|
136
|
+
"COMPUTED_VALUE_IGNORED",
|
|
137
|
+
"computedValue is ignored without a variableName (no hidden field is appended).",
|
|
138
|
+
"info"
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
if (item.retrievedValue) {
|
|
142
|
+
push(`${path}.retrievedValue`, "RETRIEVED_VALUE_UNUSED", "retrievedValue is not consumed by the renderer.", "info");
|
|
143
|
+
}
|
|
144
|
+
validatePrintConfig(item.printConfig, `${path}.printConfig`, push);
|
|
145
|
+
validateInputOptions(item, path, { entry, requiresOptions, optionsAsChoice, hasSpecificOptionEditor }, push);
|
|
146
|
+
}
|
|
147
|
+
function validatePrintConfig(printConfig, path, push) {
|
|
148
|
+
if (printConfig === void 0 || printConfig === null) return;
|
|
149
|
+
if (typeof printConfig === "string") {
|
|
150
|
+
if (printConfig.trim() === "") {
|
|
151
|
+
push(path, "PRINTCONFIG_EMPTY", "printConfig is an empty string; nothing is appended to the placeholder.", "info");
|
|
152
|
+
}
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (!isPlainObject(printConfig)) {
|
|
156
|
+
push(
|
|
157
|
+
path,
|
|
158
|
+
"PRINTCONFIG_INVALID_TYPE",
|
|
159
|
+
"printConfig must be an object map of primitive values or a raw string; other shapes are ignored by the print renderer.",
|
|
160
|
+
"info"
|
|
161
|
+
);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const entries = Object.entries(printConfig);
|
|
165
|
+
if (entries.length === 0) {
|
|
166
|
+
push(path, "PRINTCONFIG_EMPTY", "printConfig is an empty object; nothing is appended to the placeholder.", "info");
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
for (const [key, value] of entries) {
|
|
170
|
+
const t = typeof value;
|
|
171
|
+
if (t !== "string" && t !== "number" && t !== "boolean") {
|
|
172
|
+
push(
|
|
173
|
+
`${path}.${key}`,
|
|
174
|
+
"PRINTCONFIG_VALUE_INVALID",
|
|
175
|
+
`printConfig.${key} must be a string, number, or boolean; the print renderer cannot append a ${Array.isArray(value) ? "array" : t}.`,
|
|
176
|
+
"info"
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function validateInputOptions(item, path, ctx, push) {
|
|
182
|
+
const { requiresOptions, optionsAsChoice, hasSpecificOptionEditor } = ctx;
|
|
183
|
+
const inputType = item.inputType;
|
|
184
|
+
const opts = item.inputOptions;
|
|
185
|
+
const optsPath = `${path}.inputOptions`;
|
|
186
|
+
const hasOptions = opts !== void 0 && opts !== null && opts !== "";
|
|
187
|
+
if (requiresOptions && !hasSpecificOptionEditor && !hasOptions) {
|
|
188
|
+
push(optsPath, "OPTIONS_REQUIRED", `${inputType} requires inputOptions.`, "warning");
|
|
189
|
+
}
|
|
190
|
+
switch (inputType) {
|
|
191
|
+
case "CustomCode":
|
|
192
|
+
if (typeof item.inputCustomCode !== "string" || item.inputCustomCode.trim() === "") {
|
|
193
|
+
push(`${path}.inputCustomCode`, "CUSTOMCODE_EMPTY", "CustomCode requires inputCustomCode; otherwise it renders nothing.", "error");
|
|
194
|
+
}
|
|
195
|
+
return;
|
|
196
|
+
case "MasterAutocomplete":
|
|
197
|
+
if (hasOptions && (typeof opts !== "string" || opts.trim() === "")) {
|
|
198
|
+
push(optsPath, "OPTIONS_NOT_STRING", "MasterAutocomplete inputOptions must be a non-empty group-key string.", "warning");
|
|
199
|
+
}
|
|
200
|
+
return;
|
|
201
|
+
case "DocumentForm":
|
|
202
|
+
if (hasOptions && (typeof opts !== "string" || opts.trim() === "")) {
|
|
203
|
+
push(optsPath, "OPTIONS_NOT_STRING", "DocumentForm inputOptions must be the child template code (a non-empty string).", "warning");
|
|
204
|
+
}
|
|
205
|
+
return;
|
|
206
|
+
case "Header":
|
|
207
|
+
if (hasOptions && typeof opts !== "string") {
|
|
208
|
+
push(optsPath, "OPTIONS_NOT_STRING", "Header inputOptions should be a class string; non-strings are ignored.", "warning");
|
|
209
|
+
}
|
|
210
|
+
return;
|
|
211
|
+
case "FormHidden":
|
|
212
|
+
if (hasOptions && !isPlainObject(opts)) {
|
|
213
|
+
push(optsPath, "OPTIONS_NOT_OBJECT", "FormHidden inputOptions must be an object { itemValue?, hook? }.", "error");
|
|
214
|
+
} else if (isPlainObject(opts)) {
|
|
215
|
+
const o = opts;
|
|
216
|
+
if (o.hook !== void 0 && typeof o.hook !== "string") {
|
|
217
|
+
push(`${optsPath}.hook`, "OPTIONS_NOT_STRING", "FormHidden inputOptions.hook must be a string.", "warning");
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return;
|
|
221
|
+
case "FormTable":
|
|
222
|
+
validateFormTableOptions(opts, optsPath, push);
|
|
223
|
+
return;
|
|
224
|
+
case "FormTableData":
|
|
225
|
+
validateFormTableDataOptions(opts, optsPath, push);
|
|
226
|
+
return;
|
|
227
|
+
default:
|
|
228
|
+
if (optionsAsChoice && hasOptions) {
|
|
229
|
+
validateChoiceOptions(opts, optsPath, push);
|
|
230
|
+
}
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function validateChoiceOptions(opts, path, push) {
|
|
235
|
+
if (typeof opts === "string") {
|
|
236
|
+
if (!CHOICE_STRING_REGEX.test(opts.trim())) {
|
|
237
|
+
push(
|
|
238
|
+
path,
|
|
239
|
+
"CHOICE_OPTIONS_INVALID",
|
|
240
|
+
"Choice inputOptions string is malformed (quotes or empty commas); it parses to zero options.",
|
|
241
|
+
"error"
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (Array.isArray(opts)) {
|
|
247
|
+
if (!opts.every((it) => isPlainObject(it))) {
|
|
248
|
+
push(path, "CHOICE_OPTIONS_INVALID", "Choice inputOptions array must contain only objects.", "error");
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
opts.forEach((it, i) => {
|
|
252
|
+
const o = it;
|
|
253
|
+
const hasLabel = o.label !== void 0 && o.label !== "";
|
|
254
|
+
const hasValue = o.value !== void 0 && o.value !== "";
|
|
255
|
+
if (!hasLabel && !hasValue) {
|
|
256
|
+
push(`${path}[${i}]`, "CHOICE_ITEM_EMPTY", "Choice item has neither label nor value; it renders blank.", "info");
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
push(path, "CHOICE_OPTIONS_INVALID", "Choice inputOptions must be a compact string or an array of { label, value } objects.", "error");
|
|
262
|
+
}
|
|
263
|
+
function validateFormTableOptions(opts, path, push) {
|
|
264
|
+
if (!isPlainObject(opts)) {
|
|
265
|
+
push(path, "OPTIONS_NOT_OBJECT", "FormTable inputOptions must be an object with a formTemplate.", "error");
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const o = opts;
|
|
269
|
+
const formTemplate = coerceTemplateArray(o.formTemplate);
|
|
270
|
+
if (formTemplate === void 0) {
|
|
271
|
+
push(
|
|
272
|
+
`${path}.formTemplate`,
|
|
273
|
+
"FORMTABLE_NO_FORMTEMPLATE",
|
|
274
|
+
"FormTable requires a formTemplate (array of items or a JSON string) for the row editor.",
|
|
275
|
+
"error"
|
|
276
|
+
);
|
|
277
|
+
} else {
|
|
278
|
+
validateItemArray(formTemplate, `${path}.formTemplate`, push);
|
|
279
|
+
}
|
|
280
|
+
validateTableHeaders(o.headers, `${path}.headers`, push);
|
|
281
|
+
}
|
|
282
|
+
function validateFormTableDataOptions(opts, path, push) {
|
|
283
|
+
if (!isPlainObject(opts)) {
|
|
284
|
+
push(path, "OPTIONS_NOT_OBJECT", "FormTableData inputOptions must be an object with a dataTemplate.", "error");
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const o = opts;
|
|
288
|
+
const dataTemplate = coerceTemplateArray(o.dataTemplate);
|
|
289
|
+
const dataVars = /* @__PURE__ */ new Set();
|
|
290
|
+
if (dataTemplate === void 0) {
|
|
291
|
+
push(
|
|
292
|
+
`${path}.dataTemplate`,
|
|
293
|
+
"FORMTABLEDATA_NO_DATATEMPLATE",
|
|
294
|
+
"FormTableData has no dataTemplate; no editable columns are rendered.",
|
|
295
|
+
"warning"
|
|
296
|
+
);
|
|
297
|
+
} else {
|
|
298
|
+
validateItemArray(dataTemplate, `${path}.dataTemplate`, push);
|
|
299
|
+
for (const it of dataTemplate) {
|
|
300
|
+
if (typeof it.variableName === "string" && it.variableName.trim()) dataVars.add(it.variableName.trim());
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const itemTemplate = coerceTemplateArray(o.itemTemplate);
|
|
304
|
+
if (itemTemplate !== void 0) validateItemArray(itemTemplate, `${path}.itemTemplate`, push);
|
|
305
|
+
validateTableHeaders(o.headers, `${path}.headers`, push);
|
|
306
|
+
if (o.disableApplyToAll !== void 0 && o.disableApplyToAll !== "") {
|
|
307
|
+
const val = o.disableApplyToAll;
|
|
308
|
+
if (val !== "false" && val !== "true" && val !== "partial") {
|
|
309
|
+
push(`${path}.disableApplyToAll`, "APPLYTOALL_INVALID", 'disableApplyToAll must be "false", "true", or "partial".', "warning");
|
|
310
|
+
} else if (val === "partial") {
|
|
311
|
+
const keys = typeof o.disableApplyToAllPartial === "string" ? o.disableApplyToAllPartial.split(",").map((s) => s.trim()).filter(Boolean) : [];
|
|
312
|
+
if (keys.length === 0) {
|
|
313
|
+
push(
|
|
314
|
+
`${path}.disableApplyToAllPartial`,
|
|
315
|
+
"APPLYTOALL_INVALID",
|
|
316
|
+
'disableApplyToAll is "partial" but disableApplyToAllPartial lists no columns.',
|
|
317
|
+
"warning"
|
|
318
|
+
);
|
|
319
|
+
} else if (dataTemplate !== void 0) {
|
|
320
|
+
for (const k of keys) {
|
|
321
|
+
if (!dataVars.has(k)) {
|
|
322
|
+
push(
|
|
323
|
+
`${path}.disableApplyToAllPartial`,
|
|
324
|
+
"APPLYTOALL_KEY_UNKNOWN",
|
|
325
|
+
`disableApplyToAllPartial key "${k}" is not a variableName in dataTemplate.`,
|
|
326
|
+
"warning"
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function validateTableHeaders(headers, path, push) {
|
|
335
|
+
if (headers === void 0 || headers === null) return;
|
|
336
|
+
if (!Array.isArray(headers)) {
|
|
337
|
+
push(path, "OPTIONS_NOT_OBJECT", "headers must be an array.", "warning");
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
headers.forEach((h, i) => {
|
|
341
|
+
if (!isPlainObject(h)) {
|
|
342
|
+
push(`${path}[${i}]`, "OPTIONS_NOT_OBJECT", "header entry must be an object.", "warning");
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
const key = h.key;
|
|
346
|
+
if (key === void 0 || key === "") {
|
|
347
|
+
push(`${path}[${i}].key`, "HEADER_NO_KEY", "header entry has no key; the column cannot bind to a row property.", "warning");
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
function coerceTemplateArray(value) {
|
|
352
|
+
if (value === void 0 || value === null || value === "") return void 0;
|
|
353
|
+
if (Array.isArray(value)) return value;
|
|
354
|
+
if (typeof value === "string") {
|
|
355
|
+
try {
|
|
356
|
+
const parsed = JSON.parse(value);
|
|
357
|
+
return Array.isArray(parsed) ? parsed : void 0;
|
|
358
|
+
} catch {
|
|
359
|
+
return void 0;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return void 0;
|
|
363
|
+
}
|
|
364
|
+
function finalize(raw, strict) {
|
|
365
|
+
const issues = raw.map((r) => ({
|
|
366
|
+
path: r.path,
|
|
367
|
+
code: r.code,
|
|
368
|
+
message: r.message,
|
|
369
|
+
severity: strict && r.base === "warning" ? "error" : r.base
|
|
370
|
+
}));
|
|
371
|
+
const errors = issues.filter((i) => i.severity === "error");
|
|
372
|
+
const warnings = issues.filter((i) => i.severity === "warning");
|
|
373
|
+
const infos = issues.filter((i) => i.severity === "info");
|
|
374
|
+
return { valid: errors.length === 0, errors, warnings, infos, issues };
|
|
375
|
+
}
|
|
376
|
+
export function useDocumentTemplateValidate(source, options = {}) {
|
|
377
|
+
return computed(() => validateDocumentTemplate(toValue(source), options));
|
|
378
|
+
}
|
|
@@ -26,10 +26,29 @@ export declare function useGraphqlModel<T extends GraphqlModelProps>(props: T):
|
|
|
26
26
|
canUpdate: import("vue").ComputedRef<boolean>;
|
|
27
27
|
canDelete: import("vue").ComputedRef<boolean>;
|
|
28
28
|
createItem: (item: Record<string, any>, callback?: FormDialogCallback, importing?: boolean) => Promise<void>;
|
|
29
|
-
importItems: (
|
|
29
|
+
importItems: (importData: Record<string, any>[], callback?: FormDialogCallback) => void;
|
|
30
30
|
updateItem: (item: Record<string, any>, callback?: FormDialogCallback) => Promise<void>;
|
|
31
31
|
deleteItem: (item: Record<string, any>, callback?: FormDialogCallback) => Promise<any>;
|
|
32
|
-
loadItems: (options: any) => void;
|
|
33
|
-
reload: () => void;
|
|
32
|
+
loadItems: (options: any) => Promise<void> | undefined;
|
|
33
|
+
reload: () => Promise<void> | undefined;
|
|
34
34
|
isLoading: import("vue").Ref<boolean, boolean>;
|
|
35
|
+
importProgress: {
|
|
36
|
+
isImporting: import("vue").Ref<boolean, boolean>;
|
|
37
|
+
total: import("vue").Ref<number, number>;
|
|
38
|
+
processed: import("vue").Ref<number, number>;
|
|
39
|
+
succeeded: import("vue").Ref<number, number>;
|
|
40
|
+
failed: import("vue").Ref<number, number>;
|
|
41
|
+
errors: import("vue").Ref<{
|
|
42
|
+
index: number;
|
|
43
|
+
message: string;
|
|
44
|
+
}[], import("./importProgress.js").ImportError[] | {
|
|
45
|
+
index: number;
|
|
46
|
+
message: string;
|
|
47
|
+
}[]>;
|
|
48
|
+
percent: import("vue").ComputedRef<number>;
|
|
49
|
+
reset: () => void;
|
|
50
|
+
run: <T_1 = any>(items: T_1[], worker: import("./importProgress.js").ImportWorker<T_1>, options?: {
|
|
51
|
+
concurrency?: number;
|
|
52
|
+
}) => Promise<import("./importProgress.js").ImportSummary>;
|
|
53
|
+
};
|
|
35
54
|
};
|