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

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 i4$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';
@@ -32,7 +32,7 @@ import * as i6$1 from 'primeng/tooltip';
32
32
  import { TooltipModule } from 'primeng/tooltip';
33
33
  import * as i7$1 from 'primeng/listbox';
34
34
  import { ListboxModule } from 'primeng/listbox';
35
- import * as i4$1 from 'primeng/checkbox';
35
+ import * as i3$1 from 'primeng/checkbox';
36
36
  import { CheckboxModule } from 'primeng/checkbox';
37
37
  import { DatePickerModule } from 'primeng/datepicker';
38
38
  import { RadioButtonModule } from 'primeng/radiobutton';
@@ -305,21 +305,33 @@ class QueryBuilderService {
305
305
  return groupableFields;
306
306
  }
307
307
  extractSelectableFields(fields) {
308
- const selectableFields = [];
308
+ const tempFields = [];
309
309
  this.traverseFields(fields, (field) => {
310
- if (field.key && field.props && ((field.props['select'] && field.props['select'].hidden == false) || !field.props['select']) && !field.props?.hidden) {
310
+ if (field.key &&
311
+ field.props &&
312
+ ((field.props['select'] && field.props['select'].hidden === false) || !field.props['select']) &&
313
+ !field.props?.hidden) {
311
314
  const isNumeric = ['number', 'currency'].includes(field.type);
312
- selectableFields.push({
315
+ const tableConfig = field.props['table'] ?? {};
316
+ const mergedProps = { ...field.props, ...(tableConfig.props ?? {}) };
317
+ const order = tableConfig.order ??
318
+ tableConfig.props?.order ??
319
+ mergedProps['order'] ??
320
+ Number.MAX_SAFE_INTEGER;
321
+ tempFields.push({
313
322
  key: field.props['entityKey'] ? field.props['entityKey'] : field.key,
314
323
  label: this.translate.instant(field.props.label || field.key),
315
324
  dataType: this.getDataType(field.type),
316
- isNumeric: isNumeric,
325
+ isNumeric,
317
326
  defaultVisible: field.props['defaultVisible'] !== false,
318
- aggregatable: isNumeric && field.props['aggregatable'] !== false
327
+ aggregatable: isNumeric && field.props['aggregatable'] !== false,
328
+ order
319
329
  });
320
330
  }
321
331
  });
322
- return selectableFields;
332
+ return tempFields
333
+ .sort((a, b) => a.order - b.order)
334
+ .map(({ order, ...rest }) => rest); // remove order after sorting
323
335
  }
324
336
  traverseFields(fields, callback) {
325
337
  fields.forEach(field => {
@@ -604,11 +616,8 @@ class GenericSearchAdvanced {
604
616
  onSubmit() {
605
617
  // Use the new QueryBuilderService methods
606
618
  const odataParams = this.queryBuilder.buildODataFromQueryModel(this.model, this.fields);
607
- // this.odataSearch.emit(odataParams);
608
619
  // Generate query string using the unified method
609
620
  const queryString = this.queryBuilder.toODataQueryString(odataParams);
610
- // console.log('OData Query String:', queryString);
611
- debugger;
612
621
  if (this.model?.pagination && this.model?.pagination?.top) {
613
622
  this.paginationChange.emit({
614
623
  top: this.model?.pagination?.top,
@@ -626,18 +635,22 @@ class GenericSearchAdvanced {
626
635
  onReset() {
627
636
  this.model = {};
628
637
  this.form.reset();
629
- this.paginationChange.emit({
638
+ // this.paginationChange.emit({
639
+ // top:10,
640
+ // // skip:,
641
+ // });
642
+ // this.search.emit(this.model);
643
+ const odataParams = this.queryBuilder.buildODataFromQueryModel(this.model, this.fields);
644
+ // this.odataSearch.emit(odataParams);
645
+ // Generate query string using the unified method
646
+ const queryString = this.queryBuilder.toODataQueryString(odataParams);
647
+ this.search.emit({
648
+ filter: this.model['filter'],
649
+ query: queryString,
650
+ // sorting:,
630
651
  top: 10,
631
652
  // skip:,
632
653
  });
633
- this.search.emit(this.model);
634
- // Emit empty QueryParameters using the proper structure
635
- // this.odataSearch.emit({
636
- // filters: [],
637
- // orderBy: [],
638
- // groupBy: [],
639
- // expand: []
640
- // });
641
654
  }
642
655
  // Toggle drawer visibility
643
656
  toggleDrawer() {
@@ -648,7 +661,7 @@ class GenericSearchAdvanced {
648
661
  this.drawerVisible = false;
649
662
  }
650
663
  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" }] });
664
+ 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: i4$1.TranslatePipe, name: "translate" }] });
652
665
  }
653
666
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: GenericSearchAdvanced, decorators: [{
654
667
  type: Component,
@@ -783,183 +796,161 @@ class SortBuilderComponent extends FieldType {
783
796
  return availableFields.length > 0 ? availableFields[0].key : '';
784
797
  }
785
798
  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>
799
+ 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">
800
+ <div class="mb-6">
801
+ <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || ('SORTING' | translate) }}</h5>
802
+ <p class="text-gray-600 text-sm">{{ ('PRIORITY_HINT' | translate) }}</p>
803
+ </div>
804
+
805
+ <!-- Sort List -->
806
+ <div *ngIf="sorts.length > 0" class="sort-list space-y-2 mb-3">
807
+ <div
808
+ *ngFor="let sort of sorts; let i = index; let isFirst = first; let isLast = last"
809
+ class="sort-row p-2 border-round surface-card"
810
+ pDraggable
811
+ pDroppable
812
+ (onDragStart)="onDragStart(i)"
813
+ (onDrop)="onDrop($event, i)"
814
+ [ngClass]="{'border-left-3 border-primary': isFirst, 'border-left-3 border-200': !isFirst}">
815
+
816
+ <div class="grid grid-cols-4 align-items-center gap-2">
817
+ <!-- Drag Handle -->
818
+ <div class="col-span-2 flex">
819
+ <button
820
+ pButton
821
+ icon="pi pi-bars"
822
+ type="button"
823
+ class="p-button-text p-button-plain cursor-move"
824
+ [pTooltip]="'DRAG_TOOLTIP' | translate"
825
+ tooltipPosition="top">
826
+ </button>
827
+ <p-select
828
+ [options]="getAvailableFields(sort.field)"
829
+ optionLabel="label"
830
+ optionValue="key"
831
+ [(ngModel)]="sort.field"
832
+ (onChange)="updateValue()"
833
+ [placeholder]="'SELECT_FIELD_SORT' | translate"
834
+ [showClear]="true"
835
+ appendTo="body"
836
+ styleClass="w-full">
837
+ </p-select>
838
+ </div>
898
839
 
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> -->
840
+ <!-- Direction Selector -->
841
+ <div class="col-fixed">
842
+ <p-select
843
+ [options]="directionOptions"
844
+ [(ngModel)]="sort.direction"
845
+ (onChange)="updateValue()"
846
+ [placeholder]="'DIRECTION' | translate"
847
+ appendTo="body"
848
+ styleClass="w-full">
849
+ </p-select>
903
850
  </div>
904
- </div>
905
851
 
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>
852
+ <!-- Actions -->
853
+ <div class="col-fixed flex gap-2" style="justify-content: flex-end;">
854
+ <!-- Move Up -->
855
+ <button
856
+ outlined
857
+ style="width: var(--p-button-icon-only-width);"
858
+ *ngIf="!isFirst"
859
+ pButton
860
+ icon="pi pi-arrow-up"
861
+ type="button"
862
+ class="p-button-sm p-button-success"
863
+ (click)="moveSort(i, i - 1)"
864
+ [pTooltip]="'MOVE_UP' | translate"
865
+ tooltipPosition="top">
866
+ </button>
912
867
 
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>
868
+ <!-- Move Down -->
869
+ <button
870
+ outlined
871
+ style="width: var(--p-button-icon-only-width);"
872
+ *ngIf="!isLast"
873
+ pButton
874
+ icon="pi pi-arrow-down"
875
+ type="button"
876
+ class="p-button-sm p-button-success"
877
+ (click)="moveSort(i, i + 1)"
878
+ [pTooltip]="'MOVE_DOWN' | translate"
879
+ tooltipPosition="top">
880
+ </button>
947
881
 
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>
882
+ <!-- Remove -->
883
+ <button
884
+ style="width: var(--p-button-icon-only-width);"
885
+ pButton
886
+ icon="pi pi-times"
887
+ type="button"
888
+ class="p-button-sm p-button-danger"
889
+ (click)="removeSort(i)"
890
+ [pTooltip]="'REMOVE_SORT' | translate"
891
+ tooltipPosition="top">
892
+ </button>
959
893
  </div>
960
894
  </div>
961
895
  </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"] }] });
896
+ </div>
897
+
898
+ <!-- Empty State -->
899
+ <div *ngIf="sorts.length === 0" class="empty-state text-center p-4 border-round surface-section">
900
+ <i class="pi pi-sort-alt text-4xl text-500 mb-3"></i>
901
+ <p class="text-500 mb-3">{{ 'NO_SORT_RULES' | translate }}</p>
902
+ <p class="text-400 text-sm mb-3">{{ 'DEFAULT_ORDER' | translate }}</p>
903
+ </div>
904
+
905
+ <!-- Actions -->
906
+ <div class="flex gap-2">
907
+ <button
908
+ pButton
909
+ icon="pi pi-sort-alt"
910
+ [label]="'ADD_SORT' | translate"
911
+ type="button"
912
+ class="p-button-outlined flex-1"
913
+ (click)="addSort()">
914
+ </button>
915
+
916
+ <button
917
+ *ngIf="sorts.length > 1"
918
+ pButton
919
+ icon="pi pi-random"
920
+ [label]="'REVERSE_ORDER' | translate"
921
+ type="button"
922
+ class="p-button-outlined"
923
+ (click)="reverseSorts()"
924
+ [pTooltip]="'REVERSE_TOOLTIP' | translate"
925
+ tooltipPosition="top">
926
+ </button>
927
+
928
+ <button
929
+ *ngIf="sorts.length > 0"
930
+ pButton
931
+ icon="pi pi-trash"
932
+ type="button"
933
+ class="p-button-outlined p-button-danger"
934
+ (click)="clearAll()"
935
+ [pTooltip]="'CLEAR_ALL_TOOLTIP' | translate"
936
+ tooltipPosition="top">
937
+ </button>
938
+ </div>
939
+
940
+ <!-- Summary -->
941
+ <div *ngIf="sorts.length > 0" class="sort-summary mt-3 p-2 border-round surface-ground">
942
+ <h5 class="mt-0 mb-2 text-sm">{{ 'SORT_SUMMARY' | translate }}:</h5>
943
+ <div class="text-sm text-500">
944
+ <span *ngFor="let sort of sorts; let i = index" class="sort-step">
945
+ <span class="font-semibold">{{ getFieldLabel(sort.field) }}</span>
946
+ <span class="direction-badge" [ngClass]="sort.direction === 'asc' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'">
947
+ {{ sort.direction === 'asc' ? '▲' : '▼' }}
948
+ </span>
949
+ <span *ngIf="!isLast"> {{ 'THEN' | translate }} </span>
950
+ </span>
951
+ </div>
952
+ </div>
953
+ </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: i4$1.TranslatePipe, name: "translate" }] });
963
954
  }
964
955
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SortBuilderComponent, decorators: [{
965
956
  type: Component,
@@ -969,184 +960,163 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImpor
969
960
  SelectModule,
970
961
  ButtonModule,
971
962
  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>
963
+ TooltipModule,
964
+ TranslateModule
965
+ ], template: `<div class="sort-builder p-3 border-round border-1 surface-border">
966
+ <div class="mb-6">
967
+ <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || ('SORTING' | translate) }}</h5>
968
+ <p class="text-gray-600 text-sm">{{ ('PRIORITY_HINT' | translate) }}</p>
969
+ </div>
970
+
971
+ <!-- Sort List -->
972
+ <div *ngIf="sorts.length > 0" class="sort-list space-y-2 mb-3">
973
+ <div
974
+ *ngFor="let sort of sorts; let i = index; let isFirst = first; let isLast = last"
975
+ class="sort-row p-2 border-round surface-card"
976
+ pDraggable
977
+ pDroppable
978
+ (onDragStart)="onDragStart(i)"
979
+ (onDrop)="onDrop($event, i)"
980
+ [ngClass]="{'border-left-3 border-primary': isFirst, 'border-left-3 border-200': !isFirst}">
981
+
982
+ <div class="grid grid-cols-4 align-items-center gap-2">
983
+ <!-- Drag Handle -->
984
+ <div class="col-span-2 flex">
985
+ <button
986
+ pButton
987
+ icon="pi pi-bars"
988
+ type="button"
989
+ class="p-button-text p-button-plain cursor-move"
990
+ [pTooltip]="'DRAG_TOOLTIP' | translate"
991
+ tooltipPosition="top">
992
+ </button>
993
+ <p-select
994
+ [options]="getAvailableFields(sort.field)"
995
+ optionLabel="label"
996
+ optionValue="key"
997
+ [(ngModel)]="sort.field"
998
+ (onChange)="updateValue()"
999
+ [placeholder]="'SELECT_FIELD_SORT' | translate"
1000
+ [showClear]="true"
1001
+ appendTo="body"
1002
+ styleClass="w-full">
1003
+ </p-select>
1004
+ </div>
1085
1005
 
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> -->
1006
+ <!-- Direction Selector -->
1007
+ <div class="col-fixed">
1008
+ <p-select
1009
+ [options]="directionOptions"
1010
+ [(ngModel)]="sort.direction"
1011
+ (onChange)="updateValue()"
1012
+ [placeholder]="'DIRECTION' | translate"
1013
+ appendTo="body"
1014
+ styleClass="w-full">
1015
+ </p-select>
1090
1016
  </div>
1091
- </div>
1092
1017
 
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>
1018
+ <!-- Actions -->
1019
+ <div class="col-fixed flex gap-2" style="justify-content: flex-end;">
1020
+ <!-- Move Up -->
1021
+ <button
1022
+ outlined
1023
+ style="width: var(--p-button-icon-only-width);"
1024
+ *ngIf="!isFirst"
1025
+ pButton
1026
+ icon="pi pi-arrow-up"
1027
+ type="button"
1028
+ class="p-button-sm p-button-success"
1029
+ (click)="moveSort(i, i - 1)"
1030
+ [pTooltip]="'MOVE_UP' | translate"
1031
+ tooltipPosition="top">
1032
+ </button>
1099
1033
 
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>
1034
+ <!-- Move Down -->
1035
+ <button
1036
+ outlined
1037
+ style="width: var(--p-button-icon-only-width);"
1038
+ *ngIf="!isLast"
1039
+ pButton
1040
+ icon="pi pi-arrow-down"
1041
+ type="button"
1042
+ class="p-button-sm p-button-success"
1043
+ (click)="moveSort(i, i + 1)"
1044
+ [pTooltip]="'MOVE_DOWN' | translate"
1045
+ tooltipPosition="top">
1046
+ </button>
1134
1047
 
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>
1048
+ <!-- Remove -->
1049
+ <button
1050
+ style="width: var(--p-button-icon-only-width);"
1051
+ pButton
1052
+ icon="pi pi-times"
1053
+ type="button"
1054
+ class="p-button-sm p-button-danger"
1055
+ (click)="removeSort(i)"
1056
+ [pTooltip]="'REMOVE_SORT' | translate"
1057
+ tooltipPosition="top">
1058
+ </button>
1146
1059
  </div>
1147
1060
  </div>
1148
1061
  </div>
1149
- ` }]
1062
+ </div>
1063
+
1064
+ <!-- Empty State -->
1065
+ <div *ngIf="sorts.length === 0" class="empty-state text-center p-4 border-round surface-section">
1066
+ <i class="pi pi-sort-alt text-4xl text-500 mb-3"></i>
1067
+ <p class="text-500 mb-3">{{ 'NO_SORT_RULES' | translate }}</p>
1068
+ <p class="text-400 text-sm mb-3">{{ 'DEFAULT_ORDER' | translate }}</p>
1069
+ </div>
1070
+
1071
+ <!-- Actions -->
1072
+ <div class="flex gap-2">
1073
+ <button
1074
+ pButton
1075
+ icon="pi pi-sort-alt"
1076
+ [label]="'ADD_SORT' | translate"
1077
+ type="button"
1078
+ class="p-button-outlined flex-1"
1079
+ (click)="addSort()">
1080
+ </button>
1081
+
1082
+ <button
1083
+ *ngIf="sorts.length > 1"
1084
+ pButton
1085
+ icon="pi pi-random"
1086
+ [label]="'REVERSE_ORDER' | translate"
1087
+ type="button"
1088
+ class="p-button-outlined"
1089
+ (click)="reverseSorts()"
1090
+ [pTooltip]="'REVERSE_TOOLTIP' | translate"
1091
+ tooltipPosition="top">
1092
+ </button>
1093
+
1094
+ <button
1095
+ *ngIf="sorts.length > 0"
1096
+ pButton
1097
+ icon="pi pi-trash"
1098
+ type="button"
1099
+ class="p-button-outlined p-button-danger"
1100
+ (click)="clearAll()"
1101
+ [pTooltip]="'CLEAR_ALL_TOOLTIP' | translate"
1102
+ tooltipPosition="top">
1103
+ </button>
1104
+ </div>
1105
+
1106
+ <!-- Summary -->
1107
+ <div *ngIf="sorts.length > 0" class="sort-summary mt-3 p-2 border-round surface-ground">
1108
+ <h5 class="mt-0 mb-2 text-sm">{{ 'SORT_SUMMARY' | translate }}:</h5>
1109
+ <div class="text-sm text-500">
1110
+ <span *ngFor="let sort of sorts; let i = index" class="sort-step">
1111
+ <span class="font-semibold">{{ getFieldLabel(sort.field) }}</span>
1112
+ <span class="direction-badge" [ngClass]="sort.direction === 'asc' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'">
1113
+ {{ sort.direction === 'asc' ? '▲' : '▼' }}
1114
+ </span>
1115
+ <span *ngIf="!isLast"> {{ 'THEN' | translate }} </span>
1116
+ </span>
1117
+ </div>
1118
+ </div>
1119
+ </div>` }]
1150
1120
  }] });
1151
1121
 
1152
1122
  // query-builder.component.ts
@@ -1437,7 +1407,7 @@ class QueryBuilderComponent extends FieldType {
1437
1407
  }
1438
1408
  }
1439
1409
  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" }] });
1410
+ 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: i4$1.TranslatePipe, name: "translate" }] });
1441
1411
  }
1442
1412
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: QueryBuilderComponent, decorators: [{
1443
1413
  type: Component,
@@ -1543,7 +1513,7 @@ class TabTypeComponent extends FieldType {
1543
1513
  </p-tabpanel>
1544
1514
  </p-tabpanels>
1545
1515
  </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" }] });
1516
+ `, 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: i4$1.TranslatePipe, name: "translate" }] });
1547
1517
  }
