@elite.framework/ng.ui.core 1.0.83 → 1.0.84

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.
@@ -5,7 +5,7 @@ import { CommonModule } from '@angular/common';
5
5
  import * as i2$1 from '@angular/forms';
6
6
  import { FormGroup, ReactiveFormsModule, FormsModule, FormControl, FormArray } from '@angular/forms';
7
7
  import { FormlyForm, FieldType, FormlyField, provideFormlyConfig } from '@ngx-formly/core';
8
- import * as i10 from '@ngx-translate/core';
8
+ import * as i8$1 from '@ngx-translate/core';
9
9
  import { TranslateService, TranslateModule } from '@ngx-translate/core';
10
10
  import { ToolbarModule } from 'primeng/toolbar';
11
11
  import * as i4 from 'primeng/button';
@@ -648,7 +648,7 @@ class GenericSearchAdvanced {
648
648
  this.drawerVisible = false;
649
649
  }
650
650
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: GenericSearchAdvanced, deps: [], target: i0.ɵɵFactoryTarget.Component });
651
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: GenericSearchAdvanced, isStandalone: true, selector: "lib-generic-search-advanced", inputs: { model: "model", fields: "fields", enableSelect: "enableSelect", enableGroup: "enableGroup", odataConfig: "odataConfig" }, outputs: { search: "search", paginationChange: "paginationChange", odataSearch: "odataSearch" }, ngImport: i0, template: "<div class=\"flex flex-wrap items-center gap-3 w-full\">\r\n <!-- Search Input with Icon -->\r\n <p-inputgroup class=\"w-full\">\r\n <input\r\n pInputText\r\n type=\"text\"\r\n [(ngModel)]=\"model['filter']\"\r\n placeholder=\"{{ 'SEARCH' | translate }}\"\r\n (keyup.enter)=\"onSubmit()\"\r\n />\r\n\r\n\r\n <p-inputgroup-addon>\r\n <p-button\r\n icon=\"pi pi-search\"\r\n severity=\"secondary\"\r\n (click)=\"onSubmit()\"\r\n ></p-button>\r\n </p-inputgroup-addon>\r\n<p-inputgroup-addon>\r\n <div class=\"relative inline-flex\">\r\n <p-button\r\n icon=\"pi pi-filter\"\r\n severity=\"secondary\"\r\n (onClick)=\"drawerVisible = true\">\r\n </p-button>\r\n\r\n <p-badge\r\n *ngIf=\"filterCount > 0\"\r\n [value]=\"filterCount\"\r\n severity=\"warn\"\r\n size=\"small\"\r\n class=\"absolute -top-0 -right-0\">\r\n </p-badge>\r\n </div>\r\n</p-inputgroup-addon>\r\n\r\n <p-inputgroup-addon *ngIf=\"model['filter'] || filterCount > 0\">\r\n <p-button\r\n icon=\"pi pi-times\"\r\n severity=\"danger\"\r\n (click)=\"model['filter']=''; onReset()\"\r\n ></p-button>\r\n </p-inputgroup-addon>\r\n</p-inputgroup>\r\n\r\n\r\n</div>\r\n\r\n<!-- Drawer for Advanced Multi-field Search -->\r\n @if(drawerVisible){\r\n<p-drawer\r\n [(visible)]=\"drawerVisible\"\r\n position=\"right\"\r\n [styleClass]=\"'!w-full md:!w-80 lg:!w-[40rem] !h-full' \"\r\n [modal]=\"true\"\r\n [dismissible]=\"true\"\r\n styleClass=\"p-4 w-full max-w-md max-h-[90vh] flex flex-col\"\r\n>\r\n <!-- Entire form wrapper -->\r\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit(); drawerVisible=false\" class=\"flex flex-col flex-1\">\r\n <!-- Scrollable Form -->\r\n <div class=\"flex-1 overflow-auto\">\r\n <formly-form\r\n [form]=\"form\"\r\n [fields]=\"fields_\"\r\n [model]=\"model\"\r\n [options]=\"options\"\r\n >\r\n </formly-form>\r\n </div>\r\n\r\n </form>\r\n <!-- Action Buttons -->\r\n <ng-template pTemplate=\"footer\">\r\n <div class=\"flex justify-end mt-2 space-x-2 flex-none\">\r\n <button\r\n type=\"submit\"\r\n pButton size=\"small\"\r\n (click)=\" onSubmit(); drawerVisible=false\"\r\n label=\"{{ 'SEARCH' | translate }}\">\r\n </button>\r\n <button\r\n type=\"button\"\r\n pButton\r\n size=\"small\"\r\n class=\"p-button-text\"\r\n (click)=\"onReset(); drawerVisible=false\"\r\n >\r\n {{ 'CLEAR' | translate }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n</p-drawer>\r\n\r\n }\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: ToolbarModule }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$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: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: InputIconModule }, { kind: "ngmodule", type: IconFieldModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i5.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i6.Drawer, selector: "p-drawer", inputs: ["appendTo", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "ngmodule", type: InputGroupModule }, { kind: "component", type: i7.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["styleClass"] }, { kind: "ngmodule", type: InputGroupAddonModule }, { kind: "component", type: i8.InputGroupAddon, selector: "p-inputgroup-addon, p-inputGroupAddon", inputs: ["style", "styleClass"] }, { kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i9.Badge, selector: "p-badge", inputs: ["styleClass", "badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
651
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: GenericSearchAdvanced, isStandalone: true, selector: "lib-generic-search-advanced", inputs: { model: "model", fields: "fields", enableSelect: "enableSelect", enableGroup: "enableGroup", odataConfig: "odataConfig" }, outputs: { search: "search", paginationChange: "paginationChange", odataSearch: "odataSearch" }, ngImport: i0, template: "<div class=\"flex flex-wrap items-center gap-3 w-full\">\r\n <!-- Search Input with Icon -->\r\n <p-inputgroup class=\"w-full\">\r\n <input\r\n pInputText\r\n type=\"text\"\r\n [(ngModel)]=\"model['filter']\"\r\n placeholder=\"{{ 'SEARCH' | translate }}\"\r\n (keyup.enter)=\"onSubmit()\"\r\n />\r\n\r\n\r\n <p-inputgroup-addon>\r\n <p-button\r\n icon=\"pi pi-search\"\r\n severity=\"secondary\"\r\n (click)=\"onSubmit()\"\r\n ></p-button>\r\n </p-inputgroup-addon>\r\n<p-inputgroup-addon>\r\n <div class=\"relative inline-flex\">\r\n <p-button\r\n icon=\"pi pi-filter\"\r\n severity=\"secondary\"\r\n (onClick)=\"drawerVisible = true\">\r\n </p-button>\r\n\r\n <p-badge\r\n *ngIf=\"filterCount > 0\"\r\n [value]=\"filterCount\"\r\n severity=\"warn\"\r\n size=\"small\"\r\n class=\"absolute -top-0 -right-0\">\r\n </p-badge>\r\n </div>\r\n</p-inputgroup-addon>\r\n\r\n <p-inputgroup-addon *ngIf=\"model['filter'] || filterCount > 0\">\r\n <p-button\r\n icon=\"pi pi-times\"\r\n severity=\"danger\"\r\n (click)=\"model['filter']=''; onReset()\"\r\n ></p-button>\r\n </p-inputgroup-addon>\r\n</p-inputgroup>\r\n\r\n\r\n</div>\r\n\r\n<!-- Drawer for Advanced Multi-field Search -->\r\n @if(drawerVisible){\r\n<p-drawer\r\n [(visible)]=\"drawerVisible\"\r\n position=\"right\"\r\n [styleClass]=\"'!w-full md:!w-80 lg:!w-[40rem] !h-full' \"\r\n [modal]=\"true\"\r\n [dismissible]=\"true\"\r\n styleClass=\"p-4 w-full max-w-md max-h-[90vh] flex flex-col\"\r\n>\r\n <!-- Entire form wrapper -->\r\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit(); drawerVisible=false\" class=\"flex flex-col flex-1\">\r\n <!-- Scrollable Form -->\r\n <div class=\"flex-1 overflow-auto\">\r\n <formly-form\r\n [form]=\"form\"\r\n [fields]=\"fields_\"\r\n [model]=\"model\"\r\n [options]=\"options\"\r\n >\r\n </formly-form>\r\n </div>\r\n\r\n </form>\r\n <!-- Action Buttons -->\r\n <ng-template pTemplate=\"footer\">\r\n <div class=\"flex justify-end mt-2 space-x-2 flex-none\">\r\n <button\r\n type=\"submit\"\r\n pButton size=\"small\"\r\n (click)=\" onSubmit(); drawerVisible=false\"\r\n label=\"{{ 'SEARCH' | translate }}\">\r\n </button>\r\n <button\r\n type=\"button\"\r\n pButton\r\n size=\"small\"\r\n class=\"p-button-text\"\r\n (click)=\"onReset(); drawerVisible=false\"\r\n >\r\n {{ 'CLEAR' | translate }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n</p-drawer>\r\n\r\n }\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: ToolbarModule }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$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: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: InputIconModule }, { kind: "ngmodule", type: IconFieldModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i5.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i6.Drawer, selector: "p-drawer", inputs: ["appendTo", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "ngmodule", type: InputGroupModule }, { kind: "component", type: i7.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["styleClass"] }, { kind: "ngmodule", type: InputGroupAddonModule }, { kind: "component", type: i8.InputGroupAddon, selector: "p-inputgroup-addon, p-inputGroupAddon", inputs: ["style", "styleClass"] }, { kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i9.Badge, selector: "p-badge", inputs: ["styleClass", "badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "pipe", type: i8$1.TranslatePipe, name: "translate" }] });
652
652
  }
653
653
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: GenericSearchAdvanced, decorators: [{
654
654
  type: Component,
@@ -783,183 +783,161 @@ class SortBuilderComponent extends FieldType {
783
783
  return availableFields.length > 0 ? availableFields[0].key : '';
784
784
  }
785
785
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SortBuilderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
786
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: SortBuilderComponent, isStandalone: true, selector: "formly-sort-builder", usesInheritance: true, ngImport: i0, template: `
787
- <div class="sort-builder p-3 border-round border-1 surface-border">
788
- <div class="flex justify-content-between align-items-center mb-3">
789
- <h4 class="mt-0 mb-0">{{ props.label }}</h4>
790
- <small class="text-500">الأولوية من الأعلى إلى الأسفل</small>
791
- </div>
792
-
793
- <!-- Sort List -->
794
- <div *ngIf="sorts.length > 0" class="sort-list space-y-2 mb-3">
795
- <div
796
- *ngFor="let sort of sorts; let i = index; let isFirst = first; let isLast = last"
797
- class="sort-row p-2 border-round surface-card"
798
- pDraggable
799
- pDroppable
800
- (onDragStart)="onDragStart(i)"
801
- (onDrop)="onDrop($event, i)"
802
- [ngClass]="{'border-left-3 border-primary': isFirst, 'border-left-3 border-200': !isFirst}">
803
-
804
- <div class="grid grid-cols-4 align-items-center gap-2">
805
- <!-- Drag Handle -->
806
-
807
-
808
- <!-- Field Selector -->
809
- <div class="col-span-2 flex">
810
- <button
811
- pButton
812
- icon="pi pi-bars"
813
- type="button"
814
- class="p-button-text p-button-plain cursor-move"
815
- pTooltip="اسحب لتغيير الأولوية"
816
- tooltipPosition="top">
817
- </button>
818
- <p-select
819
- [options]="getAvailableFields(sort.field)"
820
- optionLabel="label"
821
- optionValue="key"
822
- [(ngModel)]="sort.field"
823
- (onChange)="updateValue()"
824
- placeholder="اختر الحقل للترتيب"
825
- [showClear]="true"
826
- appendTo="body"
827
- styleClass="w-full">
828
- </p-select>
829
- </div>
830
-
831
-
832
- <!-- Direction Icon -->
833
- <div class="col-fixed">
834
- <p-select
835
- [options]="directionOptions"
836
- [(ngModel)]="sort.direction"
837
- (onChange)="updateValue()"
838
- placeholder="الاتجاه"
839
- appendTo="body"
840
- styleClass="w-full">
841
- </p-select>
842
- </div>
843
-
844
- <!-- Actions -->
845
- <div class="col-fixed flex gap-2" style="justify-content: flex-end;">
846
-
847
- <!--
848
- <button
849
- outlined
850
- pButton
851
- [icon]="getDirectionIcon(sort.direction)"
852
- type="button"
853
- [ngClass]="'p-button-text p-button-sm' + getDirectionColor(sort.direction)"
854
- pTooltip="{{ sort.direction === 'asc' ? 'تصاعدي' : 'تنازلي' }}"
855
- tooltipPosition="top">
856
- </button> -->
857
- <!-- Move Up -->
858
- <button
859
- outlined
860
- style=" width: var(--p-button-icon-only-width);"
861
- *ngIf="!isFirst"
862
- pButton
863
- icon="pi pi-arrow-up"
864
- type="button"
865
- class=" p-button-sm p-button-success"
866
- (click)="moveSort(i, i - 1)"
867
- pTooltip="تحريك للأعلى"
868
- tooltipPosition="top">
869
- </button>
870
-
871
- <!-- Move Down -->
872
- <button
873
- outlined
874
- style=" width: var(--p-button-icon-only-width);"
875
- *ngIf="!isLast"
876
- pButton
877
- icon="pi pi-arrow-down"
878
- type="button"
879
- class=" p-button-sm p-button-success"
880
- (click)="moveSort(i, i + 1)"
881
- pTooltip="تحريك للأسفل"
882
- tooltipPosition="top">
883
- </button>
884
-
885
- <!-- Remove -->
886
- <button
887
- style=" width: var(--p-button-icon-only-width);"
888
- pButton
889
- icon="pi pi-times"
890
- type="button"
891
- class=" p-button-sm p-button-danger"
892
- (click)="removeSort(i)"
893
- pTooltip="حذف الترتيب"
894
- tooltipPosition="top">
895
- </button>
896
- </div>
897
- </div>
786
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: SortBuilderComponent, isStandalone: true, selector: "formly-sort-builder", usesInheritance: true, ngImport: i0, template: `<div class="sort-builder p-3 border-round border-1 surface-border">
787
+ <div class="mb-6">
788
+ <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || ('SORTING' | translate) }}</h5>
789
+ <p class="text-gray-600 text-sm">{{ ('PRIORITY_HINT' | translate) }}</p>
790
+ </div>
791
+
792
+ <!-- Sort List -->
793
+ <div *ngIf="sorts.length > 0" class="sort-list space-y-2 mb-3">
794
+ <div
795
+ *ngFor="let sort of sorts; let i = index; let isFirst = first; let isLast = last"
796
+ class="sort-row p-2 border-round surface-card"
797
+ pDraggable
798
+ pDroppable
799
+ (onDragStart)="onDragStart(i)"
800
+ (onDrop)="onDrop($event, i)"
801
+ [ngClass]="{'border-left-3 border-primary': isFirst, 'border-left-3 border-200': !isFirst}">
802
+
803
+ <div class="grid grid-cols-4 align-items-center gap-2">
804
+ <!-- Drag Handle -->
805
+ <div class="col-span-2 flex">
806
+ <button
807
+ pButton
808
+ icon="pi pi-bars"
809
+ type="button"
810
+ class="p-button-text p-button-plain cursor-move"
811
+ [pTooltip]="'DRAG_TOOLTIP' | translate"
812
+ tooltipPosition="top">
813
+ </button>
814
+ <p-select
815
+ [options]="getAvailableFields(sort.field)"
816
+ optionLabel="label"
817
+ optionValue="key"
818
+ [(ngModel)]="sort.field"
819
+ (onChange)="updateValue()"
820
+ [placeholder]="'SELECT_FIELD_SORT' | translate"
821
+ [showClear]="true"
822
+ appendTo="body"
823
+ styleClass="w-full">
824
+ </p-select>
825
+ </div>
898
826
 
