@ramathibodi/nuxt-commons 0.1.26 → 0.1.28

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/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^3.0.0"
6
6
  },
7
- "version": "0.1.26",
7
+ "version": "0.1.28",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.3",
10
10
  "unbuild": "2.0.0"
@@ -1,14 +1,10 @@
1
1
  <script lang="ts" setup>
2
- import { type Ref, ref, watch} from 'vue'
2
+ import {type Ref, ref, watch, onMounted} from 'vue'
3
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
- }
4
+ import {isEqual} from 'lodash-es'
5
+ import type {FormDialogCallback} from "../../../types/formDialog";
6
+
10
7
 
11
- const props = defineProps<Props>();
12
8
  const emit = defineEmits<{
13
9
  (e: "update:modelValue", value: {}): void;
14
10
  }>();
@@ -21,58 +17,55 @@ interface Image {
21
17
  props: {};
22
18
  }
23
19
 
24
- const images = ref<Image[]>([]);
20
+ interface Props {
21
+ modelValue?: any[];
22
+ readonly?: boolean;
23
+ label?: string;
24
+ }
25
+ const props = withDefaults(defineProps<Props>(), {
26
+ modelValue: () => [] as any[],
27
+ })
28
+
29
+ const images = ref<any[]>([]);
30
+ // uploadImages = images that are imported by FileBtn
31
+ const uploadImages: Ref<any[]> = ref([]);
32
+ // dialog = dialog for capturing image
25
33
  const dialog: Ref<boolean> = ref(false);
34
+ // dialogUpdate, dataUpdate = dialog for editing image
26
35
  const dialogUpdate: Ref<boolean> = ref(false);
27
36
  const dataUpdate: Ref<Image> = ref({
28
37
  title: "",
29
38
  data: "",
30
39
  props: {},
31
40
  });
41
+
42
+
43
+ // remove selected image
32
44
  const remove = (index: number) => {
33
45
  images.value.splice(index, 1);
34
46
  };
35
47
 
48
+ // open dialog for editing selected image
36
49
  const setDataUpdate = (data: Image) => {
37
50
  dataUpdate.value = data;
38
51
  dialogUpdate.value = true;
39
52
  };
40
53
 
41
54
 
42
- interface FileBase64 {
43
- base64string: string;
44
- mineType: string;
45
- filename: string;
46
- }
47
55
 
48
-
49
- const uploadImages: Ref<any[]> = ref([]);
56
+ // check if File name is already exist
50
57
  const checkDuplicationName = async (currentImageName: string) => {
51
58
  for (const {title} of images.value) {
52
- if(isEqual(title, currentImageName)) return true
59
+ if (isEqual(title, currentImageName)) return true
53
60
  }
54
61
  }
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
- }
62
+ // check if the base64 is image or not
63
+ const isImage = (fileBase64: any) => {
64
+ const typeFile: string = fileBase64.mineType.substring(5, 10);
65
+ return typeFile === "image";
75
66
  };