1548
1518
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: TabTypeComponent, decorators: [{
1549
1519
  type: Component,
@@ -1801,311 +1771,309 @@ class ColumnsBuilderComponent extends FieldType {
1801
1771
  }
1802
1772
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ColumnsBuilderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1803
1773
  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>
1774
+ <div>
1775
+ <!-- Header -->
1776
+ <div class="mb-6">
1777
+ <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || ('COLUMNS_MANAGEMENT' | translate) }}</h5>
1778
+ <p class="text-gray-600 text-sm">{{ props.description || ('COLUMNS_DESCRIPTION' | translate) }}</p>
1779
+ </div>
1780
+
1781
+ <!-- Quick Actions -->
1782
+ <div class="flex flex-wrap gap-2 mb-6">
1783
+ <button
1784
+ type="button"
1785
+ (click)="toggleAll(true)"
1786
+ 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"
1787
+ >
1788
+ <i class="pi pi-eye"></i>
1789
+ {{ 'SHOW_ALL' | translate }}
1790
+ </button>
1791
+ <button
1792
+ type="button"
1793
+ (click)="toggleAll(false)"
1794
+ 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"
1795
+ >
1796
+ <i class="pi pi-eye-slash"></i>
1797
+ {{ 'HIDE_ALL' | translate }}
1798
+ </button>
1799
+ <button
1800
+ type="button"
1801
+ (click)="resetToDefault()"
1802
+ 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"
1803
+ >
1804
+ <i class="pi pi-refresh"></i>
1805
+ {{ 'RESET_TO_DEFAULT' | translate }}
1806
+ </button>
1807
+ </div>
1808
+
1809
+ <!-- Drag Info -->
1810
+ <div class="mb-4 p-2 bg-blue-50 border border-blue-200 rounded text-sm text-blue-700">
1811
+ <i class="pi pi-info-circle mr-2"></i>
1812
+ {{ 'DRAG_COLUMNS_INFO' | translate }}
1813
+ </div>
1814
+
1815
+ <!-- Columns List -->
1816
+ <div class="space-y-3">
1817
+ <div *ngIf="columns.length === 0" class="text-center py-8 px-4 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50">
1818
+ <i class="pi pi-table text-4xl text-gray-400 mb-3"></i>
1819
+ <p class="text-gray-500">{{ 'NO_COLUMNS_AVAILABLE' | translate }}</p>
1820
+ </div>
1851
1821
 
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"
1822
+ <div *ngFor="let column of columns; let i = index"
1823
+ class="bg-gray-50 rounded-lg border border-gray-200 p-1 transition-colors hover:bg-gray-100"
1824
+ draggable="true"
1825
+ (dragstart)="onDragStart($event, i)"
1826
+ (dragover)="onDragOver($event)"
1827
+ (drop)="onDrop($event, i)"
1828
+ (dragenter)="onDragEnter($event)"
1829
+ (dragleave)="onDragLeave($event)">
1830
+
1831
+ <div class="grid grid-cols-12 gap-4 items-center">
1832
+ <!-- Drag Handle -->
1833
+ <div class="col-span-1 flex justify-center cursor-move text-gray-400 hover:text-gray-600"
1854
1834
  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>