899
- <!-- Field Info -->
900
- <!-- <div *ngIf="sort.field" class="field-info mt-2 text-sm text-500">
901
- <small>الحقل: {{ getFieldLabel(sort.field) }}</small>
902
- </div> -->
827
+ <!-- Direction Selector -->
828
+ <div class="col-fixed">
829
+ <p-select
830
+ [options]="directionOptions"
831
+ [(ngModel)]="sort.direction"
832
+ (onChange)="updateValue()"
833
+ [placeholder]="'DIRECTION' | translate"
834
+ appendTo="body"
835
+ styleClass="w-full">
836
+ </p-select>
903
837
  </div>
904
- </div>
905
838
 
906
- <!-- Empty State -->
907
- <div *ngIf="sorts.length === 0" class="empty-state text-center p-4 border-round surface-section">
908
- <i class="pi pi-sort-alt text-4xl text-500 mb-3"></i>
909
- <p class="text-500 mb-3">لا توجد قواعد ترتيب محددة</p>
910
- <p class="text-400 text-sm mb-3">سيتم استخدام الترتيب الافتراضي للبيانات</p>
911
- </div>
839
+ <!-- Actions -->
840
+ <div class="col-fixed flex gap-2" style="justify-content: flex-end;">
841
+ <!-- Move Up -->
842
+ <button
843
+ outlined
844
+ style="width: var(--p-button-icon-only-width);"
845
+ *ngIf="!isFirst"
846
+ pButton
847
+ icon="pi pi-arrow-up"
848
+ type="button"
849
+ class="p-button-sm p-button-success"
850
+ (click)="moveSort(i, i - 1)"
851
+ [pTooltip]="'MOVE_UP' | translate"
852
+ tooltipPosition="top">
853
+ </button>
912
854
 
913
- <!-- Actions -->
914
- <div class="flex gap-2">
915
- <button
916
- pButton
917
- icon="pi pi-sort-alt"
918
- label="إضافة ترتيب"
919
- type="button"
920
- class="p-button-outlined flex-1"
921
- (click)="addSort()">
922
- </button>
923
-
924
- <button
925
- *ngIf="sorts.length > 1"
926
- pButton
927
- icon="pi pi-random"
928
- label="عكس الترتيب"
929
- type="button"
930
- class="p-button-outlined"
931
- (click)="reverseSorts()"
932
- pTooltip="عكس اتجاه جميع قواعد الترتيب"
933
- tooltipPosition="top">
934
- </button>
935
-
936
- <button
937
- *ngIf="sorts.length > 0"
938
- pButton
939
- icon="pi pi-trash"
940
- type="button"
941
- class="p-button-outlined p-button-danger"
942
- (click)="clearAll()"
943
- pTooltip="مسح جميع قواعد الترتيب"
944
- tooltipPosition="top">
945
- </button>
946
- </div>
855
+ <!-- Move Down -->
856
+ <button
857
+ outlined
858
+ style="width: var(--p-button-icon-only-width);"
859
+ *ngIf="!isLast"
860
+ pButton
861
+ icon="pi pi-arrow-down"
862
+ type="button"
863
+ class="p-button-sm p-button-success"
864
+ (click)="moveSort(i, i + 1)"
865
+ [pTooltip]="'MOVE_DOWN' | translate"
866
+ tooltipPosition="top">
867
+ </button>
947
868
 
948
- <!-- Summary -->
949
- <div *ngIf="sorts.length > 0" class="sort-summary mt-3 p-2 border-round surface-ground">
950
- <h5 class="mt-0 mb-2 text-sm">ملخص الترتيب:</h5>
951
- <div class="text-sm text-500">
952
- <span *ngFor="let sort of sorts; let i = index" class="sort-step">
953
- <span class="font-semibold">{{ getFieldLabel(sort.field) }}</span>
954
- <span class="direction-badge" [ngClass]="sort.direction === 'asc' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'">
955
- {{ sort.direction === 'asc' ? '▲' : '▼' }}
956
- </span>
957
- <span *ngIf="!isLast"> ثم </span>
958
- </span>
869
+ <!-- Remove -->
870
+ <button
871
+ style="width: var(--p-button-icon-only-width);"
872
+ pButton
873
+ icon="pi pi-times"
874
+ type="button"
875
+ class="p-button-sm p-button-danger"
876
+ (click)="removeSort(i)"
877
+ [pTooltip]="'REMOVE_SORT' | translate"
878
+ tooltipPosition="top">
879
+ </button>
959
880
  </div>
960
881
  </div>
961
882
  </div>
962
- `, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i5$1.Draggable, selector: "[pDraggable]", inputs: ["pDraggable", "dragEffect", "dragHandle", "pDraggableDisabled"], outputs: ["onDragStart", "onDragEnd", "onDrag"] }, { kind: "directive", type: i5$1.Droppable, selector: "[pDroppable]", inputs: ["pDroppable", "pDroppableDisabled", "dropEffect"], outputs: ["onDragEnter", "onDragLeave", "onDrop"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }] });
883
+ </div>
884
+
885
+ <!-- Empty State -->
886
+ <div *ngIf="sorts.length === 0" class="empty-state text-center p-4 border-round surface-section">
887
+ <i class="pi pi-sort-alt text-4xl text-500 mb-3"></i>
888
+ <p class="text-500 mb-3">{{ 'NO_SORT_RULES' | translate }}</p>
889
+ <p class="text-400 text-sm mb-3">{{ 'DEFAULT_ORDER' | translate }}</p>
890
+ </div>
891
+
892
+ <!-- Actions -->
893
+ <div class="flex gap-2">
894
+ <button
895
+ pButton
896
+ icon="pi pi-sort-alt"
897
+ [label]="'ADD_SORT' | translate"
898
+ type="button"
899
+ class="p-button-outlined flex-1"
900
+ (click)="addSort()">
901
+ </button>
902
+
903
+ <button
904
+ *ngIf="sorts.length > 1"
905
+ pButton
906
+ icon="pi pi-random"
907
+ [label]="'REVERSE_ORDER' | translate"
908
+ type="button"
909
+ class="p-button-outlined"
910
+ (click)="reverseSorts()"
911
+ [pTooltip]="'REVERSE_TOOLTIP' | translate"
912
+ tooltipPosition="top">
913
+ </button>
914
+
915
+ <button
916
+ *ngIf="sorts.length > 0"
917
+ pButton
918
+ icon="pi pi-trash"
919
+ type="button"
920
+ class="p-button-outlined p-button-danger"
921
+ (click)="clearAll()"
922
+ [pTooltip]="'CLEAR_ALL_TOOLTIP' | translate"
923
+ tooltipPosition="top">
924
+ </button>
925
+ </div>
926
+
927
+ <!-- Summary -->
928
+ <div *ngIf="sorts.length > 0" class="sort-summary mt-3 p-2 border-round surface-ground">
929
+ <h5 class="mt-0 mb-2 text-sm">{{ 'SORT_SUMMARY' | translate }}:</h5>
930
+ <div class="text-sm text-500">
931
+ <span *ngFor="let sort of sorts; let i = index" class="sort-step">
932
+ <span class="font-semibold">{{ getFieldLabel(sort.field) }}</span>
933
+ <span class="direction-badge" [ngClass]="sort.direction === 'asc' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'">
934
+ {{ sort.direction === 'asc' ? '▲' : '▼' }}
935
+ </span>
936
+ <span *ngIf="!isLast"> {{ 'THEN' | translate }} </span>
937
+ </span>
938
+ </div>
939
+ </div>
940
+ </div>`, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i5$1.Draggable, selector: "[pDraggable]", inputs: ["pDraggable", "dragEffect", "dragHandle", "pDraggableDisabled"], outputs: ["onDragStart", "onDragEnd", "onDrag"] }, { kind: "directive", type: i5$1.Droppable, selector: "[pDroppable]", inputs: ["pDroppable", "pDroppableDisabled", "dropEffect"], outputs: ["onDragEnter", "onDragLeave", "onDrop"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i8$1.TranslatePipe, name: "translate" }] });
963
941
  }
964
942
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SortBuilderComponent, decorators: [{
965
943
  type: Component,
@@ -969,184 +947,163 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImpor
969
947
  SelectModule,
970
948
  ButtonModule,
971
949
  DragDropModule,
972
- TooltipModule
973
- ], template: `
974
- <div class="sort-builder p-3 border-round border-1 surface-border">
975
- <div class="flex justify-content-between align-items-center mb-3">
976
- <h4 class="mt-0 mb-0">{{ props.label }}</h4>
977
- <small class="text-500">الأولوية من الأعلى إلى الأسفل</small>
978
- </div>
979
-
980
- <!-- Sort List -->
981
- <div *ngIf="sorts.length > 0" class="sort-list space-y-2 mb-3">
982
- <div
983
- *ngFor="let sort of sorts; let i = index; let isFirst = first; let isLast = last"
984
- class="sort-row p-2 border-round surface-card"
985
- pDraggable
986
- pDroppable
987
- (onDragStart)="onDragStart(i)"
988
- (onDrop)="onDrop($event, i)"
989
- [ngClass]="{'border-left-3 border-primary': isFirst, 'border-left-3 border-200': !isFirst}">
990
-
991
- <div class="grid grid-cols-4 align-items-center gap-2">
992
- <!-- Drag Handle -->
993
-
994
-
995
- <!-- Field Selector -->
996
- <div class="col-span-2 flex">
997
- <button
998
- pButton
999
- icon="pi pi-bars"
1000
- type="button"
1001
- class="p-button-text p-button-plain cursor-move"
1002
- pTooltip="اسحب لتغيير الأولوية"
1003
- tooltipPosition="top">
1004
- </button>
1005
- <p-select
1006
- [options]="getAvailableFields(sort.field)"
1007
- optionLabel="label"
1008
- optionValue="key"
1009
- [(ngModel)]="sort.field"
1010
- (onChange)="updateValue()"
1011
- placeholder="اختر الحقل للترتيب"
1012
- [showClear]="true"
1013
- appendTo="body"
1014
- styleClass="w-full">
1015
- </p-select>
1016
- </div>
1017
-
1018
-
1019
- <!-- Direction Icon -->
1020
- <div class="col-fixed">
1021
- <p-select
1022
- [options]="directionOptions"
1023
- [(ngModel)]="sort.direction"
1024
- (onChange)="updateValue()"
1025
- placeholder="الاتجاه"
1026
- appendTo="body"
1027
- styleClass="w-full">
1028
- </p-select>
1029
- </div>
1030
-
1031
- <!-- Actions -->
1032
- <div class="col-fixed flex gap-2" style="justify-content: flex-end;">
1033
-
1034
- <!--
1035
- <button
1036
- outlined
1037
- pButton
1038
- [icon]="getDirectionIcon(sort.direction)"
1039
- type="button"
1040
- [ngClass]="'p-button-text p-button-sm' + getDirectionColor(sort.direction)"
1041
- pTooltip="{{ sort.direction === 'asc' ? 'تصاعدي' : 'تنازلي' }}"
1042
- tooltipPosition="top">
1043
- </button> -->
1044
- <!-- Move Up -->
1045
- <button
1046
- outlined
1047
- style=" width: var(--p-button-icon-only-width);"
1048
- *ngIf="!isFirst"
1049
- pButton
1050
- icon="pi pi-arrow-up"
1051
- type="button"
1052
- class=" p-button-sm p-button-success"
1053
- (click)="moveSort(i, i - 1)"
1054
- pTooltip="تحريك للأعلى"
1055
- tooltipPosition="top">
1056
- </button>
1057
-
1058
- <!-- Move Down -->
1059
- <button
1060
- outlined
1061
- style=" width: var(--p-button-icon-only-width);"
1062
- *ngIf="!isLast"
1063
- pButton
1064
- icon="pi pi-arrow-down"
1065
- type="button"
1066
- class=" p-button-sm p-button-success"
1067
- (click)="moveSort(i, i + 1)"
1068
- pTooltip="تحريك للأسفل"
1069
- tooltipPosition="top">
1070
- </button>
1071
-
1072
- <!-- Remove -->
1073
- <button
1074
- style=" width: var(--p-button-icon-only-width);"
1075
- pButton
1076
- icon="pi pi-times"
1077
- type="button"
1078
- class=" p-button-sm p-button-danger"
1079
- (click)="removeSort(i)"
1080
- pTooltip="حذف الترتيب"
1081
- tooltipPosition="top">
1082
- </button>
1083
- </div>
1084
- </div>
950
+ TooltipModule,
951
+ TranslateModule
952
+ ], template: `<div class="sort-builder p-3 border-round border-1 surface-border">
953
+ <div class="mb-6">
954
+ <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || ('SORTING' | translate) }}</h5>
955
+ <p class="text-gray-600 text-sm">{{ ('PRIORITY_HINT' | translate) }}</p>
956
+ </div>
957
+
958
+ <!-- Sort List -->
959
+ <div *ngIf="sorts.length > 0" class="sort-list space-y-2 mb-3">
960
+ <div
961
+ *ngFor="let sort of sorts; let i = index; let isFirst = first; let isLast = last"
962
+ class="sort-row p-2 border-round surface-card"
963
+ pDraggable
964
+ pDroppable
965
+ (onDragStart)="onDragStart(i)"
966
+ (onDrop)="onDrop($event, i)"
967
+ [ngClass]="{'border-left-3 border-primary': isFirst, 'border-left-3 border-200': !isFirst}">
968
+
969
+ <div class="grid grid-cols-4 align-items-center gap-2">
970
+ <!-- Drag Handle -->
971
+ <div class="col-span-2 flex">
972
+ <button
973
+ pButton
974
+ icon="pi pi-bars"
975
+ type="button"
976
+ class="p-button-text p-button-plain cursor-move"
977
+ [pTooltip]="'DRAG_TOOLTIP' | translate"
978
+ tooltipPosition="top">
979
+ </button>
980
+ <p-select
981
+ [options]="getAvailableFields(sort.field)"
982
+ optionLabel="label"
983
+ optionValue="key"
984
+ [(ngModel)]="sort.field"
985
+ (onChange)="updateValue()"
986
+ [placeholder]="'SELECT_FIELD_SORT' | translate"
987
+ [showClear]="true"
988
+ appendTo="body"
989
+ styleClass="w-full">
990
+ </p-select>
991
+ </div>
1085
992
 
1086
- <!-- Field Info -->
1087
- <!-- <div *ngIf="sort.field" class="field-info mt-2 text-sm text-500">
1088
- <small>الحقل: {{ getFieldLabel(sort.field) }}</small>
1089
- </div> -->
993
+ <!-- Direction Selector -->
994
+ <div class="col-fixed">
995
+ <p-select
996
+ [options]="directionOptions"
997
+ [(ngModel)]="sort.direction"
998
+ (onChange)="updateValue()"
999
+ [placeholder]="'DIRECTION' | translate"
1000
+ appendTo="body"
1001
+ styleClass="w-full">
1002
+ </p-select>
1090
1003
  </div>
1091
- </div>
1092
1004
 
