@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.
- package/package.json +4 -4
- package/src/components/Crud.vue +27 -12
- package/src/components/CrudActiveFilters.vue +11 -9
- package/src/components/CrudAi.vue +38 -25
- package/src/components/CrudAutocomplete.vue +14 -2
- package/src/components/CrudDialog.vue +6 -6
- package/src/components/CrudExportList.vue +13 -12
- package/src/components/CrudFieldRange.vue +8 -4
- package/src/components/CrudFilters.vue +8 -2
- package/src/components/CrudFiltersAction.vue +3 -3
- package/src/components/CrudFiltersDynamic.vue +18 -10
- package/src/components/CrudForm.vue +44 -31
- package/src/components/CrudFormField.vue +48 -8
- package/src/components/CrudFormList.vue +44 -32
- package/src/components/CrudFormRecord.vue +19 -11
- package/src/components/CrudImportList.vue +17 -16
- package/src/components/CrudList.vue +41 -12
- package/src/components/CrudListGallery.vue +65 -27
- package/src/components/CrudListTable.vue +49 -10
- package/src/components/CrudNotify.vue +3 -1
- package/src/components/CrudRefDisplay.vue +2 -2
- package/src/components/CrudRouteForm.vue +8 -4
- package/src/components/CrudRowValue.vue +9 -8
- package/src/components/CrudSearch.vue +2 -1
- package/src/components/buttons/CrudAiButton.vue +9 -4
- package/src/components/buttons/CrudColumnsButton.vue +22 -8
- package/src/components/buttons/CrudCreateButton.vue +9 -4
- package/src/components/buttons/CrudCreateOnTheFlyButton.vue +13 -4
- package/src/components/buttons/CrudDeleteButton.vue +9 -5
- package/src/components/buttons/CrudDialogNextButton.vue +19 -0
- package/src/components/buttons/CrudDialogPrevButton.vue +19 -0
- package/src/components/buttons/CrudExportButton.vue +13 -8
- package/src/components/buttons/CrudFilterButton.vue +10 -5
- package/src/components/buttons/CrudGroupByButton.vue +33 -16
- package/src/components/buttons/CrudImportButton.vue +16 -10
- package/src/components/buttons/CrudOpenRouteFormButton.vue +19 -0
- package/src/components/buttons/CrudRefreshButton.vue +9 -4
- package/src/components/buttons/CrudSavedQueriesButton.vue +42 -20
- package/src/components/buttons/CrudUpdateButton.vue +9 -5
- package/src/components/buttons/CrudViewButton.vue +9 -5
- package/src/components/combobox/EntityCombobox.vue +4 -0
- package/src/config/CrudButtonConfig.ts +104 -0
- package/src/cruds/EntityCrud.ts +7 -7
- package/src/index.ts +33 -1
|
@@ -6,8 +6,10 @@ import { useDateFormat } from "@drax/common-vue"
|
|
|
6
6
|
import { useI18n } from "vue-i18n"
|
|
7
7
|
import { useCrudGroupBy } from '../../composables/UseCrudGroupBy'
|
|
8
8
|
import CrudActiveFilters from "../CrudActiveFilters.vue";
|
|
9
|
+
import { useCrudButtonConfig } from "../../config/CrudButtonConfig";
|
|
9
10
|
|
|
10
11
|
const { t, te } = useI18n()
|
|
12
|
+
const buttonConfig = useCrudButtonConfig("groupBy")
|
|
11
13
|
|
|
12
14
|
const {formatDateByUnit} = useDateFormat()
|
|
13
15
|
|
|
@@ -66,25 +68,31 @@ const totalCount = computed(() => {
|
|
|
66
68
|
</script>
|
|
67
69
|
|
|
68
70
|
<template>
|
|
69
|
-
<div>
|
|
71
|
+
<div id="crud-group-by-wrapper" class="crud-group-by-wrapper">
|
|
70
72
|
<v-btn
|
|
73
|
+
id="crud-group-by-button"
|
|
74
|
+
class="crud-group-by-button mr-1"
|
|
71
75
|
icon
|
|
72
|
-
variant="
|
|
76
|
+
:variant="buttonConfig.variant"
|
|
77
|
+
:rounded="buttonConfig.rounded"
|
|
78
|
+
:color="buttonConfig.color"
|
|
73
79
|
@click="openDialog"
|
|
74
80
|
>
|
|
75
|
-
<v-icon
|
|
81
|
+
<v-icon id="crud-group-by-button-icon" class="crud-group-by-button__icon">{{ buttonConfig.icon }}</v-icon>
|
|
76
82
|
<v-tooltip activator="parent" location="bottom">
|
|
77
83
|
{{ t('crud.groupBy.button') }}
|
|
78
84
|
</v-tooltip>
|
|
79
85
|
</v-btn>
|
|
80
86
|
|
|
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>
|
|
87
|
+
<v-dialog id="crud-group-by-dialog" class="crud-group-by-dialog" v-model="dialog" max-width="800" >
|
|
88
|
+
<v-card id="crud-group-by-card" class="crud-group-by-dialog__card">
|
|
89
|
+
<v-card-title id="crud-group-by-title" class="crud-group-by-dialog__title d-flex align-center">
|
|
90
|
+
<v-icon id="crud-group-by-title-icon" class="crud-group-by-dialog__title-icon mr-2">mdi-chart-bar</v-icon>
|
|
85
91
|
{{ t('crud.groupBy.title') }}
|
|
86
92
|
<v-spacer></v-spacer>
|
|
87
93
|
<v-btn
|
|
94
|
+
id="crud-group-by-close-button"
|
|
95
|
+
class="crud-group-by-dialog__close-button"
|
|
88
96
|
icon
|
|
89
97
|
variant="text"
|
|
90
98
|
@click="resetAndClose"
|
|
@@ -96,11 +104,13 @@ const totalCount = computed(() => {
|
|
|
96
104
|
|
|
97
105
|
<v-divider></v-divider>
|
|
98
106
|
|
|
99
|
-
<v-card-text>
|
|
100
|
-
<crud-active-filters :entity="entity"></crud-active-filters>
|
|
107
|
+
<v-card-text id="crud-group-by-config" class="crud-group-by-dialog__config">
|
|
108
|
+
<crud-active-filters id="crud-group-by-active-filters" class="crud-group-by-dialog__active-filters" :entity="entity"></crud-active-filters>
|
|
101
109
|
<v-divider></v-divider>
|
|
102
110
|
|
|
103
111
|
<v-select
|
|
112
|
+
id="crud-group-by-fields-select"
|
|
113
|
+
class="crud-group-by-dialog__fields-select"
|
|
104
114
|
v-model="selectedFields"
|
|
105
115
|
:items="availableFields"
|
|
106
116
|
item-title="label"
|
|
@@ -116,12 +126,13 @@ const totalCount = computed(() => {
|
|
|
116
126
|
<!-- Selector de formato de fecha -->
|
|
117
127
|
<v-select
|
|
118
128
|
v-if="hasDateFields"
|
|
129
|
+
id="crud-group-by-date-format-select"
|
|
119
130
|
v-model="dateFormat"
|
|
120
131
|
:items="dateFormatOptions"
|
|
121
132
|
:label="t('crud.groupBy.dateFormatLabel')"
|
|
122
133
|
density="compact"
|
|
123
134
|
variant="outlined"
|
|
124
|
-
class="mt-4"
|
|
135
|
+
class="crud-group-by-dialog__date-format-select mt-4"
|
|
125
136
|
:menu-props="{ zIndex: 3000 }"
|
|
126
137
|
>
|
|
127
138
|
<template v-slot:prepend-inner>
|
|
@@ -134,9 +145,11 @@ const totalCount = computed(() => {
|
|
|
134
145
|
|
|
135
146
|
<v-divider></v-divider>
|
|
136
147
|
|
|
137
|
-
<v-card-actions>
|
|
148
|
+
<v-card-actions id="crud-group-by-actions" class="crud-group-by-dialog__actions">
|
|
138
149
|
<v-spacer></v-spacer>
|
|
139
150
|
<v-btn
|
|
151
|
+
id="crud-group-by-apply-button"
|
|
152
|
+
class="crud-group-by-dialog__apply-button"
|
|
140
153
|
color="primary"
|
|
141
154
|
variant="flat"
|
|
142
155
|
@click="handleGroupBy"
|
|
@@ -148,20 +161,22 @@ const totalCount = computed(() => {
|
|
|
148
161
|
</v-card-actions>
|
|
149
162
|
<v-divider class="mb-4"></v-divider>
|
|
150
163
|
<!-- Tabla de resultados -->
|
|
151
|
-
<v-card-text v-if="groupByData.length > 0">
|
|
164
|
+
<v-card-text v-if="groupByData.length > 0" id="crud-group-by-results" class="crud-group-by-dialog__results">
|
|
152
165
|
|
|
153
166
|
|
|
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>
|
|
167
|
+
<div id="crud-group-by-results-header" class="crud-group-by-dialog__results-header d-flex align-center mb-3">
|
|
168
|
+
<v-icon id="crud-group-by-results-icon" class="crud-group-by-dialog__results-icon mr-2">mdi-table</v-icon>
|
|
169
|
+
<span id="crud-group-by-results-title" class="crud-group-by-dialog__results-title text-h6">{{ t('crud.groupBy.results') }}</span>
|
|
157
170
|
<v-spacer></v-spacer>
|
|
158
|
-
<v-chip color="primary" variant="flat" size="small">
|
|
171
|
+
<v-chip id="crud-group-by-total-chip" class="crud-group-by-dialog__total-chip" color="primary" variant="flat" size="small">
|
|
159
172
|
{{ t('crud.groupBy.total') }}: {{ totalCount }}
|
|
160
173
|
</v-chip>
|
|
161
174
|
</div>
|
|
162
175
|
|
|
163
176
|
|
|
164
177
|
<v-data-table
|
|
178
|
+
id="crud-group-by-results-table"
|
|
179
|
+
class="crud-group-by-dialog__results-table"
|
|
165
180
|
:headers="headers"
|
|
166
181
|
:items="groupByData"
|
|
167
182
|
density="compact"
|
|
@@ -191,7 +206,9 @@ const totalCount = computed(() => {
|
|
|
191
206
|
<!-- Formato especial para el count -->
|
|
192
207
|
<template v-slot:item.count="{ value }">
|
|
193
208
|
<v-chip color="primary" size="small" variant="flat">
|
|
209
|
+
<span class="crud-group-by-dialog__count-value">
|
|
194
210
|
{{ value }}
|
|
211
|
+
</span>
|
|
195
212
|
</v-chip>
|
|
196
213
|
</template>
|
|
197
214
|
</v-data-table>
|
|
@@ -4,8 +4,10 @@ import type {PropType} from "vue";
|
|
|
4
4
|
import type {IEntityCrud} from "@drax/crud-share"
|
|
5
5
|
import {useCrud} from "../../composables/UseCrud";
|
|
6
6
|
import {useI18n} from "vue-i18n";
|
|
7
|
+
import {useCrudButtonConfig} from "../../config/CrudButtonConfig";
|
|
7
8
|
|
|
8
9
|
const {t} = useI18n()
|
|
10
|
+
const buttonConfig = useCrudButtonConfig("import")
|
|
9
11
|
const {entity} = defineProps({
|
|
10
12
|
entity: {type: Object as PropType<IEntityCrud>, required: true},
|
|
11
13
|
})
|
|
@@ -37,33 +39,37 @@ function onFileChange(event: Event) {
|
|
|
37
39
|
</script>
|
|
38
40
|
|
|
39
41
|
<template>
|
|
40
|
-
<div v-if="entity.isImportable">
|
|
42
|
+
<div v-if="entity.isImportable" id="crud-import-button-wrapper" class="crud-import-button-wrapper">
|
|
41
43
|
<input
|
|
42
44
|
ref="fileInput"
|
|
43
|
-
|
|
45
|
+
id="crud-import-file-input"
|
|
46
|
+
class="crud-import-button__file-input d-none"
|
|
44
47
|
type="file"
|
|
45
48
|
:accept="entity.importFormats.includes('CSV') && entity.importFormats.includes('JSON') ? '.csv,.json,application/json,text/csv' : entity.importFormats.includes('CSV') ? '.csv,text/csv' : '.json,application/json'"
|
|
46
49
|
@change="onFileChange"
|
|
47
50
|
/>
|
|
48
|
-
<v-menu>
|
|
51
|
+
<v-menu id="crud-import-menu" class="crud-import-menu">
|
|
49
52
|
<template v-slot:activator="{ props: mp }">
|
|
50
|
-
<v-tooltip location="top">
|
|
53
|
+
<v-tooltip id="crud-import-button-tooltip" class="crud-import-button__tooltip" location="top">
|
|
51
54
|
<template v-slot:activator="{ props }">
|
|
52
55
|
<v-btn
|
|
53
56
|
v-bind="{...mp, ...props}"
|
|
54
57
|
:disabled="importLoading"
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
id="crud-import-button"
|
|
59
|
+
class="crud-import-button mr-1"
|
|
60
|
+
:variant="buttonConfig.variant"
|
|
61
|
+
:rounded="buttonConfig.rounded"
|
|
62
|
+
:color="buttonConfig.color"
|
|
57
63
|
:loading="importLoading"
|
|
58
|
-
icon="
|
|
64
|
+
:icon="buttonConfig.icon"
|
|
59
65
|
></v-btn>
|
|
60
66
|
</template>
|
|
61
67
|
{{ t('action.import')}}
|
|
62
68
|
</v-tooltip>
|
|
63
69
|
</template>
|
|
64
|
-
<v-list>
|
|
65
|
-
<v-list-item v-for="format in entity.importFormats" @click="selectFormat(format)">
|
|
66
|
-
<v-list-item-title>{{ format }}</v-list-item-title>
|
|
70
|
+
<v-list id="crud-import-format-list" class="crud-import-menu__list">
|
|
71
|
+
<v-list-item v-for="format in entity.importFormats" :id="`crud-import-format-${format}`" class="crud-import-menu__item" @click="selectFormat(format)">
|
|
72
|
+
<v-list-item-title class="crud-import-menu__item-title">{{ format }}</v-list-item-title>
|
|
67
73
|
</v-list-item>
|
|
68
74
|
</v-list>
|
|
69
75
|
</v-menu>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {useCrudButtonConfig} from "../../config/CrudButtonConfig";
|
|
3
|
+
|
|
4
|
+
defineOptions({inheritAttrs: false})
|
|
5
|
+
|
|
6
|
+
const buttonConfig = useCrudButtonConfig("openRouteForm")
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<v-btn
|
|
11
|
+
v-bind="$attrs"
|
|
12
|
+
:id="$attrs.id || 'crud-open-route-form-button'"
|
|
13
|
+
class="crud-open-route-form-button"
|
|
14
|
+
:icon="buttonConfig.icon"
|
|
15
|
+
:variant="buttonConfig.variant"
|
|
16
|
+
:rounded="buttonConfig.rounded"
|
|
17
|
+
:color="buttonConfig.color"
|
|
18
|
+
/>
|
|
19
|
+
</template>
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import {useI18n} from "vue-i18n";
|
|
3
|
+
import {useCrudButtonConfig} from "../../config/CrudButtonConfig";
|
|
3
4
|
|
|
4
5
|
const {t} = useI18n()
|
|
6
|
+
const buttonConfig = useCrudButtonConfig("refresh")
|
|
5
7
|
</script>
|
|
6
8
|
|
|
7
9
|
<template>
|
|
8
|
-
<v-tooltip location="top">
|
|
10
|
+
<v-tooltip :id="`${$attrs.id || 'crud-refresh-button'}-tooltip`" class="crud-refresh-button__tooltip" location="top">
|
|
9
11
|
<template v-slot:activator="{ props }">
|
|
10
12
|
<v-btn
|
|
11
13
|
v-bind="{ ...$attrs, ...props }"
|
|
12
|
-
icon="
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
:icon="buttonConfig.icon"
|
|
15
|
+
:id="$attrs.id || 'crud-refresh-button'"
|
|
16
|
+
class="crud-refresh-button mr-1"
|
|
17
|
+
:variant="buttonConfig.variant"
|
|
18
|
+
:rounded="buttonConfig.rounded"
|
|
19
|
+
:color="buttonConfig.color"
|
|
15
20
|
>
|
|
16
21
|
</v-btn>
|
|
17
22
|
</template>
|
|
@@ -8,10 +8,12 @@ import {useCrudColumns} from "../../composables/UseCrudColumns";
|
|
|
8
8
|
import {CrudSavedQueryProvider} from "@drax/crud-front";
|
|
9
9
|
import {useAuth, useAuthStore} from "@drax/identity-vue";
|
|
10
10
|
import {createCrudFilterValue} from "../../helpers/CrudRangeFilters";
|
|
11
|
+
import {useCrudButtonConfig} from "../../config/CrudButtonConfig";
|
|
11
12
|
|
|
12
13
|
const {t, te} = useI18n();
|
|
13
14
|
const {hasPermission} = useAuth();
|
|
14
15
|
const authStore = useAuthStore();
|
|
16
|
+
const buttonConfig = useCrudButtonConfig("savedQueries");
|
|
15
17
|
|
|
16
18
|
const props = defineProps({
|
|
17
19
|
entity: {type: Object as PropType<IEntityCrud>, required: true},
|
|
@@ -216,6 +218,8 @@ function onMenuUpdate(value: boolean) {
|
|
|
216
218
|
<template>
|
|
217
219
|
<v-menu
|
|
218
220
|
v-if="canViewSavedQueries"
|
|
221
|
+
id="crud-saved-queries-menu"
|
|
222
|
+
class="crud-saved-queries-menu"
|
|
219
223
|
:model-value="menu"
|
|
220
224
|
offset-y
|
|
221
225
|
:close-on-content-click="false"
|
|
@@ -224,21 +228,27 @@ function onMenuUpdate(value: boolean) {
|
|
|
224
228
|
<template #activator="{ props: activatorProps }">
|
|
225
229
|
<v-btn
|
|
226
230
|
v-bind="activatorProps"
|
|
231
|
+
id="crud-saved-queries-button"
|
|
232
|
+
class="crud-saved-queries-button mr-1"
|
|
227
233
|
icon
|
|
228
|
-
variant="
|
|
234
|
+
:variant="buttonConfig.variant"
|
|
235
|
+
:rounded="buttonConfig.rounded"
|
|
236
|
+
:color="buttonConfig.color"
|
|
229
237
|
>
|
|
230
|
-
<v-icon
|
|
238
|
+
<v-icon id="crud-saved-queries-button-icon" class="crud-saved-queries-button__icon">{{ buttonConfig.icon }}</v-icon>
|
|
231
239
|
<v-tooltip activator="parent" location="bottom">
|
|
232
240
|
{{ title }}
|
|
233
241
|
</v-tooltip>
|
|
234
242
|
</v-btn>
|
|
235
243
|
</template>
|
|
236
244
|
|
|
237
|
-
<v-list min-width="280">
|
|
238
|
-
<v-list-subheader>{{ title }}</v-list-subheader>
|
|
245
|
+
<v-list id="crud-saved-queries-list" class="crud-saved-queries-menu__list" min-width="280">
|
|
246
|
+
<v-list-subheader id="crud-saved-queries-title" class="crud-saved-queries-menu__title">{{ title }}</v-list-subheader>
|
|
239
247
|
|
|
240
248
|
<v-list-item
|
|
241
249
|
v-if="canCreateSavedQueries"
|
|
250
|
+
id="crud-saved-queries-save-item"
|
|
251
|
+
class="crud-saved-queries-menu__save-item"
|
|
242
252
|
@click="openSaveDialog"
|
|
243
253
|
>
|
|
244
254
|
<template #prepend>
|
|
@@ -249,17 +259,19 @@ function onMenuUpdate(value: boolean) {
|
|
|
249
259
|
|
|
250
260
|
<v-divider />
|
|
251
261
|
|
|
252
|
-
<v-list-item v-if="loading">
|
|
253
|
-
<v-progress-linear indeterminate />
|
|
262
|
+
<v-list-item v-if="loading" id="crud-saved-queries-loading-item" class="crud-saved-queries-menu__loading-item">
|
|
263
|
+
<v-progress-linear id="crud-saved-queries-loading" class="crud-saved-queries-menu__loading" indeterminate />
|
|
254
264
|
</v-list-item>
|
|
255
265
|
|
|
256
|
-
<v-list-item v-else-if="savedQueries.length === 0">
|
|
257
|
-
<v-list-item-title class="text-medium-emphasis">{{ noQueriesText }}</v-list-item-title>
|
|
266
|
+
<v-list-item v-else-if="savedQueries.length === 0" id="crud-saved-queries-empty-item" class="crud-saved-queries-menu__empty-item">
|
|
267
|
+
<v-list-item-title class="crud-saved-queries-menu__empty-title text-medium-emphasis">{{ noQueriesText }}</v-list-item-title>
|
|
258
268
|
</v-list-item>
|
|
259
269
|
|
|
260
270
|
<v-list-item
|
|
261
271
|
v-for="query in savedQueries"
|
|
262
272
|
:key="query._id"
|
|
273
|
+
:id="`crud-saved-query-${query._id}`"
|
|
274
|
+
class="crud-saved-queries-menu__query-item"
|
|
263
275
|
@click="applyQuery(query)"
|
|
264
276
|
>
|
|
265
277
|
<template #prepend>
|
|
@@ -269,6 +281,8 @@ function onMenuUpdate(value: boolean) {
|
|
|
269
281
|
<template #append>
|
|
270
282
|
<v-btn
|
|
271
283
|
v-if="canDeleteQuery(query)"
|
|
284
|
+
:id="`crud-saved-query-delete-${query._id}`"
|
|
285
|
+
class="crud-saved-queries-menu__delete-button"
|
|
272
286
|
icon
|
|
273
287
|
variant="text"
|
|
274
288
|
color="red"
|
|
@@ -285,11 +299,13 @@ function onMenuUpdate(value: boolean) {
|
|
|
285
299
|
</v-list>
|
|
286
300
|
</v-menu>
|
|
287
301
|
|
|
288
|
-
<v-dialog v-model="saveDialog" max-width="460">
|
|
289
|
-
<v-card>
|
|
290
|
-
<v-card-title>{{ saveTitle }}</v-card-title>
|
|
291
|
-
<v-card-text>
|
|
302
|
+
<v-dialog id="crud-saved-query-save-dialog" class="crud-saved-query-save-dialog" v-model="saveDialog" max-width="460">
|
|
303
|
+
<v-card id="crud-saved-query-save-card" class="crud-saved-query-save-dialog__card">
|
|
304
|
+
<v-card-title id="crud-saved-query-save-title" class="crud-saved-query-save-dialog__title">{{ saveTitle }}</v-card-title>
|
|
305
|
+
<v-card-text id="crud-saved-query-save-content" class="crud-saved-query-save-dialog__content">
|
|
292
306
|
<v-text-field
|
|
307
|
+
id="crud-saved-query-name-field"
|
|
308
|
+
class="crud-saved-query-save-dialog__name-field"
|
|
293
309
|
v-model="form.name"
|
|
294
310
|
:label="te('crud.savedQueries.name') ? t('crud.savedQueries.name') : 'Name'"
|
|
295
311
|
density="compact"
|
|
@@ -297,18 +313,22 @@ function onMenuUpdate(value: boolean) {
|
|
|
297
313
|
autofocus
|
|
298
314
|
/>
|
|
299
315
|
<v-switch
|
|
316
|
+
id="crud-saved-query-shared-switch"
|
|
317
|
+
class="crud-saved-query-save-dialog__shared-switch"
|
|
300
318
|
v-model="form.shared"
|
|
301
319
|
:label="te('crud.savedQueries.shared') ? t('crud.savedQueries.shared') : 'Shared'"
|
|
302
320
|
color="primary"
|
|
303
321
|
hide-details
|
|
304
322
|
/>
|
|
305
323
|
</v-card-text>
|
|
306
|
-
<v-card-actions>
|
|
324
|
+
<v-card-actions id="crud-saved-query-save-actions" class="crud-saved-query-save-dialog__actions">
|
|
307
325
|
<v-spacer />
|
|
308
|
-
<v-btn variant="text" @click="saveDialog = false">
|
|
326
|
+
<v-btn id="crud-saved-query-save-cancel-button" class="crud-saved-query-save-dialog__cancel-button" variant="text" @click="saveDialog = false">
|
|
309
327
|
{{ te('action.cancel') ? t('action.cancel') : 'Cancel' }}
|
|
310
328
|
</v-btn>
|
|
311
329
|
<v-btn
|
|
330
|
+
id="crud-saved-query-save-submit-button"
|
|
331
|
+
class="crud-saved-query-save-dialog__submit-button"
|
|
312
332
|
color="primary"
|
|
313
333
|
variant="flat"
|
|
314
334
|
:loading="saving"
|
|
@@ -321,18 +341,20 @@ function onMenuUpdate(value: boolean) {
|
|
|
321
341
|
</v-card>
|
|
322
342
|
</v-dialog>
|
|
323
343
|
|
|
324
|
-
<v-dialog v-model="deleteDialog" max-width="460">
|
|
325
|
-
<v-card>
|
|
326
|
-
<v-card-title>{{ deleteTitle }}</v-card-title>
|
|
327
|
-
<v-card-text>
|
|
344
|
+
<v-dialog id="crud-saved-query-delete-dialog" class="crud-saved-query-delete-dialog" v-model="deleteDialog" max-width="460">
|
|
345
|
+
<v-card id="crud-saved-query-delete-card" class="crud-saved-query-delete-dialog__card">
|
|
346
|
+
<v-card-title id="crud-saved-query-delete-title" class="crud-saved-query-delete-dialog__title">{{ deleteTitle }}</v-card-title>
|
|
347
|
+
<v-card-text id="crud-saved-query-delete-content" class="crud-saved-query-delete-dialog__content">
|
|
328
348
|
{{ deleteConfirmText }}
|
|
329
349
|
</v-card-text>
|
|
330
|
-
<v-card-actions>
|
|
350
|
+
<v-card-actions id="crud-saved-query-delete-actions" class="crud-saved-query-delete-dialog__actions">
|
|
331
351
|
<v-spacer />
|
|
332
|
-
<v-btn variant="text" @click="deleteDialog = false">
|
|
352
|
+
<v-btn id="crud-saved-query-delete-cancel-button" class="crud-saved-query-delete-dialog__cancel-button" variant="text" @click="deleteDialog = false">
|
|
333
353
|
{{ te('action.cancel') ? t('action.cancel') : 'Cancel' }}
|
|
334
354
|
</v-btn>
|
|
335
355
|
<v-btn
|
|
356
|
+
id="crud-saved-query-delete-confirm-button"
|
|
357
|
+
class="crud-saved-query-delete-dialog__confirm-button"
|
|
336
358
|
color="red"
|
|
337
359
|
variant="flat"
|
|
338
360
|
:loading="deleting"
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import {useI18n} from "vue-i18n";
|
|
3
|
+
import {useCrudButtonConfig} from "../../config/CrudButtonConfig";
|
|
3
4
|
const {t} = useI18n()
|
|
5
|
+
const buttonConfig = useCrudButtonConfig("update")
|
|
4
6
|
</script>
|
|
5
7
|
|
|
6
8
|
<template>
|
|
7
|
-
<v-tooltip location="top">
|
|
9
|
+
<v-tooltip :id="`${$attrs.id || 'crud-update-button'}-tooltip`" class="crud-update-button__tooltip" location="top">
|
|
8
10
|
<template v-slot:activator="{ props}">
|
|
9
11
|
<v-btn
|
|
10
12
|
v-bind="{ ...$attrs, ...props }"
|
|
11
|
-
icon="
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
:icon="buttonConfig.icon"
|
|
14
|
+
:id="$attrs.id || 'crud-update-button'"
|
|
15
|
+
class="crud-update-button mr-1"
|
|
16
|
+
:variant="buttonConfig.variant"
|
|
17
|
+
:rounded="buttonConfig.rounded"
|
|
18
|
+
:color="buttonConfig.color"
|
|
15
19
|
slim
|
|
16
20
|
>
|
|
17
21
|
</v-btn>
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import {useI18n} from "vue-i18n";
|
|
3
|
+
import {useCrudButtonConfig} from "../../config/CrudButtonConfig";
|
|
3
4
|
const {t} = useI18n()
|
|
5
|
+
const buttonConfig = useCrudButtonConfig("view")
|
|
4
6
|
</script>
|
|
5
7
|
|
|
6
8
|
<template>
|
|
7
|
-
<v-tooltip location="top">
|
|
9
|
+
<v-tooltip :id="`${$attrs.id || 'crud-view-button'}-tooltip`" class="crud-view-button__tooltip" location="top">
|
|
8
10
|
<template v-slot:activator="{ props}">
|
|
9
11
|
<v-btn
|
|
10
12
|
v-bind="{ ...$attrs, ...props }"
|
|
11
|
-
icon="
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
:icon="buttonConfig.icon"
|
|
14
|
+
:id="$attrs.id || 'crud-view-button'"
|
|
15
|
+
class="crud-view-button mr-1"
|
|
16
|
+
:variant="buttonConfig.variant"
|
|
17
|
+
:rounded="buttonConfig.rounded"
|
|
18
|
+
:color="buttonConfig.color"
|
|
15
19
|
slim
|
|
16
20
|
>
|
|
17
21
|
</v-btn>
|
|
@@ -17,6 +17,8 @@ const getEntityLabel = (entity: IEntityCrud) => {
|
|
|
17
17
|
<template>
|
|
18
18
|
|
|
19
19
|
<v-select
|
|
20
|
+
id="entity-combobox"
|
|
21
|
+
class="entity-combobox"
|
|
20
22
|
:items="entityStore.entities"
|
|
21
23
|
item-value="name"
|
|
22
24
|
v-model="valueModel"
|
|
@@ -28,6 +30,8 @@ const getEntityLabel = (entity: IEntityCrud) => {
|
|
|
28
30
|
<template v-slot:item="{ props: itemProps, item }">
|
|
29
31
|
<v-list-item
|
|
30
32
|
v-bind="itemProps"
|
|
33
|
+
:id="`entity-combobox-item-${(item.raw as IEntityCrud).name}`"
|
|
34
|
+
class="entity-combobox__item"
|
|
31
35
|
density="compact"
|
|
32
36
|
:title="getEntityLabel(item.raw as IEntityCrud)"
|
|
33
37
|
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import {computed, reactive} from "vue";
|
|
2
|
+
|
|
3
|
+
export type CrudButtonName =
|
|
4
|
+
"ai"
|
|
5
|
+
| "columns"
|
|
6
|
+
| "create"
|
|
7
|
+
| "createOnTheFly"
|
|
8
|
+
| "delete"
|
|
9
|
+
| "dialogNext"
|
|
10
|
+
| "dialogPrev"
|
|
11
|
+
| "export"
|
|
12
|
+
| "filter"
|
|
13
|
+
| "groupBy"
|
|
14
|
+
| "import"
|
|
15
|
+
| "openRouteForm"
|
|
16
|
+
| "refresh"
|
|
17
|
+
| "savedQueries"
|
|
18
|
+
| "update"
|
|
19
|
+
| "view";
|
|
20
|
+
|
|
21
|
+
export type CrudButtonRounded = boolean | string | number;
|
|
22
|
+
export type CrudButtonVariant = "flat" | "text" | "elevated" | "outlined" | "plain" | "tonal";
|
|
23
|
+
|
|
24
|
+
export interface CrudButtonStyle {
|
|
25
|
+
icon?: string;
|
|
26
|
+
activeIcon?: string;
|
|
27
|
+
variant?: CrudButtonVariant;
|
|
28
|
+
rounded?: CrudButtonRounded;
|
|
29
|
+
color?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type CrudButtonGlobalStyle = Pick<CrudButtonStyle, "variant" | "rounded" | "color">;
|
|
33
|
+
|
|
34
|
+
export type CrudButtonsConfig = {
|
|
35
|
+
defaults?: CrudButtonGlobalStyle;
|
|
36
|
+
buttons?: Partial<Record<CrudButtonName, CrudButtonStyle>>;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const crudButtonDefaultStyles: Record<CrudButtonName, CrudButtonStyle> = {
|
|
40
|
+
ai: {icon: "mdi-robot-outline", variant: "text"},
|
|
41
|
+
columns: {icon: "mdi-view-column", variant: "text"},
|
|
42
|
+
create: {icon: "mdi-plus", variant: "text"},
|
|
43
|
+
createOnTheFly: {icon: "mdi-plus", variant: "text"},
|
|
44
|
+
delete: {icon: "mdi-delete", variant: "text", color: "red"},
|
|
45
|
+
dialogNext: {icon: "mdi-chevron-right", variant: "text"},
|
|
46
|
+
dialogPrev: {icon: "mdi-chevron-left", variant: "text"},
|
|
47
|
+
export: {icon: "mdi-database-export-outline", variant: "text"},
|
|
48
|
+
filter: {icon: "mdi-filter", activeIcon: "mdi-filter-off", variant: "text"},
|
|
49
|
+
groupBy: {icon: "mdi-chart-bar", variant: "text"},
|
|
50
|
+
import: {icon: "mdi-database-import-outline", variant: "text"},
|
|
51
|
+
openRouteForm: {icon: "mdi-open-in-new", variant: "text"},
|
|
52
|
+
refresh: {icon: "mdi-refresh", variant: "text"},
|
|
53
|
+
savedQueries: {icon: "mdi-content-save-cog", variant: "text"},
|
|
54
|
+
update: {icon: "mdi-pencil", variant: "text", color: "blue"},
|
|
55
|
+
view: {icon: "mdi-magnify", variant: "text", color: "teal"},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const crudButtonsConfig = reactive<Required<CrudButtonsConfig>>({
|
|
59
|
+
defaults: {},
|
|
60
|
+
buttons: {},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
export function configureCrudButtons(config: CrudButtonsConfig) {
|
|
64
|
+
if (config.defaults) {
|
|
65
|
+
Object.assign(crudButtonsConfig.defaults, config.defaults);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (config.buttons) {
|
|
69
|
+
Object.entries(config.buttons).forEach(([buttonName, buttonConfig]) => {
|
|
70
|
+
if (!buttonConfig) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const key = buttonName as CrudButtonName;
|
|
75
|
+
crudButtonsConfig.buttons[key] = {
|
|
76
|
+
...(crudButtonsConfig.buttons[key] || {}),
|
|
77
|
+
...buttonConfig,
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function resetCrudButtonsConfig() {
|
|
84
|
+
Object.keys(crudButtonsConfig.defaults).forEach((key) => {
|
|
85
|
+
delete crudButtonsConfig.defaults[key as keyof CrudButtonGlobalStyle];
|
|
86
|
+
});
|
|
87
|
+
Object.keys(crudButtonsConfig.buttons).forEach((key) => {
|
|
88
|
+
delete crudButtonsConfig.buttons[key as CrudButtonName];
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function getCrudButtonConfig(buttonName: CrudButtonName): CrudButtonStyle {
|
|
93
|
+
return {
|
|
94
|
+
...crudButtonDefaultStyles[buttonName],
|
|
95
|
+
...crudButtonsConfig.defaults,
|
|
96
|
+
...(crudButtonsConfig.buttons[buttonName] || {}),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function useCrudButtonConfig(buttonName: CrudButtonName) {
|
|
101
|
+
return computed(() => getCrudButtonConfig(buttonName));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export {crudButtonDefaultStyles, crudButtonsConfig};
|
package/src/cruds/EntityCrud.ts
CHANGED
|
@@ -287,24 +287,24 @@ class EntityCrud implements IEntityCrud {
|
|
|
287
287
|
return false
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
-
get cardDensity(): 'default' | 'comfortable' | 'compact' {
|
|
291
|
-
return
|
|
290
|
+
get cardDensity(): 'default' | 'comfortable' | 'compact' | undefined {
|
|
291
|
+
return undefined
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
get cardClass(): string {
|
|
295
|
-
return '
|
|
295
|
+
return ''
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
-
get toolbarDensity(): 'default' | 'comfortable' | 'compact' {
|
|
299
|
-
return
|
|
298
|
+
get toolbarDensity(): 'default' | 'comfortable' | 'compact' | undefined {
|
|
299
|
+
return undefined
|
|
300
300
|
}
|
|
301
301
|
|
|
302
302
|
get toolbarClass(): string {
|
|
303
303
|
return 'bg-primary'
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
-
get tableDensity(): 'default' | 'comfortable' | 'compact' {
|
|
307
|
-
return
|
|
306
|
+
get tableDensity(): 'default' | 'comfortable' | 'compact' | undefined {
|
|
307
|
+
return undefined
|
|
308
308
|
}
|
|
309
309
|
|
|
310
310
|
get headerProps() {
|