1835
+ (dragstart)="onDragStart($event, i)">
1836
+ <i class="pi pi-bars"></i>
1837
+ </div>
1880
1838
 
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>
1839
+ <!-- Visibility Toggle -->
1840
+ <div class="col-span-1 flex justify-center">
1841
+ <p-checkbox
1842
+ [binary]="true"
1843
+ [formControl]="getColumnControl(column.key, 'isVisible')"
1844
+ [inputId]="'visible_' + column.key"
1845
+ styleClass="[&>div]:border-gray-300 [&>div]:hover:border-gray-400"
1846
+ (onChange)="onFormChange()"
1847
+ >
1848
+ </p-checkbox>
1849
+ </div>
1888
1850
 
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>
1851
+ <!-- Column Info -->
1852
+ <div class="col-span-12 md:col-span-4">
1853
+ <label [for]="'visible_' + column.key" class="block font-medium text-gray-900 cursor-pointer hover:text-blue-600">
1854
+ {{ column.label }}
1855
+ </label>
1856
+ <p class="text-xs text-gray-500 mt-1">{{ column.key }}</p>
1857
+ </div>
1900
1858
 
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>
1859
+ <!-- Display Name -->
1860
+ <div class="col-span-12 md:col-span-3">
1861
+ <input
1862
+ *ngIf="isColumnVisible(column.key)"
1863
+ type="text"
1864
+ [formControl]="getColumnControl(column.key, 'displayName')"
1865
+ [placeholder]="column.label"
1866
+ 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"
1867
+ (blur)="onFormChange()"
1868
+ >
1869
+ </div>
1921
1870
 
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>
1871
+ <!-- Aggregate Function -->
1872
+ <!-- <div class="col-span-12 md:col-span-3">
1873
+ <div *ngIf="column.aggregatable && isColumnVisible(column.key)">
1874
+ <p-select
1875
+ [options]="aggregateFunctions"
1876
+ optionLabel="label"
1877
+ optionValue="value"
1878
+ [formControl]="getColumnControl(column.key, 'aggregateFunction')"
1879
+ [placeholder]="'SELECT_AGGREGATE' | translate"
1880
+ [showClear]="true"
1881
+ styleClass="w-full"
1882
+ (onChange)="onFormChange()"
1883
+ >
1884
+ </p-select>
1932
1885
  </div>
