@drax/crud-vue 0.31.0 → 0.34.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 CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.31.0",
6
+ "version": "0.34.0",
7
7
  "type": "module",
8
8
  "main": "./src/index.ts",
9
9
  "module": "./src/index.ts",
@@ -24,10 +24,10 @@
24
24
  "format": "prettier --write src/"
25
25
  },
26
26
  "dependencies": {
27
- "@drax/common-front": "^0.31.0",
28
- "@drax/crud-front": "^0.31.0",
29
- "@drax/crud-share": "^0.31.0",
30
- "@drax/media-vue": "^0.31.0"
27
+ "@drax/common-front": "^0.34.0",
28
+ "@drax/crud-front": "^0.34.0",
29
+ "@drax/crud-share": "^0.34.0",
30
+ "@drax/media-vue": "^0.34.0"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "pinia": "^2.2.2",
@@ -64,5 +64,5 @@
64
64
  "vue-tsc": "^2.1.10",
65
65
  "vuetify": "^3.8.2"
66
66
  },
67
- "gitHead": "01589f8197801c0b8ad13a10d398e41d6cb2a25a"
67
+ "gitHead": "3a121099fcdd0814fd232d90aeac0b2086e2e625"
68
68
  }
package/src/EntityCrud.ts CHANGED
@@ -1,256 +1,296 @@
1
1
  import type {
2
- IEntityCrud, IEntityCrudForm, IEntityCrudHeader, IEntityCrudRefs,
3
- IEntityCrudRules, IEntityCrudField, IEntityCrudPermissions,
4
- IDraxCrudProvider, IEntityCrudFilter, IEntityCrudFormFilter
2
+ IEntityCrud, IEntityCrudForm, IEntityCrudHeader, IEntityCrudRefs,
3
+ IEntityCrudRules, IEntityCrudField, IEntityCrudPermissions,
4
+ IDraxCrudProvider, IEntityCrudFilter, IEntityCrudFormFilter, IEntityCrudFieldVariant
5
5
  } from "@drax/crud-share";
6
6
 
7
7
 