1093
- <!-- Empty State -->
1094
- <div *ngIf="sorts.length === 0" class="empty-state text-center p-4 border-round surface-section">
1095
- <i class="pi pi-sort-alt text-4xl text-500 mb-3"></i>
1096
- <p class="text-500 mb-3">لا توجد قواعد ترتيب محددة</p>
1097
- <p class="text-400 text-sm mb-3">سيتم استخدام الترتيب الافتراضي للبيانات</p>
1098
- </div>
1005
+ <!-- Actions -->
1006
+ <div class="col-fixed flex gap-2" style="justify-content: flex-end;">
1007
+ <!-- Move Up -->
1008
+ <button
1009
+ outlined
1010
+ style="width: var(--p-button-icon-only-width);"
1011
+ *ngIf="!isFirst"
1012
+ pButton
1013
+ icon="pi pi-arrow-up"
1014
+ type="button"
1015
+ class="p-button-sm p-button-success"
1016
+ (click)="moveSort(i, i - 1)"
1017
+ [pTooltip]="'MOVE_UP' | translate"
1018
+ tooltipPosition="top">
1019
+ </button>
1099
1020
 
1100
- <!-- Actions -->
1101
- <div class="flex gap-2">
1102
- <button
1103
- pButton
1104
- icon="pi pi-sort-alt"
1105
- label="إضافة ترتيب"
1106
- type="button"
1107
- class="p-button-outlined flex-1"
1108
- (click)="addSort()">
1109
- </button>
1110
-
1111
- <button
1112
- *ngIf="sorts.length > 1"
1113
- pButton
1114
- icon="pi pi-random"
1115
- label="عكس الترتيب"
1116
- type="button"
1117
- class="p-button-outlined"
1118
- (click)="reverseSorts()"
1119
- pTooltip="عكس اتجاه جميع قواعد الترتيب"
1120
- tooltipPosition="top">
1121
- </button>
1122
-
1123
- <button
1124
- *ngIf="sorts.length > 0"
1125
- pButton
1126
- icon="pi pi-trash"
1127
- type="button"
1128
- class="p-button-outlined p-button-danger"
1129
- (click)="clearAll()"
1130
- pTooltip="مسح جميع قواعد الترتيب"
1131
- tooltipPosition="top">
1132
- </button>
1133
- </div>
1021
+ <!-- Move Down -->
1022
+ <button
1023
+ outlined
1024
+ style="width: var(--p-button-icon-only-width);"
1025
+ *ngIf="!isLast"
1026
+ pButton
1027
+ icon="pi pi-arrow-down"
1028
+ type="button"
1029
+ class="p-button-sm p-button-success"
1030
+ (click)="moveSort(i, i + 1)"
1031
+ [pTooltip]="'MOVE_DOWN' | translate"
1032
+ tooltipPosition="top">
1033
+ </button>
1134
1034
 
1135
- <!-- Summary -->
1136
- <div *ngIf="sorts.length > 0" class="sort-summary mt-3 p-2 border-round surface-ground">
1137
- <h5 class="mt-0 mb-2 text-sm">ملخص الترتيب:</h5>
1138
- <div class="text-sm text-500">
1139
- <span *ngFor="let sort of sorts; let i = index" class="sort-step">
1140
- <span class="font-semibold">{{ getFieldLabel(sort.field) }}</span>
1141
- <span class="direction-badge" [ngClass]="sort.direction === 'asc' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'">
1142
- {{ sort.direction === 'asc' ? '▲' : '▼' }}
1143
- </span>
1144
- <span *ngIf="!isLast"> ثم </span>
1145
- </span>
1035
+ <!-- Remove -->
1036
+ <button
1037
+ style="width: var(--p-button-icon-only-width);"
1038
+ pButton
1039
+ icon="pi pi-times"
1040
+ type="button"
1041
+ class="p-button-sm p-button-danger"
1042
+ (click)="removeSort(i)"
1043
+ [pTooltip]="'REMOVE_SORT' | translate"
1044
+ tooltipPosition="top">
1045
+ </button>
1146
1046
  </div>
1147
1047
  </div>
1148
1048
  </div>
1149
- ` }]
1049
+ </div>
1050
+
1051
+ <!-- Empty State -->
1052
+ <div *ngIf="sorts.length === 0" class="empty-state text-center p-4 border-round surface-section">
1053
+ <i class="pi pi-sort-alt text-4xl text-500 mb-3"></i>
1054
+ <p class="text-500 mb-3">{{ 'NO_SORT_RULES' | translate }}</p>
1055
+ <p class="text-400 text-sm mb-3">{{ 'DEFAULT_ORDER' | translate }}</p>
1056
+ </div>
1057
+
1058
+ <!-- Actions -->
1059
+ <div class="flex gap-2">
1060
+ <button
1061
+ pButton
1062
+ icon="pi pi-sort-alt"
1063
+ [label]="'ADD_SORT' | translate"
1064
+ type="button"
1065
+ class="p-button-outlined flex-1"
1066
+ (click)="addSort()">
1067
+ </button>
1068
+
1069
+ <button
1070
+ *ngIf="sorts.length > 1"
1071
+ pButton
1072
+ icon="pi pi-random"
1073
+ [label]="'REVERSE_ORDER' | translate"
1074
+ type="button"
1075
+ class="p-button-outlined"
1076
+ (click)="reverseSorts()"
1077
+ [pTooltip]="'REVERSE_TOOLTIP' | translate"
1078
+ tooltipPosition="top">
1079
+ </button>
1080
+
1081
+ <button
1082
+ *ngIf="sorts.length > 0"
1083
+ pButton
1084
+ icon="pi pi-trash"
1085
+ type="button"
1086
+ class="p-button-outlined p-button-danger"
1087
+ (click)="clearAll()"
1088
+ [pTooltip]="'CLEAR_ALL_TOOLTIP' | translate"
1089
+ tooltipPosition="top">
1090
+ </button>
1091
+ </div>
1092
+
1093
+ <!-- Summary -->
1094
+ <div *ngIf="sorts.length > 0" class="sort-summary mt-3 p-2 border-round surface-ground">
1095
+ <h5 class="mt-0 mb-2 text-sm">{{ 'SORT_SUMMARY' | translate }}:</h5>
1096
+ <div class="text-sm text-500">
1097
+ <span *ngFor="let sort of sorts; let i = index" class="sort-step">
1098
+ <span class="font-semibold">{{ getFieldLabel(sort.field) }}</span>
1099
+ <span class="direction-badge" [ngClass]="sort.direction === 'asc' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'">
1100
+ {{ sort.direction === 'asc' ? '▲' : '▼' }}
1101
+ </span>
1102
+ <span *ngIf="!isLast"> {{ 'THEN' | translate }} </span>
1103
+ </span>
1104
+ </div>
1105
+ </div>
1106
+ </div>` }]
1150
1107
  }] });
1151
1108
 
1152
1109
  // query-builder.component.ts
@@ -1437,7 +1394,7 @@ class QueryBuilderComponent extends FieldType {
1437
1394
  }
1438
1395
  }
