@dataclouder/ngx-core 0.1.46 → 0.1.48

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.
@@ -85,11 +85,11 @@ var OptionValue;
85
85
  OptionValue["ReverseAlphabetical"] = "reverseAlphabetical";
86
86
  })(OptionValue || (OptionValue = {}));
87
87
  const sortOptions = [
88
- { label: 'Más reciente', value: OptionValue.Newest },
89
- { label: 'Más antiguo', value: OptionValue.Oldest },
90
- { label: 'A-Z', value: OptionValue.Alphabetical },
91
- { label: 'Z-A', value: OptionValue.ReverseAlphabetical },
92
- { label: 'Última actualización', value: 'lastUpdated' },
88
+ { label: 'Más Reciente', value: OptionValue.Newest },
89
+ { label: 'Más Antiguo', value: OptionValue.Oldest },
90
+ { label: 'Actualizado Recientemente', value: 'lastUpdated' },
91
+ { label: 'Alfabético A-Z', value: OptionValue.Alphabetical },
92
+ { label: 'Alfabético Inverso Z-A', value: OptionValue.ReverseAlphabetical },
93
93
  ];
94
94
  const sortTypes = [
95
95
  { name: 'Recientes', code: 'newest', sort: { createdDate: -1 } },
@@ -218,9 +218,10 @@ class DcListFilterDialogComponent {
218
218
  this.ref = inject(DynamicDialogRef);
219
219
  this.config = inject(DynamicDialogConfig);
220
220
  this.customFilters = this.config.data.customFilters || [];
221
+ this.customSortOptions = this.config.data.customSortOptions || [];
221
222
  this.initialUiState = this.config.data.uiState || {};
222
223
  this.availibleFilters = availibleFilters;
223
- this.sortOptions = sortOptions;
224
+ this.sortOptions = [...sortOptions, ...this.customSortOptions];
224
225
  this.selectedFilters = [];
225
226
  this.selectedSort = null;
226
227
  this.dateRange = [];
@@ -228,7 +229,6 @@ class DcListFilterDialogComponent {
228
229
  this.restoreState();
229
230
  }
230
231
  buildCustomFiltersForm() {
231
- debugger;
232
232
  const formControls = {};
233
233
  for (const filter of this.customFilters) {
234
234
  formControls[filter.field] = [filter.defaultValue || null];
@@ -280,11 +280,11 @@ class DcListFilterDialogComponent {
280
280
  });
281
281
  }
282
282
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DcListFilterDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
283
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: DcListFilterDialogComponent, isStandalone: true, selector: "dc-list-filter-dialog", ngImport: i0, template: "<div class=\"filter-dialog-content flex flex-col justify-between h-full\">\n <!-- Filters Content -->\n <div>\n <!-- Sort Options -->\n <div class=\"field\">\n <label class=\"font-semibold block mb-2\">Ordenar por</label>\n <p-select [options]=\"sortOptions\" [(ngModel)]=\"selectedSort\" optionLabel=\"label\" [style]=\"{ width: '100%' }\" placeholder=\"Seleccionar orden\"> </p-select>\n </div>\n\n <!-- <p-multiselect [options]=\"availibleFilters\" [(ngModel)]=\"selectedFilters\" optionLabel=\"name\" placeholder=\"Filtros R\u00E1pidos\" [maxSelectedLabels]=\"3\" /> -->\n\n <!-- Date Filter -->\n <div class=\"field\">\n <label class=\"font-semibold block mb-2\">Rango de fechas</label>\n <p-datepicker\n [(ngModel)]=\"dateRange\"\n selectionMode=\"range\"\n [showButtonBar]=\"true\"\n [style]=\"{ width: '100%' }\"\n placeholder=\"Seleccionar fechas\"\n dateFormat=\"dd/mm/yy\">\n </p-datepicker>\n </div>\n\n @if (customFilters?.length > 0) {\n <form [formGroup]=\"customFiltersForm\">\n <h4>Filtros Personalizados</h4>\n @for (customFilter of customFilters; track customFilter.field) {\n <div class=\"field\">\n <label class=\"font-semibold block mb-2\">{{ customFilter.name }}</label>\n @switch (customFilter.type) { @case ('select') {\n <p-select\n [options]=\"customFilter.options\"\n [formControlName]=\"customFilter.field\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [style]=\"{ width: '100%' }\"\n placeholder=\"Seleccionar {{ customFilter.name }}\" />\n } @case ('string') {\n <input type=\"text\" pInputText [formControlName]=\"customFilter.field\" class=\"w-full\" />\n } @case ('date') {\n <p-datepicker [formControlName]=\"customFilter.field\" [style]=\"{ width: '100%' }\" dateFormat=\"dd/mm/yy\"></p-datepicker>\n } }\n </div>\n }\n </form>\n }\n </div>\n\n <!-- Action Buttons -->\n <div>\n <div class=\"flex justify-end gap-2\">\n <p-button label=\"Limpiar\" icon=\"pi pi-trash\" (click)=\"clearFilters()\" styleClass=\"p-button-text\"> </p-button>\n <p-button label=\"Aplicar\" icon=\"pi pi-check\" (click)=\"applyFilters()\" severity=\"primary\"> </p-button>\n </div>\n </div>\n</div>\n", styles: [":host ::ng-deep .filter-dialog-content{display:flex;flex-direction:column;gap:1.5rem;padding:1.5rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.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: DialogModule }, { 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: MultiSelectModule }, { kind: "ngmodule", type: DatePickerModule }, { kind: "component", type: i4.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
283
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: DcListFilterDialogComponent, isStandalone: true, selector: "dc-list-filter-dialog", ngImport: i0, template: "<div class=\"filter-dialog-content flex flex-col justify-between h-full\">\n <!-- Filters Content -->\n <div>\n <!-- Sort Options -->\n <div class=\"field\">\n <label class=\"font-semibold block mb-2\">Ordenar por</label>\n <p-select [options]=\"sortOptions\" [(ngModel)]=\"selectedSort\" optionLabel=\"label\" [style]=\"{ width: '100%' }\" placeholder=\"Seleccionar orden\"> </p-select>\n </div>\n\n <!-- <p-multiselect [options]=\"availibleFilters\" [(ngModel)]=\"selectedFilters\" optionLabel=\"name\" placeholder=\"Filtros R\u00E1pidos\" [maxSelectedLabels]=\"3\" /> -->\n\n <!-- Date Filter -->\n <div class=\"field\">\n <label class=\"font-semibold block mb-2\">Rango de fechas</label>\n <p-datepicker\n [(ngModel)]=\"dateRange\"\n selectionMode=\"range\"\n [showButtonBar]=\"true\"\n [style]=\"{ width: '100%' }\"\n placeholder=\"Seleccionar fechas\"\n dateFormat=\"dd/mm/yy\">\n </p-datepicker>\n </div>\n\n @if (customFilters?.length > 0) {\n <form [formGroup]=\"customFiltersForm\">\n <h4>Filtros Personalizados</h4>\n @for (customFilter of customFilters; track customFilter.field) {\n <div class=\"field\">\n <label class=\"font-semibold block mb-2\">{{ customFilter.name }}</label>\n @switch (customFilter.type) { @case ('select') {\n <p-select\n [options]=\"customFilter.options\"\n [formControlName]=\"customFilter.field\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [showClear]=\"true\"\n [style]=\"{ width: '100%' }\"\n placeholder=\"Seleccionar {{ customFilter.name }}\" />\n } @case ('string') {\n <input type=\"text\" pInputText [formControlName]=\"customFilter.field\" class=\"w-full\" />\n } @case ('date') {\n <p-datepicker [formControlName]=\"customFilter.field\" [style]=\"{ width: '100%' }\" dateFormat=\"dd/mm/yy\"></p-datepicker>\n } }\n </div>\n }\n </form>\n }\n </div>\n\n <!-- Action Buttons -->\n <div>\n <div class=\"flex justify-end gap-2\">\n <p-button label=\"Limpiar\" icon=\"pi pi-trash\" (click)=\"clearFilters()\" styleClass=\"p-button-text\"> </p-button>\n <p-button label=\"Aplicar\" icon=\"pi pi-check\" (click)=\"applyFilters()\" severity=\"primary\"> </p-button>\n </div>\n </div>\n</div>\n", styles: [":host ::ng-deep .filter-dialog-content{display:flex;flex-direction:column;gap:1.5rem;padding:1.5rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.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: DialogModule }, { 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: MultiSelectModule }, { kind: "ngmodule", type: DatePickerModule }, { kind: "component", type: i4.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
284
284
  }
285
285
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DcListFilterDialogComponent, decorators: [{
286
286
  type: Component,
287
- args: [{ selector: 'dc-list-filter-dialog', standalone: true, imports: [FormsModule, ReactiveFormsModule, ButtonModule, DialogModule, SelectModule, MultiSelectModule, DatePickerModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"filter-dialog-content flex flex-col justify-between h-full\">\n <!-- Filters Content -->\n <div>\n <!-- Sort Options -->\n <div class=\"field\">\n <label class=\"font-semibold block mb-2\">Ordenar por</label>\n <p-select [options]=\"sortOptions\" [(ngModel)]=\"selectedSort\" optionLabel=\"label\" [style]=\"{ width: '100%' }\" placeholder=\"Seleccionar orden\"> </p-select>\n </div>\n\n <!-- <p-multiselect [options]=\"availibleFilters\" [(ngModel)]=\"selectedFilters\" optionLabel=\"name\" placeholder=\"Filtros R\u00E1pidos\" [maxSelectedLabels]=\"3\" /> -->\n\n <!-- Date Filter -->\n <div class=\"field\">\n <label class=\"font-semibold block mb-2\">Rango de fechas</label>\n <p-datepicker\n [(ngModel)]=\"dateRange\"\n selectionMode=\"range\"\n [showButtonBar]=\"true\"\n [style]=\"{ width: '100%' }\"\n placeholder=\"Seleccionar fechas\"\n dateFormat=\"dd/mm/yy\">\n </p-datepicker>\n </div>\n\n @if (customFilters?.length > 0) {\n <form [formGroup]=\"customFiltersForm\">\n <h4>Filtros Personalizados</h4>\n @for (customFilter of customFilters; track customFilter.field) {\n <div class=\"field\">\n <label class=\"font-semibold block mb-2\">{{ customFilter.name }}</label>\n @switch (customFilter.type) { @case ('select') {\n <p-select\n [options]=\"customFilter.options\"\n [formControlName]=\"customFilter.field\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [style]=\"{ width: '100%' }\"\n placeholder=\"Seleccionar {{ customFilter.name }}\" />\n } @case ('string') {\n <input type=\"text\" pInputText [formControlName]=\"customFilter.field\" class=\"w-full\" />\n } @case ('date') {\n <p-datepicker [formControlName]=\"customFilter.field\" [style]=\"{ width: '100%' }\" dateFormat=\"dd/mm/yy\"></p-datepicker>\n } }\n </div>\n }\n </form>\n }\n </div>\n\n <!-- Action Buttons -->\n <div>\n <div class=\"flex justify-end gap-2\">\n <p-button label=\"Limpiar\" icon=\"pi pi-trash\" (click)=\"clearFilters()\" styleClass=\"p-button-text\"> </p-button>\n <p-button label=\"Aplicar\" icon=\"pi pi-check\" (click)=\"applyFilters()\" severity=\"primary\"> </p-button>\n </div>\n </div>\n</div>\n", styles: [":host ::ng-deep .filter-dialog-content{display:flex;flex-direction:column;gap:1.5rem;padding:1.5rem}\n"] }]
287
+ args: [{ selector: 'dc-list-filter-dialog', standalone: true, imports: [FormsModule, ReactiveFormsModule, ButtonModule, DialogModule, SelectModule, MultiSelectModule, DatePickerModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"filter-dialog-content flex flex-col justify-between h-full\">\n <!-- Filters Content -->\n <div>\n <!-- Sort Options -->\n <div class=\"field\">\n <label class=\"font-semibold block mb-2\">Ordenar por</label>\n <p-select [options]=\"sortOptions\" [(ngModel)]=\"selectedSort\" optionLabel=\"label\" [style]=\"{ width: '100%' }\" placeholder=\"Seleccionar orden\"> </p-select>\n </div>\n\n <!-- <p-multiselect [options]=\"availibleFilters\" [(ngModel)]=\"selectedFilters\" optionLabel=\"name\" placeholder=\"Filtros R\u00E1pidos\" [maxSelectedLabels]=\"3\" /> -->\n\n <!-- Date Filter -->\n <div class=\"field\">\n <label class=\"font-semibold block mb-2\">Rango de fechas</label>\n <p-datepicker\n [(ngModel)]=\"dateRange\"\n selectionMode=\"range\"\n [showButtonBar]=\"true\"\n [style]=\"{ width: '100%' }\"\n placeholder=\"Seleccionar fechas\"\n dateFormat=\"dd/mm/yy\">\n </p-datepicker>\n </div>\n\n @if (customFilters?.length > 0) {\n <form [formGroup]=\"customFiltersForm\">\n <h4>Filtros Personalizados</h4>\n @for (customFilter of customFilters; track customFilter.field) {\n <div class=\"field\">\n <label class=\"font-semibold block mb-2\">{{ customFilter.name }}</label>\n @switch (customFilter.type) { @case ('select') {\n <p-select\n [options]=\"customFilter.options\"\n [formControlName]=\"customFilter.field\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [showClear]=\"true\"\n [style]=\"{ width: '100%' }\"\n placeholder=\"Seleccionar {{ customFilter.name }}\" />\n } @case ('string') {\n <input type=\"text\" pInputText [formControlName]=\"customFilter.field\" class=\"w-full\" />\n } @case ('date') {\n <p-datepicker [formControlName]=\"customFilter.field\" [style]=\"{ width: '100%' }\" dateFormat=\"dd/mm/yy\"></p-datepicker>\n } }\n </div>\n }\n </form>\n }\n </div>\n\n <!-- Action Buttons -->\n <div>\n <div class=\"flex justify-end gap-2\">\n <p-button label=\"Limpiar\" icon=\"pi pi-trash\" (click)=\"clearFilters()\" styleClass=\"p-button-text\"> </p-button>\n <p-button label=\"Aplicar\" icon=\"pi pi-check\" (click)=\"applyFilters()\" severity=\"primary\"> </p-button>\n </div>\n </div>\n</div>\n", styles: [":host ::ng-deep .filter-dialog-content{display:flex;flex-direction:column;gap:1.5rem;padding:1.5rem}\n"] }]
288
288
  }], ctorParameters: () => [] });
289
289
 
290
290
  const DEFAULT_FILTERS = { filters: {}, page: 0, rowsPerPage: 10, sort: { _id: -1 } };
@@ -297,6 +297,7 @@ class DCFilterBarComponent {
297
297
  this.options = input({ showCreateButton: true }, ...(ngDevMode ? [{ debugName: "options" }] : []));
298
298
  // Inputs
299
299
  this.customFilters = [];
300
+ this.customSortOptions = [];
300
301
  this.isAdmin = false;
301
302
  this.persistenceKey = ''; // Key for saving/loading filters
302
303
  // Outputs
@@ -309,7 +310,7 @@ class DCFilterBarComponent {
309
310
  this.uiState = null; // Store UI state separately
310
311
  }
311
312
  ngOnInit() {
312
- // debugger;
313
+ //
313
314
  if (this.persistenceKey) {
314
315
  this.loadSavedFilters();
315
316
  }
@@ -336,7 +337,7 @@ class DCFilterBarComponent {
336
337
  search(text) {
337
338
  if (!text) {
338
339
  this.placeholder = '';
339
- this.clearFilters();
340
+ this.doItemAction({ action: 'search', item: null });
340
341
  }
341
342
  else {
342
343
  this.doItemAction({ action: 'search', item: text });
@@ -351,6 +352,7 @@ class DCFilterBarComponent {
351
352
  contentStyle: { 'max-height': '90vh', overflow: 'auto', 'min-height': '500px', height: '100%' },
352
353
  data: {
353
354
  customFilters: this.customFilters,
355
+ customSortOptions: this.customSortOptions,
354
356
  uiState: this.uiState, // Pass current UI state to dialog
355
357
  },
356
358
  closable: true,
@@ -370,25 +372,32 @@ class DCFilterBarComponent {
370
372
  }
371
373
  applyFilters(result) {
372
374
  // result.filters is now the Mongo Query
373
- const newFilters = { ...this.filter.filters, ...result.filters };
375
+ // We replace the filters entirely with the result from the dialog,
376
+ // instead of merging, to ensure removed filters are cleared.
377
+ const newFilters = { ...result.filters };
374
378
  let newSort = this.filter.sort;
375
379
  if (result.sort) {
376
- switch (result.sort.value) {
377
- case 'newest':
378
- newSort = { createdAt: -1 };
379
- break;
380
- case 'oldest':
381
- newSort = { createdAt: 1 };
382
- break;
383
- case 'alphabetical':
384
- newSort = { name: 1 };
385
- break;
386
- case 'reverseAlphabetical':
387
- newSort = { name: -1 };
388
- break;
389
- case 'lastUpdated':
390
- newSort = { updatedAt: -1 };
391
- break;
380
+ if (result.sort.mongoSort) {
381
+ newSort = result.sort.mongoSort;
382
+ }
383
+ else {
384
+ switch (result.sort.value) {
385
+ case 'newest':
386
+ newSort = { createdAt: -1 };
387
+ break;
388
+ case 'oldest':
389
+ newSort = { createdAt: 1 };
390
+ break;
391
+ case 'alphabetical':
392
+ newSort = { name: 1 };
393
+ break;
394
+ case 'reverseAlphabetical':
395
+ newSort = { name: -1 };
396
+ break;
397
+ case 'lastUpdated':
398
+ newSort = { updatedAt: -1 };
399
+ break;
400
+ }
392
401
  }
393
402
  }
394
403
  this.filter = { ...this.filter, filters: newFilters, sort: newSort };
@@ -413,13 +422,15 @@ class DCFilterBarComponent {
413
422
  this.onFilterAction.emit(filterEvent);
414
423
  }
415
424
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCFilterBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
416
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: DCFilterBarComponent, isStandalone: true, selector: "dc-filter-bar", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, customFilters: { classPropertyName: "customFilters", publicName: "customFilters", isSignal: false, isRequired: false, transformFunction: null }, isAdmin: { classPropertyName: "isAdmin", publicName: "isAdmin", isSignal: false, isRequired: false, transformFunction: null }, persistenceKey: { classPropertyName: "persistenceKey", publicName: "persistenceKey", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { onFilterAction: "onFilterAction", onNew: "onNew" }, providers: [DialogService], ngImport: i0, template: "<div class=\"background-bar\">\n <div class=\"button-flex\">\n <p-button icon=\"pi pi-search\" label=\"buscar\" severity=\"secondary\" (click)=\"isSearchVisible = true\" />\n\n @if (isAdmin) {\n <span class=\"admin\">\n <i style=\"position: absolute; right: -5px; top: -5px; z-index: 2; color: grey\" class=\"pi pi-key\"></i>\n <p-button icon=\"pi pi-plus\" label=\"Crear Nueva\" severity=\"secondary\" (click)=\"createNew()\" />\n </span>\n }\n </div>\n\n @if (isAdmin) {\n <p-button icon=\"pi pi-objects-column\" variant=\"text\" (click)=\"doItemAction({ action: 'changeView', item: null })\" severity=\"secondary\"></p-button>\n } @if(options()?.showActions){ @for(item of items(); track $index) {\n <p-button [icon]=\"item.icon\" variant=\"text\" (click)=\"doItemAction({ action: item.title, item: item })\" severity=\"secondary\"></p-button>\n } @if(isAdmin) {\n <div class=\"button-flex\">\n <p-button icon=\"pi pi-filter\" label=\"Filtrar\" severity=\"secondary\" (click)=\"openFilterDialog()\" />\n </div>\n } }\n</div>\n\n@if (placeholder) {\n<span class=\"search-flex\" (click)=\"search(null)\"> <i class=\"pi pi-times\"></i>{{ placeholder }} </span>\n}\n\n<p-dialog [(visible)]=\"isSearchVisible\" [dismissableMask]=\"true\" [modal]=\"true\" [showHeader]=\"false\" (onHide)=\"isSearchVisible = false\">\n <h4>Qu\u00E9 vamos a buscar? (Enter)</h4>\n <div>\n <p-inputgroup>\n <input (keydown.enter)=\"search(placeholder)\" type=\"text\" pInputText [(ngModel)]=\"placeholder\" />\n\n <p-button label=\"Buscar\" icon=\"pi pi-search\" (click)=\"search(placeholder)\" />\n </p-inputgroup>\n </div>\n</p-dialog>\n", styles: [":host{display:block}.admin{margin-left:10px;position:relative}.background-bar{background-color:var(--p-primary-color);display:flex;border-radius:10px;justify-content:space-between;padding:10px}.button-flex{display:flex;margin-right:10px}.white{color:#fff}.search-flex{margin-left:10px}.search-dialog{width:750px;-webkit-backdrop-filter:blur(70px);backdrop-filter:blur(70px)}.border-none{border:none}.bg-black-alpha-50{background-color:var(--p-primary-color)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.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: DialogModule }, { kind: "component", type: i3$1.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: InputGroupModule }, { kind: "component", type: i5.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["styleClass"] }, { kind: "ngmodule", type: InputGroupAddonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
425
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: DCFilterBarComponent, isStandalone: true, selector: "dc-filter-bar", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, customFilters: { classPropertyName: "customFilters", publicName: "customFilters", isSignal: false, isRequired: false, transformFunction: null }, customSortOptions: { classPropertyName: "customSortOptions", publicName: "customSortOptions", isSignal: false, isRequired: false, transformFunction: null }, isAdmin: { classPropertyName: "isAdmin", publicName: "isAdmin", isSignal: false, isRequired: false, transformFunction: null }, persistenceKey: { classPropertyName: "persistenceKey", publicName: "persistenceKey", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { onFilterAction: "onFilterAction", onNew: "onNew" }, providers: [DialogService], ngImport: i0, template: "<div class=\"background-bar\">\n <div class=\"button-flex\">\n <p-button icon=\"pi pi-search\" label=\"buscar\" severity=\"secondary\" (click)=\"isSearchVisible = true\" />\n\n @if (isAdmin) {\n <span class=\"admin\">\n <i style=\"position: absolute; right: -5px; top: -5px; z-index: 2; color: grey\" class=\"pi pi-key\"></i>\n <p-button icon=\"pi pi-plus\" label=\"Crear Nueva\" severity=\"secondary\" (click)=\"createNew()\" />\n </span>\n }\n </div>\n\n @if (isAdmin) {\n <p-button icon=\"pi pi-objects-column\" variant=\"text\" (click)=\"doItemAction({ action: 'changeView', item: null })\" severity=\"secondary\"></p-button>\n } @if(options()?.showActions){ @for(item of items(); track $index) {\n <p-button [icon]=\"item.icon\" variant=\"text\" (click)=\"doItemAction({ action: item.title, item: item })\" severity=\"secondary\"></p-button>\n }\n <div class=\"button-flex\">\n <p-button icon=\"pi pi-filter\" label=\"Filtrar\" severity=\"secondary\" (click)=\"openFilterDialog()\" />\n </div>\n }\n</div>\n\n@if (placeholder) {\n<span class=\"search-flex\" (click)=\"search(null)\"> <i class=\"pi pi-times\"></i>{{ placeholder }} </span>\n}\n\n<p-dialog [(visible)]=\"isSearchVisible\" [dismissableMask]=\"true\" [modal]=\"true\" [showHeader]=\"false\" (onHide)=\"isSearchVisible = false\">\n <h4>Qu\u00E9 vamos a buscar? (Enter)</h4>\n <div>\n <p-inputgroup>\n <input (keydown.enter)=\"search(placeholder)\" type=\"text\" pInputText [(ngModel)]=\"placeholder\" />\n\n <p-button label=\"Buscar\" icon=\"pi pi-search\" (click)=\"search(placeholder)\" />\n </p-inputgroup>\n </div>\n</p-dialog>\n", styles: [":host{display:block}.admin{margin-left:10px;position:relative}.background-bar{background-color:var(--p-primary-color);display:flex;border-radius:10px;justify-content:space-between;padding:10px}.button-flex{display:flex;margin-right:10px}.white{color:#fff}.search-flex{margin-left:10px}.search-dialog{width:750px;-webkit-backdrop-filter:blur(70px);backdrop-filter:blur(70px)}.border-none{border:none}.bg-black-alpha-50{background-color:var(--p-primary-color)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i2.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: DialogModule }, { kind: "component", type: i3$1.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: InputGroupModule }, { kind: "component", type: i5.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["styleClass"] }, { kind: "ngmodule", type: InputGroupAddonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
417
426
  }
418
427
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCFilterBarComponent, decorators: [{
419
428
  type: Component,
420
- args: [{ selector: 'dc-filter-bar', standalone: true, imports: [FormsModule, ButtonModule, DialogModule, InputTextModule, InputGroupModule, InputGroupAddonModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [DialogService], template: "<div class=\"background-bar\">\n <div class=\"button-flex\">\n <p-button icon=\"pi pi-search\" label=\"buscar\" severity=\"secondary\" (click)=\"isSearchVisible = true\" />\n\n @if (isAdmin) {\n <span class=\"admin\">\n <i style=\"position: absolute; right: -5px; top: -5px; z-index: 2; color: grey\" class=\"pi pi-key\"></i>\n <p-button icon=\"pi pi-plus\" label=\"Crear Nueva\" severity=\"secondary\" (click)=\"createNew()\" />\n </span>\n }\n </div>\n\n @if (isAdmin) {\n <p-button icon=\"pi pi-objects-column\" variant=\"text\" (click)=\"doItemAction({ action: 'changeView', item: null })\" severity=\"secondary\"></p-button>\n } @if(options()?.showActions){ @for(item of items(); track $index) {\n <p-button [icon]=\"item.icon\" variant=\"text\" (click)=\"doItemAction({ action: item.title, item: item })\" severity=\"secondary\"></p-button>\n } @if(isAdmin) {\n <div class=\"button-flex\">\n <p-button icon=\"pi pi-filter\" label=\"Filtrar\" severity=\"secondary\" (click)=\"openFilterDialog()\" />\n </div>\n } }\n</div>\n\n@if (placeholder) {\n<span class=\"search-flex\" (click)=\"search(null)\"> <i class=\"pi pi-times\"></i>{{ placeholder }} </span>\n}\n\n<p-dialog [(visible)]=\"isSearchVisible\" [dismissableMask]=\"true\" [modal]=\"true\" [showHeader]=\"false\" (onHide)=\"isSearchVisible = false\">\n <h4>Qu\u00E9 vamos a buscar? (Enter)</h4>\n <div>\n <p-inputgroup>\n <input (keydown.enter)=\"search(placeholder)\" type=\"text\" pInputText [(ngModel)]=\"placeholder\" />\n\n <p-button label=\"Buscar\" icon=\"pi pi-search\" (click)=\"search(placeholder)\" />\n </p-inputgroup>\n </div>\n</p-dialog>\n", styles: [":host{display:block}.admin{margin-left:10px;position:relative}.background-bar{background-color:var(--p-primary-color);display:flex;border-radius:10px;justify-content:space-between;padding:10px}.button-flex{display:flex;margin-right:10px}.white{color:#fff}.search-flex{margin-left:10px}.search-dialog{width:750px;-webkit-backdrop-filter:blur(70px);backdrop-filter:blur(70px)}.border-none{border:none}.bg-black-alpha-50{background-color:var(--p-primary-color)}\n"] }]
429
+ args: [{ selector: 'dc-filter-bar', standalone: true, imports: [FormsModule, ButtonModule, DialogModule, InputTextModule, InputGroupModule, InputGroupAddonModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [DialogService], template: "<div class=\"background-bar\">\n <div class=\"button-flex\">\n <p-button icon=\"pi pi-search\" label=\"buscar\" severity=\"secondary\" (click)=\"isSearchVisible = true\" />\n\n @if (isAdmin) {\n <span class=\"admin\">\n <i style=\"position: absolute; right: -5px; top: -5px; z-index: 2; color: grey\" class=\"pi pi-key\"></i>\n <p-button icon=\"pi pi-plus\" label=\"Crear Nueva\" severity=\"secondary\" (click)=\"createNew()\" />\n </span>\n }\n </div>\n\n @if (isAdmin) {\n <p-button icon=\"pi pi-objects-column\" variant=\"text\" (click)=\"doItemAction({ action: 'changeView', item: null })\" severity=\"secondary\"></p-button>\n } @if(options()?.showActions){ @for(item of items(); track $index) {\n <p-button [icon]=\"item.icon\" variant=\"text\" (click)=\"doItemAction({ action: item.title, item: item })\" severity=\"secondary\"></p-button>\n }\n <div class=\"button-flex\">\n <p-button icon=\"pi pi-filter\" label=\"Filtrar\" severity=\"secondary\" (click)=\"openFilterDialog()\" />\n </div>\n }\n</div>\n\n@if (placeholder) {\n<span class=\"search-flex\" (click)=\"search(null)\"> <i class=\"pi pi-times\"></i>{{ placeholder }} </span>\n}\n\n<p-dialog [(visible)]=\"isSearchVisible\" [dismissableMask]=\"true\" [modal]=\"true\" [showHeader]=\"false\" (onHide)=\"isSearchVisible = false\">\n <h4>Qu\u00E9 vamos a buscar? (Enter)</h4>\n <div>\n <p-inputgroup>\n <input (keydown.enter)=\"search(placeholder)\" type=\"text\" pInputText [(ngModel)]=\"placeholder\" />\n\n <p-button label=\"Buscar\" icon=\"pi pi-search\" (click)=\"search(placeholder)\" />\n </p-inputgroup>\n </div>\n</p-dialog>\n", styles: [":host{display:block}.admin{margin-left:10px;position:relative}.background-bar{background-color:var(--p-primary-color);display:flex;border-radius:10px;justify-content:space-between;padding:10px}.button-flex{display:flex;margin-right:10px}.white{color:#fff}.search-flex{margin-left:10px}.search-dialog{width:750px;-webkit-backdrop-filter:blur(70px);backdrop-filter:blur(70px)}.border-none{border:none}.bg-black-alpha-50{background-color:var(--p-primary-color)}\n"] }]
421
430
  }], propDecorators: { customFilters: [{
422
431
  type: Input
432
+ }], customSortOptions: [{
433
+ type: Input
423
434
  }], isAdmin: [{
424
435
  type: Input
425
436
  }], persistenceKey: [{
@@ -1343,7 +1354,6 @@ class EntityBaseListComponent extends PaginationBase {
1343
1354
  await this.loadData(); // Refresh list
1344
1355
  break;
1345
1356
  case 'search':
1346
- debugger;
1347
1357
  this.filterConfig.text = item;
1348
1358
  this.loadData();
1349
1359
  break;
@@ -1375,6 +1385,7 @@ class EntityBaseListV2Component extends PaginationBase {
1375
1385
  // Public properties for configuration
1376
1386
  this.filterBarOptions = { showActions: true, showCreateButton: true, showViewButton: true };
1377
1387
  this.columns = [];
1388
+ this.fixedQuery = {};
1378
1389
  // New State Management
1379
1390
  this.mongoState = {
1380
1391
  query: {},
@@ -1401,38 +1412,22 @@ class EntityBaseListV2Component extends PaginationBase {
1401
1412
  async loadData() {
1402
1413
  try {
1403
1414
  this.isLoading = true;
1404
- // Sync PaginationBase state to MongoState
1405
1415
  this.mongoState.options.limit = this.rows;
1406
1416
  this.mongoState.options.skip = this.first;
1407
- // If sort is updated in filterConfig (from PaginationBase), sync it?
1408
- // PaginationBase updates filterConfig.sort.
1409
- // We might need to override onPageChange to update mongoState directly or sync here.
1410
- // Actually, let's use the new operation method
1417
+ const effectiveQuery = { ...this.mongoState.query, ...this.fixedQuery };
1411
1418
  const response = await this.entityCommunicationService.operation({
1412
1419
  action: 'find',
1413
- query: this.mongoState.query,
1420
+ query: effectiveQuery,
1414
1421
  projection: this.mongoState.projection,
1415
1422
  options: this.mongoState.options,
1416
1423
  payload: this.mongoState.payload,
1417
1424
  });
1418
- // Assuming response structure matches what we need.
1419
- // If 'find' returns just array, we might need 'count' separately or use an aggregation that returns both.
1420
- // The user said: "Allows executing a variety of database operations through a single endpoint."
1421
- // Usually 'find' returns an array. Pagination requires count.
1422
- // Maybe we should use 'aggregate' to get both or make two calls.
1423
- // Or maybe the backend 'find' operation returns { rows, count }?
1424
- // The user example for 'updateOne' shows standard mongo stuff.
1425
- // Let's assume for now we might need to fetch count separately or the backend handles pagination metadata if requested.
1426
- // But typically 'find' returns a cursor/array.
1427
- // Let's check if we can get count.
1428
- // The user mentioned: "Bakcend single endpoint to handle everything in mongo."
1429
- // If I use 'find', I get items.
1430
- this.items.set(response); // If response is T[]
1425
+ this.items.set(response);
1431
1426
  // We need total records for pagination.
1432
1427
  // Use aggregate to count since 'count' action might not be explicitly supported or to be safe
1433
1428
  const countResult = await this.entityCommunicationService.operation({
1434
1429
  action: 'aggregate',
1435
- payload: [{ $match: this.mongoState.query }, { $count: 'total' }],
1430
+ payload: [{ $match: effectiveQuery }, { $count: 'total' }],
1436
1431
  });
1437
1432
  const count = countResult && countResult.length > 0 ? countResult[0].total : 0;
1438
1433
  this.totalRecordsSignal.set(count);
@@ -1463,18 +1458,19 @@ class EntityBaseListV2Component extends PaginationBase {
1463
1458
  }
1464
1459
  async doAction(actionEvent) {
1465
1460
  const { item, action } = actionEvent;
1466
- if (!item) {
1467
- return;
1468
- }
1469
1461
  const id = item?._id || item?.id;
1470
1462
  switch (action) {
1471
1463
  case 'view':
1472
- this.router.navigate(['./details', id], { relativeTo: this.route });
1464
+ if (id)
1465
+ this.router.navigate(['./details', id], { relativeTo: this.route });
1473
1466
  break;
1474
1467
  case 'edit':
1475
- this.router.navigate(['./edit', id], { relativeTo: this.route });
1468
+ if (id)
1469
+ this.router.navigate(['./edit', id], { relativeTo: this.route });
1476
1470
  break;
1477
1471
  case 'delete':
1472
+ if (!id)
1473
+ return;
1478
1474
  const confirmed = confirm(`Are you sure you want to delete this item?`);
1479
1475
  if (confirmed) {
1480
1476
  try {
@@ -1492,6 +1488,8 @@ class EntityBaseListV2Component extends PaginationBase {
1492
1488
  }
1493
1489
  break;
1494
1490
  case 'clone':
1491
+ if (!id)
1492
+ return;
1495
1493
  // Clone usually requires specific logic, maybe 'create' with modified data
1496
1494
  // Or if backend supports 'clone' action via operation?
1497
1495
  // The user listed: 'findOne', 'find', 'create', 'updateOne', 'updateMany', 'deleteOne', 'deleteMany', 'aggregate'.
@@ -1505,10 +1503,22 @@ class EntityBaseListV2Component extends PaginationBase {
1505
1503
  }
1506
1504
  break;
1507
1505
  case 'search':
1508
- // Search usually updates query
1509
- // This depends on how the filter bar sends events.
1510
- // If it sends a text, we might want to regex search on some fields.
1511
- // This logic might be better in the child component or configurable.
1506
+ if (item) {
1507
+ this.mongoState.query = { ...this.mongoState.query, $text: { $search: item } };
1508
+ }
1509
+ else {
1510
+ const { $text, ...rest } = this.mongoState.query;
1511
+ this.mongoState.query = rest;
1512
+ }
1513
+ this.first = 0;
1514
+ this.mongoState.options.skip = 0;
1515
+ await this.loadData();
1516
+ break;
1517
+ case 'changeView':
1518
+ this.toggleView();
1519
+ break;
1520
+ case 'filterChange':
1521
+ this.updateQueryFromFilter(item);
1512
1522
  break;
1513
1523
  default:
1514
1524
  // this.handleCustomAction(actionEvent);
@@ -1519,7 +1529,9 @@ class EntityBaseListV2Component extends PaginationBase {
1519
1529
  // Map filterConfig.filters to mongoState.query
1520
1530
  // The filter bar returns { filters: { ... }, sort: ... }
1521
1531
  if (filterConfig.filters) {
1522
- this.mongoState.query = { ...this.mongoState.query, ...filterConfig.filters };
1532
+ // Preserve $text search if it exists, as it is managed separately via 'search' action
1533
+ const textQuery = this.mongoState.query.$text ? { $text: this.mongoState.query.$text } : {};
1534
+ this.mongoState.query = { ...textQuery, ...filterConfig.filters };
1523
1535
  }
1524
1536
  if (filterConfig.sort) {
1525
1537
  this.mongoState.options.sort = filterConfig.sort;
@@ -2861,8 +2873,31 @@ const LANGUAGES = {
2861
2873
  },
2862
2874
  };
2863
2875
  function getLangDesc(langCode, lang = 'en') {
2864
- return LANGUAGES[langCode]?.translations[lang] || langCode;
2876
+ const languageData = LANGUAGES[langCode];
2877
+ if (languageData && languageData.translations) {
2878
+ return languageData.translations[lang] || languageData.nativeName;
2879
+ }
2880
+ return langCode;
2865
2881
  }
2882
+ /**
2883
+ * How to use this pipe
2884
+ * @example
2885
+ * // In your component ts file assuming you have a variable with the lang code
2886
+ *
2887
+ * \@Component({
2888
+ * selector: 'app-example',
2889
+ * template: `
2890
+ * <span>{{'en' | langDesc: 'es'}}</span>
2891
+ * `,
2892
+ * standalone: true,
2893
+ * imports: [LangDescTranslation]
2894
+ * })
2895
+ *
2896
+ *
2897
+ * class ExampleComponent {
2898
+ * }
2899
+ *
2900
+ */
2866
2901
  function getSupportedLanguageOptions(lang = 'es') {
2867
2902
  return SUPPORTED_LANGUAGES.map((langCode) => ({
2868
2903
  value: langCode,
@@ -2872,7 +2907,8 @@ function getSupportedLanguageOptions(lang = 'es') {
2872
2907
 
2873
2908
  class LangDescTranslation {
2874
2909
  transform(value, lang) {
2875
- return getLangDesc(value, lang);
2910
+ const validLang = lang === 'es' ? 'es' : 'en';
2911
+ return getLangDesc(value, validLang);
2876
2912
  }
2877
2913
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: LangDescTranslation, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
2878
2914
  static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.1.6", ngImport: i0, type: LangDescTranslation, isStandalone: true, name: "langDesc" }); }
@@ -3637,8 +3673,10 @@ class EntityCommunicationService {
3637
3673
  clone(id, overrides = {}) {
3638
3674
  return this.httpService.postHttp({ service: `api/${this.serviceName}/${id}/clone`, data: overrides });
3639
3675
  }
3676
+ getFixedQuery() {
3677
+ return {};
3678
+ }
3640
3679
  operation(params) {
3641
- debugger;
3642
3680
  return this.httpService.postHttp({ service: `api/${this.serviceName}/operation`, data: params, host: this.customHost });
3643
3681
  }
3644
3682
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: EntityCommunicationService, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable }); }