8
8
  class EntityCrud implements IEntityCrud {
9
9
 
10
- name: string = ''
11
-
12
- constructor() {
13
- }
14
-
15
- static get instance(): IEntityCrud {
16
- throw new Error('EntityCrud instance not found')
17
- }
18
-
19
-
20
- get headers(): IEntityCrudHeader[] {
21
- return [
22
- {title: 'ID', key: '_id'},
23
- ]
24
- }
10
+ name: string = ''
11
+
12
+ constructor() {
13
+ }
14
+
15
+ static get instance(): IEntityCrud {
16
+ throw new Error('EntityCrud instance not found')
17
+ }
18
+
19
+
20
+ get headers(): IEntityCrudHeader[] {
21
+ return [
22
+ {title: 'ID', key: '_id'},
23
+ ]
24
+ }
25
+
26
+ get actionHeaders(): IEntityCrudHeader[] {
27
+ return [
28
+ {
29
+ title: 'action.actions',
30
+ key: 'actions',
31
+ sortable: false,
32
+ align: 'center',
33
+ minWidth: '190px',
34
+ fixed: 'end'
35
+ },
36
+ ]
37
+ }
38
+
39
+
40
+ get permissions(): IEntityCrudPermissions {
41
+ return {
42
+ manage: 'manage', view: 'view', create: 'create', update: 'update', delete: 'delete'
43
+ }
44
+ }
45
+
46
+ get provider(): IDraxCrudProvider<any, any, any> {
47
+ throw new Error('provider not implemented')
48
+ }
49
+
50
+ get fields(): IEntityCrudField[] {
51
+ return [
52
+ {name: '_id', type: 'string', label: 'ID', default: ''},
53
+ ]
54
+ }
55
+
56
+ get createFields() {
57
+ return this.fields
58
+ }
59
+
60
+ get updateFields() {
61
+ return this.fields
62
+ }
63
+
64
+ get deleteFields() {
65
+ return this.fields
66
+ }
67
+
68
+ get viewFields() {
69
+ return this.fields
70
+ }
71
+
72
+ get filters(): IEntityCrudFilter[] {
73
+ return [
74
+ {name: '_id', type: 'string', label: 'ID', default: '', operator: 'eq'},
75
+ ]
76
+ }
77
+
78
+ objectFields(field: IEntityCrudField) {
79
+ let value: any = {}
80
+ if (field.objectFields) {
81
+ field.objectFields.forEach(subField => {
82
+
83
+ if (subField.default != undefined) {
84
+ value[subField.name] = field.default
85
+ } else if (subField.type === 'object') {
86
+ value[subField.name] = this.objectFields(field)
87
+ } else if (/array/.test(field.type)) {
88
+ value[subField.name] = []
89
+ } else {
90
+ value = null
91
+ }
25
92
 
26
- get actionHeaders(): IEntityCrudHeader[] {
27
- return [
28
- {
29
- title: 'action.actions',
30
- key: 'actions',
31
- sortable: false,
32
- align: 'center',
33
- minWidth: '190px',
34
- fixed: 'end'
35
- },
36
- ]
93
+ })
37
94
  }
95
+ return value
96
+ }
38
97
 
98
+ get form(): IEntityCrudForm {
39
99
 
40
- get permissions(): IEntityCrudPermissions {
41
- return {
42
- manage: 'manage', view: 'view', create: 'create', update: 'update', delete: 'delete'
43
- }
44
- }
100
+ return this.fields.reduce((acc, field) => {
101
+ let value = null
102
+ if (field.default != undefined) {
103
+ value = field.default
104
+ } else if (field.type === 'object') {
105
+ value = this.objectFields(field)
106
+ } else if (/array/.test(field.type)) {
107
+ value = []
108
+ } else {
109
+ value = null
110
+ }
45
111
 
46
- get provider(): IDraxCrudProvider<any, any, any> {
47
- throw new Error('provider not implemented')
48
- }
112
+ return {...acc, [field.name]: value}
113
+ }, {})
49
114
 
50
- get fields(): IEntityCrudField[] {
51
- return [
52
- {name: '_id', type: 'string', label: 'ID', default: ''},
53
- ]
54
- }
115
+ }
55
116
 
56
- get createFields() {
57
- return this.fields
58
- }
59
117
 
60
- get updateFields() {
61
- return this.fields
62
- }
118
+ get formFilters(): IEntityCrudFormFilter[] {
119
+ return this.filters.map(
120
+ (filter: IEntityCrudFilter) =>
121
+ ({field: filter.name, value: null, operator: (filter.operator ? filter.operator : 'eq')})
122
+ ) as IEntityCrudFormFilter[]
123
+ }
63
124
 
64
- get deleteFields() {
65
- return this.fields
66
- }
125
+ get refs(): IEntityCrudRefs {
126
+ return {}
127
+ }
67
128
 
68
- get viewFields() {
69
- return this.fields
129
+ getRef(ref: string): IEntityCrud {
130
+ if (!this.refs.hasOwnProperty(ref)) {
131
+ throw new Error("Ref not found: " + ref)
70
132
  }
71
133
 
72
- get filters(): IEntityCrudFilter[] {
73
- return [
74
- {name: '_id', type: 'string', label: 'ID', default: '', operator: 'eq'},
75
- ]
76
- }
134
+ return this.refs[ref]
135
+ }
77
136
 
78
- objectFields(field: IEntityCrudField) {
79
- let value: any = {}
80
- if (field.objectFields) {
81
- field.objectFields.forEach(subField => {
82
-
83
- if (subField.default != undefined) {
84
- value[subField.name] = field.default
85
- } else if (subField.type === 'object') {
86
- value[subField.name] = this.objectFields(field)
87
- } else if (/array/.test(field.type)) {
88
- value[subField.name] = []
89
- } else {
90
- value = null
91
- }
92
-
93
- })
94
- }
95
- return value
96
- }
137
+ get rules(): IEntityCrudRules {
138
+ return {}
139
+ }
97
140
 
98
- get form(): IEntityCrudForm {
141
+ getRule(field: string | undefined): Array<Function> | undefined {
142
+ return field && this.rules[field] && this.rules[field].length > 0 ? this.rules[field] : undefined
143
+ }
99
144
 
100
- return this.fields.reduce((acc, field) => {
101
- let value = null
102
- if (field.default != undefined) {
103
- value = field.default
104
- } else if (field.type === 'object') {
105
- value = this.objectFields(field)
106
- } else if (/array/.test(field.type)) {
107
- value = []
108
- } else {
109
- value = null
110
- }
145
+ get isViewable() {
146
+ return true
147
+ }
111
148
 
112
- return {...acc, [field.name]: value}
113
- }, {})
149
+ get isEditable() {
150
+ return true
151
+ }
114
152
 
115
- }
153
+ isItemEditable():boolean {
154
+ return true
155
+ }
116
156
 
157
+ get isCreatable() {
158
+ return true
159
+ }
117
160
 
118
- get formFilters(): IEntityCrudFormFilter[] {
119
- return this.filters.map(
120
- (filter: IEntityCrudFilter) =>
121
- ({field: filter.name, value: null, operator: (filter.operator ? filter.operator : 'eq' )})
122
- ) as IEntityCrudFormFilter[]
123
- }
161
+ isItemDeletable():boolean{
162
+ return true
163
+ }
124
164
 
125
- get refs(): IEntityCrudRefs {
126
- return {}
127
- }
165
+ get isDeletable() {
166
+ return true
167
+ }
128
168
 
129
- getRef(ref: string): IEntityCrud {
130
- if (!this.refs.hasOwnProperty(ref)) {
131
- throw new Error("Ref not found: " + ref)
132
- }
169
+ get isExportable() {
170
+ return true
171
+ }
133
172
 
134
- return this.refs[ref]
135
- }
173
+ get exportFormats() {
174
+ return ['CSV', 'JSON']
175
+ }
136
176
 
137
- get rules(): IEntityCrudRules {
138
- return {}
139
- }
177
+ get exportHeaders() {
178
+ return ['_id']
179
+ }
140
180
 
141
- getRule(field: string | undefined): Array<Function> | undefined {
142
- return field && this.rules[field] && this.rules[field].length > 0 ? this.rules[field] : undefined
143
- }
181
+ get exportFileName() {
182
+ return 'export'
183
+ }
144
184
 
145
- get isViewable() {
146
- return true
147
- }
185
+ get isImportable() {
186
+ return true
187
+ }
148
188
 
149
- get isEditable() {
150
- return true
151
- }
189
+ get importFormats() {
190
+ return ['CSV', 'JSON']
191
+ }
152
192
 
153
- get isCreatable() {
154
- return true
155
- }
193
+ get dialogFullscreen() {
194
+ return false
195
+ }
156
196
 
157
- get isDeletable() {
158
- return true
159
- }
197
+ get dialogMaxWidth() {
198
+ return ''
199
+ }
160
200
 
161
- get isExportable() {
162
- return true
163
- }
164
201
 
165
- get exportFormats() {
166
- return ['CSV', 'JSON']
167
- }
202
+ get tabs(): string[] {
203
+ return []
204
+ }
168
205
 
169
- get exportHeaders() {
170
- return ['_id']
171
- }
172
206
 
173
- get exportFileName(){
174
- return 'export'
175
- }
207
+ get menus(): string[] {
208
+ return []
209
+ }
176
210
 
177
- get isImportable() {
178
- return true
179
- }
211
+ get menuMaxHeight() {
212
+ return '300px'
213
+ }
180
214
 
181
- get importFormats() {
182
- return ['CSV', 'JSON']
183
- }
215
+ get dialogZindex() {
216
+ return 1999
217
+ }
184
218
 
185
- get dialogFullscreen() {
186
- return false
187
- }
219
+ get searchEnable() {
220
+ return true
221
+ }
188
222
 
189
- get dialogMaxWidth() {
190
- return ''
191
- }
223
+ get filterButtons() {
224
+ return true
225
+ }
192
226
 
227
+ get containerFluid() {
228
+ return false
229
+ }
193
230
 
194
- get tabs():string[]{
195
- return []
196
- }
231
+ get cardDensity(): 'default' | 'comfortable' | 'compact' {
232
+ return 'default'
233
+ }
197
234
 
235
+ get cardClass(): string {
236
+ return 'rounded-xl'
237
+ }
198
238
 
199
- get menus():string[]{
200
- return []
201
- }
239
+ get toolbarDensity(): 'default' | 'comfortable' | 'compact' {
240
+ return 'default'
241
+ }
202
242
 
203
- get menuMaxHeight(){
204
- return '300px'
205
- }
243
+ get toolbarClass(): string {
244
+ return 'bg-primary'
245
+ }
206
246
 
207
- get dialogZindex() {
208
- return 1999
209
- }
247
+ get tableDensity(): 'default' | 'comfortable' | 'compact' {
248
+ return 'default'
249
+ }
210
250
 
211
- get searchEnable(){
212
- return true
213
- }
251
+ get headerProps() {
252
+ return {class: 'bg-primary'}
253
+ }
214
254
 
215
- get filterButtons(){
216
- return true
217
- }
255
+ get tableStriped(): null | 'odd' | 'even' {
256
+ return 'even'
257
+ }
218
258
 
219
- get containerFluid(){
220
- return false
221
- }
259
+ get footerClass() {
260
+ return 'bg-primary'
261
+ }
222
262
 
223
- get cardDensity() : 'default' | 'comfortable' | 'compact' {
224
- return 'default'
225
- }
263
+ get applyFilterClass() {
264
+ return 'bg-primary'
265
+ }
226
266
 
227
- get cardClass() : string {
228
- return 'rounded-xl'
229
- }
267
+ get cleanFilterClass() {
268
+ return 'text-grey'
269
+ }
230
270
 
231
- get toolbarDensity() : 'default' | 'comfortable' | 'compact' {
232
- return 'default'
233
- }
271
+ get submitBtnFormClass() {
272
+ return 'bg-primary'
273
+ }
234
274
 
235
- get toolbarClass() : string {
236
- return 'bg-primary'
237
- }
275
+ get cancelBtnFormClass() {
276
+ return 'text-grey'
277
+ }
238
278
 
239
- get tableDensity() : 'default' | 'comfortable' | 'compact' {
240
- return 'default'
241
- }
279
+ get inputVariantCreate(): IEntityCrudFieldVariant {
280
+ return 'outlined'
281
+ }
242
282
 
243
- get headerProps(){
244
- return { class: 'bg-primary' }
245
- }
283
+ get inputVariantEdit(): IEntityCrudFieldVariant {
284
+ return 'outlined'
285
+ }
246
286
 
247
- get tableStriped() : null | 'odd' | 'even' {
248
- return 'even'
249
- }
287
+ get inputVariantView(): IEntityCrudFieldVariant {
288
+ return 'filled'
289
+ }
250
290
 
251
- get footerClass(){
252
- return 'bg-primary'
253
- }
291
+ get inputVariantDelete() : IEntityCrudFieldVariant{
292
+ return 'underlined'
293
+ }
254
294
 
255
295
 
256
296
  }
@@ -95,7 +95,39 @@ defineEmits(['updateValue'])
95
95
  </script>
96
96
 
97
97
  <template>
98
+
99
+ <v-select
100
+ v-if="field.noFilter === true"
101
+ v-model="valueModel"
102
+ :label="label ? label : field.label"
103
+ :hint="field.hint"
104
+ :persistent-hint="field.persistentHint"
105
+ :placeholder="field.label"
106
+ :items="items"
107
+ :multiple="multiple"
108
+ :chips="chips"
109
+ :closable-chips="closableChips"
110
+ :item-value="itemValue"
111
+ :item-title="itemTitle"
112
+ :loading="loading"
113
+ :rules="rules"
114
+ :readonly="readonly"
115
+ :density="density"
116
+ :variant="variant"
117
+ :hide-details="hideDetails"
118
+ :single-line="singleLine"
119
+ :clearable="clearable"
120
+ :error-messages="errorMessages"
121
+ @update:modelValue="$emit('updateValue')"
122
+ :prepend-icon="prependIcon"
123
+ :append-icon="appendIcon"
124
+ :prepend-inner-icon="prependInnerIcon"
125
+ :append-inner-icon="appendInnerIcon"
126
+ ></v-select>
127
+
128
+
98
129
  <v-autocomplete
130
+ v-else
99
131
  v-model="valueModel"
100
132
  :label="label ? label : field.label"
101
133
  :hint="field.hint"
@@ -123,6 +155,8 @@ defineEmits(['updateValue'])
123
155
  :prepend-inner-icon="prependInnerIcon"
124
156
  :append-inner-icon="appendInnerIcon"
125
157
  ></v-autocomplete>
158
+
159
+
126
160
  </template>
127
161
 
128
162
  <style scoped>
@@ -97,8 +97,8 @@ const emit = defineEmits(['applyFilter', 'clearFilter'])
97
97
 
98
98
  <v-card-actions v-if="actionButtons" class="pb-0">
99
99
  <v-spacer />
100
- <v-btn variant="text" density="compact" color="grey" @click="clear">{{ t('action.clear') }}</v-btn>
101
- <v-btn variant="flat" density="compact" color="primary" @click="filter">
100
+ <v-btn variant="text" density="compact" :class="entity.cleanFilterClass" @click="clear">{{ t('action.clear') }}</v-btn>
101
+ <v-btn variant="flat" density="compact" :class="entity.applyFilterClass" @click="filter">
102
102
  {{ t('action.filter') }}
103
103
  </v-btn>
104
104
  </v-card-actions>
@@ -1,7 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import {useI18n} from "vue-i18n";
3
3
  import type {IEntityCrud, IEntityCrudField} from "@drax/crud-share";
4
- import {useFormUtils} from "../composables/UseFormUtils";
5
4
  import {getItemId} from "../helpers/getItemId";
6
5
  import CrudFormField from "./CrudFormField.vue";
7
6
  import {computed, defineEmits, defineProps, ref} from "vue";
@@ -98,9 +97,19 @@ function cancel() {
98
97
  emit('canceled')
99
98
  }
100
99
 
101
- const {
102
- variant, submitColor
103
- } = useFormUtils(operation.value)
100
+
101
+ const variant = computed(() => {
102
+ if (operation.value === 'create') {
103
+ return entity.inputVariantCreate
104
+ } else if (operation.value === 'edit') {
105
+ return entity.inputVariantEdit
106
+ } else if (operation.value === 'delete') {
107
+ return entity.inputVariantDelete
108
+ } else if (operation.value === 'view') {
109
+ return entity.inputVariantView
110
+ }
111
+ return 'outlined'
112
+ })
104
113
 
105
114
  const tabInputErrors = computed(() => {
106
115
  return (tab:string) => {
@@ -262,10 +271,10 @@ const menuInputErrors = computed(() => {
262
271
 
263
272
  <v-card-actions>
264
273
  <v-spacer></v-spacer>
265
- <v-btn variant="text" color="grey" @click="cancel">
274
+ <v-btn variant="text" :class="entity.cancelBtnFormClass" @click="cancel">
266
275
  {{ operation == 'view' ? t('action.close') : t('action.cancel') }}
267
276
  </v-btn>
268
- <v-btn variant="flat" v-if="operation != 'view'" :color="submitColor" @click="submit" :loading="store.loading">
277
+ <v-btn variant="flat" v-if="operation != 'view'" :class="entity.submitBtnFormClass" @click="submit" :loading="store.loading">
269
278
  {{ operation ? t('action.' + operation) : t('action.sent') }}
270
279
  </v-btn>
271
280
  </v-card-actions>
@@ -8,9 +8,12 @@ import {useCrudStore} from "../stores/UseCrudStore";
8
8
  import {VDateInput} from 'vuetify/labs/VDateInput'
9
9
  import type {IEntityCrud, IEntityCrudField, IEntityCrudFilter} from "@drax/crud-share";
10
10
  import {MediaField, MediaFullField} from "@drax/media-vue";
11
+ import {useAuth} from "@drax/identity-vue";
11
12
 
12
13
  const {t, te} = useI18n()
13
14
 
15
+ const {hasPermission} = useAuth()
16
+
14
17
  const store = useCrudStore()
15
18
 
16
19
  const valueModel = defineModel<any>({type: [String, Number, Boolean, Object, Array], default: false})
@@ -69,7 +72,7 @@ defineEmits(['updateValue'])
69
72
 
70
73
  <template>
71
74
 
72
- <div v-if="field && field.type">
75
+ <div v-if="field && field.type && (!field.permission || hasPermission(field.permission) )">
73
76
  <v-text-field
74
77
  v-if="field.type === 'string'"
75
78
  type="text"
@@ -163,6 +166,7 @@ defineEmits(['updateValue'])
163
166
  :append-icon="appendIcon"
164
167
  :prepend-inner-icon="prependInnerIcon"
165
168
  :append-inner-icon="appendInnerIcon"
169
+
166
170
  >
167
171
  </v-combobox>
168
172
 
@@ -165,9 +165,10 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
165
165
  />
166
166
 
167
167
  <crud-update-button
168
- v-if="entity.isEditable && hasPermission(entity.permissions.update)"
168
+ v-if="entity.isEditable && entity.isItemEditable(item) && hasPermission(entity.permissions.update)"
169
169
  @click="$emit('edit', item)"
170
170
  />
171
+
171
172
  <crud-delete-button
172
173
  v-if="entity.isDeletable && hasPermission(entity.permissions.delete)"
173
174
  @click="$emit('delete', item)"
@@ -2,11 +2,14 @@ import type {IDraxPaginateResult, IEntityCrud} from "@drax/crud-share";
2
2
  import {useCrudStore} from "../stores/UseCrudStore";
3
3
  import {computed, nextTick, toRaw} from "vue";
4
4
  import getItemId from "../helpers/getItemId";
5
+ import { useI18n } from "vue-i18n";
5
6
 
6
7
  export function useCrud(entity: IEntityCrud) {
7
8
 
8
9
  const store = useCrudStore()
9
10
 
11
+ const { t: $t } = useI18n()
12
+
10
13
  const exportError = computed({
11
14
  get() {
12
15
  return store.exportError
@@ -174,11 +177,13 @@ export function useCrud(entity: IEntityCrud) {
174
177
  }
175
178
 
176
179
  const headers: string = entity.exportHeaders.join(',')
180
+ const headersTranslate: string | undefined = entity.exportHeadersTranslate?.map(t => $t(t)).join(',')
177
181
  const fileName: string = entity.exportFileName
178
182
 
179
183
  const r: any = await entity?.provider.export({
180
184
  format: format,
181
185
  headers: headers,
186
+ headersTranslate: headersTranslate,
182
187
  separator: ";",
183
188
  fileName: fileName,
184
189
  orderBy: store.sortBy[0]?.key,