1439
1396
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: QueryBuilderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1440
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: QueryBuilderComponent, isStandalone: true, selector: "formly-query-builder", usesInheritance: true, ngImport: i0, template: "<div>\r\n\r\n <!-- Groups Container with Connecting Lines -->\r\n <div class=\"groups-container\" #groupsContainer>\r\n <div *ngFor=\"let group of groups; let groupIndex = index\"\r\n class=\"group-wrapper relative\"\r\n #groupElement>\r\n\r\n <!-- Vertical Connector Line from Previous Group -->\r\n<div *ngIf=\"groupIndex > 0\" class=\"vertical-connector\">\r\n <div class=\"vertical-line\"></div>\r\n\r\n <!-- Operator Button -->\r\n <button\r\n type=\"button\"\r\n class=\"group-logical-operator-box\"\r\n [class.and]=\"group.groupLogicalOperator === 'and'\"\r\n [class.or]=\"group.groupLogicalOperator === 'or'\"\r\n (click)=\"opPopover.toggle($event)\">\r\n <span class=\"operator-text\">\r\n {{ getLogicalOperatorText(group.groupLogicalOperator || 'and') }}\r\n </span>\r\n <div class=\"connector-arrow\"></div>\r\n </button>\r\n\r\n <!-- Popover -->\r\n <p-popover #opPopover appendTo=\"body\">\r\n <div class=\"w-12rem\">\r\n <p-listbox\r\n [options]=\"logicalOperators\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(ngModel)]=\"group.groupLogicalOperator\"\r\n (onChange)=\" opPopover.toggle($event)\"\r\n [style]=\"{ width: '100%' }\">\r\n </p-listbox>\r\n </div>\r\n </p-popover>\r\n</div>\r\n\r\n <div class=\"group-container mb-6 p-1 bg-white rounded-lg border-l-4 border-t-1 border-b-1 border-r-1 shadow-sm transition-all duration-300 relative\"\r\n [class.border-blue-500]=\"group.logicalOperator === 'and'\"\r\n [class.border-or-500]=\"group.logicalOperator === 'or'\"\r\n [class.pulse]=\"groupIndex === 0\">\r\n\r\n <!-- Rounded Button for \"\u0631\u0628\u0637 \u0627\u0644\u0634\u0631\u0648\u0637\" on left border -->\r\n<div\r\n class=\"absolute -left-4 top-1/2 transform -translate-y-1/2 z-10 transition-all duration-300\"\r\n\r\n>\r\n\r\n\r\n\r\n<!-- Logical Operator Popover Button -->\r\n<p-button\r\n [severity]=\"group.logicalOperator === 'and' ? 'success' : 'info'\"\r\n [styleClass]=\"group.logicalOperator === 'and'\r\n ? 'p-button-icon-only p-button-rounded p-button-sm logical-and'\r\n : 'p-button-icon-only p-button-rounded p-button-sm logical-or'\"\r\n (click)=\"opPopover.toggle($event)\">\r\n {{group.logicalOperator === 'and' ? ('and' | translate) : ('or' | translate)}}\r\n</p-button>\r\n\r\n<!-- Popover for Operator Selection -->\r\n<p-popover #opPopover appendTo=\"body\">\r\n <div class=\"w-10rem\">\r\n <p-listbox\r\n [options]=\"[\r\n { label: 'and' | translate, value: 'and' },\r\n { label: 'or' | translate, value: 'or' }\r\n ]\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(ngModel)]=\"group.logicalOperator\"\r\n (onChange)=\"updateValue(); opPopover.toggle($event)\"\r\n [style]=\"{ width: '100%' }\">\r\n <ng-template let-item pTemplate=\"item\">\r\n {{ item.label }}\r\n </ng-template>\r\n </p-listbox>\r\n </div>\r\n</p-popover>\r\n\r\n</div>\r\n\r\n\r\n\r\n <!-- Group Header -->\r\n <div class=\"group-header-wrapper mb-4 pl-8\">\r\n <div class=\"group-header flex justify-between items-center\">\r\n\r\n <div class=\"flex gap-1\">\r\n <button\r\n pButton\r\n icon=\"pi pi-plus\"\r\n type=\"button\"\r\n class=\"p-button-success p-button p-button-sm !p-1.5 rounded-md transition-colors\"\r\n (click)=\"addCondition(groupIndex)\"\r\n pTooltip=\"{{ 'ADD_CONDITION' | translate }}\"\r\n tooltipPosition=\"top\">\r\n </button>\r\n <button\r\n *ngIf=\"groups.length > 1\"\r\n pButton\r\n icon=\"pi pi-times\"\r\n type=\"button\"\r\n class=\"p-button-danger p-button p-button-sm !p-1.5 rounded-md transition-colors\"\r\n (click)=\"removeGroup(groupIndex)\"\r\n pTooltip=\"{{ 'DELETE_GROUP' | translate }}\"\r\n tooltipPosition=\"top\">\r\n </button>\r\n</div>\r\n </div>\r\n </div>\r\n\r\n <!-- Conditions in this group -->\r\n <div *ngFor=\"let condition of group.conditions; let conditionIndex = index\"\r\n class=\"p-1 bg-gray-50 \">\r\n <div class=\"grid grid-cols-1 gap-1 items-center\">\r\n <!-- Field Selector -->\r\n <div class=\"md:col-span-2\">\r\n <div class=\"flex w-full rounded-md overflow-hidden border border-gray-300 bg-white shadow-sm\">\r\n <!-- Field Selector Button -->\r\n <div style=\"align-items: center;display: flex; min-width: 130px;max-width: 130px;\" class=\"flex-shrink-0 \">\r\n <button\r\n type=\"button\"\r\n style=\"height: -webkit-fill-available;\"\r\n class=\"flex items-center justify-between w-full px-3 py-2 text-sm bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:z-10\"\r\n (click)=\"overlay.toggle($event)\">\r\n <span style=\"\r\n display: inline-block;\r\n max-width: 100px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n \">{{ getFieldLabel(condition.field) || ('SELECT_FIELD' | translate) }}</span>\r\n <i class=\"pi pi-chevron-down mr-2 ml-2 text-xs\"></i>\r\n </button>\r\n\r\n <!-- Overlay Content -->\r\n <p-popover #overlay appendTo=\"body\">\r\n <div class=\"w-60\">\r\n <p-listbox\r\n tabindex=\"0\"\r\n [options]=\"props['fields']\"\r\n optionLabel=\"label\"\r\n optionValue=\"key\"\r\n [(ngModel)]=\"condition.field\"\r\n (onChange)=\"onFieldChange(condition, groupIndex, conditionIndex); overlay.toggle($event)\"\r\n [style]=\"{ width: '100%' }\">\r\n </p-listbox>\r\n </div>\r\n </p-popover>\r\n </div>\r\n <!-- Operator Button -->\r\n <div style=\"align-items: center;display: flex;\" class=\"flex-shrink-0 border-l border-r border-gray-300\">\r\n <button\r\n type=\"button\"\r\n class=\"flex items-center justify-center w-full px-3 py-2 text-sm bg-gray-50 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:z-10\"\r\n style=\"height: -webkit-fill-available;\"\r\n pTooltip=\"{{ getOperatorLabel(condition.operator).label }}\"\r\n (click)=\"opPopover.toggle($event)\">\r\n <i [class]=\"getOperatorLabel(condition.operator).icon\"></i>\r\n </button>\r\n\r\n <p-popover #opPopover appendTo=\"body\">\r\n <div class=\"w-60\">\r\n <p-listbox\r\n [options]=\"condition.operatorsForField\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(ngModel)]=\"condition.operator\"\r\n (onChange)=\"opPopover.toggle($event)\"\r\n [style]=\"{ width: '100%' }\">\r\n </p-listbox>\r\n </div>\r\n </p-popover>\r\n </div>\r\n <!-- Form Field -->\r\n <div style=\"background: #f9fafb\" class=\"flex-grow p-1\">\r\n <formly-form\r\n [form]=\"form\"\r\n [fields]=\"[condition.valueFieldConfig]\"\r\n [model]=\"model\">\r\n </formly-form>\r\n </div>\r\n\r\n\r\n\r\n <!-- Delete Button -->\r\n <div style=\"align-items: center;display: flex;\" class=\"flex-shrink-0\">\r\n <button\r\n style=\"height: -webkit-fill-available;\"\r\n class=\"flex items-center justify-center w-full px-3 py-2 text-sm bg-red-50 text-red-600 hover:bg-red-100 focus:outline-none focus:ring-2 focus:ring-red-500 focus:z-10\"\r\n type=\"button\"\r\n (click)=\"removeCondition(groupIndex, conditionIndex)\"\r\n pTooltip=\"\u062D\u0630\u0641 \u0627\u0644\u0634\u0631\u0637\"\r\n tooltipPosition=\"top\">\r\n <i class=\"pi pi-times\"></i>\r\n </button>\r\n </div>\r\n</div>\r\n </div>\r\n\r\n\r\n </div>\r\n </div>\r\n\r\n <!-- Group Footer -->\r\n <div class=\"group-footer flex justify-between items-center mt-3 pt-3 border-t border-gray-200 \">\r\n <small class=\"text-gray-500\">\r\n {{ group.conditions.length }} \u0634\u0631\u0637 \u0641\u064A \u0647\u0630\u0647 \u0627\u0644\u0645\u062C\u0645\u0648\u0639\u0629\r\n </small>\r\n <small class=\"text-gray-500\">\r\n <span *ngIf=\"groupIndex > 0\">\r\n \u0645\u0631\u062A\u0628\u0637 \u0645\u0639 \u0627\u0644\u0633\u0627\u0628\u0642\u0629 \u0628\u0640 <strong [class.text-blue-600]=\"group.groupLogicalOperator === 'and'\"\r\n [class.text-amber-600]=\"group.groupLogicalOperator === 'or'\">\r\n {{ group.groupLogicalOperator === 'and' ? '\u0648' : '\u0623\u0648' }}\r\n </strong>\r\n </span>\r\n </small>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Actions -->\r\n<div class=\"flex flex-wrap gap-3 mt-6\">\r\n <button\r\n pButton\r\n type=\"button\"\r\n icon=\"pi pi-plus\"\r\n [label]=\"'GROUP' | translate\"\r\n class=\"p-button-outlined p-button-sm !bg-white !border !border-blue-500 !text-blue-600 hover:!bg-blue-50 transition-colors flex items-center gap-2\"\r\n (click)=\"addGroup();\">\r\n </button>\r\n\r\n <button\r\n pButton\r\n type=\"button\"\r\n icon=\"pi pi-plus\"\r\n [label]=\"'CONDITION' | translate\"\r\n class=\"p-button-outlined p-button-sm !bg-white !border !border-blue-500 !text-blue-600 hover:!bg-blue-50 transition-colors flex items-center gap-2\"\r\n (click)=\"addConditionToLastGroup()\">\r\n </button>\r\n\r\n <button\r\n *ngIf=\"groups.length > 0\"\r\n pButton\r\n type=\"button\"\r\n icon=\"pi pi-trash\"\r\n [label]=\"'CLEAR' | translate\"\r\n class=\"p-button-danger p-button-outlined p-button-sm !bg-white !border !border-red-500 !text-red-600 hover:!bg-red-50 transition-colors flex items-center gap-2\"\r\n (click)=\"clearAll()\">\r\n </button>\r\n</div>\r\n\r\n<!-- Empty State -->\r\n<div *ngIf=\"groups.length === 0\" class=\"empty-state text-center p-6 border-2 border-dashed border-gray-300 rounded-xl bg-gray-50\">\r\n <i class=\"pi pi-search text-4xl text-gray-400 mb-3\"></i>\r\n <p class=\"text-gray-500 mb-4\">{{ 'NO_SEARCH_CONDITIONS' | translate }}</p>\r\n <button\r\n pButton\r\n type=\"button\"\r\n icon=\"pi pi-plus\"\r\n [label]=\"'ADD_SEARCH_CONDITION' | translate\"\r\n class=\"p-button-outlined !px-4 !py-2\"\r\n (click)=\"addGroup()\">\r\n </button>\r\n</div>\r\n</div>\r\n", styles: [".vertical-connector{position:relative;display:flex;justify-content:center;margin-bottom:1rem}.vertical-line{position:absolute;top:-1rem;height:1rem;width:2px;background-color:#d1d5db}.group-logical-operator-box{position:relative;padding:.25rem .75rem;border-radius:.375rem;font-weight:500;font-size:.75rem;z-index:10;transition:all .3s ease}.group-logical-operator-box.and{background-color:#dbeafe;color:#1d4ed8;border:1px solid #93c5fd}.group-logical-operator-box.or{background-color:#fef3c7;color:#92400e;border:1px solid #fcd34d}.connector-arrow{position:absolute;top:100%;left:50%;transform:translate(-50%);width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent}.group-logical-operator-box.and .connector-arrow{border-top:6px solid #93c5fd}.group-logical-operator-box.or .connector-arrow{border-top:6px solid #fcd34d}.border-blue-500{border-color:#93c5fd}.border-or-500{border-color:#fcd34d}.border-t-1{border-top-width:1px}.border-b-1{border-bottom-width:1px}.border-r-1{border-right-width:1px}.p-popover-content{padding:5px!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: SelectModule }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DatePickerModule }, { kind: "ngmodule", type: CheckboxModule }, { kind: "ngmodule", type: RadioButtonModule }, { kind: "component", type: FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "ngmodule", type: MenuModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: InputGroupModule }, { kind: "ngmodule", type: InputGroupAddonModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i6$2.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: ListboxModule }, { kind: "component", type: i7$1.Listbox, selector: "p-listbox, p-listBox, p-list-box", inputs: ["id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "ariaLabel", "selectOnFocus", "searchLocale", "focusOnHover", "filterMessage", "filterFields", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "scrollHeight", "tabindex", "multiple", "styleClass", "listStyle", "listStyleClass", "readonly", "checkbox", "filter", "filterBy", "filterMatchMode", "filterLocale", "metaKeySelection", "dataKey", "showToggleAll", "optionLabel", "optionValue", "optionGroupChildren", "optionGroupLabel", "optionDisabled", "ariaFilterLabel", "filterPlaceHolder", "emptyFilterMessage", "emptyMessage", "group", "options", "filterValue", "selectAll", "striped", "highlightOnSelect", "checkmark", "dragdrop", "fluid"], outputs: ["onChange", "onClick", "onDblClick", "onFilter", "onFocus", "onBlur", "onSelectAllChange", "onLazyLoad", "onDrop"] }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
1397
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: QueryBuilderComponent, isStandalone: true, selector: "formly-query-builder", usesInheritance: true, ngImport: i0, template: "<div>\r\n\r\n <!-- Groups Container with Connecting Lines -->\r\n <div class=\"groups-container\" #groupsContainer>\r\n <div *ngFor=\"let group of groups; let groupIndex = index\"\r\n class=\"group-wrapper relative\"\r\n #groupElement>\r\n\r\n <!-- Vertical Connector Line from Previous Group -->\r\n<div *ngIf=\"groupIndex > 0\" class=\"vertical-connector\">\r\n <div class=\"vertical-line\"></div>\r\n\r\n <!-- Operator Button -->\r\n <button\r\n type=\"button\"\r\n class=\"group-logical-operator-box\"\r\n [class.and]=\"group.groupLogicalOperator === 'and'\"\r\n [class.or]=\"group.groupLogicalOperator === 'or'\"\r\n (click)=\"opPopover.toggle($event)\">\r\n <span class=\"operator-text\">\r\n {{ getLogicalOperatorText(group.groupLogicalOperator || 'and') }}\r\n </span>\r\n <div class=\"connector-arrow\"></div>\r\n </button>\r\n\r\n <!-- Popover -->\r\n <p-popover #opPopover appendTo=\"body\">\r\n <div class=\"w-12rem\">\r\n <p-listbox\r\n [options]=\"logicalOperators\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(ngModel)]=\"group.groupLogicalOperator\"\r\n (onChange)=\" opPopover.toggle($event)\"\r\n [style]=\"{ width: '100%' }\">\r\n </p-listbox>\r\n </div>\r\n </p-popover>\r\n</div>\r\n\r\n <div class=\"group-container mb-6 p-1 bg-white rounded-lg border-l-4 border-t-1 border-b-1 border-r-1 shadow-sm transition-all duration-300 relative\"\r\n [class.border-blue-500]=\"group.logicalOperator === 'and'\"\r\n [class.border-or-500]=\"group.logicalOperator === 'or'\"\r\n [class.pulse]=\"groupIndex === 0\">\r\n\r\n <!-- Rounded Button for \"\u0631\u0628\u0637 \u0627\u0644\u0634\u0631\u0648\u0637\" on left border -->\r\n<div\r\n class=\"absolute -left-4 top-1/2 transform -translate-y-1/2 z-10 transition-all duration-300\"\r\n\r\n>\r\n\r\n\r\n\r\n<!-- Logical Operator Popover Button -->\r\n<p-button\r\n [severity]=\"group.logicalOperator === 'and' ? 'success' : 'info'\"\r\n [styleClass]=\"group.logicalOperator === 'and'\r\n ? 'p-button-icon-only p-button-rounded p-button-sm logical-and'\r\n : 'p-button-icon-only p-button-rounded p-button-sm logical-or'\"\r\n (click)=\"opPopover.toggle($event)\">\r\n {{group.logicalOperator === 'and' ? ('and' | translate) : ('or' | translate)}}\r\n</p-button>\r\n\r\n<!-- Popover for Operator Selection -->\r\n<p-popover #opPopover appendTo=\"body\">\r\n <div class=\"w-10rem\">\r\n <p-listbox\r\n [options]=\"[\r\n { label: 'and' | translate, value: 'and' },\r\n { label: 'or' | translate, value: 'or' }\r\n ]\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(ngModel)]=\"group.logicalOperator\"\r\n (onChange)=\"updateValue(); opPopover.toggle($event)\"\r\n [style]=\"{ width: '100%' }\">\r\n <ng-template let-item pTemplate=\"item\">\r\n {{ item.label }}\r\n </ng-template>\r\n </p-listbox>\r\n </div>\r\n</p-popover>\r\n\r\n</div>\r\n\r\n\r\n\r\n <!-- Group Header -->\r\n <div class=\"group-header-wrapper mb-4 pl-8\">\r\n <div class=\"group-header flex justify-between items-center\">\r\n\r\n <div class=\"flex gap-1\">\r\n <button\r\n pButton\r\n icon=\"pi pi-plus\"\r\n type=\"button\"\r\n class=\"p-button-success p-button p-button-sm !p-1.5 rounded-md transition-colors\"\r\n (click)=\"addCondition(groupIndex)\"\r\n pTooltip=\"{{ 'ADD_CONDITION' | translate }}\"\r\n tooltipPosition=\"top\">\r\n </button>\r\n <button\r\n *ngIf=\"groups.length > 1\"\r\n pButton\r\n icon=\"pi pi-times\"\r\n type=\"button\"\r\n class=\"p-button-danger p-button p-button-sm !p-1.5 rounded-md transition-colors\"\r\n (click)=\"removeGroup(groupIndex)\"\r\n pTooltip=\"{{ 'DELETE_GROUP' | translate }}\"\r\n tooltipPosition=\"top\">\r\n </button>\r\n</div>\r\n </div>\r\n </div>\r\n\r\n <!-- Conditions in this group -->\r\n <div *ngFor=\"let condition of group.conditions; let conditionIndex = index\"\r\n class=\"p-1 bg-gray-50 \">\r\n <div class=\"grid grid-cols-1 gap-1 items-center\">\r\n <!-- Field Selector -->\r\n <div class=\"md:col-span-2\">\r\n <div class=\"flex w-full rounded-md overflow-hidden border border-gray-300 bg-white shadow-sm\">\r\n <!-- Field Selector Button -->\r\n <div style=\"align-items: center;display: flex; min-width: 130px;max-width: 130px;\" class=\"flex-shrink-0 \">\r\n <button\r\n type=\"button\"\r\n style=\"height: -webkit-fill-available;\"\r\n class=\"flex items-center justify-between w-full px-3 py-2 text-sm bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:z-10\"\r\n (click)=\"overlay.toggle($event)\">\r\n <span style=\"\r\n display: inline-block;\r\n max-width: 100px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n \">{{ getFieldLabel(condition.field) || ('SELECT_FIELD' | translate) }}</span>\r\n <i class=\"pi pi-chevron-down mr-2 ml-2 text-xs\"></i>\r\n </button>\r\n\r\n <!-- Overlay Content -->\r\n <p-popover #overlay appendTo=\"body\">\r\n <div class=\"w-60\">\r\n <p-listbox\r\n tabindex=\"0\"\r\n [options]=\"props['fields']\"\r\n optionLabel=\"label\"\r\n optionValue=\"key\"\r\n [(ngModel)]=\"condition.field\"\r\n (onChange)=\"onFieldChange(condition, groupIndex, conditionIndex); overlay.toggle($event)\"\r\n [style]=\"{ width: '100%' }\">\r\n </p-listbox>\r\n </div>\r\n </p-popover>\r\n </div>\r\n <!-- Operator Button -->\r\n <div style=\"align-items: center;display: flex;\" class=\"flex-shrink-0 border-l border-r border-gray-300\">\r\n <button\r\n type=\"button\"\r\n class=\"flex items-center justify-center w-full px-3 py-2 text-sm bg-gray-50 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:z-10\"\r\n style=\"height: -webkit-fill-available;\"\r\n pTooltip=\"{{ getOperatorLabel(condition.operator).label }}\"\r\n (click)=\"opPopover.toggle($event)\">\r\n <i [class]=\"getOperatorLabel(condition.operator).icon\"></i>\r\n </button>\r\n\r\n <p-popover #opPopover appendTo=\"body\">\r\n <div class=\"w-60\">\r\n <p-listbox\r\n [options]=\"condition.operatorsForField\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(ngModel)]=\"condition.operator\"\r\n (onChange)=\"opPopover.toggle($event)\"\r\n [style]=\"{ width: '100%' }\">\r\n </p-listbox>\r\n </div>\r\n </p-popover>\r\n </div>\r\n <!-- Form Field -->\r\n <div style=\"background: #f9fafb\" class=\"flex-grow p-1\">\r\n <formly-form\r\n [form]=\"form\"\r\n [fields]=\"[condition.valueFieldConfig]\"\r\n [model]=\"model\">\r\n </formly-form>\r\n </div>\r\n\r\n\r\n\r\n <!-- Delete Button -->\r\n <div style=\"align-items: center;display: flex;\" class=\"flex-shrink-0\">\r\n <button\r\n style=\"height: -webkit-fill-available;\"\r\n class=\"flex items-center justify-center w-full px-3 py-2 text-sm bg-red-50 text-red-600 hover:bg-red-100 focus:outline-none focus:ring-2 focus:ring-red-500 focus:z-10\"\r\n type=\"button\"\r\n (click)=\"removeCondition(groupIndex, conditionIndex)\"\r\n pTooltip=\"\u062D\u0630\u0641 \u0627\u0644\u0634\u0631\u0637\"\r\n tooltipPosition=\"top\">\r\n <i class=\"pi pi-times\"></i>\r\n </button>\r\n </div>\r\n</div>\r\n </div>\r\n\r\n\r\n </div>\r\n </div>\r\n\r\n <!-- Group Footer -->\r\n <div class=\"group-footer flex justify-between items-center mt-3 pt-3 border-t border-gray-200 \">\r\n <small class=\"text-gray-500\">\r\n {{ group.conditions.length }} \u0634\u0631\u0637 \u0641\u064A \u0647\u0630\u0647 \u0627\u0644\u0645\u062C\u0645\u0648\u0639\u0629\r\n </small>\r\n <small class=\"text-gray-500\">\r\n <span *ngIf=\"groupIndex > 0\">\r\n \u0645\u0631\u062A\u0628\u0637 \u0645\u0639 \u0627\u0644\u0633\u0627\u0628\u0642\u0629 \u0628\u0640 <strong [class.text-blue-600]=\"group.groupLogicalOperator === 'and'\"\r\n [class.text-amber-600]=\"group.groupLogicalOperator === 'or'\">\r\n {{ group.groupLogicalOperator === 'and' ? '\u0648' : '\u0623\u0648' }}\r\n </strong>\r\n </span>\r\n </small>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Actions -->\r\n<div class=\"flex flex-wrap gap-3 mt-6\">\r\n <button\r\n pButton\r\n type=\"button\"\r\n icon=\"pi pi-plus\"\r\n [label]=\"'GROUP' | translate\"\r\n class=\"p-button-outlined p-button-sm !bg-white !border !border-blue-500 !text-blue-600 hover:!bg-blue-50 transition-colors flex items-center gap-2\"\r\n (click)=\"addGroup();\">\r\n </button>\r\n\r\n <button\r\n pButton\r\n type=\"button\"\r\n icon=\"pi pi-plus\"\r\n [label]=\"'CONDITION' | translate\"\r\n class=\"p-button-outlined p-button-sm !bg-white !border !border-blue-500 !text-blue-600 hover:!bg-blue-50 transition-colors flex items-center gap-2\"\r\n (click)=\"addConditionToLastGroup()\">\r\n </button>\r\n\r\n <button\r\n *ngIf=\"groups.length > 0\"\r\n pButton\r\n type=\"button\"\r\n icon=\"pi pi-trash\"\r\n [label]=\"'CLEAR' | translate\"\r\n class=\"p-button-danger p-button-outlined p-button-sm !bg-white !border !border-red-500 !text-red-600 hover:!bg-red-50 transition-colors flex items-center gap-2\"\r\n (click)=\"clearAll()\">\r\n </button>\r\n</div>\r\n\r\n<!-- Empty State -->\r\n<div *ngIf=\"groups.length === 0\" class=\"empty-state text-center p-6 border-2 border-dashed border-gray-300 rounded-xl bg-gray-50\">\r\n <i class=\"pi pi-search text-4xl text-gray-400 mb-3\"></i>\r\n <p class=\"text-gray-500 mb-4\">{{ 'NO_SEARCH_CONDITIONS' | translate }}</p>\r\n <button\r\n pButton\r\n type=\"button\"\r\n icon=\"pi pi-plus\"\r\n [label]=\"'ADD_SEARCH_CONDITION' | translate\"\r\n class=\"p-button-outlined !px-4 !py-2\"\r\n (click)=\"addGroup()\">\r\n </button>\r\n</div>\r\n</div>\r\n", styles: [".vertical-connector{position:relative;display:flex;justify-content:center;margin-bottom:1rem}.vertical-line{position:absolute;top:-1rem;height:1rem;width:2px;background-color:#d1d5db}.group-logical-operator-box{position:relative;padding:.25rem .75rem;border-radius:.375rem;font-weight:500;font-size:.75rem;z-index:10;transition:all .3s ease}.group-logical-operator-box.and{background-color:#dbeafe;color:#1d4ed8;border:1px solid #93c5fd}.group-logical-operator-box.or{background-color:#fef3c7;color:#92400e;border:1px solid #fcd34d}.connector-arrow{position:absolute;top:100%;left:50%;transform:translate(-50%);width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent}.group-logical-operator-box.and .connector-arrow{border-top:6px solid #93c5fd}.group-logical-operator-box.or .connector-arrow{border-top:6px solid #fcd34d}.border-blue-500{border-color:#93c5fd}.border-or-500{border-color:#fcd34d}.border-t-1{border-top-width:1px}.border-b-1{border-bottom-width:1px}.border-r-1{border-right-width:1px}.p-popover-content{padding:5px!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: SelectModule }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "buttonProps", "autofocus", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DatePickerModule }, { kind: "ngmodule", type: CheckboxModule }, { kind: "ngmodule", type: RadioButtonModule }, { kind: "component", type: FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "ngmodule", type: MenuModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: InputGroupModule }, { kind: "ngmodule", type: InputGroupAddonModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i6$2.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: ListboxModule }, { kind: "component", type: i7$1.Listbox, selector: "p-listbox, p-listBox, p-list-box", inputs: ["id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "ariaLabel", "selectOnFocus", "searchLocale", "focusOnHover", "filterMessage", "filterFields", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "scrollHeight", "tabindex", "multiple", "styleClass", "listStyle", "listStyleClass", "readonly", "checkbox", "filter", "filterBy", "filterMatchMode", "filterLocale", "metaKeySelection", "dataKey", "showToggleAll", "optionLabel", "optionValue", "optionGroupChildren", "optionGroupLabel", "optionDisabled", "ariaFilterLabel", "filterPlaceHolder", "emptyFilterMessage", "emptyMessage", "group", "options", "filterValue", "selectAll", "striped", "highlightOnSelect", "checkmark", "dragdrop", "fluid"], outputs: ["onChange", "onClick", "onDblClick", "onFilter", "onFocus", "onBlur", "onSelectAllChange", "onLazyLoad", "onDrop"] }, { kind: "pipe", type: i8$1.TranslatePipe, name: "translate" }] });
1441
1398
  }
