@drax/crud-vue 0.5.3 → 0.5.5

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.5.3",
6
+ "version": "0.5.5",
7
7
  "type": "module",
8
8
  "main": "./src/index.ts",
9
9
  "module": "./src/index.ts",
@@ -24,9 +24,9 @@
24
24
  "format": "prettier --write src/"
25
25
  },
26
26
  "dependencies": {
27
- "@drax/common-front": "^0.5.1",
27
+ "@drax/common-front": "^0.5.5",
28
28
  "@drax/crud-front": "^0.5.3",
29
- "@drax/crud-share": "^0.5.3"
29
+ "@drax/crud-share": "^0.5.5"
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": "56ea5a743bce196d6322ae6c26ea5b041450d7a3"
66
+ "gitHead": "c89751dd8eb2ede7d565b596f698c2b83e0c2fed"
67
67
  }
package/src/EntityCrud.ts CHANGED
@@ -40,6 +40,14 @@ class EntityCrud implements IEntityCrud{
40
40
  ]
41
41
  }
42
42
 
43
+ get createFields(){
44
+ return this.fields
45
+ }
46
+
47
+ get updateFields(){
48
+ return this.fields
49
+ }
50
+
43
51
  get filters():IEntityCrudFilter[]{
44
52
  return [
45
53
  {name: '_id', type: 'string', label: 'ID', default: '', operator: 'eq' },
@@ -104,6 +112,10 @@ class EntityCrud implements IEntityCrud{
104
112
  return field && this.rules[field] && this.rules[field].length > 0 ? this.rules[field] : undefined
105
113
  }
106
114
 
115
+ get isViewable(){
116
+ return true
117
+ }
118
+
107
119
  get isEditable(){
108
120
  return true
109
121
  }
@@ -12,7 +12,7 @@ const {entity} = defineProps({
12
12
  })
13
13
 
14
14
  const {
15
- onCreate, onEdit, onDelete, onCancel, onSubmit,resetCrudStore,
15
+ onView, onCreate, onEdit, onDelete, onCancel, onSubmit, resetCrudStore,
16
16
  operation, dialog, form, notify, error, message, doExport,
17
17
  prepareFilters
18
18
  } = useCrud(entity);
@@ -34,12 +34,20 @@ onBeforeMount(() => {
34
34
  @edit="onEdit"
35
35
  @delete="onDelete"
36
36
  @export="doExport"
37
+ @view="onView"
37
38
  >
38
39
  <template v-for="header in entity.headers" :key="header.key" v-slot:[`item.${header.key}`]="{item, value}">
39
40
  <slot :name="`item.${header.key}`" v-bind="{item, value}">
40
- {{ value }}
41
+ {{ (Array.isArray(value) && value.length > 0) || !Array.isArray(value) ? value : '' }}
41
42
  </slot>
42
43
  </template>
44
+
45
+
46
+ <template v-slot:item.actions="{item}">
47
+ <slot name="item.actions" v-bind="{item}">
48
+ </slot>
49
+ </template>
50
+
43
51
  </crud-list>
44
52
  </v-card>
45
53
 
@@ -3,16 +3,20 @@ 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";
7
6
 
8
7
  const valueModel = defineModel<string | string[]>({type: [String, Array], required: false})
9
8
 
10
9
  const {entity, multiple} = defineProps({
11
10
  entity: {type: Object as PropType<IEntityCrud|undefined>, required: true},
12
11
  field: {type: Object as PropType<IEntityCrudField>, required: true},
12
+ prependIcon: {type: String},
13
+ prependInnerIcon: {type: String},
14
+ appendIcon: {type: String},
15
+ appendInnerIcon: {type: String},
13
16
  multiple: {type: Boolean, default: false},
14
17
  chips: {type: Boolean, default: false},
15
18
  closableChips: {type: Boolean, default: true},
19
+ readonly: {type: Boolean, default: false},
16
20
  clearable: {type: Boolean, default: true},
17
21
  label: {type: String},
18
22
  itemValue: {type: [String], default: '_id'},
@@ -34,63 +38,59 @@ const items: Ref<Array<any>> = ref([])
34
38
 
35
39
  const debouncedSearch = debounce(search, 300)
36
40
 
37
- onBeforeMount(async () => {
38
- if(valueModel.value && valueModel.value.length > 0){
39
-
40
- if(multiple && Array.isArray(valueModel.value) ){
41
- items.value = valueModel.value
42
-
43
- // valueModel.value = valueModel.value.map((item:any) => item._id)
44
- await findByIds(valueModel.value)
45
- }else if(!Array.isArray(valueModel.value)){
46
- // items.value = [valueModel.value]
47
- await findByIds([valueModel.value])
48
- }
49
-
50
-
51
-
52
- }
53
- })
54
-
55
- async function findByIds(ids: Array<string> = []) {
41
+ async function search(value: any) {
56
42
  try{
43
+ loading.value = true
57
44
  if(!entity){
58
45
  throw new Error('Entity is required')
59
46
  }
60
- if(!entity.provider){
61
- throw new Error('Provider is not defined')
62
- }
63
- if (typeof entity.provider.findByIds !== 'function') {
64
- throw new Error('Provider does not have a findByIds method');
47
+ if(!entity.provider.search){
48
+ throw new Error('Provider does not have a search method')
65
49
  }
66
- loading.value = true
67
- items.value = await entity.provider.findByIds(ids)
50
+ items.value = await entity.provider.search(value)
68
51
  }catch (e){
69
52
  console.error(e)
70
53
  }finally{
71
54
  loading.value = false
72
55
  }
56
+
73
57
  }
74
58
 
59
+ onBeforeMount(async () => {
75
60
 
76
- async function search(value: any) {
61
+ await search('')
62
+ await checkIds()
63
+ })
64
+
65
+ async function checkIds(ids: Array<string> = []) {
77
66
  try{
78
- loading.value = true
79
- if(!entity){
80
- throw new Error('Entity is required')
81
- }
82
- if(!entity.provider.search){
83
- throw new Error('Provider does not have a search method')
67
+
68
+ if(valueModel.value) {
69
+ let ids = Array.isArray(valueModel.value) ? valueModel.value : [valueModel.value]
70
+ for (let id of ids) {
71
+ if (!items.value.some((item: any) => item._id === id)) {
72
+ if (!entity) {
73
+ throw new Error('CrudAutocomplete Entity is required')
74
+ }
75
+ if (!entity.provider) {
76
+ throw new Error('CrudAutocomplete Provider is not defined')
77
+ }
78
+ if (typeof entity.provider.findById !== 'function') {
79
+ throw new Error('CrudAutocomplete Provider does not have a findById method');
80
+ }
81
+ let item = await entity.provider.findById(id)
82
+ items.value.push(item)
83
+ }
84
+ }
84
85
  }
85
- items.value = await entity.provider.search(value)
86
86
  }catch (e){
87
87
  console.error(e)
88
- }finally{
89
- loading.value = false
90
88
  }
91
-
92
89
  }
93
90
 
91
+
92
+
93
+
94
94
  defineEmits(['updateValue'])
95
95
 
96
96
  </script>
@@ -108,6 +108,7 @@ defineEmits(['updateValue'])
108
108
  :item-title="itemTitle"
109
109
  :loading="loading"
110
110
  :rules="rules"
111
+ :readonly="readonly"
111
112
  :density="density"
112
113
  :variant="variant"
113
114
  :hide-details="hideDetails"
@@ -116,6 +117,10 @@ defineEmits(['updateValue'])
116
117
  :error-messages="errorMessages"
117
118
  @update:search="debouncedSearch"
118
119
  @update:modelValue="$emit('updateValue')"
120
+ :prepend-icon="prependIcon"
121
+ :append-icon="appendIcon"
122
+ :prepend-inner-icon="prependInnerIcon"
123
+ :append-inner-icon="appendInnerIcon"
119
124
  ></v-autocomplete>
120
125
  </template>
121
126
 
@@ -1,27 +1,39 @@
1
1
  <script setup lang="ts">
2
- import type {TOperation} from "../interfaces/TOperation";
2
+ import {computed} from "vue";
3
3
  import type {PropType} from "vue";
4
- import type {IEntityCrud} from "@drax/crud-share";
4
+ import type {IEntityCrud, IEntityCrudOperation} from "@drax/crud-share";
5
5
  const dialog = defineModel({type: Boolean, default: false})
6
6
  import {useI18n} from "vue-i18n";
7
7
  const {t,te} = useI18n()
8
8
 
9
- defineProps({
9
+ const {operation,entity } = defineProps({
10
10
  entity: {type: Object as PropType<IEntityCrud>, required: true},
11
- operation: {type: String as PropType<TOperation>}
11
+ operation: {type: String as PropType<IEntityCrudOperation>}
12
12
  })
13
13
 
14
14
  defineEmits(
15
15
  ['submit', 'close']
16
16
  )
17
17
 
18
+ const title = computed(() => {
19
+
20
+
21
+
22
+ if(te('operation.'+operation)){
23
+ const entityNameLocale = t(entity.name.toLowerCase()+'.entity')
24
+ return t('operation.'+operation,{entity: entityNameLocale })
25
+ }else{
26
+ return operation
27
+ }
28
+ })
29
+
18
30
  </script>
19
31
 
20
32
  <template>
21
33
  <v-dialog v-model="dialog" :fullscreen="entity.dialogFullscreen">
22
34
  <v-card>
23
35
  <v-toolbar>
24
- <v-toolbar-title>{{entity.name}} {{te('action.'+operation) ? t('action.'+operation) : operation}}</v-toolbar-title>
36
+ <v-toolbar-title>{{title}}</v-toolbar-title>
25
37
  <v-spacer></v-spacer>
26
38
  <v-btn icon @click="dialog = false"><v-icon>mdi-close</v-icon></v-btn>
27
39
  </v-toolbar>
@@ -39,6 +39,7 @@ const emit = defineEmits(['filter', 'clear','updateValue'])
39
39
  :field="filter"
40
40
  :entity="entity"
41
41
  v-model="valueModel[index].value"
42
+ :clearable="true"
42
43
  density="compact"
43
44
  variant="outlined"
44
45
  hide-details single-line disable-rules
@@ -1,26 +1,43 @@
1
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 {TOperation} from "../interfaces/TOperation";
6
- import type {IEntityCrud} from "@drax/crud-share";
7
2
  import {useI18n} from "vue-i18n";
3
+ import type {IEntityCrud, IEntityCrudOperation} from "@drax/crud-share";
4
+ import {useFormUtils} from "../composables/UseFormUtils";
5
+ import CrudFormField from "./CrudFormField.vue";
6
+ import {computed, defineEmits, defineModel, defineProps, ref} from "vue";
7
+ import type { PropType} from "vue";
8
8
  import {useCrudStore} from "../stores/UseCrudStore";
9
- const {t,te} = useI18n()
10
- const store = useCrudStore()
11
- const valueModel = defineModel({type: [Object]})
12
9
 
13
10
 
14
- const {entity} = defineProps({
11
+ const {t, te} = useI18n()
12
+
13
+ const valueModel = defineModel({type: [Object]})
14
+
15
+ const {entity, operation} = defineProps({
15
16
  entity: {type: Object as PropType<IEntityCrud>, required: true},
16
- operation: {type: String as PropType<TOperation>, required: true},
17
+ operation: {type: String as PropType<IEntityCrudOperation>, required: true},
17
18
  readonly: {type: Boolean, default: false},
18
19
  error: {type: String, required: false},
19
20
  })
20
21
 
22
+ const emit = defineEmits(['submit', 'cancel'])
23
+
24
+ const store = useCrudStore()
25
+
21
26
  const valid = ref()
22
27
  const formRef = ref()
23
28
 
29
+ const fields = computed(() => {
30
+ if(operation === 'create') {
31
+ return entity.createFields
32
+ }else if(operation === 'edit') {
33
+ return entity.updateFields
34
+ }else if(operation === 'delete') {
35
+ return entity.updateFields
36
+ }else if(operation === 'view') {
37
+ return entity.updateFields
38
+ }
39
+ })
40
+
24
41
  async function submit() {
25
42
  store.resetErrors()
26
43
  await formRef.value.validate()
@@ -35,7 +52,10 @@ function cancel() {
35
52
  emit('cancel')
36
53
  }
37
54
 
38
- const emit = defineEmits(['submit', 'cancel'])
55
+ const {
56
+ variant, submitColor, readonly
57
+ } = useFormUtils(operation)
58
+
39
59
 
40
60
  </script>
41
61
 
@@ -48,12 +68,20 @@ const emit = defineEmits(['submit', 'cancel'])
48
68
  <v-card-text v-if="error">
49
69
  <v-alert color="error">{{ te(error) ? t(error) : error }}</v-alert>
50
70
  </v-card-text>
71
+
51
72
  <v-card-text>
52
- <template v-for="field in entity.fields" :key="field.name">
73
+ <template v-for="field in fields" :key="field.name">
53
74
  <crud-form-field
54
75
  :field="field"
55
76
  :entity="entity"
56
77
  v-model="valueModel[field.name]"
78
+ :clearable="false"
79
+ :readonly="readonly"
80
+ :variant="variant"
81
+ :prepend-inner-icon="field?.prependInnerIcon"
82
+ :prepend-icon="field?.prependIcon"
83
+ :append-icon="field?.appendIcon"
84
+ :append-inner-icon="field?.appendInnerIcon"
57
85
  />
58
86
  </template>
59
87
  </v-card-text>
@@ -61,7 +89,7 @@ const emit = defineEmits(['submit', 'cancel'])
61
89
  <v-card-actions>
62
90
  <v-spacer></v-spacer>
63
91
  <v-btn variant="text" color="grey" @click="cancel">{{ t('action.cancel') }}</v-btn>
64
- <v-btn variant="flat" color="primary" @click="submit">
92
+ <v-btn variant="flat" v-if="operation != 'view'" :color="submitColor" @click="submit">
65
93
  {{ operation ? t('action.' + operation) : t('action.sent') }}
66
94
  </v-btn>
67
95
  </v-card-actions>
@@ -16,10 +16,14 @@ const valueModel = defineModel<any>({type: [String, Number, Boolean, Object, Arr
16
16
  const {index, entity, field, disableRules} = defineProps({
17
17
  entity: {type: Object as PropType<IEntityCrud>, required: true},
18
18
  field: {type: Object as PropType<IEntityCrudField|IEntityCrudFilter|undefined>, required: true},
19
+ prependIcon: {type: String, default: ''},
20
+ prependInnerIcon: {type: String, default: ''},
21
+ appendIcon: {type: String, default: ''},
22
+ appendInnerIcon: {type: String, default: ''},
19
23
  readonly: {type: Boolean, default: false},
20
24
  hideDetails: {type: Boolean, default: false},
21
25
  singleLine: {type: Boolean, default: false},
22
- clearable: {type: Boolean, default: true},
26
+ clearable: {type: Boolean, default: false},
23
27
  disableRules: {type: Boolean, default: false},
24
28
  index: {type: Number, default: 0},
25
29
  density: {type: String as PropType<'comfortable' | 'compact' | 'default'>, default: 'default'},
@@ -35,7 +39,7 @@ if(!field){
35
39
  const name = computed(() => index > 0 ? `${field.name}_${index}` : field.name)
36
40
 
37
41
  const label = computed(() => {
38
- const i18n = `${entity.name}.fields.${field.name}`
42
+ const i18n = `${entity.name}.field.${field.name}`
39
43
  return te(i18n) ? t(i18n) : field.label
40
44
  })
41
45
 
@@ -69,9 +73,12 @@ defineEmits(['updateValue'])
69
73
  :clearable="clearable"
70
74
  :hide-details="hideDetails"
71
75
  :single-line="singleLine"
76
+ :prepend-icon="prependIcon"
77
+ :append-icon="appendIcon"
78
+ :prepend-inner-icon="prependInnerIcon"
79
+ :append-inner-icon="appendInnerIcon"
72
80
  @update:modelValue="$emit('updateValue')"
73
- >
74
- </v-text-field>
81
+ />
75
82
 
76
83
  <v-text-field
77
84
  v-if="field.type === 'number'"
@@ -88,10 +95,13 @@ defineEmits(['updateValue'])
88
95
  :hide-details="hideDetails"
89
96
  :single-line="singleLine"
90
97
  @update:modelValue="$emit('updateValue')"
91
- >
92
- </v-text-field>
98
+ :prepend-icon="prependIcon"
99
+ :append-icon="appendIcon"
100
+ :prepend-inner-icon="prependInnerIcon"
101
+ :append-inner-icon="appendInnerIcon"
102
+ />
93
103
 
94
- <v-checkbox
104
+ <v-switch
95
105
  v-if="field.type === 'boolean'"
96
106
  :name="name"
97
107
  :label="label"
@@ -105,8 +115,12 @@ defineEmits(['updateValue'])
105
115
  :hide-details="hideDetails"
106
116
  :single-line="singleLine"
107
117
  @update:modelValue="$emit('updateValue')"
108
- >
109
- </v-checkbox>
118
+ :prepend-icon="prependIcon"
119
+ :append-icon="appendIcon"
120
+ :prepend-inner-icon="prependInnerIcon"
121
+ :append-inner-icon="appendInnerIcon"
122
+ color="primary"
123
+ />
110
124
 
111
125
 
112
126
  <v-date-input
@@ -117,8 +131,6 @@ defineEmits(['updateValue'])
117
131
  v-model="valueModel"
118
132
  :readonly="readonly"
119
133
  :error-messages="inputErrors"
120
- prepend-inner-icon="mdi-calendar"
121
- prepend-icon=""
122
134
  :rules="rules"
123
135
  :density="density"
124
136
  :variant="variant"
@@ -126,6 +138,10 @@ defineEmits(['updateValue'])
126
138
  :hide-details="hideDetails"
127
139
  :single-line="singleLine"
128
140
  @update:modelValue="$emit('updateValue')"
141
+ :prepend-icon="prependIcon"
142
+ :append-icon="appendIcon"
143
+ :prepend-inner-icon="prependInnerIcon"
144
+ :append-inner-icon="appendInnerIcon"
129
145
  />
130
146
 
131
147
  <crud-autocomplete
@@ -138,10 +154,15 @@ defineEmits(['updateValue'])
138
154
  :rules="rules"
139
155
  :density="density"
140
156
  :variant="variant"
157
+ :readonly="readonly"
141
158
  :clearable="clearable"
142
159
  :hide-details="hideDetails"
143
160
  :single-line="singleLine"
144
161
  @updateValue="$emit('updateValue')"
162
+ :prepend-icon="prependIcon"
163
+ :append-icon="appendIcon"
164
+ :prepend-inner-icon="prependInnerIcon"
165
+ :append-inner-icon="appendInnerIcon"
145
166
  />
146
167
 
147
168
  <v-card v-if="field.type === 'object'" class="mt-3" variant="flat" border>
@@ -159,6 +180,10 @@ defineEmits(['updateValue'])
159
180
  :hide-details="hideDetails"
160
181
  :single-line="singleLine"
161
182
  @updateValue="$emit('updateValue')"
183
+ :prepend-icon="prependIcon"
184
+ :append-icon="appendIcon"
185
+ :prepend-inner-icon="prependInnerIcon"
186
+ :append-inner-icon="appendInnerIcon"
162
187
  ></crud-form-field>
163
188
  </v-card-text>
164
189
 
@@ -182,6 +207,10 @@ defineEmits(['updateValue'])
182
207
  :single-line="singleLine"
183
208
  :rules="rules"
184
209
  @update:modelValue="$emit('updateValue')"
210
+ :prepend-icon="prependIcon"
211
+ :append-icon="appendIcon"
212
+ :prepend-inner-icon="prependInnerIcon"
213
+ :append-inner-icon="appendInnerIcon"
185
214
  >
186
215
  </v-combobox>
187
216
 
@@ -202,6 +231,10 @@ defineEmits(['updateValue'])
202
231
  :hide-details="hideDetails"
203
232
  :single-line="singleLine"
204
233
  @updateValue="$emit('updateValue')"
234
+ :prepend-icon="prependIcon"
235
+ :append-icon="appendIcon"
236
+ :prepend-inner-icon="prependInnerIcon"
237
+ :append-inner-icon="appendInnerIcon"
205
238
  />
206
239
 
207
240
 
@@ -222,6 +255,10 @@ defineEmits(['updateValue'])
222
255
  :single-line="singleLine"
223
256
  :rules="rules"
224
257
  @update:modelValue="$emit('updateValue')"
258
+ :prepend-icon="prependIcon"
259
+ :append-icon="appendIcon"
260
+ :prepend-inner-icon="prependInnerIcon"
261
+ :append-inner-icon="appendInnerIcon"
225
262
  >
226
263
  </v-combobox>
227
264
 
@@ -2,7 +2,6 @@
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";
6
5
 
7
6
  const valueModel = defineModel({type: Array, default: () => []});
8
7
 
@@ -8,6 +8,7 @@ import CrudImportButton from "./buttons/CrudImportButton.vue";
8
8
  import CrudCreateButton from "./buttons/CrudCreateButton.vue";
9
9
  import CrudUpdateButton from "./buttons/CrudUpdateButton.vue";
10
10
  import CrudDeleteButton from "./buttons/CrudDeleteButton.vue";
11
+ import CrudViewButton from "./buttons/CrudViewButton.vue";
11
12
  import CrudExportList from "./CrudExportList.vue";
12
13
  import type {IEntityCrud} from "@drax/crud-share";
13
14
  import {useI18n} from "vue-i18n";
@@ -31,12 +32,12 @@ const actions: IEntityCrudHeader[] = [{
31
32
  title: t('action.actions'),
32
33
  key: 'actions',
33
34
  sortable: false,
34
- align: 'end',
35
- minWidth: '140px'
35
+ align: 'center',
36
+ minWidth: '190px'
36
37
  }]
37
38
  const tHeaders: IEntityCrudHeader[] = entity.headers.map(header => ({
38
39
  ...header,
39
- title: te(`${entity.name.toLowerCase()}.fields.${header.title}`) ? t(`${entity.name.toLowerCase()}.fields.${header.title}`) : header.title
40
+ title: te(`${entity.name.toLowerCase()}.field.${header.title}`) ? t(`${entity.name.toLowerCase()}.field.${header.title}`) : header.title
40
41
  }))
41
42
 
42
43
  const headers: IEntityCrudHeader[] = [...tHeaders, ...actions]
@@ -46,6 +47,8 @@ defineExpose({
46
47
  doPaginate
47
48
  });
48
49
 
50
+ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
51
+
49
52
  </script>
50
53
 
51
54
  <template>
@@ -67,7 +70,7 @@ defineExpose({
67
70
  >
68
71
  <template v-slot:top>
69
72
  <v-toolbar density="compact">
70
- <v-toolbar-title>{{ entity.name }}</v-toolbar-title>
73
+ <v-toolbar-title>{{ te(`${entity.name.toLowerCase()}.crud`) ? t(`${entity.name.toLowerCase()}.crud`) : entity.name }}</v-toolbar-title>
71
74
  <v-spacer></v-spacer>
72
75
 
73
76
  <crud-import-button
@@ -120,6 +123,15 @@ defineExpose({
120
123
 
121
124
 
122
125
  <template v-slot:item.actions="{item}">
126
+
127
+ <slot name="item.actions" v-bind="{item}">
128
+ </slot>
129
+
130
+ <crud-view-button
131
+ v-if="entity.isViewable && hasPermission(entity.permissions.view)"
132
+ @click="$emit('view', item)"
133
+ />
134
+
123
135
  <crud-update-button
124
136
  v-if="entity.isEditable && hasPermission(entity.permissions.update)"
125
137
  @click="$emit('edit', item)"
@@ -128,6 +140,7 @@ defineExpose({
128
140
  v-if="entity.isDeletable && hasPermission(entity.permissions.delete)"
129
141
  @click="$emit('delete', item)"
130
142
  />
143
+
131
144
  </template>
132
145
 
133
146
  </v-data-table-server>
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ import {useI18n} from "vue-i18n";
3
+ const {t} = useI18n()
4
+ </script>
5
+
6
+ <template>
7
+ <v-tooltip location="top">
8
+ <template v-slot:activator="{ props}">
9
+ <v-btn
10
+ v-bind="{ ...$attrs, ...props }"
11
+ icon="mdi-magnify"
12
+ class="mr-1"
13
+ variant="text"
14
+ color="secondary"
15
+ slim
16
+ >
17
+ </v-btn>
18
+ </template>
19
+ {{ t('action.view')}}
20
+ </v-tooltip>
21
+ </template>
22
+
23
+ <style scoped>
24
+
25
+ </style>
@@ -83,13 +83,6 @@ export function useCrud(entity: IEntityCrud) {
83
83
 
84
84
 
85
85
 
86
-
87
- function onCreate() {
88
- store.setOperation("create")
89
- store.setForm(entity.form)
90
- store.setDialog(true)
91
- }
92
-
93
86
  function cast(item: any){
94
87
  entity.fields.filter(field => field.type === 'date')
95
88
  .forEach(field => {
@@ -98,31 +91,44 @@ export function useCrud(entity: IEntityCrud) {
98
91
 
99
92
  entity.fields.filter(field => field.type === 'ref')
100
93
  .forEach(field => {
101
- item[field.name] = item[field.name]._id
94
+ item[field.name] = item[field.name]?._id ? item[field.name]._id : item[field.name]
102
95
  })
103
96
 
104
97
  entity.fields.filter(field => field.type === 'array.ref')
105
98
  .forEach(field => {
106
- item[field.name] = item[field.name].map(((i:any) => i._id))
99
+ item[field.name] = item[field.name].map(((i:any) => i?._id ? i._id : i))
107
100
  })
108
101
 
109
102
  return item
110
103
  }
111
104
 
105
+ function onView(item: object) {
106
+ store.setOperation("view")
107
+ store.setForm(cast({...item}))
108
+ openDialog()
109
+ }
110
+
111
+
112
+ function onCreate() {
113
+ store.setOperation("create")
114
+ store.setForm(entity.form)
115
+ openDialog()
116
+ }
117
+
112
118
  function onEdit(item: object) {
113
119
  store.setOperation("edit")
114
120
  store.setForm(cast({...item}))
115
- store.setDialog(true)
121
+ openDialog()
116
122
  }
117
123
 
118
124
  function onDelete(item: object) {
119
125
  store.setOperation("delete")
120
126
  store.setForm(cast({...item}))
121
- store.setDialog(true)
127
+ openDialog()
122
128
  }
123
129
 
124
130
  function onCancel() {
125
- store.setDialog(false)
131
+ closeDialog()
126
132
  store.setError("")
127
133
  store.setInputErrors(null)
128
134
  }
@@ -130,6 +136,9 @@ export function useCrud(entity: IEntityCrud) {
130
136
  function onSubmit(formData: any) {
131
137
  store.setInputErrors(null)
132
138
  switch (store.operation) {
139
+ case "view":
140
+ closeDialog()
141
+ break
133
142
  case "create":
134
143
  doCreate(formData)
135
144
  break
@@ -142,11 +151,19 @@ export function useCrud(entity: IEntityCrud) {
142
151
  }
143
152
  }
144
153
 
154
+ function openDialog() {
155
+ store.setDialog(true)
156
+ }
157
+
158
+ function closeDialog() {
159
+ store.setDialog(false)
160
+ }
161
+
145
162
  async function doCreate(formData: any) {
146
163
  try {
147
164
  await entity?.provider.create(formData)
148
165
  await doPaginate()
149
- store.setDialog(false)
166
+ closeDialog()
150
167
  store.showMessage("Entity created successfully!")
151
168
  } catch (e: any) {
152
169
  if(e.inputErrors){
@@ -162,7 +179,7 @@ export function useCrud(entity: IEntityCrud) {
162
179
  try {
163
180
  await entity?.provider.update(formData._id, formData)
164
181
  await doPaginate()
165
- store.setDialog(false)
182
+ closeDialog()
166
183
  store.showMessage("Entity updated successfully!")
167
184
  } catch (e: any) {
168
185
  console.log("inputErrors", e.inputErrors)
@@ -179,7 +196,7 @@ export function useCrud(entity: IEntityCrud) {
179
196
  try {
180
197
  await entity?.provider.delete(formData._id)
181
198
  await doPaginate()
182
- store.setDialog(false)
199
+ closeDialog()
183
200
  store.showMessage("Entity deleted successfully!")
184
201
  } catch (e: any) {
185
202
  store.setError(e.message || "An error occurred while deleting the entity")
@@ -198,7 +215,7 @@ export function useCrud(entity: IEntityCrud) {
198
215
 
199
216
 
200
217
  return {
201
- doPaginate, doExport, onCreate, onEdit, onDelete, onCancel, onSubmit,resetCrudStore,
218
+ doPaginate, doExport, onView, onCreate, onEdit, onDelete, onCancel, onSubmit,resetCrudStore,
202
219
  operation, dialog, form, notify, error, message, formValid,
203
220
  loading, itemsPerPage, page, sortBy, search, totalItems, items,
204
221
  prepareFilters,filters,
@@ -0,0 +1,42 @@
1
+ import type {IEntityCrudOperation} from "@drax/crud-share";
2
+ import {computed} from "vue";
3
+
4
+
5
+ export function useFormUtils(operation:IEntityCrudOperation) {
6
+
7
+ const readonly = computed(() => {
8
+ return operation === 'delete' || operation === 'view';
9
+ })
10
+
11
+ const submitColor = computed(() => {
12
+ if(operation === 'create') {
13
+ return 'primary'
14
+ }else if(operation === 'edit') {
15
+ return 'primary'
16
+ }else if(operation === 'delete') {
17
+ return 'red'
18
+ }else if(operation === 'view') {
19
+ return 'secondary'
20
+ }
21
+ })
22
+
23
+ const variant = computed(() => {
24
+ if(operation === 'create') {
25
+ return 'filled'
26
+ }else if(operation === 'edit') {
27
+ return 'filled'
28
+ }else if(operation === 'delete') {
29
+ return 'underlined'
30
+ }else if(operation === 'view') {
31
+ return 'underlined'
32
+ }
33
+ })
34
+
35
+
36
+
37
+ return {
38
+ readonly,
39
+ variant,
40
+ submitColor,
41
+ }
42
+ }
package/src/index.ts CHANGED
@@ -8,6 +8,7 @@ import CrudNotify from "./components/CrudNotify.vue";
8
8
  import CrudSearch from "./components/CrudSearch.vue";
9
9
  import {useCrudStore} from "./stores/UseCrudStore";
10
10
  import {useCrud} from "./composables/UseCrud";
11
+ import {useFormUtils} from "./composables/UseFormUtils";
11
12
  import {EntityCrud} from "./EntityCrud";
12
13
 
13
14
 
@@ -21,6 +22,7 @@ export {
21
22
  CrudNotify,
22
23
  CrudSearch,
23
24
  useCrud,
25
+ useFormUtils,
24
26
  useCrudStore,
25
27
  EntityCrud
26
28
 
@@ -1,10 +1,10 @@
1
1
  import {defineStore} from "pinia";
2
- import type {TOperation} from "../interfaces/TOperation";
2
+ import type {IEntityCrudOperation} from "@drax/crud-share";
3
3
 
4
4
  export const useCrudStore = defineStore('CrudStore', {
5
5
  state: () => (
6
6
  {
7
- operation: null as TOperation,
7
+ operation: null as IEntityCrudOperation,
8
8
  dialog: false as boolean,
9
9
  form: {} as any,
10
10
  formValid: {} as any,
@@ -36,7 +36,7 @@ export const useCrudStore = defineStore('CrudStore', {
36
36
  }
37
37
  },
38
38
  actions: {
39
- setOperation(operation: TOperation) {
39
+ setOperation(operation: IEntityCrudOperation) {
40
40
  this.operation = operation
41
41
  },
42
42
  setDialog(dialog: boolean) {
@@ -1,6 +0,0 @@
1
- type TOperation = "create" | "edit" | "delete" | null
2
-
3
-
4
- export type {
5
- TOperation
6
- }