@drax/crud-vue 0.31.0 → 0.33.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.33.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.33.0",
28
+ "@drax/crud-front": "^0.33.0",
29
+ "@drax/crud-share": "^0.33.0",
30
+ "@drax/media-vue": "^0.33.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": "2a006597a635f61776d252f92bb3899371244379"
68
68
  }
package/src/EntityCrud.ts CHANGED
@@ -1,258 +1,276 @@
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
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
- }
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'
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
43
91
  }
44
- }
45
92
 
46
- get provider(): IDraxCrudProvider<any, any, any> {
47
- throw new Error('provider not implemented')
93
+ })
48
94
  }
95
+ return value
96
+ }
49
97
 
50
- get fields(): IEntityCrudField[] {
51
- return [
52
- {name: '_id', type: 'string', label: 'ID', default: ''},
53
- ]
54
- }
98
+ get form(): IEntityCrudForm {
55
99
 
56
- get createFields() {
57
- return this.fields
58
- }
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
+ }
59
111
 
60
- get updateFields() {
61
- return this.fields
62
- }
112
+ return {...acc, [field.name]: value}
113
+ }, {})
63
114
 
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
- }
92
-
93
- })
94
- }
95
- return value
96
- }
115
+ }
97
116
 
98
- get form(): IEntityCrudForm {
99
117
 
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
- }
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
+ }
111
124
 
112
- return {...acc, [field.name]: value}
113
- }, {})
125
+ get refs(): IEntityCrudRefs {
126
+ return {}
127
+ }
114
128
 
129
+ getRef(ref: string): IEntityCrud {
130
+ if (!this.refs.hasOwnProperty(ref)) {
131
+ throw new Error("Ref not found: " + ref)
115
132
  }
116
133
 
134
+ return this.refs[ref]
135
+ }
117
136
 
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
- }
137
+ get rules(): IEntityCrudRules {
138
+ return {}
139
+ }
124
140
 
125
- get refs(): IEntityCrudRefs {
126
- return {}
127
- }
141
+ getRule(field: string | undefined): Array<Function> | undefined {
142
+ return field && this.rules[field] && this.rules[field].length > 0 ? this.rules[field] : undefined
143
+ }
128
144
 
129
- getRef(ref: string): IEntityCrud {
130
- if (!this.refs.hasOwnProperty(ref)) {
131
- throw new Error("Ref not found: " + ref)
132
- }
145
+ get isViewable() {
146
+ return true
147
+ }
133
148
 
134
- return this.refs[ref]
135
- }
149
+ get isEditable() {
150
+ return true
151
+ }
136
152
 
137
- get rules(): IEntityCrudRules {
138
- return {}
139
- }
153
+ isItemEditable():boolean {
154
+ return true
155
+ }
140
156
 
141
- getRule(field: string | undefined): Array<Function> | undefined {
142
- return field && this.rules[field] && this.rules[field].length > 0 ? this.rules[field] : undefined
143
- }
157
+ get isCreatable() {
158
+ return true
159
+ }
144
160
 
145
- get isViewable() {
146
- return true
147
- }
161
+ get isDeletable() {
162
+ return true
163
+ }
148
164
 
149
- get isEditable() {
150
- return true
151
- }
165
+ get isExportable() {
166
+ return true
167
+ }
152
168
 
153
- get isCreatable() {
154
- return true
155
- }
169
+ get exportFormats() {
170
+ return ['CSV', 'JSON']
171
+ }
156
172
 
157
- get isDeletable() {
158
- return true
159
- }
173
+ get exportHeaders() {
174
+ return ['_id']
175
+ }
160
176
 
161
- get isExportable() {
162
- return true
163
- }
164
-
165
- get exportFormats() {
166
- return ['CSV', 'JSON']
167
- }
177
+ get exportFileName() {
178
+ return 'export'
179
+ }
168
180
 
169
- get exportHeaders() {
170
- return ['_id']
171
- }
181
+ get isImportable() {
182
+ return true
183
+ }
172
184
 
173
- get exportFileName(){
174
- return 'export'
175
- }
185
+ get importFormats() {
186
+ return ['CSV', 'JSON']
187
+ }
176
188
 
177
- get isImportable() {
178
- return true
179
- }
189
+ get dialogFullscreen() {
190
+ return false
191
+ }
180
192
 
181
- get importFormats() {
182
- return ['CSV', 'JSON']
183
- }
193
+ get dialogMaxWidth() {
194
+ return ''
195
+ }
184
196
 
