@drax/crud-vue 0.5.2 → 0.5.3
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/EntityCrud.ts +15 -6
- package/src/components/Crud.vue +3 -1
- package/src/components/CrudAutocomplete.vue +13 -1
- package/src/components/CrudFilters.vue +64 -0
- package/src/components/CrudFormField.vue +77 -6
- package/src/components/CrudFormList.vue +14 -0
- package/src/components/CrudList.vue +28 -7
- package/src/components/CrudSearch.vue +5 -3
- package/src/composables/UseCrud.ts +29 -19
- package/src/stores/UseCrudStore.ts +4 -0
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.5.
|
|
6
|
+
"version": "0.5.3",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "./src/index.ts",
|
|
9
9
|
"module": "./src/index.ts",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@drax/common-front": "^0.5.1",
|
|
28
|
-
"@drax/crud-front": "^0.5.
|
|
29
|
-
"@drax/crud-share": "^0.5.
|
|
28
|
+
"@drax/crud-front": "^0.5.3",
|
|
29
|
+
"@drax/crud-share": "^0.5.3"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"pinia": "^2.2.2",
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"vue-tsc": "^2.0.11",
|
|
64
64
|
"vuetify": "^3.7.1"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "56ea5a743bce196d6322ae6c26ea5b041450d7a3"
|
|
67
67
|
}
|
package/src/EntityCrud.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
IEntityCrud, IEntityCrudForm, IEntityCrudHeader, IEntityCrudRefs,
|
|
3
3
|
IEntityCrudRules, IEntityCrudField, IEntityCrudPermissions,
|
|
4
|
-
IDraxCrudProvider
|
|
4
|
+
IDraxCrudProvider, IEntityCrudFilter, IEntityCrudFormFilter
|
|
5
5
|
} from "@drax/crud-share";
|
|
6
6
|
|
|
7
7
|
|
|
@@ -36,7 +36,13 @@ class EntityCrud implements IEntityCrud{
|
|
|
36
36
|
|
|
37
37
|
get fields():IEntityCrudField[]{
|
|
38
38
|
return [
|
|
39
|
-
{name: '
|
|
39
|
+
{name: '_id', type: 'string', label: 'ID', default: '' },
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get filters():IEntityCrudFilter[]{
|
|
44
|
+
return [
|
|
45
|
+
{name: '_id', type: 'string', label: 'ID', default: '', operator: 'eq' },
|
|
40
46
|
]
|
|
41
47
|
}
|
|
42
48
|
|
|
@@ -57,7 +63,7 @@ class EntityCrud implements IEntityCrud{
|
|
|
57
63
|
|
|
58
64
|
get form():IEntityCrudForm{
|
|
59
65
|
|
|
60
|
-
|
|
66
|
+
return this.fields.reduce((acc, field) => {
|
|
61
67
|
let value = null
|
|
62
68
|
if(field.type === 'object'){
|
|
63
69
|
value = this.objectFields(field)
|
|
@@ -68,10 +74,14 @@ class EntityCrud implements IEntityCrud{
|
|
|
68
74
|
return {...acc, [field.name]: value }
|
|
69
75
|
}, {})
|
|
70
76
|
|
|
71
|
-
|
|
77
|
+
}
|
|
72
78
|
|
|
73
|
-
return form
|
|
74
79
|
|
|
80
|
+
get formFilters():IEntityCrudFormFilter[]{
|
|
81
|
+
return this.filters.map(
|
|
82
|
+
(filter:IEntityCrudFilter) =>
|
|
83
|
+
({field:filter.name, value: null, operator: filter.operator })
|
|
84
|
+
)
|
|
75
85
|
}
|
|
76
86
|
|
|
77
87
|
get refs():IEntityCrudRefs{
|
|
@@ -91,7 +101,6 @@ class EntityCrud implements IEntityCrud{
|
|
|
91
101
|
}
|
|
92
102
|
|
|
93
103
|
getRule(field:string|undefined):Array<Function>|undefined {
|
|
94
|
-
console.log("Getting rule for field: ", field, this.rules)
|
|
95
104
|
return field && this.rules[field] && this.rules[field].length > 0 ? this.rules[field] : undefined
|
|
96
105
|
}
|
|
97
106
|
|
package/src/components/Crud.vue
CHANGED
|
@@ -13,11 +13,13 @@ const {entity} = defineProps({
|
|
|
13
13
|
|
|
14
14
|
const {
|
|
15
15
|
onCreate, onEdit, onDelete, onCancel, onSubmit,resetCrudStore,
|
|
16
|
-
operation, dialog, form, notify, error, message, doExport
|
|
16
|
+
operation, dialog, form, notify, error, message, doExport,
|
|
17
|
+
prepareFilters
|
|
17
18
|
} = useCrud(entity);
|
|
18
19
|
|
|
19
20
|
onBeforeMount(() => {
|
|
20
21
|
resetCrudStore()
|
|
22
|
+
prepareFilters()
|
|
21
23
|
})
|
|
22
24
|
|
|
23
25
|
</script>
|
|
@@ -3,6 +3,7 @@ import {debounce} from "@drax/common-front"
|
|
|
3
3
|
import { type PropType, type Ref} from "vue";
|
|
4
4
|
import {ref, onBeforeMount} from "vue";
|
|
5
5
|
import type {IEntityCrud, IEntityCrudField} from "@drax/crud-share";
|
|
6
|
+
import {VDateInput} from "vuetify/lib/labs/VDateInput";
|
|
6
7
|
|
|
7
8
|
const valueModel = defineModel<string | string[]>({type: [String, Array], required: false})
|
|
8
9
|
|
|
@@ -18,6 +19,10 @@ const {entity, multiple} = defineProps({
|
|
|
18
19
|
itemTitle: {type: [String], default: 'name'},
|
|
19
20
|
rules: {type: Array as PropType<any>, default: []},
|
|
20
21
|
errorMessages: {type: Array as PropType<string[]>, default: []},
|
|
22
|
+
hideDetails: {type: Boolean, default: false},
|
|
23
|
+
singleLine: {type: Boolean, default: false},
|
|
24
|
+
density: {type: String as PropType<'comfortable' | 'compact' | 'default'>, default: 'default'},
|
|
25
|
+
variant: {type: String as PropType<'underlined' | 'outlined' | 'filled' | 'solo' | 'solo-inverted' | 'solo-filled' | 'plain'>, default: 'filled'},
|
|
21
26
|
})
|
|
22
27
|
|
|
23
28
|
if(!entity){
|
|
@@ -86,6 +91,8 @@ async function search(value: any) {
|
|
|
86
91
|
|
|
87
92
|
}
|
|
88
93
|
|
|
94
|
+
defineEmits(['updateValue'])
|
|
95
|
+
|
|
89
96
|
</script>
|
|
90
97
|
|
|
91
98
|
<template>
|
|
@@ -97,13 +104,18 @@ async function search(value: any) {
|
|
|
97
104
|
:multiple="multiple"
|
|
98
105
|
:chips="chips"
|
|
99
106
|
:closable-chips="closableChips"
|
|
100
|
-
:clearable="clearable"
|
|
101
107
|
:item-value="itemValue"
|
|
102
108
|
:item-title="itemTitle"
|
|
103
109
|
:loading="loading"
|
|
104
110
|
:rules="rules"
|
|
111
|
+
:density="density"
|
|
112
|
+
:variant="variant"
|
|
113
|
+
:hide-details="hideDetails"
|
|
114
|
+
:single-line="singleLine"
|
|
115
|
+
:clearable="clearable"
|
|
105
116
|
:error-messages="errorMessages"
|
|
106
117
|
@update:search="debouncedSearch"
|
|
118
|
+
@update:modelValue="$emit('updateValue')"
|
|
107
119
|
></v-autocomplete>
|
|
108
120
|
</template>
|
|
109
121
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type {PropType} from "vue";
|
|
3
|
+
import {ref} from "vue";
|
|
4
|
+
import CrudFormField from "./CrudFormField.vue";
|
|
5
|
+
import type {IEntityCrud} from "@drax/crud-share";
|
|
6
|
+
import {useI18n} from "vue-i18n";
|
|
7
|
+
|
|
8
|
+
const {t} = useI18n()
|
|
9
|
+
const valueModel = defineModel({type: [Object]})
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
const {entity} = defineProps({
|
|
13
|
+
entity: {type: Object as PropType<IEntityCrud>, required: true},
|
|
14
|
+
actions: {type: Boolean, default: false},
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const formRef = ref()
|
|
18
|
+
|
|
19
|
+
async function filter() {
|
|
20
|
+
emit('filter')
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function clear() {
|
|
24
|
+
emit('filter')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
const emit = defineEmits(['filter', 'clear','updateValue'])
|
|
29
|
+
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<template>
|
|
33
|
+
<v-card flat >
|
|
34
|
+
<v-row dense class="mt-1" justify="space-between">
|
|
35
|
+
<v-col v-for="(filter,index) in entity.filters" :key="filter.name"
|
|
36
|
+
cols="12" sm="6" md="4"
|
|
37
|
+
>
|
|
38
|
+
<crud-form-field
|
|
39
|
+
:field="filter"
|
|
40
|
+
:entity="entity"
|
|
41
|
+
v-model="valueModel[index].value"
|
|
42
|
+
density="compact"
|
|
43
|
+
variant="outlined"
|
|
44
|
+
hide-details single-line disable-rules
|
|
45
|
+
@updateValue="$emit('updateValue')"
|
|
46
|
+
/>
|
|
47
|
+
</v-col>
|
|
48
|
+
|
|
49
|
+
</v-row>
|
|
50
|
+
|
|
51
|
+
<v-card-actions v-if="actions" class="pb-0">
|
|
52
|
+
<v-spacer />
|
|
53
|
+
<v-btn variant="text" density="compact" color="grey" @click="clear">{{ t('action.clear') }}</v-btn>
|
|
54
|
+
<v-btn variant="flat" density="compact" color="primary" @click="filter">
|
|
55
|
+
{{ t('action.filter') }}
|
|
56
|
+
</v-btn>
|
|
57
|
+
</v-card-actions>
|
|
58
|
+
|
|
59
|
+
</v-card>
|
|
60
|
+
</template>
|
|
61
|
+
|
|
62
|
+
<style scoped>
|
|
63
|
+
|
|
64
|
+
</style>
|
|
@@ -6,20 +6,28 @@ import CrudAutocomplete from "./CrudAutocomplete.vue";
|
|
|
6
6
|
import {useI18n} from "vue-i18n";
|
|
7
7
|
import {useCrudStore} from "../stores/UseCrudStore";
|
|
8
8
|
import {VDateInput} from 'vuetify/labs/VDateInput'
|
|
9
|
-
import type {IEntityCrud, IEntityCrudField} from "@drax/crud-share";
|
|
9
|
+
import type {IEntityCrud, IEntityCrudField, IEntityCrudFilter} from "@drax/crud-share";
|
|
10
10
|
const {t, te} = useI18n()
|
|
11
11
|
|
|
12
12
|
const store = useCrudStore()
|
|
13
13
|
|
|
14
14
|
const valueModel = defineModel<any>({type: [String, Number, Boolean, Object, Array], default: false})
|
|
15
15
|
|
|
16
|
-
const {index, entity, field} = defineProps({
|
|
16
|
+
const {index, entity, field, disableRules} = defineProps({
|
|
17
17
|
entity: {type: Object as PropType<IEntityCrud>, required: true},
|
|
18
|
-
field: {type: Object as PropType<IEntityCrudField|undefined>, required: true},
|
|
18
|
+
field: {type: Object as PropType<IEntityCrudField|IEntityCrudFilter|undefined>, required: true},
|
|
19
19
|
readonly: {type: Boolean, default: false},
|
|
20
|
+
hideDetails: {type: Boolean, default: false},
|
|
21
|
+
singleLine: {type: Boolean, default: false},
|
|
22
|
+
clearable: {type: Boolean, default: true},
|
|
23
|
+
disableRules: {type: Boolean, default: false},
|
|
20
24
|
index: {type: Number, default: 0},
|
|
25
|
+
density: {type: String as PropType<'comfortable' | 'compact' | 'default'>, default: 'default'},
|
|
26
|
+
variant: {type: String as PropType<'underlined' | 'outlined' | 'filled' | 'solo' | 'solo-inverted' | 'solo-filled' | 'plain'>, default: 'filled'},
|
|
21
27
|
})
|
|
22
28
|
|
|
29
|
+
|
|
30
|
+
|
|
23
31
|
if(!field){
|
|
24
32
|
throw new Error("CrudFormField must be provided with a field object")
|
|
25
33
|
}
|
|
@@ -32,6 +40,7 @@ const label = computed(() => {
|
|
|
32
40
|
})
|
|
33
41
|
|
|
34
42
|
const rules = computed(() => {
|
|
43
|
+
if(disableRules) return undefined
|
|
35
44
|
return entity.getRule(field.name) as any
|
|
36
45
|
})
|
|
37
46
|
|
|
@@ -39,6 +48,8 @@ const inputErrors = computed(() =>
|
|
|
39
48
|
store.getInputErrors(field.name).map((error: string) => t(te(error) ? t(error) : error))
|
|
40
49
|
)
|
|
41
50
|
|
|
51
|
+
defineEmits(['updateValue'])
|
|
52
|
+
|
|
42
53
|
</script>
|
|
43
54
|
|
|
44
55
|
<template>
|
|
@@ -53,6 +64,12 @@ const inputErrors = computed(() =>
|
|
|
53
64
|
:readonly="readonly"
|
|
54
65
|
:error-messages="inputErrors"
|
|
55
66
|
:rules="rules"
|
|
67
|
+
:density="density"
|
|
68
|
+
:variant="variant"
|
|
69
|
+
:clearable="clearable"
|
|
70
|
+
:hide-details="hideDetails"
|
|
71
|
+
:single-line="singleLine"
|
|
72
|
+
@update:modelValue="$emit('updateValue')"
|
|
56
73
|
>
|
|
57
74
|
</v-text-field>
|
|
58
75
|
|
|
@@ -65,6 +82,12 @@ const inputErrors = computed(() =>
|
|
|
65
82
|
:readonly="readonly"
|
|
66
83
|
:error-messages="inputErrors"
|
|
67
84
|
:rules="rules"
|
|
85
|
+
:density="density"
|
|
86
|
+
:variant="variant"
|
|
87
|
+
:clearable="clearable"
|
|
88
|
+
:hide-details="hideDetails"
|
|
89
|
+
:single-line="singleLine"
|
|
90
|
+
@update:modelValue="$emit('updateValue')"
|
|
68
91
|
>
|
|
69
92
|
</v-text-field>
|
|
70
93
|
|
|
@@ -76,6 +99,12 @@ const inputErrors = computed(() =>
|
|
|
76
99
|
:readonly="readonly"
|
|
77
100
|
:error-messages="inputErrors"
|
|
78
101
|
:rules="rules"
|
|
102
|
+
:density="density"
|
|
103
|
+
:variant="variant"
|
|
104
|
+
:clearable="clearable"
|
|
105
|
+
:hide-details="hideDetails"
|
|
106
|
+
:single-line="singleLine"
|
|
107
|
+
@update:modelValue="$emit('updateValue')"
|
|
79
108
|
>
|
|
80
109
|
</v-checkbox>
|
|
81
110
|
|
|
@@ -91,6 +120,12 @@ const inputErrors = computed(() =>
|
|
|
91
120
|
prepend-inner-icon="mdi-calendar"
|
|
92
121
|
prepend-icon=""
|
|
93
122
|
:rules="rules"
|
|
123
|
+
:density="density"
|
|
124
|
+
:variant="variant"
|
|
125
|
+
:clearable="clearable"
|
|
126
|
+
:hide-details="hideDetails"
|
|
127
|
+
:single-line="singleLine"
|
|
128
|
+
@update:modelValue="$emit('updateValue')"
|
|
94
129
|
/>
|
|
95
130
|
|
|
96
131
|
<crud-autocomplete
|
|
@@ -101,6 +136,12 @@ const inputErrors = computed(() =>
|
|
|
101
136
|
:label="label"
|
|
102
137
|
:error-messages="inputErrors"
|
|
103
138
|
:rules="rules"
|
|
139
|
+
:density="density"
|
|
140
|
+
:variant="variant"
|
|
141
|
+
:clearable="clearable"
|
|
142
|
+
:hide-details="hideDetails"
|
|
143
|
+
:single-line="singleLine"
|
|
144
|
+
@updateValue="$emit('updateValue')"
|
|
104
145
|
/>
|
|
105
146
|
|
|
106
147
|
<v-card v-if="field.type === 'object'" class="mt-3" variant="flat" border>
|
|
@@ -112,6 +153,12 @@ const inputErrors = computed(() =>
|
|
|
112
153
|
:entity="entity"
|
|
113
154
|
:field="oField"
|
|
114
155
|
v-model="valueModel[oField.name]"
|
|
156
|
+
:density="density"
|
|
157
|
+
:variant="variant"
|
|
158
|
+
:clearable="clearable"
|
|
159
|
+
:hide-details="hideDetails"
|
|
160
|
+
:single-line="singleLine"
|
|
161
|
+
@updateValue="$emit('updateValue')"
|
|
115
162
|
></crud-form-field>
|
|
116
163
|
</v-card-text>
|
|
117
164
|
|
|
@@ -126,9 +173,15 @@ const inputErrors = computed(() =>
|
|
|
126
173
|
:multiple="true"
|
|
127
174
|
:chips="true"
|
|
128
175
|
:closable-chips="true"
|
|
129
|
-
:clearable="true"
|
|
130
176
|
:readonly="readonly"
|
|
131
177
|
:error-messages="inputErrors"
|
|
178
|
+
:density="density"
|
|
179
|
+
:variant="variant"
|
|
180
|
+
:clearable="clearable"
|
|
181
|
+
:hide-details="hideDetails"
|
|
182
|
+
:single-line="singleLine"
|
|
183
|
+
:rules="rules"
|
|
184
|
+
@update:modelValue="$emit('updateValue')"
|
|
132
185
|
>
|
|
133
186
|
</v-combobox>
|
|
134
187
|
|
|
@@ -140,9 +193,15 @@ const inputErrors = computed(() =>
|
|
|
140
193
|
v-model="valueModel"
|
|
141
194
|
:multiple="true"
|
|
142
195
|
:chips="true"
|
|
143
|
-
:clearable="true"
|
|
144
196
|
:label="label"
|
|
197
|
+
:rules="rules"
|
|
145
198
|
:error-messages="inputErrors"
|
|
199
|
+
:density="density"
|
|
200
|
+
:variant="variant"
|
|
201
|
+
:clearable="clearable"
|
|
202
|
+
:hide-details="hideDetails"
|
|
203
|
+
:single-line="singleLine"
|
|
204
|
+
@updateValue="$emit('updateValue')"
|
|
146
205
|
/>
|
|
147
206
|
|
|
148
207
|
|
|
@@ -154,9 +213,15 @@ const inputErrors = computed(() =>
|
|
|
154
213
|
v-model="valueModel"
|
|
155
214
|
:multiple="true"
|
|
156
215
|
:chips="true"
|
|
157
|
-
:clearable="true"
|
|
158
216
|
:readonly="readonly"
|
|
159
217
|
:error-messages="inputErrors"
|
|
218
|
+
:density="density"
|
|
219
|
+
:variant="variant"
|
|
220
|
+
:clearable="clearable"
|
|
221
|
+
:hide-details="hideDetails"
|
|
222
|
+
:single-line="singleLine"
|
|
223
|
+
:rules="rules"
|
|
224
|
+
@update:modelValue="$emit('updateValue')"
|
|
160
225
|
>
|
|
161
226
|
</v-combobox>
|
|
162
227
|
|
|
@@ -167,6 +232,12 @@ const inputErrors = computed(() =>
|
|
|
167
232
|
:field="field"
|
|
168
233
|
v-model="valueModel"
|
|
169
234
|
:readonly="readonly"
|
|
235
|
+
:density="density"
|
|
236
|
+
:variant="variant"
|
|
237
|
+
:clearable="clearable"
|
|
238
|
+
:hide-details="hideDetails"
|
|
239
|
+
:single-line="singleLine"
|
|
240
|
+
@updateValue="$emit('updateValue')"
|
|
170
241
|
/>
|
|
171
242
|
|
|
172
243
|
</div>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type {PropType} from "vue";
|
|
3
3
|
import CrudFormField from "./CrudFormField.vue";
|
|
4
4
|
import type {IEntityCrud, IEntityCrudField} from "@drax/crud-share";
|
|
5
|
+
import {VDateInput} from "vuetify/lib/labs/VDateInput";
|
|
5
6
|
|
|
6
7
|
const valueModel = defineModel({type: Array, default: () => []});
|
|
7
8
|
|
|
@@ -9,6 +10,11 @@ const {field} = defineProps({
|
|
|
9
10
|
entity: {type: Object as PropType<IEntityCrud>, required: true},
|
|
10
11
|
field: {type: Object as PropType<IEntityCrudField>, required: true},
|
|
11
12
|
readonly: {type: Boolean, default: false},
|
|
13
|
+
hideDetails: {type: Boolean, default: false},
|
|
14
|
+
singleLine: {type: Boolean, default: false},
|
|
15
|
+
clearable: {type: Boolean, default: true},
|
|
16
|
+
density: {type: String as PropType<'comfortable' | 'compact' | 'default'>, default: 'default'},
|
|
17
|
+
variant: {type: String as PropType<'underlined' | 'outlined' | 'filled' | 'solo' | 'solo-inverted' | 'solo-filled' | 'plain'>, default: 'filled'},
|
|
12
18
|
})
|
|
13
19
|
|
|
14
20
|
function newItem() {
|
|
@@ -31,6 +37,8 @@ function removeItem(index: number) {
|
|
|
31
37
|
valueModel.value.splice(index, 1);
|
|
32
38
|
}
|
|
33
39
|
|
|
40
|
+
defineEmits(['updateValue'])
|
|
41
|
+
|
|
34
42
|
</script>
|
|
35
43
|
|
|
36
44
|
<template>
|
|
@@ -50,6 +58,12 @@ function removeItem(index: number) {
|
|
|
50
58
|
v-model="(valueModel[index] as any)[key]"
|
|
51
59
|
:readonly="readonly"
|
|
52
60
|
:index="index"
|
|
61
|
+
:density="density"
|
|
62
|
+
:variant="variant"
|
|
63
|
+
:clearable="clearable"
|
|
64
|
+
:hide-details="hideDetails"
|
|
65
|
+
:single-line="singleLine"
|
|
66
|
+
@updateValue="$emit('updateValue')"
|
|
53
67
|
/>
|
|
54
68
|
</template>
|
|
55
69
|
|
|
@@ -12,20 +12,28 @@ import CrudExportList from "./CrudExportList.vue";
|
|
|
12
12
|
import type {IEntityCrud} from "@drax/crud-share";
|
|
13
13
|
import {useI18n} from "vue-i18n";
|
|
14
14
|
import type {IEntityCrudHeader} from "@drax/crud-share";
|
|
15
|
+
import CrudFilters from "./CrudFilters.vue";
|
|
15
16
|
|
|
16
|
-
const {t,te} = useI18n()
|
|
17
|
+
const {t, te} = useI18n()
|
|
17
18
|
const {hasPermission} = useAuth()
|
|
18
19
|
|
|
19
20
|
const {entity} = defineProps({
|
|
20
21
|
entity: {type: Object as PropType<IEntityCrud>, required: true},
|
|
22
|
+
|
|
21
23
|
})
|
|
22
24
|
|
|
23
25
|
const {
|
|
24
26
|
loading, itemsPerPage, page, sortBy, search, totalItems, items,
|
|
25
|
-
|
|
27
|
+
doPaginate, filters
|
|
26
28
|
} = useCrud(entity)
|
|
27
29
|
|
|
28
|
-
const actions: IEntityCrudHeader[] = [{
|
|
30
|
+
const actions: IEntityCrudHeader[] = [{
|
|
31
|
+
title: t('action.actions'),
|
|
32
|
+
key: 'actions',
|
|
33
|
+
sortable: false,
|
|
34
|
+
align: 'end',
|
|
35
|
+
minWidth: '140px'
|
|
36
|
+
}]
|
|
29
37
|
const tHeaders: IEntityCrudHeader[] = entity.headers.map(header => ({
|
|
30
38
|
...header,
|
|
31
39
|
title: te(`${entity.name.toLowerCase()}.fields.${header.title}`) ? t(`${entity.name.toLowerCase()}.fields.${header.title}`) : header.title
|
|
@@ -35,7 +43,7 @@ const headers: IEntityCrudHeader[] = [...tHeaders, ...actions]
|
|
|
35
43
|
|
|
36
44
|
|
|
37
45
|
defineExpose({
|
|
38
|
-
|
|
46
|
+
doPaginate
|
|
39
47
|
});
|
|
40
48
|
|
|
41
49
|
</script>
|
|
@@ -55,7 +63,7 @@ defineExpose({
|
|
|
55
63
|
:search="search"
|
|
56
64
|
:multi-sort="false"
|
|
57
65
|
item-value="name"
|
|
58
|
-
@update:options="
|
|
66
|
+
@update:options="doPaginate"
|
|
59
67
|
>
|
|
60
68
|
<template v-slot:top>
|
|
61
69
|
<v-toolbar density="compact">
|
|
@@ -80,12 +88,25 @@ defineExpose({
|
|
|
80
88
|
|
|
81
89
|
</v-toolbar>
|
|
82
90
|
|
|
83
|
-
<crud-export-list
|
|
91
|
+
<crud-export-list
|
|
92
|
+
:entity="entity"
|
|
93
|
+
/>
|
|
84
94
|
|
|
85
95
|
<v-card>
|
|
86
96
|
<v-card-text>
|
|
87
|
-
<crud-search
|
|
97
|
+
<crud-search
|
|
98
|
+
v-model="search"
|
|
99
|
+
/>
|
|
88
100
|
</v-card-text>
|
|
101
|
+
|
|
102
|
+
<v-card-text class="pt-0">
|
|
103
|
+
<crud-filters
|
|
104
|
+
:entity="entity"
|
|
105
|
+
v-model="filters"
|
|
106
|
+
@updateValue="doPaginate()"
|
|
107
|
+
/>
|
|
108
|
+
</v-card-text>
|
|
109
|
+
|
|
89
110
|
</v-card>
|
|
90
111
|
|
|
91
112
|
</template>
|
|
@@ -5,12 +5,14 @@ const model = defineModel<any>()
|
|
|
5
5
|
</script>
|
|
6
6
|
|
|
7
7
|
<template>
|
|
8
|
-
<v-text-field v-model="model"
|
|
9
|
-
density="compact"
|
|
8
|
+
<v-text-field v-model="model"
|
|
9
|
+
density="compact"
|
|
10
|
+
class="mr-2"
|
|
10
11
|
variant="outlined"
|
|
11
12
|
append-inner-icon="mdi-magnify"
|
|
12
13
|
:label="t('action.search')"
|
|
13
|
-
single-line
|
|
14
|
+
single-line hide-details
|
|
15
|
+
clearable @click:clear="() => model = ''"
|
|
14
16
|
/>
|
|
15
17
|
</template>
|
|
16
18
|
|
|
@@ -6,15 +6,37 @@ export function useCrud(entity: IEntityCrud) {
|
|
|
6
6
|
|
|
7
7
|
const store = useCrudStore()
|
|
8
8
|
|
|
9
|
+
const dialog = computed({get(){return store.dialog} , set(value){store.setDialog(value)}})
|
|
10
|
+
const operation = computed({get(){return store.operation} , set(value){store.setOperation(value)}})
|
|
11
|
+
const form = computed({get(){return store.form} , set(value){store.setForm(value)}})
|
|
12
|
+
const formValid = computed({get(){return store.formValid} , set(value){store.setFormValid(value)}})
|
|
13
|
+
const notify = computed({get(){return store.notify} , set(value){store.setNotify(value)}})
|
|
14
|
+
const error = computed({get(){return store.error} , set(value){store.setError(value)}})
|
|
15
|
+
const message = computed({get(){return store.message} , set(value){store.setMessage(value)}})
|
|
16
|
+
const loading = computed({get(){return store.loading} , set(value){store.setLoading(value)}})
|
|
17
|
+
const itemsPerPage = computed({get(){return store.itemsPerPage} , set(value){store.setItemsPerPage(value)}})
|
|
18
|
+
const page = computed({get(){return store.page} , set(value){store.setPage(value)}})
|
|
19
|
+
const sortBy = computed({get(){return store.sortBy} , set(value){store.setSortBy(value)}})
|
|
20
|
+
const search = computed({get(){return store.search} , set(value){store.setSearch(value)}})
|
|
21
|
+
const totalItems = computed({get(){return store.totalItems} , set(value){store.setTotalItems(value)}})
|
|
22
|
+
const items = computed({get(){return store.items} , set(value){store.setItems(value)}})
|
|
23
|
+
const exportFiles = computed({get(){return store.exportFiles} , set(value){store.setExportFiles(value)}})
|
|
24
|
+
const exportLoading = computed({get(){return store.exportLoading} , set(value){store.setExportLoading(value)}})
|
|
25
|
+
const exportListVisible = computed({get(){return store.exportListVisible} , set(value){store.setExportListVisible(value)}})
|
|
26
|
+
const filters = computed({get(){return store.filters} , set(value){store.setFilters(value)}})
|
|
27
|
+
|
|
28
|
+
|
|
9
29
|
async function doPaginate() {
|
|
10
30
|
store.setLoading(true)
|
|
11
31
|
try {
|
|
32
|
+
|
|
12
33
|
const r: IDraxPaginateResult<any> = await entity?.provider.paginate({
|
|
13
34
|
page: store.page,
|
|
14
35
|
limit: store.itemsPerPage,
|
|
15
36
|
orderBy: store.sortBy[0]?.key,
|
|
16
37
|
order: store.sortBy[0]?.order,
|
|
17
|
-
search: store.search
|
|
38
|
+
search: store.search,
|
|
39
|
+
filters: store.filters
|
|
18
40
|
})
|
|
19
41
|
store.setItems(r.items)
|
|
20
42
|
store.setTotalItems(r.total)
|
|
@@ -170,28 +192,16 @@ export function useCrud(entity: IEntityCrud) {
|
|
|
170
192
|
store.$reset()
|
|
171
193
|
}
|
|
172
194
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const notify = computed({get(){return store.notify} , set(value){store.setNotify(value)}})
|
|
178
|
-
const error = computed({get(){return store.error} , set(value){store.setError(value)}})
|
|
179
|
-
const message = computed({get(){return store.message} , set(value){store.setMessage(value)}})
|
|
180
|
-
const loading = computed({get(){return store.loading} , set(value){store.setLoading(value)}})
|
|
181
|
-
const itemsPerPage = computed({get(){return store.itemsPerPage} , set(value){store.setItemsPerPage(value)}})
|
|
182
|
-
const page = computed({get(){return store.page} , set(value){store.setPage(value)}})
|
|
183
|
-
const sortBy = computed({get(){return store.sortBy} , set(value){store.setSortBy(value)}})
|
|
184
|
-
const search = computed({get(){return store.search} , set(value){store.setSearch(value)}})
|
|
185
|
-
const totalItems = computed({get(){return store.totalItems} , set(value){store.setTotalItems(value)}})
|
|
186
|
-
const items = computed({get(){return store.items} , set(value){store.setItems(value)}})
|
|
187
|
-
const exportFiles = computed({get(){return store.exportFiles} , set(value){store.setExportFiles(value)}})
|
|
188
|
-
const exportLoading = computed({get(){return store.exportLoading} , set(value){store.setExportLoading(value)}})
|
|
189
|
-
const exportListVisible = computed({get(){return store.exportListVisible} , set(value){store.setExportListVisible(value)}})
|
|
195
|
+
function prepareFilters(){
|
|
196
|
+
store.setFilters(entity.formFilters)
|
|
197
|
+
}
|
|
198
|
+
|
|
190
199
|
|
|
191
200
|
return {
|
|
192
|
-
|
|
201
|
+
doPaginate, doExport, onCreate, onEdit, onDelete, onCancel, onSubmit,resetCrudStore,
|
|
193
202
|
operation, dialog, form, notify, error, message, formValid,
|
|
194
203
|
loading, itemsPerPage, page, sortBy, search, totalItems, items,
|
|
204
|
+
prepareFilters,filters,
|
|
195
205
|
exportFiles,exportLoading,exportListVisible
|
|
196
206
|
}
|
|
197
207
|
|
|
@@ -11,6 +11,7 @@ export const useCrudStore = defineStore('CrudStore', {
|
|
|
11
11
|
notify: false as boolean,
|
|
12
12
|
message: '' as string,
|
|
13
13
|
error: '' as string,
|
|
14
|
+
filters: [] as any[],
|
|
14
15
|
items: [] as any[],
|
|
15
16
|
totalItems: 0 as number,
|
|
16
17
|
itemsPerPage: 5 as number,
|
|
@@ -99,6 +100,9 @@ export const useCrudStore = defineStore('CrudStore', {
|
|
|
99
100
|
},
|
|
100
101
|
setExportListVisible(exportListVisible: boolean) {
|
|
101
102
|
this.exportListVisible = exportListVisible
|
|
103
|
+
},
|
|
104
|
+
setFilters(filters: any[]) {
|
|
105
|
+
this.filters = filters
|
|
102
106
|
}
|
|
103
107
|
}
|
|
104
108
|
|