@drax/crud-vue 3.46.0 → 3.48.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 (44) hide show
  1. package/package.json +4 -4
  2. package/src/components/Crud.vue +27 -12
  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 +9 -4
  26. package/src/components/buttons/CrudColumnsButton.vue +22 -8
  27. package/src/components/buttons/CrudCreateButton.vue +9 -4
  28. package/src/components/buttons/CrudCreateOnTheFlyButton.vue +13 -4
  29. package/src/components/buttons/CrudDeleteButton.vue +9 -5
  30. package/src/components/buttons/CrudDialogNextButton.vue +19 -0
  31. package/src/components/buttons/CrudDialogPrevButton.vue +19 -0
  32. package/src/components/buttons/CrudExportButton.vue +13 -8
  33. package/src/components/buttons/CrudFilterButton.vue +10 -5
  34. package/src/components/buttons/CrudGroupByButton.vue +33 -16
  35. package/src/components/buttons/CrudImportButton.vue +16 -10
  36. package/src/components/buttons/CrudOpenRouteFormButton.vue +19 -0
  37. package/src/components/buttons/CrudRefreshButton.vue +9 -4
  38. package/src/components/buttons/CrudSavedQueriesButton.vue +42 -20
  39. package/src/components/buttons/CrudUpdateButton.vue +9 -5
  40. package/src/components/buttons/CrudViewButton.vue +9 -5
  41. package/src/components/combobox/EntityCombobox.vue +4 -0
  42. package/src/config/CrudButtonConfig.ts +104 -0
  43. package/src/cruds/EntityCrud.ts +7 -7
  44. package/src/index.ts +33 -1
