@ramathibodi/nuxt-commons 0.1.21 → 0.1.23

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.
Files changed (46) hide show
  1. package/dist/module.d.mts +1 -1
  2. package/dist/module.d.ts +1 -1
  3. package/dist/module.json +5 -1
  4. package/dist/runtime/components/ExportCSV.vue +22 -13
  5. package/dist/runtime/components/FileBtn.vue +4 -2
  6. package/dist/runtime/components/ImportCSV.vue +24 -14
  7. package/dist/runtime/components/document/TemplateBuilder.vue +1 -1
  8. package/dist/runtime/components/form/SignPad.vue +30 -30
  9. package/dist/runtime/components/form/Table.vue +3 -20
  10. package/dist/runtime/components/form/images/Field.vue +187 -0
  11. package/dist/runtime/components/form/images/Pad.vue +43 -0
  12. package/dist/runtime/components/model/Table.vue +20 -12
  13. package/dist/runtime/components/model/iterator.vue +24 -14
  14. package/dist/runtime/composables/alert.d.ts +1 -1
  15. package/dist/runtime/composables/{alert.mjs → alert.js} +1 -2
  16. package/dist/runtime/composables/api.d.ts +4 -4
  17. package/dist/runtime/composables/api.js +52 -0
  18. package/dist/runtime/composables/document/{template.mjs → template.js} +8 -16
  19. package/dist/runtime/composables/graphql.d.ts +6 -5
  20. package/dist/runtime/composables/{graphql.mjs → graphql.js} +31 -40
  21. package/dist/runtime/composables/graphqlModel.d.ts +18 -17
  22. package/dist/runtime/composables/{graphqlModel.mjs → graphqlModel.js} +26 -36
  23. package/dist/runtime/composables/graphqlModelItem.d.ts +13 -13
  24. package/dist/runtime/composables/{graphqlModelItem.mjs → graphqlModelItem.js} +6 -9
  25. package/dist/runtime/composables/graphqlModelOperation.d.ts +7 -7
  26. package/dist/runtime/composables/{graphqlModelOperation.mjs → graphqlModelOperation.js} +6 -12
  27. package/dist/runtime/composables/graphqlOperation.d.ts +2 -2
  28. package/dist/runtime/composables/{graphqlOperation.mjs → graphqlOperation.js} +15 -28
  29. package/dist/runtime/composables/menu.d.ts +1 -1
  30. package/dist/runtime/composables/{menu.mjs → menu.js} +4 -5
  31. package/dist/runtime/composables/utils/fuzzy.d.ts +1 -1
  32. package/dist/runtime/composables/utils/validation.d.ts +32 -0
  33. package/dist/runtime/plugins/permission.d.ts +1 -1
  34. package/dist/runtime/plugins/{permission.mjs → permission.js} +2 -4
  35. package/dist/runtime/types/menu.d.ts +3 -0
  36. package/dist/runtime/utils/datetime.d.ts +214 -16
  37. package/dist/runtime/utils/{datetime.mjs → datetime.js} +22 -44
  38. package/dist/runtime/utils/{object.mjs → object.js} +1 -2
  39. package/dist/types.d.mts +1 -16
  40. package/dist/types.d.ts +1 -16
  41. package/package.json +35 -34
  42. package/dist/runtime/composables/api.mjs +0 -64
  43. package/dist/runtime/plugins/vueSignaturePad.d.ts +0 -2
  44. package/dist/runtime/plugins/vueSignaturePad.mjs +0 -5
  45. /package/dist/runtime/composables/utils/{fuzzy.mjs → fuzzy.js} +0 -0
  46. /package/dist/runtime/composables/utils/{validation.mjs → validation.js} +0 -0
package/dist/module.d.mts CHANGED
@@ -2,6 +2,6 @@ import * as _nuxt_schema from '@nuxt/schema';
2
2
 
3
3
  interface ModuleOptions {
4
4
  }
5
- declare const _default: _nuxt_schema.NuxtModule<ModuleOptions>;
5
+ declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
6
6
 
7
7
  export { type ModuleOptions, _default as default };