67
+
68
+ // convert FIle that is uploaded by FileBtn to base64
76
69
  const convertFileToBase64 = async (file: any) => {
77
70
  try {
78
71
  const readPromise: any = new Promise((resolve, reject) => {
@@ -97,22 +90,92 @@ const convertFileToBase64 = async (file: any) => {
97
90
  alert?.addAlert({message: error, alertType: 'error'})
98
91
  }
99
92
  };
100
- const isImage = (fileBase64: any) => {
101
- const typeFile: string = fileBase64.mineType.substring(5, 10);
102
- return typeFile === "image" ? true : false;
103
- };
104
93
 
105
- const addImage = (data: FileBase64) => {
94
+ // push image into Field
95
+ const addImage = (data: Image) => {
106
96
  images.value.push({
107
- title: data.filename,
108
- data: `${data.mineType},${data.base64string}`,
97
+ title: data.title,
98
+ data: data.data,
109
99
  props: {},
110
100
  });
111
101
  dialog.value = false;
112
102
  };
103
+
104
+ const update = async () => {
105
+ const duplicatedFileName = ref("")
106
+ for (const image of uploadImages.value) {
107
+ if (await checkDuplicationName(image.name)) {
108
+ duplicatedFileName.value += `${image.name},`
109
+ } else {
110
+ const fileBase64: any = await convertFileToBase64(image);
111
+ if (isImage(fileBase64)) {
112
+ addImage({
113
+ title: fileBase64.filename,
114
+ data: `${fileBase64.mineType},${fileBase64.base64string}`,
115
+ props: {},
116
+ })
117
+ } else {
118
+ alert?.addAlert({
119
+ message: `ไฟล์ "${fileBase64.filename}" ไม่ใช่ไฟล์นามสกุล .jpg หรือ .jpeg`,
120
+ alertType: 'error'
121
+ })
122
+ }
123
+ }
124
+ }
125
+ uploadImages.value = []
126
+ if (duplicatedFileName.value !== "") {
127
+ alert?.addAlert({message: `ไม่สามารถอัพโหลดไฟล์ ${duplicatedFileName.value}`, alertType: 'error'})
128
+ duplicatedFileName.value = ""
129
+ }
130
+ };
131
+
132
+ // Capture Image
133
+ const modelData = ref();
134
+ const captureImage = (image: any, callback: FormDialogCallback) => {
135
+ addImage({
136
+ title: Math.random().toString(36).slice(2, 11),
137
+ data: image.imageCapture,
138
+ props: {}
139
+ })
140
+ callback.done()
141
+ }
142
+
143
+ // open Fullscreen image
144
+ const dialogImageFullScreen = ref(false)
145
+ const imageFullScreen = ref({
146
+ title: "",
147
+ image: ""
148
+ })
149
+
150
+ const openImageFullScreen = (image: { [key: string]: string }) => {
151
+ dialogImageFullScreen.value = true
152
+ imageFullScreen.value.title = image.title
153
+ imageFullScreen.value.image = image.data
154
+ }
155
+
156
+
113
157
  watch(images, () => {
114
- emit("update:modelValue", images);
115
- }, { deep: true });
158
+ emit("update:modelValue", images.value);
159
+ }, {deep: true});
160
+
161
+
162
+ // updating when the parent component adds image to v-model
163
+ watch(props.modelValue, () => {
164
+ images.value = props.modelValue
165
+ }, {deep: true});
166
+
167
+
168
+ onMounted(() => {
169
+ // import images by v-model
170
+ for (const modelValue of props.modelValue) {
171
+ addImage({
172
+ title: modelValue.title ?? Math.random().toString(36).slice(2, 11),
173
+ data: modelValue.data,
174
+ props: {}
175
+ })
176
+ }
177
+ })
178
+
116
179
  </script>
117
180
 
118
181
  <template>
@@ -140,7 +203,7 @@ watch(images, () => {
140
203
  <VCardText>
141
204
  <VRow dense justify="center">
142
205
  <VCol v-for="(image, index) in images" :key="index" cols="4">
143
- <VCard max-height="250">
206
+ <VCard>
144
207
  <VToolbar density="compact">
145
208
  <VToolbarTitle>
146
209
  {{ image.title }}
@@ -161,13 +224,16 @@ watch(images, () => {
161
224
  </VToolbar>
162
225
  <v-img
163
226
  :src="image.data"
164
- @click="setDataUpdate(image)"
165
- ></v-img>
227
+ @click="readonly ? openImageFullScreen(image) : setDataUpdate(image)"
228
+ height="250"
229
+ />
166
230
  </VCard>
167
231
  </VCol>
168
232
  </VRow>
169
233
  </VCardText>
170
234
  </VCard>
235
+
236
+
171
237
  <VDialog
172
238
  v-model="dialogUpdate"
173
239
  fullscreen
@@ -178,10 +244,21 @@ watch(images, () => {
178
244
  @closedDialog="dialogUpdate = false"
179
245
  ></FormImagesPad>
180
246
  </VDialog>
181
- <VDialog v-model="dialog">
182
- <FormImagesCapture
183
247
 
184
- @close-dialog="dialog = false"
185
- ></FormImagesCapture>
186
- </VDialog>
248
+ <FormDialog v-model="dialog" :form-data="modelData" @create="captureImage">
249
+ <template #default="{ data }">
250
+ <FormImagesCapture v-model="data.imageCapture"/>
251
+ </template>
252
+ </FormDialog>
253
+
254
+ <v-dialog v-model="dialogImageFullScreen">
255
+ <v-toolbar :title="imageFullScreen.title">
256
+ <v-spacer/>
257
+ <v-btn icon="mdi mdi-close" @click="dialogImageFullScreen = false"/>
258
+ </v-toolbar>
259
+ <v-card height="80vh">
260
+ <v-img :src="imageFullScreen.image"/>
261
+ </v-card>
262
+
263
+ </v-dialog>
187
264
  </template>
@@ -1,7 +1,7 @@
1
1
  <script lang="ts" setup>
2
2
  import {VAutocomplete} from 'vuetify/components/VAutocomplete'
3
3
  import {concat, isEmpty, sortBy} from 'lodash-es'
4
- import {computed, ref, watch} from 'vue'
4
+ import {computed, ref, watch,watchEffect} from 'vue'
5
5
  import {watchDebounced} from '@vueuse/core'
6
6
  import {useFuzzy} from '../../composables/utils/fuzzy'
7
7
  import {useGraphQl} from '../../composables/graphql'
@@ -66,16 +66,15 @@ function query(groupKey: string, filterText: string | undefined) {
66
66
  })
67
67
  }
68
68
 
69
- watch(() => props.waitForFilter && !props.filterText, (newValue) => {
70
- if (newValue) {
69
+ watchEffect(()=>{
70
+ if (props.waitForFilter && !props.filterText) {
71
71
  masterItems.value = []
72
72
  items.value = []
73
73
  selectedItem.value = undefined
74
- }
75
- else {
74
+ } else {
76
75
  query(props.groupKey, props.filterText)
77
76
  }
78
- }, { immediate: true })
77
+ })
79
78
 
80
79
  watch(() => props.modelValue, (newValue) => {
81
80
  selectedItem.value = newValue
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ramathibodi/nuxt-commons",
3
- "version": "0.1.26",
3
+ "version": "0.1.28",
4
4
  "description": "Ramathibodi Nuxt modules for common components",
5
5
  "repository": {
6
6
  "type": "git",
@@ -114,5 +114,5 @@
114
114
  "vitest": "^1.6.0",
115
115
  "vue-tsc": "2.0.29"
116
116
  },
117
- "packageManager": "pnpm@9.12.0+sha512.4abf725084d7bcbafbd728bfc7bee61f2f791f977fd87542b3579dcb23504d170d46337945e4c66485cd12d588a0c0e570ed9c477e7ccdd8507cf05f3f92eaca"
117
+ "packageManager": "pnpm@9.12.1+sha512.e5a7e52a4183a02d5931057f7a0dbff9d5e9ce3161e33fa68ae392125b79282a8a8a470a51dfc8a0ed86221442eb2fb57019b0990ed24fab519bf0e1bc5ccfc4"
118
118
  }