tailjng 0.0.55 → 0.0.57
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/cli/settings/components-list.js +8 -0
- package/cli/settings/header-generator.js +1 -1
- package/fesm2022/tailjng.mjs.map +1 -1
- package/lib/interfaces/crud/crud.interface.d.ts +5 -2
- package/lib/interfaces/crud/filter.interface.d.ts +4 -0
- package/package.json +1 -1
- package/src/lib/components/card/card-complete/complete-card.component.html +104 -0
- package/src/lib/components/card/card-complete/complete-card.component.scss +35 -0
- package/src/lib/components/card/card-complete/complete-card.component.ts +652 -0
- package/src/lib/components/coach-mark/coach-mark.component.html +36 -0
- package/src/lib/components/coach-mark/coach-mark.component.scss +20 -0
- package/src/lib/components/coach-mark/coach-mark.component.ts +45 -0
- package/src/lib/components/coach-mark/coach-mark.directive.ts +256 -0
- package/src/lib/components/filter/filter-complete/complete-filter.component.html +194 -178
- package/src/lib/components/filter/filter-complete/complete-filter.component.ts +11 -1
- package/src/lib/components/form/form-validation/validation-form.component.html +1 -1
- package/src/lib/components/input/input/input.component.html +1 -1
- package/src/lib/components/input/input-file/file-input.component.html +3 -3
- package/src/lib/components/input/input-textarea/textarea-input.component.html +23 -19
- package/src/lib/components/select/select-dropdown/dropdown-select.component.html +5 -4
- package/src/lib/components/select/select-dropdown/dropdown-select.component.ts +3 -0
- package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.html +2 -1
- package/src/lib/components/table/table-crud-complete/complete-crud-table.component.html +3 -1
- package/src/lib/components/table/table-crud-complete/complete-crud-table.component.ts +7 -1
|
@@ -1,195 +1,211 @@
|
|
|
1
|
-
<div
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
1
|
+
<div
|
|
2
|
+
class="flex flex-col md:flex-row-reverse justify-between items-center mb-4 gap-3 select-none"
|
|
3
|
+
>
|
|
4
|
+
<div class="flex items-center gap-3 md:w-auto w-full">
|
|
5
|
+
<!-- Search -->
|
|
6
|
+
@if (isSearch) {
|
|
7
|
+
<div class="relative w-full">
|
|
8
|
+
<input
|
|
9
|
+
type="text"
|
|
10
|
+
[(ngModel)]="searchQuery"
|
|
11
|
+
[placeholder]="searchPlaceholder"
|
|
12
|
+
class="input w-full h-[40px] bg-background dark:bg-dark-background border border-border dark:border-dark-border text-black dark:text-white placeholder:text-muted-foreground/70 dark:placeholder:text-dark-muted-foreground/70 rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary dark:focus:ring-dark-primary transition duration-200 resize-y disabled:opacity-60 disabled:cursor-not-allowed"
|
|
13
|
+
/>
|
|
14
|
+
|
|
15
|
+
<div
|
|
16
|
+
class="absolute right-3 top-1/2 transform -translate-y-1/2 flex items-center gap-2"
|
|
17
|
+
>
|
|
18
|
+
@if (isLoadingSearch) {
|
|
19
|
+
<lucide-icon
|
|
20
|
+
[name]="iconsService.icons.loading"
|
|
21
|
+
size="18"
|
|
22
|
+
class="text-gray-400 animate-spin"
|
|
23
|
+
></lucide-icon>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@if (searchQuery && !isLoadingSearch) {
|
|
27
|
+
<button
|
|
28
|
+
(click)="clearSearch()"
|
|
29
|
+
class="pr-1 mr-1 text-gray-400 hover:text-gray-600 focus:outline-none cursor-pointer"
|
|
30
|
+
aria-label="Limpiar búsqueda"
|
|
31
|
+
>
|
|
32
|
+
<lucide-icon
|
|
33
|
+
[name]="iconsService.icons.close"
|
|
34
|
+
size="16"
|
|
35
|
+
></lucide-icon>
|
|
36
|
+
</button>
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@if (!isLoadingSearch && !searchQuery) {
|
|
40
|
+
<lucide-icon
|
|
41
|
+
[name]="iconsService.icons.search"
|
|
42
|
+
size="16"
|
|
43
|
+
class="text-gray-400"
|
|
44
|
+
></lucide-icon>
|
|
45
|
+
}
|
|
35
46
|
</div>
|
|
47
|
+
</div>
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
<!-- Elements per page -->
|
|
51
|
+
@if (isItemsPerPage) {
|
|
52
|
+
<div class="min-w-[75px]">
|
|
53
|
+
<JDropdownSelect
|
|
54
|
+
[isLoading]="isLoadingPerPage"
|
|
55
|
+
[(ngModel)]="itemsPerPage"
|
|
56
|
+
(selectionChange)="onItemsPerPageChange()"
|
|
57
|
+
placeholder="Mostrar"
|
|
58
|
+
title="Mostrar elementos"
|
|
59
|
+
[options]="itemsPerPageOptions"
|
|
60
|
+
/>
|
|
61
|
+
</div>
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
<!-- Show columns -->
|
|
65
|
+
@if (columns.length > 0 && isShowColumns) {
|
|
66
|
+
<div>
|
|
67
|
+
<JMultiTableSelect
|
|
68
|
+
type="multi-table"
|
|
69
|
+
title="Seleccionar columnas"
|
|
70
|
+
[columns]="visibleColumns"
|
|
71
|
+
/>
|
|
72
|
+
</div>
|
|
73
|
+
}
|
|
74
|
+
</div>
|
|
36
75
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
76
|
+
<div
|
|
77
|
+
class="flex gap-3 text-sm w-full md:w-auto md:justify-center justify-between"
|
|
78
|
+
>
|
|
79
|
+
<div class="flex flex-row flex-wrap gap-2">
|
|
80
|
+
@for (button of filtersButton; track $index) {
|
|
81
|
+
@if (getIsVisible(button)) {
|
|
82
|
+
<JButton
|
|
83
|
+
[icon]="button.icon"
|
|
84
|
+
[iconSize]="22"
|
|
85
|
+
[iconChange]="button.iconChange"
|
|
86
|
+
[isChangeIcon]="getIsChangeIcon(button)"
|
|
87
|
+
[isLoading]="getIsLoading(button)"
|
|
88
|
+
[disabled]="getDisabled(button)"
|
|
89
|
+
[tooltip]="getTooltip(button)"
|
|
90
|
+
[tooltipPosition]="button.tooltipPosition ?? 'top'"
|
|
91
|
+
(clicked)="filterBottomClick(button)"
|
|
92
|
+
[classes]="button.classes ?? ''"
|
|
93
|
+
[ngClasses]="{ 'min-w-auto p-1! pl-2! pr-2!': true }"
|
|
94
|
+
/>
|
|
95
|
+
|
|
96
|
+
@if (button.type === "upload") {
|
|
97
|
+
<input
|
|
98
|
+
#hiddenFileInput
|
|
99
|
+
type="file"
|
|
100
|
+
accept=".xlsx,.xls"
|
|
101
|
+
(change)="onCustomFileSelected($event, button)"
|
|
102
|
+
style="display: none"
|
|
46
103
|
/>
|
|
47
|
-
|
|
104
|
+
}
|
|
48
105
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
</div>
|
|
62
|
-
|
|
63
|
-
<div class="flex gap-3 text-sm w-full md:w-auto md:justify-center justify-between " >
|
|
64
|
-
|
|
65
|
-
<div class="flex flex-row flex-wrap gap-2">
|
|
66
|
-
@for (button of filtersButton; track $index) {
|
|
67
|
-
@if (getIsVisible(button)) {
|
|
68
|
-
<JButton
|
|
69
|
-
[icon]="button.icon"
|
|
70
|
-
[iconSize]="22"
|
|
71
|
-
[iconChange]="button.iconChange"
|
|
72
|
-
[isChangeIcon]="getIsChangeIcon(button)"
|
|
73
|
-
[isLoading]="isButtonLoading(button)"
|
|
74
|
-
[disabled]="getDisabled(button)"
|
|
75
|
-
[tooltip]="getTooltip(button)"
|
|
76
|
-
[tooltipPosition]="button.tooltipPosition ?? 'top'"
|
|
77
|
-
(clicked)="filterBottomClick(button)"
|
|
78
|
-
[classes]="button.classes ?? ''"
|
|
79
|
-
[ngClasses]="{'min-w-auto p-1! pl-2! pr-2!' : true}"
|
|
80
|
-
/>
|
|
81
|
-
|
|
82
|
-
@if (button.type === 'upload') {
|
|
83
|
-
<input
|
|
84
|
-
#hiddenFileInput
|
|
85
|
-
type="file"
|
|
86
|
-
accept=".xlsx,.xls"
|
|
87
|
-
(change)="onCustomFileSelected($event, button)"
|
|
88
|
-
style="display: none"
|
|
89
|
-
/>
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
@if (checked) {
|
|
95
|
-
<JSwitchCheckbox onKeyPress
|
|
96
|
-
[title]="titleChecked"
|
|
97
|
-
[isChecked]="isChecked"
|
|
98
|
-
(click)="checkActiveInactive.emit(isChecked)"
|
|
99
|
-
[isLoading]="isLoadingChecked"
|
|
100
|
-
/>
|
|
101
|
-
}
|
|
102
|
-
</div>
|
|
103
|
-
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@if (checked) {
|
|
109
|
+
<JSwitchCheckbox
|
|
110
|
+
onKeyPress
|
|
111
|
+
[title]="titleChecked"
|
|
112
|
+
[isChecked]="isChecked"
|
|
113
|
+
(click)="checkActiveInactive.emit(isChecked)"
|
|
114
|
+
[isLoading]="isLoadingChecked"
|
|
115
|
+
/>
|
|
116
|
+
}
|
|
104
117
|
</div>
|
|
118
|
+
</div>
|
|
105
119
|
</div>
|
|
106
120
|
|
|
107
|
-
|
|
108
121
|
<!-- Content Filters -->
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
<div class="select-none">
|
|
123
|
+
<JDialog
|
|
124
|
+
[openModal]="dialogOpen"
|
|
125
|
+
(closeModal)="dialogOpen = false"
|
|
126
|
+
[dialogTemplate]="templateDialog"
|
|
127
|
+
position="leftCenter"
|
|
128
|
+
title="Filtros"
|
|
129
|
+
[width]="220"
|
|
130
|
+
height="auto"
|
|
131
|
+
[overlay]="false"
|
|
132
|
+
[draggable]="true"
|
|
133
|
+
/>
|
|
121
134
|
</div>
|
|
122
135
|
|
|
123
136
|
<ng-template #templateDialog>
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
137
|
+
<div class="m-0 pt-1">
|
|
138
|
+
@if (filtersSelect.length > 0) {
|
|
139
|
+
<div class="flex flex-col gap-2">
|
|
140
|
+
@for (filter of filtersSelect; track $index) {
|
|
141
|
+
@if (filter.isVisible ?? true) {
|
|
142
|
+
@if (filter.type === "dropdown") {
|
|
143
|
+
<div>
|
|
144
|
+
<JDropdownSelect
|
|
145
|
+
[type]="'dropdown'"
|
|
146
|
+
[(ngModel)]="filter.selected"
|
|
147
|
+
(selectionChange)="
|
|
148
|
+
filter.onSelected ? filter.onSelected($event) : null
|
|
149
|
+
"
|
|
150
|
+
[optionLabel]="filter.optionLabel ?? ''"
|
|
151
|
+
[optionValue]="filter.optionValue ?? ''"
|
|
152
|
+
[labelSeparator]="filter.labelSeparator ?? ''"
|
|
153
|
+
[placeholder]="filter.placeholder ?? ''"
|
|
154
|
+
[showClear]="filter.showClear ?? false"
|
|
155
|
+
[options]="filter.options"
|
|
156
|
+
[sort]="filter.sort ?? 'ASC'"
|
|
157
|
+
[showAllOption]="filter.showAllOption ?? false"
|
|
158
|
+
/>
|
|
159
|
+
</div>
|
|
160
|
+
}
|
|
129
161
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
@if (filter.type === 'multi-table') {
|
|
170
|
-
<div>
|
|
171
|
-
<JMultiTableSelect
|
|
172
|
-
[(ngModel)]="filter.selected"
|
|
173
|
-
(selectionChange)="filter.onSelected ? filter.onSelected($event) : null"
|
|
174
|
-
[columns]="filter.columns"
|
|
175
|
-
[btnText]="filter.btnText ?? ''"
|
|
176
|
-
[isFilterSelect]="true"
|
|
177
|
-
/>
|
|
178
|
-
</div>
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
</div>
|
|
183
|
-
|
|
184
|
-
} @else {
|
|
185
|
-
<div class="text-center text-sm text-black dark:text-white pt-5 pb-5">
|
|
186
|
-
<p>No hay filtros disponibles</p>
|
|
187
|
-
</div>
|
|
162
|
+
<!-- Searchable -->
|
|
163
|
+
@if (filter.type === "searchable") {
|
|
164
|
+
<div>
|
|
165
|
+
<JDropdownSelect
|
|
166
|
+
[type]="'searchable'"
|
|
167
|
+
[(ngModel)]="filter.selected"
|
|
168
|
+
(selectionChange)="filter.onSelected?.($event)"
|
|
169
|
+
[endpoint]="filter.endpoint"
|
|
170
|
+
[optionLabel]="filter.optionLabel"
|
|
171
|
+
[optionValue]="filter.optionValue"
|
|
172
|
+
[labelSeparator]="filter.labelSeparator ?? ''"
|
|
173
|
+
[placeholder]="filter.placeholder ?? ''"
|
|
174
|
+
[showClear]="filter.showClear ?? false"
|
|
175
|
+
[loadOnInit]="filter.loadOnInit ?? false"
|
|
176
|
+
[isSearch]="filter.isSearch ?? true"
|
|
177
|
+
[searchFields]="filter.searchFields || []"
|
|
178
|
+
[defaultFilters]="filter.defaultFilters || []"
|
|
179
|
+
[sort]="filter.sort ?? 'ASC'"
|
|
180
|
+
[showAllOption]="filter.showAllOption ?? false"
|
|
181
|
+
/>
|
|
182
|
+
</div>
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@if (filter.type === "multi-table") {
|
|
186
|
+
<div>
|
|
187
|
+
<JMultiTableSelect
|
|
188
|
+
[(ngModel)]="filter.selected"
|
|
189
|
+
(selectionChange)="
|
|
190
|
+
filter.onSelected ? filter.onSelected($event) : null
|
|
191
|
+
"
|
|
192
|
+
[columns]="filter.columns"
|
|
193
|
+
[btnText]="filter.btnText ?? ''"
|
|
194
|
+
[isFilterSelect]="true"
|
|
195
|
+
/>
|
|
196
|
+
</div>
|
|
197
|
+
}
|
|
198
|
+
}
|
|
188
199
|
}
|
|
189
|
-
|
|
200
|
+
</div>
|
|
201
|
+
} @else {
|
|
202
|
+
<div class="text-center text-sm text-black dark:text-white pt-5 pb-5">
|
|
203
|
+
<p>No hay filtros disponibles</p>
|
|
204
|
+
</div>
|
|
205
|
+
}
|
|
206
|
+
</div>
|
|
190
207
|
</ng-template>
|
|
191
208
|
|
|
192
|
-
|
|
193
209
|
<!-- Content load data -->
|
|
194
210
|
<!-- <JDialog
|
|
195
211
|
[openModal]="dialogOpenCharge"
|
|
@@ -224,4 +240,4 @@
|
|
|
224
240
|
|
|
225
241
|
</div>
|
|
226
242
|
</div>
|
|
227
|
-
</ng-template> -->
|
|
243
|
+
</ng-template> -->
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
import { Component, EventEmitter, Input, Output, OnDestroy, OnInit, ViewChild, ElementRef } from '@angular/core';
|
|
3
2
|
import { FormsModule } from '@angular/forms';
|
|
4
3
|
import { LucideAngularModule } from 'lucide-angular';
|
|
@@ -29,6 +28,7 @@ export class JCompleteFilterComponent implements OnInit, OnDestroy {
|
|
|
29
28
|
@Input() searchPlaceholder: string = 'Buscar...';
|
|
30
29
|
|
|
31
30
|
// Inputs
|
|
31
|
+
@Input() isSearch: boolean = true;
|
|
32
32
|
@Input() params: any;
|
|
33
33
|
@Input() columns: TableColumn<any>[] = [];
|
|
34
34
|
@Input() endpoint!: string;
|
|
@@ -490,4 +490,14 @@ export class JCompleteFilterComponent implements OnInit, OnDestroy {
|
|
|
490
490
|
// Si no se define, por defecto es visible
|
|
491
491
|
return button.isVisible !== false;
|
|
492
492
|
}
|
|
493
|
+
|
|
494
|
+
getIsLoading(button: FilterButton): boolean {
|
|
495
|
+
if (button.isLoading === undefined) {
|
|
496
|
+
return false;
|
|
497
|
+
}
|
|
498
|
+
if (typeof button.isLoading === 'function') {
|
|
499
|
+
return button.isLoading();
|
|
500
|
+
}
|
|
501
|
+
return button.isLoading;
|
|
502
|
+
}
|
|
493
503
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
(blur)="onTouched()"
|
|
12
12
|
[ngClass]="combinedNgClass"
|
|
13
13
|
[class]="classes"
|
|
14
|
-
class="input w-full h-[40px] bg-background dark:bg-dark-background border border-border dark:border-dark-border text-black dark:text-white rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary transition duration-200"
|
|
14
|
+
class="input w-full h-[40px] bg-background dark:bg-dark-background border border-border dark:border-dark-border text-black dark:text-white placeholder:text-muted-foreground/70 dark:placeholder:text-dark-muted-foreground/70 rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary dark:focus:ring-dark-primary transition duration-200 resize-y disabled:opacity-60 disabled:cursor-not-allowed"
|
|
15
15
|
/>
|
|
16
16
|
|
|
17
17
|
@if (value && clearButton) {
|
|
@@ -15,13 +15,13 @@
|
|
|
15
15
|
|
|
16
16
|
<label
|
|
17
17
|
[for]="id"
|
|
18
|
-
class="input block text-sm
|
|
18
|
+
class="input block text-sm w-full h-[40px] pr-1 bg-background dark:bg-dark-background border border-border dark:border-dark-border text-black dark:text-white placeholder:text-muted-foreground dark:placeholder:text-dark-muted-foreground rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary dark:focus:ring-dark-primary transition duration-200 resize-y disabled:opacity-60 disabled:cursor-not-allowed flex items-center justify-between transition duration-200 cursor-pointer"
|
|
19
19
|
>
|
|
20
|
-
<div class="truncate" [ngClass]="{ 'opacity-
|
|
20
|
+
<div class="truncate" [ngClass]="{ 'opacity-80' : !innerValue?.name }">
|
|
21
21
|
@if (innerValue?.name) {
|
|
22
22
|
<span>{{ innerValue?.name }}</span>
|
|
23
23
|
} @else {
|
|
24
|
-
<span class="flex items-center gap-2">
|
|
24
|
+
<span class="flex items-center gap-2 text-muted-foreground dark:text-dark-muted-foreground">
|
|
25
25
|
<lucide-icon [name]="iconsService.icons.upload" [size]="15" />
|
|
26
26
|
Seleccionar archivo...
|
|
27
27
|
</span>
|
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
<div class="relative w-full flex">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
2
|
+
<textarea
|
|
3
|
+
[id]="id"
|
|
4
|
+
[name]="name ?? ''"
|
|
5
|
+
[placeholder]="placeholder"
|
|
6
|
+
[value]="value"
|
|
7
|
+
(input)="onInput($event)"
|
|
8
|
+
[required]="required"
|
|
9
|
+
[disabled]="disabled"
|
|
10
|
+
(blur)="onTouched()"
|
|
11
|
+
[ngClass]="combinedNgClass"
|
|
12
|
+
[class]="classes"
|
|
13
|
+
class="input w-full h-[70px] min-h-[70px] pr-10 bg-background dark:bg-dark-background border border-border dark:border-dark-border text-black dark:text-white placeholder:text-muted-foreground/70 dark:placeholder:text-dark-muted-foreground/70 rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary dark:focus:ring-dark-primary transition duration-200 resize-y disabled:opacity-60 disabled:cursor-not-allowed"
|
|
14
|
+
></textarea>
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
@if (value && clearButton) {
|
|
17
|
+
<button
|
|
18
|
+
type="button"
|
|
19
|
+
class="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 text-gray-400 hover:text-gray-500 pr-1 mr-1 text-gray-400 hover:text-gray-600 focus:outline-none cursor-pointer"
|
|
20
|
+
(click)="clearInput()"
|
|
21
|
+
>
|
|
22
|
+
<lucide-icon [name]="iconsService.icons.close" class="w-4 h-4" />
|
|
23
|
+
</button>
|
|
24
|
+
}
|
|
25
|
+
</div>
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
type="button"
|
|
5
5
|
[disabled]="disabled || isLoading"
|
|
6
6
|
(click)="toggleColumnSelector()"
|
|
7
|
-
class="flex w-full h-[40px] items-center justify-between px-3 py-2 text-sm bg-background dark:bg-dark-background border border-border dark:border-dark-border rounded focus:outline-none focus:ring-2 focus:ring-primary select-none"
|
|
7
|
+
[class]="'flex w-full h-[40px] items-center justify-between px-3 py-2 text-sm bg-background dark:bg-dark-background border border-border dark:border-dark-border rounded focus:outline-none focus:ring-2 focus:ring-primary select-none' + ' ' + classes"
|
|
8
8
|
[ngClass]="{
|
|
9
|
-
'opacity-50 cursor-not-allowed pointer-events-none': disabled || isLoading
|
|
9
|
+
'opacity-50 cursor-not-allowed pointer-events-none': disabled || isLoading,
|
|
10
|
+
ngClass: true
|
|
10
11
|
}"
|
|
11
12
|
>
|
|
12
|
-
<span class="truncate text-black dark:text-white" [ngClass]="{'opacity-
|
|
13
|
+
<span class="truncate text-black dark:text-white" [ngClass]="{'opacity-70 text-muted-foreground dark:text-dark-muted-foreground' : selectedValue === null}">{{selectedLabel}}</span>
|
|
13
14
|
|
|
14
15
|
<div class="flex items-center">
|
|
15
16
|
@if (showClear && selectedValue !== null) {
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
<!-- Dropdown positioned outside the flow -->
|
|
33
34
|
@if (isColumnSelectorOpen) {
|
|
34
35
|
<div @modalTransition
|
|
35
|
-
class="absolute z-[100] min-w-[250px] mt-1 bg-background dark:bg-dark-background rounded-lg shadow-lg border border-border border-dark-border"
|
|
36
|
+
[class]="'absolute z-[100] min-w-[250px] mt-1 bg-background dark:bg-dark-background rounded-lg shadow-lg border border-border border-dark-border' + ' ' + classes"
|
|
36
37
|
[style.width.px]="dropdownWidth"
|
|
37
38
|
[style.top.px]="dropdownTop"
|
|
38
39
|
[style.left.px]="dropdownLeft"
|
|
@@ -55,6 +55,9 @@ export class JDropdownSelectComponent implements ControlValueAccessor, AfterView
|
|
|
55
55
|
|
|
56
56
|
@Input() isSearch = true;
|
|
57
57
|
@Input() isFilterSelect = false;
|
|
58
|
+
|
|
59
|
+
@Input() classes: string = '';
|
|
60
|
+
@Input() ngClass: { [key: string]: boolean } = {};
|
|
58
61
|
|
|
59
62
|
@Output() selectionChange = new EventEmitter<any>();
|
|
60
63
|
@Output() fullData = new EventEmitter<any[]>();
|
package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.html
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
<div class="relative w-full h-full">
|
|
2
3
|
<div class="w-auto" #selectButton>
|
|
3
4
|
<button
|
|
@@ -7,7 +8,7 @@
|
|
|
7
8
|
class="flex w-full h-[40px] items-center justify-between px-3 py-2 text-sm bg-background dark:bg-dark-background border border-border dark:border-dark-border rounded focus:outline-none focus:ring-2 focus:ring-primary select-none"
|
|
8
9
|
[ngClass]="{ 'opacity-50 cursor-not-allowed pointer-events-none': disabled || isLoading }"
|
|
9
10
|
>
|
|
10
|
-
<span class="truncate text-black dark:text-white" [ngClass]="{ 'opacity-
|
|
11
|
+
<span class="truncate text-black dark:text-white" [ngClass]="{ 'opacity-70 text-muted-foreground dark:text-dark-muted-foreground': selectedValues.length === 0 }">
|
|
11
12
|
{{ displayLabel }}
|
|
12
13
|
</span>
|
|
13
14
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div class="w-full mb-3">
|
|
2
2
|
|
|
3
|
-
@if (
|
|
3
|
+
@if (isFilter) {
|
|
4
4
|
<JFilter
|
|
5
5
|
[params]="params"
|
|
6
6
|
[columns]="columns"
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
[mainEndpoint]="mainEndpoint"
|
|
9
9
|
[data]="data"
|
|
10
10
|
[(searchQuery)]="searchQuery"
|
|
11
|
+
[isSearch]="isSearch"
|
|
12
|
+
[isShowColumns]="isEyeColumn"
|
|
11
13
|
(search)="onSearch()"
|
|
12
14
|
[searchPlaceholder]="searchPlaceholder"
|
|
13
15
|
[isItemsPerPage]="isItemsPerPage"
|
|
@@ -65,7 +65,9 @@ export class JCompleteCrudTableComponent implements OnInit {
|
|
|
65
65
|
@Input() isNumbering: boolean = true;
|
|
66
66
|
@Input() defaultFilters: { [key: string]: any } = {};
|
|
67
67
|
@Input() isPaginator = true;
|
|
68
|
+
@Input() isFilter = true;
|
|
68
69
|
@Input() isSearch = true;
|
|
70
|
+
@Input() isEyeColumn = true;
|
|
69
71
|
@Input() hideRowCondition?: (row: any) => boolean
|
|
70
72
|
|
|
71
73
|
data: any[] = [];
|
|
@@ -1049,6 +1051,7 @@ export class JCompleteCrudTableComponent implements OnInit {
|
|
|
1049
1051
|
};
|
|
1050
1052
|
|
|
1051
1053
|
getRowNgClass(row: any): any {
|
|
1054
|
+
|
|
1052
1055
|
const base: any = {
|
|
1053
1056
|
'cursor-pointer': this.hasExpandable(),
|
|
1054
1057
|
};
|
|
@@ -1062,7 +1065,10 @@ export class JCompleteCrudTableComponent implements OnInit {
|
|
|
1062
1065
|
value = value?.[key];
|
|
1063
1066
|
}
|
|
1064
1067
|
|
|
1065
|
-
const normalizedValue =
|
|
1068
|
+
const normalizedValue =
|
|
1069
|
+
value === null || value === undefined
|
|
1070
|
+
? 'null'
|
|
1071
|
+
: String(value).toUpperCase();
|
|
1066
1072
|
const semanticClass = columnWithColor.rowColorCondition?.[normalizedValue];
|
|
1067
1073
|
|
|
1068
1074
|
if (semanticClass && this.rowColorMap[semanticClass]) {
|