@drax/crud-vue 3.46.0 → 3.47.0

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.
Files changed (38) hide show
  1. package/package.json +3 -3
  2. package/src/components/Crud.vue +21 -3
  3. package/src/components/CrudActiveFilters.vue +11 -9
  4. package/src/components/CrudAi.vue +38 -25
  5. package/src/components/CrudAutocomplete.vue +14 -2
  6. package/src/components/CrudDialog.vue +6 -6
  7. package/src/components/CrudExportList.vue +13 -12
  8. package/src/components/CrudFieldRange.vue +8 -4
  9. package/src/components/CrudFilters.vue +8 -2
  10. package/src/components/CrudFiltersAction.vue +3 -3
  11. package/src/components/CrudFiltersDynamic.vue +18 -10
  12. package/src/components/CrudForm.vue +44 -31
  13. package/src/components/CrudFormField.vue +48 -8
  14. package/src/components/CrudFormList.vue +44 -32
  15. package/src/components/CrudFormRecord.vue +19 -11
  16. package/src/components/CrudImportList.vue +17 -16
  17. package/src/components/CrudList.vue +41 -12
  18. package/src/components/CrudListGallery.vue +65 -27
  19. package/src/components/CrudListTable.vue +49 -10
  20. package/src/components/CrudNotify.vue +3 -1
  21. package/src/components/CrudRefDisplay.vue +2 -2
  22. package/src/components/CrudRouteForm.vue +8 -4
  23. package/src/components/CrudRowValue.vue +9 -8
  24. package/src/components/CrudSearch.vue +2 -1
  25. package/src/components/buttons/CrudAiButton.vue +3 -2
  26. package/src/components/buttons/CrudColumnsButton.vue +17 -7
  27. package/src/components/buttons/CrudCreateButton.vue +3 -2
  28. package/src/components/buttons/CrudCreateOnTheFlyButton.vue +7 -2
  29. package/src/components/buttons/CrudDeleteButton.vue +3 -2
  30. package/src/components/buttons/CrudExportButton.vue +7 -6
  31. package/src/components/buttons/CrudFilterButton.vue +4 -3
  32. package/src/components/buttons/CrudGroupByButton.vue +28 -15
  33. package/src/components/buttons/CrudImportButton.vue +10 -8
  34. package/src/components/buttons/CrudRefreshButton.vue +3 -2
  35. package/src/components/buttons/CrudSavedQueriesButton.vue +37 -19
  36. package/src/components/buttons/CrudUpdateButton.vue +3 -2
  37. package/src/components/buttons/CrudViewButton.vue +3 -2
  38. package/src/components/combobox/EntityCombobox.vue +4 -0
@@ -50,6 +50,8 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
50
50
 
51
51
  <template>
52
52
  <v-data-table-server
53
+ :id="`crud-list-table-${entity.name}`"
54
+ class="crud-list-table"
53
55
  :density="entity.tableDensity"
54
56
  :striped="entity.tableStriped"
55
57
  :header-props="entity.headerProps"
@@ -71,25 +73,26 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
71
73
  <template v-slot:no-data>
72
74
  <v-alert
73
75
  v-if="paginationError"
76
+ id="crud-list-table-pagination-error"
74
77
  variant="tonal"
75
- class="w-100 ma-2"
78
+ class="crud-list-table__pagination-error w-100 ma-2"
76
79
  style="width: 100%; min-width: 100%"
77
80
  prominent
78
81
  type="error"
79
82
  :text="te(paginationError) ? t(paginationError) : paginationError"
80
83
  />
81
- <v-alert v-else variant="tonal" class="w-100 ma-2 " type="info" :text="te('crud.noData') ? t('crud.noData') : 'No data' " />
84
+ <v-alert v-else id="crud-list-table-no-data" variant="tonal" class="crud-list-table__no-data w-100 ma-2 " type="info" :text="te('crud.noData') ? t('crud.noData') : 'No data' " />
82
85
  </template>
83
86
 
84
87
  <template v-slot:bottom>