1933
- </div>
1886
+ <span *ngIf="!column.aggregatable && isColumnVisible(column.key)" class="text-xs text-gray-500">
1887
+ {{ 'NO_AGGREGATES_AVAILABLE' | translate }}
1888
+ </span>
1889
+ </div> -->
1934
1890
  </div>
1935
1891
 
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
1892
+ <!-- Aggregate Info -->
1893
+ <div *ngIf="hasAggregateFunction(column.key) && isColumnVisible(column.key)"
1894
+ class="mt-3 p-3 bg-blue-50 border border-blue-200 rounded-lg">
1895
+ <div class="flex items-center gap-2">
1896
+ <i class="pi pi-info-circle text-blue-500 text-sm"></i>
1897
+ <span class="text-sm text-blue-800">
1898
+ {{ 'AGGREGATE_INFO' | translate:{function: getAggregateLabel(getAggregateFunctionValue(column.key))} }}
1949
1899
  </span>
1950
1900
  </div>
1951
1901
  </div>
1952
1902
  </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 }] });
1903
+ </div>
1904
+
1905
+ <!-- Summary -->
1906
+ <div class="flex flex-col sm:flex-row justify-between items-center gap-4 mt-6 pt-4 border-t border-gray-200">
1907
+ <span class="text-sm text-gray-600">
1908
+ {{ 'COLUMNS_VISIBLE_COUNT' | translate:{visible: visibleColumnsCount, total: columns.length} }}
1909
+ </span>
1910
+ <!-- <div class="flex gap-4 text-sm">
1911
+ <span class="inline-flex items-center gap-1 text-green-600">
1912
+ <i class="pi pi-chart-line"></i>
1913
+ {{ numericColumnsCount }} {{ 'NUMERIC' | translate }}
1914
+ </span>
1915
+ <span class="inline-flex items-center gap-1 text-blue-600">
1916
+ <i class="pi pi-calculator"></i>
1917
+ {{ aggregatedColumnsCount }} {{ 'AGGREGATED' | translate }}
1918
+ </span>
1919
+ </div> -->
1920
+ </div>
1921
+ </div>
1922
+ `, 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: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: DatePickerModule }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i3$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: i4$1.TranslatePipe, name: "translate" }] });
1954
1923
  }
1955
1924
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ColumnsBuilderComponent, decorators: [{
1956
1925
  type: Component,
1957
1926
  args: [{
1958
1927
  selector: 'formly-columns-builder',
1959
1928
  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>
1929
+ <div>
1930
+ <!-- Header -->
1931
+ <div class="mb-6">
1932
+ <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || ('COLUMNS_MANAGEMENT' | translate) }}</h5>
1933
+ <p class="text-gray-600 text-sm">{{ props.description || ('COLUMNS_DESCRIPTION' | translate) }}</p>
1934
+ </div>
1935
+
1936
+ <!-- Quick Actions -->
1937
+ <div class="flex flex-wrap gap-2 mb-6">
1938
+ <button
1939
+ type="button"
1940
+ (click)="toggleAll(true)"
1941
+ 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"
1942
+ >
1943
+ <i class="pi pi-eye"></i>
1944
+ {{ 'SHOW_ALL' | translate }}
1945
+ </button>
1946
+ <button
1947
+ type="button"
1948
+ (click)="toggleAll(false)"
1949
+ 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"
1950
+ >
1951
+ <i class="pi pi-eye-slash"></i>
1952
+ {{ 'HIDE_ALL' | translate }}
1953
+ </button>
1954
+ <button
1955
+ type="button"
1956
+ (click)="resetToDefault()"
1957
+ 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"
1958
+ >
1959
+ <i class="pi pi-refresh"></i>
1960
+ {{ 'RESET_TO_DEFAULT' | translate }}
1961
+ </button>
1962
+ </div>
1963
+
1964
+ <!-- Drag Info -->
1965
+ <div class="mb-4 p-2 bg-blue-50 border border-blue-200 rounded text-sm text-blue-700">
1966
+ <i class="pi pi-info-circle mr-2"></i>
1967
+ {{ 'DRAG_COLUMNS_INFO' | translate }}
1968
+ </div>
1969
+
1970
+ <!-- Columns List -->
1971
+ <div class="space-y-3">
1972
+ <div *ngIf="columns.length === 0" class="text-center py-8 px-4 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50">
1973
+ <i class="pi pi-table text-4xl text-gray-400 mb-3"></i>
1974
+ <p class="text-gray-500">{{ 'NO_COLUMNS_AVAILABLE' | translate }}</p>
1975
+ </div>
2007
1976
 
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"
1977
+ <div *ngFor="let column of columns; let i = index"
1978
+ class="bg-gray-50 rounded-lg border border-gray-200 p-1 transition-colors hover:bg-gray-100"
1979
+ draggable="true"
1980
+ (dragstart)="onDragStart($event, i)"
1981
+ (dragover)="onDragOver($event)"
1982
+ (drop)="onDrop($event, i)"
1983
+ (dragenter)="onDragEnter($event)"
1984
+ (dragleave)="onDragLeave($event)">
1985
+
1986
+ <div class="grid grid-cols-12 gap-4 items-center">
1987
+ <!-- Drag Handle -->
1988
+ <div class="col-span-1 flex justify-center cursor-move text-gray-400 hover:text-gray-600"
2010
1989
  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>
1990
+ (dragstart)="onDragStart($event, i)">
1991
+ <i class="pi pi-bars"></i>
1992
+ </div>
2036
1993
 
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>
1994
+ <!-- Visibility Toggle -->
1995
+ <div class="col-span-1 flex justify-center">
1996
+ <p-checkbox
1997
+ [binary]="true"
1998
+ [formControl]="getColumnControl(column.key, 'isVisible')"
1999
+ [inputId]="'visible_' + column.key"
2000
+ styleClass="[&>div]:border-gray-300 [&>div]:hover:border-gray-400"
2001
+ (onChange)="onFormChange()"
2002
+ >
2003
+ </p-checkbox>
2004
+ </div>
2044
2005
 
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>
2006
+ <!-- Column Info -->
2007
+ <div class="col-span-12 md:col-span-4">
2008
+ <label [for]="'visible_' + column.key" class="block font-medium text-gray-900 cursor-pointer hover:text-blue-600">
2009
+ {{ column.label }}
2010
+ </label>
2011
+ <p class="text-xs text-gray-500 mt-1">{{ column.key }}</p>
2012
+ </div>
2056
2013
 
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>
2014
+ <!-- Display Name -->
2015
+ <div class="col-span-12 md:col-span-3">
2016
+ <input
2017
+ *ngIf="isColumnVisible(column.key)"
2018
+ type="text"
2019
+ [formControl]="getColumnControl(column.key, 'displayName')"
2020
+ [placeholder]="column.label"
2021
+ 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"
2022
+ (blur)="onFormChange()"
2023
+ >
2024
+ </div>
2077
2025
 
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>
2026
+ <!-- Aggregate Function -->
2027
+ <!-- <div class="col-span-12 md:col-span-3">
2028
+ <div *ngIf="column.aggregatable && isColumnVisible(column.key)">
2029
+ <p-select
2030
+ [options]="aggregateFunctions"
2031
+ optionLabel="label"
2032
+ optionValue="value"
2033
+ [formControl]="getColumnControl(column.key, 'aggregateFunction')"
2034
+ [placeholder]="'SELECT_AGGREGATE' | translate"
2035
+ [showClear]="true"
2036
+ styleClass="w-full"
2037
+ (onChange)="onFormChange()"
2038
+ >
2039
+ </p-select>
2088
2040
  </div>
2089
- </div>
2041
+ <span *ngIf="!column.aggregatable && isColumnVisible(column.key)" class="text-xs text-gray-500">
2042
+ {{ 'NO_AGGREGATES_AVAILABLE' | translate }}
2043
+ </span>
2044
+ </div> -->
2090
2045
  </div>
2091
2046
 
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
2047
+ <!-- Aggregate Info -->
2048
+ <div *ngIf="hasAggregateFunction(column.key) && isColumnVisible(column.key)"
2049
+ class="mt-3 p-3 bg-blue-50 border border-blue-200 rounded-lg">
2050
+ <div class="flex items-center gap-2">
2051
+ <i class="pi pi-info-circle text-blue-500 text-sm"></i>
2052
+ <span class="text-sm text-blue-800">
2053
+ {{ 'AGGREGATE_INFO' | translate:{function: getAggregateLabel(getAggregateFunctionValue(column.key))} }}
2105
2054
  </span>
2106
2055
  </div>
2107
2056
  </div>
2108
2057
  </div>
2058
+ </div>
2059
+
2060
+ <!-- Summary -->
2061
+ <div class="flex flex-col sm:flex-row justify-between items-center gap-4 mt-6 pt-4 border-t border-gray-200">
2062
+ <span class="text-sm text-gray-600">
2063
+ {{ 'COLUMNS_VISIBLE_COUNT' | translate:{visible: visibleColumnsCount, total: columns.length} }}
2064
+ </span>
2065
+ <!-- <div class="flex gap-4 text-sm">
2066
+ <span class="inline-flex items-center gap-1 text-green-600">
2067
+ <i class="pi pi-chart-line"></i>
2068
+ {{ numericColumnsCount }} {{ 'NUMERIC' | translate }}
2069
+ </span>
2070
+ <span class="inline-flex items-center gap-1 text-blue-600">
2071
+ <i class="pi pi-calculator"></i>
2072
+ {{ aggregatedColumnsCount }} {{ 'AGGREGATED' | translate }}
2073
+ </span>
2074
+ </div> -->
2075
+ </div>
2076
+ </div>
2109
2077
  `,
