vue-wiguet-chatweb 0.1.36 → 0.1.38

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-wiguet-chatweb",
3
- "version": "0.1.36",
3
+ "version": "0.1.38",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -1,35 +1,61 @@
1
1
  <template>
2
2
  <div class="widget">
3
- <div class="header-widget">
3
+ <div class="header-widget flex-0">
4
4
  <h4 class="title-chat">{{ titlePrincipal }}</h4>
5
5
  <button @click="() => toggleChat()" class="btn-close">
6
6
  <IconClose class="pointer" />
7
7
  </button>
8
8
  </div>
9
- <div class="messages-container" ref="messageContainerRef">
10
- <div class="loader" v-if="isLoading">
11
- <Loader />
12
- </div>
13
- <MessageList
14
- v-if="messagesData.data.length > 0"
15
- :messages="messagesData.data"
16
- :canLoadMoreMessages="messagesData.canLoadMoreMessages"
17
- @loadMore="getMessages"
18
- @retry="retryMessage"
19
- @on-qualifying="(args) => onQualifying(args)"
20
- @see="(message: Message) => {
21
- currentDialogView = DIALOG_VIEWS.SEE
22
- urlFileMessage = message.urlFile
23
- dialog.title = 'Imagen'
24
- dialog.modelValue = true
25
- }"
26
- />
27
- <div class="fit" v-else>
28
- <span class="center">No tienes mensajes</span>
9
+
10
+ <div class="flex-1" style="position: relative; height: 0;">
11
+ <div
12
+ ref="dropZoneRef"
13
+ @drop.self.prevent="
14
+ (e) => {
15
+ dropHandler(e);
16
+ (e.target as HTMLElement)?.classList?.remove('drop-over');
17
+ (e.target as HTMLElement).style.zIndex = '-1';
18
+ }
19
+ "
20
+ @dragenter.self="
21
+ (e) => {
22
+ (e.target as HTMLElement)?.classList?.add('drop-over');
23
+ }
24
+ "
25
+ @dragleave.self="
26
+ (e) => {
27
+ (e.target as HTMLElement)?.classList?.remove('drop-over');
28
+ (e.target as HTMLElement).style.zIndex = '-1';
29
+ }
30
+ "
31
+ @dragover.prevent
32
+ style="position: absolute; bottom: 0; left: 0; right: 0; top: 0; z-index: -1;"
33
+ ></div>
34
+ <div class="messages-container" ref="messageContainerRef" @dragenter.prevent="dropZoneRef!.style.zIndex = '1'">
35
+ <div class="loader" v-if="isLoading">
36
+ <Loader />
37
+ </div>
38
+ <MessageList
39
+ v-if="messagesData.data.length > 0"
40
+ :messages="messagesData.data"
41
+ :canLoadMoreMessages="messagesData.canLoadMoreMessages"
42
+ @loadMore="getMessages"
43
+ @retry="retryMessage"
44
+ @on-qualifying="(args) => onQualifying(args)"
45
+ @see="(message: Message) => {
46
+ currentDialogView = DIALOG_VIEWS.SEE
47
+ urlFileMessage = message.urlFile
48
+ dialog.title = 'Imagen'
49
+ dialog.modelValue = true
50
+ }"
51
+ />
52
+ <div class="fit" v-else>
53
+ <span class="center">No tienes mensajes</span>
54
+ </div>
29
55
  </div>
30
56
  </div>
31
57
 
32
- <div class="w-full">
58
+ <div class="w-full flex-0">
33
59
  <form v-if="!isDisabledBoxMessage" class="message-send" @submit.prevent="(event) => submitMessage()">
34
60
  <div class="form-message">
35
61
  <div class="jl-inputgroup-chat">
@@ -46,15 +72,15 @@
46
72
  }
47
73
  "
48
74
  @keyup.enter="saltoDeLineaOEnviar"
75
+ @paste.prevent="handlePaste"
49
76
  />
50
77
 
51
78
  <input
52
79
  type="file"
53
80
  ref="fileInputRef"
54
81
  @change="onFileSelect"
55
- accept="image/*"
82
+ accept="image/png,image/jpeg,image/jpg,image/webp"
56
83
  style="display: none;"
57
- key="fileInputKey"
58
84
 
59
85
  />
60
86
  <button
@@ -64,7 +90,6 @@
64
90
  @click="