85
- <v-data-table-footer :class="entity.footerClass"
88
+ <v-data-table-footer id="crud-list-table-footer" :class="['crud-list-table__footer', entity.footerClass]"
86
89
  :items-per-page-options="[5, 10, 20, 50]"
87
90
  ></v-data-table-footer>
88
91
  </template>
89
92
 
90
93
  <template v-slot:top>
91
- <v-toolbar :class="entity.toolbarClass" :density="entity.toolbarDensity">
92
- <v-toolbar-title>
94
+ <v-toolbar id="crud-list-table-toolbar" :class="['crud-list-table__toolbar', entity.toolbarClass]" :density="entity.toolbarDensity">
95
+ <v-toolbar-title id="crud-list-table-title" class="crud-list-table__title">
93
96
  {{ te(`${entity.name.toLowerCase()}.crud`) ? t(`${entity.name.toLowerCase()}.crud`) : entity.name }}
94
97
  </v-toolbar-title>
95
98
  <v-spacer></v-spacer>
@@ -100,30 +103,42 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
100
103
 
101
104
  <crud-saved-queries-button
102
105
  v-if="entity.isSavedQueriesEnabled"
106
+ id="crud-list-table-saved-queries-button"
107
+ class="crud-list-table__saved-queries-button"
103
108
  :entity="entity"
104
109
  />
105
110
 
106
111
 
107
112
  <crud-import-button
113
+ id="crud-list-table-import-button"
114
+ class="crud-list-table__import-button"
108
115
  :entity="entity"
109
116
  @import="(file:any, format:any) => $emit('import', file, format)"
110
117
  />
111
118
 
112
119
  <crud-export-button
120
+ id="crud-list-table-export-button"
121
+ class="crud-list-table__export-button"
113
122
  :entity="entity"
114
123
  @export="(v:any) => $emit('export',v)"
115
124
  />
116
125
 
117
126
  <crud-group-by-button
118
127
  v-if="entity.isGroupable"
128
+ id="crud-list-table-group-by-button"
129
+ class="crud-list-table__group-by-button"
119
130
  :entity="entity"
120
131
  />
121
132
 
122
133
  <crud-filter-button
134
+ id="crud-list-table-filter-button"
135
+ class="crud-list-table__filter-button"
123
136
  :entity="entity" />
124
137
 
125
138
  <crud-columns-button
126
139
  v-if="entity.isColumnSelectable"
140
+ id="crud-list-table-columns-button"
141
+ class="crud-list-table__columns-button"
127
142
  :entity="entity"
128
143
  />
129
144
 
@@ -134,11 +149,15 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
134
149
 
135
150
  <crud-refresh-button
136
151
  v-if="entity.isRefreshable !== false"
152
+ id="crud-list-table-refresh-button"
153
+ class="crud-list-table__refresh-button"
137
154
  @click="doPaginate"
138
155
  />
139
156
 
140
157
  <crud-create-button
141
158
  v-if="entity.isCreatable"
159
+ id="crud-list-table-create-button"
160
+ class="crud-list-table__create-button"
142
161
  :entity="entity"
143
162
  @click="$emit('create')"
144
163
  />
@@ -150,6 +169,8 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
150
169
  </v-toolbar>
151
170
 
152
171
  <crud-export-list
172
+ id="crud-list-table-export-list"
173
+ class="crud-list-table__export-list"
153
174
  :entity="entity"
154
175
  >
155
176
  <template #export-table="{ exportFiles }">
@@ -158,6 +179,8 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
158
179
  </crud-export-list>
159
180
 
160
181
  <crud-import-list
182
+ id="crud-list-table-import-list"
183
+ class="crud-list-table__import-list"
161
184
  :entity="entity"
162
185
  >
163
186
  <template #import-table="{ importFiles }">
@@ -165,20 +188,24 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
165
188
  </template>
166
189
  </crud-import-list>
167
190
 
168
- <v-card variant="flat">
169
- <v-card-text v-if="entity.searchEnable">
191
+ <v-card id="crud-list-table-controls" class="crud-list-table__controls" variant="flat">
192
+ <v-card-text v-if="entity.searchEnable" id="crud-list-table-search-section" class="crud-list-table__search-section">
170
193
  <crud-search