2110
2078
  imports: [
2111
2079
  CommonModule,
@@ -2266,321 +2234,317 @@ class GroupBuilderComponent extends FieldType {
2266
2234
  return this.groups.length < this.maxGroups;
2267
2235
  }
2268
2236
  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>
2237
+ 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>
2238
+ <!-- Header -->
2239
+ <div class="mb-6">
2240
+ <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || ('DATA_GROUPING' | translate) }}</h5>
2241
+ <p class="text-gray-600 text-sm">{{ props.description || ('GROUP_DESCRIPTION' | translate) }}</p>
2242
+ </div>
2243
+
2244
+ <!-- Group Configuration -->
2245
+ <div class="space-y-4">
2246
+ <div class="flex items-center justify-between">
2247
+ <span class="font-medium text-gray-700">{{ 'GROUP_LEVELS' | translate }}</span>
2248
+ <button
2249
+ type="button"
2250
+ *ngIf="canAddMoreGroups()"
2251
+ (click)="addGroup()"
2252
+ [disabled]="!canAddMoreGroups()"
2253
+ 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"
2254
+ >
2255
+ <i class="pi pi-plus"></i>
2256
+ {{ 'ADD_GROUP_LEVEL' | translate }}
2257
+ </button>
2258
+ </div>
2292
2259
 
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>
2260
+ <!-- Drag Info -->
2261
+ <div *ngIf="groups.length > 1" class="mb-4 p-2 bg-blue-50 border border-blue-200 rounded text-sm text-blue-700">
2262
+ <i class="pi pi-info-circle mr-2"></i>
2263
+ {{ 'DRAG_INFO' | translate }}
2264
+ </div>
2298
2265
 
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>
2266
+ <!-- Empty State -->
2267
+ <div *ngIf="groups.length === 0" class="text-center py-8 px-4 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50">
2268
+ <i class="pi pi-layer-group text-4xl text-gray-400 mb-3"></i>
2269
+ <p class="text-gray-500 mb-4">{{ 'NO_GROUPING_LEVELS' | translate }}</p>
2270
+ <button
2271
+ type="button"
2272
+ (click)="addGroup()"
2273
+ 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"
2274
+ >
2275
+ <i class="pi pi-plus"></i>
2276
+ {{ 'ADD_FIRST_GROUP_LEVEL' | translate }}
2277
+ </button>
2278
+ </div>
2312
2279
 
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"
2280
+ <!-- Groups List with Drag & Drop -->
2281
+ <div class="space-y-3">
2282
+ <div *ngFor="let group of groups.controls; let i = index"
2283
+ class="bg-gray-50 rounded-lg border border-gray-200 p-4 transition-colors hover:bg-gray-100"
2284
+ draggable="true"
2285
+ (dragstart)="onDragStart($event, i)"
2286
+ (dragover)="onDragOver($event)"
2287
+ (drop)="onDrop($event, i)"
2288
+ (dragenter)="onDragEnter($event)"
2289
+ (dragleave)="onDragLeave($event)"
2290
+ (dragend)="onDragEnd($event)">
2291
+
2292
+ <div class="grid grid-cols-12 gap-4 items-start">
2293
+ <!-- Drag Handle -->
2294
+ <div *ngIf="groups.length > 1"
2295
+ class="col-span-1 flex justify-center cursor-move text-gray-400 hover:text-gray-600 pt-2"
2317
2296
  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>