package/dist/module.d.ts CHANGED
@@ -2,6 +2,6 @@ import * as _nuxt_schema from '@nuxt/schema';
2
2
 
3
3
  interface ModuleOptions {
4
4
  }
5
- declare const _default: _nuxt_schema.NuxtModule<ModuleOptions>;
5
+ declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
6
6
 
7
7
  export { type ModuleOptions, _default as default };
package/dist/module.json CHANGED
@@ -4,5 +4,9 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^3.0.0"
6
6
  },
7
- "version": "0.1.21"
7
+ "version": "0.1.23",
8
+ "builder": {
9
+ "@nuxt/module-builder": "0.8.3",
10
+ "unbuild": "2.0.0"
11
+ }
8
12
  }
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import {ref, withDefaults} from 'vue'
2
+ import {ref} from 'vue'
3
3
  import * as XLSX from 'xlsx'
4
4
  import {VBtn} from 'vuetify/components/VBtn'
5
5
  import {useAlert} from '../composables/alert'
@@ -20,7 +20,7 @@ function exportFile() {
20
20
  if (props.modelValue && Array.isArray(props.modelValue)) {
21
21
  loading.value = true
22
22
  const workbook = XLSX.utils.book_new()
23
- const worksheet = XLSX.utils.json_to_sheet(props.modelValue)
23
+ const worksheet = XLSX.utils.json_to_sheet(serializeRoleField(props.modelValue))
24
24
  const fileName = `${props.fileName}.xlsx`
25
25
  XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
26
26
  XLSX.writeFile(workbook, fileName)
@@ -30,25 +30,34 @@ function exportFile() {
30
30
  alert?.addAlert({ message: 'Invalid or no data to export', alertType: 'error' })
31
31
  }
32
32
  }
33
+
34
+ const serializeRoleField = (items: any) => {
35
+ return items.map((item:any) => {
36
+ if (item.properties && typeof item.properties === 'object') {
37
+ item.properties = JSON.stringify(item.properties);
38
+ }
39
+ return item;
40
+ });
41
+ }
33
42
  </script>
34
43
 
35
44
  <template>
36
45
  <VBtn
37
- v-bind="$attrs"
38
- color="primary"
39
- :loading="loading"
40
- :disabled="loading"
41
- text="Export CSV"
42
- @click="exportFile"
46
+ v-bind="$attrs"
47
+ color="primary"
48
+ :loading="loading"
49
+ :disabled="loading"
50
+ text="Export CSV"
51
+ @click="exportFile"
43
52
  >
44
53
  <template
45
- v-for="(_, name, index) in ($slots as {})"
46
- :key="index"
47
- #[name]="slotData"
54
+ v-for="(_, name, index) in ($slots as {})"
55
+ :key="index"
56
+ #[name]="slotData"
48
57
  >
49
58
  <slot
50
- :name="name"
51
- v-bind="((slotData || {}) as object)"
59
+ :name="name"
60
+ v-bind="((slotData || {}) as object)"
52
61
  />
53
62
  </template>
54
63
  </VBtn>
@@ -29,9 +29,10 @@ const reset = () => {
29
29
  files.value = undefined
30
30
  }
31
31
 
32
- watch(files, () => {
32
+ const emitFiles = () => {
33
33
  emit('update:modelValue', files.value)
34
- }, { deep: true })
34
+ files.value = []
35
+ }
35
36
 
36
37
  defineExpose({ reset })
37
38
  </script>
@@ -55,6 +56,7 @@ defineExpose({ reset })
55
56
  <v-file-input
56
57
  ref="fileInput"
57
58
  v-model="files"
59
+ @update:modelValue="emitFiles"
58
60
  :accept="props.accept"
59
61
  :multiple="props.multiple"
60
62
  style="display: none"
@@ -30,34 +30,44 @@ function uploadedFile(files: File[] | File | undefined) {
30
30
  const reader = new FileReader()
31
31
  reader.onload = (e: ProgressEvent<FileReader>) => {
32
32
  const workbook = XLSX.read(e.target?.result)
33
- emit('import', XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]))
33
+ const parseData = parsePropertiesField(XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]))
34
+ emit('import', parseData)
34
35
  loading.value = false
35
36
  fileBtnRef.value.reset()
