tailjng 0.1.6 → 0.1.7
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/README.md +12 -4
- package/cli/execute/init-app.js +5 -2
- package/cli/execute/sync-app.js +14 -2
- package/cli/settings/colors-config-utils.js +43 -8
- package/cli/settings/icons-config-utils.js +62 -0
- package/cli/settings/path-utils.js +32 -2
- package/cli/settings/project-utils.js +7 -1
- package/cli/templates/app.generator.js +2 -2
- package/fesm2022/tailjng.mjs +247 -80
- package/fesm2022/tailjng.mjs.map +1 -1
- package/lib/services/static/theme.service.d.ts +39 -1
- package/lib/utils/theme/theme-variables.util.d.ts +31 -0
- package/package.json +1 -1
- package/public-api.d.ts +2 -1
- package/registry/components.json +41 -18
- package/src/colors.safelist.css +2 -2
- package/src/lib/components/.config/README.md +11 -0
- package/src/lib/components/.config/colors/README.md +38 -0
- package/src/lib/components/{colors-config → .config/colors}/colors.config.ts +5 -5
- package/src/lib/components/{colors-config → .config/colors}/colors.safelist.css +2 -2
- package/src/lib/components/.config/icons/README.md +26 -0
- package/src/lib/components/.config/icons/icons.lucide.ts +134 -0
- package/src/lib/components/.config/input/README.md +24 -0
- package/src/lib/components/.config/input/input.classes.ts +119 -0
- package/src/lib/components/alert/alert-dialog/dialog-alert.component.css +244 -2
- package/src/lib/components/alert/alert-dialog/dialog-alert.component.html +25 -38
- package/src/lib/components/alert/alert-dialog/dialog-alert.component.ts +66 -56
- package/src/lib/components/alert/alert-dialog/dialog-alert.types.ts +19 -0
- package/src/lib/components/alert/alert-toast/toast-alert.component.css +630 -12
- package/src/lib/components/alert/alert-toast/toast-alert.component.html +103 -102
- package/src/lib/components/alert/alert-toast/toast-alert.component.ts +485 -128
- package/src/lib/components/alert/alert-toast/toast-alert.types.ts +25 -0
- package/src/lib/components/badge/badge.component.html +34 -21
- package/src/lib/components/badge/badge.component.ts +140 -31
- package/src/lib/components/button/button.component.html +16 -10
- package/src/lib/components/button/button.component.ts +162 -22
- package/src/lib/components/card/card-complete/complete-card.component.html +2 -2
- package/src/lib/components/card/card-complete/complete-card.component.ts +26 -16
- package/src/lib/components/card/card-crud-complete/complete-crud-card.component.html +2 -2
- package/src/lib/components/card/card-crud-complete/complete-crud-card.component.ts +26 -16
- package/src/lib/components/checkbox/checkbox-input/input-checkbox.component.css +97 -0
- package/src/lib/components/checkbox/checkbox-input/input-checkbox.component.html +54 -46
- package/src/lib/components/checkbox/checkbox-input/input-checkbox.component.ts +135 -64
- package/src/lib/components/checkbox/checkbox-input/input-checkbox.types.ts +3 -0
- package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.css +112 -0
- package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.html +28 -25
- package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.ts +67 -15
- package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.types.ts +1 -0
- package/src/lib/components/coach-mark/coach-mark.component.html +4 -22
- package/src/lib/components/coach-mark/coach-mark.component.scss +1 -1
- package/src/lib/components/coach-mark/coach-mark.component.ts +51 -18
- package/src/lib/components/coach-mark/coach-mark.directive.ts +133 -78
- package/src/lib/components/coach-mark/coach-mark.types.ts +12 -0
- package/src/lib/components/dialog/dialog.component.css +103 -1
- package/src/lib/components/dialog/dialog.component.html +46 -66
- package/src/lib/components/dialog/dialog.component.ts +136 -110
- package/src/lib/components/dialog/dialog.types.ts +19 -0
- package/src/lib/components/filter/filter-complete/complete-filter.component.html +16 -19
- package/src/lib/components/filter/filter-complete/complete-filter.component.scss +35 -0
- package/src/lib/components/filter/filter-complete/complete-filter.component.ts +58 -34
- package/src/lib/components/filter/filter-complete/complete-filter.types.ts +7 -0
- package/src/lib/components/filter/filter-complete/complete-filter.util.ts +16 -0
- package/src/lib/components/form/form-container/container-form.component.css +4 -0
- package/src/lib/components/form/form-container/container-form.component.html +2 -2
- package/src/lib/components/form/form-container/container-form.component.ts +72 -16
- package/src/lib/components/form/form-container/container-form.types.ts +42 -0
- package/src/lib/components/form/form-container/form-col-span.directive.ts +25 -0
- package/src/lib/components/form/form-sidebar/sidebar-form.component.css +276 -0
- package/src/lib/components/form/form-sidebar/sidebar-form.component.html +117 -125
- package/src/lib/components/form/form-sidebar/sidebar-form.component.ts +109 -34
- package/src/lib/components/form/form-sidebar/sidebar-form.types.ts +3 -0
- package/src/lib/components/{toggle-radio/toggle-radio.component.css → form/form-validation/validation-form.component.css} +0 -1
- package/src/lib/components/form/form-validation/validation-form.component.html +10 -6
- package/src/lib/components/form/form-validation/validation-form.component.ts +99 -12
- package/src/lib/components/form/form-validation/validation-form.types.ts +33 -0
- package/src/lib/components/icon/icon.component.html +8 -5
- package/src/lib/components/icon/icon.component.ts +111 -9
- package/src/lib/components/input/input/input.component.html +19 -16
- package/src/lib/components/input/input/input.component.ts +130 -53
- package/src/lib/components/input/input/input.types.ts +8 -0
- package/src/lib/components/input/input-file/file-input.component.html +65 -56
- package/src/lib/components/input/input-file/file-input.component.ts +276 -173
- package/src/lib/components/input/input-file/file-input.types.ts +2 -0
- package/src/lib/components/input/input-range/range-input.component.css +67 -0
- package/src/lib/components/input/input-range/range-input.component.html +50 -58
- package/src/lib/components/input/input-range/range-input.component.ts +148 -60
- package/src/lib/components/input/input-range/range-input.types.ts +7 -0
- package/src/lib/components/input/input-textarea/textarea-input.component.html +16 -7
- package/src/lib/components/input/input-textarea/textarea-input.component.ts +140 -50
- package/src/lib/components/input/input-textarea/textarea-input.types.ts +2 -0
- package/src/lib/components/label/label.component.html +17 -16
- package/src/lib/components/label/label.component.ts +70 -16
- package/src/lib/components/label/label.types.ts +2 -0
- package/src/lib/components/menu/menu-options-table/menu-options-defaults.ts +34 -0
- package/src/lib/components/menu/menu-options-table/options-table-menu.component.html +34 -20
- package/src/lib/components/menu/menu-options-table/options-table-menu.component.ts +211 -58
- package/src/lib/components/menu/menu-options-table/options-table-menu.types.ts +38 -0
- package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.html +49 -52
- package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.ts +112 -24
- package/src/lib/components/menu/options-coach-menu/options-coach-menu.types.ts +9 -0
- package/src/lib/components/mode-toggle/mode-toggle.component.html +11 -16
- package/src/lib/components/mode-toggle/mode-toggle.component.ts +69 -33
- package/src/lib/components/paginator/paginator-complete/complete-paginator.component.html +4 -4
- package/src/lib/components/paginator/paginator-complete/complete-paginator.component.ts +31 -7
- package/src/lib/components/paginator/paginator-complete/complete-paginator.types.ts +12 -0
- package/src/lib/components/paginator/paginator-complete/complete-paginator.util.ts +36 -0
- package/src/lib/components/progress-bar/progress-bar.component.css +11 -0
- package/src/lib/components/progress-bar/progress-bar.component.html +41 -40
- package/src/lib/components/progress-bar/progress-bar.component.ts +95 -11
- package/src/lib/components/progress-bar/progress-bar.types.ts +2 -0
- package/src/lib/components/select/select-dropdown/dropdown-select.component.css +6 -0
- package/src/lib/components/select/select-dropdown/dropdown-select.component.html +54 -44
- package/src/lib/components/select/select-dropdown/dropdown-select.component.ts +450 -509
- package/src/lib/components/select/select-dropdown/dropdown-select.types.ts +43 -0
- package/src/lib/components/select/select-dropdown/dropdown-select.util.ts +179 -0
- package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.css +6 -0
- package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.html +131 -42
- package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.ts +491 -475
- package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.types.ts +22 -0
- package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.util.ts +20 -0
- package/src/lib/components/select/select-multi-table/multi-table-select.component.css +10 -0
- package/src/lib/components/select/select-multi-table/multi-table-select.component.html +76 -60
- package/src/lib/components/select/select-multi-table/multi-table-select.component.ts +250 -313
- package/src/lib/components/select/select-multi-table/multi-table-select.types.ts +10 -0
- package/src/lib/components/select/select-multi-table/multi-table-select.util.ts +5 -0
- package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.css +212 -0
- package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.html +62 -53
- package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.ts +84 -27
- package/src/lib/components/sidebar/sidebar-static/static-sidebar.types.ts +2 -0
- package/src/lib/components/table/table-complete/complete-table.component.html +15 -17
- package/src/lib/components/table/table-complete/complete-table.component.ts +190 -338
- package/src/lib/components/table/table-complete/complete-table.types.ts +28 -0
- package/src/lib/components/table/table-complete/complete-table.util.ts +236 -0
- package/src/lib/components/table/table-complete/index.ts +2 -0
- package/src/lib/components/table/table-crud-complete/complete-crud-table.animations.ts +34 -0
- package/src/lib/components/table/table-crud-complete/complete-crud-table.component.html +73 -128
- package/src/lib/components/table/table-crud-complete/complete-crud-table.component.ts +542 -829
- package/src/lib/components/table/table-crud-complete/complete-crud-table.types.ts +57 -0
- package/src/lib/components/table/table-crud-complete/complete-crud-table.util.ts +723 -0
- package/src/lib/components/table/table-crud-complete/index.ts +3 -0
- package/src/lib/components/theme-generator/theme-generator.component.css +21 -0
- package/src/lib/components/theme-generator/theme-generator.component.html +146 -116
- package/src/lib/components/theme-generator/theme-generator.component.ts +44 -24
- package/src/lib/components/toggle-radio/shared/toggle-options.types.ts +8 -0
- package/src/lib/components/toggle-radio/shared/toggle-options.util.ts +44 -0
- package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.css +135 -0
- package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.html +52 -0
- package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.ts +198 -0
- package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.types.ts +1 -0
- package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.css +108 -0
- package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.html +37 -0
- package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.ts +193 -0
- package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.types.ts +1 -0
- package/src/lib/components/tooltip/tooltip.directive.ts +12 -9
- package/src/lib/components/tooltip/tooltip.service.ts +331 -133
- package/src/lib/components/tooltip/tooltip.types.ts +9 -0
- package/src/lib/components/viewer/viewer-image/image-viewer.component.css +90 -4
- package/src/lib/components/viewer/viewer-image/image-viewer.component.html +52 -103
- package/src/lib/components/viewer/viewer-image/image-viewer.component.ts +182 -177
- package/src/lib/components/viewer/viewer-image/image-viewer.types.ts +3 -0
- package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.css +177 -0
- package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.html +74 -24
- package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.ts +168 -15
- package/src/lib/components/viewer/viewer-pdf/pdf-viewer.types.ts +1 -0
- package/src/styles.css +2 -2
- package/lib/services/static/icons.service.d.ts +0 -65
- package/src/lib/components/colors-config/README.md +0 -38
- package/src/lib/components/form/form-sidebar/sidebar-form.component.scss +0 -0
- package/src/lib/components/form/form-validation/validation-form.component.scss +0 -0
- package/src/lib/components/menu/menu-options-table/options-table-menu.component.scss +0 -0
- package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.scss +0 -12
- package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.scss +0 -0
- package/src/lib/components/toggle-radio/toggle-radio.component.html +0 -51
- package/src/lib/components/toggle-radio/toggle-radio.component.ts +0 -222
- package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.scss +0 -0
- package/tailjng-0.1.6.tgz +0 -0
|
@@ -1,172 +1,209 @@
|
|
|
1
|
-
// TODO: BETA - IN DEVELOPMENT
|
|
2
1
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
|
3
2
|
import { CommonModule } from '@angular/common';
|
|
4
3
|
import { FormsModule } from '@angular/forms';
|
|
5
|
-
import {
|
|
6
|
-
|
|
4
|
+
import {
|
|
5
|
+
JAlertDialogService,
|
|
6
|
+
JAlertToastService,
|
|
7
|
+
JConverterCrudService,
|
|
8
|
+
JGenericCrudService,
|
|
9
|
+
JTransformService,
|
|
10
|
+
TableColumn} from 'tailjng';
|
|
7
11
|
import { JButtonComponent } from '../../button/button.component';
|
|
8
12
|
import { JInputCheckboxComponent } from '../../checkbox/checkbox-input/input-checkbox.component';
|
|
9
13
|
import { JInputComponent } from '../../input/input/input.component';
|
|
10
14
|
import { JDropdownSelectComponent } from '../../select/select-dropdown/dropdown-select.component';
|
|
11
|
-
|
|
15
|
+
import type {
|
|
16
|
+
CompleteTableEquivalenceConfigs,
|
|
17
|
+
CompleteTableEquivalenceMaps,
|
|
18
|
+
CompleteTableSortDirection} from './complete-table.types';
|
|
19
|
+
import {
|
|
20
|
+
applyColumnDefaults,
|
|
21
|
+
filterDisplayDataBySearch,
|
|
22
|
+
findRowIndexByJsonSnapshot,
|
|
23
|
+
flattenObject,
|
|
24
|
+
formatCellDisplayValue,
|
|
25
|
+
getStaticTableEquivalenceData,
|
|
26
|
+
hasEquivalenceConfig,
|
|
27
|
+
isBooleanValue,
|
|
28
|
+
isDateValue,
|
|
29
|
+
parseCellEditValue,
|
|
30
|
+
rebuildObject,
|
|
31
|
+
resolveStaticTableSortState,
|
|
32
|
+
setNestedValue as assignNestedValue,
|
|
33
|
+
sortDisplayDataInPlace,
|
|
34
|
+
toggleNestedBooleanOnItem} from './complete-table.util';
|
|
35
|
+
import { Icons } from '../../.config/icons/icons.lucide';
|
|
36
|
+
import { JIconComponent } from '../../icon/icon.component';
|
|
37
|
+
|
|
38
|
+
export type {
|
|
39
|
+
CompleteTableEquivalenceConfig,
|
|
40
|
+
CompleteTableEquivalenceConfigs,
|
|
41
|
+
CompleteTableEquivalenceData,
|
|
42
|
+
CompleteTableEquivalenceMaps,
|
|
43
|
+
CompleteTableEquivalenceOption,
|
|
44
|
+
CompleteTableGetCellValueFn,
|
|
45
|
+
CompleteTableSortDirection} from './complete-table.types';
|
|
46
|
+
export {
|
|
47
|
+
applyColumnDefaults,
|
|
48
|
+
filterDisplayDataBySearch,
|
|
49
|
+
findRowIndexByJsonSnapshot,
|
|
50
|
+
flattenObject,
|
|
51
|
+
formatCellDisplayValue,
|
|
52
|
+
getStaticTableEquivalenceData,
|
|
53
|
+
hasEquivalenceConfig,
|
|
54
|
+
isBooleanValue,
|
|
55
|
+
isDateValue,
|
|
56
|
+
parseCellEditValue,
|
|
57
|
+
rebuildObject,
|
|
58
|
+
resolveStaticTableSortState,
|
|
59
|
+
setNestedValue,
|
|
60
|
+
sortDisplayDataInPlace,
|
|
61
|
+
toggleNestedBooleanOnItem} from './complete-table.util';
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Static-data table for bulk entry dialogs (search, sort, inline edit, save many).
|
|
65
|
+
*
|
|
66
|
+
* Install: `npx tailjng add table-complete`
|
|
67
|
+
*
|
|
68
|
+
* Logic lives in `complete-table.util.ts`; shared cell helpers reuse `table-crud-complete` utils.
|
|
69
|
+
*/
|
|
12
70
|
@Component({
|
|
13
71
|
selector: 'JCompleteTable',
|
|
14
72
|
standalone: true,
|
|
15
|
-
imports: [
|
|
73
|
+
imports: [
|
|
74
|
+
CommonModule,
|
|
75
|
+
FormsModule,
|
|
76
|
+
JIconComponent,
|
|
77
|
+
JButtonComponent,
|
|
78
|
+
JInputCheckboxComponent,
|
|
79
|
+
JInputComponent,
|
|
80
|
+
JDropdownSelectComponent,
|
|
81
|
+
],
|
|
16
82
|
templateUrl: './complete-table.component.html',
|
|
17
83
|
styleUrl: './complete-table.component.scss',
|
|
18
84
|
})
|
|
19
85
|
export class JCompleteTableComponent implements OnInit {
|
|
86
|
+
readonly Icons = Icons;
|
|
20
87
|
|
|
21
88
|
Math = Math;
|
|
22
89
|
|
|
90
|
+
// =====================================================
|
|
91
|
+
// Inputs / outputs
|
|
92
|
+
// =====================================================
|
|
93
|
+
|
|
23
94
|
@Input() endpoint!: string;
|
|
24
95
|
@Input() mainEndpoint!: string;
|
|
25
|
-
@Output() closeDialog
|
|
96
|
+
@Output() closeDialog = new EventEmitter<void>();
|
|
26
97
|
|
|
27
98
|
@Input() staticData: any[] = [];
|
|
28
99
|
@Input() columns: TableColumn<any>[] = [];
|
|
29
100
|
|
|
30
|
-
|
|
101
|
+
@Input() isOptions = true;
|
|
31
102
|
|
|
32
|
-
|
|
33
|
-
@Input()
|
|
103
|
+
@Input() equivalenceConfigs: CompleteTableEquivalenceConfigs = {};
|
|
104
|
+
@Input() equivalences: CompleteTableEquivalenceMaps = {};
|
|
34
105
|
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
106
|
+
// =====================================================
|
|
107
|
+
// State
|
|
108
|
+
// =====================================================
|
|
109
|
+
|
|
110
|
+
displayData: any[] = [];
|
|
111
|
+
|
|
112
|
+
searchQuery = '';
|
|
113
|
+
searchPlaceholder = 'Buscar...';
|
|
114
|
+
isLoadingSearch = false;
|
|
39
115
|
|
|
40
|
-
// Ordenamiento
|
|
41
116
|
sortColumn: string | null = null;
|
|
42
|
-
sortDirection:
|
|
117
|
+
sortDirection: CompleteTableSortDirection = 'none';
|
|
43
118
|
sortingColumn: string | null = null;
|
|
44
|
-
isLoadingSort
|
|
119
|
+
isLoadingSort = false;
|
|
45
120
|
|
|
46
|
-
// Edicion
|
|
47
121
|
editingRowIndex: number | null = null;
|
|
48
|
-
|
|
49
|
-
@Input() equivalences: any = {};
|
|
122
|
+
editingRowItem: any = null;
|
|
50
123
|
|
|
51
124
|
constructor(
|
|
52
|
-
public readonly iconsService: JIconsService,
|
|
53
125
|
public readonly transformService: JTransformService,
|
|
54
126
|
private readonly converterService: JConverterCrudService,
|
|
55
127
|
private readonly alertDialogService: JAlertDialogService,
|
|
56
128
|
private readonly alertToastService: JAlertToastService,
|
|
57
129
|
private readonly genericService: JGenericCrudService,
|
|
58
|
-
) {
|
|
59
|
-
|
|
130
|
+
) {}
|
|
60
131
|
|
|
61
132
|
ngOnInit(): void {
|
|
62
|
-
this.displayData = this.staticData.map(item => this.rebuildObject(item)) ?? [];
|
|
63
|
-
|
|
133
|
+
this.displayData = this.staticData.map((item) => this.rebuildObject(item)) ?? [];
|
|
64
134
|
this.columnDefaults();
|
|
65
135
|
}
|
|
66
136
|
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (column.sortable === undefined) {
|
|
75
|
-
column.sortable = true;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (column.isSearchable === undefined) {
|
|
79
|
-
column.isSearchable = true;
|
|
80
|
-
}
|
|
81
|
-
});
|
|
137
|
+
// =====================================================
|
|
138
|
+
// Columns / cell values
|
|
139
|
+
// =====================================================
|
|
140
|
+
|
|
141
|
+
columnDefaults(): void {
|
|
142
|
+
applyColumnDefaults(this.columns);
|
|
82
143
|
}
|
|
83
144
|
|
|
84
|
-
// Método para obtener el valor de las celdas dinámicamente
|
|
85
145
|
getValue(item: any, column: TableColumn<any>, raw = false): any {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
// Si existe un valueGetter, se usa directamente
|
|
89
|
-
if (typeof column.valueGetter === 'function') {
|
|
90
|
-
value = column.valueGetter(item);
|
|
91
|
-
} else {
|
|
92
|
-
// Si no, se busca el valor por key (con soporte para claves anidadas)
|
|
93
|
-
const keys = column.key.split('.');
|
|
94
|
-
value = item;
|
|
95
|
-
|
|
96
|
-
for (const key of keys) {
|
|
97
|
-
if (value != null) {
|
|
98
|
-
value = value[key];
|
|
99
|
-
} else {
|
|
100
|
-
value = null;
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
146
|
+
if (raw) {
|
|
147
|
+
return parseCellEditValue(item, column, this.converterService);
|
|
104
148
|
}
|
|
105
149
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return this.converterService.parseData(value, column);
|
|
109
|
-
} else {
|
|
150
|
+
return formatCellDisplayValue(item, column, this.converterService);
|
|
151
|
+
}
|
|
110
152
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
153
|
+
isBoolean(value: any): boolean {
|
|
154
|
+
return isBooleanValue(value);
|
|
155
|
+
}
|
|
115
156
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return formatted ?? value;
|
|
119
|
-
}
|
|
157
|
+
isDate(value: any): boolean {
|
|
158
|
+
return isDateValue(value);
|
|
120
159
|
}
|
|
121
160
|
|
|
161
|
+
flattenObject(obj: any, prefix = ''): any {
|
|
162
|
+
return flattenObject(obj, prefix);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
rebuildObject(flatObj: any): any {
|
|
166
|
+
return rebuildObject(flatObj);
|
|
167
|
+
}
|
|
122
168
|
|
|
123
169
|
// =====================================================
|
|
124
|
-
//
|
|
170
|
+
// Save / edit / delete
|
|
125
171
|
// =====================================================
|
|
126
172
|
|
|
127
|
-
// Método para guardar los registros actuales
|
|
128
173
|
saveRecords(): void {
|
|
129
|
-
|
|
130
174
|
if (this.displayData.length > 0) {
|
|
131
|
-
|
|
132
175
|
this.alertDialogService.AlertDialog({
|
|
133
176
|
type: 'question',
|
|
134
177
|
title: '¿Estás seguro de que deseas guardar los registros?',
|
|
135
|
-
description:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
} else {
|
|
160
|
-
this.alertToastService.AlertToast({
|
|
161
|
-
type: 'info',
|
|
162
|
-
title: 'No hay registros',
|
|
163
|
-
description: 'No hay registros para guardar.',
|
|
164
|
-
});
|
|
178
|
+
description:
|
|
179
|
+
'Asegúrate de verificar que los datos sean correctos, tenga en cuenta que no se tiene el control total de las validaciones como el formulario unitario.',
|
|
180
|
+
onConfirm: async () =>
|
|
181
|
+
new Promise<void>((resolve, reject) => {
|
|
182
|
+
this.genericService
|
|
183
|
+
.createMany<any[]>({ endpoint: this.mainEndpoint, data: this.displayData })
|
|
184
|
+
.subscribe({
|
|
185
|
+
next: (response) => {
|
|
186
|
+
this.alertToastService.AlertToast({
|
|
187
|
+
type: 'success',
|
|
188
|
+
title: 'Registros guardados',
|
|
189
|
+
description: response.message});
|
|
190
|
+
|
|
191
|
+
resolve();
|
|
192
|
+
this.closeDialog.emit();
|
|
193
|
+
},
|
|
194
|
+
error: reject});
|
|
195
|
+
}),
|
|
196
|
+
onCancel: () => {
|
|
197
|
+
console.log('Guardado cancelado');
|
|
198
|
+
}});
|
|
199
|
+
return;
|
|
165
200
|
}
|
|
166
|
-
}
|
|
167
201
|
|
|
168
|
-
|
|
169
|
-
|
|
202
|
+
this.alertToastService.AlertToast({
|
|
203
|
+
type: 'info',
|
|
204
|
+
title: 'No hay registros',
|
|
205
|
+
description: 'No hay registros para guardar.'});
|
|
206
|
+
}
|
|
170
207
|
|
|
171
208
|
onEdit(item: any): void {
|
|
172
209
|
if (this.editingRowItem === item) {
|
|
@@ -176,22 +213,16 @@ export class JCompleteTableComponent implements OnInit {
|
|
|
176
213
|
}
|
|
177
214
|
}
|
|
178
215
|
|
|
179
|
-
// Eliminar registro
|
|
180
216
|
onDelete(index: number): void {
|
|
181
|
-
|
|
182
217
|
this.alertDialogService.AlertDialog({
|
|
183
218
|
type: 'question',
|
|
184
219
|
title: 'Confirmar eliminación',
|
|
185
220
|
description: '¿Estás seguro de que deseas eliminar este registro?',
|
|
186
221
|
onConfirm: () => {
|
|
187
|
-
// Encuentra el objeto real que corresponde en staticData
|
|
188
222
|
const itemToDelete = this.displayData[index];
|
|
189
|
-
|
|
190
|
-
// Borrar de displayData
|
|
191
223
|
this.displayData.splice(index, 1);
|
|
192
224
|
|
|
193
|
-
|
|
194
|
-
const indexInStatic = this.staticData.findIndex(item => {
|
|
225
|
+
const indexInStatic = this.staticData.findIndex((item) => {
|
|
195
226
|
const rebuilt = this.rebuildObject(item);
|
|
196
227
|
return JSON.stringify(rebuilt) === JSON.stringify(itemToDelete);
|
|
197
228
|
});
|
|
@@ -200,321 +231,142 @@ export class JCompleteTableComponent implements OnInit {
|
|
|
200
231
|
this.staticData.splice(indexInStatic, 1);
|
|
201
232
|
}
|
|
202
233
|
},
|
|
203
|
-
onCancel: () => {
|
|
204
|
-
|
|
205
|
-
|
|
234
|
+
onCancel: () => {
|
|
235
|
+
console.log('Eliminación cancelada');
|
|
236
|
+
}});
|
|
206
237
|
}
|
|
207
238
|
|
|
208
239
|
// =====================================================
|
|
209
|
-
//
|
|
240
|
+
// Inline editing
|
|
210
241
|
// =====================================================
|
|
211
242
|
|
|
212
|
-
// Verifica si una columna tiene configuración de equivalencia
|
|
213
243
|
hasEquivalence(columnKey: string): boolean {
|
|
214
|
-
|
|
215
|
-
if (conf && conf.keyColumnSearch === columnKey) {
|
|
216
|
-
return true;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
return false;
|
|
244
|
+
return hasEquivalenceConfig(this.equivalenceConfigs, columnKey);
|
|
220
245
|
}
|
|
221
246
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
keyReturn: string;
|
|
225
|
-
options: { key: any; label: string }[];
|
|
226
|
-
} | null {
|
|
227
|
-
for (const [name, conf] of Object.entries(this.equivalenceConfigs || {})) {
|
|
228
|
-
if (conf && conf.keyColumnSearch === columnKey) {
|
|
229
|
-
const keyReturn = conf.keyReturn;
|
|
230
|
-
const idMap = (this.equivalences as any)[keyReturn];
|
|
231
|
-
if (!idMap) return null;
|
|
232
|
-
|
|
233
|
-
const options = Object.entries(idMap).map(([id, label]) => ({
|
|
234
|
-
key: +id,
|
|
235
|
-
label: String(label),
|
|
236
|
-
}));
|
|
237
|
-
|
|
238
|
-
return {
|
|
239
|
-
keyReturn,
|
|
240
|
-
options,
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
return null;
|
|
247
|
+
getEquivalenceData(columnKey: string): ReturnType<typeof getStaticTableEquivalenceData> {
|
|
248
|
+
return getStaticTableEquivalenceData(this.equivalenceConfigs, this.equivalences, columnKey);
|
|
245
249
|
}
|
|
246
250
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
// Maneja el cambio de equivalencia en un item
|
|
250
251
|
onEquivalenceChange(item: any, columnKey: string, newId: any): void {
|
|
251
252
|
const eqData = this.getEquivalenceData(columnKey);
|
|
252
|
-
if (!eqData)
|
|
253
|
+
if (!eqData) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
253
256
|
|
|
254
257
|
const newLabel = eqData.options.find((opt) => opt.key == newId)?.label ?? null;
|
|
255
|
-
|
|
256
|
-
this.setNestedValue(item, columnKey, newLabel);
|
|
258
|
+
assignNestedValue(item, columnKey, newLabel);
|
|
257
259
|
item[eqData.keyReturn] = newId;
|
|
258
260
|
|
|
259
|
-
const index = this.displayData
|
|
260
|
-
(row) => JSON.stringify(row) === JSON.stringify(item)
|
|
261
|
-
);
|
|
261
|
+
const index = findRowIndexByJsonSnapshot(this.displayData, item);
|
|
262
262
|
if (index !== -1) {
|
|
263
263
|
this.staticData[index] = this.flattenObject(item);
|
|
264
264
|
}
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
-
|
|
268
|
-
// Maneja el cambio de valor en un campo editable
|
|
269
267
|
onFieldChange(item: any, columnKey: string, value: any): void {
|
|
270
|
-
|
|
271
|
-
|
|
268
|
+
assignNestedValue(item, columnKey, value);
|
|
269
|
+
|
|
270
|
+
const index = findRowIndexByJsonSnapshot(this.displayData, item);
|
|
272
271
|
if (index !== -1) {
|
|
273
272
|
this.staticData[index] = this.flattenObject(item);
|
|
274
273
|
}
|
|
275
274
|
}
|
|
276
275
|
|
|
277
|
-
|
|
278
|
-
// Establece un valor anidado en un objeto según la clave de columna
|
|
279
276
|
setNestedValue(item: any, columnKey: string, value: any): void {
|
|
280
|
-
|
|
281
|
-
let current = item;
|
|
282
|
-
|
|
283
|
-
for (let i = 0; i < keys.length; i++) {
|
|
284
|
-
const key = keys[i];
|
|
285
|
-
if (i === keys.length - 1) {
|
|
286
|
-
current[key] = value;
|
|
287
|
-
} else {
|
|
288
|
-
if (!current[key]) {
|
|
289
|
-
current[key] = {};
|
|
290
|
-
}
|
|
291
|
-
current = current[key];
|
|
292
|
-
}
|
|
293
|
-
}
|
|
277
|
+
assignNestedValue(item, columnKey, value);
|
|
294
278
|
}
|
|
295
279
|
|
|
296
280
|
// =====================================================
|
|
297
|
-
//
|
|
281
|
+
// Checkbox (local toggle)
|
|
298
282
|
// =====================================================
|
|
299
283
|
|
|
300
|
-
// Método para cambiar el estado de un checkbox
|
|
301
284
|
onCheckboxChange(item: any, column: TableColumn<any>): void {
|
|
302
285
|
const newValue = this.getValue(item, column);
|
|
286
|
+
toggleNestedBooleanOnItem(item, column, newValue);
|
|
303
287
|
|
|
304
|
-
|
|
305
|
-
const updatedValue = !newValue;
|
|
306
|
-
|
|
307
|
-
const keys = column.key.split('.');
|
|
308
|
-
let current = item;
|
|
309
|
-
|
|
310
|
-
for (let i = 0; i < keys.length; i++) {
|
|
311
|
-
const key = keys[i];
|
|
312
|
-
|
|
313
|
-
if (i === keys.length - 1) {
|
|
314
|
-
current[key] = updatedValue;
|
|
315
|
-
} else {
|
|
316
|
-
if (!current[key]) {
|
|
317
|
-
current[key] = {};
|
|
318
|
-
}
|
|
319
|
-
current = current[key];
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Buscar índice real
|
|
324
|
-
const index = this.displayData.findIndex((row) => {
|
|
325
|
-
return JSON.stringify(row) === JSON.stringify(item);
|
|
326
|
-
});
|
|
327
|
-
|
|
288
|
+
const index = findRowIndexByJsonSnapshot(this.displayData, item);
|
|
328
289
|
if (index !== -1) {
|
|
329
290
|
this.staticData[index] = this.flattenObject(item);
|
|
330
291
|
}
|
|
331
292
|
}
|
|
332
293
|
|
|
333
|
-
|
|
334
|
-
|
|
335
294
|
// =====================================================
|
|
336
|
-
//
|
|
295
|
+
// Search
|
|
337
296
|
// =====================================================
|
|
338
297
|
|
|
339
|
-
// Ejecuta búsqueda al cambiar el valor del input.
|
|
340
298
|
onSearch(): void {
|
|
341
299
|
this.isLoadingSearch = true;
|
|
342
300
|
|
|
343
301
|
setTimeout(() => {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
this.
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
.filter((col) => col.isSearchable)
|
|
351
|
-
.map(col => col.key);
|
|
352
|
-
|
|
353
|
-
this.displayData = this.staticData
|
|
354
|
-
.map(item => this.rebuildObject(item))
|
|
355
|
-
.filter(item => {
|
|
356
|
-
return searchableKeys.some(key => {
|
|
357
|
-
const column = this.columns.find(col => col.key === key);
|
|
358
|
-
const value = column ? this.getValue(item, column) : undefined;
|
|
359
|
-
return value?.toString().toLowerCase().includes(this.searchQuery.trim().toLowerCase());
|
|
360
|
-
});
|
|
361
|
-
});
|
|
362
|
-
}
|
|
302
|
+
this.displayData = filterDisplayDataBySearch(
|
|
303
|
+
this.staticData,
|
|
304
|
+
this.columns,
|
|
305
|
+
this.searchQuery,
|
|
306
|
+
(row, column) => this.getValue(row, column),
|
|
307
|
+
);
|
|
363
308
|
|
|
364
309
|
this.isLoadingSearch = false;
|
|
365
310
|
}, 300);
|
|
366
311
|
}
|
|
367
312
|
|
|
368
|
-
// Limpia el campo de búsqueda y vuelve a cargar los datos originales.
|
|
369
313
|
clearSearch(): void {
|
|
370
314
|
this.searchQuery = '';
|
|
371
315
|
this.onSearch();
|
|
372
316
|
}
|
|
373
317
|
|
|
374
|
-
|
|
375
318
|
// =====================================================
|
|
376
|
-
//
|
|
319
|
+
// Sort
|
|
377
320
|
// =====================================================
|
|
378
321
|
|
|
379
|
-
// Ejecuta ordenamiento al hacer clic en cabecera.
|
|
380
322
|
onSort(column: TableColumn<any>): void {
|
|
381
|
-
if (!column.sortable)
|
|
323
|
+
if (!column.sortable) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
382
326
|
|
|
383
327
|
this.sortingColumn = column.key;
|
|
384
328
|
this.isLoadingSort = true;
|
|
385
329
|
|
|
386
330
|
setTimeout(() => {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
} else if (this.sortDirection === 'desc') {
|
|
391
|
-
this.sortDirection = 'none';
|
|
392
|
-
this.sortColumn = null;
|
|
393
|
-
} else {
|
|
394
|
-
this.sortDirection = 'asc';
|
|
395
|
-
}
|
|
396
|
-
} else {
|
|
397
|
-
this.sortColumn = column.key;
|
|
398
|
-
this.sortDirection = 'asc';
|
|
399
|
-
}
|
|
400
|
-
|
|
331
|
+
const next = resolveStaticTableSortState(column, this.sortColumn, this.sortDirection);
|
|
332
|
+
this.sortColumn = next.sortColumn;
|
|
333
|
+
this.sortDirection = next.sortDirection;
|
|
401
334
|
this.sortData();
|
|
402
|
-
|
|
403
335
|
this.isLoadingSort = false;
|
|
404
336
|
}, 300);
|
|
405
337
|
}
|
|
406
338
|
|
|
407
|
-
|
|
408
|
-
// Ordena los datos estáticos según sortColumn y sortDirection.
|
|
409
339
|
sortData(): void {
|
|
410
340
|
if (!this.sortColumn || this.sortDirection === 'none') {
|
|
411
|
-
// Restaurar orden original si no hay ordenamiento
|
|
412
341
|
this.onSearch();
|
|
413
342
|
return;
|
|
414
343
|
}
|
|
415
344
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
if (valA === 'S/N' && valB !== 'S/N') return -1;
|
|
424
|
-
if (valB === 'S/N' && valA !== 'S/N') return 1;
|
|
425
|
-
|
|
426
|
-
if (valA == null || valB == null) return 0;
|
|
427
|
-
|
|
428
|
-
const compA = valA.toString().toLowerCase();
|
|
429
|
-
const compB = valB.toString().toLowerCase();
|
|
430
|
-
|
|
431
|
-
if (compA < compB) return this.sortDirection === 'asc' ? -1 : 1;
|
|
432
|
-
if (compA > compB) return this.sortDirection === 'asc' ? 1 : -1;
|
|
433
|
-
return 0;
|
|
434
|
-
});
|
|
345
|
+
sortDisplayDataInPlace(
|
|
346
|
+
this.displayData,
|
|
347
|
+
this.sortColumn,
|
|
348
|
+
this.sortDirection,
|
|
349
|
+
this.columns,
|
|
350
|
+
(row, column) => this.getValue(row, column),
|
|
351
|
+
);
|
|
435
352
|
}
|
|
436
353
|
|
|
437
|
-
// Verifica si la tabla está en proceso de ordenamiento o búsqueda.
|
|
438
354
|
isLoading(type: 'sort' | 'search'): boolean {
|
|
439
355
|
if (type === 'sort') {
|
|
440
356
|
return this.isLoadingSort;
|
|
441
|
-
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (type === 'search') {
|
|
442
360
|
return this.isLoadingSearch;
|
|
443
361
|
}
|
|
362
|
+
|
|
444
363
|
return false;
|
|
445
364
|
}
|
|
446
365
|
|
|
447
|
-
// Maneja el evento de ordenamiento al presionar Enter o Espacio en la cabecera.
|
|
448
366
|
onSortKeyPress(event: KeyboardEvent, column: TableColumn<any>): void {
|
|
449
367
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
450
368
|
event.preventDefault();
|
|
451
369
|
this.onSort(column);
|
|
452
370
|
}
|
|
453
371
|
}
|
|
454
|
-
|
|
455
|
-
// =====================================================
|
|
456
|
-
// Prosesamiento de datos
|
|
457
|
-
// =====================================================
|
|
458
|
-
|
|
459
|
-
// Obtener el valor de las celdas para identificar un campo booleano
|
|
460
|
-
isBoolean(value: any): boolean {
|
|
461
|
-
return typeof value === 'boolean';
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
// Obtener el valor de las celdas para identificar un campo de fecha
|
|
465
|
-
isDate(value: any): boolean {
|
|
466
|
-
return value instanceof Date || (typeof value === 'string' && !isNaN(Date.parse(value)));
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
// Obtener los datos planos
|
|
470
|
-
flattenObject(obj: any, prefix: string = ''): any {
|
|
471
|
-
let result: any = {};
|
|
472
|
-
|
|
473
|
-
for (const key of Object.keys(obj)) {
|
|
474
|
-
const value = obj[key];
|
|
475
|
-
const prefixedKey = prefix ? `${prefix}.${key}` : key;
|
|
476
|
-
|
|
477
|
-
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
478
|
-
Object.assign(result, this.flattenObject(value, prefixedKey));
|
|
479
|
-
} else {
|
|
480
|
-
result[prefixedKey] = value;
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
return result;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
// Reconstruir el objeto a partir de los datos planos
|
|
488
|
-
rebuildObject(flatObj: any): any {
|
|
489
|
-
const result: any = {};
|
|
490
|
-
|
|
491
|
-
for (const key in flatObj) {
|
|
492
|
-
if (!Object.prototype.hasOwnProperty.call(flatObj, key)) continue;
|
|
493
|
-
|
|
494
|
-
const value = flatObj[key];
|
|
495
|
-
|
|
496
|
-
if (key.includes('.')) {
|
|
497
|
-
const parts = key.split('.');
|
|
498
|
-
let current = result;
|
|
499
|
-
|
|
500
|
-
for (let i = 0; i < parts.length; i++) {
|
|
501
|
-
const part = parts[i];
|
|
502
|
-
|
|
503
|
-
if (i === parts.length - 1) {
|
|
504
|
-
current[part] = value;
|
|
505
|
-
} else {
|
|
506
|
-
if (!current[part]) {
|
|
507
|
-
current[part] = {};
|
|
508
|
-
}
|
|
509
|
-
current = current[part];
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
} else {
|
|
513
|
-
result[key] = value;
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
return result;
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
}
|
|
372
|
+
}
|