2297
+ (dragstart)="onDragStart($event, i)">
2298
+ <i class="pi pi-bars"></i>
2299
+ </div>
2300
+
2301
+ <!-- Group Content -->
2302
+ <div class="col-span-11">
2303
+ <div class="flex items-center justify-between mb-3">
2304
+ <div class="flex items-center gap-2">
2305
+ <i class="pi pi-sort-alt text-gray-500"></i>
2306
+ <span class="font-medium text-gray-700">{{ 'GROUP_LEVEL' | translate }} {{ i + 1 }}</span>
2307
+ </div>
2308
+ <div class="flex items-center gap-1">
2309
+ <button
2310
+ type="button"
2311
+ (click)="removeGroup(i)"
2312
+ class="p-1 text-red-500 hover:text-red-700 hover:bg-red-50 rounded transition-colors"
2313
+ [pTooltip]="'REMOVE' | translate"
2314
+ >
2315
+ <i class="pi pi-times"></i>
2316
+ </button>
2332
2317
  </div>
2318
+ </div>
2333
2319
 
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>
2320
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
2321
+ <!-- Field Selection -->
2322
+ <div>
2323
+ <label class="block text-sm font-medium text-gray-700 mb-2">{{ 'FIELD' | translate }}</label>
2324
+ <p-select
2325
+ [options]="availableFields"
2326
+ optionLabel="label"
2327
+ optionValue="key"
2328
+ [formControl]="getGroupControl(i, 'field')"
2329
+ [placeholder]="'SELECT_FIELD' | translate"
2330
+ [showClear]="true"
2331
+ (onChange)="onFieldChange(i, $event.value)"
2332
+ styleClass="w-full"
2333
+ >
2334
+ <ng-template pTemplate="selectedItem">
2335
+ <span *ngIf="getGroupControl(i, 'field').value" class="text-gray-900">
2336
+ {{ getFieldLabel(getGroupControl(i, 'field').value) }}
2337
+ </span>
2338
+ <span *ngIf="!getGroupControl(i, 'field').value" class="text-gray-500">{{ 'SELECT_FIELD' | translate }}</span>
2339
+ </ng-template>
2340
+ </p-select>
2341
+ </div>
2342
+
2343
+ <!-- Display Name -->
2344
+ <div>
2345
+ <label class="block text-sm font-medium text-gray-700 mb-2">{{ 'DISPLAY_NAME' | translate }}</label>
2346
+ <input
2347
+ type="text"
2348
+ pInputText
2349
+ [formControl]="getGroupControl(i, 'displayName')"
2350
+ [placeholder]="'DISPLAY_NAME_PLACEHOLDER' | translate"
2351
+ class="w-full text-gray-900"
2352
+ (blur)="onFormChange()"
2353
+ >
2404
2354
  </div>