36
37
  }
37
38
  loading.value = true
38
39
  reader.readAsArrayBuffer(files)
39
40
  }
41
+
42
+ const parsePropertiesField = (items:any) => {
43
+ return items.map(item => {
44
+ if (item.properties && typeof item.properties === 'string') {
45
+ item.properties = JSON.parse(item.properties);
46
+ }
47
+ return item;
48
+ });
49
+ };
40
50
  </script>
41
51
 
42
52
  <template>
43
53
  <FileBtn
44
- ref="fileBtnRef"
45
- v-bind="$attrs"
46
- color="primary"
47
- :loading="loading"
48
- text="Import CSV"
49
- accept=".csv, .xlsx"
50
- :multiple="false"
51
- @update:model-value="uploadedFile"
54
+ ref="fileBtnRef"
55
+ v-bind="$attrs"
56
+ color="primary"
57
+ :loading="loading"
58
+ text="Import CSV"
59
+ accept=".csv, .xlsx"
60
+ :multiple="false"
61
+ @update:model-value="uploadedFile"
52
62
  >
53
63
  <template
54
- v-for="(_, name, index) in ($slots as {})"
55
- :key="index"
56
- #[name]="slotData"
64
+ v-for="(_, name, index) in ($slots as {})"
65
+ :key="index"
66
+ #[name]="slotData"
57
67
  >
58
68
  <slot
59
- :name="name"
60
- v-bind="((slotData || {}) as object)"
69
+ :name="name"
70
+ v-bind="((slotData || {}) as object)"
61
71
  />
62
72
  </template>
63
73
  </FileBtn>
@@ -11,7 +11,7 @@ const isAdvanceMode = computed(() => {
11
11
  return modelValue.value && !isValidJsonArrayOfObjects(modelValue.value)
12
12
  })
13
13
 
14
- const templateItems = ref<Record<string, any>>([])
14
+ const templateItems = ref<Record<string, any>[]>([])
15
15
 