65
91
  () => {
66
92
  fileInputRef.value = '';
67
- fileInputKey++;
68
93
  fileInputRef?.click();
69
94
  }
70
95
  "
@@ -86,7 +111,7 @@
86
111
 
87
112
  <ODialog v-bind="dialog">
88
113
  <div v-if="currentDialogView === DIALOG_VIEWS.UPLOAD" class="flex flex-col justify-center items-center">
89
- <img v-for="(urlFile, i) in urlFiles" :key="i" :src="urlFile.toString()" alt="Image" width="400" />
114
+ <img v-for="(urlFile, i) in urlFilesPreview" :key="i" :src="urlFile.toString()" alt="Image" width="400" />
90
115
 
91
116
  <form
92
117
  class="message-send"
@@ -124,7 +149,7 @@
124
149
  </form>
125
150
  </div>
126
151
  <div v-else>
127
- <img v-if="urlFileMessage" :src="urlFileMessage" alt="Image" style="width: 55vw;" />
152
+ <img v-if="urlFileMessage" :src="urlFileMessage" alt="Image" style="max-height: 85vh;" />
128
153
  </div>
129
154
  </ODialog>
130
155
  </template>
@@ -176,9 +201,9 @@ const enum DIALOG_VIEWS {
176
201
  const message = ref("");
177
202
  const notViewed = ref(0);
178
203
  const fileInputRef = ref();
179
- const fileInputKey = ref(0);
180
204
  const currentDialogView = ref(DIALOG_VIEWS.SEE)
181
205
  const urlFileMessage = ref<string>()
206
+ const dropZoneRef = ref<InstanceType<typeof HTMLElement>>();
182
207
 
183
208
  const messagesData = ref<{ data: Message[]; canLoadMoreMessages: boolean }>({
184
209
  data: [],
@@ -294,7 +319,7 @@ function createMessage(message: string, codigoTipoMensaje?: TypeMessageTypeCodes
294
319
  createdAt: new Date().toISOString(),
295
320
  updatedAt: new Date().toISOString(),
296
321
  file: inputFiles.value?.[0],
297
- urlFile: urlFiles.value?.[0],
322
+ urlFile: urlFilesPreview.value?.[0],
298
323
  messageType,
299
324
  sender: {
300
325
  nombreCompleto: props.user.nombreCompleto,
@@ -344,9 +369,12 @@ function updateMessageStatus(
344
369
 
345
370
  messageUpdated = { ...messageAResponder, chatId: newMessage?.chatId }
346
371
  } else {
347
- messagesData.value.data[idxMessageToCommunicate] = messageUpdated;
372
+ const messageCopy = { ...messageUpdated }
373
+ messageCopy.urlFile = messagesData.value.data[idxMessageToCommunicate].urlFile;
374
+ delete messageCopy.thumbnailFile;
375
+ messagesData.value.data[idxMessageToCommunicate] = messageCopy;
348
376
  }
349
-
377
+
350
378
  return messageUpdated;
351
379
  }
352
380
 
@@ -355,7 +383,7 @@ const submitMessage = async (
355
383
  ) => {
356
384
 
357
385
  const newMessage = createMessage(message.value, messageExtraData?.codigoTipoMensaje);
358
- message.value = '';
386
+
359
387
  if (!newMessage) return;
360
388
 
361
389
  let idxMessageToCommunicate = -1;
@@ -377,6 +405,9 @@ const submitMessage = async (
377
405
  codigoTipoMensaje: messageExtraData?.codigoTipoMensaje,
378
406
  files: inputFiles.value,
379
407
  }
408
+
409
+ message.value = '';
410
+
380
411
  sendApi(body).then((messageSaved) => {
381
412
  let messageUpdated = updateMessageStatus(
382
413
  newMessage,
@@ -580,12 +611,13 @@ function onQualifying({ message: messageParam, emoji }: { message: Message, emoj
580
611
 
581
612
  const isDisabledBoxMessage = ref(false);
582
613
 
614
+ const tiposArchivosPermitidos = ['image/png', 'image/jpeg', 'image/jpg', 'image/webp'];
583
615
  // Adjuntar
584
616
  function onFileSelect() {
585
617
  inputFiles.value = [];
586
- urlFiles.value = [];
587
-
588
- const filesParam = fileInputRef.value?.files ?? []
618
+ urlFilesPreview.value = [];
619
+
620
+ const filesParam: File[] = Array.from(fileInputRef.value?.files) ?? []
589
621
 
590
622
  const file = filesParam?.[0];
591
623
 
@@ -593,7 +625,7 @@ function onFileSelect() {
593
625
 
594
626
  if (!file) return;
595
627
 
596
- if (!(['image/png','image/jpeg','image/jpg','image/webp'].includes(file.type))) {
628
+ if (!(tiposArchivosPermitidos.includes(file.type))) {
597
629
  emit('show-toast', {
598
630
  severity: "warn",
599
631
  summary: "Error",
@@ -613,10 +645,10 @@ function onFileSelect() {
613
645
  return
614
646
  }
615
647
 
616
- urlFiles.value.push(URL.createObjectURL(file))
648
+ urlFilesPreview.value.push(URL.createObjectURL(file))
617
649
 
618
650
  currentDialogView.value = DIALOG_VIEWS.UPLOAD;
619
- dialog.title = 'Preparar imagen';
651
+ dialog.title = 'Vista previa';
620
652
  dialog.modelValue = true;
621
653
 
622
654
  nextTick(()=>{
@@ -624,10 +656,69 @@ function onFileSelect() {
624
656
  })
625
657
  }
626
658
 
659
+
660
+ const handlePaste = (e: ClipboardEvent) => {
661
+ const files = e.clipboardData?.files ?? (window as any).clipboardData?.files ?? [];
662
+
663
+ if (files.length === 0) return;
664
+
665
+ const file = files?.[0];
666
+
667
+ if (!file) return;
668
+
669
+ if (!tiposArchivosPermitidos.includes(file?.type)) return;
670
+
671
+ currentDialogView.value = DIALOG_VIEWS.UPLOAD;
672
+ urlFilesPreview.value = [];
673
+
674
+ inputFiles.value = [file];
675
+ urlFilesPreview.value.push(URL.createObjectURL(file));
676
+ dialog.modelValue = true;
677
+
678
+ nextTick(()=>{
679
+ textAreaRef.value?.focus()
680
+ })
681
+ };
682
+
683
+ function dropHandler(ev: DragEvent) {
684
+ if (!ev.dataTransfer?.items) return;
685
+
686
+ currentDialogView.value = DIALOG_VIEWS.UPLOAD;
687
+
688
+ Array.from(ev.dataTransfer.items).forEach((item) => {
689
+ if (item.kind === 'file') {
690
+ const file = item.getAsFile();
691
+
692
+ if (!file) return;
693
+
694
+ if (!tiposArchivosPermitidos.includes(file.type)) {
695
+ emit('show-toast',{
696
+ severity: 'error',
697
+ summary: 'Error',
698
+ detail: 'El archivo debe ser una imagen',
699
+ life: 5000,
700
+ });
701
+
702
+ return;
703
+ }
704
+
705
+ inputFiles.value = [file];
706
+
707
+ urlFilesPreview.value = [];
708
+ urlFilesPreview.value.push(URL.createObjectURL(file));
709
+ dialog.modelValue = true;
710
+ }
711
+ });
712
+
713
+ nextTick(()=>{
714
+ textAreaRef.value?.focus()
715
+ })
716
+ }
717
+
627
718
  // Dialog
628
719
 
629
- const inputFiles = ref<(File & { objectURL: string })[]>([]);
630
- const urlFiles = ref<Array<string>>([]);
720
+ const inputFiles = ref<File[]>([]);
721
+ const urlFilesPreview = ref<Array<string>>([]);
631
722
 
632
723
  const dialog = reactive<IPropsDialog>({
633
724
  modelValue: false,
@@ -636,7 +727,7 @@ const dialog = reactive<IPropsDialog>({
636
727
 
637
728
  if (args) return;
638
729
 
639
- urlFiles.value = [];
730
+ urlFilesPreview.value = [];
640
731
  inputFiles.value = [];
641
732
  },
642
733
  title: 'Preparar imagen'
@@ -687,6 +778,7 @@ onUnmounted(() => {
687
778
 
688
779
  .messages-container {
689
780
  position: relative;
781
+ height: 100%;
690
782
  }
691
783
  .loader {
692
784
  position: absolute;
@@ -713,4 +805,8 @@ onUnmounted(() => {
713
805
  margin: 1.5rem;
714
806
  text-align: center;
715
807
  }
808
+
809
+ .drop-over {
810
+ border: 2px dashed #007bff !important;
811
+ }
716
812
  </style>