ui-core-abv 0.6.76 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/ui-core-abv.mjs +774 -75
- package/fesm2022/ui-core-abv.mjs.map +1 -1
- package/lib/components/dynamic-form/form/dynamic-form.component.d.ts +11 -2
- package/lib/components/dynamic-form/form-wrapper/form-wrapper.component.d.ts +5 -0
- package/lib/components/dynamic-form/form.models.d.ts +17 -2
- package/lib/components/dynamic-form/repeater/repeater.component.d.ts +21 -0
- package/lib/components/user-formbuilder/block-editor/block-editor.component.d.ts +22 -2
- package/lib/components/user-formbuilder/block-editor/field-editor/field-editor.component.d.ts +12 -2
- package/lib/components/user-formbuilder/block-editor/field-type-selector/field-type-selector.component.d.ts +4 -3
- package/lib/components/user-formbuilder/user-formbuilder.component.d.ts +11 -0
- package/lib/translate/dictionary.en.d.ts +24 -0
- package/lib/translate/dictionary.es.d.ts +31 -7
- package/package.json +1 -1
- package/public-api.d.ts +1 -0
package/fesm2022/ui-core-abv.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { CommonModule, CurrencyPipe, DatePipe } from '@angular/common';
|
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
4
|
import { Input, Component, EventEmitter, Output, Directive, forwardRef, InjectionToken, Optional, Inject, Injectable, inject, ChangeDetectorRef, Pipe, ViewContainerRef, ElementRef, ViewChild, createComponent, HostListener, ViewChildren, Host, DestroyRef, signal, computed, effect, TemplateRef, ContentChild, Injector, EnvironmentInjector, HostBinding, input, output } from '@angular/core';
|
|
5
5
|
import * as i1$1 from '@angular/forms';
|
|
6
|
-
import { NG_VALUE_ACCESSOR, FormsModule,
|
|
6
|
+
import { NG_VALUE_ACCESSOR, FormsModule, FormBuilder, Validators, ReactiveFormsModule, FormArray } from '@angular/forms';
|
|
7
7
|
import { BehaviorSubject, Subject, debounceTime, distinctUntilChanged, tap, switchMap, of, finalize, map, isObservable, from, Subscription } from 'rxjs';
|
|
8
8
|
import { HttpClient } from '@angular/common/http';
|
|
9
9
|
import { Overlay, OverlayRef } from '@angular/cdk/overlay';
|
|
@@ -388,6 +388,8 @@ const DICTIONARY_EN = {
|
|
|
388
388
|
block_subtitle: 'Subtitle',
|
|
389
389
|
add_block: 'Add block',
|
|
390
390
|
delete_block: 'Delete block',
|
|
391
|
+
delete_block_dependency_blocked: 'This block cannot be deleted because it contains fields that other fields depend on',
|
|
392
|
+
delete_field_dependency_blocked: 'This field cannot be deleted because another field depends on its value',
|
|
391
393
|
preview_form: 'Preview',
|
|
392
394
|
submit_form: 'Submit',
|
|
393
395
|
select_field_to_edit: 'Select a field to edit its properties',
|
|
@@ -486,6 +488,13 @@ const DICTIONARY_EN = {
|
|
|
486
488
|
selectSearchEnabled_tip: 'Enables search among options',
|
|
487
489
|
selectNullable: 'Allow empty option',
|
|
488
490
|
selectSearchEnabled: 'Enable search',
|
|
491
|
+
repeaterMinItems: 'Minimum items',
|
|
492
|
+
repeaterMinItems_tip: 'Minimum number of required items',
|
|
493
|
+
repeaterMaxItems: 'Maximum items',
|
|
494
|
+
repeaterMaxItems_tip: 'Maximum number of allowed items',
|
|
495
|
+
repeaterAddLabel: 'Add button label',
|
|
496
|
+
repeaterRemoveLabel: 'Remove button label',
|
|
497
|
+
repeaterItemTitle: 'Item title',
|
|
489
498
|
},
|
|
490
499
|
options_editor: {
|
|
491
500
|
title: 'Options',
|
|
@@ -511,10 +520,25 @@ const DICTIONARY_EN = {
|
|
|
511
520
|
delete: 'Delete',
|
|
512
521
|
show_advanced: 'Show advanced',
|
|
513
522
|
hide_advanced: 'Hide advanced',
|
|
523
|
+
subfields: 'Sub-fields',
|
|
524
|
+
},
|
|
525
|
+
visibility_operators: {
|
|
526
|
+
equals: 'Equals',
|
|
527
|
+
notEquals: 'Does not equal',
|
|
528
|
+
greaterThan: 'Is greater than',
|
|
529
|
+
lessThan: 'Is less than',
|
|
530
|
+
includes: 'Includes',
|
|
531
|
+
notIncludes: 'Does not include',
|
|
532
|
+
isEmpty: 'Is empty',
|
|
533
|
+
isNotEmpty: 'Is not empty',
|
|
514
534
|
},
|
|
515
535
|
validation: {
|
|
516
536
|
duplicate_identifier: 'The identifier "{{identifier}}" is used more than once.',
|
|
517
537
|
duplicate_identifier_title: 'Validation error',
|
|
538
|
+
},
|
|
539
|
+
repeater: {
|
|
540
|
+
no_subfields: 'No sub-fields yet. Add one below.',
|
|
541
|
+
add_subfield: 'Add sub-field',
|
|
518
542
|
}
|
|
519
543
|
},
|
|
520
544
|
validation: {
|
|
@@ -691,6 +715,8 @@ const DICTIONARY_ES = {
|
|
|
691
715
|
block_subtitle: 'Subtítulo',
|
|
692
716
|
add_block: 'Agregar bloque',
|
|
693
717
|
delete_block: 'Eliminar bloque',
|
|
718
|
+
delete_block_dependency_blocked: 'Este bloque no se puede eliminar porque contiene campos de los que dependen otros campos',
|
|
719
|
+
delete_field_dependency_blocked: 'Este campo no se puede eliminar porque otro campo depende de su valor',
|
|
694
720
|
preview_form: 'Vista previa',
|
|
695
721
|
submit_form: 'Guardar',
|
|
696
722
|
select_field_to_edit: 'Selecciona un campo para editar sus propiedades',
|
|
@@ -773,22 +799,29 @@ const DICTIONARY_ES = {
|
|
|
773
799
|
iaValidation: 'Validación IA',
|
|
774
800
|
iaValidationPrompt: 'Prompt de validación IA',
|
|
775
801
|
searchApi_tip: 'URL para obtener opciones de búsqueda',
|
|
776
|
-
optionsSourceKey: '
|
|
777
|
-
optionsSourceKey_tip: '
|
|
778
|
-
optionsSourceIdField: '
|
|
779
|
-
optionsSourceIdField_tip: '
|
|
780
|
-
optionsSourceTextField: '
|
|
781
|
-
optionsSourceTextField_tip: '
|
|
802
|
+
optionsSourceKey: 'Origen de opciones',
|
|
803
|
+
optionsSourceKey_tip: 'Opciones manuales o API externa',
|
|
804
|
+
optionsSourceIdField: 'Nombre de campo ID',
|
|
805
|
+
optionsSourceIdField_tip: 'Propiedad del objeto para usar como ID',
|
|
806
|
+
optionsSourceTextField: 'Nombre de campo de texto',
|
|
807
|
+
optionsSourceTextField_tip: 'Propiedad del objeto para mostrar',
|
|
782
808
|
optionsSourceTextTemplate: 'Plantilla de texto',
|
|
783
809
|
optionsSourceTextTemplate_tip: 'Ejemplo: {{name}} ({{id}})',
|
|
784
810
|
optionsSourceDependsOn: 'Depende de',
|
|
785
|
-
optionsSourceDependsOn_tip: '
|
|
811
|
+
optionsSourceDependsOn_tip: 'Campo para filtrar opciones según valor',
|
|
786
812
|
optionsSourceParamName: 'Nombre del parámetro',
|
|
787
813
|
optionsSourceParamName_tip: 'Nombre con el que se envía el valor dependiente',
|
|
788
814
|
selectNullable_tip: 'Permite seleccionar una opción vacía',
|
|
789
815
|
selectSearchEnabled_tip: 'Habilita búsqueda entre opciones',
|
|
790
816
|
selectNullable: 'Permitir opción vacía',
|
|
791
817
|
selectSearchEnabled: 'Habilitar búsqueda',
|
|
818
|
+
repeaterMinItems: 'Mínimo de ítems',
|
|
819
|
+
repeaterMinItems_tip: 'Cantidad mínima de ítems requerida',
|
|
820
|
+
repeaterMaxItems: 'Máximo de ítems',
|
|
821
|
+
repeaterMaxItems_tip: 'Cantidad máxima de ítems permitida',
|
|
822
|
+
repeaterAddLabel: 'Etiqueta del botón agregar',
|
|
823
|
+
repeaterRemoveLabel: 'Etiqueta del botón eliminar',
|
|
824
|
+
repeaterItemTitle: 'Título de ítem',
|
|
792
825
|
},
|
|
793
826
|
options_editor: {
|
|
794
827
|
title: 'Opciones',
|
|
@@ -814,10 +847,25 @@ const DICTIONARY_ES = {
|
|
|
814
847
|
delete: 'Eliminar',
|
|
815
848
|
show_advanced: 'Mostrar avanzado',
|
|
816
849
|
hide_advanced: 'Ocultar avanzado',
|
|
850
|
+
subfields: 'Sub-campos',
|
|
851
|
+
},
|
|
852
|
+
visibility_operators: {
|
|
853
|
+
equals: 'Es igual a',
|
|
854
|
+
notEquals: 'No es igual a',
|
|
855
|
+
greaterThan: 'Es mayor que',
|
|
856
|
+
lessThan: 'Es menor que',
|
|
857
|
+
includes: 'Incluye',
|
|
858
|
+
notIncludes: 'No incluye',
|
|
859
|
+
isEmpty: 'Está vacío',
|
|
860
|
+
isNotEmpty: 'No está vacío',
|
|
817
861
|
},
|
|
818
862
|
validation: {
|
|
819
863
|
duplicate_identifier: 'El identificador "{{identifier}}" se está usando más de una vez.',
|
|
820
864
|
duplicate_identifier_title: 'Error de validación',
|
|
865
|
+
},
|
|
866
|
+
repeater: {
|
|
867
|
+
no_subfields: 'Sin sub-campos. Añade uno abajo.',
|
|
868
|
+
add_subfield: 'Agregar sub-campo',
|
|
821
869
|
}
|
|
822
870
|
},
|
|
823
871
|
validation: {
|
|
@@ -3848,6 +3896,111 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
3848
3896
|
type: Injectable
|
|
3849
3897
|
}], ctorParameters: () => [] });
|
|
3850
3898
|
|
|
3899
|
+
class UicRepeaterComponent {
|
|
3900
|
+
fb = inject(FormBuilder);
|
|
3901
|
+
formArray;
|
|
3902
|
+
field;
|
|
3903
|
+
cols = 2;
|
|
3904
|
+
error;
|
|
3905
|
+
ngOnInit() {
|
|
3906
|
+
if (this.formArray.length === 0) {
|
|
3907
|
+
const min = this.field.repeaterMinItems ?? 0;
|
|
3908
|
+
for (let i = 0; i < min; i++) {
|
|
3909
|
+
this.addGroup();
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
}
|
|
3913
|
+
getGroup(index) {
|
|
3914
|
+
return this.formArray.at(index);
|
|
3915
|
+
}
|
|
3916
|
+
addGroup() {
|
|
3917
|
+
if (this.field.repeaterMaxItems && this.formArray.length >= this.field.repeaterMaxItems) {
|
|
3918
|
+
return;
|
|
3919
|
+
}
|
|
3920
|
+
const group = this.fb.group({});
|
|
3921
|
+
(this.field.repeaterFields || []).forEach(subField => {
|
|
3922
|
+
const validators = this.mapValidatorsFromField(subField);
|
|
3923
|
+
const controlState = {
|
|
3924
|
+
value: this.getBlankValue(subField),
|
|
3925
|
+
disabled: !!subField.disabled
|
|
3926
|
+
};
|
|
3927
|
+
group.addControl(subField.name, this.fb.control(controlState, validators));
|
|
3928
|
+
});
|
|
3929
|
+
this.formArray.push(group);
|
|
3930
|
+
}
|
|
3931
|
+
removeGroup(index) {
|
|
3932
|
+
if (this.field.repeaterMinItems && this.formArray.length <= this.field.repeaterMinItems) {
|
|
3933
|
+
return;
|
|
3934
|
+
}
|
|
3935
|
+
this.formArray.removeAt(index);
|
|
3936
|
+
}
|
|
3937
|
+
get canAdd() {
|
|
3938
|
+
if (!this.field.repeaterMaxItems)
|
|
3939
|
+
return true;
|
|
3940
|
+
return this.formArray.length < this.field.repeaterMaxItems;
|
|
3941
|
+
}
|
|
3942
|
+
get canRemove() {
|
|
3943
|
+
if (this.field.repeaterMinItems !== undefined && this.field.repeaterMinItems !== null) {
|
|
3944
|
+
return this.formArray.length > this.field.repeaterMinItems;
|
|
3945
|
+
}
|
|
3946
|
+
return true;
|
|
3947
|
+
}
|
|
3948
|
+
mapValidatorsFromField(field) {
|
|
3949
|
+
const validators = [];
|
|
3950
|
+
if (field.required)
|
|
3951
|
+
validators.push(Validators.required);
|
|
3952
|
+
if (typeof field.min === 'number')
|
|
3953
|
+
validators.push(Validators.min(field.min));
|
|
3954
|
+
if (typeof field.max === 'number')
|
|
3955
|
+
validators.push(Validators.max(field.max));
|
|
3956
|
+
if (typeof field.maxLength === 'number')
|
|
3957
|
+
validators.push(Validators.maxLength(field.maxLength));
|
|
3958
|
+
if (typeof field.minLength === 'number')
|
|
3959
|
+
validators.push(Validators.minLength(field.minLength));
|
|
3960
|
+
if (field.pattern instanceof RegExp)
|
|
3961
|
+
validators.push(Validators.pattern(field.pattern));
|
|
3962
|
+
return validators;
|
|
3963
|
+
}
|
|
3964
|
+
getBlankValue(field) {
|
|
3965
|
+
switch (field.type) {
|
|
3966
|
+
case 'text':
|
|
3967
|
+
case 'textarea':
|
|
3968
|
+
case 'phone':
|
|
3969
|
+
return '';
|
|
3970
|
+
case 'checkbox':
|
|
3971
|
+
case 'switch':
|
|
3972
|
+
return false;
|
|
3973
|
+
case 'multyselect':
|
|
3974
|
+
return [];
|
|
3975
|
+
case 'slider':
|
|
3976
|
+
return field.min ?? 0;
|
|
3977
|
+
default:
|
|
3978
|
+
return null;
|
|
3979
|
+
}
|
|
3980
|
+
}
|
|
3981
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UicRepeaterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3982
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: UicRepeaterComponent, isStandalone: true, selector: "ui-repeater", inputs: { formArray: "formArray", field: "field", cols: "cols", error: "error" }, ngImport: i0, template: "<div class=\"repeater-label\"> {{field.label}} </div>\r\n<div class=\"uic-repeater\" [class.disabled]=\"formArray.disabled\">\r\n @for (group of formArray.controls; track $index) {\r\n <div class=\"uic-repeater-item\">\r\n <div class=\"uic-repeater-item-header\">\r\n <h4 class=\"uic-repeater-item-title\">\r\n {{ field.repeaterItemTitle || field.label || 'Item' }} {{ $index + 1 }}\r\n </h4>\r\n @if (canRemove && !formArray.disabled) {\r\n <ui-button \r\n [icon]=\"'ri-delete-bin-line'\" \r\n [type]=\"'bordered'\" \r\n [color]=\"'red'\" \r\n size=\"s\" \r\n (click)=\"removeGroup($index)\"\r\n [text]=\"field.repeaterRemoveLabel || 'Eliminar'\">\r\n </ui-button>\r\n }\r\n </div>\r\n <div class=\"uic-repeater-item-body\">\r\n <ui-dynamic-form \r\n [form]=\"getGroup($index)\" \r\n [fields]=\"field.repeaterFields || []\" \r\n [disabled]=\"formArray.disabled\"\r\n [cols]=\"cols\"\r\n [isSubForm]=\"true\">\r\n </ui-dynamic-form>\r\n </div>\r\n </div>\r\n }\r\n \r\n @if (canAdd && !formArray.disabled) {\r\n <div class=\"uic-repeater-add-action\">\r\n <ui-button \r\n [icon]=\"'ri-add-line'\" \r\n [type]=\"'bordered'\" \r\n [color]=\"'primary'\" \r\n (click)=\"addGroup()\"\r\n [text]=\"field.repeaterAddLabel || 'A\u00F1adir'\">\r\n </ui-button>\r\n </div>\r\n }\r\n @if (error) {\r\n <p class=\"uic-repeater-error\">{{ error }}</p>\r\n }\r\n</div>\r\n", styles: [".uic-repeater{display:flex;flex-direction:column;gap:16px;width:100%}.uic-repeater.disabled{opacity:.7;pointer-events:none}.uic-repeater .uic-repeater-item{border:1px solid var(--primary-400, #e0e0e0);border-radius:8px;padding:16px;background-color:var(--uic-bg-color, #fff)}.uic-repeater .uic-repeater-item .uic-repeater-item-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;padding-bottom:12px;border-bottom:1px dashed var(--uic-border-color, #e0e0e0)}.uic-repeater .uic-repeater-item .uic-repeater-item-header .uic-repeater-item-title{margin:0;font-size:14px;font-weight:600;color:var(--uic-text-color, #333)}.uic-repeater .uic-repeater-item .uic-repeater-item-body{width:100%}.uic-repeater .uic-repeater-add-action{margin-top:8px}.uic-repeater .uic-repeater-error{margin:4px 0 0;font-size:12px;color:var(--uic-red, #e53935)}.repeater-label{font-size:max(var(--form-ref) + 4px,14px);line-height:1.125rem;min-height:1.125rem;font-weight:400;color:var(--grey-950);margin-bottom:var(--input-label-space)}\n"], dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CommonModule) }, { kind: "ngmodule", type: i0.forwardRef(() => ReactiveFormsModule) }, { kind: "component", type: i0.forwardRef(() => UicButtonComponent), selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "component", type: i0.forwardRef(() => UicDynamicFormComponent), selector: "ui-dynamic-form", inputs: ["fields", "isSubForm", "form", "disabled", "voiceToTextSilenceMs", "cols", "fileUidResolverFn", "selectOptionsResolver"] }] });
|
|
3983
|
+
}
|
|
3984
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UicRepeaterComponent, decorators: [{
|
|
3985
|
+
type: Component,
|
|
3986
|
+
args: [{ selector: 'ui-repeater', standalone: true, imports: [
|
|
3987
|
+
CommonModule,
|
|
3988
|
+
ReactiveFormsModule,
|
|
3989
|
+
UicButtonComponent,
|
|
3990
|
+
forwardRef(() => UicDynamicFormComponent)
|
|
3991
|
+
], template: "<div class=\"repeater-label\"> {{field.label}} </div>\r\n<div class=\"uic-repeater\" [class.disabled]=\"formArray.disabled\">\r\n @for (group of formArray.controls; track $index) {\r\n <div class=\"uic-repeater-item\">\r\n <div class=\"uic-repeater-item-header\">\r\n <h4 class=\"uic-repeater-item-title\">\r\n {{ field.repeaterItemTitle || field.label || 'Item' }} {{ $index + 1 }}\r\n </h4>\r\n @if (canRemove && !formArray.disabled) {\r\n <ui-button \r\n [icon]=\"'ri-delete-bin-line'\" \r\n [type]=\"'bordered'\" \r\n [color]=\"'red'\" \r\n size=\"s\" \r\n (click)=\"removeGroup($index)\"\r\n [text]=\"field.repeaterRemoveLabel || 'Eliminar'\">\r\n </ui-button>\r\n }\r\n </div>\r\n <div class=\"uic-repeater-item-body\">\r\n <ui-dynamic-form \r\n [form]=\"getGroup($index)\" \r\n [fields]=\"field.repeaterFields || []\" \r\n [disabled]=\"formArray.disabled\"\r\n [cols]=\"cols\"\r\n [isSubForm]=\"true\">\r\n </ui-dynamic-form>\r\n </div>\r\n </div>\r\n }\r\n \r\n @if (canAdd && !formArray.disabled) {\r\n <div class=\"uic-repeater-add-action\">\r\n <ui-button \r\n [icon]=\"'ri-add-line'\" \r\n [type]=\"'bordered'\" \r\n [color]=\"'primary'\" \r\n (click)=\"addGroup()\"\r\n [text]=\"field.repeaterAddLabel || 'A\u00F1adir'\">\r\n </ui-button>\r\n </div>\r\n }\r\n @if (error) {\r\n <p class=\"uic-repeater-error\">{{ error }}</p>\r\n }\r\n</div>\r\n", styles: [".uic-repeater{display:flex;flex-direction:column;gap:16px;width:100%}.uic-repeater.disabled{opacity:.7;pointer-events:none}.uic-repeater .uic-repeater-item{border:1px solid var(--primary-400, #e0e0e0);border-radius:8px;padding:16px;background-color:var(--uic-bg-color, #fff)}.uic-repeater .uic-repeater-item .uic-repeater-item-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;padding-bottom:12px;border-bottom:1px dashed var(--uic-border-color, #e0e0e0)}.uic-repeater .uic-repeater-item .uic-repeater-item-header .uic-repeater-item-title{margin:0;font-size:14px;font-weight:600;color:var(--uic-text-color, #333)}.uic-repeater .uic-repeater-item .uic-repeater-item-body{width:100%}.uic-repeater .uic-repeater-add-action{margin-top:8px}.uic-repeater .uic-repeater-error{margin:4px 0 0;font-size:12px;color:var(--uic-red, #e53935)}.repeater-label{font-size:max(var(--form-ref) + 4px,14px);line-height:1.125rem;min-height:1.125rem;font-weight:400;color:var(--grey-950);margin-bottom:var(--input-label-space)}\n"] }]
|
|
3992
|
+
}], propDecorators: { formArray: [{
|
|
3993
|
+
type: Input,
|
|
3994
|
+
args: [{ required: true }]
|
|
3995
|
+
}], field: [{
|
|
3996
|
+
type: Input,
|
|
3997
|
+
args: [{ required: true }]
|
|
3998
|
+
}], cols: [{
|
|
3999
|
+
type: Input
|
|
4000
|
+
}], error: [{
|
|
4001
|
+
type: Input
|
|
4002
|
+
}] } });
|
|
4003
|
+
|
|
3851
4004
|
class UicDynamicFormComponent {
|
|
3852
4005
|
ngZone;
|
|
3853
4006
|
fieldsSignal = signal([]);
|
|
@@ -3869,9 +4022,9 @@ class UicDynamicFormComponent {
|
|
|
3869
4022
|
get fields() {
|
|
3870
4023
|
return this.fieldsSignal();
|
|
3871
4024
|
}
|
|
4025
|
+
isSubForm = false;
|
|
3872
4026
|
set form(value) {
|
|
3873
4027
|
this.formSignal.set(value);
|
|
3874
|
-
this.formState.setForm(value);
|
|
3875
4028
|
}
|
|
3876
4029
|
get form() {
|
|
3877
4030
|
return this.formSignal();
|
|
@@ -3906,6 +4059,12 @@ class UicDynamicFormComponent {
|
|
|
3906
4059
|
return field.visibilityRules.every(rule => this.matchesVisibilityRule(rule));
|
|
3907
4060
|
});
|
|
3908
4061
|
});
|
|
4062
|
+
formSyncEffect = effect(() => {
|
|
4063
|
+
const form = this.formSignal();
|
|
4064
|
+
if (form && !this.isSubForm) {
|
|
4065
|
+
this.formState.setForm(form);
|
|
4066
|
+
}
|
|
4067
|
+
});
|
|
3909
4068
|
fieldStateSyncEffect = effect(() => {
|
|
3910
4069
|
this.visibleFieldStates();
|
|
3911
4070
|
this.syncFieldEnabledState();
|
|
@@ -3965,7 +4124,14 @@ class UicDynamicFormComponent {
|
|
|
3965
4124
|
const isVisible = visibleNames.has(field.name);
|
|
3966
4125
|
const wasVisible = this.fieldVisibilityState.get(field.name);
|
|
3967
4126
|
if (!isVisible && wasVisible) {
|
|
3968
|
-
|
|
4127
|
+
if (field.type === 'repeater') {
|
|
4128
|
+
const arr = control;
|
|
4129
|
+
while (arr.length > 0)
|
|
4130
|
+
arr.removeAt(0, { emitEvent: false });
|
|
4131
|
+
}
|
|
4132
|
+
else {
|
|
4133
|
+
control.setValue(this.getClearValue(field.type), { emitEvent: false });
|
|
4134
|
+
}
|
|
3969
4135
|
control.markAsPristine();
|
|
3970
4136
|
control.markAsUntouched();
|
|
3971
4137
|
}
|
|
@@ -3988,14 +4154,20 @@ class UicDynamicFormComponent {
|
|
|
3988
4154
|
if (fieldType === 'checkbox' || fieldType === 'switch') {
|
|
3989
4155
|
return false;
|
|
3990
4156
|
}
|
|
3991
|
-
if (fieldType === 'multyselect') {
|
|
4157
|
+
if (fieldType === 'multyselect' || fieldType === 'repeater') {
|
|
3992
4158
|
return [];
|
|
3993
4159
|
}
|
|
3994
4160
|
return null;
|
|
3995
4161
|
}
|
|
3996
4162
|
matchesVisibilityRule(rule) {
|
|
3997
4163
|
const currentValue = this.getValueByFieldName(rule.fieldName);
|
|
4164
|
+
const dependencyField = this.findFieldByName(rule.fieldName);
|
|
4165
|
+
const dependencyType = dependencyField?.type;
|
|
3998
4166
|
switch (rule.operator) {
|
|
4167
|
+
case 'isEmpty':
|
|
4168
|
+
return this.isEmptyValue(currentValue);
|
|
4169
|
+
case 'isNotEmpty':
|
|
4170
|
+
return !this.isEmptyValue(currentValue);
|
|
3999
4171
|
case 'equals': {
|
|
4000
4172
|
if (typeof currentValue === 'boolean') {
|
|
4001
4173
|
const normalizedRuleValue = this.parseBooleanLike(rule.value);
|
|
@@ -4003,7 +4175,7 @@ class UicDynamicFormComponent {
|
|
|
4003
4175
|
return currentValue === normalizedRuleValue;
|
|
4004
4176
|
}
|
|
4005
4177
|
}
|
|
4006
|
-
return currentValue
|
|
4178
|
+
return currentValue == rule.value;
|
|
4007
4179
|
}
|
|
4008
4180
|
case 'notEquals': {
|
|
4009
4181
|
if (typeof currentValue === 'boolean') {
|
|
@@ -4012,27 +4184,33 @@ class UicDynamicFormComponent {
|
|
|
4012
4184
|
return currentValue !== normalizedRuleValue;
|
|
4013
4185
|
}
|
|
4014
4186
|
}
|
|
4015
|
-
return currentValue
|
|
4187
|
+
return currentValue != rule.value;
|
|
4016
4188
|
}
|
|
4017
4189
|
case 'greaterThan':
|
|
4018
|
-
return
|
|
4190
|
+
return this.compareVisibilityValues(currentValue, rule.value, dependencyType) > 0;
|
|
4019
4191
|
case 'lessThan':
|
|
4020
|
-
return
|
|
4192
|
+
return this.compareVisibilityValues(currentValue, rule.value, dependencyType) < 0;
|
|
4021
4193
|
case 'includes':
|
|
4194
|
+
if (dependencyType === 'phone') {
|
|
4195
|
+
return this.getPhoneComparableValue(currentValue).includes(String(rule.value ?? ''));
|
|
4196
|
+
}
|
|
4022
4197
|
if (currentValue == null)
|
|
4023
4198
|
return false;
|
|
4024
4199
|
if (Array.isArray(currentValue)) {
|
|
4025
|
-
return
|
|
4200
|
+
return this.arrayIncludesVisibilityValue(currentValue, rule.value);
|
|
4026
4201
|
}
|
|
4027
4202
|
if (typeof currentValue === 'string') {
|
|
4028
4203
|
return currentValue.includes(rule.value);
|
|
4029
4204
|
}
|
|
4030
4205
|
return false;
|
|
4031
4206
|
case 'notIncludes':
|
|
4207
|
+
if (dependencyType === 'phone') {
|
|
4208
|
+
return !this.getPhoneComparableValue(currentValue).includes(String(rule.value ?? ''));
|
|
4209
|
+
}
|
|
4032
4210
|
if (currentValue == null)
|
|
4033
4211
|
return true;
|
|
4034
4212
|
if (Array.isArray(currentValue)) {
|
|
4035
|
-
return !
|
|
4213
|
+
return !this.arrayIncludesVisibilityValue(currentValue, rule.value);
|
|
4036
4214
|
}
|
|
4037
4215
|
if (typeof currentValue === 'string') {
|
|
4038
4216
|
return !currentValue.includes(rule.value);
|
|
@@ -4042,6 +4220,61 @@ class UicDynamicFormComponent {
|
|
|
4042
4220
|
return true;
|
|
4043
4221
|
}
|
|
4044
4222
|
}
|
|
4223
|
+
findFieldByName(fieldName) {
|
|
4224
|
+
return this.fieldsSignal().find(field => field.name === fieldName);
|
|
4225
|
+
}
|
|
4226
|
+
isEmptyValue(value) {
|
|
4227
|
+
if (value === null || value === undefined)
|
|
4228
|
+
return true;
|
|
4229
|
+
if (typeof value === 'string')
|
|
4230
|
+
return value.trim().length === 0;
|
|
4231
|
+
if (Array.isArray(value))
|
|
4232
|
+
return value.length === 0;
|
|
4233
|
+
if (typeof value === 'object')
|
|
4234
|
+
return Object.keys(value).length === 0;
|
|
4235
|
+
return false;
|
|
4236
|
+
}
|
|
4237
|
+
compareVisibilityValues(currentValue, ruleValue, fieldType) {
|
|
4238
|
+
const currentComparable = this.toComparableVisibilityValue(currentValue, fieldType);
|
|
4239
|
+
const ruleComparable = this.toComparableVisibilityValue(ruleValue, fieldType);
|
|
4240
|
+
if (currentComparable === null || ruleComparable === null) {
|
|
4241
|
+
return Number.NaN;
|
|
4242
|
+
}
|
|
4243
|
+
return currentComparable - ruleComparable;
|
|
4244
|
+
}
|
|
4245
|
+
toComparableVisibilityValue(value, fieldType) {
|
|
4246
|
+
if (value === null || value === undefined || value === '')
|
|
4247
|
+
return null;
|
|
4248
|
+
if (fieldType === 'date') {
|
|
4249
|
+
const timestamp = Date.parse(String(value));
|
|
4250
|
+
return Number.isNaN(timestamp) ? null : timestamp;
|
|
4251
|
+
}
|
|
4252
|
+
if (fieldType === 'time') {
|
|
4253
|
+
const match = String(value).match(/^(\d{1,2}):(\d{2})$/);
|
|
4254
|
+
if (!match)
|
|
4255
|
+
return null;
|
|
4256
|
+
const hours = Number(match[1]);
|
|
4257
|
+
const minutes = Number(match[2]);
|
|
4258
|
+
if (!Number.isFinite(hours) || !Number.isFinite(minutes))
|
|
4259
|
+
return null;
|
|
4260
|
+
return hours * 60 + minutes;
|
|
4261
|
+
}
|
|
4262
|
+
const numericValue = Number(value);
|
|
4263
|
+
return Number.isNaN(numericValue) ? null : numericValue;
|
|
4264
|
+
}
|
|
4265
|
+
getPhoneComparableValue(value) {
|
|
4266
|
+
if (!value)
|
|
4267
|
+
return '';
|
|
4268
|
+
if (typeof value === 'string')
|
|
4269
|
+
return value;
|
|
4270
|
+
if (typeof value === 'object') {
|
|
4271
|
+
return String(value.internationalNumber ?? '');
|
|
4272
|
+
}
|
|
4273
|
+
return '';
|
|
4274
|
+
}
|
|
4275
|
+
arrayIncludesVisibilityValue(values, ruleValue) {
|
|
4276
|
+
return values.some(value => value == ruleValue);
|
|
4277
|
+
}
|
|
4045
4278
|
parseBooleanLike(value) {
|
|
4046
4279
|
if (typeof value === 'boolean')
|
|
4047
4280
|
return value;
|
|
@@ -4076,6 +4309,9 @@ class UicDynamicFormComponent {
|
|
|
4076
4309
|
});
|
|
4077
4310
|
});
|
|
4078
4311
|
}
|
|
4312
|
+
asFormArray(control) {
|
|
4313
|
+
return control;
|
|
4314
|
+
}
|
|
4079
4315
|
isListening(fieldName) {
|
|
4080
4316
|
return this.listeningField === fieldName;
|
|
4081
4317
|
}
|
|
@@ -4097,7 +4333,8 @@ class UicDynamicFormComponent {
|
|
|
4097
4333
|
field: field.label ?? field.name,
|
|
4098
4334
|
requiredLength: err.requiredLength,
|
|
4099
4335
|
}),
|
|
4100
|
-
pattern: (_err, field) => this.i18n.translate('validation.pattern', { field: field.label ?? field.name })
|
|
4336
|
+
pattern: (_err, field) => this.i18n.translate('validation.pattern', { field: field.label ?? field.name }),
|
|
4337
|
+
minLengthArray: (_err, field) => this.i18n.translate('validation.required', { field: field.label ?? field.name })
|
|
4101
4338
|
};
|
|
4102
4339
|
getInputColor(field, value) {
|
|
4103
4340
|
const scale = field.internalColorScale;
|
|
@@ -4358,7 +4595,7 @@ class UicDynamicFormComponent {
|
|
|
4358
4595
|
recognition.start();
|
|
4359
4596
|
}
|
|
4360
4597
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UicDynamicFormComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
|
|
4361
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: UicDynamicFormComponent, isStandalone: true, selector: "ui-dynamic-form", inputs: { fields: "fields", form: "form", disabled: "disabled", voiceToTextSilenceMs: "voiceToTextSilenceMs", cols: "cols", fileUidResolverFn: "fileUidResolverFn", selectOptionsResolver: "selectOptionsResolver" }, ngImport: i0, template: "<div class=\"form\" [ngStyle]=\"{'--cols': cols, '--min': '180px'}\" [formGroup]=\"form\">\r\n @for (state of visibleFieldStates(); track state.field.name) {\r\n @let field = state.field;\r\n @let control = state.control;\r\n @let currentValue = state.value ?? '';\r\n @let error = getControlErrorMessages(control, field)[0];\r\n\r\n <div [style.grid-column]=\"getGridColumn(field)\">\n @if (['text', 'number'].includes(field.type)) {\r\n @let inputColor = getInputColor(field, currentValue);\r\n <ui-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [disabled]=\"!!control?.disabled\"\r\n [internalIconColor]=\"inputColor\"\r\n [internalIcon]=\"field.internalIcon || (currentValue !== '' ? getIconByColor(field, inputColor) : '')\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\">\r\n <input #inp\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [type]=\"field.type\"\r\n [step]=\"field.step\"\r\n [min]=\"field.min\"\r\n [max]=\"field.max\"\r\n [minLength]=\"field.minLength||null\"\r\n [maxlength]=\"field.maxLength||null\"\r\n [placeholder]=\"field.placeholder??field.label\"/>\r\n @if (field.maxLength && field.showCounter) {\r\n <span counter>{{inp.value.length}} /{{field.maxLength}}</span>\r\n }\r\n </ui-input>\r\n }\r\n @if (field.type === 'textarea') {\r\n <ui-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [disabled]=\"!!control?.disabled\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\">\r\n <textarea #ta\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [minLength]=\"field.minLength||null\"\r\n [maxlength]=\"field.maxLength||null\"\r\n [textareaAutoresize]=\"field.textareaResize\"\r\n [textareaAutoresizeMinRows]=\"field.resizeMinRows??1\"\r\n [textareaAutoresizeMaxRows]=\"field.resizeMaxRows??5\"\r\n [rows]=\"field.resizeMinRows??3\"\r\n [placeholder]=\"field.placeholder??field.label\"\r\n ></textarea>\r\n @if (field.voiceToTextEnabled && !control?.disabled) {\r\n @let listening = isListening(field.name);\r\n <div class=\"speak-icon\" (click)=\"ta.focus()\">\r\n <ui-button\r\n [disabled]=\"listening\"\r\n style=\"margin-bottom: 2px;\"\r\n (click)=\"voiceToText(ta, field.name)\"\r\n [icon]=\"listening?'ri-mic-fill':'ri-mic-line'\"\r\n [type]=\"listening?'filled':'bordered'\"\r\n size=\"s\"\r\n [iconOnly]=\"true\"\r\n ></ui-button>\r\n @if (listening) {\r\n <i class=\"ri-voiceprint-line\"></i>\r\n }\r\n </div>\r\n }\r\n @if (field.showCounter) {\r\n <span counter>\r\n {{ta.value.length}}\r\n @if (field.maxLength) {\r\n /{{field.maxLength}}\r\n }\r\n </span>\r\n }\r\n </ui-input>\r\n }\r\n @if (field.type === 'phone') {\r\n <ui-phone-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [placeholder]=\"field.placeholder||field.label||''\"\r\n >\r\n </ui-phone-input>\r\n }\r\n @else if (field.type === 'date') {\r\n <ui-date-picker\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [tip]=\"field.tip??''\"\r\n [justMonth]=\"!!field.monthMode\"\r\n [min]=\"field.minDate??''\"\r\n [max]=\"field.maxDate??''\"\r\n [monthDay]=\"field.monthDay||'first'\"\r\n [formControlName]=\"field.name\"\r\n ></ui-date-picker>\r\n }\r\n @else if (field.type === 'time') {\r\n <ui-time-picker\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [tip]=\"field.tip??''\"\r\n [interval]=\"field.timeInterval??5\"\r\n [formControlName]=\"field.name\"\r\n ></ui-time-picker>\r\n }\r\n @else if (field.type === 'select') {\r\n <ui-select\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [loading]=\"field.loading??false\"\r\n [nullable]=\"field.selectNullable??false\"\r\n [searcherEnabled]=\"field.selectSearchEnabled??false\"\r\n [tip]=\"field.tip??''\"\r\n [formControlName]=\"field.name\"\r\n [options]=\"field.options || []\"\r\n ></ui-select>\r\n }\r\n @else if (field.type === 'multyselect') {\r\n <ui-multy-select\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [tip]=\"field.tip??''\"\r\n [formControlName]=\"field.name\"\r\n [options]=\"field.options || []\"\r\n ></ui-multy-select>\r\n }\r\n @else if (field.type === 'searcher') {\r\n <ui-searcher\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\"\r\n [searchFn]=\"getSearcherFn(field)\"\r\n [itemDisplayFn]=\"getSearcherDisplayFn(field)\"\r\n [itemIsEnabledFn]=\"getSearcherIsEnabledFn(field)\"\r\n [placeholder]=\"field.placeholder??'common.search_ellipsis'\"\r\n [error]=\"error\"\r\n ></ui-searcher>\r\n }\r\n @else if (field.type === 'file') {\r\n <ui-file-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [multy]=\"field.multyEnabled??false\"\n [tip]=\"field.tip??''\"\n [fileTypes]=\"field.fileTypes??null\"\n [fileUidResolverFn]=\"fileUidResolverFn\"\n [formControlName]=\"field.name\"\n ></ui-file-input>\n }\n @else if (['checkbox', 'switch'].includes(field.type)) {\r\n <ui-checkbox\r\n [label]=\"(field.label??'') + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [placeholder]=\"field.placeholder??''\"\r\n [tip]=\"field.tip??''\"\r\n [type]=\"field.type === 'checkbox' ? 'checkbox' : 'switch'\"\r\n ></ui-checkbox>\r\n }\r\n @else if (field.type === 'radio') {\r\n <ui-radio\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [tip]=\"field.tip??''\"\r\n [loading]=\"field.loading??false\"\r\n [error]=\"error\"\r\n [options]=\"field.options || []\"\r\n ></ui-radio>\r\n }\r\n @else if (field.type === 'slider') {\r\n <ui-slider\r\n [min]=\"field.min??0\"\r\n [max]=\"field.max??100\"\r\n [step]=\"field.sliderInterval??1\"\r\n [markerCount]=\"field.sliderMarks??5\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [tip]=\"field.tip??''\"\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n ></ui-slider>\r\n }\r\n @else if (field.type === 'pool') {\r\n <ui-pool-options\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [multy]=\"field.multyEnabled??false\"\r\n [tip]=\"field.tip??''\"\r\n [listViewTitle]=\"field.poolTitle??'common.selected'\"\r\n [enabledListView]=\"field.poolEnabledListView||false\"\r\n [formControlName]=\"field.name\"\r\n [options]=\"field.options || []\"\r\n ></ui-pool-options>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".form{width:100%;display:grid;align-items:stretch;gap:1rem;padding-bottom:.75rem}@media (max-width: 479px){.form{grid-template-columns:1fr}}@media (min-width: 768px){.form{grid-template-columns:repeat(var(--cols),minmax(0,1fr))}}@media (min-width: 480px) and (max-width: 767px){.form{grid-template-columns:repeat(min(var(--cols),2),minmax(0,1fr))}}.form>*{min-width:0}h2{margin-top:1.5rem}.speak-icon{display:flex;width:100%;align-items:center;gap:10px}.speak-icon i{font-size:20px;color:var(--primary-500)}textarea{resize:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: UicDatePickerComponent, selector: "ui-date-picker", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "disabled", "label", "error", "tip", "max", "min", "justMonth", "monthDay"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: UicSliderComponent, selector: "ui-slider", inputs: ["icon", "iconColor", "label", "error", "tip", "min", "max", "step", "markerCount", "disabled", "loading"] }, { kind: "component", type: UicButtonComponent, selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "component", type: UicPoolOptionsComponent, selector: "ui-pool-options", inputs: ["icon", "iconColor", "size", "label", "error", "tip", "disabled", "loading", "multy", "enabledListView", "listViewTitle", "options"] }, { kind: "component", type: UicTimePickerComponent, selector: "ui-time-picker", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "disabled", "label", "error", "tip", "interval"] }, { kind: "component", type: UicRadioComponent, selector: "ui-radio", inputs: ["icon", "iconColor", "label", "error", "tip", "disabled", "loading", "options", "emptyText", "direction"] }, { kind: "component", type: UicSearcherComponent, selector: "ui-searcher", inputs: ["icon", "iconColor", "internalIcon", "size", "label", "error", "tip", "showSubtitle", "disabled", "loading", "minimumSearchLength", "showSelected", "placeholder", "searchFn", "itemDisplayFn", "itemIsEnabledFn", "manualSearch", "stateless"], outputs: ["pickedItem"] }, { kind: "component", type: UicMultySelectComponent, selector: "ui-multy-select", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "size", "label", "error", "tip", "showSubtitle", "disabled", "nonSelectedText", "allSelectedText", "loading", "options"] }, { kind: "component", type: UicFileInputComponent, selector: "ui-file-input", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "size", "label", "error", "tip", "disabled", "loading", "multy", "fileTypes", "fileUidResolverFn"] }, { kind: "component", type: UicSelectComponent, selector: "ui-select", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "size", "label", "error", "tip", "showSubtitle", "disabled", "nonSelectedText", "noneText", "emptyText", "searcherEnabled", "loading", "nullable", "options"] }, { kind: "directive", type: UicTextareaAutoresizeDirective, selector: "[textareaAutoresize]", inputs: ["minRows", "maxRows", "textareaAutoresize"] }, { kind: "directive", type: UicTextareaAutoresizeMinRowsDirective, selector: "[textareaAutoresizeMinRows]", inputs: ["textareaAutoresizeMinRows"] }, { kind: "directive", type: UicTextareaAutoresizeMaxRowsDirective, selector: "[textareaAutoresizeMaxRows]", inputs: ["textareaAutoresizeMaxRows"] }, { kind: "component", type: UicInputComponent, selector: "ui-input", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "size", "label", "error", "tip", "disabled", "loading"], outputs: ["clickButton"] }, { kind: "component", type: UicCheckboxComponent, selector: "ui-checkbox", inputs: ["icon", "iconColor", "label", "tip", "type", "placeholder", "loading", "noPadding", "disabled"] }, { kind: "component", type: UicPhoneInputComponent, selector: "ui-phone-input", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "size", "label", "error", "tip", "placeholder", "disabled", "loading", "preferredCountries", "flagPath", "countries"] }, { kind: "ngmodule", type: FormsModule }] });
|
|
4598
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: UicDynamicFormComponent, isStandalone: true, selector: "ui-dynamic-form", inputs: { fields: "fields", isSubForm: "isSubForm", form: "form", disabled: "disabled", voiceToTextSilenceMs: "voiceToTextSilenceMs", cols: "cols", fileUidResolverFn: "fileUidResolverFn", selectOptionsResolver: "selectOptionsResolver" }, ngImport: i0, template: "<div class=\"form\" [ngStyle]=\"{'--cols': cols, '--min': '180px'}\" [formGroup]=\"form\">\r\n @for (state of visibleFieldStates(); track state.field.name) {\r\n @let field = state.field;\r\n @let control = state.control;\r\n @let currentValue = state.value ?? '';\r\n @let error = getControlErrorMessages(control, field)[0];\r\n\r\n <div [style.grid-column]=\"getGridColumn(field)\">\r\n @if (['text', 'number'].includes(field.type)) {\r\n @let inputColor = getInputColor(field, currentValue);\r\n <ui-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [disabled]=\"!!control?.disabled\"\r\n [internalIconColor]=\"inputColor\"\r\n [internalIcon]=\"field.internalIcon || (currentValue !== '' ? getIconByColor(field, inputColor) : '')\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\">\r\n <input #inp\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [type]=\"field.type\"\r\n [step]=\"field.step\"\r\n [min]=\"field.min\"\r\n [max]=\"field.max\"\r\n [minLength]=\"field.minLength||null\"\r\n [maxlength]=\"field.maxLength||null\"\r\n [placeholder]=\"field.placeholder??field.label\"/>\r\n @if (field.maxLength && field.showCounter) {\r\n <span counter>{{inp.value.length}} /{{field.maxLength}}</span>\r\n }\r\n </ui-input>\r\n }\r\n @if (field.type === 'textarea') {\r\n <ui-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [disabled]=\"!!control?.disabled\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\">\r\n <textarea #ta\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [minLength]=\"field.minLength||null\"\r\n [maxlength]=\"field.maxLength||null\"\r\n [textareaAutoresize]=\"field.textareaResize\"\r\n [textareaAutoresizeMinRows]=\"field.resizeMinRows??1\"\r\n [textareaAutoresizeMaxRows]=\"field.resizeMaxRows??5\"\r\n [rows]=\"field.resizeMinRows??3\"\r\n [placeholder]=\"field.placeholder??field.label\"\r\n ></textarea>\r\n @if (field.voiceToTextEnabled && !control?.disabled) {\r\n @let listening = isListening(field.name);\r\n <div class=\"speak-icon\" (click)=\"ta.focus()\">\r\n <ui-button\r\n [disabled]=\"listening\"\r\n style=\"margin-bottom: 2px;\"\r\n (click)=\"voiceToText(ta, field.name)\"\r\n [icon]=\"listening?'ri-mic-fill':'ri-mic-line'\"\r\n [type]=\"listening?'filled':'bordered'\"\r\n size=\"s\"\r\n [iconOnly]=\"true\"\r\n ></ui-button>\r\n @if (listening) {\r\n <i class=\"ri-voiceprint-line\"></i>\r\n }\r\n </div>\r\n }\r\n @if (field.showCounter) {\r\n <span counter>\r\n {{ta.value.length}}\r\n @if (field.maxLength) {\r\n /{{field.maxLength}}\r\n }\r\n </span>\r\n }\r\n </ui-input>\r\n }\r\n @if (field.type === 'phone') {\r\n <ui-phone-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [placeholder]=\"field.placeholder||field.label||''\"\r\n >\r\n </ui-phone-input>\r\n }\r\n @else if (field.type === 'date') {\r\n <ui-date-picker\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [tip]=\"field.tip??''\"\r\n [justMonth]=\"!!field.monthMode\"\r\n [min]=\"field.minDate??''\"\r\n [max]=\"field.maxDate??''\"\r\n [monthDay]=\"field.monthDay||'first'\"\r\n [formControlName]=\"field.name\"\r\n ></ui-date-picker>\r\n }\r\n @else if (field.type === 'time') {\r\n <ui-time-picker\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [tip]=\"field.tip??''\"\r\n [interval]=\"field.timeInterval??5\"\r\n [formControlName]=\"field.name\"\r\n ></ui-time-picker>\r\n }\r\n @else if (field.type === 'select') {\r\n <ui-select\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [loading]=\"field.loading??false\"\r\n [nullable]=\"field.selectNullable??false\"\r\n [searcherEnabled]=\"field.selectSearchEnabled??false\"\r\n [tip]=\"field.tip??''\"\r\n [formControlName]=\"field.name\"\r\n [options]=\"field.options || []\"\r\n ></ui-select>\r\n }\r\n @else if (field.type === 'multyselect') {\r\n <ui-multy-select\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [tip]=\"field.tip??''\"\r\n [formControlName]=\"field.name\"\r\n [options]=\"field.options || []\"\r\n ></ui-multy-select>\r\n }\r\n @else if (field.type === 'searcher') {\r\n <ui-searcher\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\"\r\n [searchFn]=\"getSearcherFn(field)\"\r\n [itemDisplayFn]=\"getSearcherDisplayFn(field)\"\r\n [itemIsEnabledFn]=\"getSearcherIsEnabledFn(field)\"\r\n [placeholder]=\"field.placeholder??'common.search_ellipsis'\"\r\n [error]=\"error\"\r\n ></ui-searcher>\r\n }\r\n @else if (field.type === 'file') {\r\n <ui-file-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [multy]=\"field.multyEnabled??false\"\r\n [tip]=\"field.tip??''\"\r\n [fileTypes]=\"field.fileTypes??null\"\r\n [fileUidResolverFn]=\"fileUidResolverFn\"\r\n [formControlName]=\"field.name\"\r\n ></ui-file-input>\r\n }\r\n @else if (['checkbox', 'switch'].includes(field.type)) {\r\n <ui-checkbox\r\n [label]=\"(field.label??'') + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [placeholder]=\"field.placeholder??''\"\r\n [tip]=\"field.tip??''\"\r\n [type]=\"field.type === 'checkbox' ? 'checkbox' : 'switch'\"\r\n ></ui-checkbox>\r\n }\r\n @else if (field.type === 'radio') {\r\n <ui-radio\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [tip]=\"field.tip??''\"\r\n [loading]=\"field.loading??false\"\r\n [error]=\"error\"\r\n [options]=\"field.options || []\"\r\n ></ui-radio>\r\n }\r\n @else if (field.type === 'slider') {\r\n <ui-slider\r\n [min]=\"field.min??0\"\r\n [max]=\"field.max??100\"\r\n [step]=\"field.sliderInterval??1\"\r\n [markerCount]=\"field.sliderMarks??5\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [tip]=\"field.tip??''\"\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n ></ui-slider>\r\n }\r\n @else if (field.type === 'pool') {\r\n <ui-pool-options\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [multy]=\"field.multyEnabled??false\"\r\n [tip]=\"field.tip??''\"\r\n [listViewTitle]=\"field.poolTitle??'common.selected'\"\r\n [enabledListView]=\"field.poolEnabledListView||false\"\r\n [formControlName]=\"field.name\"\r\n [options]=\"field.options || []\"\r\n ></ui-pool-options>\r\n }\r\n @else if (field.type === 'repeater') {\r\n <ui-repeater\r\n [formArray]=\"asFormArray(control)\"\r\n [field]=\"field\"\r\n [cols]=\"cols\"\r\n [error]=\"error\"\r\n ></ui-repeater>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".form{width:100%;display:grid;align-items:stretch;gap:1rem;padding-bottom:.75rem}@media (max-width: 479px){.form{grid-template-columns:1fr}}@media (min-width: 768px){.form{grid-template-columns:repeat(var(--cols),minmax(0,1fr))}}@media (min-width: 480px) and (max-width: 767px){.form{grid-template-columns:repeat(min(var(--cols),2),minmax(0,1fr))}}.form>*{min-width:0}h2{margin-top:1.5rem}.speak-icon{display:flex;width:100%;align-items:center;gap:10px}.speak-icon i{font-size:20px;color:var(--primary-500)}textarea{resize:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: UicDatePickerComponent, selector: "ui-date-picker", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "disabled", "label", "error", "tip", "max", "min", "justMonth", "monthDay"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: UicSliderComponent, selector: "ui-slider", inputs: ["icon", "iconColor", "label", "error", "tip", "min", "max", "step", "markerCount", "disabled", "loading"] }, { kind: "component", type: UicButtonComponent, selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "component", type: UicPoolOptionsComponent, selector: "ui-pool-options", inputs: ["icon", "iconColor", "size", "label", "error", "tip", "disabled", "loading", "multy", "enabledListView", "listViewTitle", "options"] }, { kind: "component", type: UicTimePickerComponent, selector: "ui-time-picker", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "disabled", "label", "error", "tip", "interval"] }, { kind: "component", type: UicRadioComponent, selector: "ui-radio", inputs: ["icon", "iconColor", "label", "error", "tip", "disabled", "loading", "options", "emptyText", "direction"] }, { kind: "component", type: UicSearcherComponent, selector: "ui-searcher", inputs: ["icon", "iconColor", "internalIcon", "size", "label", "error", "tip", "showSubtitle", "disabled", "loading", "minimumSearchLength", "showSelected", "placeholder", "searchFn", "itemDisplayFn", "itemIsEnabledFn", "manualSearch", "stateless"], outputs: ["pickedItem"] }, { kind: "component", type: UicMultySelectComponent, selector: "ui-multy-select", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "size", "label", "error", "tip", "showSubtitle", "disabled", "nonSelectedText", "allSelectedText", "loading", "options"] }, { kind: "component", type: UicFileInputComponent, selector: "ui-file-input", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "size", "label", "error", "tip", "disabled", "loading", "multy", "fileTypes", "fileUidResolverFn"] }, { kind: "component", type: UicSelectComponent, selector: "ui-select", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "size", "label", "error", "tip", "showSubtitle", "disabled", "nonSelectedText", "noneText", "emptyText", "searcherEnabled", "loading", "nullable", "options"] }, { kind: "directive", type: UicTextareaAutoresizeDirective, selector: "[textareaAutoresize]", inputs: ["minRows", "maxRows", "textareaAutoresize"] }, { kind: "directive", type: UicTextareaAutoresizeMinRowsDirective, selector: "[textareaAutoresizeMinRows]", inputs: ["textareaAutoresizeMinRows"] }, { kind: "directive", type: UicTextareaAutoresizeMaxRowsDirective, selector: "[textareaAutoresizeMaxRows]", inputs: ["textareaAutoresizeMaxRows"] }, { kind: "component", type: UicInputComponent, selector: "ui-input", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "size", "label", "error", "tip", "disabled", "loading"], outputs: ["clickButton"] }, { kind: "component", type: UicCheckboxComponent, selector: "ui-checkbox", inputs: ["icon", "iconColor", "label", "tip", "type", "placeholder", "loading", "noPadding", "disabled"] }, { kind: "component", type: UicPhoneInputComponent, selector: "ui-phone-input", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "size", "label", "error", "tip", "placeholder", "disabled", "loading", "preferredCountries", "flagPath", "countries"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: UicRepeaterComponent, selector: "ui-repeater", inputs: ["formArray", "field", "cols", "error"] }] });
|
|
4362
4599
|
}
|
|
4363
4600
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UicDynamicFormComponent, decorators: [{
|
|
4364
4601
|
type: Component,
|
|
@@ -4381,10 +4618,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
4381
4618
|
UicInputComponent,
|
|
4382
4619
|
UicCheckboxComponent,
|
|
4383
4620
|
UicPhoneInputComponent,
|
|
4384
|
-
FormsModule
|
|
4385
|
-
], template: "<div class=\"form\" [ngStyle]=\"{'--cols': cols, '--min': '180px'}\" [formGroup]=\"form\">\r\n @for (state of visibleFieldStates(); track state.field.name) {\r\n @let field = state.field;\r\n @let control = state.control;\r\n @let currentValue = state.value ?? '';\r\n @let error = getControlErrorMessages(control, field)[0];\r\n\r\n <div [style.grid-column]=\"getGridColumn(field)\">\n @if (['text', 'number'].includes(field.type)) {\r\n @let inputColor = getInputColor(field, currentValue);\r\n <ui-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [disabled]=\"!!control?.disabled\"\r\n [internalIconColor]=\"inputColor\"\r\n [internalIcon]=\"field.internalIcon || (currentValue !== '' ? getIconByColor(field, inputColor) : '')\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\">\r\n <input #inp\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [type]=\"field.type\"\r\n [step]=\"field.step\"\r\n [min]=\"field.min\"\r\n [max]=\"field.max\"\r\n [minLength]=\"field.minLength||null\"\r\n [maxlength]=\"field.maxLength||null\"\r\n [placeholder]=\"field.placeholder??field.label\"/>\r\n @if (field.maxLength && field.showCounter) {\r\n <span counter>{{inp.value.length}} /{{field.maxLength}}</span>\r\n }\r\n </ui-input>\r\n }\r\n @if (field.type === 'textarea') {\r\n <ui-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [disabled]=\"!!control?.disabled\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\">\r\n <textarea #ta\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [minLength]=\"field.minLength||null\"\r\n [maxlength]=\"field.maxLength||null\"\r\n [textareaAutoresize]=\"field.textareaResize\"\r\n [textareaAutoresizeMinRows]=\"field.resizeMinRows??1\"\r\n [textareaAutoresizeMaxRows]=\"field.resizeMaxRows??5\"\r\n [rows]=\"field.resizeMinRows??3\"\r\n [placeholder]=\"field.placeholder??field.label\"\r\n ></textarea>\r\n @if (field.voiceToTextEnabled && !control?.disabled) {\r\n @let listening = isListening(field.name);\r\n <div class=\"speak-icon\" (click)=\"ta.focus()\">\r\n <ui-button\r\n [disabled]=\"listening\"\r\n style=\"margin-bottom: 2px;\"\r\n (click)=\"voiceToText(ta, field.name)\"\r\n [icon]=\"listening?'ri-mic-fill':'ri-mic-line'\"\r\n [type]=\"listening?'filled':'bordered'\"\r\n size=\"s\"\r\n [iconOnly]=\"true\"\r\n ></ui-button>\r\n @if (listening) {\r\n <i class=\"ri-voiceprint-line\"></i>\r\n }\r\n </div>\r\n }\r\n @if (field.showCounter) {\r\n <span counter>\r\n {{ta.value.length}}\r\n @if (field.maxLength) {\r\n /{{field.maxLength}}\r\n }\r\n </span>\r\n }\r\n </ui-input>\r\n }\r\n @if (field.type === 'phone') {\r\n <ui-phone-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [placeholder]=\"field.placeholder||field.label||''\"\r\n >\r\n </ui-phone-input>\r\n }\r\n @else if (field.type === 'date') {\r\n <ui-date-picker\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [tip]=\"field.tip??''\"\r\n [justMonth]=\"!!field.monthMode\"\r\n [min]=\"field.minDate??''\"\r\n [max]=\"field.maxDate??''\"\r\n [monthDay]=\"field.monthDay||'first'\"\r\n [formControlName]=\"field.name\"\r\n ></ui-date-picker>\r\n }\r\n @else if (field.type === 'time') {\r\n <ui-time-picker\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [tip]=\"field.tip??''\"\r\n [interval]=\"field.timeInterval??5\"\r\n [formControlName]=\"field.name\"\r\n ></ui-time-picker>\r\n }\r\n @else if (field.type === 'select') {\r\n <ui-select\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [loading]=\"field.loading??false\"\r\n [nullable]=\"field.selectNullable??false\"\r\n [searcherEnabled]=\"field.selectSearchEnabled??false\"\r\n [tip]=\"field.tip??''\"\r\n [formControlName]=\"field.name\"\r\n [options]=\"field.options || []\"\r\n ></ui-select>\r\n }\r\n @else if (field.type === 'multyselect') {\r\n <ui-multy-select\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [tip]=\"field.tip??''\"\r\n [formControlName]=\"field.name\"\r\n [options]=\"field.options || []\"\r\n ></ui-multy-select>\r\n }\r\n @else if (field.type === 'searcher') {\r\n <ui-searcher\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\"\r\n [searchFn]=\"getSearcherFn(field)\"\r\n [itemDisplayFn]=\"getSearcherDisplayFn(field)\"\r\n [itemIsEnabledFn]=\"getSearcherIsEnabledFn(field)\"\r\n [placeholder]=\"field.placeholder??'common.search_ellipsis'\"\r\n [error]=\"error\"\r\n ></ui-searcher>\r\n }\r\n @else if (field.type === 'file') {\r\n <ui-file-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [multy]=\"field.multyEnabled??false\"\n [tip]=\"field.tip??''\"\n [fileTypes]=\"field.fileTypes??null\"\n [fileUidResolverFn]=\"fileUidResolverFn\"\n [formControlName]=\"field.name\"\n ></ui-file-input>\n }\n @else if (['checkbox', 'switch'].includes(field.type)) {\r\n <ui-checkbox\r\n [label]=\"(field.label??'') + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [placeholder]=\"field.placeholder??''\"\r\n [tip]=\"field.tip??''\"\r\n [type]=\"field.type === 'checkbox' ? 'checkbox' : 'switch'\"\r\n ></ui-checkbox>\r\n }\r\n @else if (field.type === 'radio') {\r\n <ui-radio\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [tip]=\"field.tip??''\"\r\n [loading]=\"field.loading??false\"\r\n [error]=\"error\"\r\n [options]=\"field.options || []\"\r\n ></ui-radio>\r\n }\r\n @else if (field.type === 'slider') {\r\n <ui-slider\r\n [min]=\"field.min??0\"\r\n [max]=\"field.max??100\"\r\n [step]=\"field.sliderInterval??1\"\r\n [markerCount]=\"field.sliderMarks??5\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [tip]=\"field.tip??''\"\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n ></ui-slider>\r\n }\r\n @else if (field.type === 'pool') {\r\n <ui-pool-options\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [multy]=\"field.multyEnabled??false\"\r\n [tip]=\"field.tip??''\"\r\n [listViewTitle]=\"field.poolTitle??'common.selected'\"\r\n [enabledListView]=\"field.poolEnabledListView||false\"\r\n [formControlName]=\"field.name\"\r\n [options]=\"field.options || []\"\r\n ></ui-pool-options>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".form{width:100%;display:grid;align-items:stretch;gap:1rem;padding-bottom:.75rem}@media (max-width: 479px){.form{grid-template-columns:1fr}}@media (min-width: 768px){.form{grid-template-columns:repeat(var(--cols),minmax(0,1fr))}}@media (min-width: 480px) and (max-width: 767px){.form{grid-template-columns:repeat(min(var(--cols),2),minmax(0,1fr))}}.form>*{min-width:0}h2{margin-top:1.5rem}.speak-icon{display:flex;width:100%;align-items:center;gap:10px}.speak-icon i{font-size:20px;color:var(--primary-500)}textarea{resize:none}\n"] }]
|
|
4621
|
+
FormsModule,
|
|
4622
|
+
UicRepeaterComponent
|
|
4623
|
+
], template: "<div class=\"form\" [ngStyle]=\"{'--cols': cols, '--min': '180px'}\" [formGroup]=\"form\">\r\n @for (state of visibleFieldStates(); track state.field.name) {\r\n @let field = state.field;\r\n @let control = state.control;\r\n @let currentValue = state.value ?? '';\r\n @let error = getControlErrorMessages(control, field)[0];\r\n\r\n <div [style.grid-column]=\"getGridColumn(field)\">\r\n @if (['text', 'number'].includes(field.type)) {\r\n @let inputColor = getInputColor(field, currentValue);\r\n <ui-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [disabled]=\"!!control?.disabled\"\r\n [internalIconColor]=\"inputColor\"\r\n [internalIcon]=\"field.internalIcon || (currentValue !== '' ? getIconByColor(field, inputColor) : '')\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\">\r\n <input #inp\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [type]=\"field.type\"\r\n [step]=\"field.step\"\r\n [min]=\"field.min\"\r\n [max]=\"field.max\"\r\n [minLength]=\"field.minLength||null\"\r\n [maxlength]=\"field.maxLength||null\"\r\n [placeholder]=\"field.placeholder??field.label\"/>\r\n @if (field.maxLength && field.showCounter) {\r\n <span counter>{{inp.value.length}} /{{field.maxLength}}</span>\r\n }\r\n </ui-input>\r\n }\r\n @if (field.type === 'textarea') {\r\n <ui-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [disabled]=\"!!control?.disabled\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\">\r\n <textarea #ta\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [minLength]=\"field.minLength||null\"\r\n [maxlength]=\"field.maxLength||null\"\r\n [textareaAutoresize]=\"field.textareaResize\"\r\n [textareaAutoresizeMinRows]=\"field.resizeMinRows??1\"\r\n [textareaAutoresizeMaxRows]=\"field.resizeMaxRows??5\"\r\n [rows]=\"field.resizeMinRows??3\"\r\n [placeholder]=\"field.placeholder??field.label\"\r\n ></textarea>\r\n @if (field.voiceToTextEnabled && !control?.disabled) {\r\n @let listening = isListening(field.name);\r\n <div class=\"speak-icon\" (click)=\"ta.focus()\">\r\n <ui-button\r\n [disabled]=\"listening\"\r\n style=\"margin-bottom: 2px;\"\r\n (click)=\"voiceToText(ta, field.name)\"\r\n [icon]=\"listening?'ri-mic-fill':'ri-mic-line'\"\r\n [type]=\"listening?'filled':'bordered'\"\r\n size=\"s\"\r\n [iconOnly]=\"true\"\r\n ></ui-button>\r\n @if (listening) {\r\n <i class=\"ri-voiceprint-line\"></i>\r\n }\r\n </div>\r\n }\r\n @if (field.showCounter) {\r\n <span counter>\r\n {{ta.value.length}}\r\n @if (field.maxLength) {\r\n /{{field.maxLength}}\r\n }\r\n </span>\r\n }\r\n </ui-input>\r\n }\r\n @if (field.type === 'phone') {\r\n <ui-phone-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [placeholder]=\"field.placeholder||field.label||''\"\r\n >\r\n </ui-phone-input>\r\n }\r\n @else if (field.type === 'date') {\r\n <ui-date-picker\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [tip]=\"field.tip??''\"\r\n [justMonth]=\"!!field.monthMode\"\r\n [min]=\"field.minDate??''\"\r\n [max]=\"field.maxDate??''\"\r\n [monthDay]=\"field.monthDay||'first'\"\r\n [formControlName]=\"field.name\"\r\n ></ui-date-picker>\r\n }\r\n @else if (field.type === 'time') {\r\n <ui-time-picker\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [tip]=\"field.tip??''\"\r\n [interval]=\"field.timeInterval??5\"\r\n [formControlName]=\"field.name\"\r\n ></ui-time-picker>\r\n }\r\n @else if (field.type === 'select') {\r\n <ui-select\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [loading]=\"field.loading??false\"\r\n [nullable]=\"field.selectNullable??false\"\r\n [searcherEnabled]=\"field.selectSearchEnabled??false\"\r\n [tip]=\"field.tip??''\"\r\n [formControlName]=\"field.name\"\r\n [options]=\"field.options || []\"\r\n ></ui-select>\r\n }\r\n @else if (field.type === 'multyselect') {\r\n <ui-multy-select\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [tip]=\"field.tip??''\"\r\n [formControlName]=\"field.name\"\r\n [options]=\"field.options || []\"\r\n ></ui-multy-select>\r\n }\r\n @else if (field.type === 'searcher') {\r\n <ui-searcher\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [tip]=\"field.tip??''\"\r\n [searchFn]=\"getSearcherFn(field)\"\r\n [itemDisplayFn]=\"getSearcherDisplayFn(field)\"\r\n [itemIsEnabledFn]=\"getSearcherIsEnabledFn(field)\"\r\n [placeholder]=\"field.placeholder??'common.search_ellipsis'\"\r\n [error]=\"error\"\r\n ></ui-searcher>\r\n }\r\n @else if (field.type === 'file') {\r\n <ui-file-input\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [internalIcon]=\"field.internalIcon??''\"\r\n [internalIconColor]=\"field.internalIconColor??'grey'\"\r\n [multy]=\"field.multyEnabled??false\"\r\n [tip]=\"field.tip??''\"\r\n [fileTypes]=\"field.fileTypes??null\"\r\n [fileUidResolverFn]=\"fileUidResolverFn\"\r\n [formControlName]=\"field.name\"\r\n ></ui-file-input>\r\n }\r\n @else if (['checkbox', 'switch'].includes(field.type)) {\r\n <ui-checkbox\r\n [label]=\"(field.label??'') + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [placeholder]=\"field.placeholder??''\"\r\n [tip]=\"field.tip??''\"\r\n [type]=\"field.type === 'checkbox' ? 'checkbox' : 'switch'\"\r\n ></ui-checkbox>\r\n }\r\n @else if (field.type === 'radio') {\r\n <ui-radio\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [tip]=\"field.tip??''\"\r\n [loading]=\"field.loading??false\"\r\n [error]=\"error\"\r\n [options]=\"field.options || []\"\r\n ></ui-radio>\r\n }\r\n @else if (field.type === 'slider') {\r\n <ui-slider\r\n [min]=\"field.min??0\"\r\n [max]=\"field.max??100\"\r\n [step]=\"field.sliderInterval??1\"\r\n [markerCount]=\"field.sliderMarks??5\"\r\n [id]=\"field.name\"\r\n [formControlName]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [tip]=\"field.tip??''\"\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n ></ui-slider>\r\n }\r\n @else if (field.type === 'pool') {\r\n <ui-pool-options\r\n [error]=\"error\"\r\n [label]=\"field.label + (field.required ? ' *' : '')\"\r\n [id]=\"field.name\"\r\n [icon]=\"field.icon??''\"\r\n [loading]=\"field.loading??false\"\r\n [multy]=\"field.multyEnabled??false\"\r\n [tip]=\"field.tip??''\"\r\n [listViewTitle]=\"field.poolTitle??'common.selected'\"\r\n [enabledListView]=\"field.poolEnabledListView||false\"\r\n [formControlName]=\"field.name\"\r\n [options]=\"field.options || []\"\r\n ></ui-pool-options>\r\n }\r\n @else if (field.type === 'repeater') {\r\n <ui-repeater\r\n [formArray]=\"asFormArray(control)\"\r\n [field]=\"field\"\r\n [cols]=\"cols\"\r\n [error]=\"error\"\r\n ></ui-repeater>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".form{width:100%;display:grid;align-items:stretch;gap:1rem;padding-bottom:.75rem}@media (max-width: 479px){.form{grid-template-columns:1fr}}@media (min-width: 768px){.form{grid-template-columns:repeat(var(--cols),minmax(0,1fr))}}@media (min-width: 480px) and (max-width: 767px){.form{grid-template-columns:repeat(min(var(--cols),2),minmax(0,1fr))}}.form>*{min-width:0}h2{margin-top:1.5rem}.speak-icon{display:flex;width:100%;align-items:center;gap:10px}.speak-icon i{font-size:20px;color:var(--primary-500)}textarea{resize:none}\n"] }]
|
|
4386
4624
|
}], ctorParameters: () => [{ type: i0.NgZone }], propDecorators: { fields: [{
|
|
4387
4625
|
type: Input
|
|
4626
|
+
}], isSubForm: [{
|
|
4627
|
+
type: Input
|
|
4388
4628
|
}], form: [{
|
|
4389
4629
|
type: Input,
|
|
4390
4630
|
args: [{ required: true }]
|
|
@@ -4472,10 +4712,12 @@ class UicFormWrapperComponent {
|
|
|
4472
4712
|
buildForm() {
|
|
4473
4713
|
this.formValueSub?.unsubscribe();
|
|
4474
4714
|
this.formValueSub = null;
|
|
4475
|
-
const
|
|
4476
|
-
const
|
|
4715
|
+
const allFields = this.collectAllFields();
|
|
4716
|
+
const regularFields = allFields.filter(field => field.type !== 'repeater');
|
|
4717
|
+
const repeaterFields = allFields.filter(field => field.type === 'repeater');
|
|
4718
|
+
const numericFields = regularFields.filter(field => field.type === 'number');
|
|
4477
4719
|
const newForm = this.fb.group({});
|
|
4478
|
-
|
|
4720
|
+
regularFields.forEach(field => {
|
|
4479
4721
|
const validators = this.mapValidatorsFromField(field);
|
|
4480
4722
|
const initial = this.normalizeFieldValue(field, this.newFieldInitialValue(field, true));
|
|
4481
4723
|
const controlState = {
|
|
@@ -4484,6 +4726,25 @@ class UicFormWrapperComponent {
|
|
|
4484
4726
|
};
|
|
4485
4727
|
newForm.addControl(field.name, this.fb.control(controlState, validators));
|
|
4486
4728
|
});
|
|
4729
|
+
repeaterFields.forEach(field => {
|
|
4730
|
+
const arrayValidators = field.required
|
|
4731
|
+
? [this.repeaterArrayValidator(field.repeaterMinItems ?? 1)]
|
|
4732
|
+
: [];
|
|
4733
|
+
const formArray = new FormArray([], arrayValidators);
|
|
4734
|
+
const initialItems = this.initialValues?.[field.name];
|
|
4735
|
+
if (Array.isArray(initialItems) && initialItems.length > 0) {
|
|
4736
|
+
initialItems.forEach(itemValues => {
|
|
4737
|
+
formArray.push(this.buildRepeaterGroup(field, itemValues), { emitEvent: false });
|
|
4738
|
+
});
|
|
4739
|
+
}
|
|
4740
|
+
else {
|
|
4741
|
+
const min = field.repeaterMinItems ?? 0;
|
|
4742
|
+
for (let i = 0; i < min; i++) {
|
|
4743
|
+
formArray.push(this.buildRepeaterGroup(field, {}), { emitEvent: false });
|
|
4744
|
+
}
|
|
4745
|
+
}
|
|
4746
|
+
newForm.addControl(field.name, formArray);
|
|
4747
|
+
});
|
|
4487
4748
|
this.formValueSub = newForm.valueChanges.subscribe(() => {
|
|
4488
4749
|
this.normalizeNumericControls(newForm, numericFields);
|
|
4489
4750
|
this.handleFormChange();
|
|
@@ -4494,6 +4755,21 @@ class UicFormWrapperComponent {
|
|
|
4494
4755
|
this.updateDisabledState();
|
|
4495
4756
|
this.focusConfiguredField();
|
|
4496
4757
|
}
|
|
4758
|
+
buildRepeaterGroup(field, values = {}) {
|
|
4759
|
+
const group = this.fb.group({});
|
|
4760
|
+
(field.repeaterFields ?? []).forEach(subField => {
|
|
4761
|
+
const validators = this.mapValidatorsFromField(subField);
|
|
4762
|
+
const value = values[subField.name] ?? this.blankValue(subField);
|
|
4763
|
+
group.addControl(subField.name, this.fb.control({ value, disabled: this.disabled || !!subField.disabled }, validators));
|
|
4764
|
+
});
|
|
4765
|
+
return group;
|
|
4766
|
+
}
|
|
4767
|
+
repeaterArrayValidator(min) {
|
|
4768
|
+
return (control) => {
|
|
4769
|
+
const arr = control;
|
|
4770
|
+
return arr.length >= min ? null : { minLengthArray: { required: min, actual: arr.length } };
|
|
4771
|
+
};
|
|
4772
|
+
}
|
|
4497
4773
|
focusConfiguredField() {
|
|
4498
4774
|
if (!this.focusFieldName || this.hasFocusedCurrentTrigger)
|
|
4499
4775
|
return;
|
|
@@ -4536,6 +4812,20 @@ class UicFormWrapperComponent {
|
|
|
4536
4812
|
}
|
|
4537
4813
|
for (const block of this.effectiveSchema.blocks) {
|
|
4538
4814
|
block.fields = this.updateFieldOptions(block);
|
|
4815
|
+
block.fields = block.fields.map(field => {
|
|
4816
|
+
if (field.type !== 'repeater' || !field.repeaterFields?.length)
|
|
4817
|
+
return field;
|
|
4818
|
+
const namespace = this.externalData[field.name];
|
|
4819
|
+
if (!namespace || typeof namespace !== 'object' || Array.isArray(namespace))
|
|
4820
|
+
return field;
|
|
4821
|
+
const updatedRepeaterFields = field.repeaterFields.map(subField => {
|
|
4822
|
+
if (subField.type !== 'select' && subField.type !== 'pool' && subField.type !== 'multyselect')
|
|
4823
|
+
return subField;
|
|
4824
|
+
const subOptions = namespace[subField.name];
|
|
4825
|
+
return Array.isArray(subOptions) ? { ...subField, options: subOptions } : subField;
|
|
4826
|
+
});
|
|
4827
|
+
return { ...field, repeaterFields: updatedRepeaterFields };
|
|
4828
|
+
});
|
|
4539
4829
|
}
|
|
4540
4830
|
}
|
|
4541
4831
|
mapValidatorsFromField(field) {
|
|
@@ -4583,6 +4873,16 @@ class UicFormWrapperComponent {
|
|
|
4583
4873
|
updateOptionsSources(force = false) {
|
|
4584
4874
|
const fields = this.collectAllFields().filter(field => this.hasUsableOptionsSource(field));
|
|
4585
4875
|
const fieldNames = new Set(fields.map(field => field.name));
|
|
4876
|
+
for (const block of this.effectiveSchema?.blocks ?? []) {
|
|
4877
|
+
for (const f of block.fields) {
|
|
4878
|
+
if (f.type === 'repeater' && f.repeaterFields?.length) {
|
|
4879
|
+
f.repeaterFields.forEach(sf => {
|
|
4880
|
+
if (this.hasUsableOptionsSource(sf))
|
|
4881
|
+
fieldNames.add(`${f.name}__${sf.name}`);
|
|
4882
|
+
});
|
|
4883
|
+
}
|
|
4884
|
+
}
|
|
4885
|
+
}
|
|
4586
4886
|
for (const fieldName of this.optionSourceSubs.keys()) {
|
|
4587
4887
|
if (!fieldNames.has(fieldName)) {
|
|
4588
4888
|
this.optionSourceSubs.get(fieldName)?.unsubscribe();
|
|
@@ -4591,6 +4891,80 @@ class UicFormWrapperComponent {
|
|
|
4591
4891
|
}
|
|
4592
4892
|
}
|
|
4593
4893
|
fields.forEach(field => this.resolveOptionsSourceField(field, force));
|
|
4894
|
+
this.updateRepeaterSubFieldOptionsSources(force);
|
|
4895
|
+
}
|
|
4896
|
+
updateRepeaterSubFieldOptionsSources(force = false) {
|
|
4897
|
+
if (!this.effectiveSchema?.blocks?.length)
|
|
4898
|
+
return;
|
|
4899
|
+
for (const block of this.effectiveSchema.blocks) {
|
|
4900
|
+
for (const field of block.fields) {
|
|
4901
|
+
if (field.type !== 'repeater' || !field.repeaterFields?.length)
|
|
4902
|
+
continue;
|
|
4903
|
+
field.repeaterFields.forEach(subField => {
|
|
4904
|
+
if (this.hasUsableOptionsSource(subField)) {
|
|
4905
|
+
this.resolveRepeaterSubFieldOptionsSource(field, subField, force);
|
|
4906
|
+
}
|
|
4907
|
+
});
|
|
4908
|
+
}
|
|
4909
|
+
}
|
|
4910
|
+
}
|
|
4911
|
+
resolveRepeaterSubFieldOptionsSource(parentField, subField, force = false) {
|
|
4912
|
+
const source = subField.optionsSource;
|
|
4913
|
+
const subFieldKey = `${parentField.name}__${subField.name}`;
|
|
4914
|
+
if (!this.selectOptionsResolver) {
|
|
4915
|
+
this.updateRepeaterSubFieldOptionsState(parentField.name, subField.name, {
|
|
4916
|
+
options: subField.options ?? [],
|
|
4917
|
+
loading: false
|
|
4918
|
+
});
|
|
4919
|
+
return;
|
|
4920
|
+
}
|
|
4921
|
+
if (!force && this.optionSourceSubs.has(subFieldKey))
|
|
4922
|
+
return;
|
|
4923
|
+
this.optionSourceSubs.get(subFieldKey)?.unsubscribe();
|
|
4924
|
+
this.updateRepeaterSubFieldOptionsState(parentField.name, subField.name, { loading: true });
|
|
4925
|
+
const values = this.toNestedValues(this.form?.getRawValue?.() ?? {});
|
|
4926
|
+
let optionsResult;
|
|
4927
|
+
try {
|
|
4928
|
+
optionsResult = this.selectOptionsResolver(source, { field: subField, values, dependencyValue: undefined });
|
|
4929
|
+
}
|
|
4930
|
+
catch (error) {
|
|
4931
|
+
this.handleOptionsSourceError(subField, source, error);
|
|
4932
|
+
return;
|
|
4933
|
+
}
|
|
4934
|
+
const sub = this.toObservable(optionsResult).subscribe({
|
|
4935
|
+
next: items => {
|
|
4936
|
+
const options = this.mapOptionsSourceItems(items, source);
|
|
4937
|
+
this.updateRepeaterSubFieldOptionsState(parentField.name, subField.name, { options, loading: false });
|
|
4938
|
+
},
|
|
4939
|
+
error: (error) => this.handleOptionsSourceError(subField, source, error),
|
|
4940
|
+
complete: () => this.updateRepeaterSubFieldOptionsState(parentField.name, subField.name, { loading: false })
|
|
4941
|
+
});
|
|
4942
|
+
this.optionSourceSubs.set(subFieldKey, sub);
|
|
4943
|
+
}
|
|
4944
|
+
updateRepeaterSubFieldOptionsState(repeaterFieldName, subFieldName, values) {
|
|
4945
|
+
if (!this.effectiveSchema?.blocks?.length)
|
|
4946
|
+
return;
|
|
4947
|
+
for (const block of this.effectiveSchema.blocks) {
|
|
4948
|
+
const repeaterIdx = block.fields.findIndex(f => f.name === repeaterFieldName);
|
|
4949
|
+
if (repeaterIdx === -1)
|
|
4950
|
+
continue;
|
|
4951
|
+
const repeaterField = block.fields[repeaterIdx];
|
|
4952
|
+
if (!repeaterField.repeaterFields)
|
|
4953
|
+
continue;
|
|
4954
|
+
const subIdx = repeaterField.repeaterFields.findIndex(sf => sf.name === subFieldName);
|
|
4955
|
+
if (subIdx === -1)
|
|
4956
|
+
continue;
|
|
4957
|
+
const updatedRepeaterFields = [...repeaterField.repeaterFields];
|
|
4958
|
+
updatedRepeaterFields[subIdx] = {
|
|
4959
|
+
...updatedRepeaterFields[subIdx],
|
|
4960
|
+
...(values.options !== undefined ? { options: values.options } : {}),
|
|
4961
|
+
...(values.loading !== undefined ? { loading: values.loading } : {})
|
|
4962
|
+
};
|
|
4963
|
+
block.fields[repeaterIdx] = { ...repeaterField, repeaterFields: updatedRepeaterFields };
|
|
4964
|
+
block.fields = [...block.fields];
|
|
4965
|
+
this.effectiveSchema.blocks = [...this.effectiveSchema.blocks];
|
|
4966
|
+
return;
|
|
4967
|
+
}
|
|
4594
4968
|
}
|
|
4595
4969
|
updateDependentOptionsSources() {
|
|
4596
4970
|
const fields = this.collectAllFields().filter(field => {
|
|
@@ -4834,12 +5208,28 @@ class UicFormWrapperComponent {
|
|
|
4834
5208
|
return;
|
|
4835
5209
|
const fields = this.collectAllFields();
|
|
4836
5210
|
const fieldMap = new Map(fields.map(field => [field.name, field]));
|
|
4837
|
-
const resetValues = {};
|
|
4838
5211
|
Object.keys(this.form.controls).forEach(name => {
|
|
4839
5212
|
const field = fieldMap.get(name);
|
|
4840
|
-
|
|
5213
|
+
const control = this.form.get([name]);
|
|
5214
|
+
if (!control)
|
|
5215
|
+
return;
|
|
5216
|
+
if (field?.type === 'repeater') {
|
|
5217
|
+
const formArray = control;
|
|
5218
|
+
while (formArray.length > 0) {
|
|
5219
|
+
formArray.removeAt(0, { emitEvent: false });
|
|
5220
|
+
}
|
|
5221
|
+
const min = field.repeaterMinItems ?? 0;
|
|
5222
|
+
for (let i = 0; i < min; i++) {
|
|
5223
|
+
formArray.push(this.buildRepeaterGroup(field, {}), { emitEvent: false });
|
|
5224
|
+
}
|
|
5225
|
+
formArray.markAsPristine();
|
|
5226
|
+
formArray.markAsUntouched();
|
|
5227
|
+
}
|
|
5228
|
+
else {
|
|
5229
|
+
const resetValue = this.resolveResetValue(name, field, hardReset);
|
|
5230
|
+
control.reset(resetValue, { emitEvent: false });
|
|
5231
|
+
}
|
|
4841
5232
|
});
|
|
4842
|
-
this.form.reset(resetValues, { emitEvent: false });
|
|
4843
5233
|
this.handleFormChange();
|
|
4844
5234
|
}
|
|
4845
5235
|
addFieldControl(field, after) {
|
|
@@ -5030,7 +5420,7 @@ class UicFormWrapperComponent {
|
|
|
5030
5420
|
};
|
|
5031
5421
|
}
|
|
5032
5422
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UicFormWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5033
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: UicFormWrapperComponent, isStandalone: true, selector: "ui-form-wrapper", inputs: { schema: "schema", fields: "fields", cols: "cols", externalData: "externalData", selectOptionsResolver: "selectOptionsResolver", loading: "loading", disabled: "disabled", showButtons: "showButtons", fillSelects: "fillSelects", initialValues: "initialValues", focusFieldName: "focusFieldName", focusFieldTrigger: "focusFieldTrigger", fileUidResolverFn: "fileUidResolverFn" }, outputs: { formSubmit: "formSubmit", formChange: "formChange", optionsSourceError: "optionsSourceError" }, providers: [UicFormStateService], usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"form\" (ngSubmit)=\"handleSubmit()\">\r\n @for (block of effectiveSchema.blocks; track $index) {\r\n \r\n <section class=\"form-block\">\r\n @if (block.title){\r\n <div class=\"block-title\">{{ block.title }}</div>\r\n }\r\n @if (block.subtitle){\r\n <div class=\"block-subtitle\">{{ block.subtitle }}</div>\r\n }\r\n @if (loading) {\r\n <ui-skeleton-loader\r\n [cols]=\"effectiveSchema.cols\"\r\n [inputs]=\"block.fields.length\"\r\n ></ui-skeleton-loader>\r\n } @else {\r\n <ui-dynamic-form\n [cols]=\"effectiveSchema.cols\"\n [disabled]=\"disabled\"\n [fileUidResolverFn]=\"fileUidResolverFn\"\n [fields]=\"block.fields\"\n [form]=\"form\"\n [selectOptionsResolver]=\"selectOptionsResolver\">\n </ui-dynamic-form>\n }\r\n </section>\r\n }\r\n @if ( showButtons ) {\r\n\r\n <div class=\"form-buttons\">\r\n <ui-button color=\"black\" type=\"bordered\" (click)=\"clean()\">{{'common.clear' | uicTranslate}}</ui-button>\r\n <ui-button color=\"black\" (click)=\"submit()\">{{'common.save' | uicTranslate}}</ui-button>\r\n </div>\r\n }\r\n</form>\r\n", styles: [":host{display:block;padding:.25rem 0}.block-title{font-size:1.625rem;font-weight:600;line-height:calc(1.625rem + 4px);margin:1rem 0;color:var(--grey-950)}.block-subtitle{font-size:1.25rem;font-weight:600;line-height:calc(1.25rem + 4px);margin:.75rem 0;color:var(--grey-950)}.form-buttons{display:flex;gap:10px;width:100%}\n"], dependencies: [{ kind: "component", type: UicDynamicFormComponent, selector: "ui-dynamic-form", inputs: ["fields", "form", "disabled", "voiceToTextSilenceMs", "cols", "fileUidResolverFn", "selectOptionsResolver"] }, { kind: "component", type: UicSkeletonLoaderComponent, selector: "ui-skeleton-loader", inputs: ["inputs", "cols"] }, { kind: "component", type: UicButtonComponent, selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "pipe", type: UicTranslatePipe, name: "uicTranslate" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }] });
|
|
5423
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: UicFormWrapperComponent, isStandalone: true, selector: "ui-form-wrapper", inputs: { schema: "schema", fields: "fields", cols: "cols", externalData: "externalData", selectOptionsResolver: "selectOptionsResolver", loading: "loading", disabled: "disabled", showButtons: "showButtons", fillSelects: "fillSelects", initialValues: "initialValues", focusFieldName: "focusFieldName", focusFieldTrigger: "focusFieldTrigger", fileUidResolverFn: "fileUidResolverFn" }, outputs: { formSubmit: "formSubmit", formChange: "formChange", optionsSourceError: "optionsSourceError" }, providers: [UicFormStateService], usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"form\" (ngSubmit)=\"handleSubmit()\">\r\n @for (block of effectiveSchema.blocks; track $index) {\r\n \r\n <section class=\"form-block\">\r\n @if (block.title){\r\n <div class=\"block-title\">{{ block.title }}</div>\r\n }\r\n @if (block.subtitle){\r\n <div class=\"block-subtitle\">{{ block.subtitle }}</div>\r\n }\r\n @if (loading) {\r\n <ui-skeleton-loader\r\n [cols]=\"effectiveSchema.cols\"\r\n [inputs]=\"block.fields.length\"\r\n ></ui-skeleton-loader>\r\n } @else {\r\n <ui-dynamic-form\n [cols]=\"effectiveSchema.cols\"\n [disabled]=\"disabled\"\n [fileUidResolverFn]=\"fileUidResolverFn\"\n [fields]=\"block.fields\"\n [form]=\"form\"\n [selectOptionsResolver]=\"selectOptionsResolver\">\n </ui-dynamic-form>\n }\r\n </section>\r\n }\r\n @if ( showButtons ) {\r\n\r\n <div class=\"form-buttons\">\r\n <ui-button color=\"black\" type=\"bordered\" (click)=\"clean()\">{{'common.clear' | uicTranslate}}</ui-button>\r\n <ui-button color=\"black\" (click)=\"submit()\">{{'common.save' | uicTranslate}}</ui-button>\r\n </div>\r\n }\r\n</form>\r\n", styles: [":host{display:block;padding:.25rem 0}.block-title{font-size:1.625rem;font-weight:600;line-height:calc(1.625rem + 4px);margin:1rem 0;color:var(--grey-950)}.block-subtitle{font-size:1.25rem;font-weight:600;line-height:calc(1.25rem + 4px);margin:.75rem 0;color:var(--grey-950)}.form-buttons{display:flex;gap:10px;width:100%}\n"], dependencies: [{ kind: "component", type: UicDynamicFormComponent, selector: "ui-dynamic-form", inputs: ["fields", "isSubForm", "form", "disabled", "voiceToTextSilenceMs", "cols", "fileUidResolverFn", "selectOptionsResolver"] }, { kind: "component", type: UicSkeletonLoaderComponent, selector: "ui-skeleton-loader", inputs: ["inputs", "cols"] }, { kind: "component", type: UicButtonComponent, selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "pipe", type: UicTranslatePipe, name: "uicTranslate" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }] });
|
|
5034
5424
|
}
|
|
5035
5425
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UicFormWrapperComponent, decorators: [{
|
|
5036
5426
|
type: Component,
|
|
@@ -6408,7 +6798,10 @@ function mapEditableBlocksToBlocks(blocks, editable) {
|
|
|
6408
6798
|
...field.fieldData,
|
|
6409
6799
|
disabled: !editable,
|
|
6410
6800
|
optionsSource,
|
|
6411
|
-
visibilityRules: visibilityRules ?? field.fieldData.visibilityRules
|
|
6801
|
+
visibilityRules: visibilityRules ?? field.fieldData.visibilityRules,
|
|
6802
|
+
...(field.repeaterSubFields?.length
|
|
6803
|
+
? { repeaterFields: field.repeaterSubFields.map(sf => ({ ...sf.fieldData, disabled: !editable })) }
|
|
6804
|
+
: {})
|
|
6412
6805
|
};
|
|
6413
6806
|
})
|
|
6414
6807
|
}));
|
|
@@ -8472,22 +8865,33 @@ const simpleFade = trigger('simpleFade', [
|
|
|
8472
8865
|
]);
|
|
8473
8866
|
|
|
8474
8867
|
;
|
|
8868
|
+
const VISIBILITY_OPERATOR_OPTIONS = [
|
|
8869
|
+
{ id: 'equals', text: 'equals' },
|
|
8870
|
+
{ id: 'notEquals', text: 'notEquals' },
|
|
8871
|
+
{ id: 'greaterThan', text: 'greaterThan' },
|
|
8872
|
+
{ id: 'lessThan', text: 'lessThan' },
|
|
8873
|
+
{ id: 'includes', text: 'includes' },
|
|
8874
|
+
{ id: 'notIncludes', text: 'notIncludes' },
|
|
8875
|
+
{ id: 'isEmpty', text: 'isEmpty' },
|
|
8876
|
+
{ id: 'isNotEmpty', text: 'isNotEmpty' }
|
|
8877
|
+
];
|
|
8475
8878
|
const FIELDS_CONFIG = [
|
|
8476
|
-
{ value: 'text', icon: 'ri-text', detail: 'Campo de texto en una sola linea', label: 'Texto corto', properties: ['placeholder', 'minLength', 'maxLength', 'showCounter'] },
|
|
8477
|
-
{ value: 'textarea', icon: 'ri-file-text-line', detail: 'Texto multilinea con ajuste de altura', label: 'Area de texto', properties: ['placeholder', 'minLength', 'maxLength', 'showCounter', 'voiceToTextEnabled', 'textareaResize', 'resizeMinRows', 'resizeMaxRows'] },
|
|
8478
|
-
{ value: 'number', icon: 'ri-hashtag', detail: 'Campo numerico con control de paso', label: 'Numero', properties: ['placeholder', 'step', 'min', 'max'] },
|
|
8479
|
-
{ value: 'phone', icon: 'ri-phone-line', detail: 'Telefono con pais y codigo', label: 'Telefono', properties: ['placeholder'] },
|
|
8480
|
-
{ value: 'select', icon: 'ri-
|
|
8481
|
-
{ value: 'multyselect', icon: 'ri-
|
|
8482
|
-
{ value: 'date', icon: 'ri-calendar-2-line', detail: 'Selector de fecha o mes', label: 'Fecha', properties: ['monthMode', 'monthDay', 'minDate', 'maxDate'] },
|
|
8483
|
-
{ value: 'time', icon: 'ri-timer-2-line', detail: 'Selector de hora', label: 'Hora', properties: ['timeInterval'] },
|
|
8484
|
-
{ value: 'radio', icon: 'ri-radio-button-line', detail: 'Seleccion unica entre opciones', label: 'Radio', properties: ['options'] },
|
|
8485
|
-
{ value: 'checkbox', icon: 'ri-checkbox-line', detail: 'Campo booleano tipo check', label: 'Checkbox', properties: ['placeholder'] },
|
|
8486
|
-
{ value: 'switch', icon: 'ri-toggle-line', detail: 'Campo booleano tipo switch', label: 'Switch', properties: ['placeholder'] },
|
|
8487
|
-
{ value: 'pool', icon: 'ri-
|
|
8488
|
-
{ value: 'file', icon: 'ri-attachment-line', detail: 'Carga de archivos', label: 'Archivo', properties: ['multyEnabled', 'fileTypes', 'iaValidation', 'iaValidationPrompt'] },
|
|
8489
|
-
{ value: 'searcher', icon: 'ri-seo-line', detail: 'Buscador con fuente de datos externa', label: 'Buscador', properties: ['placeholder', 'optionsSource.key', 'optionsSource.idField', 'optionsSource.textField', 'optionsSource.textTemplate', 'optionsSource.dependsOn', 'optionsSource.paramName'] },
|
|
8490
|
-
{ value: 'slider', icon: 'ri-equalizer-2-line', detail: 'Control deslizante continuo', label: 'Deslizador', properties: ['min', 'max', 'sliderInterval', 'sliderMarks'] }
|
|
8879
|
+
{ value: 'text', icon: 'ri-text', detail: 'Campo de texto en una sola linea', label: 'Texto corto', properties: ['placeholder', 'minLength', 'maxLength', 'showCounter'], visibility: { outputType: 'string', operators: ['equals', 'notEquals', 'includes', 'notIncludes', 'isEmpty', 'isNotEmpty'] } },
|
|
8880
|
+
{ value: 'textarea', icon: 'ri-file-text-line', detail: 'Texto multilinea con ajuste de altura', label: 'Area de texto', properties: ['placeholder', 'minLength', 'maxLength', 'showCounter', 'voiceToTextEnabled', 'textareaResize', 'resizeMinRows', 'resizeMaxRows'], visibility: { outputType: 'string', operators: ['equals', 'notEquals', 'includes', 'notIncludes', 'isEmpty', 'isNotEmpty'] } },
|
|
8881
|
+
{ value: 'number', icon: 'ri-hashtag', detail: 'Campo numerico con control de paso', label: 'Numero', properties: ['placeholder', 'step', 'min', 'max'], visibility: { outputType: 'number', operators: ['equals', 'notEquals', 'greaterThan', 'lessThan', 'isEmpty', 'isNotEmpty'] } },
|
|
8882
|
+
{ value: 'phone', icon: 'ri-phone-line', detail: 'Telefono con pais y codigo', label: 'Telefono', properties: ['placeholder'], visibility: { outputType: 'UicPhoneInputValue', operators: ['includes', 'notIncludes', 'isEmpty', 'isNotEmpty'] } },
|
|
8883
|
+
{ value: 'select', icon: 'ri-arrow-drop-down-line', detail: 'Seleccion simple desde opciones', label: 'Selector', properties: ['options', 'selectSearchEnabled', 'selectNullable'], visibility: { outputType: 'string', operators: ['equals', 'notEquals', 'includes', 'notIncludes', 'isEmpty', 'isNotEmpty'] } },
|
|
8884
|
+
{ value: 'multyselect', icon: 'ri-arrow-down-double-line', detail: 'Seleccion multiple desde opciones', label: 'Selector multiple', properties: ['options'], visibility: { outputType: 'string[]', operators: ['includes', 'notIncludes', 'isEmpty', 'isNotEmpty'] } },
|
|
8885
|
+
{ value: 'date', icon: 'ri-calendar-2-line', detail: 'Selector de fecha o mes', label: 'Fecha', properties: ['monthMode', 'monthDay', 'minDate', 'maxDate'], visibility: { outputType: 'string yyyy-MM-dd', operators: ['equals', 'notEquals', 'greaterThan', 'lessThan', 'isEmpty', 'isNotEmpty'] } },
|
|
8886
|
+
{ value: 'time', icon: 'ri-timer-2-line', detail: 'Selector de hora', label: 'Hora', properties: ['timeInterval'], visibility: { outputType: 'string HH:mm', operators: ['equals', 'notEquals', 'greaterThan', 'lessThan', 'isEmpty', 'isNotEmpty'] } },
|
|
8887
|
+
{ value: 'radio', icon: 'ri-radio-button-line', detail: 'Seleccion unica entre opciones', label: 'Radio', properties: ['options'], visibility: { outputType: 'string', operators: ['equals', 'notEquals', 'includes', 'notIncludes', 'isEmpty', 'isNotEmpty'] } },
|
|
8888
|
+
{ value: 'checkbox', icon: 'ri-checkbox-line', detail: 'Campo booleano tipo check', label: 'Checkbox', properties: ['placeholder'], visibility: { outputType: 'boolean', operators: ['equals', 'notEquals', 'isEmpty', 'isNotEmpty'] } },
|
|
8889
|
+
{ value: 'switch', icon: 'ri-toggle-line', detail: 'Campo booleano tipo switch', label: 'Switch', properties: ['placeholder'], visibility: { outputType: 'boolean', operators: ['equals', 'notEquals', 'isEmpty', 'isNotEmpty'] } },
|
|
8890
|
+
{ value: 'pool', icon: 'ri-bubble-chart-line', detail: 'Seleccion con lista y detalle por item', label: 'Pool de opciones', properties: ['options', 'multyEnabled', 'poolEnabledListView', 'poolTitle'], visibility: { outputType: 'selectedDetailed[]', operators: ['isEmpty', 'isNotEmpty'] } },
|
|
8891
|
+
{ value: 'file', icon: 'ri-attachment-line', detail: 'Carga de archivos', label: 'Archivo', properties: ['multyEnabled', 'fileTypes', 'iaValidation', 'iaValidationPrompt'], visibility: { outputType: 'UicFileInputValue[]', operators: ['isEmpty', 'isNotEmpty'] } },
|
|
8892
|
+
{ value: 'searcher', icon: 'ri-seo-line', detail: 'Buscador con fuente de datos externa', label: 'Buscador', properties: ['placeholder', 'optionsSource.key', 'optionsSource.idField', 'optionsSource.textField', 'optionsSource.textTemplate', 'optionsSource.dependsOn', 'optionsSource.paramName'], visibility: { outputType: 'object', operators: ['isEmpty', 'isNotEmpty'] } },
|
|
8893
|
+
{ value: 'slider', icon: 'ri-equalizer-2-line', detail: 'Control deslizante continuo', label: 'Deslizador', properties: ['min', 'max', 'sliderInterval', 'sliderMarks'], visibility: { outputType: 'number', operators: ['equals', 'notEquals', 'greaterThan', 'lessThan', 'isEmpty', 'isNotEmpty'] } },
|
|
8894
|
+
{ value: 'repeater', icon: 'ri-stack-line', detail: 'Grupo de campos repetibles', label: 'Repetidor', properties: ['repeaterMinItems', 'repeaterMaxItems', 'repeaterAddLabel', 'repeaterRemoveLabel', 'repeaterItemTitle'], visibility: { outputType: 'object[]', operators: ['isEmpty', 'isNotEmpty'] } }
|
|
8491
8895
|
];
|
|
8492
8896
|
const BASE_FORM_FIELDS = [
|
|
8493
8897
|
{
|
|
@@ -8698,6 +9102,11 @@ const EXTRA_FORM_FIELDS = [
|
|
|
8698
9102
|
fieldName: 'optionsSource.key',
|
|
8699
9103
|
operator: 'notEquals',
|
|
8700
9104
|
value: null
|
|
9105
|
+
},
|
|
9106
|
+
{
|
|
9107
|
+
fieldName: 'optionsSource.dependsOn',
|
|
9108
|
+
operator: 'notEquals',
|
|
9109
|
+
value: ''
|
|
8701
9110
|
}
|
|
8702
9111
|
]
|
|
8703
9112
|
},
|
|
@@ -8922,6 +9331,42 @@ const EXTRA_FORM_FIELDS = [
|
|
|
8922
9331
|
internalIcon: 'ri-folder-add-line',
|
|
8923
9332
|
tip: 'form_builder.extra.multyEnabled_tip',
|
|
8924
9333
|
type: 'checkbox'
|
|
9334
|
+
},
|
|
9335
|
+
{
|
|
9336
|
+
name: 'repeaterMinItems',
|
|
9337
|
+
label: 'form_builder.extra.repeaterMinItems',
|
|
9338
|
+
internalIcon: 'ri-skip-down-line',
|
|
9339
|
+
tip: 'form_builder.extra.repeaterMinItems_tip',
|
|
9340
|
+
type: 'number',
|
|
9341
|
+
step: 1,
|
|
9342
|
+
min: 0
|
|
9343
|
+
},
|
|
9344
|
+
{
|
|
9345
|
+
name: 'repeaterMaxItems',
|
|
9346
|
+
label: 'form_builder.extra.repeaterMaxItems',
|
|
9347
|
+
internalIcon: 'ri-skip-up-line',
|
|
9348
|
+
tip: 'form_builder.extra.repeaterMaxItems_tip',
|
|
9349
|
+
type: 'number',
|
|
9350
|
+
step: 1,
|
|
9351
|
+
min: 1
|
|
9352
|
+
},
|
|
9353
|
+
{
|
|
9354
|
+
name: 'repeaterAddLabel',
|
|
9355
|
+
label: 'form_builder.extra.repeaterAddLabel',
|
|
9356
|
+
internalIcon: 'ri-add-circle-line',
|
|
9357
|
+
type: 'text'
|
|
9358
|
+
},
|
|
9359
|
+
{
|
|
9360
|
+
name: 'repeaterRemoveLabel',
|
|
9361
|
+
label: 'form_builder.extra.repeaterRemoveLabel',
|
|
9362
|
+
internalIcon: 'ri-delete-bin-line',
|
|
9363
|
+
type: 'text'
|
|
9364
|
+
},
|
|
9365
|
+
{
|
|
9366
|
+
name: 'repeaterItemTitle',
|
|
9367
|
+
label: 'form_builder.extra.repeaterItemTitle',
|
|
9368
|
+
internalIcon: 'ri-price-tag-2-line',
|
|
9369
|
+
type: 'text'
|
|
8925
9370
|
}
|
|
8926
9371
|
];
|
|
8927
9372
|
const BRANCH_FORM_FIELDS = [
|
|
@@ -8938,12 +9383,7 @@ const BRANCH_FORM_FIELDS = [
|
|
|
8938
9383
|
label: 'form_builder.field_editor.operator',
|
|
8939
9384
|
type: 'select',
|
|
8940
9385
|
options: [
|
|
8941
|
-
|
|
8942
|
-
{ id: 'notEquals', text: 'notEquals' },
|
|
8943
|
-
{ id: 'greaterThan', text: 'greaterThan' },
|
|
8944
|
-
{ id: 'lessThan', text: 'lessThan' },
|
|
8945
|
-
{ id: 'includes', text: 'includes' },
|
|
8946
|
-
{ id: 'notIncludes', text: 'notIncludes' }
|
|
9386
|
+
...VISIBILITY_OPERATOR_OPTIONS
|
|
8947
9387
|
],
|
|
8948
9388
|
required: true
|
|
8949
9389
|
},
|
|
@@ -9035,8 +9475,10 @@ class FieldEditorComponent {
|
|
|
9035
9475
|
return !!fieldType && (fieldType.value === 'searcher' || fieldType.properties.includes('options'));
|
|
9036
9476
|
});
|
|
9037
9477
|
hasExternalOptionsSource = computed(() => !!this.localField().optionsSource?.key);
|
|
9478
|
+
isRepeater = computed(() => this.fieldType()?.value === 'repeater');
|
|
9038
9479
|
config = input.required();
|
|
9039
9480
|
focusRequiredField = input(false);
|
|
9481
|
+
isSubField = input(false);
|
|
9040
9482
|
options = input({});
|
|
9041
9483
|
hiddenSections = signal([]);
|
|
9042
9484
|
fieldChange = output();
|
|
@@ -9046,20 +9488,14 @@ class FieldEditorComponent {
|
|
|
9046
9488
|
optionsSourceFields = computed(() => this.buildOptionsSourceFields());
|
|
9047
9489
|
advancedFields = computed(() => (this.buildAdvancedBlocks()));
|
|
9048
9490
|
styleFields = computed(() => (this.buildDesignBlocks()));
|
|
9049
|
-
|
|
9491
|
+
branchDraftValues = signal({});
|
|
9492
|
+
branchFields = computed(() => this.buildBranchFields(this.branchDraftValues()));
|
|
9050
9493
|
initialValues = computed(() => {
|
|
9051
9494
|
const fieldData = this.config().fieldData;
|
|
9052
9495
|
return fieldData ?? {};
|
|
9053
9496
|
});
|
|
9054
9497
|
branchInitialValues = computed(() => {
|
|
9055
|
-
|
|
9056
|
-
if (!firstRule)
|
|
9057
|
-
return {};
|
|
9058
|
-
return {
|
|
9059
|
-
fieldName: firstRule.fieldName ?? null,
|
|
9060
|
-
operator: firstRule.operator ?? null,
|
|
9061
|
-
value: firstRule.value ?? null
|
|
9062
|
-
};
|
|
9498
|
+
return this.branchDraftValues();
|
|
9063
9499
|
});
|
|
9064
9500
|
/*
|
|
9065
9501
|
{
|
|
@@ -9077,6 +9513,7 @@ class FieldEditorComponent {
|
|
|
9077
9513
|
this.localField.set(field);
|
|
9078
9514
|
if (this.currentFieldCode !== config.code) {
|
|
9079
9515
|
this.currentFieldCode = config.code;
|
|
9516
|
+
this.branchDraftValues.set(this.ruleToBranchValues(field.visibilityRules?.[0]));
|
|
9080
9517
|
this.scrollPropertiesToTop();
|
|
9081
9518
|
}
|
|
9082
9519
|
});
|
|
@@ -9089,8 +9526,23 @@ class FieldEditorComponent {
|
|
|
9089
9526
|
}
|
|
9090
9527
|
updateRuleValue(fr) {
|
|
9091
9528
|
const fieldName = fr['fieldName'];
|
|
9092
|
-
const
|
|
9093
|
-
const
|
|
9529
|
+
const previousDraft = this.branchDraftValues();
|
|
9530
|
+
const parentChanged = fieldName !== previousDraft['fieldName'];
|
|
9531
|
+
const selectedOperator = (parentChanged ? null : fr['operator']);
|
|
9532
|
+
const allowedOperators = this.getAllowedVisibilityOperators(this.getDependencyFieldType(fieldName));
|
|
9533
|
+
const operator = selectedOperator && allowedOperators.includes(selectedOperator)
|
|
9534
|
+
? selectedOperator
|
|
9535
|
+
: null;
|
|
9536
|
+
const value = parentChanged || this.isValueLessVisibilityOperator(operator) ? null : fr['value'];
|
|
9537
|
+
const nextDraft = {
|
|
9538
|
+
fieldName: fieldName ?? null,
|
|
9539
|
+
operator,
|
|
9540
|
+
value
|
|
9541
|
+
};
|
|
9542
|
+
this.branchDraftValues.set(nextDraft);
|
|
9543
|
+
if (parentChanged) {
|
|
9544
|
+
this.clearCurrentVisibilityRule();
|
|
9545
|
+
}
|
|
9094
9546
|
// Ignore partial emissions while the dependency form is still incomplete.
|
|
9095
9547
|
if (!fieldName || !operator)
|
|
9096
9548
|
return;
|
|
@@ -9119,6 +9571,7 @@ class FieldEditorComponent {
|
|
|
9119
9571
|
...this.localField(),
|
|
9120
9572
|
visibilityRules: []
|
|
9121
9573
|
};
|
|
9574
|
+
this.branchDraftValues.set({});
|
|
9122
9575
|
this.localField.set(updatedField);
|
|
9123
9576
|
this.fieldChange.emit(updatedField);
|
|
9124
9577
|
}
|
|
@@ -9127,6 +9580,7 @@ class FieldEditorComponent {
|
|
|
9127
9580
|
...this.localField(),
|
|
9128
9581
|
visibilityRules: null
|
|
9129
9582
|
};
|
|
9583
|
+
this.branchDraftValues.set({});
|
|
9130
9584
|
this.localField.set(updatedField);
|
|
9131
9585
|
this.fieldChange.emit(updatedField);
|
|
9132
9586
|
}
|
|
@@ -9211,15 +9665,99 @@ class FieldEditorComponent {
|
|
|
9211
9665
|
}
|
|
9212
9666
|
return field;
|
|
9213
9667
|
}
|
|
9214
|
-
buildBranchFields() {
|
|
9668
|
+
buildBranchFields(values) {
|
|
9669
|
+
const fieldName = values['fieldName'];
|
|
9670
|
+
const dependencyType = this.getDependencyFieldType(fieldName);
|
|
9671
|
+
const allowedOperators = this.getAllowedVisibilityOperators(dependencyType);
|
|
9215
9672
|
return BRANCH_FORM_FIELDS.map(field => ({
|
|
9216
|
-
...field,
|
|
9673
|
+
...this.prepareBranchField(field, fieldName, allowedOperators),
|
|
9217
9674
|
label: this.translateService.translate(field.label ?? ''),
|
|
9218
9675
|
placeholder: field.placeholder ? this.translateService.translate(field.placeholder) : this.translateService.translate(field.label ?? '')
|
|
9219
9676
|
}));
|
|
9220
9677
|
}
|
|
9678
|
+
prepareBranchField(field, fieldName, allowedOperators) {
|
|
9679
|
+
if (field.name === 'operator') {
|
|
9680
|
+
return {
|
|
9681
|
+
...field,
|
|
9682
|
+
options: VISIBILITY_OPERATOR_OPTIONS
|
|
9683
|
+
.filter(option => allowedOperators.includes(option.id))
|
|
9684
|
+
.map(option => ({
|
|
9685
|
+
...option,
|
|
9686
|
+
text: this.translateService.translate(`form_builder.visibility_operators.${option.id}`)
|
|
9687
|
+
})),
|
|
9688
|
+
visibilityRules: [
|
|
9689
|
+
{ fieldName: 'fieldName', operator: 'notEquals', value: null },
|
|
9690
|
+
{ fieldName: 'fieldName', operator: 'notEquals', value: '' }
|
|
9691
|
+
]
|
|
9692
|
+
};
|
|
9693
|
+
}
|
|
9694
|
+
if (field.name === 'value') {
|
|
9695
|
+
const valueField = {
|
|
9696
|
+
...field,
|
|
9697
|
+
visibilityRules: [
|
|
9698
|
+
{ fieldName: 'fieldName', operator: 'notEquals', value: null },
|
|
9699
|
+
{ fieldName: 'fieldName', operator: 'notEquals', value: '' },
|
|
9700
|
+
{ fieldName: 'operator', operator: 'notEquals', value: null },
|
|
9701
|
+
{ fieldName: 'operator', operator: 'notEquals', value: '' },
|
|
9702
|
+
{ fieldName: 'operator', operator: 'notEquals', value: 'isEmpty' },
|
|
9703
|
+
{ fieldName: 'operator', operator: 'notEquals', value: 'isNotEmpty' }
|
|
9704
|
+
],
|
|
9705
|
+
type: this.getBranchValueFieldType(fieldName)
|
|
9706
|
+
};
|
|
9707
|
+
if (valueField.type === 'select') {
|
|
9708
|
+
valueField.options = [
|
|
9709
|
+
{ id: 'true', text: 'true' },
|
|
9710
|
+
{ id: 'false', text: 'false' }
|
|
9711
|
+
];
|
|
9712
|
+
}
|
|
9713
|
+
return valueField;
|
|
9714
|
+
}
|
|
9715
|
+
return field;
|
|
9716
|
+
}
|
|
9717
|
+
getAllowedVisibilityOperators(fieldType) {
|
|
9718
|
+
return FIELDS_CONFIG.find(field => field.value === fieldType)?.visibility.operators ?? [];
|
|
9719
|
+
}
|
|
9720
|
+
getDependencyFieldType(fieldName) {
|
|
9721
|
+
const option = this.options()['fieldName']?.find(item => item.id === fieldName);
|
|
9722
|
+
const type = option?.fieldType;
|
|
9723
|
+
return FIELDS_CONFIG.some(field => field.value === type) ? type : null;
|
|
9724
|
+
}
|
|
9725
|
+
getBranchValueFieldType(fieldName) {
|
|
9726
|
+
const dependencyType = this.getDependencyFieldType(fieldName);
|
|
9727
|
+
if (dependencyType === 'number' || dependencyType === 'slider')
|
|
9728
|
+
return 'number';
|
|
9729
|
+
if (dependencyType === 'date')
|
|
9730
|
+
return 'date';
|
|
9731
|
+
if (dependencyType === 'time')
|
|
9732
|
+
return 'time';
|
|
9733
|
+
if (dependencyType === 'checkbox' || dependencyType === 'switch')
|
|
9734
|
+
return 'select';
|
|
9735
|
+
return 'text';
|
|
9736
|
+
}
|
|
9737
|
+
ruleToBranchValues(rule) {
|
|
9738
|
+
if (!rule)
|
|
9739
|
+
return {};
|
|
9740
|
+
return {
|
|
9741
|
+
fieldName: rule.fieldName ?? null,
|
|
9742
|
+
operator: rule.operator ?? null,
|
|
9743
|
+
value: rule.value ?? null
|
|
9744
|
+
};
|
|
9745
|
+
}
|
|
9746
|
+
clearCurrentVisibilityRule() {
|
|
9747
|
+
if (!this.localField().visibilityRules?.length)
|
|
9748
|
+
return;
|
|
9749
|
+
const updatedField = {
|
|
9750
|
+
...this.localField(),
|
|
9751
|
+
visibilityRules: []
|
|
9752
|
+
};
|
|
9753
|
+
this.localField.set(updatedField);
|
|
9754
|
+
this.fieldChange.emit(updatedField);
|
|
9755
|
+
}
|
|
9756
|
+
isValueLessVisibilityOperator(operator) {
|
|
9757
|
+
return operator === 'isEmpty' || operator === 'isNotEmpty';
|
|
9758
|
+
}
|
|
9221
9759
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FieldEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9222
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: FieldEditorComponent, isStandalone: true, selector: "lib-field-editor", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, focusRequiredField: { classPropertyName: "focusRequiredField", publicName: "focusRequiredField", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fieldChange: "fieldChange" }, ngImport: i0, template: "<div class=\"props-title\">{{'form_builder.field_editor.basic' | uicTranslate}} <i (click)=\"toggleSection('basic')\" class=\"{{hiddenSections().includes('basic') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('basic')\">\n <ui-form-wrapper\n [fields]=\"requiredFields\" \n [initialValues]=\"initialValues()\"\n [focusFieldName]=\"focusRequiredField() ? 'label' : null\"\n [focusFieldTrigger]=\"focusRequiredField() ? config().code : null\"\n [cols]=\"1\" \n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n @if (hasOptionsSourceConfig()) {\n <ui-form-wrapper\n [fields]=\"optionsSourceFields()\"\n [initialValues]=\"initialValues()\"\n [externalData]=\"options()\"\n [cols]=\"1\"\n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n @if (hasOptions() && !hasExternalOptionsSource()) {\n <ui-field-options-editor [options]=\"localField().options ?? []\" (optionsChange)=\"updateOptions($event)\"></ui-field-options-editor>\n }\n }\n</div>\n\n<div class=\"props-title\">{{'form_builder.field_editor.advanced' | uicTranslate}} <i (click)=\"toggleSection('advanced')\" class=\"{{hiddenSections().includes('advanced') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('advanced')\">\n <ui-form-wrapper\n [fields]=\"advancedFields()\" \n [initialValues]=\"initialValues()\"\n [cols]=\"1\" \n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n</div>\n\n<div class=\"props-title\">{{'form_builder.field_editor.style' | uicTranslate}} <i (click)=\"toggleSection('style')\" class=\"{{hiddenSections().includes('style') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('style')\">\n <ui-form-wrapper\n [fields]=\"styleFields()\" \n [initialValues]=\"initialValues()\"\n [cols]=\"1\" \n (formChange)=\"updateFieldValues($event)\"> \n </ui-form-wrapper>\n</div>\n\n<div class=\"props-title\">{{'form_builder.field_editor.dependency_title' | uicTranslate}} <i (click)=\"toggleSection('dependency')\" class=\"{{hiddenSections().includes('dependency') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('dependency')\">\n
|
|
9760
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: FieldEditorComponent, isStandalone: true, selector: "lib-field-editor", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, focusRequiredField: { classPropertyName: "focusRequiredField", publicName: "focusRequiredField", isSignal: true, isRequired: false, transformFunction: null }, isSubField: { classPropertyName: "isSubField", publicName: "isSubField", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fieldChange: "fieldChange" }, ngImport: i0, template: "<div class=\"props-title\">{{'form_builder.field_editor.basic' | uicTranslate}} <i (click)=\"toggleSection('basic')\" class=\"{{hiddenSections().includes('basic') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('basic')\">\r\n <ui-form-wrapper\r\n [fields]=\"requiredFields\" \r\n [initialValues]=\"initialValues()\"\r\n [focusFieldName]=\"focusRequiredField() ? 'label' : null\"\r\n [focusFieldTrigger]=\"focusRequiredField() ? config().code : null\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n @if (hasOptionsSourceConfig()) {\r\n <ui-form-wrapper\r\n [fields]=\"optionsSourceFields()\"\r\n [initialValues]=\"initialValues()\"\r\n [externalData]=\"options()\"\r\n [cols]=\"1\"\r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n @if (hasOptions() && !hasExternalOptionsSource()) {\r\n <ui-field-options-editor [options]=\"localField().options ?? []\" (optionsChange)=\"updateOptions($event)\"></ui-field-options-editor>\r\n }\r\n }\r\n</div>\r\n\r\n<div class=\"props-title\">{{'form_builder.field_editor.advanced' | uicTranslate}} <i (click)=\"toggleSection('advanced')\" class=\"{{hiddenSections().includes('advanced') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('advanced')\">\r\n <ui-form-wrapper\r\n [fields]=\"advancedFields()\" \r\n [initialValues]=\"initialValues()\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n</div>\r\n\r\n<div class=\"props-title\">{{'form_builder.field_editor.style' | uicTranslate}} <i (click)=\"toggleSection('style')\" class=\"{{hiddenSections().includes('style') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('style')\">\r\n <ui-form-wrapper\r\n [fields]=\"styleFields()\" \r\n [initialValues]=\"initialValues()\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateFieldValues($event)\"> \r\n </ui-form-wrapper>\r\n</div>\r\n\r\n@if (!isSubField()) {\r\n <div class=\"props-title\">{{'form_builder.field_editor.dependency_title' | uicTranslate}} <i (click)=\"toggleSection('dependency')\" class=\"{{hiddenSections().includes('dependency') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n <div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('dependency')\">\r\n @if (localField().visibilityRules ) {\r\n <p>{{'form_builder.field_editor.dependency_description' | uicTranslate}}</p>\r\n <ui-form-wrapper\r\n [fields]=\"branchFields()\" \r\n [initialValues]=\"branchInitialValues()\"\r\n [externalData]=\"options()\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateRuleValue($event)\">\r\n </ui-form-wrapper>\r\n <ui-button color=\"black\" size=\"s\" (click)=\"removeRule()\">{{'form_builder.field_editor.remove_relation' | uicTranslate}}</ui-button>\r\n }@else {\r\n <ui-button color=\"black\" size=\"s\" (click)=\"addRule()\">{{'form_builder.field_editor.add_relation' | uicTranslate}}</ui-button>\r\n }\r\n </div>\r\n}\r\n", styles: [".hidden{display:none}.props-title{font-size:14px;font-weight:600;margin-bottom:8px;background:var(--grey-200);padding:5px;border-radius:5px;display:flex;justify-content:space-between}.props-title i{cursor:pointer}.props-inputs{padding-left:20px;margin-bottom:10px}p{font-size:14px;margin:10px 0;color:var(--yellow-800)}\n"], dependencies: [{ kind: "component", type: UicFormWrapperComponent, selector: "ui-form-wrapper", inputs: ["schema", "fields", "cols", "externalData", "selectOptionsResolver", "loading", "disabled", "showButtons", "fillSelects", "initialValues", "focusFieldName", "focusFieldTrigger", "fileUidResolverFn"], outputs: ["formSubmit", "formChange", "optionsSourceError"] }, { kind: "component", type: UicButtonComponent, selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "pipe", type: UicTranslatePipe, name: "uicTranslate" }, { kind: "component", type: UicFieldOptionsEditorComponent, selector: "ui-field-options-editor", inputs: ["options"], outputs: ["optionsChange"] }] });
|
|
9223
9761
|
}
|
|
9224
9762
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FieldEditorComponent, decorators: [{
|
|
9225
9763
|
type: Component,
|
|
@@ -9228,21 +9766,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
9228
9766
|
UicButtonComponent,
|
|
9229
9767
|
UicTranslatePipe,
|
|
9230
9768
|
UicFieldOptionsEditorComponent
|
|
9231
|
-
], template: "<div class=\"props-title\">{{'form_builder.field_editor.basic' | uicTranslate}} <i (click)=\"toggleSection('basic')\" class=\"{{hiddenSections().includes('basic') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('basic')\">\n <ui-form-wrapper\n [fields]=\"requiredFields\" \n [initialValues]=\"initialValues()\"\n [focusFieldName]=\"focusRequiredField() ? 'label' : null\"\n [focusFieldTrigger]=\"focusRequiredField() ? config().code : null\"\n [cols]=\"1\" \n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n @if (hasOptionsSourceConfig()) {\n <ui-form-wrapper\n [fields]=\"optionsSourceFields()\"\n [initialValues]=\"initialValues()\"\n [externalData]=\"options()\"\n [cols]=\"1\"\n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n @if (hasOptions() && !hasExternalOptionsSource()) {\n <ui-field-options-editor [options]=\"localField().options ?? []\" (optionsChange)=\"updateOptions($event)\"></ui-field-options-editor>\n }\n }\n</div>\n\n<div class=\"props-title\">{{'form_builder.field_editor.advanced' | uicTranslate}} <i (click)=\"toggleSection('advanced')\" class=\"{{hiddenSections().includes('advanced') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('advanced')\">\n <ui-form-wrapper\n [fields]=\"advancedFields()\" \n [initialValues]=\"initialValues()\"\n [cols]=\"1\" \n (formChange)=\"updateFieldValues($event)\">\n </ui-form-wrapper>\n</div>\n\n<div class=\"props-title\">{{'form_builder.field_editor.style' | uicTranslate}} <i (click)=\"toggleSection('style')\" class=\"{{hiddenSections().includes('style') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('style')\">\n <ui-form-wrapper\n [fields]=\"styleFields()\" \n [initialValues]=\"initialValues()\"\n [cols]=\"1\" \n (formChange)=\"updateFieldValues($event)\"> \n </ui-form-wrapper>\n</div>\n\n<div class=\"props-title\">{{'form_builder.field_editor.dependency_title' | uicTranslate}} <i (click)=\"toggleSection('dependency')\" class=\"{{hiddenSections().includes('dependency') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('dependency')\">\n
|
|
9769
|
+
], template: "<div class=\"props-title\">{{'form_builder.field_editor.basic' | uicTranslate}} <i (click)=\"toggleSection('basic')\" class=\"{{hiddenSections().includes('basic') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('basic')\">\r\n <ui-form-wrapper\r\n [fields]=\"requiredFields\" \r\n [initialValues]=\"initialValues()\"\r\n [focusFieldName]=\"focusRequiredField() ? 'label' : null\"\r\n [focusFieldTrigger]=\"focusRequiredField() ? config().code : null\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n @if (hasOptionsSourceConfig()) {\r\n <ui-form-wrapper\r\n [fields]=\"optionsSourceFields()\"\r\n [initialValues]=\"initialValues()\"\r\n [externalData]=\"options()\"\r\n [cols]=\"1\"\r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n @if (hasOptions() && !hasExternalOptionsSource()) {\r\n <ui-field-options-editor [options]=\"localField().options ?? []\" (optionsChange)=\"updateOptions($event)\"></ui-field-options-editor>\r\n }\r\n }\r\n</div>\r\n\r\n<div class=\"props-title\">{{'form_builder.field_editor.advanced' | uicTranslate}} <i (click)=\"toggleSection('advanced')\" class=\"{{hiddenSections().includes('advanced') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('advanced')\">\r\n <ui-form-wrapper\r\n [fields]=\"advancedFields()\" \r\n [initialValues]=\"initialValues()\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateFieldValues($event)\">\r\n </ui-form-wrapper>\r\n</div>\r\n\r\n<div class=\"props-title\">{{'form_builder.field_editor.style' | uicTranslate}} <i (click)=\"toggleSection('style')\" class=\"{{hiddenSections().includes('style') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n<div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('style')\">\r\n <ui-form-wrapper\r\n [fields]=\"styleFields()\" \r\n [initialValues]=\"initialValues()\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateFieldValues($event)\"> \r\n </ui-form-wrapper>\r\n</div>\r\n\r\n@if (!isSubField()) {\r\n <div class=\"props-title\">{{'form_builder.field_editor.dependency_title' | uicTranslate}} <i (click)=\"toggleSection('dependency')\" class=\"{{hiddenSections().includes('dependency') ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'}}\"></i> </div>\r\n <div class=\"props-inputs\" [class.hidden]=\"hiddenSections().includes('dependency')\">\r\n @if (localField().visibilityRules ) {\r\n <p>{{'form_builder.field_editor.dependency_description' | uicTranslate}}</p>\r\n <ui-form-wrapper\r\n [fields]=\"branchFields()\" \r\n [initialValues]=\"branchInitialValues()\"\r\n [externalData]=\"options()\"\r\n [cols]=\"1\" \r\n (formChange)=\"updateRuleValue($event)\">\r\n </ui-form-wrapper>\r\n <ui-button color=\"black\" size=\"s\" (click)=\"removeRule()\">{{'form_builder.field_editor.remove_relation' | uicTranslate}}</ui-button>\r\n }@else {\r\n <ui-button color=\"black\" size=\"s\" (click)=\"addRule()\">{{'form_builder.field_editor.add_relation' | uicTranslate}}</ui-button>\r\n }\r\n </div>\r\n}\r\n", styles: [".hidden{display:none}.props-title{font-size:14px;font-weight:600;margin-bottom:8px;background:var(--grey-200);padding:5px;border-radius:5px;display:flex;justify-content:space-between}.props-title i{cursor:pointer}.props-inputs{padding-left:20px;margin-bottom:10px}p{font-size:14px;margin:10px 0;color:var(--yellow-800)}\n"] }]
|
|
9232
9770
|
}], ctorParameters: () => [] });
|
|
9233
9771
|
|
|
9234
9772
|
class FieldTypeSelectorComponent {
|
|
9235
|
-
|
|
9773
|
+
excludeTypes = input([]);
|
|
9774
|
+
types = computed(() => FIELDS_CONFIG.filter(f => !this.excludeTypes().includes(f.value)));
|
|
9236
9775
|
selectType = output();
|
|
9237
9776
|
addField(type) {
|
|
9238
9777
|
this.selectType.emit(type);
|
|
9239
9778
|
}
|
|
9240
9779
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FieldTypeSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9241
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: FieldTypeSelectorComponent, isStandalone: true, selector: "lib-field-type-selector", outputs: { selectType: "selectType" }, ngImport: i0, template: "@for (type of types; track $index) {\r\n <div [uiTooltip]=\"type.label | uicTranslate\" (click)=\"addField(type)\" class=\"field-type\">\n <i [class]=\"type.icon\"></i>\r\n
|
|
9780
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: FieldTypeSelectorComponent, isStandalone: true, selector: "lib-field-type-selector", inputs: { excludeTypes: { classPropertyName: "excludeTypes", publicName: "excludeTypes", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectType: "selectType" }, ngImport: i0, template: "@for (type of types(); track $index) {\r\n <div [uiTooltip]=\"type.label | uicTranslate\" (click)=\"addField(type)\" class=\"field-type\">\r\n <i [class]=\"type.icon\"></i>\r\n </div>\r\n}\r\n", styles: [":host{display:flex;overflow:auto;gap:5px}.field-type{border:solid 1px var(--grey-300);border-radius:5px;padding:5px;display:flex;align-items:center;background-color:#fff;cursor:pointer;gap:5px}.field-type b{font-weight:400}.field-type p{font-size:12px;color:var(--grey-400)}\n"], dependencies: [{ kind: "directive", type: UicToolTipDirective, selector: "[uiTooltip]", inputs: ["uiTooltip"] }, { kind: "pipe", type: UicTranslatePipe, name: "uicTranslate" }] });
|
|
9242
9781
|
}
|
|
9243
9782
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FieldTypeSelectorComponent, decorators: [{
|
|
9244
9783
|
type: Component,
|
|
9245
|
-
args: [{ selector: 'lib-field-type-selector', imports: [UicToolTipDirective, UicTranslatePipe], template: "@for (type of types; track $index) {\r\n <div [uiTooltip]=\"type.label | uicTranslate\" (click)=\"addField(type)\" class=\"field-type\">\n <i [class]=\"type.icon\"></i>\r\n
|
|
9784
|
+
args: [{ selector: 'lib-field-type-selector', imports: [UicToolTipDirective, UicTranslatePipe], template: "@for (type of types(); track $index) {\r\n <div [uiTooltip]=\"type.label | uicTranslate\" (click)=\"addField(type)\" class=\"field-type\">\r\n <i [class]=\"type.icon\"></i>\r\n </div>\r\n}\r\n", styles: [":host{display:flex;overflow:auto;gap:5px}.field-type{border:solid 1px var(--grey-300);border-radius:5px;padding:5px;display:flex;align-items:center;background-color:#fff;cursor:pointer;gap:5px}.field-type b{font-weight:400}.field-type p{font-size:12px;color:var(--grey-400)}\n"] }]
|
|
9246
9785
|
}] });
|
|
9247
9786
|
|
|
9248
9787
|
class BlockEditorComponent {
|
|
@@ -9257,9 +9796,81 @@ class BlockEditorComponent {
|
|
|
9257
9796
|
addFieldRequest = output();
|
|
9258
9797
|
deleteBlock = output();
|
|
9259
9798
|
notifySelectedField = output();
|
|
9799
|
+
notifySelectedSubField = output();
|
|
9260
9800
|
selectedFieldId = null;
|
|
9801
|
+
selectedSubFieldCode = null;
|
|
9802
|
+
visibilityParentFieldCodes = new Set();
|
|
9803
|
+
excludeSubFieldTypes = ['repeater'];
|
|
9804
|
+
expandedRepeaters = signal(new Set());
|
|
9805
|
+
isRepeaterExpanded(code) {
|
|
9806
|
+
return this.expandedRepeaters().has(code);
|
|
9807
|
+
}
|
|
9808
|
+
toggleRepeater(code, event) {
|
|
9809
|
+
event.stopPropagation();
|
|
9810
|
+
const next = new Set(this.expandedRepeaters());
|
|
9811
|
+
next.has(code) ? next.delete(code) : next.add(code);
|
|
9812
|
+
this.expandedRepeaters.set(next);
|
|
9813
|
+
}
|
|
9814
|
+
isRepeaterParentSelected(field) {
|
|
9815
|
+
if (this.selectedFieldId === field.code)
|
|
9816
|
+
return true;
|
|
9817
|
+
if (field.fieldData.type !== 'repeater')
|
|
9818
|
+
return false;
|
|
9819
|
+
return !!(this.selectedSubFieldCode && field.repeaterSubFields?.some(sf => sf.code === this.selectedSubFieldCode));
|
|
9820
|
+
}
|
|
9261
9821
|
selectField(field) {
|
|
9262
9822
|
this.notifySelectedField.emit(field);
|
|
9823
|
+
this.notifySelectedSubField.emit(null);
|
|
9824
|
+
}
|
|
9825
|
+
onSelectSubField(parentCode, subField, event) {
|
|
9826
|
+
event.stopPropagation();
|
|
9827
|
+
this.notifySelectedSubField.emit({ parentCode, subField });
|
|
9828
|
+
}
|
|
9829
|
+
addSubField(parentCode, type) {
|
|
9830
|
+
const parentField = this.block().fields.find(f => f.code === parentCode);
|
|
9831
|
+
const existing = parentField?.repeaterSubFields ?? [];
|
|
9832
|
+
const sfCode = this.generateSubFieldCode(existing);
|
|
9833
|
+
const newSf = {
|
|
9834
|
+
code: sfCode,
|
|
9835
|
+
order: existing.length + 1,
|
|
9836
|
+
type: type.value,
|
|
9837
|
+
field: type,
|
|
9838
|
+
fieldData: { name: sfCode, label: 'Nuevo campo', type: type.value }
|
|
9839
|
+
};
|
|
9840
|
+
this.updateSubFields(parentCode, [...existing, newSf]);
|
|
9841
|
+
this.notifySelectedSubField.emit({ parentCode, subField: newSf });
|
|
9842
|
+
}
|
|
9843
|
+
deleteSubField(parentCode, sfCode, event) {
|
|
9844
|
+
event.stopPropagation();
|
|
9845
|
+
const parentField = this.block().fields.find(f => f.code === parentCode);
|
|
9846
|
+
const updated = (parentField?.repeaterSubFields ?? []).filter(sf => sf.code !== sfCode);
|
|
9847
|
+
this.updateSubFields(parentCode, updated);
|
|
9848
|
+
if (this.selectedSubFieldCode === sfCode) {
|
|
9849
|
+
this.notifySelectedSubField.emit(null);
|
|
9850
|
+
}
|
|
9851
|
+
}
|
|
9852
|
+
reorderSubFields(parentCode, event) {
|
|
9853
|
+
if (event.previousIndex === event.currentIndex)
|
|
9854
|
+
return;
|
|
9855
|
+
const parentField = this.block().fields.find(f => f.code === parentCode);
|
|
9856
|
+
const next = [...(parentField?.repeaterSubFields ?? [])];
|
|
9857
|
+
moveItemInArray(next, event.previousIndex, event.currentIndex);
|
|
9858
|
+
this.updateSubFields(parentCode, next);
|
|
9859
|
+
}
|
|
9860
|
+
updateSubFields(parentCode, subFields) {
|
|
9861
|
+
this.blockChange.emit({
|
|
9862
|
+
...this.block(),
|
|
9863
|
+
fields: this.block().fields.map(f => f.code !== parentCode ? f : { ...f, repeaterSubFields: subFields })
|
|
9864
|
+
});
|
|
9865
|
+
}
|
|
9866
|
+
generateSubFieldCode(existing) {
|
|
9867
|
+
const max = existing.reduce((m, sf) => {
|
|
9868
|
+
if (!sf.code.startsWith('sf_'))
|
|
9869
|
+
return m;
|
|
9870
|
+
const n = parseInt(sf.code.slice(3), 10);
|
|
9871
|
+
return isNaN(n) ? m : Math.max(m, n);
|
|
9872
|
+
}, 0);
|
|
9873
|
+
return `sf_${max + 1}`;
|
|
9263
9874
|
}
|
|
9264
9875
|
changeTitle(newTitle) {
|
|
9265
9876
|
this.blockChange.emit({ ...this.block(), title: newTitle });
|
|
@@ -9270,13 +9881,27 @@ class BlockEditorComponent {
|
|
|
9270
9881
|
addField(newFieldType) {
|
|
9271
9882
|
this.addFieldRequest.emit(newFieldType);
|
|
9272
9883
|
}
|
|
9884
|
+
requestDeleteBlock(e) {
|
|
9885
|
+
e.stopPropagation();
|
|
9886
|
+
if (this.isBlockVisibilityParent())
|
|
9887
|
+
return;
|
|
9888
|
+
this.deleteBlock.emit(this.block().code);
|
|
9889
|
+
}
|
|
9273
9890
|
deleteField(fieldCode, e) {
|
|
9274
9891
|
e.stopPropagation();
|
|
9892
|
+
if (this.isVisibilityParent(fieldCode))
|
|
9893
|
+
return;
|
|
9275
9894
|
this.blockChange.emit({ ...this.block(), fields: this.block().fields.filter(f => f.code !== fieldCode) });
|
|
9276
9895
|
if (this.selectedFieldId === fieldCode) {
|
|
9277
9896
|
this.notifySelectedField.emit(null);
|
|
9278
9897
|
}
|
|
9279
9898
|
}
|
|
9899
|
+
isVisibilityParent(fieldCode) {
|
|
9900
|
+
return this.visibilityParentFieldCodes.has(fieldCode);
|
|
9901
|
+
}
|
|
9902
|
+
isBlockVisibilityParent() {
|
|
9903
|
+
return this.block().fields.some(field => this.isVisibilityParent(field.code));
|
|
9904
|
+
}
|
|
9280
9905
|
reorderFields(event) {
|
|
9281
9906
|
if (event.previousIndex === event.currentIndex)
|
|
9282
9907
|
return;
|
|
@@ -9285,7 +9910,7 @@ class BlockEditorComponent {
|
|
|
9285
9910
|
this.blockChange.emit({ ...this.block(), fields: nextFields });
|
|
9286
9911
|
}
|
|
9287
9912
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BlockEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9288
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: BlockEditorComponent, isStandalone: true, selector: "lib-block-editor", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, selectedFieldId: { classPropertyName: "selectedFieldId", publicName: "selectedFieldId", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { blockChange: "blockChange", addFieldRequest: "addFieldRequest", deleteBlock: "deleteBlock", notifySelectedField: "notifySelectedField" }, ngImport: i0, template: "<div class=\"form-block-card\">\n <div class=\"form-block-card-header\">\n <div>\n <input [placeholder]=\"'form_builder.block_title' | uicTranslate\" [ngModel]=\"block().title\" (ngModelChange)=\"changeTitle($event)\">\n <input [placeholder]=\"'form_builder.block_subtitle' | uicTranslate\" [ngModel]=\"block().subtitle\" (ngModelChange)=\"changeSubtitle($event)\">\n </div>\n <ui-button [uiTooltip]=\"'form_builder.delete_block' | uicTranslate\" (click)=\"deleteBlock.emit(block().code)\" size=\"s\" icon=\"ri-delete-bin-line\" color=\"red\" type=\"ghost\" [iconOnly]=\"true\"></ui-button>\n </div>\n <div\n class=\"form-block-card-body\"\n cdkDropList\n [cdkDropListData]=\"block().fields\"\n (cdkDropListDropped)=\"reorderFields($event)\">\n \n <!-- FIELDS -->\n @for(edtField of block().fields; track edtField.code; let i = $index) {\n <div\n class=\"xfield-card\"\n cdkDrag\n [class.selected-field]=\"selectedFieldId === edtField.code\"\n (click)=\"selectField(edtField)\">\n <i class=\"ri-draggable field-drag-handle\" cdkDragHandle></i>\n\n <div class=\"xfield-card-icon\">\n <i [class]=\"edtField.field?.icon ?? ''\"></i> \n </div>\n <div class=\"xfield-card-body\">\n <b> {{edtField.fieldData.label}} \n @if(edtField.fieldData.visibilityRules) {\n <i class=\"branched-field ri-git-merge-line\"></i> \n <span class=\"vs-rule\"> {{edtField.fieldData.visibilityRules[0]?.fieldLabel ?? edtField.fieldData.visibilityRules[0]?.fieldName ?? '-'}} </span>\n }\n </b>\n <p> {{edtField.field?.label ?? edtField.type ?? edtField.fieldData.type}} </p>\n </div>\n <div class=\"xfield-card-actions\">\n <ui-button (click)=\"deleteField(edtField.code, $event)\" size=\"s\" icon=\"ri-delete-bin-line\" color=\"red\" type=\"ghost\" [iconOnly]=\"true\"></ui-button>\n </div>\n </div>\n\n }\n\n </div>\n <div class=\"new-field\">\n {{'form_builder.add_new_field' | uicTranslate}}\n <lib-field-type-selector (selectType)=\"addField($event)\"></lib-field-type-selector>\n </div>\n</div>\n", styles: [".form-block-card{border:solid 1px var(--blue-500);border-radius:5px;overflow:hidden}.form-block-card-header{display:flex;gap:5px;align-items:center;background-color:#fff;padding:10px;border-bottom:solid 1px var(--grey-300)}.form-block-card-header>div{flex:1 1;gap:4px;display:flex;flex-direction:column}.form-block-card-header>div input{border:solid 1px var(--grey-100);padding:3px 6px;border-radius:5px}.form-block-card-header>div input:focus{border:solid 1px var(--primary-500);outline:none}.form-block-card-body{padding:15px;display:flex;flex-direction:column;background-color:var(--grey-50);gap:10px}.xfield-card{background-color:#fff;border-radius:5px;padding:10px;gap:10px;display:flex;align-items:center;border:solid 2px var(--grey-200);cursor:pointer;transition:border-color .3s ease}.xfield-card:hover{border-color:var(--grey-300)}.xfield-card-icon{display:flex;justify-content:center;align-items:center;border-radius:5px;width:30px;height:30px;font-size:20px;background-color:var(--grey-300);color:var(--grey-600)}.xfield-card-body{flex:1 1}.xfield-card-body b{display:flex;align-items:center;gap:5px}.xfield-card-body p{color:var(--grey-400);font-size:12px}.field-drag-handle{cursor:grab;color:var(--grey-400);transition:color .2s ease}.field-drag-handle:active{cursor:grabbing}.xfield-card:hover .field-drag-handle{color:var(--grey-600)}.cdk-drag-preview{box-sizing:border-box;border-radius:5px;box-shadow:0 6px 12px #0000002e}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.form-block-card-body.cdk-drop-list-dragging .xfield-card:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.branched-field{color:var(--yellow-600)}.selected-field,.selected-field:hover{border-color:var(--primary-500)}.new-field{border-top:solid 1px var(--grey-300);padding:10px;background-color:#fff;display:flex;flex-direction:column;gap:5px;font-size:14px}.vs-rule{font-size:12px;color:var(--grey-600)}\n"], dependencies: [{ kind: "component", type: UicButtonComponent, selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "directive", type: UicToolTipDirective, selector: "[uiTooltip]", inputs: ["uiTooltip"] }, { kind: "pipe", type: UicTranslatePipe, name: "uicTranslate" }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1$3.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i1$3.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i1$3.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: FieldTypeSelectorComponent, selector: "lib-field-type-selector", outputs: ["selectType"] }] });
|
|
9913
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: BlockEditorComponent, isStandalone: true, selector: "lib-block-editor", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, selectedFieldId: { classPropertyName: "selectedFieldId", publicName: "selectedFieldId", isSignal: false, isRequired: false, transformFunction: null }, selectedSubFieldCode: { classPropertyName: "selectedSubFieldCode", publicName: "selectedSubFieldCode", isSignal: false, isRequired: false, transformFunction: null }, visibilityParentFieldCodes: { classPropertyName: "visibilityParentFieldCodes", publicName: "visibilityParentFieldCodes", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { blockChange: "blockChange", addFieldRequest: "addFieldRequest", deleteBlock: "deleteBlock", notifySelectedField: "notifySelectedField", notifySelectedSubField: "notifySelectedSubField" }, ngImport: i0, template: "<div class=\"form-block-card\">\r\n <div class=\"form-block-card-header\">\r\n <div>\r\n <input [placeholder]=\"'form_builder.block_title' | uicTranslate\" [ngModel]=\"block().title\" (ngModelChange)=\"changeTitle($event)\">\r\n <input [placeholder]=\"'form_builder.block_subtitle' | uicTranslate\" [ngModel]=\"block().subtitle\" (ngModelChange)=\"changeSubtitle($event)\">\r\n </div>\r\n <ui-button\r\n [uiTooltip]=\"(isBlockVisibilityParent() ? 'form_builder.delete_block_dependency_blocked' : 'form_builder.delete_block') | uicTranslate\"\r\n [disabled]=\"isBlockVisibilityParent()\"\r\n (click)=\"requestDeleteBlock($event)\"\r\n size=\"s\"\r\n icon=\"ri-delete-bin-line\"\r\n color=\"red\"\r\n type=\"ghost\"\r\n [iconOnly]=\"true\">\r\n </ui-button>\r\n </div>\r\n <div\r\n class=\"form-block-card-body\"\r\n cdkDropList\r\n [cdkDropListData]=\"block().fields\"\r\n (cdkDropListDropped)=\"reorderFields($event)\">\r\n \r\n <!-- FIELDS -->\r\n @for(edtField of block().fields; track edtField.code; let i = $index) {\r\n <div class=\"field-with-subfields\">\r\n <div\r\n class=\"xfield-card\"\r\n cdkDrag\r\n [class.selected-field]=\"isRepeaterParentSelected(edtField)\"\r\n (click)=\"selectField(edtField)\">\r\n <i class=\"ri-draggable field-drag-handle\" cdkDragHandle></i>\r\n\r\n <div class=\"xfield-card-icon\">\r\n <i [class]=\"edtField.field?.icon ?? ''\"></i> \r\n </div>\r\n <div class=\"xfield-card-body\">\r\n <b> {{edtField.fieldData.label}} \r\n @if(edtField.fieldData.visibilityRules) {\r\n <i class=\"branched-field ri-git-merge-line\"></i> \r\n <span class=\"vs-rule\"> {{edtField.fieldData.visibilityRules[0]?.fieldLabel ?? edtField.fieldData.visibilityRules[0]?.fieldName ?? '-'}} </span>\r\n }\r\n </b>\r\n <p> {{edtField.field?.label ?? edtField.type ?? edtField.fieldData.type}} </p>\r\n </div>\r\n <div class=\"xfield-card-actions\">\r\n @if (edtField.fieldData.type === 'repeater') {\r\n <ui-button\r\n [icon]=\"isRepeaterExpanded(edtField.code) ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line'\"\r\n size=\"s\" color=\"black\" type=\"ghost\" [iconOnly]=\"true\"\r\n (click)=\"toggleRepeater(edtField.code, $event)\">\r\n </ui-button>\r\n }\r\n <ui-button\r\n [uiTooltip]=\"(isVisibilityParent(edtField.code) ? 'form_builder.delete_field_dependency_blocked' : 'form_builder.field_editor.delete') | uicTranslate\"\r\n [disabled]=\"isVisibilityParent(edtField.code)\"\r\n (click)=\"deleteField(edtField.code, $event)\"\r\n size=\"s\"\r\n icon=\"ri-delete-bin-line\"\r\n color=\"red\"\r\n type=\"ghost\"\r\n [iconOnly]=\"true\">\r\n </ui-button>\r\n </div>\r\n </div>\r\n\r\n @if (edtField.fieldData.type === 'repeater' && isRepeaterExpanded(edtField.code)) {\r\n <div class=\"repeater-inline-panel\">\r\n <div\r\n class=\"repeater-subfields-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"edtField.repeaterSubFields ?? []\"\r\n (cdkDropListDropped)=\"reorderSubFields(edtField.code, $event)\">\r\n @for (sf of edtField.repeaterSubFields ?? []; track sf.code) {\r\n <div\r\n class=\"xfield-card subfield-card\"\r\n cdkDrag\r\n [class.selected-field]=\"selectedSubFieldCode === sf.code\"\r\n (click)=\"onSelectSubField(edtField.code, sf, $event)\">\r\n <i class=\"ri-draggable field-drag-handle\" cdkDragHandle></i>\r\n <div class=\"xfield-card-icon\">\r\n <i [class]=\"sf.field?.icon ?? 'ri-question-line'\"></i>\r\n </div>\r\n <div class=\"xfield-card-body\">\r\n <b>{{ sf.fieldData.label || sf.fieldData.name }}</b>\r\n <p>{{ sf.field?.label ?? sf.type ?? sf.fieldData.type }}</p>\r\n </div>\r\n <div class=\"xfield-card-actions\">\r\n <ui-button\r\n size=\"s\" icon=\"ri-delete-bin-line\" color=\"red\" type=\"ghost\" [iconOnly]=\"true\"\r\n (click)=\"deleteSubField(edtField.code, sf.code, $event)\">\r\n </ui-button>\r\n </div>\r\n </div>\r\n } @empty {\r\n <p class=\"empty-hint\">{{'form_builder.repeater.no_subfields' | uicTranslate}}</p>\r\n }\r\n </div>\r\n <div class=\"new-subfield\">\r\n {{'form_builder.repeater.add_subfield' | uicTranslate}}\r\n <lib-field-type-selector [excludeTypes]=\"excludeSubFieldTypes\" (selectType)=\"addSubField(edtField.code, $event)\"></lib-field-type-selector>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n }\r\n\r\n </div>\r\n <div class=\"new-field\">\r\n {{'form_builder.add_new_field' | uicTranslate}}\r\n <lib-field-type-selector (selectType)=\"addField($event)\"></lib-field-type-selector>\r\n </div>\r\n</div>\r\n", styles: [".form-block-card{border:solid 1px var(--blue-500);border-radius:5px;overflow:hidden}.form-block-card-header{display:flex;gap:5px;align-items:center;background-color:#fff;padding:10px;border-bottom:solid 1px var(--grey-300)}.form-block-card-header>div{flex:1 1;gap:4px;display:flex;flex-direction:column}.form-block-card-header>div input{border:solid 1px var(--grey-100);padding:3px 6px;border-radius:5px}.form-block-card-header>div input:focus{border:solid 1px var(--primary-500);outline:none}.form-block-card-body{padding:15px;display:flex;flex-direction:column;background-color:var(--grey-50);gap:10px}.xfield-card{background-color:#fff;border-radius:5px;padding:10px;gap:10px;display:flex;align-items:center;border:solid 2px var(--grey-200);cursor:pointer;transition:border-color .3s ease}.xfield-card:hover{border-color:var(--grey-300)}.xfield-card-icon{display:flex;justify-content:center;align-items:center;border-radius:5px;width:30px;height:30px;font-size:20px;background-color:var(--grey-300);color:var(--grey-600)}.xfield-card-body{flex:1 1}.xfield-card-body b{display:flex;align-items:center;gap:5px}.xfield-card-body p{color:var(--grey-400);font-size:12px}.field-drag-handle{cursor:grab;color:var(--grey-400);transition:color .2s ease}.field-drag-handle:active{cursor:grabbing}.xfield-card:hover .field-drag-handle{color:var(--grey-600)}.cdk-drag-preview{box-sizing:border-box;border-radius:5px;box-shadow:0 6px 12px #0000002e}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.field-with-subfields{display:flex;flex-direction:column;gap:0}.repeater-inline-panel{background-color:var(--grey-100);border:solid 1px var(--blue-300);border-top:none;border-radius:0 0 5px 5px;padding:10px 10px 8px 28px;display:flex;flex-direction:column;gap:8px}.repeater-subfields-list{display:flex;flex-direction:column;gap:6px;min-height:6px}.subfield-card{font-size:13px;border-radius:4px;padding:7px 8px!important}.subfield-card .xfield-card-icon{width:26px!important;height:26px!important;font-size:16px!important}.subfield-card b{font-size:13px}.subfield-card p{font-size:11px}.new-subfield{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--grey-500);flex-wrap:wrap;padding-top:2px}.empty-hint{font-size:12px;color:var(--grey-400);text-align:center;padding:4px 0;margin:0}.form-block-card-body.cdk-drop-list-dragging .xfield-card:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.branched-field{color:var(--yellow-600)}.selected-field,.selected-field:hover{border-color:var(--primary-500)}.new-field{border-top:solid 1px var(--grey-300);padding:10px;background-color:#fff;display:flex;flex-direction:column;gap:5px;font-size:14px}.vs-rule{font-size:12px;color:var(--grey-600)}\n"], dependencies: [{ kind: "component", type: UicButtonComponent, selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "directive", type: UicToolTipDirective, selector: "[uiTooltip]", inputs: ["uiTooltip"] }, { kind: "pipe", type: UicTranslatePipe, name: "uicTranslate" }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1$3.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i1$3.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i1$3.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: FieldTypeSelectorComponent, selector: "lib-field-type-selector", inputs: ["excludeTypes"], outputs: ["selectType"] }] });
|
|
9289
9914
|
}
|
|
9290
9915
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BlockEditorComponent, decorators: [{
|
|
9291
9916
|
type: Component,
|
|
@@ -9296,9 +9921,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
9296
9921
|
DragDropModule,
|
|
9297
9922
|
FormsModule,
|
|
9298
9923
|
FieldTypeSelectorComponent
|
|
9299
|
-
], template: "<div class=\"form-block-card\">\n <div class=\"form-block-card-header\">\n <div>\n <input [placeholder]=\"'form_builder.block_title' | uicTranslate\" [ngModel]=\"block().title\" (ngModelChange)=\"changeTitle($event)\">\n <input [placeholder]=\"'form_builder.block_subtitle' | uicTranslate\" [ngModel]=\"block().subtitle\" (ngModelChange)=\"changeSubtitle($event)\">\n </div>\n <ui-button
|
|
9924
|
+
], template: "<div class=\"form-block-card\">\r\n <div class=\"form-block-card-header\">\r\n <div>\r\n <input [placeholder]=\"'form_builder.block_title' | uicTranslate\" [ngModel]=\"block().title\" (ngModelChange)=\"changeTitle($event)\">\r\n <input [placeholder]=\"'form_builder.block_subtitle' | uicTranslate\" [ngModel]=\"block().subtitle\" (ngModelChange)=\"changeSubtitle($event)\">\r\n </div>\r\n <ui-button\r\n [uiTooltip]=\"(isBlockVisibilityParent() ? 'form_builder.delete_block_dependency_blocked' : 'form_builder.delete_block') | uicTranslate\"\r\n [disabled]=\"isBlockVisibilityParent()\"\r\n (click)=\"requestDeleteBlock($event)\"\r\n size=\"s\"\r\n icon=\"ri-delete-bin-line\"\r\n color=\"red\"\r\n type=\"ghost\"\r\n [iconOnly]=\"true\">\r\n </ui-button>\r\n </div>\r\n <div\r\n class=\"form-block-card-body\"\r\n cdkDropList\r\n [cdkDropListData]=\"block().fields\"\r\n (cdkDropListDropped)=\"reorderFields($event)\">\r\n \r\n <!-- FIELDS -->\r\n @for(edtField of block().fields; track edtField.code; let i = $index) {\r\n <div class=\"field-with-subfields\">\r\n <div\r\n class=\"xfield-card\"\r\n cdkDrag\r\n [class.selected-field]=\"isRepeaterParentSelected(edtField)\"\r\n (click)=\"selectField(edtField)\">\r\n <i class=\"ri-draggable field-drag-handle\" cdkDragHandle></i>\r\n\r\n <div class=\"xfield-card-icon\">\r\n <i [class]=\"edtField.field?.icon ?? ''\"></i> \r\n </div>\r\n <div class=\"xfield-card-body\">\r\n <b> {{edtField.fieldData.label}} \r\n @if(edtField.fieldData.visibilityRules) {\r\n <i class=\"branched-field ri-git-merge-line\"></i> \r\n <span class=\"vs-rule\"> {{edtField.fieldData.visibilityRules[0]?.fieldLabel ?? edtField.fieldData.visibilityRules[0]?.fieldName ?? '-'}} </span>\r\n }\r\n </b>\r\n <p> {{edtField.field?.label ?? edtField.type ?? edtField.fieldData.type}} </p>\r\n </div>\r\n <div class=\"xfield-card-actions\">\r\n @if (edtField.fieldData.type === 'repeater') {\r\n <ui-button\r\n [icon]=\"isRepeaterExpanded(edtField.code) ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line'\"\r\n size=\"s\" color=\"black\" type=\"ghost\" [iconOnly]=\"true\"\r\n (click)=\"toggleRepeater(edtField.code, $event)\">\r\n </ui-button>\r\n }\r\n <ui-button\r\n [uiTooltip]=\"(isVisibilityParent(edtField.code) ? 'form_builder.delete_field_dependency_blocked' : 'form_builder.field_editor.delete') | uicTranslate\"\r\n [disabled]=\"isVisibilityParent(edtField.code)\"\r\n (click)=\"deleteField(edtField.code, $event)\"\r\n size=\"s\"\r\n icon=\"ri-delete-bin-line\"\r\n color=\"red\"\r\n type=\"ghost\"\r\n [iconOnly]=\"true\">\r\n </ui-button>\r\n </div>\r\n </div>\r\n\r\n @if (edtField.fieldData.type === 'repeater' && isRepeaterExpanded(edtField.code)) {\r\n <div class=\"repeater-inline-panel\">\r\n <div\r\n class=\"repeater-subfields-list\"\r\n cdkDropList\r\n [cdkDropListData]=\"edtField.repeaterSubFields ?? []\"\r\n (cdkDropListDropped)=\"reorderSubFields(edtField.code, $event)\">\r\n @for (sf of edtField.repeaterSubFields ?? []; track sf.code) {\r\n <div\r\n class=\"xfield-card subfield-card\"\r\n cdkDrag\r\n [class.selected-field]=\"selectedSubFieldCode === sf.code\"\r\n (click)=\"onSelectSubField(edtField.code, sf, $event)\">\r\n <i class=\"ri-draggable field-drag-handle\" cdkDragHandle></i>\r\n <div class=\"xfield-card-icon\">\r\n <i [class]=\"sf.field?.icon ?? 'ri-question-line'\"></i>\r\n </div>\r\n <div class=\"xfield-card-body\">\r\n <b>{{ sf.fieldData.label || sf.fieldData.name }}</b>\r\n <p>{{ sf.field?.label ?? sf.type ?? sf.fieldData.type }}</p>\r\n </div>\r\n <div class=\"xfield-card-actions\">\r\n <ui-button\r\n size=\"s\" icon=\"ri-delete-bin-line\" color=\"red\" type=\"ghost\" [iconOnly]=\"true\"\r\n (click)=\"deleteSubField(edtField.code, sf.code, $event)\">\r\n </ui-button>\r\n </div>\r\n </div>\r\n } @empty {\r\n <p class=\"empty-hint\">{{'form_builder.repeater.no_subfields' | uicTranslate}}</p>\r\n }\r\n </div>\r\n <div class=\"new-subfield\">\r\n {{'form_builder.repeater.add_subfield' | uicTranslate}}\r\n <lib-field-type-selector [excludeTypes]=\"excludeSubFieldTypes\" (selectType)=\"addSubField(edtField.code, $event)\"></lib-field-type-selector>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n }\r\n\r\n </div>\r\n <div class=\"new-field\">\r\n {{'form_builder.add_new_field' | uicTranslate}}\r\n <lib-field-type-selector (selectType)=\"addField($event)\"></lib-field-type-selector>\r\n </div>\r\n</div>\r\n", styles: [".form-block-card{border:solid 1px var(--blue-500);border-radius:5px;overflow:hidden}.form-block-card-header{display:flex;gap:5px;align-items:center;background-color:#fff;padding:10px;border-bottom:solid 1px var(--grey-300)}.form-block-card-header>div{flex:1 1;gap:4px;display:flex;flex-direction:column}.form-block-card-header>div input{border:solid 1px var(--grey-100);padding:3px 6px;border-radius:5px}.form-block-card-header>div input:focus{border:solid 1px var(--primary-500);outline:none}.form-block-card-body{padding:15px;display:flex;flex-direction:column;background-color:var(--grey-50);gap:10px}.xfield-card{background-color:#fff;border-radius:5px;padding:10px;gap:10px;display:flex;align-items:center;border:solid 2px var(--grey-200);cursor:pointer;transition:border-color .3s ease}.xfield-card:hover{border-color:var(--grey-300)}.xfield-card-icon{display:flex;justify-content:center;align-items:center;border-radius:5px;width:30px;height:30px;font-size:20px;background-color:var(--grey-300);color:var(--grey-600)}.xfield-card-body{flex:1 1}.xfield-card-body b{display:flex;align-items:center;gap:5px}.xfield-card-body p{color:var(--grey-400);font-size:12px}.field-drag-handle{cursor:grab;color:var(--grey-400);transition:color .2s ease}.field-drag-handle:active{cursor:grabbing}.xfield-card:hover .field-drag-handle{color:var(--grey-600)}.cdk-drag-preview{box-sizing:border-box;border-radius:5px;box-shadow:0 6px 12px #0000002e}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.field-with-subfields{display:flex;flex-direction:column;gap:0}.repeater-inline-panel{background-color:var(--grey-100);border:solid 1px var(--blue-300);border-top:none;border-radius:0 0 5px 5px;padding:10px 10px 8px 28px;display:flex;flex-direction:column;gap:8px}.repeater-subfields-list{display:flex;flex-direction:column;gap:6px;min-height:6px}.subfield-card{font-size:13px;border-radius:4px;padding:7px 8px!important}.subfield-card .xfield-card-icon{width:26px!important;height:26px!important;font-size:16px!important}.subfield-card b{font-size:13px}.subfield-card p{font-size:11px}.new-subfield{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--grey-500);flex-wrap:wrap;padding-top:2px}.empty-hint{font-size:12px;color:var(--grey-400);text-align:center;padding:4px 0;margin:0}.form-block-card-body.cdk-drop-list-dragging .xfield-card:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.branched-field{color:var(--yellow-600)}.selected-field,.selected-field:hover{border-color:var(--primary-500)}.new-field{border-top:solid 1px var(--grey-300);padding:10px;background-color:#fff;display:flex;flex-direction:column;gap:5px;font-size:14px}.vs-rule{font-size:12px;color:var(--grey-600)}\n"] }]
|
|
9300
9925
|
}], propDecorators: { selectedFieldId: [{
|
|
9301
9926
|
type: Input
|
|
9927
|
+
}], selectedSubFieldCode: [{
|
|
9928
|
+
type: Input
|
|
9929
|
+
}], visibilityParentFieldCodes: [{
|
|
9930
|
+
type: Input
|
|
9302
9931
|
}] } });
|
|
9303
9932
|
|
|
9304
9933
|
class UicUserFormbuilderComponent {
|
|
@@ -9319,9 +9948,15 @@ class UicUserFormbuilderComponent {
|
|
|
9319
9948
|
editingSnapshot = signal(null);
|
|
9320
9949
|
isReadOnly = signal(true);
|
|
9321
9950
|
selectedField = signal(null);
|
|
9951
|
+
editingSubField = signal(null);
|
|
9322
9952
|
focusNewFieldCode = signal(null);
|
|
9323
9953
|
propertiesWidth = signal(250);
|
|
9324
9954
|
previewSchema = computed(() => helperShowFormFromBuilder(this.editableBlocks(), this.editableCols()));
|
|
9955
|
+
visibilityParentFieldCodes = computed(() => new Set(this.editableBlocks()
|
|
9956
|
+
.flatMap(block => block.fields)
|
|
9957
|
+
.flatMap(field => field.fieldData.visibilityRules ?? [])
|
|
9958
|
+
.map(rule => rule.fieldName)
|
|
9959
|
+
.filter((fieldName) => !!fieldName)));
|
|
9325
9960
|
isResizingProperties = false;
|
|
9326
9961
|
resizeStartX = 0;
|
|
9327
9962
|
resizeStartWidth = 0;
|
|
@@ -9332,7 +9967,8 @@ class UicUserFormbuilderComponent {
|
|
|
9332
9967
|
.filter(field => field.code !== currentSelected?.code)
|
|
9333
9968
|
.map(field => ({
|
|
9334
9969
|
id: field.code,
|
|
9335
|
-
text: field.fieldData.label || field.fieldData.name
|
|
9970
|
+
text: field.fieldData.label || field.fieldData.name,
|
|
9971
|
+
fieldType: field.fieldData.type
|
|
9336
9972
|
}));
|
|
9337
9973
|
return {
|
|
9338
9974
|
fieldName: fieldOptions,
|
|
@@ -9377,6 +10013,18 @@ class UicUserFormbuilderComponent {
|
|
|
9377
10013
|
if (selectedField !== this.selectedField()) {
|
|
9378
10014
|
this.selectedField.set(selectedField);
|
|
9379
10015
|
}
|
|
10016
|
+
// Sync editingSubField
|
|
10017
|
+
const subCtx = this.editingSubField();
|
|
10018
|
+
if (subCtx) {
|
|
10019
|
+
const parentField = blocks.flatMap(b => b.fields).find(f => f.code === subCtx.parentCode);
|
|
10020
|
+
const latestSf = parentField?.repeaterSubFields?.find(sf => sf.code === subCtx.subField.code);
|
|
10021
|
+
if (!latestSf) {
|
|
10022
|
+
this.editingSubField.set(null);
|
|
10023
|
+
}
|
|
10024
|
+
else if (latestSf !== subCtx.subField) {
|
|
10025
|
+
this.editingSubField.set({ ...subCtx, subField: latestSf });
|
|
10026
|
+
}
|
|
10027
|
+
}
|
|
9380
10028
|
});
|
|
9381
10029
|
}
|
|
9382
10030
|
addBlock() {
|
|
@@ -9419,6 +10067,38 @@ class UicUserFormbuilderComponent {
|
|
|
9419
10067
|
selectField(field) {
|
|
9420
10068
|
this.selectedField.set(field);
|
|
9421
10069
|
this.focusNewFieldCode.set(null);
|
|
10070
|
+
this.editingSubField.set(null);
|
|
10071
|
+
}
|
|
10072
|
+
onSelectSubField(event) {
|
|
10073
|
+
this.editingSubField.set(event);
|
|
10074
|
+
if (event) {
|
|
10075
|
+
// Highlight the parent repeater field in the block (deselect root selection)
|
|
10076
|
+
const parentField = this.editableBlocks()
|
|
10077
|
+
.flatMap(b => b.fields)
|
|
10078
|
+
.find(f => f.code === event.parentCode);
|
|
10079
|
+
if (parentField)
|
|
10080
|
+
this.selectedField.set(parentField);
|
|
10081
|
+
}
|
|
10082
|
+
}
|
|
10083
|
+
onSubFieldChange(updatedFieldData) {
|
|
10084
|
+
const context = this.editingSubField();
|
|
10085
|
+
if (!context)
|
|
10086
|
+
return;
|
|
10087
|
+
const updatedSubField = {
|
|
10088
|
+
...context.subField,
|
|
10089
|
+
type: updatedFieldData.type,
|
|
10090
|
+
fieldData: updatedFieldData
|
|
10091
|
+
};
|
|
10092
|
+
this.editingSubField.set({ ...context, subField: updatedSubField });
|
|
10093
|
+
this.editableBlocks.update(blocks => blocks.map(block => ({
|
|
10094
|
+
...block,
|
|
10095
|
+
fields: block.fields.map(field => {
|
|
10096
|
+
if (field.code !== context.parentCode)
|
|
10097
|
+
return field;
|
|
10098
|
+
const updatedSubFields = (field.repeaterSubFields ?? []).map(sf => sf.code !== context.subField.code ? sf : updatedSubField);
|
|
10099
|
+
return { ...field, repeaterSubFields: updatedSubFields };
|
|
10100
|
+
})
|
|
10101
|
+
})));
|
|
9422
10102
|
}
|
|
9423
10103
|
startPropertiesResize(event) {
|
|
9424
10104
|
event.preventDefault();
|
|
@@ -9467,7 +10147,10 @@ class UicUserFormbuilderComponent {
|
|
|
9467
10147
|
cols: this.editableCols(),
|
|
9468
10148
|
blocks: blocksWithOrderedFields.map(block => ({
|
|
9469
10149
|
...block,
|
|
9470
|
-
fields: block.fields.map(({ field, ...restField }) =>
|
|
10150
|
+
fields: block.fields.map(({ field, ...restField }) => ({
|
|
10151
|
+
...restField,
|
|
10152
|
+
repeaterSubFields: restField.repeaterSubFields?.map(({ field: _sf, ...sfRest }) => sfRest)
|
|
10153
|
+
}))
|
|
9471
10154
|
}))
|
|
9472
10155
|
});
|
|
9473
10156
|
}
|
|
@@ -9568,6 +10251,22 @@ class UicUserFormbuilderComponent {
|
|
|
9568
10251
|
};
|
|
9569
10252
|
}
|
|
9570
10253
|
}
|
|
10254
|
+
// Hydrate sub-fields for repeater
|
|
10255
|
+
if (hydratedField.repeaterSubFields?.length) {
|
|
10256
|
+
const hydratedSubFields = hydratedField.repeaterSubFields.map(sf => {
|
|
10257
|
+
if (sf.field)
|
|
10258
|
+
return sf;
|
|
10259
|
+
const sfConfig = FIELDS_CONFIG.find(c => c.value === sf.type);
|
|
10260
|
+
if (!sfConfig)
|
|
10261
|
+
return sf;
|
|
10262
|
+
changed = true;
|
|
10263
|
+
blockChanged = true;
|
|
10264
|
+
return { ...sf, field: sfConfig };
|
|
10265
|
+
});
|
|
10266
|
+
if (hydratedSubFields !== hydratedField.repeaterSubFields) {
|
|
10267
|
+
hydratedField = { ...hydratedField, repeaterSubFields: hydratedSubFields };
|
|
10268
|
+
}
|
|
10269
|
+
}
|
|
9571
10270
|
const visibilityRules = hydratedField.fieldData.visibilityRules;
|
|
9572
10271
|
if (!visibilityRules?.length)
|
|
9573
10272
|
return hydratedField;
|
|
@@ -9641,7 +10340,7 @@ class UicUserFormbuilderComponent {
|
|
|
9641
10340
|
return value;
|
|
9642
10341
|
}
|
|
9643
10342
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UicUserFormbuilderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9644
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: UicUserFormbuilderComponent, isStandalone: true, selector: "ui-user-formbuilder", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, formTitle: { classPropertyName: "formTitle", publicName: "formTitle", isSignal: false, isRequired: false, transformFunction: null }, optionSources: { classPropertyName: "optionSources", publicName: "optionSources", isSignal: false, isRequired: false, transformFunction: null }, selectOptionsResolver: { classPropertyName: "selectOptionsResolver", publicName: "selectOptionsResolver", isSignal: false, isRequired: false, transformFunction: null }, readOnly: { classPropertyName: "readOnly", publicName: "readOnly", isSignal: true, isRequired: false, transformFunction: null }, editableFormInput: { classPropertyName: "editableFormInput", publicName: "editableForm", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitFormRequest: "submitFormRequest" }, host: { listeners: { "document:mousemove": "onPropertiesResize($event)", "document:mouseup": "stopPropertiesResize()" } }, ngImport: i0, template: "<div class=\"formeditor\" [class.focused]=\"!isReadOnly()\">\r\n <div class=\"formeditor-header\">\r\n <div style=\"flex: 1 1;\">\r\n {{formTitle}} \r\n \r\n <div class=\"cols-selector\"> \r\n @if (isReadOnly()) {\r\n {{editableCols()}}\r\n }@else {\r\n <ui-select [options]=\"[{id: 1, text: '1'}, {id: 2, text: '2'}, {id: 3, text: '3'}, {id: 4, text: '4'}]\" [ngModel]=\"editableCols()\" (ngModelChange)=\"editableCols.set($event)\"></ui-select> \r\n }\r\n col(s)</div>\r\n </div>\r\n @if (isReadOnly()) {\r\n @if (!disabled) {\r\n <ui-button color=\"black\" icon=\"ri-edit-line\" text=\"Editar\" (click)=\"enableEditMode()\"></ui-button>\r\n }\r\n } @else {\r\n <ui-button color=\"black\" type=\"bordered\" icon=\"ri-eye-line\" [text]=\"'form_builder.preview_form' | uicTranslate\" (click)=\"printForm()\"></ui-button>\r\n <ui-button color=\"black\" type=\"bordered\" icon=\"ri-close-line\" text=\"Descartar cambios\" (click)=\"discardChanges()\"></ui-button>\r\n <ui-button color=\"black\" icon=\"ri-check-line\" [text]=\"'form_builder.submit_form' | uicTranslate\" (click)=\"submitForm()\"></ui-button>\r\n }\r\n </div>\r\n @if (!isReadOnly()) {\r\n <div class=\"formeditor-body\">\r\n \r\n <!-- BLOCKS -->\r\n <div class=\"formeditor-overflow\">\r\n <div class=\"formeditor-workarea\">\r\n @for (block of editableBlocks(); track block.code; let i = $index) {\r\n <lib-block-editor \r\n [block]=\"block\"\r\n [selectedFieldId]=\"selectedField()?.code ?? null\"\n (blockChange)=\"onBlockChange(i, $event)\"\n (addFieldRequest)=\"addField(block.code, $event)\"\n (notifySelectedField)=\"selectField($event)\"\n (deleteBlock)=\"deleteBlock($event)\">\n </lib-block-editor>\n }\r\n <ui-button type=\"bordered\" icon=\"ri-add-line\" color=\"black\" [text]=\"'form_builder.add_block' | uicTranslate\" (click)=\"addBlock()\"></ui-button>\r\n </div>\r\n </div>\r\n <!-- PROPERTIES -->\r\n <div class=\"formeditor-properties\" [style.width.px]=\"propertiesWidth()\">\n <div\n class=\"formeditor-properties-resize\"\n (mousedown)=\"startPropertiesResize($event)\">\n </div>\n <h3>Propiedades</h3>\n <div class=\"formeditor-properties-form\">\n @if (
|
|
10343
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: UicUserFormbuilderComponent, isStandalone: true, selector: "ui-user-formbuilder", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, formTitle: { classPropertyName: "formTitle", publicName: "formTitle", isSignal: false, isRequired: false, transformFunction: null }, optionSources: { classPropertyName: "optionSources", publicName: "optionSources", isSignal: false, isRequired: false, transformFunction: null }, selectOptionsResolver: { classPropertyName: "selectOptionsResolver", publicName: "selectOptionsResolver", isSignal: false, isRequired: false, transformFunction: null }, readOnly: { classPropertyName: "readOnly", publicName: "readOnly", isSignal: true, isRequired: false, transformFunction: null }, editableFormInput: { classPropertyName: "editableFormInput", publicName: "editableForm", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitFormRequest: "submitFormRequest" }, host: { listeners: { "document:mousemove": "onPropertiesResize($event)", "document:mouseup": "stopPropertiesResize()" } }, ngImport: i0, template: "<div class=\"formeditor\" [class.focused]=\"!isReadOnly()\">\r\n <div class=\"formeditor-header\">\r\n <div style=\"flex: 1 1;\">\r\n {{formTitle}} \r\n \r\n <div class=\"cols-selector\"> \r\n @if (isReadOnly()) {\r\n {{editableCols()}}\r\n }@else {\r\n <ui-select [options]=\"[{id: 1, text: '1'}, {id: 2, text: '2'}, {id: 3, text: '3'}, {id: 4, text: '4'}]\" [ngModel]=\"editableCols()\" (ngModelChange)=\"editableCols.set($event)\"></ui-select> \r\n }\r\n col(s)</div>\r\n </div>\r\n @if (isReadOnly()) {\r\n @if (!disabled) {\r\n <ui-button color=\"black\" icon=\"ri-edit-line\" text=\"Editar\" (click)=\"enableEditMode()\"></ui-button>\r\n }\r\n } @else {\r\n <ui-button color=\"black\" type=\"bordered\" icon=\"ri-eye-line\" [text]=\"'form_builder.preview_form' | uicTranslate\" (click)=\"printForm()\"></ui-button>\r\n <ui-button color=\"black\" type=\"bordered\" icon=\"ri-close-line\" text=\"Descartar cambios\" (click)=\"discardChanges()\"></ui-button>\r\n <ui-button color=\"black\" icon=\"ri-check-line\" [text]=\"'form_builder.submit_form' | uicTranslate\" (click)=\"submitForm()\"></ui-button>\r\n }\r\n </div>\r\n @if (!isReadOnly()) {\r\n <div class=\"formeditor-body\">\r\n \r\n <!-- BLOCKS -->\r\n <div class=\"formeditor-overflow\">\r\n <div class=\"formeditor-workarea\">\r\n @for (block of editableBlocks(); track block.code; let i = $index) {\r\n <lib-block-editor \r\n [block]=\"block\"\r\n [selectedFieldId]=\"selectedField()?.code ?? null\"\r\n [selectedSubFieldCode]=\"editingSubField()?.subField?.code ?? null\"\r\n [visibilityParentFieldCodes]=\"visibilityParentFieldCodes()\"\r\n (blockChange)=\"onBlockChange(i, $event)\"\r\n (addFieldRequest)=\"addField(block.code, $event)\"\r\n (notifySelectedField)=\"selectField($event)\"\r\n (notifySelectedSubField)=\"onSelectSubField($event)\"\r\n (deleteBlock)=\"deleteBlock($event)\">\r\n </lib-block-editor>\r\n }\r\n <ui-button type=\"bordered\" icon=\"ri-add-line\" color=\"black\" [text]=\"'form_builder.add_block' | uicTranslate\" (click)=\"addBlock()\"></ui-button>\r\n </div>\r\n </div>\r\n <!-- PROPERTIES -->\r\n <div class=\"formeditor-properties\" [style.width.px]=\"propertiesWidth()\">\r\n <div\r\n class=\"formeditor-properties-resize\"\r\n (mousedown)=\"startPropertiesResize($event)\">\r\n </div>\r\n <h3>Propiedades</h3>\r\n <div class=\"formeditor-properties-form\">\r\n @if (editingSubField()) {\r\n <div class=\"subfield-back-header\">\r\n <i class=\"ri-stack-line\"></i>\r\n <span>{{editingSubField()!.subField.fieldData.label || editingSubField()!.subField.fieldData.name}}</span>\r\n </div>\r\n <lib-field-editor\r\n [config]=\"editingSubField()!.subField\"\r\n [isSubField]=\"true\"\r\n [options]=\"{}\"\r\n (fieldChange)=\"onSubFieldChange($event)\">\r\n </lib-field-editor>\r\n } @else if (selectedField()) {\r\n <lib-field-editor \r\n [config]=\"selectedField()!\"\r\n [focusRequiredField]=\"focusNewFieldCode() === selectedField()?.code\"\r\n [options]=\"dependencyOptions()\"\r\n (fieldChange)=\"onFieldChange($event)\">\r\n </lib-field-editor>\r\n }@else{\r\n <div class=\"no-selected-field\">\r\n <i class=\"ri-edit-box-line\"></i>\r\n <p>{{'form_builder.select_field_to_edit' | uicTranslate}}</p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }@else {\r\n <div class=\"form-preview\">\r\n <ui-form-wrapper \r\n [schema]=\"previewSchema()\"\r\n [selectOptionsResolver]=\"selectOptionsResolver\"\r\n [showButtons]=\"false\">\r\n </ui-form-wrapper>\r\n </div>\r\n }\r\n </div>\r\n\r\n", styles: [".formeditor{display:flex;flex-direction:column;overflow:hidden;background-color:var(--grey-100);border:solid 1px var(--grey-300);border-radius:5px;max-height:500px}.formeditor-header{background-color:#fff;padding:5px 10px;align-items:center;display:flex;gap:10px;border-bottom:solid 1px var(--grey-300)}.formeditor-body{display:flex;gap:10px;overflow:hidden;padding:10px;min-height:0}.formeditor-overflow{padding:5px;flex:1 1;overflow:auto;min-width:0}.formeditor-workarea{display:flex;flex-direction:column;gap:15px;height:fit-content}.formeditor-properties{width:250px;flex:0 0 auto;display:flex;flex-direction:column;position:relative;background-color:#fff;border:solid 1px var(--grey-300);border-radius:5px;min-height:0;min-width:250px;max-width:600px}.formeditor-properties-resize{position:absolute;top:0;bottom:0;left:-6px;width:10px;cursor:col-resize;z-index:1}.formeditor-properties>h3{padding:10px;border-bottom:solid 1px var(--grey-300)}.formeditor-properties-form{padding:10px;overflow:auto;flex:1 1 auto;min-height:0}.form-preview{padding:20px;overflow:auto;background-color:#fff}.focused{border:solid 1px var(--primary-400);border-radius:10px;box-shadow:0 0 0 3px var(--secondary-alpha)}.no-selected-field{width:100%;display:flex;flex-direction:column;justify-content:center;align-items:center;padding:20px 0;font-size:13px;gap:15px;text-align:center;color:var(--grey-400)}.no-selected-field i{font-size:24px}.cols-selector{margin-left:8px;padding-left:8px;border-left:solid 1px var(--grey-400);display:inline-flex;align-items:center;gap:5px}.subfield-back-header{display:flex;align-items:center;gap:6px;padding:0 0 10px;border-bottom:solid 1px var(--grey-200);margin-bottom:10px;color:var(--grey-500);font-size:12px}.subfield-back-header i{font-size:14px;color:var(--primary-500)}.subfield-back-header span{font-weight:600;color:var(--grey-700);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"], dependencies: [{ kind: "component", type: UicButtonComponent, selector: "ui-button", inputs: ["text", "icon", "rightIcon", "iconOnly", "disabled", "loading", "size", "type", "color"] }, { kind: "component", type: UicFormWrapperComponent, selector: "ui-form-wrapper", inputs: ["schema", "fields", "cols", "externalData", "selectOptionsResolver", "loading", "disabled", "showButtons", "fillSelects", "initialValues", "focusFieldName", "focusFieldTrigger", "fileUidResolverFn"], outputs: ["formSubmit", "formChange", "optionsSourceError"] }, { kind: "pipe", type: UicTranslatePipe, name: "uicTranslate" }, { kind: "component", type: FieldEditorComponent, selector: "lib-field-editor", inputs: ["config", "focusRequiredField", "isSubField", "options"], outputs: ["fieldChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: BlockEditorComponent, selector: "lib-block-editor", inputs: ["block", "selectedFieldId", "selectedSubFieldCode", "visibilityParentFieldCodes"], outputs: ["blockChange", "addFieldRequest", "deleteBlock", "notifySelectedField", "notifySelectedSubField"] }, { kind: "component", type: UicSelectComponent, selector: "ui-select", inputs: ["icon", "iconColor", "internalIcon", "internalIconColor", "size", "label", "error", "tip", "showSubtitle", "disabled", "nonSelectedText", "noneText", "emptyText", "searcherEnabled", "loading", "nullable", "options"] }] });
|
|
9645
10344
|
}
|
|
9646
10345
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UicUserFormbuilderComponent, decorators: [{
|
|
9647
10346
|
type: Component,
|
|
@@ -9653,7 +10352,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
9653
10352
|
FormsModule,
|
|
9654
10353
|
BlockEditorComponent,
|
|
9655
10354
|
UicSelectComponent
|
|
9656
|
-
], template: "<div class=\"formeditor\" [class.focused]=\"!isReadOnly()\">\r\n <div class=\"formeditor-header\">\r\n <div style=\"flex: 1 1;\">\r\n {{formTitle}} \r\n \r\n <div class=\"cols-selector\"> \r\n @if (isReadOnly()) {\r\n {{editableCols()}}\r\n }@else {\r\n <ui-select [options]=\"[{id: 1, text: '1'}, {id: 2, text: '2'}, {id: 3, text: '3'}, {id: 4, text: '4'}]\" [ngModel]=\"editableCols()\" (ngModelChange)=\"editableCols.set($event)\"></ui-select> \r\n }\r\n col(s)</div>\r\n </div>\r\n @if (isReadOnly()) {\r\n @if (!disabled) {\r\n <ui-button color=\"black\" icon=\"ri-edit-line\" text=\"Editar\" (click)=\"enableEditMode()\"></ui-button>\r\n }\r\n } @else {\r\n <ui-button color=\"black\" type=\"bordered\" icon=\"ri-eye-line\" [text]=\"'form_builder.preview_form' | uicTranslate\" (click)=\"printForm()\"></ui-button>\r\n <ui-button color=\"black\" type=\"bordered\" icon=\"ri-close-line\" text=\"Descartar cambios\" (click)=\"discardChanges()\"></ui-button>\r\n <ui-button color=\"black\" icon=\"ri-check-line\" [text]=\"'form_builder.submit_form' | uicTranslate\" (click)=\"submitForm()\"></ui-button>\r\n }\r\n </div>\r\n @if (!isReadOnly()) {\r\n <div class=\"formeditor-body\">\r\n \r\n <!-- BLOCKS -->\r\n <div class=\"formeditor-overflow\">\r\n <div class=\"formeditor-workarea\">\r\n @for (block of editableBlocks(); track block.code; let i = $index) {\r\n <lib-block-editor \r\n [block]=\"block\"\r\n [selectedFieldId]=\"selectedField()?.code ?? null\"\n (blockChange)=\"onBlockChange(i, $event)\"\n (addFieldRequest)=\"addField(block.code, $event)\"\n (notifySelectedField)=\"selectField($event)\"\n (deleteBlock)=\"deleteBlock($event)\">\n </lib-block-editor>\n }\r\n <ui-button type=\"bordered\" icon=\"ri-add-line\" color=\"black\" [text]=\"'form_builder.add_block' | uicTranslate\" (click)=\"addBlock()\"></ui-button>\r\n </div>\r\n </div>\r\n <!-- PROPERTIES -->\r\n <div class=\"formeditor-properties\" [style.width.px]=\"propertiesWidth()\">\n <div\n class=\"formeditor-properties-resize\"\n (mousedown)=\"startPropertiesResize($event)\">\n </div>\n <h3>Propiedades</h3>\n <div class=\"formeditor-properties-form\">\n @if (
|
|
10355
|
+
], template: "<div class=\"formeditor\" [class.focused]=\"!isReadOnly()\">\r\n <div class=\"formeditor-header\">\r\n <div style=\"flex: 1 1;\">\r\n {{formTitle}} \r\n \r\n <div class=\"cols-selector\"> \r\n @if (isReadOnly()) {\r\n {{editableCols()}}\r\n }@else {\r\n <ui-select [options]=\"[{id: 1, text: '1'}, {id: 2, text: '2'}, {id: 3, text: '3'}, {id: 4, text: '4'}]\" [ngModel]=\"editableCols()\" (ngModelChange)=\"editableCols.set($event)\"></ui-select> \r\n }\r\n col(s)</div>\r\n </div>\r\n @if (isReadOnly()) {\r\n @if (!disabled) {\r\n <ui-button color=\"black\" icon=\"ri-edit-line\" text=\"Editar\" (click)=\"enableEditMode()\"></ui-button>\r\n }\r\n } @else {\r\n <ui-button color=\"black\" type=\"bordered\" icon=\"ri-eye-line\" [text]=\"'form_builder.preview_form' | uicTranslate\" (click)=\"printForm()\"></ui-button>\r\n <ui-button color=\"black\" type=\"bordered\" icon=\"ri-close-line\" text=\"Descartar cambios\" (click)=\"discardChanges()\"></ui-button>\r\n <ui-button color=\"black\" icon=\"ri-check-line\" [text]=\"'form_builder.submit_form' | uicTranslate\" (click)=\"submitForm()\"></ui-button>\r\n }\r\n </div>\r\n @if (!isReadOnly()) {\r\n <div class=\"formeditor-body\">\r\n \r\n <!-- BLOCKS -->\r\n <div class=\"formeditor-overflow\">\r\n <div class=\"formeditor-workarea\">\r\n @for (block of editableBlocks(); track block.code; let i = $index) {\r\n <lib-block-editor \r\n [block]=\"block\"\r\n [selectedFieldId]=\"selectedField()?.code ?? null\"\r\n [selectedSubFieldCode]=\"editingSubField()?.subField?.code ?? null\"\r\n [visibilityParentFieldCodes]=\"visibilityParentFieldCodes()\"\r\n (blockChange)=\"onBlockChange(i, $event)\"\r\n (addFieldRequest)=\"addField(block.code, $event)\"\r\n (notifySelectedField)=\"selectField($event)\"\r\n (notifySelectedSubField)=\"onSelectSubField($event)\"\r\n (deleteBlock)=\"deleteBlock($event)\">\r\n </lib-block-editor>\r\n }\r\n <ui-button type=\"bordered\" icon=\"ri-add-line\" color=\"black\" [text]=\"'form_builder.add_block' | uicTranslate\" (click)=\"addBlock()\"></ui-button>\r\n </div>\r\n </div>\r\n <!-- PROPERTIES -->\r\n <div class=\"formeditor-properties\" [style.width.px]=\"propertiesWidth()\">\r\n <div\r\n class=\"formeditor-properties-resize\"\r\n (mousedown)=\"startPropertiesResize($event)\">\r\n </div>\r\n <h3>Propiedades</h3>\r\n <div class=\"formeditor-properties-form\">\r\n @if (editingSubField()) {\r\n <div class=\"subfield-back-header\">\r\n <i class=\"ri-stack-line\"></i>\r\n <span>{{editingSubField()!.subField.fieldData.label || editingSubField()!.subField.fieldData.name}}</span>\r\n </div>\r\n <lib-field-editor\r\n [config]=\"editingSubField()!.subField\"\r\n [isSubField]=\"true\"\r\n [options]=\"{}\"\r\n (fieldChange)=\"onSubFieldChange($event)\">\r\n </lib-field-editor>\r\n } @else if (selectedField()) {\r\n <lib-field-editor \r\n [config]=\"selectedField()!\"\r\n [focusRequiredField]=\"focusNewFieldCode() === selectedField()?.code\"\r\n [options]=\"dependencyOptions()\"\r\n (fieldChange)=\"onFieldChange($event)\">\r\n </lib-field-editor>\r\n }@else{\r\n <div class=\"no-selected-field\">\r\n <i class=\"ri-edit-box-line\"></i>\r\n <p>{{'form_builder.select_field_to_edit' | uicTranslate}}</p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }@else {\r\n <div class=\"form-preview\">\r\n <ui-form-wrapper \r\n [schema]=\"previewSchema()\"\r\n [selectOptionsResolver]=\"selectOptionsResolver\"\r\n [showButtons]=\"false\">\r\n </ui-form-wrapper>\r\n </div>\r\n }\r\n </div>\r\n\r\n", styles: [".formeditor{display:flex;flex-direction:column;overflow:hidden;background-color:var(--grey-100);border:solid 1px var(--grey-300);border-radius:5px;max-height:500px}.formeditor-header{background-color:#fff;padding:5px 10px;align-items:center;display:flex;gap:10px;border-bottom:solid 1px var(--grey-300)}.formeditor-body{display:flex;gap:10px;overflow:hidden;padding:10px;min-height:0}.formeditor-overflow{padding:5px;flex:1 1;overflow:auto;min-width:0}.formeditor-workarea{display:flex;flex-direction:column;gap:15px;height:fit-content}.formeditor-properties{width:250px;flex:0 0 auto;display:flex;flex-direction:column;position:relative;background-color:#fff;border:solid 1px var(--grey-300);border-radius:5px;min-height:0;min-width:250px;max-width:600px}.formeditor-properties-resize{position:absolute;top:0;bottom:0;left:-6px;width:10px;cursor:col-resize;z-index:1}.formeditor-properties>h3{padding:10px;border-bottom:solid 1px var(--grey-300)}.formeditor-properties-form{padding:10px;overflow:auto;flex:1 1 auto;min-height:0}.form-preview{padding:20px;overflow:auto;background-color:#fff}.focused{border:solid 1px var(--primary-400);border-radius:10px;box-shadow:0 0 0 3px var(--secondary-alpha)}.no-selected-field{width:100%;display:flex;flex-direction:column;justify-content:center;align-items:center;padding:20px 0;font-size:13px;gap:15px;text-align:center;color:var(--grey-400)}.no-selected-field i{font-size:24px}.cols-selector{margin-left:8px;padding-left:8px;border-left:solid 1px var(--grey-400);display:inline-flex;align-items:center;gap:5px}.subfield-back-header{display:flex;align-items:center;gap:6px;padding:0 0 10px;border-bottom:solid 1px var(--grey-200);margin-bottom:10px;color:var(--grey-500);font-size:12px}.subfield-back-header i{font-size:14px;color:var(--primary-500)}.subfield-back-header span{font-weight:600;color:var(--grey-700);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"] }]
|
|
9657
10356
|
}], ctorParameters: () => [], propDecorators: { disabled: [{
|
|
9658
10357
|
type: Input
|
|
9659
10358
|
}], formTitle: [{
|
|
@@ -10471,5 +11170,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
10471
11170
|
* Generated bundle index. Do not edit.
|
|
10472
11171
|
*/
|
|
10473
11172
|
|
|
10474
|
-
export { BASE_FORM_FIELDS, BRANCH_FORM_FIELDS, DROPDOWN_OVERLAY_CONTROLS, EXTRA_FORM_FIELDS, FIELDS_CONFIG, FirstCapitalPipe, LAYOUT_FORM_FIELDS, MODAL_CLOSE_EVENT, MODAL_CLOSE_REQUEST, MODAL_COMPONENT, MODAL_CONFIG, MODAL_DATA, UIC_TRANSLATE_CONFIG, UiDropdownCloseDirective, UiModalRef, UicAccordionComponent, UicActionButtonComponent, UicAlertContainerComponent, UicButtonComponent, UicCheckboxComponent, UicDatePickerComponent, UicDropdownContainerComponent, UicEditableTableComponent, UicExcelTableComponent, UicFileInputComponent, UicFormWrapperComponent, UicInputComponent, UicKpiCardComponent, UicModalService, UicMultySearcherComponent, UicMultySelectComponent, UicNameInitsPipe, UicOverlayCardComponent, UicPhoneInputComponent, UicPoolOptionsComponent, UicPortletCardComponent, UicProgressBarComponent, UicPushAlertService, UicRadioComponent, UicRuleBuilderComponent, UicSearcherComponent, UicSelectComponent, UicShortTableComponent, UicSignaturePadComponent, UicSkeletonCardsComponent, UicSkeletonLoaderComponent, UicSliderComponent, UicStepTabsComponent, UicStepsFormComponent, UicSwichComponent, UicTableComponent, UicTabsButtonComponent, UicTagSelectorComponent, UicTextareaAutoresizeDirective, UicTextareaAutoresizeMaxRowsDirective, UicTextareaAutoresizeMinRowsDirective, UicTimePickerComponent, UicTinyAlertService, UicToolTipDirective, UicTranslatePipe, UicTranslateService, UicTreeAdminComponent, UicUserFormbuilderComponent, UicWorkPanelComponent, animatedRow, fadeAndRise, fadeBackdrop, helperFormMapFormdataToObject, helperShowFormFromBuilder, helperTableMapDatoToColums, highlightRow, isMobile, provideUicTranslateConfig, pushTop, sideModal, simpleFade };
|
|
11173
|
+
export { BASE_FORM_FIELDS, BRANCH_FORM_FIELDS, DROPDOWN_OVERLAY_CONTROLS, EXTRA_FORM_FIELDS, FIELDS_CONFIG, FirstCapitalPipe, LAYOUT_FORM_FIELDS, MODAL_CLOSE_EVENT, MODAL_CLOSE_REQUEST, MODAL_COMPONENT, MODAL_CONFIG, MODAL_DATA, UIC_TRANSLATE_CONFIG, UiDropdownCloseDirective, UiModalRef, UicAccordionComponent, UicActionButtonComponent, UicAlertContainerComponent, UicButtonComponent, UicCheckboxComponent, UicDatePickerComponent, UicDropdownContainerComponent, UicEditableTableComponent, UicExcelTableComponent, UicFileInputComponent, UicFormWrapperComponent, UicInputComponent, UicKpiCardComponent, UicModalService, UicMultySearcherComponent, UicMultySelectComponent, UicNameInitsPipe, UicOverlayCardComponent, UicPhoneInputComponent, UicPoolOptionsComponent, UicPortletCardComponent, UicProgressBarComponent, UicPushAlertService, UicRadioComponent, UicRepeaterComponent, UicRuleBuilderComponent, UicSearcherComponent, UicSelectComponent, UicShortTableComponent, UicSignaturePadComponent, UicSkeletonCardsComponent, UicSkeletonLoaderComponent, UicSliderComponent, UicStepTabsComponent, UicStepsFormComponent, UicSwichComponent, UicTableComponent, UicTabsButtonComponent, UicTagSelectorComponent, UicTextareaAutoresizeDirective, UicTextareaAutoresizeMaxRowsDirective, UicTextareaAutoresizeMinRowsDirective, UicTimePickerComponent, UicTinyAlertService, UicToolTipDirective, UicTranslatePipe, UicTranslateService, UicTreeAdminComponent, UicUserFormbuilderComponent, UicWorkPanelComponent, VISIBILITY_OPERATOR_OPTIONS, animatedRow, fadeAndRise, fadeBackdrop, helperFormMapFormdataToObject, helperShowFormFromBuilder, helperTableMapDatoToColums, highlightRow, isMobile, provideUicTranslateConfig, pushTop, sideModal, simpleFade };
|
|
10475
11174
|
//# sourceMappingURL=ui-core-abv.mjs.map
|