16
16
  const headers = ref([
17
17
  { title: '',
@@ -1,22 +1,22 @@
1
1
  <script lang="ts" setup>
2
- import { VueSignaturePad } from 'vue-signature-pad'
3
- import { type Ref, ref, onMounted, onBeforeUnmount, withDefaults } from 'vue'
2
+ import { VueSignaturePad } from 'vue-signature-pad';
3
+ import { type Ref, ref, onMounted, onBeforeUnmount } from 'vue'
4
4
 
5
5
  interface SignatureOptions {
6
- penColor: string
7
- minWidth?: number
8
- maxWidth?: number
6
+ penColor: string
7
+ minWidth?: number
8
+ maxWidth?: number
9
9
  }
10
10
 
11
11
  interface SignatureProps {
12
- title?: string
13
- titleConfirm?: string
14
- modelValue: string
12
+ title?: string
13
+ titleConfirm?: string
14
+ modelValue?: string
15
15
  }
16
16
 
17
17
  const props = withDefaults(defineProps<SignatureProps>(), {
18
- title: 'Draw Your Signature',
19
- titleConfirm: 'I Accept My Signature',
18
+ title: 'Draw Your Signature',
19
+ titleConfirm: 'I Accept My Signature',
20
20
  })
21
21
 
22
22
  const signaturePadRef: Ref<any> = ref(null)
@@ -28,54 +28,54 @@ const signatureOptions: Ref<SignatureOptions> = ref({ penColor: defaultColor, mi
28
28
  const isDialogOpen: Ref<boolean> = ref(false)
29
29
 
30
30
  const undoSignature = (): void => {
31
- signaturePadRef.value.undoSignature()
31
+ signaturePadRef.value.undoSignature()
32
32
  }
33
33
 
34
34
  const clearSignature = (): void => {
35
- signaturePadRef.value.clearSignature()
35
+ signaturePadRef.value.clearSignature()
36
36
  }
37
37
 
38
38
  const closeDialog = (): void => {
39
- isDialogOpen.value = false
40
- signaturePadRef.value.clearSignature()
41
- signaturePadRef.value.clearCacheImages()
39
+ isDialogOpen.value = false
40
+ signaturePadRef.value.clearSignature()
41
+ signaturePadRef.value.clearCacheImages()
42
42
  }
43
43
 
44
44
  const emit = defineEmits<{
45
- (event: 'update:modelValue', value: string): void
45
+ (event: 'update:modelValue', value: string): void
46
46
  }>()
47
47
 
48
48
  const saveSignature = (): void => {
49
- isDialogOpen.value = false
50
- const { isEmpty, data } = signaturePadRef.value.saveSignature()
51
- signatureData.value = isEmpty ? '' : data
52
- emit('update:modelValue', signatureData.value)
49
+ isDialogOpen.value = false
50
+ const { isEmpty, data } = signaturePadRef.value.saveSignature()
51
+ signatureData.value = isEmpty ? '' : data
52
+ emit('update:modelValue', signatureData.value)
53
53
  }
54
54
 
55
55
  const changePenColor = (color: string): void => {
56
- selectedColor.value = color
57
- signatureOptions.value = { penColor: color }
56
+ selectedColor.value = color
57
+ signatureOptions.value = { penColor: color }
58
58
  }
59
59
 
60
60
  const openSignatureDialog = (): void => {
61
- selectedColor.value = defaultColor
62
- signatureOptions.value = { penColor: defaultColor }
63
- isDialogOpen.value = true
61
+ selectedColor.value = defaultColor
62
+ signatureOptions.value = { penColor: defaultColor }
63
+ isDialogOpen.value = true
64
64
  }
65
65
 
66
66
  const signaturePadHeight: Ref<string> = ref('')
67
67
  const updateSignaturePadHeight = () => {
68
- const screenHeight = window.innerHeight
69
- signaturePadHeight.value = `${screenHeight * 0.4}px`
68
+ const screenHeight = window.innerHeight
69
+ signaturePadHeight.value = `${screenHeight * 0.4}px`
70
70
  }
71
71
 
72
72
  onMounted(() => {
73
- updateSignaturePadHeight()
74
- window.addEventListener('resize', updateSignaturePadHeight)
73
+ updateSignaturePadHeight()
74
+ window.addEventListener('resize', updateSignaturePadHeight)
75
75
  })
76
76
 
77
77
  onBeforeUnmount(() => {
78
- window.removeEventListener('resize', updateSignaturePadHeight)
78
+ window.removeEventListener('resize', updateSignaturePadHeight)
79
79
  })
80
80
  </script>
81
81
 
@@ -235,26 +235,9 @@ const operation = ref({ openDialog, createItem, updateItem, deleteItem, moveUpIt
235
235
  v-if="!$slots['item.operation']"
236
236
  #item.operation="props"
237
237
  >
238
- <v-btn
239
- :disabled="props.index==0"
240
- variant="flat"
241
- density="compact"
242
- icon="mdi:mdi-arrow-up-thick"
243
- @click="moveUpItem(props.item)"
244
- />
245
- <v-btn
246
- variant="flat"
247
- density="compact"
248
- icon="fa:fas fa-arrow-right-to-bracket"
249
- @click="moveToItem(props.item)"
250
- />
251
- <v-btn
252
- :disabled="props.index==items.length-1"
253
- variant="flat"
254
- density="compact"
255
- icon="mdi:mdi-arrow-down-thick"
256
- @click="moveDownItem(props.item)"
257
- />
238
+ <v-icon density="compact" :disabled="props.index==0" @click="moveUpItem(props.item)">mdi:mdi-arrow-up-thick</v-icon>
239
+ <v-icon density="compact" @click="moveToItem(props.item)">fa:fas fa-arrow-right-to-bracket</v-icon>
240
+ <v-icon density="compact" :disabled="props.index==items.length-1" @click="moveDownItem(props.item)">mdi:mdi-arrow-down-thick</v-icon>
258
241
  </template>
259
242
  <template
260
243
  v-if="!$slots['item.action']"
@@ -0,0 +1,187 @@
1
+ <script lang="ts" setup>
2
+ import { type Ref, ref, watch} from 'vue'
3
+ import {useAlert} from '../../../composables/alert'
4
+ import { isEqual } from 'lodash-es'
5
+ interface Props {
6
+ modelValue?: any;
7
+ readonly?: boolean;
8
+ label?: string;
9
+ }
10
+
11
+ const props = defineProps<Props>();
12
+ const emit = defineEmits<{
13
+ (e: "update:modelValue", value: {}): void;
14
+ }>();
15
+
16
+ const alert = useAlert()
17
+
18
+ interface Image {
19
+ title: string;
20
+ data: string;
21
+ props: {};
22
+ }
23
+
24
+ const images = ref<Image[]>([]);
25
+ const dialog: Ref<boolean> = ref(false);
26
+ const dialogUpdate: Ref<boolean> = ref(false);
27
+ const dataUpdate: Ref<Image> = ref({
28
+ title: "",
29
+ data: "",
30
+ props: {},
31
+ });
32
+ const remove = (index: number) => {
33
+ images.value.splice(index, 1);
34
+ };
35
+
36
+ const setDataUpdate = (data: Image) => {
37
+ dataUpdate.value = data;
38
+ dialogUpdate.value = true;
39
+ };
40
+
41
+
42
+ interface FileBase64 {
43
+ base64string: string;
44
+ mineType: string;
45
+ filename: string;
46
+ }
47
+
48
+
49
+ const uploadImages: Ref<any[]> = ref([]);
50
+ const checkDuplicationName = async (currentImageName: string) => {
51
+ for (const {title} of images.value) {
52
+ if(isEqual(title, currentImageName)) return true
53
+ }
54
+ }
55
+
56
+ const update = async () => {
57
+ const duplicatedFileName = ref("")
58
+ for (const image of uploadImages.value) {
59
+ if(await checkDuplicationName(image.name)){
60
+ duplicatedFileName.value += `${image.name},`
61
+ }else{
62
+ const fileBase64: any = await convertFileToBase64(image);
63
+ if (isImage(fileBase64)) {
64
+ addImage(fileBase64);
65
+ } else {
66
+ alert?.addAlert({message: `ไฟล์ "${fileBase64.filename}" ไม่ใช่ไฟล์นามสกุล .jpg หรือ .jpeg`, alertType: 'error'})
67
+ }
68
+ }
69
+ }
70
+ uploadImages.value = []
71
+ if(duplicatedFileName.value !== ""){
72
+ alert?.addAlert({message: `ไม่สามารถอัพโหลดไฟล์ ${duplicatedFileName.value}`, alertType: 'error'})
73
+ duplicatedFileName.value = ""
74
+ }
75
+ };
76
+ const convertFileToBase64 = async (file: any) => {
77
+ try {
78
+ const readPromise: any = new Promise((resolve, reject) => {
79
+ const reader = new FileReader();
80
+ reader.onload = () => {
81
+ let result: any = reader.result;
82
+ const mineType = result.split(",")[0];
83
+ const base64 = result.split(",")[1];
84
+ resolve({
85
+ base64string: base64,
86
+ mineType: mineType,
87
+ filename: file.name,
88
+ });
89
+ };
90
+ reader.onerror = (error) => {
91
+ reject(error);
92
+ };
93
+ reader.readAsDataURL(file);
94
+ });
95
+ return await readPromise;
96
+ } catch (error: any) {
97
+ alert?.addAlert({message: error, alertType: 'error'})
98
+ }
99
+ };
100
+ const isImage = (fileBase64: any) => {
101
+ const typeFile: string = fileBase64.mineType.substring(5, 10);
102
+ return typeFile === "image" ? true : false;
103
+ };
104
+
105
+ const addImage = (data: FileBase64) => {
106
+ images.value.push({
107
+ title: data.filename,
108
+ data: `${data.mineType},${data.base64string}`,
109
+ props: {},
110
+ });
111
+ dialog.value = false;
112
+ };
113
+ watch(images, () => {
114
+ emit("update:modelValue", images);
115
+ }, { deep: true });
116
+ </script>
117
+
118
+ <template>
119
+ <VCard>
120
+ <VToolbar density="compact">
121
+ <VToolbarTitle>{{ label }}</VToolbarTitle>
122
+ <v-spacer></v-spacer>
123
+ <VToolbarItems v-if="!readonly">
124
+ <FileBtn
125
+ ref="fileBtn"
126
+ v-model="uploadImages"
127
+ accept=".jpg, .jpeg"
128
+ color="primary"
129
+ icon="mdi:mdi-image-plus"
130
+ iconOnly
131
+ multiple
132
+ variant="text"
133
+ @update:model-value="update"
134
+ />
135
+ <v-btn color="primary" icon @click="dialog = true">
136
+ <v-icon>mdi mdi-camera-plus</v-icon>
137
+ </v-btn>
138
+ </VToolbarItems>
139
+ </VToolbar>
140
+ <VCardText>
141
+ <VRow dense justify="center">
142
+ <VCol v-for="(image, index) in images" :key="index" cols="4">
143
+ <VCard max-height="250">
144
+ <VToolbar density="compact">
145
+ <VToolbarTitle>
146
+ {{ image.title }}
147
+ </VToolbarTitle>
148
+ <VSpacer></VSpacer>
149
+ <VToolbarItems v-if="!readonly">
150
+ <v-btn icon @click="remove(index)">
151
+ <v-icon>mdi mdi-delete-outline</v-icon>
152
+ </v-btn>
153
+ <v-btn
154
+ color="primary"
155
+ icon
156
+ @click="setDataUpdate(image)"
157
+ >
158
+ <v-icon>mdi mdi-image-edit-outline</v-icon>
159
+ </v-btn>
160
+ </VToolbarItems>
161
+ </VToolbar>
162
+ <v-img
163
+ :src="image.data"
164
+ @click="setDataUpdate(image)"
165
+ ></v-img>
166
+ </VCard>
167
+ </VCol>
168
+ </VRow>
169
+ </VCardText>
170
+ </VCard>
171
+ <VDialog
172
+ v-model="dialogUpdate"
173
+ fullscreen
174
+ transition="dialog-bottom-transition"
175
+ >
176
+ <FormImagesPad
177
+ v-model="dataUpdate.data"
178
+ @closedDialog="dialogUpdate = false"
179
+ ></FormImagesPad>
180
+ </VDialog>
181
+ <VDialog v-model="dialog">
182
+ <FormImagesCapture
183
+
184
+ @close-dialog="dialog = false"
185
+ ></FormImagesCapture>
186
+ </VDialog>
187
+ </template>
@@ -0,0 +1,43 @@
1
+ <script setup lang="ts">
2
+ import { onMounted, nextTick } from 'vue';
3
+ import Painterro from 'painterro';
4
+
5
+ const props = defineProps({
6
+ modelValue: String
7
+ })
8
+
9
+ const emit = defineEmits(['update:modelValue', 'closedDialog'])
10
+
11
+ const setting = {
12
+ id: "painterroContainer",
13
+ defaultTool: 'brush',
14
+ toolbarPosition: 'top',
15
+ toolbarHeightPx: '50',
16
+ pixelizePixelSize: '5%',
17
+ hiddenTools: [
18
+ 'resize',
19
+ 'redo',
20
+ 'bucket',
21
+ 'clear',
22
+ 'settings',
23
+ ],
24
+ saveHandler: function (image:any, done:any) {
25
+ emit('update:modelValue', image.asDataURL())
26
+ emit('closedDialog', false)
27
+ done(true)
28
+ },
29
+ onClose: function () {
30
+ emit('closedDialog', false)
31
+ }
32
+ }
33
+
34
+ onMounted(async () => {
35
+ await nextTick();
36
+ props.modelValue != "" ? Painterro(setting).show(props.modelValue) : Painterro(setting).show()
37
+ });
38
+
39
+ </script>
40
+
41
+ <template>
42
+ <div id="painterroContainer" style="width: 100%; height: 100dvh;"></div>
43
+ </template>
@@ -1,9 +1,9 @@
1
1
  <script lang="ts" setup>
2
- import {computed, nextTick, ref, useAttrs} from 'vue'
3
- import {VDataTable} from 'vuetify/components/VDataTable'
4
- import {omit} from 'lodash-es'
5
- import type {GraphqlModelProps} from '../../composables/graphqlModel'
6
- import {useGraphqlModel} from '../../composables/graphqlModel'
2
+ import { computed,watch, nextTick, ref, useAttrs } from 'vue'
3
+ import { VDataTable } from 'vuetify/components/VDataTable'
4
+ import { omit } from 'lodash-es'
5
+ import type { GraphqlModelProps } from '../../composables/graphqlModel'
6
+ import { useGraphqlModel } from '../../composables/graphqlModel'
7
7
 
8
8
  defineOptions({
9
9
  inheritAttrs: false,
@@ -17,6 +17,9 @@ interface Props extends /* @vue-ignore */ InstanceType<typeof VDataTable['$props
17
17
  toolbarColor?: string
18
18
  importable?: boolean
19
19
  exportable?: boolean
20
+ insertable?: boolean
21
+ searchable?: boolean
22
+ search?: string
20
23
  }
21
24
 
22
25
  const props = withDefaults(defineProps<Props & GraphqlModelProps>(), {
@@ -25,6 +28,8 @@ const props = withDefaults(defineProps<Props & GraphqlModelProps>(), {
25
28
  toolbarColor: 'primary',
26
29
  importable: true,
27
30
  exportable: true,
31
+ insertable: true,
32
+ searchable: true,
28
33
  modelKey: 'id',
29
34
  modelBy: undefined,
30
35
  fields: () => [],
@@ -40,7 +45,7 @@ const currentItem = ref<Record<string, any> | undefined>(undefined)
40
45
  const isDialogOpen = ref<boolean>(false)
41
46
 
42
47
  const { items, itemsLength,
43
- search,
48
+ search,setSearch,
44
49
  canServerPageable, canServerSearch, canCreate, canUpdate, canDelete,
45
50
  createItem, importItems, updateItem, deleteItem,
46
51
  loadItems, reload,
@@ -53,12 +58,16 @@ function openDialog(item?: object) {
53
58
  })
54
59
  }
55
60
 
56
- const operation = ref({ openDialog, createItem, importItems, updateItem, deleteItem, reload, canServerPageable, canServerSearch, canCreate, canUpdate, canDelete })
61
+ const operation = ref({ openDialog, createItem, importItems, updateItem, deleteItem, reload, setSearch, canServerPageable, canServerSearch, canCreate, canUpdate, canDelete })
57
62
 
58
63
  const computedInitialData = computed(() => {
59
64
  return Object.assign({}, props.initialData, props.modelBy)
60
65
  })
61
66
 
67
+ watch(()=>props.search,()=>{
68
+ search.value = props.search
69
+ },{immediate:true})
70
+
62
71
  defineExpose({ reload })
63
72
  </script>
64
73
 
@@ -67,7 +76,6 @@ defineExpose({ reload })
67
76
  <slot
68
77
  name="header"
69
78
  :items="items"
70
- :search="search"
71
79
  :operation="operation"
72
80
  >
73
81
  <VToolbar :color="toolbarColor">
@@ -94,7 +102,7 @@ defineExpose({ reload })
94
102
  </slot>
95
103
  </VToolbarTitle>
96
104
  </v-col>
97
- <v-col cols="5">
105
+ <v-col cols="5" v-if="props.searchable">
98
106
  <slot name="search">
99
107
  <VTextField
100
108
  v-model="search"
@@ -112,11 +120,11 @@ defineExpose({ reload })
112
120
  <VToolbarItems>
113
121
  <slot name="toolbarItems" />
114
122
  <ImportCSV
115
- v-if="props.importable"
123
+ v-if="props.importable && canCreate && props.insertable"
116
124
  icon="mdi mdi-file-upload"
117
125
  variant="flat"
118
- @import="importItems"
119
126
  :color="toolbarColor"
127
+ @import="importItems"
120
128
  />
121
129
  <ExportCSV
122
130
  v-if="props.exportable && items.length"
@@ -127,7 +135,7 @@ defineExpose({ reload })
127
135
  :color="toolbarColor"
128
136
  />
129
137
  <VBtn
130
- v-if="canCreate"
138
+ v-if="canCreate && props.insertable"
131
139
  :color="toolbarColor"
132
140
  prepend-icon="mdi mdi-plus"
133
141
  variant="flat"