1442
1399
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: QueryBuilderComponent, decorators: [{
1443
1400
  type: Component,
@@ -1543,7 +1500,7 @@ class TabTypeComponent extends FieldType {
1543
1500
  </p-tabpanel>
1544
1501
  </p-tabpanels>
1545
1502
  </p-tabs>
1546
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i2$2.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i2$2.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i2$2.TabPanel, selector: "p-tabpanel", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: i2$2.TabList, selector: "p-tablist" }, { kind: "component", type: i2$2.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i9.Badge, selector: "p-badge", inputs: ["styleClass", "badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "component", type: FormlyField, selector: "formly-field", inputs: ["field"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
1503
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i2$2.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i2$2.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i2$2.TabPanel, selector: "p-tabpanel", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: i2$2.TabList, selector: "p-tablist" }, { kind: "component", type: i2$2.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i9.Badge, selector: "p-badge", inputs: ["styleClass", "badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "component", type: FormlyField, selector: "formly-field", inputs: ["field"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i8$1.TranslatePipe, name: "translate" }] });
1547
1504
  }
1548
1505
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: TabTypeComponent, decorators: [{
1549
1506
  type: Component,
@@ -1801,311 +1758,309 @@ class ColumnsBuilderComponent extends FieldType {
1801
1758
  }
1802
1759
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ColumnsBuilderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1803
1760
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: ColumnsBuilderComponent, isStandalone: true, selector: "formly-columns-builder", usesInheritance: true, ngImport: i0, template: `
1804
- <div>
1805
- <!-- Header -->
1806
- <div class="mb-6">
1807
- <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || 'Columns Management' }}</h5>
1808
- <p class="text-gray-600 text-sm">{{ props.description || 'Select and configure columns to display' }}</p>
1809
- </div>
1810
-
1811
- <!-- Quick Actions -->
1812
- <div class="flex flex-wrap gap-2 mb-6">
1813
- <button
1814
- type="button"
1815
- (click)="toggleAll(true)"
1816
- class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
1817
- >
1818
- <i class="pi pi-eye"></i>
1819
- Show All
1820
- </button>
1821
- <button
1822
- type="button"
1823
- (click)="toggleAll(false)"
1824
- class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
1825
- >
1826
- <i class="pi pi-eye-slash"></i>
1827
- Hide All
1828
- </button>
1829
- <button
1830
- type="button"
1831
- (click)="resetToDefault()"
1832
- class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
1833
- >
1834
- <i class="pi pi-refresh"></i>
1835
- Reset to Default
1836
- </button>
1837
- </div>
1838
-
1839
- <!-- Drag Info -->
1840
- <div class="mb-4 p-2 bg-blue-50 border border-blue-200 rounded text-sm text-blue-700">
1841
- <i class="pi pi-info-circle mr-2"></i>
1842
- Drag the handle to reorder columns
1843
- </div>
1844
-
1845
- <!-- Columns List -->
1846
- <div class="space-y-3">
1847
- <div *ngIf="columns.length === 0" class="text-center py-8 px-4 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50">
1848
- <i class="pi pi-table text-4xl text-gray-400 mb-3"></i>
1849
- <p class="text-gray-500">No columns available</p>
1850
- </div>
1761
+ <div>
1762
+ <!-- Header -->
1763
+ <div class="mb-6">
1764
+ <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || ('COLUMNS_MANAGEMENT' | translate) }}</h5>
1765
+ <p class="text-gray-600 text-sm">{{ props.description || ('COLUMNS_DESCRIPTION' | translate) }}</p>
1766
+ </div>
1767
+
1768
+ <!-- Quick Actions -->
1769
+ <div class="flex flex-wrap gap-2 mb-6">
1770
+ <button
1771
+ type="button"
1772
+ (click)="toggleAll(true)"
1773
+ class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
1774
+ >
1775
+ <i class="pi pi-eye"></i>
1776
+ {{ 'SHOW_ALL' | translate }}
1777
+ </button>
1778
+ <button
1779
+ type="button"
1780
+ (click)="toggleAll(false)"
1781
+ class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
1782
+ >
1783
+ <i class="pi pi-eye-slash"></i>
1784
+ {{ 'HIDE_ALL' | translate }}
1785
+ </button>
1786
+ <button
1787
+ type="button"
1788
+ (click)="resetToDefault()"
1789
+ class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
1790
+ >
1791
+ <i class="pi pi-refresh"></i>
1792
+ {{ 'RESET_TO_DEFAULT' | translate }}
1793
+ </button>
1794
+ </div>
1795
+
1796
+ <!-- Drag Info -->
1797
+ <div class="mb-4 p-2 bg-blue-50 border border-blue-200 rounded text-sm text-blue-700">
1798
+ <i class="pi pi-info-circle mr-2"></i>
1799
+ {{ 'DRAG_COLUMNS_INFO' | translate }}
1800
+ </div>
1801
+
1802
+ <!-- Columns List -->
1803
+ <div class="space-y-3">
1804
+ <div *ngIf="columns.length === 0" class="text-center py-8 px-4 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50">
1805
+ <i class="pi pi-table text-4xl text-gray-400 mb-3"></i>
1806
+ <p class="text-gray-500">{{ 'NO_COLUMNS_AVAILABLE' | translate }}</p>
1807
+ </div>
1851
1808
 
1852
- <div *ngFor="let column of columns; let i = index"
1853
- class="bg-gray-50 rounded-lg border border-gray-200 p-1 transition-colors hover:bg-gray-100"
1809
+ <div *ngFor="let column of columns; let i = index"
1810
+ class="bg-gray-50 rounded-lg border border-gray-200 p-1 transition-colors hover:bg-gray-100"
1811
+ draggable="true"
1812
+ (dragstart)="onDragStart($event, i)"
1813
+ (dragover)="onDragOver($event)"
1814
+ (drop)="onDrop($event, i)"
1815
+ (dragenter)="onDragEnter($event)"
1816
+ (dragleave)="onDragLeave($event)">
1817
+
1818
+ <div class="grid grid-cols-12 gap-4 items-center">
1819
+ <!-- Drag Handle -->
1820
+ <div class="col-span-1 flex justify-center cursor-move text-gray-400 hover:text-gray-600"
1854
1821
  draggable="true"
1855
- (dragstart)="onDragStart($event, i)"
1856
- (dragover)="onDragOver($event)"
1857
- (drop)="onDrop($event, i)"
1858
- (dragenter)="onDragEnter($event)"
1859
- (dragleave)="onDragLeave($event)">
1860
-
1861
- <div class="grid grid-cols-12 gap-4 items-center">
1862
- <!-- Drag Handle -->
1863
- <div class="col-span-1 flex justify-center cursor-move text-gray-400 hover:text-gray-600"
1864
- draggable="true"
1865
- (dragstart)="onDragStart($event, i)">
1866
- <i class="pi pi-bars"></i>
1867
- </div>
1868
-
1869
- <!-- Visibility Toggle -->
1870
- <div class="col-span-1 flex justify-center">
1871
- <p-checkbox
1872
- [binary]="true"
1873
- [formControl]="getColumnControl(column.key, 'isVisible')"
1874
- [inputId]="'visible_' + column.key"
1875
- styleClass="[&>div]:border-gray-300 [&>div]:hover:border-gray-400"
1876
- (onChange)="onFormChange()"
1877
- >
1878
- </p-checkbox>
1879
- </div>
1822
+ (dragstart)="onDragStart($event, i)">
1823
+ <i class="pi pi-bars"></i>
1824
+ </div>
1880
1825
 
1881
- <!-- Column Info -->
1882
- <div class="col-span-12 md:col-span-4">
1883
- <label [for]="'visible_' + column.key" class="block font-medium text-gray-900 cursor-pointer hover:text-blue-600">
1884
- {{ column.label }}
1885
- </label>
1886
- <p class="text-xs text-gray-500 mt-1">{{ column.key }}</p>
1887
- </div>
1826
+ <!-- Visibility Toggle -->
1827
+ <div class="col-span-1 flex justify-center">
1828
+ <p-checkbox
1829
+ [binary]="true"
1830
+ [formControl]="getColumnControl(column.key, 'isVisible')"
1831
+ [inputId]="'visible_' + column.key"
1832
+ styleClass="[&>div]:border-gray-300 [&>div]:hover:border-gray-400"
1833
+ (onChange)="onFormChange()"
1834
+ >
1835
+ </p-checkbox>
1836
+ </div>
1888
1837
 
1889
- <!-- Display Name -->
1890
- <div class="col-span-12 md:col-span-3">
1891
- <input
1892
- *ngIf="isColumnVisible(column.key)"
1893
- type="text"
1894
- [formControl]="getColumnControl(column.key, 'displayName')"
1895
- [placeholder]="column.label"
1896
- class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
1897
- (blur)="onFormChange()"
1898
- >
1899
- </div>
1838
+ <!-- Column Info -->
1839
+ <div class="col-span-12 md:col-span-4">
1840
+ <label [for]="'visible_' + column.key" class="block font-medium text-gray-900 cursor-pointer hover:text-blue-600">
1841
+ {{ column.label }}
1842
+ </label>
1843
+ <p class="text-xs text-gray-500 mt-1">{{ column.key }}</p>
1844
+ </div>
1900
1845
 
1901
- <!-- Aggregate Function -->
1902
- <div class="col-span-12 md:col-span-3">
1903
- <div *ngIf="column.aggregatable && isColumnVisible(column.key)">
1904
- <p-select
1905
- [options]="aggregateFunctions"
1906
- optionLabel="label"
1907
- optionValue="value"
1908
- [formControl]="getColumnControl(column.key, 'aggregateFunction')"
1909
- placeholder="Select aggregate"
1910
- [showClear]="true"
1911
- styleClass="w-full"
1912
- (onChange)="onFormChange()"
1913
- >
1914
- </p-select>
1915
- </div>
1916
- <span *ngIf="!column.aggregatable && isColumnVisible(column.key)" class="text-xs text-gray-500">
1917
- No aggregates available
1918
- </span>
1919
- </div>
1920
- </div>
1846
+ <!-- Display Name -->
1847
+ <div class="col-span-12 md:col-span-3">
1848
+ <input
1849
+ *ngIf="isColumnVisible(column.key)"
1850
+ type="text"
1851
+ [formControl]="getColumnControl(column.key, 'displayName')"
1852
+ [placeholder]="column.label"
1853
+ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
1854
+ (blur)="onFormChange()"
1855
+ >
1856
+ </div>
1921
1857
 
1922
- <!-- Aggregate Info -->
1923
- <div *ngIf="hasAggregateFunction(column.key) && isColumnVisible(column.key)"
1924
- class="mt-3 p-3 bg-blue-50 border border-blue-200 rounded-lg">
1925
- <div class="flex items-center gap-2">
1926
- <i class="pi pi-info-circle text-blue-500 text-sm"></i>
1927
- <span class="text-sm text-blue-800">
1928
- Will calculate <strong>{{ getAggregateLabel(getAggregateFunctionValue(column.key)) }}</strong>
1929
- for this column in grouped data
1930
- </span>
1931
- </div>
1858
+ <!-- Aggregate Function -->
1859
+ <div class="col-span-12 md:col-span-3">
1860
+ <div *ngIf="column.aggregatable && isColumnVisible(column.key)">
1861
+ <p-select
1862
+ [options]="aggregateFunctions"
1863
+ optionLabel="label"
1864
+ optionValue="value"
1865
+ [formControl]="getColumnControl(column.key, 'aggregateFunction')"
1866
+ [placeholder]="'SELECT_AGGREGATE' | translate"
1867
+ [showClear]="true"
1868
+ styleClass="w-full"
1869
+ (onChange)="onFormChange()"
1870
+ >
1871
+ </p-select>
1932
1872
  </div>
1873
+ <span *ngIf="!column.aggregatable && isColumnVisible(column.key)" class="text-xs text-gray-500">
1874
+ {{ 'NO_AGGREGATES_AVAILABLE' | translate }}
1875
+ </span>
1933
1876
  </div>
1934
1877
  </div>
1935
1878
 
1936
- <!-- Summary -->
1937
- <div class="flex flex-col sm:flex-row justify-between items-center gap-4 mt-6 pt-4 border-t border-gray-200">
1938
- <span class="text-sm text-gray-600">
1939
- {{ visibleColumnsCount }} of {{ columns.length }} columns visible
1940
- </span>
1941
- <div class="flex gap-4 text-sm">
1942
- <span class="inline-flex items-center gap-1 text-green-600">
1943
- <i class="pi pi-chart-line"></i>
1944
- {{ numericColumnsCount }} numeric
1945
- </span>
1946
- <span class="inline-flex items-center gap-1 text-blue-600">
1947
- <i class="pi pi-calculator"></i>
1948
- {{ aggregatedColumnsCount }} aggregated
1879
+ <!-- Aggregate Info -->
1880
+ <div *ngIf="hasAggregateFunction(column.key) && isColumnVisible(column.key)"
1881
+ class="mt-3 p-3 bg-blue-50 border border-blue-200 rounded-lg">
1882
+ <div class="flex items-center gap-2">
1883
+ <i class="pi pi-info-circle text-blue-500 text-sm"></i>
1884
+ <span class="text-sm text-blue-800">
1885
+ {{ 'AGGREGATE_INFO' | translate:{function: getAggregateLabel(getAggregateFunctionValue(column.key))} }}
1949
1886
  </span>
1950
1887
  </div>
1951
1888
  </div>
1952
1889
  </div>
1953
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$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: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: DatePickerModule }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i4$1.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: RadioButtonModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "ngmodule", type: MenuModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: InputGroupModule }, { kind: "ngmodule", type: InputGroupAddonModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: ListboxModule }] });
1890
+ </div>
1891
+
1892
+ <!-- Summary -->
1893
+ <div class="flex flex-col sm:flex-row justify-between items-center gap-4 mt-6 pt-4 border-t border-gray-200">
1894
+ <span class="text-sm text-gray-600">
1895
+ {{ 'COLUMNS_VISIBLE_COUNT' | translate:{visible: visibleColumnsCount, total: columns.length} }}
1896
+ </span>
1897
+ <div class="flex gap-4 text-sm">
1898
+ <span class="inline-flex items-center gap-1 text-green-600">
1899
+ <i class="pi pi-chart-line"></i>
1900
+ {{ numericColumnsCount }} {{ 'NUMERIC' | translate }}
1901
+ </span>
1902
+ <span class="inline-flex items-center gap-1 text-blue-600">
1903
+ <i class="pi pi-calculator"></i>
1904
+ {{ aggregatedColumnsCount }} {{ 'AGGREGATED' | translate }}
1905
+ </span>
1906
+ </div>
1907
+ </div>
1908
+ </div>
1909
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$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: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: DatePickerModule }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i4$1.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: RadioButtonModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "ngmodule", type: MenuModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: InputGroupModule }, { kind: "ngmodule", type: InputGroupAddonModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: ListboxModule }, { kind: "pipe", type: i8$1.TranslatePipe, name: "translate" }] });
1954
1910
  }
1955
1911
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ColumnsBuilderComponent, decorators: [{
1956
1912
  type: Component,
1957
1913
  args: [{
1958
1914
  selector: 'formly-columns-builder',
1959
1915
  template: `
1960
- <div>
1961
- <!-- Header -->
1962
- <div class="mb-6">
1963
- <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || 'Columns Management' }}</h5>
1964
- <p class="text-gray-600 text-sm">{{ props.description || 'Select and configure columns to display' }}</p>
1965
- </div>
1966
-
1967
- <!-- Quick Actions -->
1968
- <div class="flex flex-wrap gap-2 mb-6">
1969
- <button
1970
- type="button"
1971
- (click)="toggleAll(true)"
1972
- class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
1973
- >
1974
- <i class="pi pi-eye"></i>
1975
- Show All
1976
- </button>
1977
- <button
1978
- type="button"
1979
- (click)="toggleAll(false)"
1980
- class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
1981
- >
1982
- <i class="pi pi-eye-slash"></i>
1983
- Hide All
1984
- </button>
1985
- <button
1986
- type="button"
1987
- (click)="resetToDefault()"
1988
- class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
1989
- >
1990
- <i class="pi pi-refresh"></i>
1991
- Reset to Default
1992
- </button>
1993
- </div>
1994
-
1995
- <!-- Drag Info -->
1996
- <div class="mb-4 p-2 bg-blue-50 border border-blue-200 rounded text-sm text-blue-700">
1997
- <i class="pi pi-info-circle mr-2"></i>
1998
- Drag the handle to reorder columns
1999
- </div>
2000
-
2001
- <!-- Columns List -->
2002
- <div class="space-y-3">
2003
- <div *ngIf="columns.length === 0" class="text-center py-8 px-4 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50">
2004
- <i class="pi pi-table text-4xl text-gray-400 mb-3"></i>
2005
- <p class="text-gray-500">No columns available</p>
2006
- </div>
1916
+ <div>
1917
+ <!-- Header -->
1918
+ <div class="mb-6">
1919
+ <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || ('COLUMNS_MANAGEMENT' | translate) }}</h5>
1920
+ <p class="text-gray-600 text-sm">{{ props.description || ('COLUMNS_DESCRIPTION' | translate) }}</p>
1921
+ </div>
1922
+
1923
+ <!-- Quick Actions -->
1924
+ <div class="flex flex-wrap gap-2 mb-6">
1925
+ <button
1926
+ type="button"
1927
+ (click)="toggleAll(true)"
1928
+ class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
1929
+ >
1930
+ <i class="pi pi-eye"></i>
1931
+ {{ 'SHOW_ALL' | translate }}
1932
+ </button>
1933
+ <button
1934
+ type="button"
1935
+ (click)="toggleAll(false)"
1936
+ class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
1937
+ >
1938
+ <i class="pi pi-eye-slash"></i>
1939
+ {{ 'HIDE_ALL' | translate }}
1940
+ </button>
1941
+ <button
1942
+ type="button"
1943
+ (click)="resetToDefault()"
1944
+ class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
1945
+ >
1946
+ <i class="pi pi-refresh"></i>
1947
+ {{ 'RESET_TO_DEFAULT' | translate }}
1948
+ </button>
1949
+ </div>
1950
+
1951
+ <!-- Drag Info -->
1952
+ <div class="mb-4 p-2 bg-blue-50 border border-blue-200 rounded text-sm text-blue-700">
1953
+ <i class="pi pi-info-circle mr-2"></i>
1954
+ {{ 'DRAG_COLUMNS_INFO' | translate }}
1955
+ </div>
1956
+
1957
+ <!-- Columns List -->
1958
+ <div class="space-y-3">
1959
+ <div *ngIf="columns.length === 0" class="text-center py-8 px-4 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50">
1960
+ <i class="pi pi-table text-4xl text-gray-400 mb-3"></i>
1961
+ <p class="text-gray-500">{{ 'NO_COLUMNS_AVAILABLE' | translate }}</p>
1962
+ </div>
2007
1963
 
2008
- <div *ngFor="let column of columns; let i = index"
2009
- class="bg-gray-50 rounded-lg border border-gray-200 p-1 transition-colors hover:bg-gray-100"
1964
+ <div *ngFor="let column of columns; let i = index"
1965
+ class="bg-gray-50 rounded-lg border border-gray-200 p-1 transition-colors hover:bg-gray-100"
1966
+ draggable="true"
1967
+ (dragstart)="onDragStart($event, i)"
1968
+ (dragover)="onDragOver($event)"
1969
+ (drop)="onDrop($event, i)"
1970
+ (dragenter)="onDragEnter($event)"
1971
+ (dragleave)="onDragLeave($event)">
1972
+
1973
+ <div class="grid grid-cols-12 gap-4 items-center">
1974
+ <!-- Drag Handle -->
1975
+ <div class="col-span-1 flex justify-center cursor-move text-gray-400 hover:text-gray-600"
2010
1976
  draggable="true"
2011
- (dragstart)="onDragStart($event, i)"
2012
- (dragover)="onDragOver($event)"
2013
- (drop)="onDrop($event, i)"
2014
- (dragenter)="onDragEnter($event)"
2015
- (dragleave)="onDragLeave($event)">
2016
-
2017
- <div class="grid grid-cols-12 gap-4 items-center">
2018
- <!-- Drag Handle -->
2019
- <div class="col-span-1 flex justify-center cursor-move text-gray-400 hover:text-gray-600"
2020
- draggable="true"
2021
- (dragstart)="onDragStart($event, i)">
2022
- <i class="pi pi-bars"></i>
2023
- </div>
2024
-
2025
- <!-- Visibility Toggle -->
2026
- <div class="col-span-1 flex justify-center">
2027
- <p-checkbox
2028
- [binary]="true"
2029
- [formControl]="getColumnControl(column.key, 'isVisible')"
2030
- [inputId]="'visible_' + column.key"
2031
- styleClass="[&>div]:border-gray-300 [&>div]:hover:border-gray-400"
2032
- (onChange)="onFormChange()"
2033
- >
2034
- </p-checkbox>
2035
- </div>
1977
+ (dragstart)="onDragStart($event, i)">
1978
+ <i class="pi pi-bars"></i>
1979
+ </div>
2036
1980
 
2037
- <!-- Column Info -->
2038
- <div class="col-span-12 md:col-span-4">
2039
- <label [for]="'visible_' + column.key" class="block font-medium text-gray-900 cursor-pointer hover:text-blue-600">
2040
- {{ column.label }}
2041
- </label>
2042
- <p class="text-xs text-gray-500 mt-1">{{ column.key }}</p>
2043
- </div>
1981
+ <!-- Visibility Toggle -->
1982
+ <div class="col-span-1 flex justify-center">
1983
+ <p-checkbox
1984
+ [binary]="true"
1985
+ [formControl]="getColumnControl(column.key, 'isVisible')"
1986
+ [inputId]="'visible_' + column.key"
1987
+ styleClass="[&>div]:border-gray-300 [&>div]:hover:border-gray-400"
1988
+ (onChange)="onFormChange()"
1989
+ >
1990
+ </p-checkbox>
1991
+ </div>
2044
1992
 
2045
- <!-- Display Name -->
2046
- <div class="col-span-12 md:col-span-3">
2047
- <input
2048
- *ngIf="isColumnVisible(column.key)"
2049
- type="text"
2050
- [formControl]="getColumnControl(column.key, 'displayName')"
2051
- [placeholder]="column.label"
2052
- class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
2053
- (blur)="onFormChange()"
2054
- >
2055
- </div>
1993
+ <!-- Column Info -->
1994
+ <div class="col-span-12 md:col-span-4">
1995
+ <label [for]="'visible_' + column.key" class="block font-medium text-gray-900 cursor-pointer hover:text-blue-600">
1996
+ {{ column.label }}
1997
+ </label>
1998
+ <p class="text-xs text-gray-500 mt-1">{{ column.key }}</p>
1999
+ </div>
2056
2000
 
2057
- <!-- Aggregate Function -->
2058
- <div class="col-span-12 md:col-span-3">
2059
- <div *ngIf="column.aggregatable && isColumnVisible(column.key)">
2060
- <p-select
2061
- [options]="aggregateFunctions"
2062
- optionLabel="label"
2063
- optionValue="value"
2064
- [formControl]="getColumnControl(column.key, 'aggregateFunction')"
2065
- placeholder="Select aggregate"
2066
- [showClear]="true"
2067
- styleClass="w-full"
2068
- (onChange)="onFormChange()"
2069
- >
2070
- </p-select>
2071
- </div>
2072
- <span *ngIf="!column.aggregatable && isColumnVisible(column.key)" class="text-xs text-gray-500">
2073
- No aggregates available
2074
- </span>
2075
- </div>
2076
- </div>
2001
+ <!-- Display Name -->
2002
+ <div class="col-span-12 md:col-span-3">
2003
+ <input
2004
+ *ngIf="isColumnVisible(column.key)"
2005
+ type="text"
2006
+ [formControl]="getColumnControl(column.key, 'displayName')"
2007
+ [placeholder]="column.label"
2008
+ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
2009
+ (blur)="onFormChange()"
2010
+ >
2011
+ </div>
2077
2012
 
2078
- <!-- Aggregate Info -->
2079
- <div *ngIf="hasAggregateFunction(column.key) && isColumnVisible(column.key)"
2080
- class="mt-3 p-3 bg-blue-50 border border-blue-200 rounded-lg">
2081
- <div class="flex items-center gap-2">
2082
- <i class="pi pi-info-circle text-blue-500 text-sm"></i>
2083
- <span class="text-sm text-blue-800">
2084
- Will calculate <strong>{{ getAggregateLabel(getAggregateFunctionValue(column.key)) }}</strong>
2085
- for this column in grouped data
2086
- </span>
2087
- </div>
2013
+ <!-- Aggregate Function -->
2014
+ <div class="col-span-12 md:col-span-3">
2015
+ <div *ngIf="column.aggregatable && isColumnVisible(column.key)">
2016
+ <p-select
2017
+ [options]="aggregateFunctions"
2018
+ optionLabel="label"
2019
+ optionValue="value"
2020
+ [formControl]="getColumnControl(column.key, 'aggregateFunction')"
2021
+ [placeholder]="'SELECT_AGGREGATE' | translate"
2022
+ [showClear]="true"
2023
+ styleClass="w-full"
2024
+ (onChange)="onFormChange()"
2025
+ >
2026
+ </p-select>
2088
2027
  </div>
2028
+ <span *ngIf="!column.aggregatable && isColumnVisible(column.key)" class="text-xs text-gray-500">
2029
+ {{ 'NO_AGGREGATES_AVAILABLE' | translate }}
2030
+ </span>
2089
2031
  </div>
2090
2032
  </div>
2091
2033
 
2092
- <!-- Summary -->
2093
- <div class="flex flex-col sm:flex-row justify-between items-center gap-4 mt-6 pt-4 border-t border-gray-200">
2094
- <span class="text-sm text-gray-600">
2095
- {{ visibleColumnsCount }} of {{ columns.length }} columns visible
2096
- </span>
2097
- <div class="flex gap-4 text-sm">
2098
- <span class="inline-flex items-center gap-1 text-green-600">
2099
- <i class="pi pi-chart-line"></i>
2100
- {{ numericColumnsCount }} numeric
2101
- </span>
2102
- <span class="inline-flex items-center gap-1 text-blue-600">
2103
- <i class="pi pi-calculator"></i>
2104
- {{ aggregatedColumnsCount }} aggregated
2034
+ <!-- Aggregate Info -->
2035
+ <div *ngIf="hasAggregateFunction(column.key) && isColumnVisible(column.key)"
2036
+ class="mt-3 p-3 bg-blue-50 border border-blue-200 rounded-lg">
2037
+ <div class="flex items-center gap-2">
2038
+ <i class="pi pi-info-circle text-blue-500 text-sm"></i>
2039
+ <span class="text-sm text-blue-800">
2040
+ {{ 'AGGREGATE_INFO' | translate:{function: getAggregateLabel(getAggregateFunctionValue(column.key))} }}
2105
2041
  </span>
2106
2042
  </div>
2107
2043
  </div>
2108
2044
  </div>
2045
+ </div>
2046
+
2047
+ <!-- Summary -->
2048
+ <div class="flex flex-col sm:flex-row justify-between items-center gap-4 mt-6 pt-4 border-t border-gray-200">
2049
+ <span class="text-sm text-gray-600">
2050
+ {{ 'COLUMNS_VISIBLE_COUNT' | translate:{visible: visibleColumnsCount, total: columns.length} }}
2051
+ </span>
2052
+ <div class="flex gap-4 text-sm">
2053
+ <span class="inline-flex items-center gap-1 text-green-600">
2054
+ <i class="pi pi-chart-line"></i>
2055
+ {{ numericColumnsCount }} {{ 'NUMERIC' | translate }}
2056
+ </span>
2057
+ <span class="inline-flex items-center gap-1 text-blue-600">
2058
+ <i class="pi pi-calculator"></i>
2059
+ {{ aggregatedColumnsCount }} {{ 'AGGREGATED' | translate }}
2060
+ </span>
2061
+ </div>
2062
+ </div>
2063
+ </div>
2109
2064
  `,
2110
2065
  imports: [
2111
2066
  CommonModule,
@@ -2266,321 +2221,317 @@ class GroupBuilderComponent extends FieldType {
2266
2221
  return this.groups.length < this.maxGroups;
2267
2222
  }
2268
2223
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: GroupBuilderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2269
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: GroupBuilderComponent, isStandalone: true, selector: "formly-group-builder", usesInheritance: true, ngImport: i0, template: `
2270
- <div>
2271
- <!-- Header -->
2272
- <div class="mb-6">
2273
- <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || 'Data Grouping' }}</h5>
2274
- <p class="text-gray-600 text-sm">{{ props.description || 'Group data by fields to create hierarchical views' }}</p>
2275
- </div>
2276
-
2277
- <!-- Group Configuration -->
2278
- <div class="space-y-4">
2279
- <div class="flex items-center justify-between">
2280
- <span class="font-medium text-gray-700">Group Levels</span>
2281
- <button
2282
- type="button"
2283
- *ngIf="canAddMoreGroups()"
2284
- (click)="addGroup()"
2285
- [disabled]="!canAddMoreGroups()"
2286
- class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-blue-700 bg-blue-50 rounded-lg hover:bg-blue-100 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
2287
- >
2288
- <i class="pi pi-plus"></i>
2289
- Add Group Level
2290
- </button>
2291
- </div>
2224
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: GroupBuilderComponent, isStandalone: true, selector: "formly-group-builder", usesInheritance: true, ngImport: i0, template: `<div>
2225
+ <!-- Header -->
2226
+ <div class="mb-6">
2227
+ <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || ('DATA_GROUPING' | translate) }}</h5>
2228
+ <p class="text-gray-600 text-sm">{{ props.description || ('GROUP_DESCRIPTION' | translate) }}</p>
2229
+ </div>
2230
+
2231
+ <!-- Group Configuration -->
2232
+ <div class="space-y-4">
2233
+ <div class="flex items-center justify-between">
2234
+ <span class="font-medium text-gray-700">{{ 'GROUP_LEVELS' | translate }}</span>
2235
+ <button
2236
+ type="button"
2237
+ *ngIf="canAddMoreGroups()"
2238
+ (click)="addGroup()"
2239
+ [disabled]="!canAddMoreGroups()"
2240
+ class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-blue-700 bg-blue-50 rounded-lg hover:bg-blue-100 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
2241
+ >
2242
+ <i class="pi pi-plus"></i>
2243
+ {{ 'ADD_GROUP_LEVEL' | translate }}
2244
+ </button>
2245
+ </div>
2292
2246
 
2293
- <!-- Drag Info -->
2294
- <div *ngIf="groups.length > 1" class="mb-4 p-2 bg-blue-50 border border-blue-200 rounded text-sm text-blue-700">
2295
- <i class="pi pi-info-circle mr-2"></i>
2296
- Drag the handle to reorder group levels
2297
- </div>
2247
+ <!-- Drag Info -->
2248
+ <div *ngIf="groups.length > 1" class="mb-4 p-2 bg-blue-50 border border-blue-200 rounded text-sm text-blue-700">
2249
+ <i class="pi pi-info-circle mr-2"></i>
2250
+ {{ 'DRAG_INFO' | translate }}
2251
+ </div>
2298
2252
 
2299
- <!-- Empty State -->
2300
- <div *ngIf="groups.length === 0" class="text-center py-8 px-4 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50">
2301
- <i class="pi pi-layer-group text-4xl text-gray-400 mb-3"></i>
2302
- <p class="text-gray-500 mb-4">No grouping levels defined</p>
2303
- <button
2304
- type="button"
2305
- (click)="addGroup()"
2306
- class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 transition-colors"
2307
- >
2308
- <i class="pi pi-plus"></i>
2309
- Add First Group Level
2310
- </button>
2311
- </div>
2253
+ <!-- Empty State -->
2254
+ <div *ngIf="groups.length === 0" class="text-center py-8 px-4 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50">
2255
+ <i class="pi pi-layer-group text-4xl text-gray-400 mb-3"></i>
2256
+ <p class="text-gray-500 mb-4">{{ 'NO_GROUPING_LEVELS' | translate }}</p>
2257
+ <button
2258
+ type="button"
2259
+ (click)="addGroup()"
2260
+ class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 transition-colors"
2261
+ >
2262
+ <i class="pi pi-plus"></i>
2263
+ {{ 'ADD_FIRST_GROUP_LEVEL' | translate }}
2264
+ </button>
2265
+ </div>
2312
2266
 
2313
- <!-- Groups List with Drag & Drop -->
2314
- <div class="space-y-3">
2315
- <div *ngFor="let group of groups.controls; let i = index"
2316
- class="bg-gray-50 rounded-lg border border-gray-200 p-4 transition-colors hover:bg-gray-100"
2267
+ <!-- Groups List with Drag & Drop -->
2268
+ <div class="space-y-3">
2269
+ <div *ngFor="let group of groups.controls; let i = index"
2270
+ class="bg-gray-50 rounded-lg border border-gray-200 p-4 transition-colors hover:bg-gray-100"
2271
+ draggable="true"
2272
+ (dragstart)="onDragStart($event, i)"
2273
+ (dragover)="onDragOver($event)"
2274
+ (drop)="onDrop($event, i)"
2275
+ (dragenter)="onDragEnter($event)"
2276
+ (dragleave)="onDragLeave($event)"
2277
+ (dragend)="onDragEnd($event)">
2278
+
2279
+ <div class="grid grid-cols-12 gap-4 items-start">
2280
+ <!-- Drag Handle -->
2281
+ <div *ngIf="groups.length > 1"
2282
+ class="col-span-1 flex justify-center cursor-move text-gray-400 hover:text-gray-600 pt-2"
2317
2283
  draggable="true"
2318
- (dragstart)="onDragStart($event, i)"
2319
- (dragover)="onDragOver($event)"
2320
- (drop)="onDrop($event, i)"
2321
- (dragenter)="onDragEnter($event)"
2322
- (dragleave)="onDragLeave($event)"
2323
- (dragend)="onDragEnd($event)">
2324
-
2325
- <div class="grid grid-cols-12 gap-4 items-start">
2326
- <!-- Drag Handle -->
2327
- <div *ngIf="groups.length > 1"
2328
- class="col-span-1 flex justify-center cursor-move text-gray-400 hover:text-gray-600 pt-2"
2329
- draggable="true"
2330
- (dragstart)="onDragStart($event, i)">
2331
- <i class="pi pi-bars"></i>
2284
+ (dragstart)="onDragStart($event, i)">
2285
+ <i class="pi pi-bars"></i>
2286
+ </div>
2287
+
2288
+ <!-- Group Content -->
2289
+ <div class="col-span-11">
2290
+ <div class="flex items-center justify-between mb-3">
2291
+ <div class="flex items-center gap-2">
2292
+ <i class="pi pi-sort-alt text-gray-500"></i>
2293
+ <span class="font-medium text-gray-700">{{ 'GROUP_LEVEL' | translate }} {{ i + 1 }}</span>
2294
+ </div>
2295
+ <div class="flex items-center gap-1">
2296
+ <button
2297
+ type="button"
2298
+ (click)="removeGroup(i)"
2299
+ class="p-1 text-red-500 hover:text-red-700 hover:bg-red-50 rounded transition-colors"
2300
+ [pTooltip]="'REMOVE' | translate"
2301
+ >
2302
+ <i class="pi pi-times"></i>
2303
+ </button>
2304
+ </div>
2305
+ </div>
2306
+
2307
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
2308
+ <!-- Field Selection -->
2309
+ <div>
2310
+ <label class="block text-sm font-medium text-gray-700 mb-2">{{ 'FIELD' | translate }}</label>
2311
+ <p-select
2312
+ [options]="availableFields"
2313
+ optionLabel="label"
2314
+ optionValue="key"
2315
+ [formControl]="getGroupControl(i, 'field')"
2316
+ [placeholder]="'SELECT_FIELD' | translate"
2317
+ [showClear]="true"
2318
+ (onChange)="onFieldChange(i, $event.value)"
2319
+ styleClass="w-full"
2320
+ >
2321
+ <ng-template pTemplate="selectedItem">
2322
+ <span *ngIf="getGroupControl(i, 'field').value" class="text-gray-900">
2323
+ {{ getFieldLabel(getGroupControl(i, 'field').value) }}
2324
+ </span>
2325
+ <span *ngIf="!getGroupControl(i, 'field').value" class="text-gray-500">{{ 'SELECT_FIELD' | translate }}</span>
2326
+ </ng-template>
2327
+ </p-select>
2332
2328
  </div>
2333
2329
 
2334
- <!-- Group Content -->
2335
- <div class="col-span-11">
2336
- <div class="flex items-center justify-between mb-3">
2337
- <div class="flex items-center gap-2">
2338
- <i class="pi pi-sort-alt text-gray-500"></i>
2339
- <span class="font-medium text-gray-700">Group Level {{ i + 1 }}</span>
2340
- </div>
2341
- <div class="flex items-center gap-1">
2342
- <button
2343
- type="button"
2344
- (click)="removeGroup(i)"
2345
- class="p-1 text-red-500 hover:text-red-700 hover:bg-red-50 rounded transition-colors"
2346
- [pTooltip]="'Remove'"
2347
- >
2348
- <i class="pi pi-times"></i>
2349
- </button>
2350
- </div>
2351
- </div>
2352
-
2353
- <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
2354
- <!-- Field Selection -->
2355
- <div>
2356
- <label class="block text-sm font-medium text-gray-700 mb-2">Field</label>
2357
- <p-select
2358
- [options]="availableFields"
2359
- optionLabel="label"
2360
- optionValue="key"
2361
- [formControl]="getGroupControl(i, 'field')"
2362
- placeholder="Select field"
2363
- [showClear]="true"
2364
- (onChange)="onFieldChange(i, $event.value)"
2365
- styleClass="w-full"
2366
- >
2367
- <ng-template pTemplate="selectedItem">
2368
- <span *ngIf="getGroupControl(i, 'field').value" class="text-gray-900">
2369
- {{ getFieldLabel(getGroupControl(i, 'field').value) }}
2370
- </span>
2371
- <span *ngIf="!getGroupControl(i, 'field').value" class="text-gray-500">Select field</span>
2372
- </ng-template>
2373
- </p-select>
2374
- </div>
2375
-
2376
- <!-- Display Name -->
2377
- <div>
2378
- <label class="block text-sm font-medium text-gray-700 mb-2">Display Name</label>
2379
- <input
2380
- type="text"
2381
- pInputText
2382
- [formControl]="getGroupControl(i, 'displayName')"
2383
- placeholder="Display name (optional)"
2384
- class="w-full text-gray-900"
2385
- (blur)="onFormChange()"
2386
- >
2387
- </div>
2388
- </div>
2389
-
2390
- <!-- Show Total Toggle -->
2391
- <div class="flex items-center gap-2 mt-3">
2392
- <p-checkbox
2393
- [binary]="true"
2394
- [formControl]="getGroupControl(i, 'showTotal')"
2395
- [inputId]="'showTotal' + i"
2396
- styleClass="[&>div]:border-gray-300 [&>div]:hover:border-gray-400"
2397
- (onChange)="onFormChange()"
2398
- >
2399
- </p-checkbox>
2400
- <label [for]="'showTotal' + i" class="text-sm text-gray-700 cursor-pointer hover:text-gray-900">
2401
- Show total for this group level
2402
- </label>
2403
- </div>
2330
+ <!-- Display Name -->
2331
+ <div>
2332
+ <label class="block text-sm font-medium text-gray-700 mb-2">{{ 'DISPLAY_NAME' | translate }}</label>
2333
+ <input
2334
+ type="text"
2335
+ pInputText
2336
+ [formControl]="getGroupControl(i, 'displayName')"
2337
+ [placeholder]="'DISPLAY_NAME_PLACEHOLDER' | translate"
2338
+ class="w-full text-gray-900"
2339
+ (blur)="onFormChange()"
2340
+ >
2404
2341
  </div>
2405
2342
  </div>
2406
- </div>
2407
- </div>
2408
- </div>
2409
2343
 
2410
- <!-- Grouping Tips -->
2411
- <div *ngIf="groups.length > 0" class="mt-4 p-4 bg-blue-50 border border-blue-200 rounded-lg">
2412
- <div class="flex items-center gap-3">
2413
- <i class="pi pi-info-circle text-blue-500"></i>
2414
- <div>
2415
- <p class="text-sm text-blue-800">
2416
- Data will be grouped hierarchically in the specified order.
2417
- {{ groups.length }} level{{ groups.length > 1 ? 's' : '' }} defined.
2418
- </p>
2344
+ <!-- Show Total Toggle -->
2345
+ <div class="flex items-center gap-2 mt-3">
2346
+ <p-checkbox
2347
+ [binary]="true"
2348
+ [formControl]="getGroupControl(i, 'showTotal')"
2349
+ [inputId]="'showTotal' + i"
2350
+ styleClass="[&>div]:border-gray-300 [&>div]:hover:border-gray-400"
2351
+ (onChange)="onFormChange()"
2352
+ >
2353
+ </p-checkbox>
2354
+ <label [for]="'showTotal' + i" class="text-sm text-gray-700 cursor-pointer hover:text-gray-900">
2355
+ {{ 'SHOW_TOTAL' | translate }}
2356
+ </label>
2357
+ </div>
2419
2358
  </div>
2420
2359
  </div>
2421
2360
  </div>
2422
2361
  </div>
2423
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$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: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i5.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: DatePickerModule }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i4$1.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: RadioButtonModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "ngmodule", type: MenuModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: InputGroupModule }, { kind: "ngmodule", type: InputGroupAddonModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: ListboxModule }] });
2362
+ </div>
2363
+
2364
+ <!-- Grouping Tips -->
2365
+ <div *ngIf="groups.length > 0" class="mt-4 p-4 bg-blue-50 border border-blue-200 rounded-lg">
2366
+ <div class="flex items-center gap-3">
2367
+ <i class="pi pi-info-circle text-blue-500"></i>
2368
+ <div>
2369
+ <p class="text-sm text-blue-800">
2370
+ {{ 'GROUPING_TIPS' | translate }}
2371
+ {{ groups.length }} {{ 'LEVELS_DEFINED' | translate:{count: groups.length} }}
2372
+ </p>
2373
+ </div>
2374
+ </div>
2375
+ </div>
2376
+ </div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$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: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i5.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: DatePickerModule }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i4$1.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: RadioButtonModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "ngmodule", type: MenuModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: InputGroupModule }, { kind: "ngmodule", type: InputGroupAddonModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: ListboxModule }, { kind: "pipe", type: i8$1.TranslatePipe, name: "translate" }] });
2424
2377
  }
2425
2378
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: GroupBuilderComponent, decorators: [{
2426
2379
  type: Component,
2427
2380
  args: [{
2428
2381
  selector: 'formly-group-builder',
2429
- template: `
2430
- <div>
2431
- <!-- Header -->
2432
- <div class="mb-6">
2433
- <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || 'Data Grouping' }}</h5>
2434
- <p class="text-gray-600 text-sm">{{ props.description || 'Group data by fields to create hierarchical views' }}</p>
2435
- </div>
2436
-
2437
- <!-- Group Configuration -->
2438
- <div class="space-y-4">
2439
- <div class="flex items-center justify-between">
2440
- <span class="font-medium text-gray-700">Group Levels</span>
2441
- <button
2442
- type="button"
2443
- *ngIf="canAddMoreGroups()"
2444
- (click)="addGroup()"
2445
- [disabled]="!canAddMoreGroups()"
2446
- class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-blue-700 bg-blue-50 rounded-lg hover:bg-blue-100 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
2447
- >
2448
- <i class="pi pi-plus"></i>
2449
- Add Group Level
2450
- </button>
2451
- </div>
2382
+ template: `<div>
2383
+ <!-- Header -->
2384
+ <div class="mb-6">
2385
+ <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || ('DATA_GROUPING' | translate) }}</h5>
2386
+ <p class="text-gray-600 text-sm">{{ props.description || ('GROUP_DESCRIPTION' | translate) }}</p>
2387
+ </div>
2388
+
2389
+ <!-- Group Configuration -->
2390
+ <div class="space-y-4">
2391
+ <div class="flex items-center justify-between">
2392
+ <span class="font-medium text-gray-700">{{ 'GROUP_LEVELS' | translate }}</span>
2393
+ <button
2394
+ type="button"
2395
+ *ngIf="canAddMoreGroups()"
2396
+ (click)="addGroup()"
2397
+ [disabled]="!canAddMoreGroups()"
2398
+ class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-blue-700 bg-blue-50 rounded-lg hover:bg-blue-100 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
2399
+ >
2400
+ <i class="pi pi-plus"></i>
2401
+ {{ 'ADD_GROUP_LEVEL' | translate }}
2402
+ </button>
2403
+ </div>
2452
2404
 
2453
- <!-- Drag Info -->
2454
- <div *ngIf="groups.length > 1" class="mb-4 p-2 bg-blue-50 border border-blue-200 rounded text-sm text-blue-700">
2455
- <i class="pi pi-info-circle mr-2"></i>
2456
- Drag the handle to reorder group levels
2457
- </div>
2405
+ <!-- Drag Info -->
2406
+ <div *ngIf="groups.length > 1" class="mb-4 p-2 bg-blue-50 border border-blue-200 rounded text-sm text-blue-700">
2407
+ <i class="pi pi-info-circle mr-2"></i>
2408
+ {{ 'DRAG_INFO' | translate }}
2409
+ </div>
2458
2410
 
2459
- <!-- Empty State -->
2460
- <div *ngIf="groups.length === 0" class="text-center py-8 px-4 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50">
2461
- <i class="pi pi-layer-group text-4xl text-gray-400 mb-3"></i>
2462
- <p class="text-gray-500 mb-4">No grouping levels defined</p>
2463
- <button
2464
- type="button"
2465
- (click)="addGroup()"
2466
- class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 transition-colors"
2467
- >
2468
- <i class="pi pi-plus"></i>
2469
- Add First Group Level
2470
- </button>
2471
- </div>
2411
+ <!-- Empty State -->
2412
+ <div *ngIf="groups.length === 0" class="text-center py-8 px-4 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50">
2413
+ <i class="pi pi-layer-group text-4xl text-gray-400 mb-3"></i>
2414
+ <p class="text-gray-500 mb-4">{{ 'NO_GROUPING_LEVELS' | translate }}</p>
2415
+ <button
2416
+ type="button"
2417
+ (click)="addGroup()"
2418
+ class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 transition-colors"
2419
+ >
2420
+ <i class="pi pi-plus"></i>
2421
+ {{ 'ADD_FIRST_GROUP_LEVEL' | translate }}
2422
+ </button>
2423
+ </div>
2472
2424
 
2473
- <!-- Groups List with Drag & Drop -->
2474
- <div class="space-y-3">
2475
- <div *ngFor="let group of groups.controls; let i = index"
2476
- class="bg-gray-50 rounded-lg border border-gray-200 p-4 transition-colors hover:bg-gray-100"
2425
+ <!-- Groups List with Drag & Drop -->
2426
+ <div class="space-y-3">
2427
+ <div *ngFor="let group of groups.controls; let i = index"
2428
+ class="bg-gray-50 rounded-lg border border-gray-200 p-4 transition-colors hover:bg-gray-100"
2429
+ draggable="true"
2430
+ (dragstart)="onDragStart($event, i)"
2431
+ (dragover)="onDragOver($event)"
2432
+ (drop)="onDrop($event, i)"
2433
+ (dragenter)="onDragEnter($event)"
2434
+ (dragleave)="onDragLeave($event)"
2435
+ (dragend)="onDragEnd($event)">
2436
+
2437
+ <div class="grid grid-cols-12 gap-4 items-start">
2438
+ <!-- Drag Handle -->
2439
+ <div *ngIf="groups.length > 1"
2440
+ class="col-span-1 flex justify-center cursor-move text-gray-400 hover:text-gray-600 pt-2"
2477
2441
  draggable="true"
2478
- (dragstart)="onDragStart($event, i)"
2479
- (dragover)="onDragOver($event)"
2480
- (drop)="onDrop($event, i)"
2481
- (dragenter)="onDragEnter($event)"
2482
- (dragleave)="onDragLeave($event)"
2483
- (dragend)="onDragEnd($event)">
2484
-
2485
- <div class="grid grid-cols-12 gap-4 items-start">
2486
- <!-- Drag Handle -->
2487
- <div *ngIf="groups.length > 1"
2488
- class="col-span-1 flex justify-center cursor-move text-gray-400 hover:text-gray-600 pt-2"
2489
- draggable="true"
2490
- (dragstart)="onDragStart($event, i)">
2491
- <i class="pi pi-bars"></i>
2442
+ (dragstart)="onDragStart($event, i)">
2443
+ <i class="pi pi-bars"></i>
2444
+ </div>
2445
+
2446
+ <!-- Group Content -->
2447
+ <div class="col-span-11">
2448
+ <div class="flex items-center justify-between mb-3">
2449
+ <div class="flex items-center gap-2">
2450
+ <i class="pi pi-sort-alt text-gray-500"></i>
2451
+ <span class="font-medium text-gray-700">{{ 'GROUP_LEVEL' | translate }} {{ i + 1 }}</span>
2452
+ </div>
2453
+ <div class="flex items-center gap-1">
2454
+ <button
2455
+ type="button"
2456
+ (click)="removeGroup(i)"
2457
+ class="p-1 text-red-500 hover:text-red-700 hover:bg-red-50 rounded transition-colors"
2458
+ [pTooltip]="'REMOVE' | translate"
2459
+ >
2460
+ <i class="pi pi-times"></i>
2461
+ </button>
2462
+ </div>
2463
+ </div>
2464
+
2465
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
2466
+ <!-- Field Selection -->
2467
+ <div>
2468
+ <label class="block text-sm font-medium text-gray-700 mb-2">{{ 'FIELD' | translate }}</label>
2469
+ <p-select
2470
+ [options]="availableFields"
2471
+ optionLabel="label"
2472
+ optionValue="key"
2473
+ [formControl]="getGroupControl(i, 'field')"
2474
+ [placeholder]="'SELECT_FIELD' | translate"
2475
+ [showClear]="true"
2476
+ (onChange)="onFieldChange(i, $event.value)"
2477
+ styleClass="w-full"
2478
+ >
2479
+ <ng-template pTemplate="selectedItem">
2480
+ <span *ngIf="getGroupControl(i, 'field').value" class="text-gray-900">
2481
+ {{ getFieldLabel(getGroupControl(i, 'field').value) }}
2482
+ </span>
2483
+ <span *ngIf="!getGroupControl(i, 'field').value" class="text-gray-500">{{ 'SELECT_FIELD' | translate }}</span>
2484
+ </ng-template>
2485
+ </p-select>
2492
2486
  </div>
2493
2487
 
2494
- <!-- Group Content -->
2495
- <div class="col-span-11">
2496
- <div class="flex items-center justify-between mb-3">
2497
- <div class="flex items-center gap-2">
2498
- <i class="pi pi-sort-alt text-gray-500"></i>
2499
- <span class="font-medium text-gray-700">Group Level {{ i + 1 }}</span>
2500
- </div>
2501
- <div class="flex items-center gap-1">
2502
- <button
2503
- type="button"
2504
- (click)="removeGroup(i)"
2505
- class="p-1 text-red-500 hover:text-red-700 hover:bg-red-50 rounded transition-colors"
2506
- [pTooltip]="'Remove'"
2507
- >
2508
- <i class="pi pi-times"></i>
2509
- </button>
2510
- </div>
2511
- </div>
2512
-
2513
- <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
2514
- <!-- Field Selection -->
2515
- <div>
2516
- <label class="block text-sm font-medium text-gray-700 mb-2">Field</label>
2517
- <p-select
2518
- [options]="availableFields"
2519
- optionLabel="label"
2520
- optionValue="key"
2521
- [formControl]="getGroupControl(i, 'field')"
2522
- placeholder="Select field"
2523
- [showClear]="true"
2524
- (onChange)="onFieldChange(i, $event.value)"
2525
- styleClass="w-full"
2526
- >
2527
- <ng-template pTemplate="selectedItem">
2528
- <span *ngIf="getGroupControl(i, 'field').value" class="text-gray-900">
2529
- {{ getFieldLabel(getGroupControl(i, 'field').value) }}
2530
- </span>
2531
- <span *ngIf="!getGroupControl(i, 'field').value" class="text-gray-500">Select field</span>
2532
- </ng-template>
2533
- </p-select>
2534
- </div>
2535
-
2536
- <!-- Display Name -->
2537
- <div>
2538
- <label class="block text-sm font-medium text-gray-700 mb-2">Display Name</label>
2539
- <input
2540
- type="text"
2541
- pInputText
2542
- [formControl]="getGroupControl(i, 'displayName')"
2543
- placeholder="Display name (optional)"
2544
- class="w-full text-gray-900"
2545
- (blur)="onFormChange()"
2546
- >
2547
- </div>
2548
- </div>
2549
-
2550
- <!-- Show Total Toggle -->
2551
- <div class="flex items-center gap-2 mt-3">
2552
- <p-checkbox
2553
- [binary]="true"
2554
- [formControl]="getGroupControl(i, 'showTotal')"
2555
- [inputId]="'showTotal' + i"
2556
- styleClass="[&>div]:border-gray-300 [&>div]:hover:border-gray-400"
2557
- (onChange)="onFormChange()"
2558
- >
2559
- </p-checkbox>
2560
- <label [for]="'showTotal' + i" class="text-sm text-gray-700 cursor-pointer hover:text-gray-900">
2561
- Show total for this group level
2562
- </label>
2563
- </div>
2488
+ <!-- Display Name -->
2489
+ <div>
2490
+ <label class="block text-sm font-medium text-gray-700 mb-2">{{ 'DISPLAY_NAME' | translate }}</label>
2491
+ <input
2492
+ type="text"
2493
+ pInputText
2494
+ [formControl]="getGroupControl(i, 'displayName')"
2495
+ [placeholder]="'DISPLAY_NAME_PLACEHOLDER' | translate"
2496
+ class="w-full text-gray-900"
2497
+ (blur)="onFormChange()"
2498
+ >
2564
2499
  </div>
2565
2500
  </div>
2566
- </div>
2567
- </div>
2568
- </div>
2569
2501
 
2570
- <!-- Grouping Tips -->
2571
- <div *ngIf="groups.length > 0" class="mt-4 p-4 bg-blue-50 border border-blue-200 rounded-lg">
2572
- <div class="flex items-center gap-3">
2573
- <i class="pi pi-info-circle text-blue-500"></i>
2574
- <div>
2575
- <p class="text-sm text-blue-800">
2576
- Data will be grouped hierarchically in the specified order.
2577
- {{ groups.length }} level{{ groups.length > 1 ? 's' : '' }} defined.
2578
- </p>
2502
+ <!-- Show Total Toggle -->
2503
+ <div class="flex items-center gap-2 mt-3">
2504
+ <p-checkbox
2505
+ [binary]="true"
2506
+ [formControl]="getGroupControl(i, 'showTotal')"
2507
+ [inputId]="'showTotal' + i"
2508
+ styleClass="[&>div]:border-gray-300 [&>div]:hover:border-gray-400"
2509
+ (onChange)="onFormChange()"
2510
+ >
2511
+ </p-checkbox>
2512
+ <label [for]="'showTotal' + i" class="text-sm text-gray-700 cursor-pointer hover:text-gray-900">
2513
+ {{ 'SHOW_TOTAL' | translate }}
2514
+ </label>
2515
+ </div>
2579
2516
  </div>
2580
2517
  </div>
2581
2518
  </div>
2582
2519
  </div>
2583
- `,
2520
+ </div>
2521
+
2522
+ <!-- Grouping Tips -->
2523
+ <div *ngIf="groups.length > 0" class="mt-4 p-4 bg-blue-50 border border-blue-200 rounded-lg">
2524
+ <div class="flex items-center gap-3">
2525
+ <i class="pi pi-info-circle text-blue-500"></i>
2526
+ <div>
2527
+ <p class="text-sm text-blue-800">
2528
+ {{ 'GROUPING_TIPS' | translate }}
2529
+ {{ groups.length }} {{ 'LEVELS_DEFINED' | translate:{count: groups.length} }}
2530
+ </p>
2531
+ </div>
2532
+ </div>
2533
+ </div>
2534
+ </div>`,
2584
2535
  imports: [
2585
2536
  CommonModule,
2586
2537
  FormsModule,