2405
2355
  </div>
2406
- </div>
2407
- </div>
2408
- </div>
2409
2356
 
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>
2357
+ <!-- Show Total Toggle -->
2358
+ <div class="flex items-center gap-2 mt-3">
2359
+ <p-checkbox
2360
+ [binary]="true"
2361
+ [formControl]="getGroupControl(i, 'showTotal')"
2362
+ [inputId]="'showTotal' + i"
2363
+ styleClass="[&>div]:border-gray-300 [&>div]:hover:border-gray-400"
2364
+ (onChange)="onFormChange()"
2365
+ >
2366
+ </p-checkbox>
2367
+ <label [for]="'showTotal' + i" class="text-sm text-gray-700 cursor-pointer hover:text-gray-900">
2368
+ {{ 'SHOW_TOTAL' | translate }}
2369
+ </label>
2370
+ </div>
2419
2371
  </div>
2420
2372
  </div>
2421
2373
  </div>
2422
2374
  </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 }] });
2375
+ </div>
2376
+
2377
+ <!-- Grouping Tips -->
2378
+ <div *ngIf="groups.length > 0" class="mt-4 p-4 bg-blue-50 border border-blue-200 rounded-lg">
2379
+ <div class="flex items-center gap-3">
2380
+ <i class="pi pi-info-circle text-blue-500"></i>
2381
+ <div>
2382
+ <p class="text-sm text-blue-800">
2383
+ {{ 'GROUPING_TIPS' | translate }}
2384
+ {{ groups.length }} {{ 'LEVELS_DEFINED' | translate:{count: groups.length} }}
2385
+ </p>
2386
+ </div>
2387
+ </div>
2388
+ </div>
2389
+ </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: i3$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: i4$1.TranslatePipe, name: "translate" }] });
2424
2390
  }
