@dataclouder/ngx-core 0.1.44 → 0.1.46
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/dataclouder-ngx-core.mjs +439 -30
- package/fesm2022/dataclouder-ngx-core.mjs.map +1 -1
- package/index.d.ts +71 -6
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, Component, inject, ChangeDetectionStrategy, output, Input, HostListener, ChangeDetectorRef,
|
|
2
|
+
import { input, Component, Injectable, inject, ChangeDetectionStrategy, output, Input, HostListener, ChangeDetectorRef, Pipe, signal, effect, ViewChild, Directive, InjectionToken, computed, Optional, Inject } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/forms';
|
|
4
4
|
import { FormBuilder, FormsModule, ReactiveFormsModule, FormControl, ControlContainer, FormGroup, FormArray } from '@angular/forms';
|
|
5
5
|
import * as i2 from 'primeng/button';
|
|
@@ -8,15 +8,15 @@ import * as i3$1 from 'primeng/dialog';
|
|
|
8
8
|
import { DialogModule } from 'primeng/dialog';
|
|
9
9
|
import * as i4$1 from 'primeng/inputtext';
|
|
10
10
|
import { InputTextModule } from 'primeng/inputtext';
|
|
11
|
-
import * as i5
|
|
11
|
+
import * as i5 from 'primeng/inputgroup';
|
|
12
12
|
import { InputGroupModule } from 'primeng/inputgroup';
|
|
13
13
|
import { InputGroupAddonModule } from 'primeng/inputgroupaddon';
|
|
14
14
|
import { DynamicDialogRef, DynamicDialogConfig, DialogService } from 'primeng/dynamicdialog';
|
|
15
15
|
import * as i3 from 'primeng/select';
|
|
16
16
|
import { SelectModule } from 'primeng/select';
|
|
17
|
-
import * as
|
|
17
|
+
import * as i8 from 'primeng/multiselect';
|
|
18
18
|
import { MultiSelectModule } from 'primeng/multiselect';
|
|
19
|
-
import * as
|
|
19
|
+
import * as i4 from 'primeng/datepicker';
|
|
20
20
|
import { DatePickerModule } from 'primeng/datepicker';
|
|
21
21
|
import * as i2$1 from 'primeng/message';
|
|
22
22
|
import { MessageModule } from 'primeng/message';
|
|
@@ -89,6 +89,7 @@ const sortOptions = [
|
|
|
89
89
|
{ label: 'Más antiguo', value: OptionValue.Oldest },
|
|
90
90
|
{ label: 'A-Z', value: OptionValue.Alphabetical },
|
|
91
91
|
{ label: 'Z-A', value: OptionValue.ReverseAlphabetical },
|
|
92
|
+
{ label: 'Última actualización', value: 'lastUpdated' },
|
|
92
93
|
];
|
|
93
94
|
const sortTypes = [
|
|
94
95
|
{ name: 'Recientes', code: 'newest', sort: { createdDate: -1 } },
|
|
@@ -96,63 +97,208 @@ const sortTypes = [
|
|
|
96
97
|
{ name: 'Populares', code: 'popular', sort: { takenCount: -1 } },
|
|
97
98
|
];
|
|
98
99
|
|
|
100
|
+
class FilterService {
|
|
101
|
+
constructor() {
|
|
102
|
+
this.STORAGE_PREFIX = 'dc_filter_state_';
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Saves the UI state of the filters to localStorage.
|
|
106
|
+
* @param key Unique key for the component/list
|
|
107
|
+
* @param state The UI state object (form values)
|
|
108
|
+
*/
|
|
109
|
+
saveState(key, state) {
|
|
110
|
+
try {
|
|
111
|
+
localStorage.setItem(`${this.STORAGE_PREFIX}${key}`, JSON.stringify(state));
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
console.error('Error saving filter state', e);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Loads the UI state of the filters from localStorage.
|
|
119
|
+
* @param key Unique key for the component/list
|
|
120
|
+
* @returns The UI state object or null if not found
|
|
121
|
+
*/
|
|
122
|
+
loadState(key) {
|
|
123
|
+
try {
|
|
124
|
+
const item = localStorage.getItem(`${this.STORAGE_PREFIX}${key}`);
|
|
125
|
+
return item ? JSON.parse(item) : null;
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
console.error('Error loading filter state', e);
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Builds a MongoDB-compatible query object from the UI filter values and definitions.
|
|
134
|
+
* @param uiFilters The raw values from the form
|
|
135
|
+
* @param customFilters The definitions of the filters
|
|
136
|
+
* @returns A MongoDB query object
|
|
137
|
+
*/
|
|
138
|
+
buildQuery(uiFilters, customFilters) {
|
|
139
|
+
const query = {};
|
|
140
|
+
for (const filterDef of customFilters) {
|
|
141
|
+
const value = uiFilters[filterDef.field];
|
|
142
|
+
// Skip empty values
|
|
143
|
+
if (value === null || value === undefined || value === '' || (Array.isArray(value) && value.length === 0)) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
// Use defined operator or infer from type
|
|
147
|
+
const operator = filterDef.operator || this.inferOperator(filterDef.type);
|
|
148
|
+
switch (operator) {
|
|
149
|
+
case '$eq':
|
|
150
|
+
query[filterDef.field] = value;
|
|
151
|
+
break;
|
|
152
|
+
case '$ne':
|
|
153
|
+
query[filterDef.field] = { $ne: value };
|
|
154
|
+
break;
|
|
155
|
+
case '$regex':
|
|
156
|
+
query[filterDef.field] = { $regex: value, $options: 'i' };
|
|
157
|
+
break;
|
|
158
|
+
case '$in':
|
|
159
|
+
query[filterDef.field] = { $in: Array.isArray(value) ? value : [value] };
|
|
160
|
+
break;
|
|
161
|
+
case '$nin':
|
|
162
|
+
query[filterDef.field] = { $nin: Array.isArray(value) ? value : [value] };
|
|
163
|
+
break;
|
|
164
|
+
case '$gt':
|
|
165
|
+
query[filterDef.field] = { $gt: value };
|
|
166
|
+
break;
|
|
167
|
+
case '$gte':
|
|
168
|
+
query[filterDef.field] = { $gte: value };
|
|
169
|
+
break;
|
|
170
|
+
case '$lt':
|
|
171
|
+
query[filterDef.field] = { $lt: value };
|
|
172
|
+
break;
|
|
173
|
+
case '$lte':
|
|
174
|
+
query[filterDef.field] = { $lte: value };
|
|
175
|
+
break;
|
|
176
|
+
case 'range':
|
|
177
|
+
if (Array.isArray(value) && value.length === 2 && value[0] && value[1]) {
|
|
178
|
+
query[filterDef.field] = { $gte: value[0], $lte: value[1] };
|
|
179
|
+
}
|
|
180
|
+
break;
|
|
181
|
+
default:
|
|
182
|
+
// Default fallback
|
|
183
|
+
query[filterDef.field] = value;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return query;
|
|
187
|
+
}
|
|
188
|
+
inferOperator(type) {
|
|
189
|
+
switch (type) {
|
|
190
|
+
case 'string':
|
|
191
|
+
return '$regex';
|
|
192
|
+
case 'select':
|
|
193
|
+
case 'boolean':
|
|
194
|
+
case 'number':
|
|
195
|
+
return '$eq';
|
|
196
|
+
case 'multi-select':
|
|
197
|
+
return '$in';
|
|
198
|
+
case 'date':
|
|
199
|
+
return 'range'; // Assuming date picker returns a range usually, or exact match if single
|
|
200
|
+
default:
|
|
201
|
+
return '$eq';
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: FilterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
205
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: FilterService, providedIn: 'root' }); }
|
|
206
|
+
}
|
|
207
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: FilterService, decorators: [{
|
|
208
|
+
type: Injectable,
|
|
209
|
+
args: [{
|
|
210
|
+
providedIn: 'root',
|
|
211
|
+
}]
|
|
212
|
+
}] });
|
|
213
|
+
|
|
99
214
|
class DcListFilterDialogComponent {
|
|
100
215
|
constructor() {
|
|
101
216
|
this.fb = inject(FormBuilder);
|
|
217
|
+
this.filterService = inject(FilterService);
|
|
102
218
|
this.ref = inject(DynamicDialogRef);
|
|
103
219
|
this.config = inject(DynamicDialogConfig);
|
|
104
220
|
this.customFilters = this.config.data.customFilters || [];
|
|
221
|
+
this.initialUiState = this.config.data.uiState || {};
|
|
105
222
|
this.availibleFilters = availibleFilters;
|
|
106
223
|
this.sortOptions = sortOptions;
|
|
107
224
|
this.selectedFilters = [];
|
|
108
225
|
this.selectedSort = null;
|
|
109
226
|
this.dateRange = [];
|
|
110
227
|
this.buildCustomFiltersForm();
|
|
228
|
+
this.restoreState();
|
|
111
229
|
}
|
|
112
230
|
buildCustomFiltersForm() {
|
|
231
|
+
debugger;
|
|
113
232
|
const formControls = {};
|
|
114
233
|
for (const filter of this.customFilters) {
|
|
115
234
|
formControls[filter.field] = [filter.defaultValue || null];
|
|
116
235
|
}
|
|
117
236
|
this.customFiltersForm = this.fb.group(formControls);
|
|
118
237
|
}
|
|
238
|
+
restoreState() {
|
|
239
|
+
if (this.initialUiState) {
|
|
240
|
+
if (this.initialUiState.customFilters) {
|
|
241
|
+
this.customFiltersForm.patchValue(this.initialUiState.customFilters);
|
|
242
|
+
}
|
|
243
|
+
if (this.initialUiState.sort) {
|
|
244
|
+
this.selectedSort = this.initialUiState.sort;
|
|
245
|
+
}
|
|
246
|
+
if (this.initialUiState.dateRange) {
|
|
247
|
+
// Ensure dates are Date objects
|
|
248
|
+
this.dateRange = this.initialUiState.dateRange.map((d) => new Date(d));
|
|
249
|
+
}
|
|
250
|
+
if (this.initialUiState.quickFilters) {
|
|
251
|
+
this.selectedFilters = this.initialUiState.quickFilters;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
119
255
|
clearFilters() {
|
|
120
256
|
this.ref.close({ action: 'clear' });
|
|
121
257
|
}
|
|
122
258
|
applyFilters() {
|
|
123
259
|
const customFilterValues = this.customFiltersForm.value;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
260
|
+
// Build MongoDB Query
|
|
261
|
+
const mongoQuery = this.filterService.buildQuery(customFilterValues, this.customFilters);
|
|
262
|
+
// Add Date Range to Query
|
|
263
|
+
if (this.dateRange && this.dateRange.length === 2 && this.dateRange[0] && this.dateRange[1]) {
|
|
264
|
+
mongoQuery['createdAt'] = { $gte: this.dateRange[0], $lte: this.dateRange[1] };
|
|
265
|
+
}
|
|
266
|
+
// Capture UI State for persistence
|
|
267
|
+
const uiState = {
|
|
268
|
+
customFilters: customFilterValues,
|
|
269
|
+
sort: this.selectedSort,
|
|
270
|
+
dateRange: this.dateRange,
|
|
271
|
+
quickFilters: this.selectedFilters,
|
|
272
|
+
};
|
|
130
273
|
this.ref.close({
|
|
131
274
|
action: 'apply',
|
|
132
|
-
filters:
|
|
275
|
+
filters: mongoQuery, // The actual query for the backend
|
|
276
|
+
uiState: uiState, // The state to save for the UI
|
|
133
277
|
sort: this.selectedSort,
|
|
134
278
|
dateRange: this.dateRange,
|
|
135
279
|
quickFilters: this.selectedFilters,
|
|
136
280
|
});
|
|
137
281
|
}
|
|
138
282
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DcListFilterDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
139
|
-
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\"
|
|
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 }); }
|
|
140
284
|
}
|
|
141
285
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DcListFilterDialogComponent, decorators: [{
|
|
142
286
|
type: Component,
|
|
143
|
-
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\"
|
|
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"] }]
|
|
144
288
|
}], ctorParameters: () => [] });
|
|
145
289
|
|
|
146
290
|
const DEFAULT_FILTERS = { filters: {}, page: 0, rowsPerPage: 10, sort: { _id: -1 } };
|
|
147
291
|
class DCFilterBarComponent {
|
|
148
292
|
constructor() {
|
|
149
293
|
this.dialogService = inject(DialogService);
|
|
294
|
+
this.filterService = inject(FilterService);
|
|
150
295
|
// Signal Inputs
|
|
151
296
|
this.items = input([], ...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
152
297
|
this.options = input({ showCreateButton: true }, ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
153
298
|
// Inputs
|
|
154
299
|
this.customFilters = [];
|
|
155
300
|
this.isAdmin = false;
|
|
301
|
+
this.persistenceKey = ''; // Key for saving/loading filters
|
|
156
302
|
// Outputs
|
|
157
303
|
this.onFilterAction = output();
|
|
158
304
|
this.onNew = output();
|
|
@@ -160,6 +306,29 @@ class DCFilterBarComponent {
|
|
|
160
306
|
this.isSearchVisible = false;
|
|
161
307
|
this.placeholder = '';
|
|
162
308
|
this.filter = { ...DEFAULT_FILTERS };
|
|
309
|
+
this.uiState = null; // Store UI state separately
|
|
310
|
+
}
|
|
311
|
+
ngOnInit() {
|
|
312
|
+
// debugger;
|
|
313
|
+
if (this.persistenceKey) {
|
|
314
|
+
this.loadSavedFilters();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
loadSavedFilters() {
|
|
318
|
+
const savedState = this.filterService.loadState(this.persistenceKey);
|
|
319
|
+
if (savedState) {
|
|
320
|
+
this.uiState = savedState;
|
|
321
|
+
// Re-construct the query from the saved UI state
|
|
322
|
+
if (savedState.customFilters) {
|
|
323
|
+
const mongoQuery = this.filterService.buildQuery(savedState.customFilters, this.customFilters);
|
|
324
|
+
this.filter = { ...this.filter, filters: mongoQuery };
|
|
325
|
+
// Emit initial filter change so the list loads with these filters
|
|
326
|
+
// We use setTimeout to ensure the parent component is ready
|
|
327
|
+
setTimeout(() => {
|
|
328
|
+
this.doItemAction({ action: 'filterChange', item: this.filter });
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
}
|
|
163
332
|
}
|
|
164
333
|
createNew() {
|
|
165
334
|
this.onNew.emit('new');
|
|
@@ -180,7 +349,10 @@ class DCFilterBarComponent {
|
|
|
180
349
|
width: '70vw',
|
|
181
350
|
height: '70vh',
|
|
182
351
|
contentStyle: { 'max-height': '90vh', overflow: 'auto', 'min-height': '500px', height: '100%' },
|
|
183
|
-
data: {
|
|
352
|
+
data: {
|
|
353
|
+
customFilters: this.customFilters,
|
|
354
|
+
uiState: this.uiState, // Pass current UI state to dialog
|
|
355
|
+
},
|
|
184
356
|
closable: true,
|
|
185
357
|
modal: true,
|
|
186
358
|
maximizable: true,
|
|
@@ -197,20 +369,51 @@ class DCFilterBarComponent {
|
|
|
197
369
|
});
|
|
198
370
|
}
|
|
199
371
|
applyFilters(result) {
|
|
372
|
+
// result.filters is now the Mongo Query
|
|
200
373
|
const newFilters = { ...this.filter.filters, ...result.filters };
|
|
201
|
-
|
|
374
|
+
let newSort = this.filter.sort;
|
|
375
|
+
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;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
this.filter = { ...this.filter, filters: newFilters, sort: newSort };
|
|
395
|
+
// Update UI state
|
|
396
|
+
this.uiState = result.uiState;
|
|
397
|
+
// Save to persistence
|
|
398
|
+
if (this.persistenceKey && this.uiState) {
|
|
399
|
+
this.filterService.saveState(this.persistenceKey, this.uiState);
|
|
400
|
+
}
|
|
202
401
|
// Handle other filter types from result if necessary (sort, dateRange, etc.)
|
|
203
402
|
this.doItemAction({ action: 'filterChange', item: this.filter });
|
|
204
403
|
}
|
|
205
404
|
clearFilters() {
|
|
206
405
|
this.filter = { ...DEFAULT_FILTERS };
|
|
406
|
+
this.uiState = null;
|
|
407
|
+
if (this.persistenceKey) {
|
|
408
|
+
this.filterService.saveState(this.persistenceKey, null);
|
|
409
|
+
}
|
|
207
410
|
this.doItemAction({ action: 'filterChange', item: this.filter });
|
|
208
411
|
}
|
|
209
412
|
doItemAction(filterEvent) {
|
|
210
413
|
this.onFilterAction.emit(filterEvent);
|
|
211
414
|
}
|
|
212
415
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCFilterBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
213
|
-
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 } }, 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
|
|
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 }); }
|
|
214
417
|
}
|
|
215
418
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DCFilterBarComponent, decorators: [{
|
|
216
419
|
type: Component,
|
|
@@ -219,6 +422,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
|
|
|
219
422
|
type: Input
|
|
220
423
|
}], isAdmin: [{
|
|
221
424
|
type: Input
|
|
425
|
+
}], persistenceKey: [{
|
|
426
|
+
type: Input
|
|
222
427
|
}] } });
|
|
223
428
|
|
|
224
429
|
class ConfirmComponent {
|
|
@@ -696,7 +901,7 @@ class QuickTableComponent {
|
|
|
696
901
|
}
|
|
697
902
|
}
|
|
698
903
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: QuickTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
699
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: QuickTableComponent, isStandalone: true, selector: "app-quick-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, tableData: { classPropertyName: "tableData", publicName: "tableData", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onAction: "onAction" }, viewQueries: [{ propertyName: "tableRef", first: true, predicate: ["tableRef"], descendants: true }], ngImport: i0, template: "<p-table\n [tableStyle]=\"{ 'min-width': '20rem' }\"\n #tableRef\n [value]=\"_tableData()\"\n [columns]=\"_columns()\"\n [globalFilterFields]=\"globalFilterFields()\"\n [filters]=\"filters()\"\n (onFilter)=\"onFilterLocal($event)\">\n <ng-template pTemplate=\"caption\">\n <div class=\"flex justify-content-between align-items-center\">\n <h5 class=\"m-0\">Table Data</h5>\n <span class=\"p-input-icon-left\">\n <i class=\"pi pi-search\"></i>\n <input pInputText type=\"text\" (input)=\"onGlobalFilter($event)\" placeholder=\"Search keyword\" />\n </span>\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\" let-columns>\n <tr>\n @for (column of columns; track column) {\n <th [pSortableColumn]=\"column.field\">{{ column.header }} <p-sortIcon [field]=\"column.field\"></p-sortIcon></th>\n }\n </tr>\n <tr>\n @for (column of columns; track column) { @if(column.type === 'tags') {\n <th>\n <p-multiselect\n [options]=\"filters()?.[column.field]?.['options']\"\n placeholder=\"Selecciona\"\n (onChange)=\"filterOutsideTable('tags', column.field, $event.value)\"\n [style]=\"{ minWidth: '14rem' }\"\n [panelStyle]=\"{ minWidth: '16rem' }\">\n <ng-template let-option #item>\n <div class=\"flex items-center gap-2\">\n <span>{{ option }}</span>\n </div>\n </ng-template>\n </p-multiselect>\n </th>\n\n } @else if(column.type === 'select') {\n <th>\n <p-select\n [options]=\"filters()?.[column.field]?.['options']\"\n placeholder=\"Selecciona\"\n (onChange)=\"filterOutsideTable('select', column.field, $event.value)\"\n [style]=\"{ minWidth: '14rem' }\"\n [showClear]=\"true\"></p-select>\n </th>\n } @else if(column.type === 'boolean') {\n <th>\n <p-columnFilter [type]=\"'boolean'\" [field]=\"column.field\"></p-columnFilter>\n </th>\n } @else if(column.type === 'numeric') {\n <th>\n <!-- <p-columnFilter [type]=\"'numeric'\" [field]=\"column.field\"></p-columnFilter> -->\n </th>\n } @else {\n <th>\n <p-columnFilter [type]=\"getFilterType(column)\" [field]=\"column.field\" placeholder=\"Search\" [showMenu]=\"false\"></p-columnFilter>\n </th>\n } }\n </tr>\n </ng-template>\n <!-- @if(tableData()){ -->\n <ng-template pTemplate=\"body\" let-item let-columns=\"columns\">\n <tr>\n @for (column of columns; track column) {\n <td>\n @if(column.type === 'image'){\n <div class=\"image-container\">\n <img [src]=\"item | getPath: column\" alt=\"Image\" class=\"image\" />\n </div>\n } @else if(column.type === 'tags') {\n <div class=\"tags-container\">\n @for (tag of item[column.field]; track tag) {\n <p-tag [rounded]=\"true\" [value]=\"tag\"></p-tag>\n }\n </div>\n } @else if(column.type === 'actions') {\n <div style=\"display: flex; gap: 2px\">\n @for (actionBtn of _actions(); track actionBtn) {\n <p-button (click)=\"selectItem(item, actionBtn)\" [icon]=\"actionBtn.icon\" [severity]=\"actionBtn['severity']\" />\n }\n </div>\n } @else if(column.type === 'boolean') {\n <i\n class=\"pi\"\n [ngClass]=\"{\n 'text-green-500 pi-check-circle': column.reverse ? !(item | getPath: column) : (item | getPath: column),\n 'text-red-500 pi-times-circle': column.reverse ? (item | getPath: column) : !(item | getPath: column)\n }\"></i>\n } @else {\n <span>{{ item | getPath: column}} </span>\n }\n </td>\n }\n </tr>\n </ng-template>\n <!-- } -->\n</p-table>\n", styles: [":host{display:block;height:100%;overflow:auto}.generic-list-container{display:flex;flex-direction:column;height:100%}.generic-list-content{margin-top:10px;flex:1;overflow-y:auto;padding-bottom:10px}.card-source{margin-bottom:10px;position:relative}.paginator-container{margin-top:auto;padding-top:10px}.image-container{width:50px;height:50px;border-radius:50%;overflow:hidden;display:flex;justify-content:center;align-items:center}.image-container img{width:100%;height:100%;object-fit:cover}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: CardModule }, { kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { 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: SpeedDialModule }, { kind: "ngmodule", type: PaginatorModule }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i4$2.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i4$2.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i4$2.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i4$2.ColumnFilter, selector: "p-columnFilter, p-column-filter, p-columnfilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "filterOn", "useGrouping", "showButtons", "ariaLabel", "filterButtonProps"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i6.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { 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: "component", type: i4.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "pipe", type: GetPathPipe, name: "getPath" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
904
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: QuickTableComponent, isStandalone: true, selector: "app-quick-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, tableData: { classPropertyName: "tableData", publicName: "tableData", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onAction: "onAction" }, viewQueries: [{ propertyName: "tableRef", first: true, predicate: ["tableRef"], descendants: true }], ngImport: i0, template: "<p-table\n [tableStyle]=\"{ 'min-width': '20rem' }\"\n #tableRef\n [value]=\"_tableData()\"\n [columns]=\"_columns()\"\n [globalFilterFields]=\"globalFilterFields()\"\n [filters]=\"filters()\"\n (onFilter)=\"onFilterLocal($event)\">\n <ng-template pTemplate=\"caption\">\n <div class=\"flex justify-content-between align-items-center\">\n <h5 class=\"m-0\">Table Data</h5>\n <span class=\"p-input-icon-left\">\n <i class=\"pi pi-search\"></i>\n <input pInputText type=\"text\" (input)=\"onGlobalFilter($event)\" placeholder=\"Search keyword\" />\n </span>\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\" let-columns>\n <tr>\n @for (column of columns; track column) {\n <th [pSortableColumn]=\"column.field\">{{ column.header }} <p-sortIcon [field]=\"column.field\"></p-sortIcon></th>\n }\n </tr>\n <tr>\n @for (column of columns; track column) { @if(column.type === 'tags') {\n <th>\n <p-multiselect\n [options]=\"filters()?.[column.field]?.['options']\"\n placeholder=\"Selecciona\"\n (onChange)=\"filterOutsideTable('tags', column.field, $event.value)\"\n [style]=\"{ minWidth: '14rem' }\"\n [panelStyle]=\"{ minWidth: '16rem' }\">\n <ng-template let-option #item>\n <div class=\"flex items-center gap-2\">\n <span>{{ option }}</span>\n </div>\n </ng-template>\n </p-multiselect>\n </th>\n\n } @else if(column.type === 'select') {\n <th>\n <p-select\n [options]=\"filters()?.[column.field]?.['options']\"\n placeholder=\"Selecciona\"\n (onChange)=\"filterOutsideTable('select', column.field, $event.value)\"\n [style]=\"{ minWidth: '14rem' }\"\n [showClear]=\"true\"></p-select>\n </th>\n } @else if(column.type === 'boolean') {\n <th>\n <p-columnFilter [type]=\"'boolean'\" [field]=\"column.field\"></p-columnFilter>\n </th>\n } @else if(column.type === 'numeric') {\n <th>\n <!-- <p-columnFilter [type]=\"'numeric'\" [field]=\"column.field\"></p-columnFilter> -->\n </th>\n } @else {\n <th>\n <p-columnFilter [type]=\"getFilterType(column)\" [field]=\"column.field\" placeholder=\"Search\" [showMenu]=\"false\"></p-columnFilter>\n </th>\n } }\n </tr>\n </ng-template>\n <!-- @if(tableData()){ -->\n <ng-template pTemplate=\"body\" let-item let-columns=\"columns\">\n <tr>\n @for (column of columns; track column) {\n <td>\n @if(column.type === 'image'){\n <div class=\"image-container\">\n <img [src]=\"item | getPath: column\" alt=\"Image\" class=\"image\" />\n </div>\n } @else if(column.type === 'tags') {\n <div class=\"tags-container\">\n @for (tag of item[column.field]; track tag) {\n <p-tag [rounded]=\"true\" [value]=\"tag\"></p-tag>\n }\n </div>\n } @else if(column.type === 'actions') {\n <div style=\"display: flex; gap: 2px\">\n @for (actionBtn of _actions(); track actionBtn) {\n <p-button (click)=\"selectItem(item, actionBtn)\" [icon]=\"actionBtn.icon\" [severity]=\"actionBtn['severity']\" />\n }\n </div>\n } @else if(column.type === 'boolean') {\n <i\n class=\"pi\"\n [ngClass]=\"{\n 'text-green-500 pi-check-circle': column.reverse ? !(item | getPath: column) : (item | getPath: column),\n 'text-red-500 pi-times-circle': column.reverse ? (item | getPath: column) : !(item | getPath: column)\n }\"></i>\n } @else {\n <span>{{ item | getPath: column}} </span>\n }\n </td>\n }\n </tr>\n </ng-template>\n <!-- } -->\n</p-table>\n", styles: [":host{display:block;height:100%;overflow:auto}.generic-list-container{display:flex;flex-direction:column;height:100%}.generic-list-content{margin-top:10px;flex:1;overflow-y:auto;padding-bottom:10px}.card-source{margin-bottom:10px;position:relative}.paginator-container{margin-top:auto;padding-top:10px}.image-container{width:50px;height:50px;border-radius:50%;overflow:hidden;display:flex;justify-content:center;align-items:center}.image-container img{width:100%;height:100%;object-fit:cover}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: CardModule }, { kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { 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: SpeedDialModule }, { kind: "ngmodule", type: PaginatorModule }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i4$2.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i4$2.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i4$2.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i4$2.ColumnFilter, selector: "p-columnFilter, p-column-filter, p-columnfilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "filterOn", "useGrouping", "showButtons", "ariaLabel", "filterButtonProps"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i6.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { 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: "component", type: i8.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "pipe", type: GetPathPipe, name: "getPath" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
700
905
|
}
|
|
701
906
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: QuickTableComponent, decorators: [{
|
|
702
907
|
type: Component,
|
|
@@ -915,15 +1120,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
|
|
|
915
1120
|
}] });
|
|
916
1121
|
|
|
917
1122
|
class DcTagsFormComponent {
|
|
918
|
-
constructor(
|
|
919
|
-
this.
|
|
1123
|
+
constructor() {
|
|
1124
|
+
this.form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
|
|
920
1125
|
this.newTagControl = new FormControl('');
|
|
921
1126
|
}
|
|
922
|
-
ngOnInit() {
|
|
923
|
-
this.form = this.parentContainer.control;
|
|
924
|
-
}
|
|
925
1127
|
get arrayForm() {
|
|
926
|
-
return this.form.get('tags');
|
|
1128
|
+
return this.form().get('tags');
|
|
927
1129
|
}
|
|
928
1130
|
addTag() {
|
|
929
1131
|
const newTag = this.newTagControl.value?.trim();
|
|
@@ -935,8 +1137,8 @@ class DcTagsFormComponent {
|
|
|
935
1137
|
removeTag(index) {
|
|
936
1138
|
this.arrayForm.removeAt(index);
|
|
937
1139
|
}
|
|
938
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DcTagsFormComponent, deps: [
|
|
939
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: DcTagsFormComponent, isStandalone: true, selector: "dc-tags-form", ngImport: i0, template: "<div [formGroup]=\"form\">\n <div formArrayName=\"tags\">\n <div class=\"flex flex-wrap gap-2\">\n @for (tagControl of arrayForm.controls; track tagControl; let i = $index) {\n <p-chip [label]=\"tagControl.value\" [removable]=\"true\" (onRemove)=\"removeTag(i)\"></p-chip>\n }\n </div>\n </div>\n</div>\n\n<div class=\"flex mt-2\">\n <input pInputText type=\"text\" [formControl]=\"newTagControl\" placeholder=\"New tag\" (keydown.enter)=\"addTag(); $event.preventDefault()\" />\n <p-button label=\"Add Tag\" icon=\"pi pi-plus\" (click)=\"addTag()\" [disabled]=\"!newTagControl.value\"></p-button>\n</div>\n", styles: [".tag-field{display:flex;align-items:center;margin-bottom:.5rem}.tag-field input{margin-right:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { 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: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ChipModule }, { kind: "component", type: i3$3.Chip, selector: "p-chip", inputs: ["label", "icon", "image", "alt", "styleClass", "disabled", "removable", "removeIcon", "chipProps"], outputs: ["onRemove", "onImageError"] }], viewProviders: [
|
|
1140
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DcTagsFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1141
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.6", type: DcTagsFormComponent, isStandalone: true, selector: "dc-tags-form", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div [formGroup]=\"form()\">\n <div formArrayName=\"tags\">\n <div class=\"flex flex-wrap gap-2\">\n @for (tagControl of arrayForm.controls; track tagControl; let i = $index) {\n <p-chip [label]=\"tagControl.value\" [removable]=\"true\" (onRemove)=\"removeTag(i)\"></p-chip>\n }\n </div>\n </div>\n</div>\n\n<div class=\"flex mt-2\">\n <input pInputText type=\"text\" [formControl]=\"newTagControl\" placeholder=\"New tag\" (keydown.enter)=\"addTag(); $event.preventDefault()\" />\n <p-button label=\"Add Tag\" icon=\"pi pi-plus\" (click)=\"addTag()\" [disabled]=\"!newTagControl.value\"></p-button>\n</div>\n", styles: [".tag-field{display:flex;align-items:center;margin-bottom:.5rem}.tag-field input{margin-right:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { 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: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ChipModule }, { kind: "component", type: i3$3.Chip, selector: "p-chip", inputs: ["label", "icon", "image", "alt", "styleClass", "disabled", "removable", "removeIcon", "chipProps"], outputs: ["onRemove", "onImageError"] }], viewProviders: [
|
|
940
1142
|
{
|
|
941
1143
|
provide: ControlContainer,
|
|
942
1144
|
useFactory: () => inject(ControlContainer, { skipSelf: true }),
|
|
@@ -950,19 +1152,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
|
|
|
950
1152
|
provide: ControlContainer,
|
|
951
1153
|
useFactory: () => inject(ControlContainer, { skipSelf: true }),
|
|
952
1154
|
},
|
|
953
|
-
], template: "<div [formGroup]=\"form\">\n <div formArrayName=\"tags\">\n <div class=\"flex flex-wrap gap-2\">\n @for (tagControl of arrayForm.controls; track tagControl; let i = $index) {\n <p-chip [label]=\"tagControl.value\" [removable]=\"true\" (onRemove)=\"removeTag(i)\"></p-chip>\n }\n </div>\n </div>\n</div>\n\n<div class=\"flex mt-2\">\n <input pInputText type=\"text\" [formControl]=\"newTagControl\" placeholder=\"New tag\" (keydown.enter)=\"addTag(); $event.preventDefault()\" />\n <p-button label=\"Add Tag\" icon=\"pi pi-plus\" (click)=\"addTag()\" [disabled]=\"!newTagControl.value\"></p-button>\n</div>\n", styles: [".tag-field{display:flex;align-items:center;margin-bottom:.5rem}.tag-field input{margin-right:.5rem}\n"] }]
|
|
954
|
-
}]
|
|
1155
|
+
], template: "<div [formGroup]=\"form()\">\n <div formArrayName=\"tags\">\n <div class=\"flex flex-wrap gap-2\">\n @for (tagControl of arrayForm.controls; track tagControl; let i = $index) {\n <p-chip [label]=\"tagControl.value\" [removable]=\"true\" (onRemove)=\"removeTag(i)\"></p-chip>\n }\n </div>\n </div>\n</div>\n\n<div class=\"flex mt-2\">\n <input pInputText type=\"text\" [formControl]=\"newTagControl\" placeholder=\"New tag\" (keydown.enter)=\"addTag(); $event.preventDefault()\" />\n <p-button label=\"Add Tag\" icon=\"pi pi-plus\" (click)=\"addTag()\" [disabled]=\"!newTagControl.value\"></p-button>\n</div>\n", styles: [".tag-field{display:flex;align-items:center;margin-bottom:.5rem}.tag-field input{margin-right:.5rem}\n"] }]
|
|
1156
|
+
}] });
|
|
955
1157
|
|
|
956
1158
|
class DcLearnableFormComponent {
|
|
957
1159
|
constructor() {
|
|
958
1160
|
this.form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
|
|
959
1161
|
}
|
|
960
1162
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DcLearnableFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
961
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.1.6", type: DcLearnableFormComponent, isStandalone: true, selector: "dc-learnable-form", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div [formGroup]=\"form()\">\n <div class=\"form-grid\">\n <div class=\"row\">\n <div class=\"form-field\">\n <label for=\"level\">Level <span pTooltip=\"Difficulty level\">\u2139\uFE0F</span></label>\n <p-inputNumber id=\"level\" formControlName=\"level\" [min]=\"0\" [max]=\"10\"></p-inputNumber>\n </div>\n <div class=\"form-field\">\n <label for=\"takenCount\">Taken Count <span pTooltip=\"How many times this has been taken\">\u2139\uFE0F</span></label>\n <p-inputNumber id=\"takenCount\" formControlName=\"takenCount\" [min]=\"0\"></p-inputNumber>\n </div>\n </div>\n <div class=\"form-field\">\n <label for=\"tags\">Tags <span pTooltip=\"Relevant tags for this content\">\u2139\uFE0F</span></label>\n <dc-tags-form />\n </div>\n </div>\n</div>\n", styles: [".form-grid{display:grid;gap:1rem}.row{display:grid;grid-template-columns:repeat(2,1fr);gap:1rem}.form-field{display:flex;flex-direction:column}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { 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.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: CardModule }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i2$5.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "placeholder", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "autocomplete", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i4$3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "component", type: DcTagsFormComponent, selector: "dc-tags-form" }] }); }
|
|
1163
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.1.6", type: DcLearnableFormComponent, isStandalone: true, selector: "dc-learnable-form", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div [formGroup]=\"form()\">\n <div class=\"form-grid\">\n <div class=\"row\">\n <div class=\"form-field\">\n <label for=\"level\">Level <span pTooltip=\"Difficulty level\">\u2139\uFE0F</span></label>\n <p-inputNumber id=\"level\" formControlName=\"level\" [min]=\"0\" [max]=\"10\"></p-inputNumber>\n </div>\n <div class=\"form-field\">\n <label for=\"takenCount\">Taken Count <span pTooltip=\"How many times this has been taken\">\u2139\uFE0F</span></label>\n <p-inputNumber id=\"takenCount\" formControlName=\"takenCount\" [min]=\"0\"></p-inputNumber>\n </div>\n </div>\n <div class=\"form-field\">\n <label for=\"tags\">Tags <span pTooltip=\"Relevant tags for this content\">\u2139\uFE0F</span></label>\n <dc-tags-form [form]=\"form()\" />\n </div>\n </div>\n</div>\n", styles: [".form-grid{display:grid;gap:1rem}.row{display:grid;grid-template-columns:repeat(2,1fr);gap:1rem}.form-field{display:flex;flex-direction:column}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { 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.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: CardModule }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i2$5.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "placeholder", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "autocomplete", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i4$3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "component", type: DcTagsFormComponent, selector: "dc-tags-form", inputs: ["form"] }] }); }
|
|
962
1164
|
}
|
|
963
1165
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: DcLearnableFormComponent, decorators: [{
|
|
964
1166
|
type: Component,
|
|
965
|
-
args: [{ selector: 'dc-learnable-form', standalone: true, imports: [ReactiveFormsModule, CardModule, InputNumberModule, TooltipModule, DcTagsFormComponent], template: "<div [formGroup]=\"form()\">\n <div class=\"form-grid\">\n <div class=\"row\">\n <div class=\"form-field\">\n <label for=\"level\">Level <span pTooltip=\"Difficulty level\">\u2139\uFE0F</span></label>\n <p-inputNumber id=\"level\" formControlName=\"level\" [min]=\"0\" [max]=\"10\"></p-inputNumber>\n </div>\n <div class=\"form-field\">\n <label for=\"takenCount\">Taken Count <span pTooltip=\"How many times this has been taken\">\u2139\uFE0F</span></label>\n <p-inputNumber id=\"takenCount\" formControlName=\"takenCount\" [min]=\"0\"></p-inputNumber>\n </div>\n </div>\n <div class=\"form-field\">\n <label for=\"tags\">Tags <span pTooltip=\"Relevant tags for this content\">\u2139\uFE0F</span></label>\n <dc-tags-form />\n </div>\n </div>\n</div>\n", styles: [".form-grid{display:grid;gap:1rem}.row{display:grid;grid-template-columns:repeat(2,1fr);gap:1rem}.form-field{display:flex;flex-direction:column}\n"] }]
|
|
1167
|
+
args: [{ selector: 'dc-learnable-form', standalone: true, imports: [ReactiveFormsModule, CardModule, InputNumberModule, TooltipModule, DcTagsFormComponent], template: "<div [formGroup]=\"form()\">\n <div class=\"form-grid\">\n <div class=\"row\">\n <div class=\"form-field\">\n <label for=\"level\">Level <span pTooltip=\"Difficulty level\">\u2139\uFE0F</span></label>\n <p-inputNumber id=\"level\" formControlName=\"level\" [min]=\"0\" [max]=\"10\"></p-inputNumber>\n </div>\n <div class=\"form-field\">\n <label for=\"takenCount\">Taken Count <span pTooltip=\"How many times this has been taken\">\u2139\uFE0F</span></label>\n <p-inputNumber id=\"takenCount\" formControlName=\"takenCount\" [min]=\"0\"></p-inputNumber>\n </div>\n </div>\n <div class=\"form-field\">\n <label for=\"tags\">Tags <span pTooltip=\"Relevant tags for this content\">\u2139\uFE0F</span></label>\n <dc-tags-form [form]=\"form()\" />\n </div>\n </div>\n</div>\n", styles: [".form-grid{display:grid;gap:1rem}.row{display:grid;grid-template-columns:repeat(2,1fr);gap:1rem}.form-field{display:flex;flex-direction:column}\n"] }]
|
|
966
1168
|
}] });
|
|
967
1169
|
|
|
968
1170
|
/**
|
|
@@ -1140,6 +1342,11 @@ class EntityBaseListComponent extends PaginationBase {
|
|
|
1140
1342
|
await this.entityCommunicationService.clone(id);
|
|
1141
1343
|
await this.loadData(); // Refresh list
|
|
1142
1344
|
break;
|
|
1345
|
+
case 'search':
|
|
1346
|
+
debugger;
|
|
1347
|
+
this.filterConfig.text = item;
|
|
1348
|
+
this.loadData();
|
|
1349
|
+
break;
|
|
1143
1350
|
default:
|
|
1144
1351
|
// this.handleCustomAction(actionEvent);
|
|
1145
1352
|
}
|
|
@@ -1151,6 +1358,187 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImpor
|
|
|
1151
1358
|
type: Directive
|
|
1152
1359
|
}], ctorParameters: () => [] });
|
|
1153
1360
|
|
|
1361
|
+
class EntityBaseListV2Component extends PaginationBase {
|
|
1362
|
+
constructor() {
|
|
1363
|
+
super();
|
|
1364
|
+
// Services
|
|
1365
|
+
this.router = inject(Router);
|
|
1366
|
+
this.route = inject(ActivatedRoute);
|
|
1367
|
+
// Inputs & Outputs
|
|
1368
|
+
this.initialViewType = input('card', ...(ngDevMode ? [{ debugName: "initialViewType" }] : []));
|
|
1369
|
+
this.onlyView = input(false, ...(ngDevMode ? [{ debugName: "onlyView" }] : []));
|
|
1370
|
+
// Outputs
|
|
1371
|
+
this.onSelect = output();
|
|
1372
|
+
// Writable Signals for component state
|
|
1373
|
+
this.items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
1374
|
+
this.totalRecordsSignal = signal(0, ...(ngDevMode ? [{ debugName: "totalRecordsSignal" }] : []));
|
|
1375
|
+
// Public properties for configuration
|
|
1376
|
+
this.filterBarOptions = { showActions: true, showCreateButton: true, showViewButton: true };
|
|
1377
|
+
this.columns = [];
|
|
1378
|
+
// New State Management
|
|
1379
|
+
this.mongoState = {
|
|
1380
|
+
query: {},
|
|
1381
|
+
projection: {},
|
|
1382
|
+
options: {
|
|
1383
|
+
sort: { _id: -1 },
|
|
1384
|
+
limit: 10,
|
|
1385
|
+
skip: 0,
|
|
1386
|
+
},
|
|
1387
|
+
payload: {},
|
|
1388
|
+
};
|
|
1389
|
+
this.viewType = signal(this.initialViewType(), ...(ngDevMode ? [{ debugName: "viewType" }] : []));
|
|
1390
|
+
effect(() => {
|
|
1391
|
+
// Keep the parent's totalRecords in sync with our signal
|
|
1392
|
+
this.totalRecords = this.totalRecordsSignal();
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
async ngOnInit() {
|
|
1396
|
+
// Initialize mongoState from PaginationBase defaults if needed
|
|
1397
|
+
this.mongoState.options.limit = this.rows;
|
|
1398
|
+
this.mongoState.options.skip = this.first;
|
|
1399
|
+
await this.loadData();
|
|
1400
|
+
}
|
|
1401
|
+
async loadData() {
|
|
1402
|
+
try {
|
|
1403
|
+
this.isLoading = true;
|
|
1404
|
+
// Sync PaginationBase state to MongoState
|
|
1405
|
+
this.mongoState.options.limit = this.rows;
|
|
1406
|
+
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
|
|
1411
|
+
const response = await this.entityCommunicationService.operation({
|
|
1412
|
+
action: 'find',
|
|
1413
|
+
query: this.mongoState.query,
|
|
1414
|
+
projection: this.mongoState.projection,
|
|
1415
|
+
options: this.mongoState.options,
|
|
1416
|
+
payload: this.mongoState.payload,
|
|
1417
|
+
});
|
|
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[]
|
|
1431
|
+
// We need total records for pagination.
|
|
1432
|
+
// Use aggregate to count since 'count' action might not be explicitly supported or to be safe
|
|
1433
|
+
const countResult = await this.entityCommunicationService.operation({
|
|
1434
|
+
action: 'aggregate',
|
|
1435
|
+
payload: [{ $match: this.mongoState.query }, { $count: 'total' }],
|
|
1436
|
+
});
|
|
1437
|
+
const count = countResult && countResult.length > 0 ? countResult[0].total : 0;
|
|
1438
|
+
this.totalRecordsSignal.set(count);
|
|
1439
|
+
}
|
|
1440
|
+
catch (error) {
|
|
1441
|
+
console.error('Error loading data', error);
|
|
1442
|
+
}
|
|
1443
|
+
finally {
|
|
1444
|
+
this.isLoading = false;
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
// Override onPageChange to update mongoState
|
|
1448
|
+
async onPageChange(pageEvent) {
|
|
1449
|
+
this.rows = pageEvent.rows;
|
|
1450
|
+
this.first = pageEvent.page * this.rows;
|
|
1451
|
+
this.mongoState.options.limit = this.rows;
|
|
1452
|
+
this.mongoState.options.skip = this.first;
|
|
1453
|
+
await this.loadData();
|
|
1454
|
+
// We can still update URL param if we want, calling super or copying logic
|
|
1455
|
+
// super.updatePageParam(pageEvent.page + 1); // private in super
|
|
1456
|
+
// We'll leave URL update for now or implement if needed.
|
|
1457
|
+
}
|
|
1458
|
+
onNew() {
|
|
1459
|
+
this.router.navigate(['./edit'], { relativeTo: this.route });
|
|
1460
|
+
}
|
|
1461
|
+
toggleView() {
|
|
1462
|
+
this.viewType.update((v) => (v === 'card' ? 'table' : 'card'));
|
|
1463
|
+
}
|
|
1464
|
+
async doAction(actionEvent) {
|
|
1465
|
+
const { item, action } = actionEvent;
|
|
1466
|
+
if (!item) {
|
|
1467
|
+
return;
|
|
1468
|
+
}
|
|
1469
|
+
const id = item?._id || item?.id;
|
|
1470
|
+
switch (action) {
|
|
1471
|
+
case 'view':
|
|
1472
|
+
this.router.navigate(['./details', id], { relativeTo: this.route });
|
|
1473
|
+
break;
|
|
1474
|
+
case 'edit':
|
|
1475
|
+
this.router.navigate(['./edit', id], { relativeTo: this.route });
|
|
1476
|
+
break;
|
|
1477
|
+
case 'delete':
|
|
1478
|
+
const confirmed = confirm(`Are you sure you want to delete this item?`);
|
|
1479
|
+
if (confirmed) {
|
|
1480
|
+
try {
|
|
1481
|
+
await this.entityCommunicationService.operation({
|
|
1482
|
+
action: 'deleteOne',
|
|
1483
|
+
query: { _id: id },
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1486
|
+
catch (error) {
|
|
1487
|
+
console.error('Error deleting item', error);
|
|
1488
|
+
}
|
|
1489
|
+
finally {
|
|
1490
|
+
await this.loadData(); // Refresh list
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
break;
|
|
1494
|
+
case 'clone':
|
|
1495
|
+
// Clone usually requires specific logic, maybe 'create' with modified data
|
|
1496
|
+
// Or if backend supports 'clone' action via operation?
|
|
1497
|
+
// The user listed: 'findOne', 'find', 'create', 'updateOne', 'updateMany', 'deleteOne', 'deleteMany', 'aggregate'.
|
|
1498
|
+
// No 'clone'. So we might need to fetch, remove _id, and create.
|
|
1499
|
+
const original = await this.entityCommunicationService.operation({ action: 'findOne', query: { _id: id } });
|
|
1500
|
+
if (original) {
|
|
1501
|
+
const { _id, ...rest } = original;
|
|
1502
|
+
// Maybe add 'Copy' to name?
|
|
1503
|
+
await this.entityCommunicationService.operation({ action: 'create', payload: { ...rest, name: rest.name + ' (Copy)' } }); // Assumption on 'name'
|
|
1504
|
+
await this.loadData();
|
|
1505
|
+
}
|
|
1506
|
+
break;
|
|
1507
|
+
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.
|
|
1512
|
+
break;
|
|
1513
|
+
default:
|
|
1514
|
+
// this.handleCustomAction(actionEvent);
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
// Helper to update query from filter bar
|
|
1518
|
+
updateQueryFromFilter(filterConfig) {
|
|
1519
|
+
// Map filterConfig.filters to mongoState.query
|
|
1520
|
+
// The filter bar returns { filters: { ... }, sort: ... }
|
|
1521
|
+
if (filterConfig.filters) {
|
|
1522
|
+
this.mongoState.query = { ...this.mongoState.query, ...filterConfig.filters };
|
|
1523
|
+
}
|
|
1524
|
+
if (filterConfig.sort) {
|
|
1525
|
+
this.mongoState.options.sort = filterConfig.sort;
|
|
1526
|
+
}
|
|
1527
|
+
if (filterConfig.text) {
|
|
1528
|
+
// Handle text search if needed, or let child handle it
|
|
1529
|
+
}
|
|
1530
|
+
// Reset pagination on filter change
|
|
1531
|
+
this.first = 0;
|
|
1532
|
+
this.mongoState.options.skip = 0;
|
|
1533
|
+
this.loadData();
|
|
1534
|
+
}
|
|
1535
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: EntityBaseListV2Component, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1536
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.6", type: EntityBaseListV2Component, isStandalone: true, inputs: { initialViewType: { classPropertyName: "initialViewType", publicName: "initialViewType", isSignal: true, isRequired: false, transformFunction: null }, onlyView: { classPropertyName: "onlyView", publicName: "onlyView", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect" }, usesInheritance: true, ngImport: i0 }); }
|
|
1537
|
+
}
|
|
1538
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: EntityBaseListV2Component, decorators: [{
|
|
1539
|
+
type: Directive
|
|
1540
|
+
}], ctorParameters: () => [] });
|
|
1541
|
+
|
|
1154
1542
|
const TOAST_ALERTS_TOKEN = new InjectionToken('Toast alerts Service');
|
|
1155
1543
|
class ToastAlertsAbstractService {
|
|
1156
1544
|
}
|
|
@@ -1234,6 +1622,12 @@ class EntityBaseFormComponent {
|
|
|
1234
1622
|
this.patchForm(result);
|
|
1235
1623
|
return result;
|
|
1236
1624
|
}
|
|
1625
|
+
reload() {
|
|
1626
|
+
const id = this.entityId();
|
|
1627
|
+
if (id) {
|
|
1628
|
+
this.loadEntityById(id);
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1237
1631
|
getDirtyValues(form) {
|
|
1238
1632
|
const dirtyValues = {};
|
|
1239
1633
|
Object.keys(form.controls).forEach((key) => {
|
|
@@ -3243,6 +3637,10 @@ class EntityCommunicationService {
|
|
|
3243
3637
|
clone(id, overrides = {}) {
|
|
3244
3638
|
return this.httpService.postHttp({ service: `api/${this.serviceName}/${id}/clone`, data: overrides });
|
|
3245
3639
|
}
|
|
3640
|
+
operation(params) {
|
|
3641
|
+
debugger;
|
|
3642
|
+
return this.httpService.postHttp({ service: `api/${this.serviceName}/operation`, data: params, host: this.customHost });
|
|
3643
|
+
}
|
|
3246
3644
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: EntityCommunicationService, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3247
3645
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: EntityCommunicationService }); }
|
|
3248
3646
|
}
|
|
@@ -3289,6 +3687,17 @@ class FormUtilsService {
|
|
|
3289
3687
|
tags: this.fb.array([]),
|
|
3290
3688
|
});
|
|
3291
3689
|
}
|
|
3690
|
+
patchLearnableFormGroup(form, data) {
|
|
3691
|
+
if (data.tags) {
|
|
3692
|
+
this.patchFormArray(form.controls.tags, data.tags);
|
|
3693
|
+
}
|
|
3694
|
+
}
|
|
3695
|
+
patchFormArray(formArray, values) {
|
|
3696
|
+
formArray.clear();
|
|
3697
|
+
values.forEach((value) => {
|
|
3698
|
+
formArray.push(this.fb.control(value));
|
|
3699
|
+
});
|
|
3700
|
+
}
|
|
3292
3701
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: FormUtilsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3293
3702
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.6", ngImport: i0, type: FormUtilsService, providedIn: 'root' }); }
|
|
3294
3703
|
}
|
|
@@ -3504,5 +3913,5 @@ const CharacterEventActions = [
|
|
|
3504
3913
|
* Generated bundle index. Do not edit.
|
|
3505
3914
|
*/
|
|
3506
3915
|
|
|
3507
|
-
export { APP_CONFIG, AppConfigService, AudioNotificationService, AudioSpeed, AudioSpeedReverse, CharacterEventActions, ChatUserSettings, ConfirmComponent, ConfirmService, DCFilterBarComponent, DCProgressToastComponent, DcAuditableViewerComponent, DcExtensionsViewerComponent, DcLearnableFormComponent, DcLearnableViewerComponent, DcManageableFormComponent, DcManageableViewerComponent, DcReactionsViewerComponent, EModelQuality, EmptyStateComponent, EntityBaseFormComponent, EntityBaseListComponent, EntityCommunicationService, FlagPipe, FormUtilsService, GetPathPipe, HTTP_CORE_CONFIG, HttpCoreService, IAIModel, LANGUAGES, LangDescTranslation, LoadingBarComponent, LoadingBarService, MobileService, ModelQualityOptions, MoodState, MoodStateOptions, OptionValue, PaginationBase, PromptService, QuickTableComponent, SUPPORTED_LANGUAGES, TOAST_ALERTS_TOKEN, ToastAlertsAbstractService, UiStateService, availibleFilters, extractJsonFromString, formatCamelCaseString, getLangDesc, getSupportedLanguageOptions, provideToastAlert, sortOptions, sortTypes };
|
|
3916
|
+
export { APP_CONFIG, AppConfigService, AudioNotificationService, AudioSpeed, AudioSpeedReverse, CharacterEventActions, ChatUserSettings, ConfirmComponent, ConfirmService, DCFilterBarComponent, DCProgressToastComponent, DcAuditableViewerComponent, DcExtensionsViewerComponent, DcLearnableFormComponent, DcLearnableViewerComponent, DcManageableFormComponent, DcManageableViewerComponent, DcReactionsViewerComponent, DcTagsFormComponent, EModelQuality, EmptyStateComponent, EntityBaseFormComponent, EntityBaseListComponent, EntityBaseListV2Component, EntityCommunicationService, FlagPipe, FormUtilsService, GetPathPipe, HTTP_CORE_CONFIG, HttpCoreService, IAIModel, LANGUAGES, LangDescTranslation, LoadingBarComponent, LoadingBarService, MobileService, ModelQualityOptions, MoodState, MoodStateOptions, OptionValue, PaginationBase, PromptService, QuickTableComponent, SUPPORTED_LANGUAGES, TOAST_ALERTS_TOKEN, ToastAlertsAbstractService, UiStateService, availibleFilters, extractJsonFromString, formatCamelCaseString, getLangDesc, getSupportedLanguageOptions, provideToastAlert, sortOptions, sortTypes };
|
|
3508
3917
|
//# sourceMappingURL=dataclouder-ngx-core.mjs.map
|