@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.
- package/fesm2022/elite.framework-ng.ui.core-formly-ui-all.mjs +9 -1
- package/fesm2022/elite.framework-ng.ui.core-formly-ui-all.mjs.map +1 -1
- package/fesm2022/elite.framework-ng.ui.core-generic-crud-table.mjs +14 -2
- package/fesm2022/elite.framework-ng.ui.core-generic-crud-table.mjs.map +1 -1
- package/fesm2022/elite.framework-ng.ui.core-generic-search-advanced.mjs +883 -919
- package/fesm2022/elite.framework-ng.ui.core-generic-search-advanced.mjs.map +1 -1
- package/generic-crud-table/index.d.ts +4 -1
- package/package.json +21 -21
|
@@ -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
|
|
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
|
|
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
|
|
308
|
+
const tempFields = [];
|
|
309
309
|
this.traverseFields(fields, (field) => {
|
|
310
|
-
if (field.key &&
|
|
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
|
-
|
|
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
|
|
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
|
|
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:
|
|
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
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
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
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
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
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
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
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
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
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
</
|
|
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
|
-
|
|
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
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
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
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
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
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
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
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
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
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
</
|
|
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:
|
|
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
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
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
|
-
|
|
1853
|
-
|
|
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
|
-
|
|
1857
|
-
|
|
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
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
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
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
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
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
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
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
<
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
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
|
-
|
|
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
|
-
<!--
|
|
1937
|
-
<div
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
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
|
-
|
|
2009
|
-
|
|
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
|
-
|
|
2013
|
-
|
|
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
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
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
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
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
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
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
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
<
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
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
|
-
|
|
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
|
-
<!--
|
|
2093
|
-
<div
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
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
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
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
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
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
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
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
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
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
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
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
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
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
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
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
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
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
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
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
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
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
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
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
|
-
<!--
|
|
2495
|
-
<div
|
|
2496
|
-
<
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
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
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
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,
|