commons-shared-web-ui 0.0.9 → 0.0.10
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.
|
@@ -4,7 +4,7 @@ import * as i1 from '@angular/common';
|
|
|
4
4
|
import { CommonModule, formatDate } from '@angular/common';
|
|
5
5
|
import { MatCardModule } from '@angular/material/card';
|
|
6
6
|
import * as i2$2 from '@angular/material/snack-bar';
|
|
7
|
-
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
7
|
+
import { MatSnackBarModule, MAT_SNACK_BAR_DATA, MatSnackBarRef } from '@angular/material/snack-bar';
|
|
8
8
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
9
9
|
import { MatDividerModule } from '@angular/material/divider';
|
|
10
10
|
import * as i6 from '@angular/material/radio';
|
|
@@ -3779,6 +3779,57 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
3779
3779
|
}]
|
|
3780
3780
|
}] });
|
|
3781
3781
|
|
|
3782
|
+
class SnackbarComponent {
|
|
3783
|
+
data = inject(MAT_SNACK_BAR_DATA);
|
|
3784
|
+
snackBarRef = inject(MatSnackBarRef);
|
|
3785
|
+
get variantClass() {
|
|
3786
|
+
return `snackbar-${this.data.variant || 'info'}`;
|
|
3787
|
+
}
|
|
3788
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SnackbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3789
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SnackbarComponent, isStandalone: false, selector: "lib-snackbar", ngImport: i0, template: "<div class=\"cc-snackbar-container\" [ngClass]=\"variantClass\">\n <div class=\"cc-snackbar-icon\">\n <!-- Success Icon -->\n <svg *ngIf=\"data.variant === 'success'\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"></path>\n <polyline points=\"22 4 12 14.01 9 11.01\"></polyline>\n </svg>\n \n <!-- Error Icon -->\n <svg *ngIf=\"data.variant === 'error'\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"></line>\n <line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"></line>\n </svg>\n \n <!-- Warning Icon -->\n <svg *ngIf=\"data.variant === 'warning'\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"></path>\n <line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"></line>\n <line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"></line>\n </svg>\n \n <!-- Info Icon -->\n <svg *ngIf=\"data.variant === 'info' || !data.variant\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\"></line>\n <line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\"></line>\n </svg>\n </div>\n \n <div class=\"cc-snackbar-message\">\n {{ data.message }}\n </div>\n\n <button *ngIf=\"data.showCloseButton\" class=\"cc-snackbar-close\" (click)=\"snackBarRef.dismiss()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n</div>\n", styles: [".cc-snackbar-container{display:flex;align-items:center;gap:var(--cc-sb-gap, 12px);padding:var(--cc-sb-padding, 12px 16px);border-radius:var(--cc-sb-radius, 8px);box-shadow:var(--cc-sb-shadow, 0 4px 6px -1px rgba(0, 0, 0, .1), 0 2px 4px -1px rgba(0, 0, 0, .06));font-family:var(--cc-sb-font-family, \"Inter\", sans-serif);font-size:var(--cc-sb-font-size, 14px);font-weight:var(--cc-sb-font-weight, 500);background:var(--cc-sb-bg, #ffffff);color:var(--cc-sb-color, #1f2937);border:var(--cc-sb-border, 1px solid transparent);min-width:var(--cc-sb-min-width, 300px)}.cc-snackbar-container.snackbar-success{background:var(--cc-sb-success-bg, #ecfdf5);color:var(--cc-sb-success-color, #065f46);border-color:var(--cc-sb-success-border, #a7f3d0)}.cc-snackbar-container.snackbar-success .cc-snackbar-icon{color:var(--cc-sb-success-icon-color, #10b981)}.cc-snackbar-container.snackbar-error{background:var(--cc-sb-error-bg, #fef2f2);color:var(--cc-sb-error-color, #991b1b);border-color:var(--cc-sb-error-border, #fecaca)}.cc-snackbar-container.snackbar-error .cc-snackbar-icon{color:var(--cc-sb-error-icon-color, #ef4444)}.cc-snackbar-container.snackbar-warning{background:var(--cc-sb-warning-bg, #fffbeb);color:var(--cc-sb-warning-color, #92400e);border-color:var(--cc-sb-warning-border, #fde68a)}.cc-snackbar-container.snackbar-warning .cc-snackbar-icon{color:var(--cc-sb-warning-icon-color, #f59e0b)}.cc-snackbar-container.snackbar-info{background:var(--cc-sb-info-bg, #eff6ff);color:var(--cc-sb-info-color, #1e40af);border-color:var(--cc-sb-info-border, #bfdbfe)}.cc-snackbar-container.snackbar-info .cc-snackbar-icon{color:var(--cc-sb-info-icon-color, #3b82f6)}.cc-snackbar-container .cc-snackbar-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0}.cc-snackbar-container .cc-snackbar-icon svg{width:var(--cc-sb-icon-size, 20px);height:var(--cc-sb-icon-size, 20px)}.cc-snackbar-container .cc-snackbar-message{flex-grow:1;line-height:1.4}.cc-snackbar-container .cc-snackbar-close{background:transparent;border:none;padding:0;margin:0;cursor:pointer;display:flex;align-items:center;justify-content:center;color:currentcolor;opacity:.7;transition:opacity .2s}.cc-snackbar-container .cc-snackbar-close:hover{opacity:1}.cc-snackbar-container .cc-snackbar-close svg{width:var(--cc-sb-close-icon-size, 16px);height:var(--cc-sb-close-icon-size, 16px)}::ng-deep .cc-snackbar-panel .mdc-snackbar__surface{background:transparent!important;box-shadow:none!important;padding:0!important;border-radius:0!important}::ng-deep .cc-snackbar-panel.mat-snack-bar-container{background:transparent!important;box-shadow:none!important;padding:0!important}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
3790
|
+
}
|
|
3791
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SnackbarComponent, decorators: [{
|
|
3792
|
+
type: Component,
|
|
3793
|
+
args: [{ selector: 'lib-snackbar', standalone: false, template: "<div class=\"cc-snackbar-container\" [ngClass]=\"variantClass\">\n <div class=\"cc-snackbar-icon\">\n <!-- Success Icon -->\n <svg *ngIf=\"data.variant === 'success'\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"></path>\n <polyline points=\"22 4 12 14.01 9 11.01\"></polyline>\n </svg>\n \n <!-- Error Icon -->\n <svg *ngIf=\"data.variant === 'error'\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"></line>\n <line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"></line>\n </svg>\n \n <!-- Warning Icon -->\n <svg *ngIf=\"data.variant === 'warning'\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"></path>\n <line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"></line>\n <line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"></line>\n </svg>\n \n <!-- Info Icon -->\n <svg *ngIf=\"data.variant === 'info' || !data.variant\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\"></line>\n <line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\"></line>\n </svg>\n </div>\n \n <div class=\"cc-snackbar-message\">\n {{ data.message }}\n </div>\n\n <button *ngIf=\"data.showCloseButton\" class=\"cc-snackbar-close\" (click)=\"snackBarRef.dismiss()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n</div>\n", styles: [".cc-snackbar-container{display:flex;align-items:center;gap:var(--cc-sb-gap, 12px);padding:var(--cc-sb-padding, 12px 16px);border-radius:var(--cc-sb-radius, 8px);box-shadow:var(--cc-sb-shadow, 0 4px 6px -1px rgba(0, 0, 0, .1), 0 2px 4px -1px rgba(0, 0, 0, .06));font-family:var(--cc-sb-font-family, \"Inter\", sans-serif);font-size:var(--cc-sb-font-size, 14px);font-weight:var(--cc-sb-font-weight, 500);background:var(--cc-sb-bg, #ffffff);color:var(--cc-sb-color, #1f2937);border:var(--cc-sb-border, 1px solid transparent);min-width:var(--cc-sb-min-width, 300px)}.cc-snackbar-container.snackbar-success{background:var(--cc-sb-success-bg, #ecfdf5);color:var(--cc-sb-success-color, #065f46);border-color:var(--cc-sb-success-border, #a7f3d0)}.cc-snackbar-container.snackbar-success .cc-snackbar-icon{color:var(--cc-sb-success-icon-color, #10b981)}.cc-snackbar-container.snackbar-error{background:var(--cc-sb-error-bg, #fef2f2);color:var(--cc-sb-error-color, #991b1b);border-color:var(--cc-sb-error-border, #fecaca)}.cc-snackbar-container.snackbar-error .cc-snackbar-icon{color:var(--cc-sb-error-icon-color, #ef4444)}.cc-snackbar-container.snackbar-warning{background:var(--cc-sb-warning-bg, #fffbeb);color:var(--cc-sb-warning-color, #92400e);border-color:var(--cc-sb-warning-border, #fde68a)}.cc-snackbar-container.snackbar-warning .cc-snackbar-icon{color:var(--cc-sb-warning-icon-color, #f59e0b)}.cc-snackbar-container.snackbar-info{background:var(--cc-sb-info-bg, #eff6ff);color:var(--cc-sb-info-color, #1e40af);border-color:var(--cc-sb-info-border, #bfdbfe)}.cc-snackbar-container.snackbar-info .cc-snackbar-icon{color:var(--cc-sb-info-icon-color, #3b82f6)}.cc-snackbar-container .cc-snackbar-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0}.cc-snackbar-container .cc-snackbar-icon svg{width:var(--cc-sb-icon-size, 20px);height:var(--cc-sb-icon-size, 20px)}.cc-snackbar-container .cc-snackbar-message{flex-grow:1;line-height:1.4}.cc-snackbar-container .cc-snackbar-close{background:transparent;border:none;padding:0;margin:0;cursor:pointer;display:flex;align-items:center;justify-content:center;color:currentcolor;opacity:.7;transition:opacity .2s}.cc-snackbar-container .cc-snackbar-close:hover{opacity:1}.cc-snackbar-container .cc-snackbar-close svg{width:var(--cc-sb-close-icon-size, 16px);height:var(--cc-sb-close-icon-size, 16px)}::ng-deep .cc-snackbar-panel .mdc-snackbar__surface{background:transparent!important;box-shadow:none!important;padding:0!important;border-radius:0!important}::ng-deep .cc-snackbar-panel.mat-snack-bar-container{background:transparent!important;box-shadow:none!important;padding:0!important}\n"] }]
|
|
3794
|
+
}] });
|
|
3795
|
+
|
|
3796
|
+
class SnackbarService {
|
|
3797
|
+
snackBar;
|
|
3798
|
+
constructor(snackBar) {
|
|
3799
|
+
this.snackBar = snackBar;
|
|
3800
|
+
}
|
|
3801
|
+
show(config) {
|
|
3802
|
+
const matConfig = {
|
|
3803
|
+
duration: config.duration ?? 5000,
|
|
3804
|
+
horizontalPosition: config.horizontalPosition ?? 'right',
|
|
3805
|
+
verticalPosition: config.verticalPosition ?? 'top',
|
|
3806
|
+
panelClass: ['cc-snackbar-panel', `cc-snackbar-${config.variant || 'info'}`],
|
|
3807
|
+
data: config // Pass the entire config down to the component
|
|
3808
|
+
};
|
|
3809
|
+
this.snackBar.openFromComponent(SnackbarComponent, matConfig);
|
|
3810
|
+
}
|
|
3811
|
+
success(message, duration) {
|
|
3812
|
+
this.show({ message, variant: 'success', duration });
|
|
3813
|
+
}
|
|
3814
|
+
error(message, duration) {
|
|
3815
|
+
this.show({ message, variant: 'error', duration });
|
|
3816
|
+
}
|
|
3817
|
+
warning(message, duration) {
|
|
3818
|
+
this.show({ message, variant: 'warning', duration });
|
|
3819
|
+
}
|
|
3820
|
+
info(message, duration) {
|
|
3821
|
+
this.show({ message, variant: 'info', duration });
|
|
3822
|
+
}
|
|
3823
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SnackbarService, deps: [{ token: i2$2.MatSnackBar }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3824
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SnackbarService, providedIn: 'root' });
|
|
3825
|
+
}
|
|
3826
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SnackbarService, decorators: [{
|
|
3827
|
+
type: Injectable,
|
|
3828
|
+
args: [{
|
|
3829
|
+
providedIn: 'root'
|
|
3830
|
+
}]
|
|
3831
|
+
}], ctorParameters: () => [{ type: i2$2.MatSnackBar }] });
|
|
3832
|
+
|
|
3782
3833
|
/**
|
|
3783
3834
|
* Utility functions for string manipulation
|
|
3784
3835
|
*/
|
|
@@ -4483,6 +4534,7 @@ class SmartFormComponent {
|
|
|
4483
4534
|
controller;
|
|
4484
4535
|
expressionService;
|
|
4485
4536
|
http;
|
|
4537
|
+
snackbarService;
|
|
4486
4538
|
formJson;
|
|
4487
4539
|
initialValues;
|
|
4488
4540
|
enableDraftAutoSave = false;
|
|
@@ -4492,6 +4544,7 @@ class SmartFormComponent {
|
|
|
4492
4544
|
* Mirrors the pattern used by ConfigurableFormComponent + translateConfig.
|
|
4493
4545
|
*/
|
|
4494
4546
|
labels = {};
|
|
4547
|
+
mode = 'CREATE';
|
|
4495
4548
|
submit = new EventEmitter();
|
|
4496
4549
|
draftSave = new EventEmitter();
|
|
4497
4550
|
formSchema;
|
|
@@ -4500,18 +4553,41 @@ class SmartFormComponent {
|
|
|
4500
4553
|
isStepper = false;
|
|
4501
4554
|
currentStep = 0;
|
|
4502
4555
|
isLoading = false;
|
|
4503
|
-
constructor(fb, controller, expressionService, http) {
|
|
4556
|
+
constructor(fb, controller, expressionService, http, snackbarService) {
|
|
4504
4557
|
this.fb = fb;
|
|
4505
4558
|
this.controller = controller;
|
|
4506
4559
|
this.expressionService = expressionService;
|
|
4507
4560
|
this.http = http;
|
|
4561
|
+
this.snackbarService = snackbarService;
|
|
4508
4562
|
}
|
|
4509
4563
|
ngOnInit() {
|
|
4510
4564
|
this.parseFormJson();
|
|
4511
|
-
|
|
4565
|
+
// Load databe in EDIT mode, or use fallback initialValues
|
|
4566
|
+
if (this.mode === 'EDIT' && this.formSchema?.editConfig?.loadApiUrl) {
|
|
4567
|
+
this.loadEditData();
|
|
4568
|
+
}
|
|
4569
|
+
else if (this.initialValues) {
|
|
4512
4570
|
this.controller.initialize(this.initialValues);
|
|
4513
4571
|
}
|
|
4514
4572
|
}
|
|
4573
|
+
loadEditData() {
|
|
4574
|
+
const config = this.formSchema.editConfig;
|
|
4575
|
+
this.isLoading = true;
|
|
4576
|
+
const headers = this.getHeaders();
|
|
4577
|
+
this.http.get(config.loadApiUrl, { headers }).subscribe({
|
|
4578
|
+
next: (response) => {
|
|
4579
|
+
// Assume API returns flat or easily mappable object matching form controls
|
|
4580
|
+
this.initialValues = response;
|
|
4581
|
+
this.controller.initialize(this.initialValues || {});
|
|
4582
|
+
this.isLoading = false;
|
|
4583
|
+
},
|
|
4584
|
+
error: (err) => {
|
|
4585
|
+
this.showAlert('error', config.errorMessage || 'Failed to load form data', config.snackbarConfig);
|
|
4586
|
+
console.error('Load data error:', err);
|
|
4587
|
+
this.isLoading = false;
|
|
4588
|
+
}
|
|
4589
|
+
});
|
|
4590
|
+
}
|
|
4515
4591
|
ngOnChanges(changes) {
|
|
4516
4592
|
if (changes['formJson'] && !changes['formJson'].isFirstChange()) {
|
|
4517
4593
|
this.parseFormJson();
|
|
@@ -4596,11 +4672,109 @@ class SmartFormComponent {
|
|
|
4596
4672
|
}
|
|
4597
4673
|
}
|
|
4598
4674
|
/**
|
|
4599
|
-
*
|
|
4600
|
-
* arrays of objects so repeater groups come out as expected.
|
|
4675
|
+
* Constructs nested payload by checking field properties on form controls.
|
|
4601
4676
|
*/
|
|
4602
4677
|
collectFormData() {
|
|
4603
|
-
|
|
4678
|
+
const rawValue = this.extractGroupValue(this.formGroup);
|
|
4679
|
+
let payload = this.buildNestedPayload(rawValue, this.fieldList);
|
|
4680
|
+
// Merge extra fields based on the mode
|
|
4681
|
+
const config = this.mode === 'EDIT' ? this.formSchema.editConfig : this.formSchema.submitConfig;
|
|
4682
|
+
if (config?.extraPayload) {
|
|
4683
|
+
payload = this.deepMerge(payload, config.extraPayload);
|
|
4684
|
+
}
|
|
4685
|
+
return payload;
|
|
4686
|
+
}
|
|
4687
|
+
/**
|
|
4688
|
+
* Deep merges the source object (e.g. extraPayload) into the target object (e.g. form payload).
|
|
4689
|
+
*/
|
|
4690
|
+
deepMerge(target, source) {
|
|
4691
|
+
if (typeof target !== 'object' || target === null) {
|
|
4692
|
+
return source;
|
|
4693
|
+
}
|
|
4694
|
+
if (typeof source !== 'object' || source === null) {
|
|
4695
|
+
return source;
|
|
4696
|
+
}
|
|
4697
|
+
if (Array.isArray(target) && Array.isArray(source)) {
|
|
4698
|
+
// For arrays, we merge objects at the same index
|
|
4699
|
+
const maxLength = Math.max(target.length, source.length);
|
|
4700
|
+
const mergedArray = [];
|
|
4701
|
+
for (let i = 0; i < maxLength; i++) {
|
|
4702
|
+
if (i < target.length && i < source.length) {
|
|
4703
|
+
mergedArray.push(this.deepMerge(target[i], source[i]));
|
|
4704
|
+
}
|
|
4705
|
+
else if (i < source.length) {
|
|
4706
|
+
mergedArray.push(source[i]);
|
|
4707
|
+
}
|
|
4708
|
+
else {
|
|
4709
|
+
mergedArray.push(target[i]);
|
|
4710
|
+
}
|
|
4711
|
+
}
|
|
4712
|
+
return mergedArray;
|
|
4713
|
+
}
|
|
4714
|
+
const merged = { ...target };
|
|
4715
|
+
Object.keys(source).forEach(key => {
|
|
4716
|
+
if (source[key] instanceof Object && key in target) {
|
|
4717
|
+
merged[key] = this.deepMerge(target[key], source[key]);
|
|
4718
|
+
}
|
|
4719
|
+
else {
|
|
4720
|
+
merged[key] = source[key];
|
|
4721
|
+
}
|
|
4722
|
+
});
|
|
4723
|
+
return merged;
|
|
4724
|
+
}
|
|
4725
|
+
buildNestedPayload(rawValue, fields) {
|
|
4726
|
+
const payload = {};
|
|
4727
|
+
fields.forEach(field => {
|
|
4728
|
+
if (field.type === 'ROW' && field.children) {
|
|
4729
|
+
Object.assign(payload, this.buildNestedPayload(rawValue, field.children));
|
|
4730
|
+
}
|
|
4731
|
+
else if (field.name && rawValue[field.name] !== undefined) {
|
|
4732
|
+
const val = rawValue[field.name];
|
|
4733
|
+
if (field.payloadPath) {
|
|
4734
|
+
this.setNestedValue(payload, field.payloadPath, val);
|
|
4735
|
+
}
|
|
4736
|
+
else {
|
|
4737
|
+
payload[field.name] = val;
|
|
4738
|
+
}
|
|
4739
|
+
}
|
|
4740
|
+
});
|
|
4741
|
+
return payload;
|
|
4742
|
+
}
|
|
4743
|
+
setNestedValue(obj, path, value) {
|
|
4744
|
+
// Regex matches the property name and optionally an array index e.g. "name[0]" -> regex yields ["name[0]", "name", "0"]
|
|
4745
|
+
const arrayRegex = /^([a-zA-Z0-9_]+)\[(\d+)\]$/;
|
|
4746
|
+
const parts = path.split('.');
|
|
4747
|
+
let current = obj;
|
|
4748
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
4749
|
+
const part = parts[i];
|
|
4750
|
+
const match = part.match(arrayRegex);
|
|
4751
|
+
if (match) {
|
|
4752
|
+
const prop = match[1];
|
|
4753
|
+
const index = parseInt(match[2], 10);
|
|
4754
|
+
if (!current[prop])
|
|
4755
|
+
current[prop] = [];
|
|
4756
|
+
if (!current[prop][index])
|
|
4757
|
+
current[prop][index] = {};
|
|
4758
|
+
current = current[prop][index];
|
|
4759
|
+
}
|
|
4760
|
+
else {
|
|
4761
|
+
if (!current[part])
|
|
4762
|
+
current[part] = {};
|
|
4763
|
+
current = current[part];
|
|
4764
|
+
}
|
|
4765
|
+
}
|
|
4766
|
+
const lastPart = parts[parts.length - 1];
|
|
4767
|
+
const matchLast = lastPart.match(arrayRegex);
|
|
4768
|
+
if (matchLast) {
|
|
4769
|
+
const prop = matchLast[1];
|
|
4770
|
+
const index = parseInt(matchLast[2], 10);
|
|
4771
|
+
if (!current[prop])
|
|
4772
|
+
current[prop] = [];
|
|
4773
|
+
current[prop][index] = value;
|
|
4774
|
+
}
|
|
4775
|
+
else {
|
|
4776
|
+
current[lastPart] = value;
|
|
4777
|
+
}
|
|
4604
4778
|
}
|
|
4605
4779
|
extractGroupValue(group) {
|
|
4606
4780
|
const result = {};
|
|
@@ -4637,22 +4811,42 @@ class SmartFormComponent {
|
|
|
4637
4811
|
}, 100);
|
|
4638
4812
|
}
|
|
4639
4813
|
submitToApi(formData) {
|
|
4640
|
-
const
|
|
4641
|
-
const
|
|
4814
|
+
const isEdit = this.mode === 'EDIT';
|
|
4815
|
+
const config = isEdit ? this.formSchema.editConfig : this.formSchema.submitConfig;
|
|
4816
|
+
if (!config || (!config.apiUrl && !config.submitApiUrl)) {
|
|
4817
|
+
this.submit.emit(formData);
|
|
4818
|
+
this.isLoading = false;
|
|
4819
|
+
return;
|
|
4820
|
+
}
|
|
4821
|
+
const apiUrl = isEdit ? config.submitApiUrl : config.apiUrl;
|
|
4822
|
+
const method = isEdit ? (config.submitMethod || 'PATCH') : (config.method || 'POST');
|
|
4642
4823
|
const headers = this.getHeaders();
|
|
4643
|
-
this.http.request(method,
|
|
4824
|
+
this.http.request(method, apiUrl, { body: formData, headers }).subscribe({
|
|
4644
4825
|
next: response => {
|
|
4645
|
-
|
|
4826
|
+
this.showAlert('success', config.successMessage || 'Form submitted successfully', config.snackbarConfig);
|
|
4646
4827
|
this.submit.emit(response);
|
|
4647
4828
|
this.isLoading = false;
|
|
4829
|
+
if (config.redirectUrl) {
|
|
4830
|
+
setTimeout(() => {
|
|
4831
|
+
window.location.href = config.redirectUrl;
|
|
4832
|
+
}, 1500);
|
|
4833
|
+
}
|
|
4648
4834
|
},
|
|
4649
4835
|
error: err => {
|
|
4650
|
-
|
|
4836
|
+
this.showAlert('error', config.errorMessage || 'Failed to submit form', config.snackbarConfig);
|
|
4651
4837
|
console.error('Submit error:', err);
|
|
4652
4838
|
this.isLoading = false;
|
|
4653
4839
|
}
|
|
4654
4840
|
});
|
|
4655
4841
|
}
|
|
4842
|
+
showAlert(type, message, customConfig) {
|
|
4843
|
+
this.snackbarService.show({
|
|
4844
|
+
variant: type,
|
|
4845
|
+
message: message,
|
|
4846
|
+
showCloseButton: true,
|
|
4847
|
+
...customConfig
|
|
4848
|
+
});
|
|
4849
|
+
}
|
|
4656
4850
|
/** Builds HttpHeaders from the token stored in the controller (sourced from configJSON). */
|
|
4657
4851
|
getHeaders() {
|
|
4658
4852
|
let headers = new HttpHeaders();
|
|
@@ -4691,13 +4885,13 @@ class SmartFormComponent {
|
|
|
4691
4885
|
const key = this.formSchema?.labels?.previousLabel || 'Previous';
|
|
4692
4886
|
return this.labels[key] || key;
|
|
4693
4887
|
}
|
|
4694
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartFormComponent, deps: [{ token: i1$2.FormBuilder }, { token: SmartFormController }, { token: ExpressionService }, { token: i3.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
|
|
4695
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartFormComponent, isStandalone: false, selector: "lib-smart-form", inputs: { formJson: "formJson", initialValues: "initialValues", enableDraftAutoSave: "enableDraftAutoSave", labels: "labels" }, outputs: { submit: "submit", draftSave: "draftSave" }, providers: [SmartFormController], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-form-container\">\r\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema\">\r\n <!-- Form Header -->\r\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\r\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\r\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\r\n </div>\r\n\r\n <!-- Stepper Navigation -->\r\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\r\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\r\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\r\n [class.completed]=\"i < currentStep\">\r\n <div class=\"step-number\">{{ i + 1 }}</div>\r\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\r\n <!-- Section Form -->\r\n <div *ngIf=\"!isStepper && formSchema.sectionConfig\" class=\"form-section\">\r\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n\r\n <!-- Stepper Form -->\r\n <div *ngIf=\"isStepper && currentStepConfig\" class=\"form-stepper\">\r\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- Form Actions -->\r\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false\">\r\n <lib-button *ngIf=\"isStepper && canGoPrevious\" [variant]=\"'outline'\" (click)=\"previousStep()\">\r\n {{ previousLabel }}\r\n </lib-button>\r\n\r\n <lib-button [variant]=\"'warning'\" [disabled]=\"isLoading\" (click)=\"handleSubmit()\">\r\n {{ isStepper && canGoNext ? nextLabel : submitLabel }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n</div>", styles: [".smart-form-container{width:100%;max-width:var(--cc-sf-form-max-width, 1200px);margin:0 auto;padding:var(--cc-sf-form-padding, 24px);font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06))}.form-header{margin-bottom:24px}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{margin-bottom:24px}.form-actions{display:flex;justify-content:flex-end;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 0 0);border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.form-actions .btn{font-size:var(--cc-sf-btn-font-size, .875rem);font-weight:var(--cc-sf-btn-font-weight, 600);border:none;cursor:pointer;transition:var(--cc-sf-btn-transition, all .2s ease);font-family:var(--cc-sf-font-family, inherit);line-height:1.5}.form-actions .btn.btn-primary{background:var(--cc-sf-btn-primary-bg, #3B82F6);color:var(--cc-sf-btn-primary-color, #ffffff);border-radius:var(--cc-sf-btn-primary-radius, 8px);padding:var(--cc-sf-btn-primary-padding, .625rem 1.5rem)}.form-actions .btn.btn-primary:hover:not(:disabled){background:var(--cc-sf-btn-primary-hover-bg, #2563EB)}.form-actions .btn.btn-primary:disabled{opacity:var(--cc-sf-btn-disabled-opacity, .55);cursor:not-allowed}.form-actions .btn.btn-secondary{background:var(--cc-sf-btn-secondary-bg, #F3F4F6);color:var(--cc-sf-btn-secondary-color, #374151);border-radius:var(--cc-sf-btn-secondary-radius, 8px);padding:var(--cc-sf-btn-secondary-padding, .625rem 1.5rem)}.form-actions .btn.btn-secondary:hover{background:var(--cc-sf-btn-secondary-hover-bg, #E5E7EB)}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: FormSectionComponent, selector: "lib-form-section", inputs: ["config", "controller", "formGroup"] }] });
|
|
4888
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartFormComponent, deps: [{ token: i1$2.FormBuilder }, { token: SmartFormController }, { token: ExpressionService }, { token: i3.HttpClient }, { token: SnackbarService }], target: i0.ɵɵFactoryTarget.Component });
|
|
4889
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartFormComponent, isStandalone: false, selector: "lib-smart-form", inputs: { formJson: "formJson", initialValues: "initialValues", enableDraftAutoSave: "enableDraftAutoSave", labels: "labels", mode: "mode" }, outputs: { submit: "submit", draftSave: "draftSave" }, providers: [SmartFormController], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-form-container\">\r\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema\">\r\n\r\n <!-- Form Header -->\r\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\r\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\r\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\r\n </div>\r\n\r\n <!-- Stepper Navigation -->\r\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\r\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\r\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\r\n [class.completed]=\"i < currentStep\">\r\n <div class=\"step-number\">{{ i + 1 }}</div>\r\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\r\n <!-- Section Form -->\r\n <div *ngIf=\"!isStepper && formSchema.sectionConfig\" class=\"form-section\">\r\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n\r\n <!-- Stepper Form -->\r\n <div *ngIf=\"isStepper && currentStepConfig\" class=\"form-stepper\">\r\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- Form Actions -->\r\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false\">\r\n <lib-button *ngIf=\"isStepper && canGoPrevious\" [variant]=\"'outline'\" (click)=\"previousStep()\">\r\n {{ previousLabel }}\r\n </lib-button>\r\n\r\n <lib-button [variant]=\"'warning'\" [disabled]=\"isLoading\" (click)=\"handleSubmit()\">\r\n {{ isStepper && canGoNext ? nextLabel : submitLabel }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n</div>", styles: [".smart-form-container{width:100%;max-width:var(--cc-sf-form-max-width, 1200px);margin:0 auto;padding:var(--cc-sf-form-padding, 24px);font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06))}.smart-form-wrapper .form-alert-feedback{margin-bottom:1rem}.form-header{margin-bottom:24px}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{margin-bottom:24px}.form-actions{display:flex;justify-content:flex-end;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 0 0);border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.form-actions .btn{font-size:var(--cc-sf-btn-font-size, .875rem);font-weight:var(--cc-sf-btn-font-weight, 600);border:none;cursor:pointer;transition:var(--cc-sf-btn-transition, all .2s ease);font-family:var(--cc-sf-font-family, inherit);line-height:1.5}.form-actions .btn.btn-primary{background:var(--cc-sf-btn-primary-bg, #3B82F6);color:var(--cc-sf-btn-primary-color, #ffffff);border-radius:var(--cc-sf-btn-primary-radius, 8px);padding:var(--cc-sf-btn-primary-padding, .625rem 1.5rem)}.form-actions .btn.btn-primary:hover:not(:disabled){background:var(--cc-sf-btn-primary-hover-bg, #2563EB)}.form-actions .btn.btn-primary:disabled{opacity:var(--cc-sf-btn-disabled-opacity, .55);cursor:not-allowed}.form-actions .btn.btn-secondary{background:var(--cc-sf-btn-secondary-bg, #F3F4F6);color:var(--cc-sf-btn-secondary-color, #374151);border-radius:var(--cc-sf-btn-secondary-radius, 8px);padding:var(--cc-sf-btn-secondary-padding, .625rem 1.5rem)}.form-actions .btn.btn-secondary:hover{background:var(--cc-sf-btn-secondary-hover-bg, #E5E7EB)}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: FormSectionComponent, selector: "lib-form-section", inputs: ["config", "controller", "formGroup"] }] });
|
|
4696
4890
|
}
|
|
4697
4891
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartFormComponent, decorators: [{
|
|
4698
4892
|
type: Component,
|
|
4699
|
-
args: [{ selector: 'lib-smart-form', providers: [SmartFormController], standalone: false, template: "<div class=\"smart-form-container\">\r\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema\">\r\n <!-- Form Header -->\r\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\r\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\r\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\r\n </div>\r\n\r\n <!-- Stepper Navigation -->\r\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\r\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\r\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\r\n [class.completed]=\"i < currentStep\">\r\n <div class=\"step-number\">{{ i + 1 }}</div>\r\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\r\n <!-- Section Form -->\r\n <div *ngIf=\"!isStepper && formSchema.sectionConfig\" class=\"form-section\">\r\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n\r\n <!-- Stepper Form -->\r\n <div *ngIf=\"isStepper && currentStepConfig\" class=\"form-stepper\">\r\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- Form Actions -->\r\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false\">\r\n <lib-button *ngIf=\"isStepper && canGoPrevious\" [variant]=\"'outline'\" (click)=\"previousStep()\">\r\n {{ previousLabel }}\r\n </lib-button>\r\n\r\n <lib-button [variant]=\"'warning'\" [disabled]=\"isLoading\" (click)=\"handleSubmit()\">\r\n {{ isStepper && canGoNext ? nextLabel : submitLabel }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n</div>", styles: [".smart-form-container{width:100%;max-width:var(--cc-sf-form-max-width, 1200px);margin:0 auto;padding:var(--cc-sf-form-padding, 24px);font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06))}.form-header{margin-bottom:24px}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{margin-bottom:24px}.form-actions{display:flex;justify-content:flex-end;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 0 0);border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.form-actions .btn{font-size:var(--cc-sf-btn-font-size, .875rem);font-weight:var(--cc-sf-btn-font-weight, 600);border:none;cursor:pointer;transition:var(--cc-sf-btn-transition, all .2s ease);font-family:var(--cc-sf-font-family, inherit);line-height:1.5}.form-actions .btn.btn-primary{background:var(--cc-sf-btn-primary-bg, #3B82F6);color:var(--cc-sf-btn-primary-color, #ffffff);border-radius:var(--cc-sf-btn-primary-radius, 8px);padding:var(--cc-sf-btn-primary-padding, .625rem 1.5rem)}.form-actions .btn.btn-primary:hover:not(:disabled){background:var(--cc-sf-btn-primary-hover-bg, #2563EB)}.form-actions .btn.btn-primary:disabled{opacity:var(--cc-sf-btn-disabled-opacity, .55);cursor:not-allowed}.form-actions .btn.btn-secondary{background:var(--cc-sf-btn-secondary-bg, #F3F4F6);color:var(--cc-sf-btn-secondary-color, #374151);border-radius:var(--cc-sf-btn-secondary-radius, 8px);padding:var(--cc-sf-btn-secondary-padding, .625rem 1.5rem)}.form-actions .btn.btn-secondary:hover{background:var(--cc-sf-btn-secondary-hover-bg, #E5E7EB)}\n"] }]
|
|
4700
|
-
}], ctorParameters: () => [{ type: i1$2.FormBuilder }, { type: SmartFormController }, { type: ExpressionService }, { type: i3.HttpClient }], propDecorators: { formJson: [{
|
|
4893
|
+
args: [{ selector: 'lib-smart-form', providers: [SmartFormController], standalone: false, template: "<div class=\"smart-form-container\">\r\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema\">\r\n\r\n <!-- Form Header -->\r\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\r\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\r\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\r\n </div>\r\n\r\n <!-- Stepper Navigation -->\r\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\r\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\r\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\r\n [class.completed]=\"i < currentStep\">\r\n <div class=\"step-number\">{{ i + 1 }}</div>\r\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\r\n <!-- Section Form -->\r\n <div *ngIf=\"!isStepper && formSchema.sectionConfig\" class=\"form-section\">\r\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n\r\n <!-- Stepper Form -->\r\n <div *ngIf=\"isStepper && currentStepConfig\" class=\"form-stepper\">\r\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- Form Actions -->\r\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false\">\r\n <lib-button *ngIf=\"isStepper && canGoPrevious\" [variant]=\"'outline'\" (click)=\"previousStep()\">\r\n {{ previousLabel }}\r\n </lib-button>\r\n\r\n <lib-button [variant]=\"'warning'\" [disabled]=\"isLoading\" (click)=\"handleSubmit()\">\r\n {{ isStepper && canGoNext ? nextLabel : submitLabel }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n</div>", styles: [".smart-form-container{width:100%;max-width:var(--cc-sf-form-max-width, 1200px);margin:0 auto;padding:var(--cc-sf-form-padding, 24px);font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06))}.smart-form-wrapper .form-alert-feedback{margin-bottom:1rem}.form-header{margin-bottom:24px}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{margin-bottom:24px}.form-actions{display:flex;justify-content:flex-end;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 0 0);border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.form-actions .btn{font-size:var(--cc-sf-btn-font-size, .875rem);font-weight:var(--cc-sf-btn-font-weight, 600);border:none;cursor:pointer;transition:var(--cc-sf-btn-transition, all .2s ease);font-family:var(--cc-sf-font-family, inherit);line-height:1.5}.form-actions .btn.btn-primary{background:var(--cc-sf-btn-primary-bg, #3B82F6);color:var(--cc-sf-btn-primary-color, #ffffff);border-radius:var(--cc-sf-btn-primary-radius, 8px);padding:var(--cc-sf-btn-primary-padding, .625rem 1.5rem)}.form-actions .btn.btn-primary:hover:not(:disabled){background:var(--cc-sf-btn-primary-hover-bg, #2563EB)}.form-actions .btn.btn-primary:disabled{opacity:var(--cc-sf-btn-disabled-opacity, .55);cursor:not-allowed}.form-actions .btn.btn-secondary{background:var(--cc-sf-btn-secondary-bg, #F3F4F6);color:var(--cc-sf-btn-secondary-color, #374151);border-radius:var(--cc-sf-btn-secondary-radius, 8px);padding:var(--cc-sf-btn-secondary-padding, .625rem 1.5rem)}.form-actions .btn.btn-secondary:hover{background:var(--cc-sf-btn-secondary-hover-bg, #E5E7EB)}\n"] }]
|
|
4894
|
+
}], ctorParameters: () => [{ type: i1$2.FormBuilder }, { type: SmartFormController }, { type: ExpressionService }, { type: i3.HttpClient }, { type: SnackbarService }], propDecorators: { formJson: [{
|
|
4701
4895
|
type: Input
|
|
4702
4896
|
}], initialValues: [{
|
|
4703
4897
|
type: Input
|
|
@@ -4705,6 +4899,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
4705
4899
|
type: Input
|
|
4706
4900
|
}], labels: [{
|
|
4707
4901
|
type: Input
|
|
4902
|
+
}], mode: [{
|
|
4903
|
+
type: Input
|
|
4708
4904
|
}], submit: [{
|
|
4709
4905
|
type: Output
|
|
4710
4906
|
}], draftSave: [{
|
|
@@ -4719,14 +4915,16 @@ class SmartFormModule {
|
|
|
4719
4915
|
ReactiveFormsModule,
|
|
4720
4916
|
FormsModule,
|
|
4721
4917
|
MaterialModule,
|
|
4722
|
-
ButtonModule
|
|
4918
|
+
ButtonModule,
|
|
4919
|
+
AlertModule], exports: [SmartFormComponent] });
|
|
4723
4920
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartFormModule, providers: [
|
|
4724
4921
|
ExpressionService
|
|
4725
4922
|
], imports: [CommonModule,
|
|
4726
4923
|
ReactiveFormsModule,
|
|
4727
4924
|
FormsModule,
|
|
4728
4925
|
MaterialModule,
|
|
4729
|
-
ButtonModule
|
|
4926
|
+
ButtonModule,
|
|
4927
|
+
AlertModule] });
|
|
4730
4928
|
}
|
|
4731
4929
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartFormModule, decorators: [{
|
|
4732
4930
|
type: NgModule,
|
|
@@ -4741,7 +4939,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
4741
4939
|
ReactiveFormsModule,
|
|
4742
4940
|
FormsModule,
|
|
4743
4941
|
MaterialModule,
|
|
4744
|
-
ButtonModule
|
|
4942
|
+
ButtonModule,
|
|
4943
|
+
AlertModule
|
|
4745
4944
|
],
|
|
4746
4945
|
exports: [
|
|
4747
4946
|
SmartFormComponent
|
|
@@ -7401,6 +7600,20 @@ var smartForm_examples = /*#__PURE__*/Object.freeze({
|
|
|
7401
7600
|
SAMPLE_FORMS: SAMPLE_FORMS
|
|
7402
7601
|
});
|
|
7403
7602
|
|
|
7603
|
+
class SnackbarModule {
|
|
7604
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SnackbarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
7605
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: SnackbarModule, declarations: [SnackbarComponent], imports: [CommonModule, MatSnackBarModule], exports: [SnackbarComponent] });
|
|
7606
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SnackbarModule, imports: [CommonModule, MatSnackBarModule] });
|
|
7607
|
+
}
|
|
7608
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SnackbarModule, decorators: [{
|
|
7609
|
+
type: NgModule,
|
|
7610
|
+
args: [{
|
|
7611
|
+
declarations: [SnackbarComponent],
|
|
7612
|
+
imports: [CommonModule, MatSnackBarModule],
|
|
7613
|
+
exports: [SnackbarComponent]
|
|
7614
|
+
}]
|
|
7615
|
+
}] });
|
|
7616
|
+
|
|
7404
7617
|
/*
|
|
7405
7618
|
* Public API Surface of commons-shared-web-ui
|
|
7406
7619
|
*/
|
|
@@ -7409,5 +7622,5 @@ var smartForm_examples = /*#__PURE__*/Object.freeze({
|
|
|
7409
7622
|
* Generated bundle index. Do not edit.
|
|
7410
7623
|
*/
|
|
7411
7624
|
|
|
7412
|
-
export { AlertComponent, AlertModule, ButtonComponent, ButtonModule, CheckboxComponent, ConfigurableFormComponent, configurableForm_examples as ConfigurableFormExamples, ConfigurableFormModule, ConfirmationModalComponent, ConfirmationModalModule, DEFAULT_ITEMS_PER_PAGE, DEFAULT_PAGE_SIZE_OPTIONS, DatepickerComponent, DropdownComponent, ExpressionService, FilterComponent, FilterModule, FilterSidebarComponent, FilterSidebarModule, FormComponentsModule, InputComponent, MaterialModule, NAV_ORIENTATION_DEFAULT, NAV_VARIANT_DEFAULT, NavComponent, NavModule, PAGINATION_THEME_DARK, PAGINATION_THEME_DEFAULT, PaginationComponent, PaginationModule, RadioComponent, SearchComponent, SharedUiModule, SmartFormComponent, SmartFormController, smartForm_examples as SmartFormExamples, SmartFormModule, SmartTableComponent, SmartTableModule, StringUtils, SummaryCardComponent, SummaryCardModule, ToggleComponent, ValidationUtils, clearLocalStorage, clearSessionStorage, getLocalStorageItem, getSessionStorageItem, removeLocalStorageItem, removeSessionStorageItem, setLocalStorageItem, setSessionStorageItem, translateConfig };
|
|
7625
|
+
export { AlertComponent, AlertModule, ButtonComponent, ButtonModule, CheckboxComponent, ConfigurableFormComponent, configurableForm_examples as ConfigurableFormExamples, ConfigurableFormModule, ConfirmationModalComponent, ConfirmationModalModule, DEFAULT_ITEMS_PER_PAGE, DEFAULT_PAGE_SIZE_OPTIONS, DatepickerComponent, DropdownComponent, ExpressionService, FilterComponent, FilterModule, FilterSidebarComponent, FilterSidebarModule, FormComponentsModule, InputComponent, MaterialModule, NAV_ORIENTATION_DEFAULT, NAV_VARIANT_DEFAULT, NavComponent, NavModule, PAGINATION_THEME_DARK, PAGINATION_THEME_DEFAULT, PaginationComponent, PaginationModule, RadioComponent, SearchComponent, SharedUiModule, SmartFormComponent, SmartFormController, smartForm_examples as SmartFormExamples, SmartFormModule, SmartTableComponent, SmartTableModule, SnackbarComponent, SnackbarModule, SnackbarService, StringUtils, SummaryCardComponent, SummaryCardModule, ToggleComponent, ValidationUtils, clearLocalStorage, clearSessionStorage, getLocalStorageItem, getSessionStorageItem, removeLocalStorageItem, removeSessionStorageItem, setLocalStorageItem, setSessionStorageItem, translateConfig };
|
|
7413
7626
|
//# sourceMappingURL=commons-shared-web-ui.mjs.map
|