@maro-tech/form 0.0.10 → 0.0.12
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.
|
@@ -2900,7 +2900,7 @@ class UiActionFormModalComponent {
|
|
|
2900
2900
|
formConfig = signal(null, ...(ngDevMode ? [{ debugName: "formConfig" }] : /* istanbul ignore next */ []));
|
|
2901
2901
|
formValue = signal({}, ...(ngDevMode ? [{ debugName: "formValue" }] : /* istanbul ignore next */ []));
|
|
2902
2902
|
fields = computed(() => this.formConfig()?.fields ?? [], ...(ngDevMode ? [{ debugName: "fields" }] : /* istanbul ignore next */ []));
|
|
2903
|
-
submitAction = computed(() => this.formConfig()?.actions?.find((action) =>
|
|
2903
|
+
submitAction = computed(() => this.formConfig()?.actions?.find((action) => this.isSubmitAction(action)), ...(ngDevMode ? [{ debugName: "submitAction" }] : /* istanbul ignore next */ []));
|
|
2904
2904
|
submitLabel = computed(() => this.submitAction()?.submit || this.submitAction()?.label || 'Save', ...(ngDevMode ? [{ debugName: "submitLabel" }] : /* istanbul ignore next */ []));
|
|
2905
2905
|
panelClass = computed(() => ({
|
|
2906
2906
|
'max-w-xl': this.size() === 'sm',
|
|
@@ -2920,8 +2920,16 @@ class UiActionFormModalComponent {
|
|
|
2920
2920
|
onValueChange(value) {
|
|
2921
2921
|
this.formValue.set(value);
|
|
2922
2922
|
}
|
|
2923
|
-
onLookupCompleted(
|
|
2924
|
-
|
|
2923
|
+
onLookupCompleted(event) {
|
|
2924
|
+
const redirectTo = String(this.formConfig()?.redirectTo || '').trim();
|
|
2925
|
+
if (!redirectTo)
|
|
2926
|
+
return;
|
|
2927
|
+
const response = this.extractData(event.response) || event.response;
|
|
2928
|
+
const target = this.resolveTemplate(redirectTo, response);
|
|
2929
|
+
if (target && !target.includes('{{') && !target.includes(':')) {
|
|
2930
|
+
this.closed.emit();
|
|
2931
|
+
void this.router.navigateByUrl(target.startsWith('/') ? target : `/${target}`);
|
|
2932
|
+
}
|
|
2925
2933
|
}
|
|
2926
2934
|
onUploadingChange(uploading) {
|
|
2927
2935
|
this.isUploading.set(uploading);
|
|
@@ -2969,7 +2977,15 @@ class UiActionFormModalComponent {
|
|
|
2969
2977
|
const endpoint = `/api/crud/form/${encodeURIComponent(formId)}${recordId ? `/${encodeURIComponent(recordId)}` : ''}`;
|
|
2970
2978
|
this.http.get(endpoint).subscribe({
|
|
2971
2979
|
next: (response) => {
|
|
2972
|
-
const
|
|
2980
|
+
const raw = response.form || response;
|
|
2981
|
+
const config = {
|
|
2982
|
+
...raw,
|
|
2983
|
+
title: raw.title || raw.meta?.title,
|
|
2984
|
+
actions: (raw.actions || []).map((action) => ({
|
|
2985
|
+
...action,
|
|
2986
|
+
type: this.normalizeActionType(action.type),
|
|
2987
|
+
})),
|
|
2988
|
+
};
|
|
2973
2989
|
this.formConfig.set(config);
|
|
2974
2990
|
this.formValue.set({ ...(config.defaults || {}), ...(config.item || {}), ...(this.initialValue() || {}), ...(recordId ? { id: recordId } : {}) });
|
|
2975
2991
|
this.isLoading.set(false);
|
|
@@ -2988,6 +3004,18 @@ class UiActionFormModalComponent {
|
|
|
2988
3004
|
return value;
|
|
2989
3005
|
return `/api${value.startsWith('/') ? value : `/${value}`}`;
|
|
2990
3006
|
}
|
|
3007
|
+
normalizeActionType(type) {
|
|
3008
|
+
const normalized = String(type || '').trim().toLowerCase();
|
|
3009
|
+
if (normalized === 'api' || normalized === 'action_api')
|
|
3010
|
+
return 'ACTION_API';
|
|
3011
|
+
if (normalized === 'submit' || normalized === 'action_submit')
|
|
3012
|
+
return 'ACTION_SUBMIT';
|
|
3013
|
+
return String(type || '');
|
|
3014
|
+
}
|
|
3015
|
+
isSubmitAction(action) {
|
|
3016
|
+
const type = this.normalizeActionType(action.type);
|
|
3017
|
+
return type === 'ACTION_API' || type === 'ACTION_SUBMIT';
|
|
3018
|
+
}
|
|
2991
3019
|
resolveMethod(method) {
|
|
2992
3020
|
return String(method || 'POST').toUpperCase();
|
|
2993
3021
|
}
|
|
@@ -3002,19 +3030,23 @@ class UiActionFormModalComponent {
|
|
|
3002
3030
|
if (!redirect)
|
|
3003
3031
|
return;
|
|
3004
3032
|
const data = this.extractData(response) || {};
|
|
3005
|
-
const target =
|
|
3006
|
-
const value = String(key).split('.').reduce((current, part) => current && typeof current === 'object' ? current[part] : undefined, data);
|
|
3007
|
-
return value == null ? '' : String(value);
|
|
3008
|
-
});
|
|
3033
|
+
const target = this.resolveTemplate(redirect, data);
|
|
3009
3034
|
if (target && !target.includes(':'))
|
|
3010
3035
|
void this.router.navigateByUrl(target.startsWith('/') ? target : `/${target}`);
|
|
3011
3036
|
}
|
|
3037
|
+
resolveTemplate(template, data) {
|
|
3038
|
+
return String(template || '').replace(/\{\{([a-zA-Z_][a-zA-Z0-9_.]*)\}\}|:([a-zA-Z_][a-zA-Z0-9_.]*)/g, (_match, bracesKey, colonKey) => {
|
|
3039
|
+
const key = String(bracesKey || colonKey || '');
|
|
3040
|
+
const value = key.split('.').reduce((current, part) => current && typeof current === 'object' ? current[part] : undefined, data);
|
|
3041
|
+
return value == null || value === '' ? '' : encodeURIComponent(String(value));
|
|
3042
|
+
});
|
|
3043
|
+
}
|
|
3012
3044
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: UiActionFormModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3013
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: UiActionFormModalComponent, isStandalone: true, selector: "forms-action-form-modal", inputs: { formId: { classPropertyName: "formId", publicName: "formId", isSignal: true, isRequired: false, transformFunction: null }, recordId: { classPropertyName: "recordId", publicName: "recordId", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, initialValue: { classPropertyName: "initialValue", publicName: "initialValue", isSignal: true, isRequired: false, transformFunction: null }, uploadPhoto: { classPropertyName: "uploadPhoto", publicName: "uploadPhoto", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", completed: "completed" }, usesOnChanges: true, ngImport: i0, template: "@if (isOpen()) {\n <div class=\"fixed inset-0 z-50 flex items-
|
|
3045
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: UiActionFormModalComponent, isStandalone: true, selector: "forms-action-form-modal", inputs: { formId: { classPropertyName: "formId", publicName: "formId", isSignal: true, isRequired: false, transformFunction: null }, recordId: { classPropertyName: "recordId", publicName: "recordId", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, initialValue: { classPropertyName: "initialValue", publicName: "initialValue", isSignal: true, isRequired: false, transformFunction: null }, uploadPhoto: { classPropertyName: "uploadPhoto", publicName: "uploadPhoto", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", completed: "completed" }, usesOnChanges: true, ngImport: i0, template: "@if (isOpen()) {\n <div class=\"fixed inset-0 z-50 flex min-h-full items-center justify-center overflow-y-auto bg-slate-950/40 p-4 sm:p-6\" role=\"dialog\" aria-modal=\"true\">\n <div class=\"my-0 flex min-h-0 max-h-[calc(100vh-2rem)] w-full flex-col overflow-hidden rounded-2xl bg-slate-50 shadow-2xl sm:max-h-[calc(100vh-3rem)]\" [ngClass]=\"panelClass()\">\n <div class=\"flex shrink-0 items-center justify-between border-b border-slate-200 bg-white px-5 py-4 sm:px-6\">\n <h2 class=\"text-lg font-semibold\">{{ formConfig()?.title || 'Form' }}</h2>\n <button type=\"button\" class=\"text-xl text-slate-400 hover:text-slate-900\" aria-label=\"Close\" (click)=\"close()\">\u00D7</button>\n </div>\n <div class=\"min-h-0 flex-1 overflow-y-auto p-4 sm:p-6\">\n @if (isLoading()) {\n <p class=\"text-sm text-slate-500\">Loading form\u2026</p>\n } @else {\n <forms-dynamic-form [fields]=\"fields()\" [value]=\"formValue()\" [showSubmit]=\"false\" [uploadPhoto]=\"uploadPhoto()\" (valueChange)=\"onValueChange($event)\" (lookupCompleted)=\"onLookupCompleted($event)\" (uploadingChange)=\"onUploadingChange($event)\" (fieldActionTriggered)=\"onFieldActionTriggered($event)\"></forms-dynamic-form>\n }\n </div>\n <div class=\"relative z-10 flex shrink-0 justify-end gap-3 border-t border-slate-200 bg-white px-5 py-4 sm:px-6\">\n <ui-button variant=\"ghost\" (click)=\"close()\">Cancel</ui-button>\n @if (submitAction()) { <ui-button variant=\"primary\" [disabled]=\"isLoading() || isSubmitting() || isUploading()\" (click)=\"confirm()\">{{ submitLabel() }}</ui-button> }\n </div>\n </div>\n </div>\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["variant", "size", "disabled", "fullWidth", "type", "withShadow", "icon", "iconOnly", "ariaLabel"] }, { kind: "component", type: UiDynamicFormComponent, selector: "forms-dynamic-form", inputs: ["fields", "value", "errors", "submitLabel", "showSubmit", "disabled", "uploadPhoto"], outputs: ["valueChange", "lookupCompleted", "submitted", "filesChange", "uploadingChange", "fieldActionTriggered"] }] });
|
|
3014
3046
|
}
|
|
3015
3047
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: UiActionFormModalComponent, decorators: [{
|
|
3016
3048
|
type: Component,
|
|
3017
|
-
args: [{ selector: 'forms-action-form-modal', standalone: true, imports: [CommonModule, UiButtonComponent, UiDynamicFormComponent], template: "@if (isOpen()) {\n <div class=\"fixed inset-0 z-50 flex items-
|
|
3049
|
+
args: [{ selector: 'forms-action-form-modal', standalone: true, imports: [CommonModule, UiButtonComponent, UiDynamicFormComponent], template: "@if (isOpen()) {\n <div class=\"fixed inset-0 z-50 flex min-h-full items-center justify-center overflow-y-auto bg-slate-950/40 p-4 sm:p-6\" role=\"dialog\" aria-modal=\"true\">\n <div class=\"my-0 flex min-h-0 max-h-[calc(100vh-2rem)] w-full flex-col overflow-hidden rounded-2xl bg-slate-50 shadow-2xl sm:max-h-[calc(100vh-3rem)]\" [ngClass]=\"panelClass()\">\n <div class=\"flex shrink-0 items-center justify-between border-b border-slate-200 bg-white px-5 py-4 sm:px-6\">\n <h2 class=\"text-lg font-semibold\">{{ formConfig()?.title || 'Form' }}</h2>\n <button type=\"button\" class=\"text-xl text-slate-400 hover:text-slate-900\" aria-label=\"Close\" (click)=\"close()\">\u00D7</button>\n </div>\n <div class=\"min-h-0 flex-1 overflow-y-auto p-4 sm:p-6\">\n @if (isLoading()) {\n <p class=\"text-sm text-slate-500\">Loading form\u2026</p>\n } @else {\n <forms-dynamic-form [fields]=\"fields()\" [value]=\"formValue()\" [showSubmit]=\"false\" [uploadPhoto]=\"uploadPhoto()\" (valueChange)=\"onValueChange($event)\" (lookupCompleted)=\"onLookupCompleted($event)\" (uploadingChange)=\"onUploadingChange($event)\" (fieldActionTriggered)=\"onFieldActionTriggered($event)\"></forms-dynamic-form>\n }\n </div>\n <div class=\"relative z-10 flex shrink-0 justify-end gap-3 border-t border-slate-200 bg-white px-5 py-4 sm:px-6\">\n <ui-button variant=\"ghost\" (click)=\"close()\">Cancel</ui-button>\n @if (submitAction()) { <ui-button variant=\"primary\" [disabled]=\"isLoading() || isSubmitting() || isUploading()\" (click)=\"confirm()\">{{ submitLabel() }}</ui-button> }\n </div>\n </div>\n </div>\n}\n" }]
|
|
3018
3050
|
}], propDecorators: { formId: [{ type: i0.Input, args: [{ isSignal: true, alias: "formId", required: false }] }], recordId: [{ type: i0.Input, args: [{ isSignal: true, alias: "recordId", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }], initialValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialValue", required: false }] }], uploadPhoto: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadPhoto", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], completed: [{ type: i0.Output, args: ["completed"] }] } });
|
|
3019
3051
|
|
|
3020
3052
|
class UiInputComponent {
|