@drax/crud-vue 0.27.0 → 0.29.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 +7 -7
- package/src/EntityCrud.ts +42 -1
- package/src/components/Crud.vue +13 -3
- package/src/components/CrudExportList.vue +5 -2
- package/src/components/CrudFilters.vue +15 -11
- package/src/components/CrudFormField.vue +2 -2
- package/src/components/CrudList.vue +33 -11
- package/src/components/buttons/CrudCreateButton.vue +0 -1
- package/src/components/buttons/CrudUpdateButton.vue +1 -1
- package/src/components/buttons/CrudViewButton.vue +1 -1
- package/src/composables/UseCrud.ts +11 -1
- package/src/stores/UseCrudStore.ts +9 -0
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.29.0",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "./src/index.ts",
|
|
9
9
|
"module": "./src/index.ts",
|
|
@@ -24,16 +24,16 @@
|
|
|
24
24
|
"format": "prettier --write src/"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@drax/common-front": "^0.
|
|
28
|
-
"@drax/crud-front": "^0.
|
|
29
|
-
"@drax/crud-share": "^0.
|
|
30
|
-
"@drax/media-vue": "^0.
|
|
27
|
+
"@drax/common-front": "^0.29.0",
|
|
28
|
+
"@drax/crud-front": "^0.29.0",
|
|
29
|
+
"@drax/crud-share": "^0.29.0",
|
|
30
|
+
"@drax/media-vue": "^0.29.0"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"pinia": "^2.2.2",
|
|
34
34
|
"vue": "^3.5.7",
|
|
35
35
|
"vue-i18n": "^9.14.0",
|
|
36
|
-
"vuetify": "^3.
|
|
36
|
+
"vuetify": "^3.9.2"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@rushstack/eslint-patch": "^1.8.0",
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
"vue-tsc": "^2.1.10",
|
|
65
65
|
"vuetify": "^3.8.2"
|
|
66
66
|
},
|
|
67
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "0a3f69beb23eb8768ebe7a3d41d61d4a6d40b104"
|
|
68
68
|
}
|
package/src/EntityCrud.ts
CHANGED
|
@@ -30,7 +30,8 @@ class EntityCrud implements IEntityCrud {
|
|
|
30
30
|
key: 'actions',
|
|
31
31
|
sortable: false,
|
|
32
32
|
align: 'center',
|
|
33
|
-
minWidth: '190px'
|
|
33
|
+
minWidth: '190px',
|
|
34
|
+
fixed: 'end'
|
|
34
35
|
},
|
|
35
36
|
]
|
|
36
37
|
}
|
|
@@ -169,6 +170,10 @@ class EntityCrud implements IEntityCrud {
|
|
|
169
170
|
return ['_id']
|
|
170
171
|
}
|
|
171
172
|
|
|
173
|
+
get exportFileName(){
|
|
174
|
+
return 'export'
|
|
175
|
+
}
|
|
176
|
+
|
|
172
177
|
get isImportable() {
|
|
173
178
|
return true
|
|
174
179
|
}
|
|
@@ -211,6 +216,42 @@ class EntityCrud implements IEntityCrud {
|
|
|
211
216
|
return true
|
|
212
217
|
}
|
|
213
218
|
|
|
219
|
+
get containerFluid(){
|
|
220
|
+
return false
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
get cardDensity() : 'default' | 'comfortable' | 'compact' {
|
|
224
|
+
return 'default'
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
get cardClass() : string {
|
|
228
|
+
return 'rounded-xl'
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
get toolbarDensity() : 'default' | 'comfortable' | 'compact' {
|
|
232
|
+
return 'default'
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
get toolbarClass() : string {
|
|
236
|
+
return 'bg-primary'
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
get tableDensity() : 'default' | 'comfortable' | 'compact' {
|
|
240
|
+
return 'default'
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
get headerProps(){
|
|
244
|
+
return { class: 'bg-primary' }
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
get tableStriped() : null | 'odd' | 'even' {
|
|
248
|
+
return 'even'
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
get footerClass(){
|
|
252
|
+
return 'bg-primary'
|
|
253
|
+
}
|
|
254
|
+
|
|
214
255
|
|
|
215
256
|
}
|
|
216
257
|
|
package/src/components/Crud.vue
CHANGED
|
@@ -22,14 +22,14 @@ onBeforeMount(() => {
|
|
|
22
22
|
prepareFilters()
|
|
23
23
|
})
|
|
24
24
|
|
|
25
|
-
const emit = defineEmits(['created', 'updated', 'deleted', 'viewed','canceled'])
|
|
25
|
+
const emit = defineEmits(['created', 'updated', 'deleted', 'viewed', 'canceled'])
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
</script>
|
|
29
29
|
|
|
30
30
|
<template>
|
|
31
|
-
<v-container fluid class="mt-5">
|
|
32
|
-
<v-card>
|
|
31
|
+
<v-container :fluid="entity.containerFluid" class="mt-5">
|
|
32
|
+
<v-card :class="entity.cardClass" :density="entity.cardDensity">
|
|
33
33
|
|
|
34
34
|
<crud-list
|
|
35
35
|
:entity="entity"
|
|
@@ -50,6 +50,16 @@ const emit = defineEmits(['created', 'updated', 'deleted', 'viewed','canceled'])
|
|
|
50
50
|
</slot>
|
|
51
51
|
</template>
|
|
52
52
|
|
|
53
|
+
<template v-for="iFilter in entity.filters"
|
|
54
|
+
:key="iFilter.name"
|
|
55
|
+
v-slot:[`filter.${iFilter.name}`]="{filter, filterIndex}"
|
|
56
|
+
>
|
|
57
|
+
<slot v-if="$slots[`filter.${iFilter.name}`]"
|
|
58
|
+
:name="`filter.${iFilter.name}`"
|
|
59
|
+
v-bind="{filter, filterIndex}"
|
|
60
|
+
/>
|
|
61
|
+
</template>
|
|
62
|
+
|
|
53
63
|
<template v-for="header in entity.headers" :key="header.key" v-slot:[`item.${header.key}`]="{item, value}">
|
|
54
64
|
<slot :name="`item.${header.key}`" v-bind="{item, value}">
|
|
55
65
|
{{ (Array.isArray(value) && value.length > 0) || !Array.isArray(value) ? value : '' }}
|
|
@@ -9,7 +9,7 @@ const {entity} = defineProps({
|
|
|
9
9
|
})
|
|
10
10
|
|
|
11
11
|
const {
|
|
12
|
-
exportFiles, exportListVisible, exportLoading
|
|
12
|
+
exportFiles, exportListVisible, exportLoading, exportError
|
|
13
13
|
} = useCrud(entity);
|
|
14
14
|
|
|
15
15
|
</script>
|
|
@@ -25,7 +25,10 @@ const {
|
|
|
25
25
|
|
|
26
26
|
</v-card-title>
|
|
27
27
|
<v-card-text>
|
|
28
|
-
<v-
|
|
28
|
+
<v-alert v-if="exportError" type="error">
|
|
29
|
+
{{ t('export.error.message') }}
|
|
30
|
+
</v-alert>
|
|
31
|
+
<v-table density="compact" v-else>
|
|
29
32
|
<thead>
|
|
30
33
|
<tr>
|
|
31
34
|
<th>Link</th><th>Rows</th><th>Time</th>
|
|
@@ -76,17 +76,21 @@ const emit = defineEmits(['applyFilter', 'clearFilter'])
|
|
|
76
76
|
:lg="filter.lg ? filter.lg : 4"
|
|
77
77
|
:xl="filter.xl ? filter.xl : 3"
|
|
78
78
|
>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
79
|
+
|
|
80
|
+
<slot :name="`filter.${filter.name}`" v-bind="{filter, filterIndex: index}">
|
|
81
|
+
<crud-form-field
|
|
82
|
+
:field="filter"
|
|
83
|
+
:entity="entity"
|
|
84
|
+
v-model="valueModel[index].value"
|
|
85
|
+
:clearable="true"
|
|
86
|
+
density="compact"
|
|
87
|
+
variant="outlined"
|
|
88
|
+
:prepend-inner-icon="icon(filter)"
|
|
89
|
+
hide-details disable-rules
|
|
90
|
+
@updateValue="onUpdateValue"
|
|
91
|
+
/>
|
|
92
|
+
</slot>
|
|
93
|
+
|
|
90
94
|
</v-col>
|
|
91
95
|
|
|
92
96
|
</v-row>
|
|
@@ -308,9 +308,9 @@ defineEmits(['updateValue'])
|
|
|
308
308
|
:append-icon="appendIcon"
|
|
309
309
|
:prepend-inner-icon="prependInnerIcon"
|
|
310
310
|
:append-inner-icon="appendInnerIcon"
|
|
311
|
-
|
|
311
|
+
:max="field.max"
|
|
312
312
|
>
|
|
313
|
-
<template v-if="field.endOfDay" v-slot:append-inner>
|
|
313
|
+
<template v-if="field.endOfDay && field.showEndOfDayChip !== false" v-slot:append-inner>
|
|
314
314
|
<v-chip size="small">23:59</v-chip>
|
|
315
315
|
</template>
|
|
316
316
|
</v-date-input>
|
|
@@ -53,7 +53,9 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
|
|
|
53
53
|
|
|
54
54
|
<template>
|
|
55
55
|
<v-data-table-server
|
|
56
|
-
|
|
56
|
+
:density="entity.tableDensity"
|
|
57
|
+
:striped="entity.tableStriped"
|
|
58
|
+
:header-props="entity.headerProps"
|
|
57
59
|
v-if="hasPermission(entity.permissions.view)"
|
|
58
60
|
v-model:items-per-page="itemsPerPage"
|
|
59
61
|
:items-per-page-options="[5, 10, 20, 50]"
|
|
@@ -68,8 +70,15 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
|
|
|
68
70
|
item-value="name"
|
|
69
71
|
@update:options="doPaginate"
|
|
70
72
|
>
|
|
73
|
+
|
|
74
|
+
<template v-slot:bottom>
|
|
75
|
+
<v-data-table-footer :class="entity.footerClass"
|
|
76
|
+
:items-per-page-options="[5, 10, 20, 50]"
|
|
77
|
+
></v-data-table-footer>
|
|
78
|
+
</template>
|
|
79
|
+
|
|
71
80
|
<template v-slot:top>
|
|
72
|
-
<v-toolbar density="
|
|
81
|
+
<v-toolbar :class="entity.toolbarClass" :density="entity.toolbarDensity">
|
|
73
82
|
<v-toolbar-title>
|
|
74
83
|
{{ te(`${entity.name.toLowerCase()}.crud`) ? t(`${entity.name.toLowerCase()}.crud`) : entity.name }}
|
|
75
84
|
</v-toolbar-title>
|
|
@@ -101,7 +110,7 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
|
|
|
101
110
|
:entity="entity"
|
|
102
111
|
/>
|
|
103
112
|
|
|
104
|
-
<v-card>
|
|
113
|
+
<v-card variant="flat">
|
|
105
114
|
<v-card-text v-if="entity.searchEnable">
|
|
106
115
|
<crud-search
|
|
107
116
|
v-model="search"
|
|
@@ -110,23 +119,36 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
|
|
|
110
119
|
|
|
111
120
|
<v-card-text class="pt-0">
|
|
112
121
|
<slot name="filters" v-bind="{filters}"></slot>
|
|
122
|
+
|
|
113
123
|
<crud-filters
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
124
|
+
v-if="!$slots.filters"
|
|
125
|
+
:entity="entity"
|
|
126
|
+
v-model="filters"
|
|
127
|
+
:action-buttons="entity.filterButtons"
|
|
128
|
+
@clearFilter="clearFilters()"
|
|
129
|
+
@applyFilter="applyFilters()"
|
|
130
|
+
>
|
|
131
|
+
|
|
132
|
+
<template v-for="iFilter in entity.filters"
|
|
133
|
+
:key="iFilter.name"
|
|
134
|
+
v-slot:[`filter.${iFilter.name}`]="{filter, filterIndex}"
|
|
135
|
+
>
|
|
136
|
+
<slot v-if="$slots[`filter.${iFilter.name}`]"
|
|
137
|
+
:name="`filter.${iFilter.name}`"
|
|
138
|
+
v-bind="{filter, filterIndex}"
|
|
139
|
+
/>
|
|
140
|
+
</template>
|
|
141
|
+
</crud-filters>
|
|
121
142
|
</v-card-text>
|
|
122
143
|
|
|
123
144
|
</v-card>
|
|
124
145
|
|
|
146
|
+
<v-divider></v-divider>
|
|
125
147
|
</template>
|
|
126
148
|
|
|
127
149
|
|
|
128
150
|
<template v-for="header in entity.headers" :key="header.key" v-slot:[`item.${header.key}`]="{item, value}">
|
|
129
|
-
<slot :name="`item.${header.key}`" v-bind="{item, value}">
|
|
151
|
+
<slot v-if="$slots[`item.${header.key}`]" :name="`item.${header.key}`" v-bind="{item, value}">
|
|
130
152
|
{{ value }}
|
|
131
153
|
</slot>
|
|
132
154
|
</template>
|
|
@@ -7,6 +7,13 @@ export function useCrud(entity: IEntityCrud) {
|
|
|
7
7
|
|
|
8
8
|
const store = useCrudStore()
|
|
9
9
|
|
|
10
|
+
const exportError = computed({
|
|
11
|
+
get() {
|
|
12
|
+
return store.exportError
|
|
13
|
+
}, set(value) {
|
|
14
|
+
store.setExportError(value)
|
|
15
|
+
}
|
|
16
|
+
})
|
|
10
17
|
|
|
11
18
|
const dialog = computed({
|
|
12
19
|
get() {
|
|
@@ -167,11 +174,13 @@ export function useCrud(entity: IEntityCrud) {
|
|
|
167
174
|
}
|
|
168
175
|
|
|
169
176
|
const headers: string = entity.exportHeaders.join(',')
|
|
177
|
+
const fileName: string = entity.exportFileName
|
|
170
178
|
|
|
171
179
|
const r: any = await entity?.provider.export({
|
|
172
180
|
format: format,
|
|
173
181
|
headers: headers,
|
|
174
182
|
separator: ";",
|
|
183
|
+
fileName: fileName,
|
|
175
184
|
orderBy: store.sortBy[0]?.key,
|
|
176
185
|
order: store.sortBy[0]?.order,
|
|
177
186
|
search: store.search,
|
|
@@ -186,6 +195,7 @@ export function useCrud(entity: IEntityCrud) {
|
|
|
186
195
|
return r
|
|
187
196
|
|
|
188
197
|
} catch (e) {
|
|
198
|
+
store.setExportError(true)
|
|
189
199
|
console.error("Error exporting csv", e)
|
|
190
200
|
} finally {
|
|
191
201
|
store.setExportLoading(false)
|
|
@@ -371,7 +381,7 @@ export function useCrud(entity: IEntityCrud) {
|
|
|
371
381
|
operation, dialog, form, notify, error, message, formValid,
|
|
372
382
|
loading, itemsPerPage, page, sortBy, search, totalItems, items,
|
|
373
383
|
prepareFilters, filters, clearFilters, applyFilters,
|
|
374
|
-
exportFiles, exportLoading, exportListVisible
|
|
384
|
+
exportFiles, exportLoading, exportListVisible, exportError
|
|
375
385
|
}
|
|
376
386
|
|
|
377
387
|
}
|
|
@@ -23,6 +23,7 @@ export const useCrudStore = defineStore('CrudStore', {
|
|
|
23
23
|
exportLoading: false,
|
|
24
24
|
exportFiles: [] as string[],
|
|
25
25
|
exportListVisible: false,
|
|
26
|
+
exportError: false
|
|
26
27
|
}
|
|
27
28
|
),
|
|
28
29
|
getters: {
|
|
@@ -42,6 +43,11 @@ export const useCrudStore = defineStore('CrudStore', {
|
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
}
|
|
46
|
+
},
|
|
47
|
+
getFilterIndex(state: any) {
|
|
48
|
+
return (filterName: string) => {
|
|
49
|
+
return state.filters.findIndex((filter: any) => filter.field === filterName)
|
|
50
|
+
}
|
|
45
51
|
}
|
|
46
52
|
|
|
47
53
|
},
|
|
@@ -111,6 +117,9 @@ export const useCrudStore = defineStore('CrudStore', {
|
|
|
111
117
|
setExportListVisible(exportListVisible: boolean) {
|
|
112
118
|
this.exportListVisible = exportListVisible
|
|
113
119
|
},
|
|
120
|
+
setExportError(error: boolean){
|
|
121
|
+
this.exportError = error
|
|
122
|
+
},
|
|
114
123
|
setFilters(filters: any[]) {
|
|
115
124
|
this.filters = filters
|
|
116
125
|
}
|