2425
2391
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: GroupBuilderComponent, decorators: [{
2426
2392
  type: Component,
2427
2393
  args: [{
2428
2394
  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>
2395
+ template: `<div>
2396
+ <!-- Header -->
2397
+ <div class="mb-6">
2398
+ <h5 class="text-lg font-semibold text-gray-900 mb-2">{{ props.label || ('DATA_GROUPING' | translate) }}</h5>
2399
+ <p class="text-gray-600 text-sm">{{ props.description || ('GROUP_DESCRIPTION' | translate) }}</p>
2400
+ </div>
2401
+
2402
+ <!-- Group Configuration -->
2403
+ <div class="space-y-4">
2404
+ <div class="flex items-center justify-between">
2405
+ <span class="font-medium text-gray-700">{{ 'GROUP_LEVELS' | translate }}</span>
2406
+ <button
2407
+ type="button"
2408
+ *ngIf="canAddMoreGroups()"
2409
+ (click)="addGroup()"
2410
+ [disabled]="!canAddMoreGroups()"
2411
+ 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"
2412
+ >
2413
+ <i class="pi pi-plus"></i>
2414
+ {{ 'ADD_GROUP_LEVEL' | translate }}
2415
+ </button>
2416
+ </div>
2452
2417
 
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>
2418
+ <!-- Drag Info -->
2419
+ <div *ngIf="groups.length > 1" class="mb-4 p-2 bg-blue-50 border border-blue-200 rounded text-sm text-blue-700">
2420
+ <i class="pi pi-info-circle mr-2"></i>
2421
+ {{ 'DRAG_INFO' | translate }}
2422
+ </div>
2458
2423
 
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>
2424
+ <!-- Empty State -->
2425
+ <div *ngIf="groups.length === 0" class="text-center py-8 px-4 border-2 border-dashed border-gray-300 rounded-lg bg-gray-50">
2426
+ <i class="pi pi-layer-group text-4xl text-gray-400 mb-3"></i>
2427
+ <p class="text-gray-500 mb-4">{{ 'NO_GROUPING_LEVELS' | translate }}</p>
2428
+ <button
2429
+ type="button"
2430
+ (click)="addGroup()"
2431
+ 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"
2432
+ >
2433
+ <i class="pi pi-plus"></i>
2434
+ {{ 'ADD_FIRST_GROUP_LEVEL' | translate }}
2435
+ </button>
2436
+ </div>
2472
2437
 
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"
2438
+ <!-- Groups List with Drag & Drop -->
2439
+ <div class="space-y-3">
2440
+ <div *ngFor="let group of groups.controls; let i = index"
2441
+ class="bg-gray-50 rounded-lg border border-gray-200 p-4 transition-colors hover:bg-gray-100"
2442
+ draggable="true"
2443
+ (dragstart)="onDragStart($event, i)"
2444
+ (dragover)="onDragOver($event)"
2445
+ (drop)="onDrop($event, i)"
2446
+ (dragenter)="onDragEnter($event)"
2447
+ (dragleave)="onDragLeave($event)"
2448
+ (dragend)="onDragEnd($event)">
2449
+
2450
+ <div class="grid grid-cols-12 gap-4 items-start">
2451
+ <!-- Drag Handle -->
2452
+ <div *ngIf="groups.length > 1"
2453
+ class="col-span-1 flex justify-center cursor-move text-gray-400 hover:text-gray-600 pt-2"
2477
2454
  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>
2455
+ (dragstart)="onDragStart($event, i)">
2456
+ <i class="pi pi-bars"></i>
2457
+ </div>
2458
+
2459
+ <!-- Group Content -->
2460
+ <div class="col-span-11">
2461
+ <div class="flex items-center justify-between mb-3">
2462
+ <div class="flex items-center gap-2">
2463
+ <i class="pi pi-sort-alt text-gray-500"></i>
2464
+ <span class="font-medium text-gray-700">{{ 'GROUP_LEVEL' | translate }} {{ i + 1 }}</span>
2465
+ </div>
2466
+ <div class="flex items-center gap-1">
2467
+ <button
2468
+ type="button"
2469
+ (click)="removeGroup(i)"
2470
+ class="p-1 text-red-500 hover:text-red-700 hover:bg-red-50 rounded transition-colors"
2471
+ [pTooltip]="'REMOVE' | translate"
2472
+ >
2473
+ <i class="pi pi-times"></i>
2474
+ </button>
2475
+ </div>
2476
+ </div>
2477
+
2478
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
2479
+ <!-- Field Selection -->
2480
+ <div>
2481
+ <label class="block text-sm font-medium text-gray-700 mb-2">{{ 'FIELD' | translate }}</label>
2482
+ <p-select
2483
+ [options]="availableFields"
2484
+ optionLabel="label"
2485
+ optionValue="key"
2486
+ [formControl]="getGroupControl(i, 'field')"
2487
+ [placeholder]="'SELECT_FIELD' | translate"
2488
+ [showClear]="true"
2489
+ (onChange)="onFieldChange(i, $event.value)"
2490
+ styleClass="w-full"
2491
+ >
2492
+ <ng-template pTemplate="selectedItem">
2493
+ <span *ngIf="getGroupControl(i, 'field').value" class="text-gray-900">
2494
+ {{ getFieldLabel(getGroupControl(i, 'field').value) }}
2495
+ </span>
2496
+ <span *ngIf="!getGroupControl(i, 'field').value" class="text-gray-500">{{ 'SELECT_FIELD' | translate }}</span>
2497
+ </ng-template>
2498
+ </p-select>
2492
2499
  </div>
2493
2500
 
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>
2501
+ <!-- Display Name -->
2502
+ <div>
2503
+ <label class="block text-sm font-medium text-gray-700 mb-2">{{ 'DISPLAY_NAME' | translate }}</label>
2504
+ <input
2505
+ type="text"
2506
+ pInputText
2507
+ [formControl]="getGroupControl(i, 'displayName')"
2508
+ [placeholder]="'DISPLAY_NAME_PLACEHOLDER' | translate"
2509
+ class="w-full text-gray-900"
2510
+ (blur)="onFormChange()"
2511
+ >
2564
2512
  </div>
2565
2513
  </div>
2566
- </div>
2567
- </div>
2568
- </div>
2569
2514
 
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>
2515
+ <!-- Show Total Toggle -->
2516
+ <div class="flex items-center gap-2 mt-3">
2517
+ <p-checkbox
2518
+ [binary]="true"
2519
+ [formControl]="getGroupControl(i, 'showTotal')"
2520
+ [inputId]="'showTotal' + i"
2521
+ styleClass="[&>div]:border-gray-300 [&>div]:hover:border-gray-400"
2522
+ (onChange)="onFormChange()"
2523
+ >
2524
+ </p-checkbox>
2525
+ <label [for]="'showTotal' + i" class="text-sm text-gray-700 cursor-pointer hover:text-gray-900">
2526
+ {{ 'SHOW_TOTAL' | translate }}
2527
+ </label>
2528
+ </div>
2579
2529
  </div>
2580
2530
  </div>
2581
2531
  </div>
2582
2532
  </div>
2583
- `,
2533
+ </div>
2534
+
2535
+ <!-- Grouping Tips -->
2536
+ <div *ngIf="groups.length > 0" class="mt-4 p-4 bg-blue-50 border border-blue-200 rounded-lg">
2537
+ <div class="flex items-center gap-3">
2538
+ <i class="pi pi-info-circle text-blue-500"></i>
2539
+ <div>
2540
+ <p class="text-sm text-blue-800">
2541
+ {{ 'GROUPING_TIPS' | translate }}
2542
+ {{ groups.length }} {{ 'LEVELS_DEFINED' | translate:{count: groups.length} }}
2543
+ </p>
2544
+ </div>
2545
+ </div>
2546
+ </div>
2547
+ </div>`,
2584
2548
  imports: [
2585
2549
  CommonModule,
2586
2550
  FormsModule,