194
+ id="crud-list-table-search"
195
+ class="crud-list-table__search"
171
196
  v-model="search"
172
197
  />
173
198
  </v-card-text>
174
199
 
175
- <v-card-text class="pt-0">
200
+ <v-card-text id="crud-list-table-filters-section" class="crud-list-table__filters-section pt-0">
176
201
  <slot name="filters" v-bind="{filters}"></slot>
177
202
 
178
- <v-card variant="flat" v-if="!$slots.filters">
203
+ <v-card id="crud-list-table-default-filters" class="crud-list-table__default-filters" variant="flat" v-if="!$slots.filters">
179
204
 
180
205
  <crud-filters
181
206
  v-if="entity.filtersEnable"
207
+ id="crud-list-table-filters"
208
+ class="crud-list-table__filters"
182
209
  :entity="entity"
183
210
  v-model="filters"
184
211
  :auto-filter="!entity.filterButtons"
@@ -199,6 +226,8 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
199
226
 
200
227
  <crud-filters-dynamic
201
228
  v-if="isDynamicFiltersEnable"
229
+ id="crud-list-table-dynamic-filters"
230
+ class="crud-list-table__dynamic-filters"
202
231
  :entity="entity"
203
232
  v-model="filters"
204
233
  :auto-filter="!entity.filterButtons"
@@ -208,6 +237,8 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
208
237
  </crud-filters-dynamic>
209
238
 
210
239
  <crud-filters-action v-if="entity.filterButtons"
240
+ id="crud-list-table-filters-actions"
241
+ class="crud-list-table__filters-actions"
211
242
  :entity="entity"
212
243
  @clearFilter="clearFilters()"
213
244
  @applyFilter="applyFilters()"
@@ -218,7 +249,7 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
218
249
 
219
250
  </v-card>
220
251
 
221
- <v-divider></v-divider>
252
+ <v-divider id="crud-list-table-toolbar-divider" class="crud-list-table__toolbar-divider"></v-divider>
222
253
 
223
254
 
224
255
 
@@ -228,6 +259,8 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
228
259
  <template v-for="header in entity.headers" :key="header.key" v-slot:[`item.${header.key}`]="{item, value}">
229
260
  <slot v-if="$slots[`item.${header.key}`]" :name="`item.${header.key}`" v-bind="{item, value}">
230
261
  <crud-row-value
262
+ :id="`crud-list-table-row-value-${header.key}`"
263
+ class="crud-list-table__row-value"
231
264
  :title="header.title || header.key"
232
265
  :value="value"
233
266
  />
@@ -242,16 +275,22 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
242
275
 
243
276
  <crud-view-button
244
277
  v-if="entity.isViewable && hasPermission(entity.permissions.view)"
278
+ :id="`crud-list-table-row-view-button-${index}`"
279
+ class="crud-list-table__row-view-button"
245
280
  @click="$emit('view', item, index)"
246
281
  />
247
282
 
248
283
  <crud-update-button
249
284
  v-if="entity.isEditable && entity.isItemEditable(item) && hasPermission(entity.permissions?.update)"
285
+ :id="`crud-list-table-row-update-button-${index}`"
286
+ class="crud-list-table__row-update-button"
250
287
  @click="$emit('edit', item, index)"
251
288
  />
252
289
 
253
290
  <crud-delete-button
254
291
  v-if="entity.isDeletable && hasPermission(entity.permissions?.delete)"
292
+ :id="`crud-list-table-row-delete-button-${index}`"
293
+ class="crud-list-table__row-delete-button"
255
294
  @click="$emit('delete', item, index)"
256
295
  />
257
296
 
