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/dist/components/Chat.vue.d.ts +1 -0
- package/dist/dto/app.dto.d.ts +1 -3
- package/dist/style.css +1 -1
- package/dist/vue-wiguet-chatweb.js +2279 -2206
- package/dist/vue-wiguet-chatweb.umd.cjs +10 -10
- package/package.json +1 -1
- package/src/components/Chat.vue +137 -41
package/package.json
CHANGED
package/src/components/Chat.vue
CHANGED
@@ -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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
@
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
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="
|
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:
|
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
|
-
|
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
|
-
|
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
|
-
|
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 (!(
|
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
|
-
|
648
|
+
urlFilesPreview.value.push(URL.createObjectURL(file))
|
617
649
|
|
618
650
|
currentDialogView.value = DIALOG_VIEWS.UPLOAD;
|
619
|
-
dialog.title = '
|
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<
|
630
|
-
const
|
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
|
-
|
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>
|