@@ -18,19 +18,20 @@ const {
18
18
  <template>
19
19
  <v-card
20
20
  v-if="importListVisible"
21
+ id="crud-import-list"
21
22
  :loading="importLoading"
22
- class="ma-3" density="compact" variant="outlined" color="secondary"
23
+ class="crud-import-list ma-3" density="compact" variant="outlined" color="secondary"
23
24
  >
24
- <v-card-title>
25
+ <v-card-title id="crud-import-list-title" class="crud-import-list__title">
25
26
  {{ t('action.imports') }}
26
27
  </v-card-title>
27
- <v-card-text>
28
- <v-alert v-if="importError" type="error">
28
+ <v-card-text id="crud-import-list-content" class="crud-import-list__content">
29
+ <v-alert v-if="importError" id="crud-import-list-error" class="crud-import-list__error" type="error">
29
30
  {{ t('error.crud.import') }}
30
31
  </v-alert>
31
32
  <template v-else>
32
33
  <slot name="import-table" :importFiles="importFiles">
33
- <v-table density="compact">
34
+ <v-table id="crud-import-list-table" class="crud-import-list__table" density="compact">
34
35
  <thead>
35
36
  <tr>
36
37
  <th> {{t('crud.import.link')}}</th>
@@ -41,17 +42,17 @@ const {
41
42
  </tr>
42
43
  </thead>
43
44
  <tbody>
44
- <tr v-for="importFile in importFiles">
45
- <td>
46
- <a v-if="importFile.url" :href="importFile.url" target="_blank">
45
+ <tr v-for="(importFile, index) in importFiles" :id="`crud-import-list-row-${index}`" class="crud-import-list__row">
46
+ <td class="crud-import-list__url-cell">
47
+ <a v-if="importFile.url" :id="`crud-import-list-link-${index}`" class="crud-import-list__link" :href="importFile.url" target="_blank">
47
48
  {{t('crud.import.report')}}
48
49
  </a>
49
- <span v-else>-</span>
50
+ <span v-else class="crud-import-list__empty-link">-</span>
50
51
  </td>
51
- <td>{{ importFile.rowCount }}</td>
52
- <td>{{ importFile.successCount ?? '-' }}</td>
53
- <td>{{ importFile.errorCount ?? '-' }}</td>
54
- <td>{{ importFile.time }}</td>
52
+ <td class="crud-import-list__row-count-cell">{{ importFile.rowCount }}</td>
53
+ <td class="crud-import-list__success-count-cell">{{ importFile.successCount ?? '-' }}</td>
54
+ <td class="crud-import-list__error-count-cell">{{ importFile.errorCount ?? '-' }}</td>
55
+ <td class="crud-import-list__time-cell">{{ importFile.time }}</td>
55
56
  </tr>
56
57
  </tbody>
57
58
  </v-table>
@@ -59,10 +60,10 @@ const {
59
60
  </template>
60
61
  </v-card-text>
61
62
 
62
- <v-card-actions>
63
+ <v-card-actions id="crud-import-list-actions" class="crud-import-list__actions">
63
64
  <v-spacer></v-spacer>
64
- <v-btn @click="importFiles = []" :loading="importLoading">{{ t('action.clear') }}</v-btn>
65
- <v-btn @click="importListVisible = false">{{ t('action.close') }}</v-btn>
65
+ <v-btn id="crud-import-list-clear-button" class="crud-import-list__clear-button" @click="importFiles = []" :loading="importLoading">{{ t('action.clear') }}</v-btn>
66
+ <v-btn id="crud-import-list-close-button" class="crud-import-list__close-button" @click="importListVisible = false">{{ t('action.close') }}</v-btn>
66
67
  </v-card-actions>
67
68
  </v-card>
68
69
  </template>
@@ -48,6 +48,8 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
48
48
 
49
49
  <template>
50
50
  <v-data-table-server
51
+ :id="`crud-list-table-${entity.name}`"
52
+ class="crud-list-table"
51
53
  :density="entity.tableDensity"
52
54
  :striped="entity.tableStriped"
53
55
  :header-props="entity.headerProps"
@@ -69,25 +71,26 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
69
71
  <template v-slot:no-data>
70
72
  <v-alert
71
73
  v-if="paginationError"
74
+ id="crud-list-pagination-error"
72
75
  variant="tonal"
73
- class="w-100 ma-2"
76
+ class="crud-list-table__pagination-error w-100 ma-2"
74
77
  style="width: 100%; min-width: 100%"
75
78
  prominent
76
79
  type="error"
77
80
  :text="te(paginationError) ? t(paginationError) : paginationError"
78
81
  />
79
- <v-alert v-else variant="tonal" class="w-100 ma-2 " type="info" :text="te('crud.noData') ? t('crud.noData') : 'No data' " />
82
+ <v-alert v-else id="crud-list-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' " />
80
83
  </template>
81
84
 
82
85
  <template v-slot:bottom>
83
- <v-data-table-footer :class="entity.footerClass"
86
+ <v-data-table-footer id="crud-list-footer" :class="['crud-list-table__footer', entity.footerClass]"
84
87
  :items-per-page-options="[5, 10, 20, 50]"
85
88
  ></v-data-table-footer>
86
89
  </template>
87
90
 
88
91
  <template v-slot:top>
89
- <v-toolbar :class="entity.toolbarClass" :density="entity.toolbarDensity">
90
- <v-toolbar-title>
92
+ <v-toolbar id="crud-list-toolbar" :class="['crud-list-table__toolbar', entity.toolbarClass]" :density="entity.toolbarDensity">
93
+ <v-toolbar-title id="crud-list-title" class="crud-list-table__title">
91
94
  {{ te(`${entity.name.toLowerCase()}.crud`) ? t(`${entity.name.toLowerCase()}.crud`) : entity.name }}
92
95
  </v-toolbar-title>
93
96
  <v-spacer></v-spacer>
@@ -96,30 +99,42 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
96
99
  </slot>
97
100
 
98
101
  <crud-import-button
102
+ id="crud-list-import-button"
103
+ class="crud-list-table__import-button"
99
104
  :entity="entity"
100
105
  @import="(file:any, format:any) => $emit('import', file, format)"
101
106
  />
102
107
 
103
108
  <crud-export-button
109
+ id="crud-list-export-button"
110
+ class="crud-list-table__export-button"
104
111
  :entity="entity"
105
112
  @export="(v:any) => $emit('export',v)"
106
113
  />
107
114
 
108
115
  <crud-group-by-button
116
+ id="crud-list-group-by-button"
117
+ class="crud-list-table__group-by-button"
109
118
  v-if="entity.isGroupable"
110
119
  :entity="entity"
111
120
  />
112
121
 
113
122
 
114
123
  <crud-filter-button
124
+ id="crud-list-filter-button"
125
+ class="crud-list-table__filter-button"
115
126
  :entity="entity" />
116
127
 
117
128
  <crud-columns-button
129
+ id="crud-list-columns-button"
130
+ class="crud-list-table__columns-button"
118
131
  v-if="entity.isColumnSelectable"
119
132
  :entity="entity"
120
133
  />
121
134
 
122
135
  <crud-create-button
136
+ id="crud-list-create-button"
137
+ class="crud-list-table__create-button"
123
138
  v-if="entity.isCreatable"
124
139
  :entity="entity"
125
140
  @click="$emit('create')"
@@ -127,32 +142,36 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
127
142
 
128
143
  </v-toolbar>
129
144
 
130
- <crud-export-list :entity="entity">
145
+ <crud-export-list id="crud-list-export-list" class="crud-list-table__export-list" :entity="entity">
131
146
  <template #export-table="{ exportFiles }">
132
147
  <slot name="export-table" :exportFiles="exportFiles" />
133
148
  </template>
134
149
  </crud-export-list>
135
150
 
136
- <crud-import-list :entity="entity">
151
+ <crud-import-list id="crud-list-import-list" class="crud-list-table__import-list" :entity="entity">
137
152
  <template #import-table="{ importFiles }">
138
153
  <slot name="import-table" :importFiles="importFiles" />
139
154
  </template>
140
155
  </crud-import-list>
141
156
 
142
- <v-card variant="flat">
143
- <v-card-text v-if="entity.searchEnable">
157
+ <v-card id="crud-list-controls" class="crud-list-table__controls" variant="flat">
158
+ <v-card-text v-if="entity.searchEnable" id="crud-list-search-section" class="crud-list-table__search-section">
144
159
  <crud-search
160
+ id="crud-list-search"
161
+ class="crud-list-table__search"
145
162
  v-model="search"
146
163
  />
147
164
  </v-card-text>
148
165
 
149
- <v-card-text class="pt-0">
166
+ <v-card-text id="crud-list-filters-section" class="crud-list-table__filters-section pt-0">
150
167
  <slot name="filters" v-bind="{filters}"></slot>
151
168
 
152
- <v-card variant="flat" v-if="!$slots.filters">
169
+ <v-card id="crud-list-default-filters" class="crud-list-table__default-filters" variant="flat" v-if="!$slots.filters">
153
170
 
154
171
  <crud-filters
155
172
  v-if="entity.filtersEnable"
173
+ id="crud-list-filters"
174
+ class="crud-list-table__filters"
156
175
  :entity="entity"
157
176
  v-model="filters"
158
177
  :auto-filter="!entity.filterButtons"
@@ -173,6 +192,8 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
173
192
 
174
193
  <crud-filters-dynamic
175
194
  v-if="entity.dynamicFiltersEnable"
195
+ id="crud-list-dynamic-filters"
196
+ class="crud-list-table__dynamic-filters"
176
197
  :entity="entity"
177
198
  v-model="filters"
178
199
  :auto-filter="!entity.filterButtons"
@@ -182,6 +203,8 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
182
203
  </crud-filters-dynamic>
183
204
 
184
205
  <crud-filters-action v-if="entity.filterButtons"
206
+ id="crud-list-filters-actions"
207
+ class="crud-list-table__filters-actions"
185
208
  :entity="entity"
186
209
  @clearFilter="clearFilters()"
187
210
  @applyFilter="applyFilters()"
@@ -192,7 +215,7 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
192
215
 
193
216
  </v-card>
194
217
 
195
- <v-divider></v-divider>
218
+ <v-divider id="crud-list-toolbar-divider" class="crud-list-table__toolbar-divider"></v-divider>
196
219
 
197
220
 
198
221
 
@@ -213,16 +236,22 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
213
236
 
214
237
  <crud-view-button
215
238
  v-if="entity.isViewable && hasPermission(entity.permissions.view)"
239
+ :id="`crud-list-row-view-button-${index}`"
240
+ class="crud-list-table__row-view-button"
216
241
  @click="$emit('view', item, index)"
217
242
  />
218
243
 
219
244
  <crud-update-button
220
245
  v-if="entity.isEditable && entity.isItemEditable(item) && hasPermission(entity.permissions?.update)"
246
+ :id="`crud-list-row-update-button-${index}`"
247
+ class="crud-list-table__row-update-button"
221
248
  @click="$emit('edit', item, index)"
222
249
  />
223
250
 
224
251
  <crud-delete-button
225
252
  v-if="entity.isDeletable && hasPermission(entity.permissions?.delete)"
253
+ :id="`crud-list-row-delete-button-${index}`"
254
+ class="crud-list-table__row-delete-button"
226
255
  @click="$emit('delete', item, index)"
227
256
  />
228
257
 
@@ -54,45 +54,57 @@ onMounted(() => {
54
54
  </script>
55
55
 
56
56
  <template>
57
- <div v-if="hasPermission(entity.permissions.view)" class="d-flex flex-column h-100 pb-4">
57
+ <div v-if="hasPermission(entity.permissions.view)" :id="`crud-list-gallery-${entity.name}`" class="crud-list-gallery d-flex flex-column h-100 pb-4">
58
58
  <!-- Toolbar -->
59
- <v-toolbar :class="entity.toolbarClass" :density="entity.toolbarDensity" extended>
60
- <v-toolbar-title>
59
+ <v-toolbar id="crud-list-gallery-toolbar" :class="['crud-list-gallery__toolbar', entity.toolbarClass]" :density="entity.toolbarDensity" extended>
60
+ <v-toolbar-title id="crud-list-gallery-title" class="crud-list-gallery__title">
61
61
  {{ te(`${entity.name.toLowerCase()}.crud`) ? t(`${entity.name.toLowerCase()}.crud`) : entity.name }}
62
62
  </v-toolbar-title>
63
63
  <v-spacer></v-spacer>
64
64
  <template v-slot:extension>
65
65
 
66
- <v-row justify="end" class="px-2 border-t-sm" >
66
+ <v-row id="crud-list-gallery-toolbar-actions" justify="end" class="crud-list-gallery__toolbar-actions px-2 border-t-sm" >
67
67
 
68
68
  <slot name="toolbar-left">
69
69
  </slot>
70
70
 
71
71
  <crud-import-button
72
+ id="crud-list-gallery-import-button"
73
+ class="crud-list-gallery__import-button"
72
74
  :entity="entity"
73
75
  @import="(file:any, format:any) => $emit('import', file, format)"
74
76
  />
75
77
 
76
78
  <crud-export-button
79
+ id="crud-list-gallery-export-button"
80
+ class="crud-list-gallery__export-button"
77
81
  :entity="entity"
78
82
  @export="(v:any) => $emit('export',v)"
79
83
  />
80
84
 
81
85
  <crud-group-by-button
82
86
  v-if="entity.isGroupable"
87
+ id="crud-list-gallery-group-by-button"
88
+ class="crud-list-gallery__group-by-button"
83
89
  :entity="entity"
84
90
  />
85
91
 
86
92
  <crud-filter-button
93
+ id="crud-list-gallery-filter-button"
94
+ class="crud-list-gallery__filter-button"
87
95
  :entity="entity" />
88
96
 
89
97
  <crud-columns-button
90
98
  v-if="entity.isColumnSelectable"
99
+ id="crud-list-gallery-columns-button"
100
+ class="crud-list-gallery__columns-button"
91
101
  :entity="entity"
92
102
  />
93
103
 
94
104
  <crud-saved-queries-button
95
105
  v-if="entity.isSavedQueriesEnabled"
106
+ id="crud-list-gallery-saved-queries-button"
107
+ class="crud-list-gallery__saved-queries-button"
96
108
  :entity="entity"
97
109
  />
98
110
 
@@ -101,11 +113,15 @@ onMounted(() => {
101
113
 
102
114
  <crud-refresh-button
103
115
  v-if="entity.isRefreshable !== false"
116
+ id="crud-list-gallery-refresh-button"
117
+ class="crud-list-gallery__refresh-button"
104
118
  @click="doPaginate"
105
119
  />
106
120
 
107
121
  <crud-create-button
108
122
  v-if="entity.isCreatable"
123
+ id="crud-list-gallery-create-button"
124
+ class="crud-list-gallery__create-button"
109
125
  :entity="entity"
110
126
  @click="$emit('create')"
111
127
  />
@@ -121,6 +137,8 @@ onMounted(() => {
121
137
  </v-toolbar>
122
138
 
123
139
  <crud-export-list
140
+ id="crud-list-gallery-export-list"
141
+ class="crud-list-gallery__export-list"
124
142
  :entity="entity"
125
143
  >
126
144
  <template #export-table="{ exportFiles }">
@@ -129,6 +147,8 @@ onMounted(() => {
129
147
  </crud-export-list>
130
148
 
131
149
  <crud-import-list
150
+ id="crud-list-gallery-import-list"
151
+ class="crud-list-gallery__import-list"
132
152
  :entity="entity"
133
153
  >
134
154
  <template #import-table="{ importFiles }">
@@ -136,20 +156,24 @@ onMounted(() => {
136
156
  </template>
137
157
  </crud-import-list>
138
158
 
139
- <v-card variant="flat">
140
- <v-card-text v-if="entity.searchEnable">
159
+ <v-card id="crud-list-gallery-controls" class="crud-list-gallery__controls" variant="flat">
160
+ <v-card-text v-if="entity.searchEnable" id="crud-list-gallery-search-section" class="crud-list-gallery__search-section">
141
161
  <crud-search
162
+ id="crud-list-gallery-search"
163
+ class="crud-list-gallery__search"
142
164
  v-model="search"
143
165
  />
144
166
  </v-card-text>
145
167
 
146
- <v-card-text class="pt-0">
168
+ <v-card-text id="crud-list-gallery-filters-section" class="crud-list-gallery__filters-section pt-0">
147
169
  <slot name="filters" v-bind="{filters}"></slot>
148
170
 
149
- <v-card variant="flat" v-if="!$slots.filters">
171
+ <v-card id="crud-list-gallery-default-filters" class="crud-list-gallery__default-filters" variant="flat" v-if="!$slots.filters">
150
172
 
151
173
  <crud-filters
152
174
  v-if="entity.filtersEnable"
175
+ id="crud-list-gallery-filters"
176
+ class="crud-list-gallery__filters"
153
177
  :entity="entity"
154
178
  v-model="filters"
155
179
  :auto-filter="!entity.filterButtons"
@@ -170,6 +194,8 @@ onMounted(() => {
170
194
 
171
195
  <crud-filters-dynamic
172
196
  v-if="isDynamicFiltersEnable"
197
+ id="crud-list-gallery-dynamic-filters"
198
+ class="crud-list-gallery__dynamic-filters"
173
199
  :entity="entity"
174
200
  v-model="filters"
175
201
  :auto-filter="!entity.filterButtons"
@@ -179,6 +205,8 @@ onMounted(() => {
179
205
  </crud-filters-dynamic>
180
206
 
181
207
  <crud-filters-action v-if="entity.filterButtons"
208
+ id="crud-list-gallery-filters-actions"
209
+ class="crud-list-gallery__filters-actions"
182
210
  :entity="entity"
183
211
  @clearFilter="clearFilters()"
184
212
  @applyFilter="applyFilters()"
@@ -189,44 +217,45 @@ onMounted(() => {
189
217
 
190
218
  </v-card>
191
219
 
192
- <v-divider></v-divider>
220
+ <v-divider id="crud-list-gallery-controls-divider" class="crud-list-gallery__controls-divider"></v-divider>
193
221
 
194
222
  <!-- CONTENT GALLERY -->
195
- <v-container fluid class="flex-grow-1 position-relative pa-4">
196
- <v-overlay :model-value="loading" contained class="align-center justify-center bg-transparent" scrim="transparent"
223
+ <v-container id="crud-list-gallery-content" class="crud-list-gallery__content flex-grow-1 position-relative pa-4" fluid>
224
+ <v-overlay id="crud-list-gallery-loading-overlay" class="crud-list-gallery__loading-overlay align-center justify-center bg-transparent" :model-value="loading" contained scrim="transparent"
197
225
  persistent z-index="4">
198
- <v-progress-circular indeterminate color="primary"></v-progress-circular>
226
+ <v-progress-circular id="crud-list-gallery-loading" class="crud-list-gallery__loading" indeterminate color="primary"></v-progress-circular>
199
227
  </v-overlay>
200
228
 
201
229
  <v-alert
202
230
  v-if="paginationError"
231
+ id="crud-list-gallery-pagination-error"
203
232
  variant="tonal"
204
- class="w-100 mb-4"
233
+ class="crud-list-gallery__pagination-error w-100 mb-4"
205
234
  prominent
206
235
  type="error"
207
236
  :text="te(paginationError) ? t(paginationError) : paginationError"
208
237
  />
209
- <v-alert v-else-if="!loading && items.length === 0" variant="tonal" class="w-100 mb-4" type="info"
238
+ <v-alert v-else-if="!loading && items.length === 0" id="crud-list-gallery-no-data" variant="tonal" class="crud-list-gallery__no-data w-100 mb-4" type="info"
210
239
  :text="te('crud.noData') ? t('crud.noData') : 'No data'"/>
211
240
 
212
241
  <!-- GALLERY GRIDS -->
213
- <v-row v-if="items.length > 0">
214
- <v-col v-for="(item, index) in items" :key="item.id || item.uuid || item.name || Math.random()" cols="12" sm="6" md="4"
242
+ <v-row v-if="items.length > 0" id="crud-list-gallery-grid" class="crud-list-gallery__grid">
243
+ <v-col v-for="(item, index) in items" :id="`crud-list-gallery-item-column-${index}`" class="crud-list-gallery__item-column" :key="item.id || item.uuid || item.name || Math.random()" cols="12" sm="6" md="4"
215
244
  xl="3">
216
245
 
217
246
 
218
- <v-card class="h-100 d-flex flex-column hover-card" elevation="2" border>
247
+ <v-card :id="`crud-list-gallery-item-card-${index}`" class="crud-list-gallery__item-card h-100 d-flex flex-column hover-card" elevation="2" border>
219
248
  <slot name="item" v-bind="{item}">
220
- <v-card-text class="field-grid">
249
+ <v-card-text :id="`crud-list-gallery-item-fields-${index}`" class="crud-list-gallery__item-fields field-grid">
221
250
  <template v-for="header in filteredHeaders.filter(h => h.key !=='actions')" :key="header.key">
222
251
 
223
- <div class="field-label font-weight-regular text-grey-darken-2">
252
+ <div :id="`crud-list-gallery-item-field-label-${index}-${header.key}`" class="crud-list-gallery__item-field-label field-label font-weight-regular text-grey-darken-2">
224
253
  {{
225
254
  te(`${entity.name.toLowerCase()}.${header.key}`) ? t(`${entity.name.toLowerCase()}.${header.key}`) : (header.title || header.key)
226
255
  }}
227
256
  </div>
228
257
 
229
- <div class="field-value font-weight-medium">
258
+ <div :id="`crud-list-gallery-item-field-value-${index}-${header.key}`" class="crud-list-gallery__item-field-value field-value font-weight-medium">
230
259
  <slot v-if="$slots[`item.${header.key}`]" :name="`item.${header.key}`"
231
260
  v-bind="{item, value: item[header.key]}">
232
261
  {{ item[header.key] }}
@@ -240,24 +269,30 @@ onMounted(() => {
240
269
  </v-card-text>
241
270
  </slot>
242
271
 
243
- <v-divider></v-divider>
272
+ <v-divider :id="`crud-list-gallery-item-divider-${index}`" class="crud-list-gallery__item-divider"></v-divider>
244
273
 
245
- <v-card-actions class="bg-grey-lighten-4 py-2 px-4 d-flex justify-end flex-wrap gap-2">
274
+ <v-card-actions :id="`crud-list-gallery-item-actions-${index}`" class="crud-list-gallery__item-actions bg-grey-lighten-4 py-2 px-4 d-flex justify-end flex-wrap gap-2">
246
275
  <slot name="item.actions" v-bind="{item, index}">
247
276
  </slot>
248
277
 
249
278
  <crud-view-button
250
279
  v-if="entity.isViewable && hasPermission(entity.permissions.view)"
280
+ :id="`crud-list-gallery-item-view-button-${index}`"
281
+ class="crud-list-gallery__item-view-button"
251
282
  @click="$emit('view', item, index)"
252
283
  />
253
284
 
254
285
  <crud-update-button
255
286
  v-if="entity.isEditable && entity.isItemEditable(item) && hasPermission(entity.permissions?.update)"
287
+ :id="`crud-list-gallery-item-update-button-${index}`"
288
+ class="crud-list-gallery__item-update-button"
256
289
  @click="$emit('edit', item, index)"
257
290
  />
258
291
 
259
292
  <crud-delete-button
260
293
  v-if="entity.isDeletable && hasPermission(entity.permissions?.delete)"
294
+ :id="`crud-list-gallery-item-delete-button-${index}`"
295
+ class="crud-list-gallery__item-delete-button"
261
296
  @click="$emit('delete', item, index)"
262
297
  />
263
298
  </v-card-actions>
@@ -267,24 +302,27 @@ onMounted(() => {
267
302
  </v-container>
268
303
 
269
304
  <!-- FOOTER WITH ALIGNED PAGINATION -->
270
- <v-divider></v-divider>
271
- <div :class="['d-flex align-center justify-space-between flex-wrap px-4 py-3 bg-surface', entity.footerClass]">
272
- <div class="d-flex align-center mb-2 mb-sm-0">
273
- <span class="text-body-2 mr-2 text-white">{{
305
+ <v-divider id="crud-list-gallery-footer-divider" class="crud-list-gallery__footer-divider"></v-divider>
306
+ <div id="crud-list-gallery-footer" :class="['crud-list-gallery__footer d-flex align-center justify-space-between flex-wrap px-4 py-3 bg-surface', entity.footerClass]">
307
+ <div id="crud-list-gallery-items-per-page" class="crud-list-gallery__items-per-page d-flex align-center mb-2 mb-sm-0">
308
+ <span id="crud-list-gallery-items-per-page-label" class="crud-list-gallery__items-per-page-label text-body-2 mr-2 text-white">{{
274
309
  te('crud.itemsPerPage') ? t('crud.itemsPerPage') : 'Items per page:'
275
310
  }}</span>
276
311
  <v-select
312
+ id="crud-list-gallery-items-per-page-select"
277
313
  v-model="itemsPerPage"
278
314
  :items="[5, 10, 20, 50]"
279
315
  variant="outlined"
280
316
  density="compact"
281
317
  hide-details
282
- class="pagination-select"
318
+ class="crud-list-gallery__items-per-page-select pagination-select"
283
319
  @update:model-value="doPaginate"
284
320
  ></v-select>
285
321
  </div>
286
322
 
287
323
  <v-pagination
324
+ id="crud-list-gallery-pagination"
325
+ class="crud-list-gallery__pagination"
288
326
  v-model="page"
289
327
  :length="Math.ceil(totalItems / itemsPerPage) || 1"
290
328
  :total-visible="5"