@@ -11,11 +11,13 @@ defineProps({
11
11
 
12
12
  <template>
13
13
 
14
- <v-snackbar v-model="valueModel" :timeout="timeout" :color="color" >
14
+ <v-snackbar id="crud-notify" class="crud-notify" v-model="valueModel" :timeout="timeout" :color="color" >
15
15
  {{message}}
16
16
 
17
17
  <template v-slot:actions>
18
18
  <v-btn
19
+ id="crud-notify-close-button"
20
+ class="crud-notify__close-button"
19
21
  icon="mdi-close"
20
22
  variant="text"
21
23
  @click="valueModel = false"
@@ -41,6 +41,6 @@ watch(
41
41
  </script>
42
42
 
43
43
  <template>
44
- <span v-if="loading">...</span>
45
- <span v-else>{{display}}</span>
44
+ <span v-if="loading" id="crud-ref-display-loading" class="crud-ref-display crud-ref-display--loading">...</span>
45
+ <span v-else id="crud-ref-display-value" class="crud-ref-display crud-ref-display--value">{{display}}</span>
46
46
  </template>
@@ -163,12 +163,14 @@ async function prepareRouteForm() {
163
163
  </script>
164
164
 
165
165
  <template>
166
- <v-container :fluid="entity.containerFluid" class="mt-5">
167
- <v-card :class="entity.cardClass" :density="entity.cardDensity">
168
- <v-progress-linear v-if="store.loading" indeterminate/>
166
+ <v-container :id="`crud-route-form-container-${entity.name}`" :fluid="entity.containerFluid" class="crud-route-form mt-5">
167
+ <v-card :id="`crud-route-form-card-${entity.name}`" :class="['crud-route-form__card', entity.cardClass]" :density="entity.cardDensity">
168
+ <v-progress-linear v-if="store.loading" id="crud-route-form-loading" class="crud-route-form__loading" indeterminate/>
169
169
 
170
- <v-card-actions class="justify-start pa-2 pb-0">
170
+ <v-card-actions id="crud-route-form-actions" class="crud-route-form__actions justify-start pa-2 pb-0">
171
171
  <v-btn
172
+ id="crud-route-form-back-button"
173
+ class="crud-route-form__back-button"
172
174
  prepend-icon="mdi-arrow-left"
173
175
  variant="text"
174
176
  @click="goToList"
@@ -179,6 +181,8 @@ async function prepareRouteForm() {
179
181
 
180
182
  <crud-form
181
183
  v-if="formReady || store.error"
184
+ id="crud-route-form-form"
185
+ class="crud-route-form__form"
182
186
  :entity="entity"
183
187
  show-submit-and-return
184
188
  @created="created"
@@ -33,24 +33,25 @@ const openFullTextDialog = () => {
33
33
  <template>
34
34
  <span
35
35
  v-if="isLongString"
36
- class="d-inline-block text-truncate crud-row-value__truncated"
36
+ id="crud-row-value-truncated"
37
+ class="crud-row-value crud-row-value--truncated d-inline-block text-truncate crud-row-value__truncated"
37
38
  @click="openFullTextDialog"
38
39
  >
39
40
  {{ displayValue }}
40
41
  </span>
41
- <span v-else>{{ displayValue }}</span>
42
+ <span v-else id="crud-row-value-text" class="crud-row-value crud-row-value--text">{{ displayValue }}</span>
42
43
 
43
- <v-dialog v-model="fullTextDialog" max-width="720">
44
- <v-card>
45
- <v-card-title class="text-wrap">
44
+ <v-dialog id="crud-row-value-dialog" class="crud-row-value-dialog" v-model="fullTextDialog" max-width="720">
45
+ <v-card id="crud-row-value-dialog-card" class="crud-row-value-dialog__card">
46
+ <v-card-title id="crud-row-value-dialog-title" class="crud-row-value-dialog__title text-wrap">
46
47
  {{ title }}
47
48
  </v-card-title>
48
- <v-card-text class="crud-row-value__dialog-text">
49
+ <v-card-text id="crud-row-value-dialog-text" class="crud-row-value-dialog__text crud-row-value__dialog-text">
49
50
  {{ displayValue }}
50
51
  </v-card-text>
51
- <v-card-actions>
52
+ <v-card-actions id="crud-row-value-dialog-actions" class="crud-row-value-dialog__actions">
52
53
  <v-spacer />
53
- <v-btn variant="text" @click="fullTextDialog = false">
54
+ <v-btn id="crud-row-value-dialog-close-button" class="crud-row-value-dialog__close-button" variant="text" @click="fullTextDialog = false">
54
55
  {{ te('action.close') ? t('action.close') : 'Close' }}
55
56
  </v-btn>
56
57
  </v-card-actions>
@@ -28,8 +28,9 @@ function clear() {
28
28
 
29
29
  <template>
30
30
  <v-text-field v-model="input"
31
+ id="crud-search-input"
31
32
  density="compact"
32
- class="mr-2"
33
+ class="crud-search-input mr-2"
33
34
  variant="outlined"
34
35
  append-inner-icon="mdi-magnify"
35
36
  :label="t('action.search')"
@@ -22,12 +22,13 @@ function toggleExpanded() {
22
22
  </script>
23
23
 
24
24
  <template>
25
- <v-tooltip location="top">
25
+ <v-tooltip :id="`${$attrs.id || 'crud-ai-button'}-tooltip`" class="crud-ai-button__tooltip" location="top">
26
26
  <template v-slot:activator="{ props }">
27
27
  <v-btn
28
28
  v-bind="{ ...$attrs, ...props }"
29
29
  icon="mdi-robot-outline"
30
- class="mr-1"
30
+ :id="$attrs.id || 'crud-ai-button'"
31
+ class="crud-ai-button mr-1"
31
32
  variant="text"
32
33
  @click="toggleExpanded"
33
34
  />
@@ -21,27 +21,31 @@ const {
21
21
  </script>
22
22
 
23
23
  <template>
24
- <v-menu offset-y :close-on-content-click="false">
24
+ <v-menu id="crud-columns-menu" class="crud-columns-menu" offset-y :close-on-content-click="false">
25
25
  <template v-slot:activator="{ props }">
26
26
  <v-btn
27
27
  v-bind="props"
28
+ id="crud-columns-button"
29
+ class="crud-columns-button"
28
30
  icon
29
31
  variant="text"
30
32
  >
31
- <v-icon>mdi-view-column</v-icon>
33
+ <v-icon id="crud-columns-button-icon" class="crud-columns-button__icon">mdi-view-column</v-icon>
32
34
  <v-tooltip activator="parent" location="bottom">
33
35
  {{ t('crud.columns.select') }}
34
36
  </v-tooltip>
35
37
  </v-btn>
36
38
  </template>
37
- <v-list>
38
- <v-list-subheader>
39
+ <v-list id="crud-columns-list" class="crud-columns-menu__list">
40
+ <v-list-subheader id="crud-columns-title" class="crud-columns-menu__title">
39
41
  {{ t('crud.columns.title') }}
40
42
  </v-list-subheader>
41
43
 
42
- <v-list-item>
43
- <div class="d-flex gap-2">
44
+ <v-list-item id="crud-columns-bulk-actions" class="crud-columns-menu__bulk-actions">
45
+ <div id="crud-columns-bulk-actions-content" class="crud-columns-menu__bulk-actions-content d-flex gap-2">
44
46
  <v-btn
47
+ id="crud-columns-select-all-button"
48
+ class="crud-columns-menu__select-all-button"
45
49
  size="small"
46
50
  variant="text"
47
51
  color="primary"
@@ -51,6 +55,8 @@ const {
51
55
  {{ t('crud.columns.selectAll') }}
52
56
  </v-btn>
53
57
  <v-btn
58
+ id="crud-columns-deselect-all-button"
59
+ class="crud-columns-menu__deselect-all-button"
54
60
  size="small"
55
61
  variant="text"
56
62
  color="primary"
@@ -67,15 +73,19 @@ const {
67
73
  <v-list-item
68
74
  v-for="column in availableColumns"
69
75
  :key="column.key"
76
+ :id="`crud-columns-item-${column.key}`"
77
+ class="crud-columns-menu__item"
70
78
  @click="toggleColumn(column.key)"
71
79
  >
72
80
  <template v-slot:prepend>
73
81
  <v-checkbox-btn
82
+ :id="`crud-columns-checkbox-${column.key}`"
83
+ class="crud-columns-menu__checkbox"
74
84
  :model-value="column.visible"
75
85
  @click.stop="toggleColumn(column.key)"
76
86
  ></v-checkbox-btn>
77
87
  </template>
78
- <v-list-item-title>{{ column.title }}</v-list-item-title>
88
+ <v-list-item-title class="crud-columns-menu__item-title">{{ column.title }}</v-list-item-title>
79
89
  </v-list-item>
80
90
  </v-list>
81
91
  </v-menu>
@@ -5,12 +5,13 @@ const {t} = useI18n()
5
5
  </script>
6
6
 
7
7
  <template>
8
- <v-tooltip location="top">
8
+ <v-tooltip :id="`${$attrs.id || 'crud-create-button'}-tooltip`" class="crud-create-button__tooltip" location="top">
9
9
  <template v-slot:activator="{ props }">
10
10
  <v-btn
11
11
  v-bind="{ ...$attrs, ...props }"
12
12
  icon="mdi-plus"
13
- class="mr-1"
13
+ :id="$attrs.id || 'crud-create-button'"
14
+ class="crud-create-button mr-1"
14
15
  variant="text"
15
16
  >
16
17
  </v-btn>
@@ -38,12 +38,13 @@ const emit = defineEmits(['created'])
38
38
  </script>
39
39
 
40
40
  <template>
41
- <v-tooltip location="top">
41
+ <v-tooltip :id="`${$attrs.id || 'crud-create-on-the-fly-button'}-tooltip`" class="crud-create-on-the-fly-button__tooltip" location="top">
42
42
  <template v-slot:activator="{ props }">
43
43
  <v-btn
44
44
  v-bind="{ ...$attrs, ...props }"
45
45
  icon="mdi-plus"
46
- class="mr-1"
46
+ :id="$attrs.id || 'crud-create-on-the-fly-button'"
47
+ class="crud-create-on-the-fly-button mr-1"
47
48
  variant="text"
48
49
  @click="openDialog"
49
50
  >
@@ -53,12 +54,16 @@ const emit = defineEmits(['created'])
53
54
  </v-tooltip>
54
55
 
55
56
  <crud-dialog
57
+ id="crud-create-on-the-fly-dialog"
58
+ class="crud-create-on-the-fly-dialog"
56
59
  v-model="dialog"
57
60
  :entity="entity"
58
61
  operation="create"
59
62
  :fullscreen="false"
60
63
  >
61
64
  <crud-form
65
+ id="crud-create-on-the-fly-form"
66
+ class="crud-create-on-the-fly-form"
62
67
  :entity="entity"
63
68
  @created="onCreated"
64
69
  @canceled="onCanceled"
@@ -5,12 +5,13 @@ const {t} = useI18n()
5
5
  </script>
6
6
 
7
7
  <template>
8
- <v-tooltip location="top">
8
+ <v-tooltip :id="`${$attrs.id || 'crud-delete-button'}-tooltip`" class="crud-delete-button__tooltip" location="top">
9
9
  <template v-slot:activator="{ props}">
10
10
  <v-btn
11
11
  v-bind="{ ...$attrs, ...props }"
12
12
  icon="mdi-delete"
13
- class="mr-1"
13
+ :id="$attrs.id || 'crud-delete-button'"
14
+ class="crud-delete-button mr-1"
14
15
  variant="text"
15
16
  color="red"
16
17
  >
@@ -16,14 +16,15 @@ const {
16
16
  </script>
17
17
 
18
18
  <template>
19
- <v-menu v-if="entity.isExportable">
19
+ <v-menu v-if="entity.isExportable" id="crud-export-menu" class="crud-export-menu">
20
20
  <template v-slot:activator="{ props: mp }">
21
- <v-tooltip location="top">
21
+ <v-tooltip id="crud-export-button-tooltip" class="crud-export-button__tooltip" location="top">
22
22
  <template v-slot:activator="{ props: tp }">
23
23
  <v-btn
24
24
  v-bind="{...mp, ...tp}"
25
25
  :disabled="exportLoading"
26
- class="mr-1"
26
+ id="crud-export-button"
27
+ class="crud-export-button mr-1"
27
28
  variant="text"
28
29
  :loading="exportLoading"
29
30
  icon="mdi-database-export-outline"
@@ -33,9 +34,9 @@ const {
33
34
  </v-tooltip>
34
35
 
35
36
  </template>
36
- <v-list>
37
- <v-list-item v-for="format in entity.exportFormats" @click="$emit('export', format)">
38
- <v-list-item-title>{{format}}</v-list-item-title>
37
+ <v-list id="crud-export-format-list" class="crud-export-menu__list">
38
+ <v-list-item v-for="format in entity.exportFormats" :id="`crud-export-format-${format}`" class="crud-export-menu__item" @click="$emit('export', format)">
39
+ <v-list-item-title class="crud-export-menu__item-title">{{format}}</v-list-item-title>
39
40
  </v-list-item>
40
41
  </v-list>
41
42
 
@@ -20,13 +20,14 @@ const {t} = useI18n()
20
20
  </script>
21
21
 
22
22
  <template>
23
- <div v-if="entity.dynamicFiltersEnable">
24
- <v-tooltip location="top">
23
+ <div v-if="entity.dynamicFiltersEnable" id="crud-filter-button-wrapper" class="crud-filter-button-wrapper">
24
+ <v-tooltip id="crud-filter-button-tooltip" class="crud-filter-button__tooltip" location="top">
25
25
  <template v-slot:activator="{ props }">
26
26
  <v-btn
27
27
  v-bind="{ ...$attrs, ...props }"
28
28
  :icon="dynamicFiltersEnable ? 'mdi-filter-off' : 'mdi-filter' "
29
- class="mr-1"
29
+ id="crud-filter-button"
30
+ class="crud-filter-button mr-1"
30
31
  variant="text"
31
32
  @click="dynamicFiltersEnable = !dynamicFiltersEnable"
32
33
  >
@@ -66,25 +66,29 @@ const totalCount = computed(() => {
66
66
  </script>
67
67
 
68
68
  <template>
69
- <div>
69
+ <div id="crud-group-by-wrapper" class="crud-group-by-wrapper">
70
70
  <v-btn
71
+ id="crud-group-by-button"
72
+ class="crud-group-by-button"
71
73
  icon
72
74
  variant="text"
73
75
  @click="openDialog"
74
76
  >
75
- <v-icon>mdi-chart-bar</v-icon>
77
+ <v-icon id="crud-group-by-button-icon" class="crud-group-by-button__icon">mdi-chart-bar</v-icon>
76
78
  <v-tooltip activator="parent" location="bottom">
77
79
  {{ t('crud.groupBy.button') }}
78
80
  </v-tooltip>
79
81
  </v-btn>
80
82
 
81
- <v-dialog v-model="dialog" max-width="800" >
82
- <v-card>
83
- <v-card-title class="d-flex align-center">
84
- <v-icon class="mr-2">mdi-chart-bar</v-icon>
83
+ <v-dialog id="crud-group-by-dialog" class="crud-group-by-dialog" v-model="dialog" max-width="800" >
84
+ <v-card id="crud-group-by-card" class="crud-group-by-dialog__card">
85
+ <v-card-title id="crud-group-by-title" class="crud-group-by-dialog__title d-flex align-center">
86
+ <v-icon id="crud-group-by-title-icon" class="crud-group-by-dialog__title-icon mr-2">mdi-chart-bar</v-icon>
85
87
  {{ t('crud.groupBy.title') }}
86
88
  <v-spacer></v-spacer>
87
89
  <v-btn
90
+ id="crud-group-by-close-button"
91
+ class="crud-group-by-dialog__close-button"
88
92
  icon
89
93
  variant="text"
90
94
  @click="resetAndClose"
@@ -96,11 +100,13 @@ const totalCount = computed(() => {
96
100
 
97
101
  <v-divider></v-divider>
98
102
 
99
- <v-card-text>
100
- <crud-active-filters :entity="entity"></crud-active-filters>
103
+ <v-card-text id="crud-group-by-config" class="crud-group-by-dialog__config">
104
+ <crud-active-filters id="crud-group-by-active-filters" class="crud-group-by-dialog__active-filters" :entity="entity"></crud-active-filters>
101
105
  <v-divider></v-divider>
102
106
 
103
107
  <v-select
108
+ id="crud-group-by-fields-select"
109
+ class="crud-group-by-dialog__fields-select"
104
110
  v-model="selectedFields"
105
111
  :items="availableFields"
106
112
  item-title="label"
@@ -116,12 +122,13 @@ const totalCount = computed(() => {
116
122
  <!-- Selector de formato de fecha -->
117
123
  <v-select
118
124
  v-if="hasDateFields"
125
+ id="crud-group-by-date-format-select"
119
126
  v-model="dateFormat"
120
127
  :items="dateFormatOptions"
121
128
  :label="t('crud.groupBy.dateFormatLabel')"
122
129
  density="compact"
123
130
  variant="outlined"
124
- class="mt-4"
131
+ class="crud-group-by-dialog__date-format-select mt-4"
125
132
  :menu-props="{ zIndex: 3000 }"
126
133
  >
127
134
  <template v-slot:prepend-inner>
@@ -134,9 +141,11 @@ const totalCount = computed(() => {
134
141
 
135
142
  <v-divider></v-divider>
136
143
 
137
- <v-card-actions>
144
+ <v-card-actions id="crud-group-by-actions" class="crud-group-by-dialog__actions">
138
145
  <v-spacer></v-spacer>
139
146
  <v-btn
147
+ id="crud-group-by-apply-button"
148
+ class="crud-group-by-dialog__apply-button"
140
149
  color="primary"
141
150
  variant="flat"
142
151
  @click="handleGroupBy"
@@ -148,20 +157,22 @@ const totalCount = computed(() => {
148
157
  </v-card-actions>
149
158
  <v-divider class="mb-4"></v-divider>
150
159
  <!-- Tabla de resultados -->
151
- <v-card-text v-if="groupByData.length > 0">
160
+ <v-card-text v-if="groupByData.length > 0" id="crud-group-by-results" class="crud-group-by-dialog__results">
152
161
 
153
162
 
154
- <div class="d-flex align-center mb-3">
155
- <v-icon class="mr-2">mdi-table</v-icon>
156
- <span class="text-h6">{{ t('crud.groupBy.results') }}</span>
163
+ <div id="crud-group-by-results-header" class="crud-group-by-dialog__results-header d-flex align-center mb-3">
164
+ <v-icon id="crud-group-by-results-icon" class="crud-group-by-dialog__results-icon mr-2">mdi-table</v-icon>
165
+ <span id="crud-group-by-results-title" class="crud-group-by-dialog__results-title text-h6">{{ t('crud.groupBy.results') }}</span>
157
166
  <v-spacer></v-spacer>
158
- <v-chip color="primary" variant="flat" size="small">
167
+ <v-chip id="crud-group-by-total-chip" class="crud-group-by-dialog__total-chip" color="primary" variant="flat" size="small">
159
168
  {{ t('crud.groupBy.total') }}: {{ totalCount }}
160
169
  </v-chip>
161
170
  </div>
162
171
 
163
172
 
164
173
  <v-data-table
174
+ id="crud-group-by-results-table"
175
+ class="crud-group-by-dialog__results-table"
165
176
  :headers="headers"
166
177
  :items="groupByData"
167
178
  density="compact"
@@ -191,7 +202,9 @@ const totalCount = computed(() => {
191
202
  <!-- Formato especial para el count -->
192
203
  <template v-slot:item.count="{ value }">
193
204
  <v-chip color="primary" size="small" variant="flat">
205
+ <span class="crud-group-by-dialog__count-value">
194
206
  {{ value }}
207
+ </span>
195
208
  </v-chip>
196
209
  </template>
197
210
  </v-data-table>