185
- get dialogFullscreen() {
186
- return false
187
- }
188
197
 
189
- get dialogMaxWidth() {
190
- return ''
191
- }
198
+ get tabs(): string[] {
199
+ return []
200
+ }
192
201
 
193
202
 
194
- get tabs():string[]{
195
- return []
196
- }
203
+ get menus(): string[] {
204
+ return []
205
+ }
197
206
 
207
+ get menuMaxHeight() {
208
+ return '300px'
209
+ }
198
210
 
199
- get menus():string[]{
200
- return []
201
- }
211
+ get dialogZindex() {
212
+ return 1999
213
+ }
202
214
 
203
- get menuMaxHeight(){
204
- return '300px'
205
- }
215
+ get searchEnable() {
216
+ return true
217
+ }
206
218
 
207
- get dialogZindex() {
208
- return 1999
209
- }
219
+ get filterButtons() {
220
+ return true
221
+ }
210
222
 
211
- get searchEnable(){
212
- return true
213
- }
223
+ get containerFluid() {
224
+ return false
225
+ }
214
226
 
215
- get filterButtons(){
216
- return true
217
- }
227
+ get cardDensity(): 'default' | 'comfortable' | 'compact' {
228
+ return 'default'
229
+ }
218
230
 
219
- get containerFluid(){
220
- return false
221
- }
231
+ get cardClass(): string {
232
+ return 'rounded-xl'
233
+ }
222
234
 
223
- get cardDensity() : 'default' | 'comfortable' | 'compact' {
224
- return 'default'
225
- }
235
+ get toolbarDensity(): 'default' | 'comfortable' | 'compact' {
236
+ return 'default'
237
+ }
226
238
 
227
- get cardClass() : string {
228
- return 'rounded-xl'
229
- }
239
+ get toolbarClass(): string {
240
+ return 'bg-primary'
241
+ }
230
242
 
231
- get toolbarDensity() : 'default' | 'comfortable' | 'compact' {
232
- return 'default'
233
- }
243
+ get tableDensity(): 'default' | 'comfortable' | 'compact' {
244
+ return 'default'
245
+ }
234
246
 
235
- get toolbarClass() : string {
236
- return 'bg-primary'
237
- }
247
+ get headerProps() {
248
+ return {class: 'bg-primary'}
249
+ }
238
250
 
239
- get tableDensity() : 'default' | 'comfortable' | 'compact' {
240
- return 'default'
241
- }
251
+ get tableStriped(): null | 'odd' | 'even' {
252
+ return 'even'
253
+ }
242
254
 
243
- get headerProps(){
244
- return { class: 'bg-primary' }
245
- }
255
+ get footerClass() {
256
+ return 'bg-primary'
257
+ }
246
258
 
247
- get tableStriped() : null | 'odd' | 'even' {
248
- return 'even'
249
- }
259
+ get applyFilterClass() {
260
+ return 'bg-primary'
261
+ }
250
262
 
251
- get footerClass(){
252
- return 'bg-primary'
253
- }
263
+ get cleanFilterClass() {
264
+ return 'text-grey'
265
+ }
254
266
 
267
+ get submitBtnFormClass() {
268
+ return 'bg-primary'
269
+ }
255
270
 
271
+ get cancelBtnFormClass() {
272
+ return 'text-grey'
273
+ }
256
274
  }
257
275
 
258
276
  export default EntityCrud;
@@ -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>
@@ -99,7 +99,7 @@ function cancel() {
99
99
  }
100
100
 
101
101
  const {
102
- variant, submitColor
102
+ variant
103
103
  } = useFormUtils(operation.value)
104
104
 
105
105
  const tabInputErrors = computed(() => {
@@ -262,10 +262,10 @@ const menuInputErrors = computed(() => {
262
262
 
263
263
  <v-card-actions>
264
264
  <v-spacer></v-spacer>
265
- <v-btn variant="text" color="grey" @click="cancel">
265
+ <v-btn variant="text" :class="entity.cancelBtnFormClass" @click="cancel">
266
266
  {{ operation == 'view' ? t('action.close') : t('action.cancel') }}
267
267
  </v-btn>
268
- <v-btn variant="flat" v-if="operation != 'view'" :color="submitColor" @click="submit" :loading="store.loading">
268
+ <v-btn variant="flat" v-if="operation != 'view'" :class="entity.submitBtnFormClass" @click="submit" :loading="store.loading">
269
269
  {{ operation ? t('action.' + operation) : t('action.sent') }}
270
270
  </v-btn>
271
271
  </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,