@quidgest/chatbot 0.1.0 → 0.2.0
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/index.d.ts +2 -1
- package/dist/index.js +44 -53
- package/dist/index.mjs +6662 -2305
- package/dist/style.css +1 -1
- package/dist/types/message.type.d.ts +18 -0
- package/package.json +7 -5
- package/src/assets/styles/styles.scss +88 -34
- package/src/components/CBMessage.vue +31 -50
- package/src/components/ChatBot.vue +172 -112
- package/src/components/index.ts +1 -1
- package/src/types/message.type.ts +37 -0
- package/src/assets/copy.svg +0 -7
- package/src/assets/thumbDown.svg +0 -9
- package/src/assets/thumbUp.svg +0 -9
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.
|
|
1
|
+
.q-chatbot{width:100%;padding:1rem;display:flex;flex-direction:column;height:100%}.q-chatbot input{line-height:1.5rem}.q-chatbot .q-input-group .i-text__field{border-radius:0;flex:1}.q-chatbot__text p{margin:0}.q-chatbot__content{background-color:#fff;border:1px solid #eaebec;height:100%;width:100%;display:flex;gap:.75rem;flex-direction:column;overflow:hidden}.q-chatbot__footer-container{padding:.8rem}.q-chatbot__input-wrapper{display:flex;flex-direction:column;position:relative}.q-chatbot__image-preview{display:inline-flex;align-items:center;position:relative;margin-top:.5rem;width:fit-content}.q-chatbot__image-preview img{width:60px;height:60px;object-fit:cover;border-radius:4px;margin-right:.25rem;border:1px solid #eaebec;overflow:hidden}.q-chatbot__image-preview img:hover+.q-chatbot__remove-image,.q-chatbot__image-preview img:focus+.q-chatbot__remove-image{opacity:1;pointer-events:auto}.q-chatbot__image-preview img:focus{outline:solid rgb(var(--q-theme-info-rgb)/50%)}.q-chatbot .q-btn.q-chatbot__remove-image{position:absolute;top:-5px;right:-5px;background-color:#00000080;color:#fff;border-radius:50%;padding:5px;font-size:12px;border:none;opacity:0;pointer-events:none;transition:opacity .2s ease-in-out}.q-chatbot .q-btn.q-chatbot__remove-image:hover,.q-chatbot .q-btn.q-chatbot__remove-image:focus{opacity:1;pointer-events:auto}.q-chatbot__send-container{padding-bottom:.25rem;display:flex;justify-content:space-between;width:100%}.q-chatbot__send-container .q-chatbot__send,.q-chatbot__send-container .q-chatbot__upload{border-radius:1rem}.q-chatbot__send-container .spacer{flex-grow:1}.q-chatbot__footer{position:sticky;padding:0 .5rem;border:1px solid #eaebec;border-radius:.25rem;bottom:0;width:100%;display:flex;flex-direction:column;gap:.25rem}.q-chatbot__footer-disabled{background-color:rgb(var(--q-theme-neutral-light-rgb)/.25);cursor:not-allowed}.q-chatbot__footer.drag-over{border:2px dashed rgb(var(--q-theme-primary-rgb)/.25);background-color:#018bd20d}.q-chatbot__footer .q-chatbot__input{min-height:50px;max-height:100px;border-bottom:1px solid #eaebec;overflow-y:auto}.q-chatbot__footer .q-text-area{max-height:100%;overflow-y:auto}.q-chatbot__footer .q-text-area .q-field__control{border:none}.q-chatbot__upload-container{display:flex;justify-content:flex-start;padding:.25rem 0}.q-chatbot__upload-container .q-chatbot__upload{border-radius:1rem}.q-chatbot__messages-container{display:flex;flex-direction:column;flex-grow:1;padding:0 1rem 2rem;gap:1.5rem;overflow-y:auto}.q-chatbot__messages-wrapper{display:flex;max-width:100%;gap:.2rem}.q-chatbot__tools{display:flex;flex-direction:row;justify-content:end;max-width:100%}.q-chatbot__message-wrapper{display:flex;flex-direction:column;gap:.2rem}.q-chatbot__message-container{display:flex;flex-direction:column;gap:.25rem}.q-chatbot__messages-wrapper_right{justify-content:flex-end}.q-chatbot__messages-wrapper_right .q-chatbot__message-container{align-items:flex-end}.q-chatbot__messages-wrapper_right .q-chatbot__message-wrapper{display:flex;align-items:flex-end}.q-chatbot__profile.q-icon__img{border-radius:50%;height:2rem;width:2rem}.q-chatbot__message{display:flex;align-items:center;padding:.3rem .5rem;background-color:#eaebec;width:fit-content;white-space:normal;min-height:2rem;word-wrap:break-word;word-break:break-word;border-radius:0 .5rem .5rem}.q-chatbot__messages-wrapper_right .q-chatbot__message{background-color:#018bd233;border-radius:.5rem 0 .5rem .5rem}.q-chatbot__sender{white-space:nowrap;color:#7c858d;font-size:.7rem}.q-chatbot__retry-button{align-items:center;display:flex}.q-chatbot__dialog-title{margin:.5rem 0}#comment-dialog .q-dialog__header,.hidden-input{display:none}.pulsing-dots{display:flex;align-items:center;justify-content:center;gap:.1rem}.dot{font-size:20px;line-height:1;animation:pulse 1s infinite;color:var(--q-theme-primary)}@keyframes pulse{0%,to{transform:scale(.8);opacity:.6}50%{transform:scale(1);opacity:1}}
|
|
@@ -14,3 +14,21 @@ export type ChatBotMessageContent = {
|
|
|
14
14
|
imageUrl?: string;
|
|
15
15
|
};
|
|
16
16
|
export type ChatBotMessageSender = 'bot' | 'user';
|
|
17
|
+
export interface CBMessageProps {
|
|
18
|
+
sender?: ChatBotMessageSender;
|
|
19
|
+
message?: string;
|
|
20
|
+
date?: Date;
|
|
21
|
+
loading?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Project locale
|
|
24
|
+
*/
|
|
25
|
+
dateFormat?: string;
|
|
26
|
+
/**
|
|
27
|
+
* User image
|
|
28
|
+
*/
|
|
29
|
+
userImage: string;
|
|
30
|
+
/**
|
|
31
|
+
* Chatbot image
|
|
32
|
+
*/
|
|
33
|
+
chatbotImage: string;
|
|
34
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quidgest/chatbot",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"main": "dist/index.cjs",
|
|
@@ -32,12 +32,14 @@
|
|
|
32
32
|
"lint:fix": "eslint . --fix && prettier --write --list-different src"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"axios": "^1.
|
|
36
|
-
"uuid": "^11.0
|
|
35
|
+
"axios": "^1.7.0",
|
|
36
|
+
"uuid": "^11.1.0",
|
|
37
|
+
"vue-markdown-render": "^2.2.1"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
|
-
"@types/
|
|
40
|
-
"@
|
|
40
|
+
"@types/markdown-it": "^14.1.2",
|
|
41
|
+
"@types/node": "^20.11.13",
|
|
42
|
+
"@vitejs/plugin-vue": "^4.5.2",
|
|
41
43
|
"eslint": "^9.9.0",
|
|
42
44
|
"eslint-plugin-prettier": "^5.2.1",
|
|
43
45
|
"prettier": "^3.3.3",
|
|
@@ -15,6 +15,12 @@
|
|
|
15
15
|
flex: 1;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
&__text {
|
|
19
|
+
p {
|
|
20
|
+
margin: 0;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
18
24
|
&__content {
|
|
19
25
|
background-color: white;
|
|
20
26
|
border: 1px solid #eaebec;
|
|
@@ -27,13 +33,70 @@
|
|
|
27
33
|
overflow: hidden;
|
|
28
34
|
}
|
|
29
35
|
|
|
30
|
-
|
|
31
36
|
&__footer-container {
|
|
32
37
|
padding: 0.8rem;
|
|
33
38
|
}
|
|
34
39
|
|
|
40
|
+
&__input-wrapper {
|
|
41
|
+
display: flex;
|
|
42
|
+
flex-direction: column;
|
|
43
|
+
position: relative;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
&__image-preview {
|
|
47
|
+
display: inline-flex;
|
|
48
|
+
align-items: center;
|
|
49
|
+
position: relative;
|
|
50
|
+
margin-top: 0.5rem;
|
|
51
|
+
width: fit-content;
|
|
52
|
+
|
|
53
|
+
img {
|
|
54
|
+
width: 60px;
|
|
55
|
+
height: 60px;
|
|
56
|
+
object-fit: cover;
|
|
57
|
+
border-radius: 4px;
|
|
58
|
+
margin-right: 0.25rem;
|
|
59
|
+
border: 1px solid #eaebec;
|
|
60
|
+
overflow: hidden;
|
|
61
|
+
|
|
62
|
+
&:hover,
|
|
63
|
+
&:focus {
|
|
64
|
+
|
|
65
|
+
& + .q-chatbot__remove-image {
|
|
66
|
+
opacity: 1;
|
|
67
|
+
pointer-events: auto;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
&:focus {
|
|
72
|
+
outline: solid rgb(var(--q-theme-info-rgb) / 50%);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.q-btn.q-chatbot__remove-image {
|
|
78
|
+
position: absolute;
|
|
79
|
+
top: -5px;
|
|
80
|
+
right: -5px;
|
|
81
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
82
|
+
color: white;
|
|
83
|
+
border-radius: 50%;
|
|
84
|
+
padding: 5px;
|
|
85
|
+
font-size: 12px;
|
|
86
|
+
border: none;
|
|
87
|
+
opacity: 0;
|
|
88
|
+
pointer-events: none;
|
|
89
|
+
transition: opacity 0.2s ease-in-out;
|
|
90
|
+
|
|
91
|
+
&:hover,
|
|
92
|
+
&:focus {
|
|
93
|
+
opacity: 1;
|
|
94
|
+
pointer-events: auto;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
35
98
|
&__send-container {
|
|
36
|
-
padding-bottom: .25rem;
|
|
99
|
+
padding-bottom: 0.25rem;
|
|
37
100
|
display: flex;
|
|
38
101
|
justify-content: space-between;
|
|
39
102
|
width: 100%;
|
|
@@ -53,20 +116,25 @@
|
|
|
53
116
|
|
|
54
117
|
&__footer {
|
|
55
118
|
position: sticky;
|
|
56
|
-
padding: 0 .5rem;
|
|
119
|
+
padding: 0 0.5rem;
|
|
57
120
|
border: 1px solid #eaebec;
|
|
58
|
-
border-radius: .25rem;
|
|
121
|
+
border-radius: 0.25rem;
|
|
59
122
|
bottom: 0;
|
|
60
123
|
width: 100%;
|
|
61
124
|
display: flex;
|
|
62
125
|
flex-direction: column;
|
|
63
|
-
gap: .25rem;
|
|
126
|
+
gap: 0.25rem;
|
|
64
127
|
|
|
65
128
|
&-disabled {
|
|
66
129
|
background-color: rgb(var(--q-theme-neutral-light-rgb) / 0.25);
|
|
67
130
|
cursor: not-allowed;
|
|
68
131
|
}
|
|
69
132
|
|
|
133
|
+
&.drag-over {
|
|
134
|
+
border: 2px dashed rgb(var(--q-theme-primary-rgb) / 0.25);
|
|
135
|
+
background-color: rgba(1, 139, 210, 0.05);
|
|
136
|
+
}
|
|
137
|
+
|
|
70
138
|
& .q-chatbot__input {
|
|
71
139
|
min-height: 50px;
|
|
72
140
|
max-height: 100px;
|
|
@@ -87,8 +155,8 @@
|
|
|
87
155
|
&__upload-container {
|
|
88
156
|
display: flex;
|
|
89
157
|
justify-content: flex-start;
|
|
90
|
-
padding: .25rem 0;
|
|
91
|
-
|
|
158
|
+
padding: 0.25rem 0;
|
|
159
|
+
|
|
92
160
|
& .q-chatbot__upload {
|
|
93
161
|
border-radius: 1rem;
|
|
94
162
|
}
|
|
@@ -180,29 +248,14 @@
|
|
|
180
248
|
display: flex;
|
|
181
249
|
}
|
|
182
250
|
|
|
183
|
-
&
|
|
184
|
-
|
|
185
|
-
display: inline-block;
|
|
186
|
-
|
|
187
|
-
img {
|
|
188
|
-
max-height: 100px;
|
|
189
|
-
width: auto;
|
|
190
|
-
border-radius: 8px;
|
|
191
|
-
margin: 10px 0;
|
|
192
|
-
}
|
|
251
|
+
&__dialog-title{
|
|
252
|
+
margin: 0.5rem 0;
|
|
193
253
|
}
|
|
254
|
+
}
|
|
194
255
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
right: 5px;
|
|
199
|
-
background-color: rgba(0, 0, 0, 0.5);
|
|
200
|
-
color: white;
|
|
201
|
-
border-radius: 50%;
|
|
202
|
-
padding: 5px;
|
|
203
|
-
cursor: pointer;
|
|
204
|
-
font-size: 12px;
|
|
205
|
-
border: none;
|
|
256
|
+
#comment-dialog {
|
|
257
|
+
.q-dialog__header {
|
|
258
|
+
display: none;
|
|
206
259
|
}
|
|
207
260
|
}
|
|
208
261
|
|
|
@@ -225,12 +278,13 @@
|
|
|
225
278
|
}
|
|
226
279
|
|
|
227
280
|
@keyframes pulse {
|
|
228
|
-
0%,
|
|
229
|
-
|
|
230
|
-
|
|
281
|
+
0%,
|
|
282
|
+
100% {
|
|
283
|
+
transform: scale(0.8);
|
|
284
|
+
opacity: 0.6;
|
|
231
285
|
}
|
|
232
286
|
50% {
|
|
233
|
-
|
|
234
|
-
|
|
287
|
+
transform: scale(1);
|
|
288
|
+
opacity: 1;
|
|
235
289
|
}
|
|
236
|
-
}
|
|
290
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="q-chatbot__message-container">
|
|
3
|
-
<!-- Chatbot Image -->
|
|
4
3
|
<q-icon
|
|
5
4
|
type="img"
|
|
6
5
|
:icon="messageImage"
|
|
@@ -20,22 +19,26 @@
|
|
|
20
19
|
<!-- When loading is true, show bouncing dots animation -->
|
|
21
20
|
<pulse-dots v-if="loading" />
|
|
22
21
|
<template v-else>
|
|
23
|
-
<
|
|
24
|
-
class="q-chatbot__text"
|
|
22
|
+
<vue-markdown-render
|
|
25
23
|
v-if="props.sender === 'bot'"
|
|
26
|
-
v-html="props.message"></div>
|
|
27
|
-
<div
|
|
28
24
|
class="q-chatbot__text"
|
|
29
|
-
|
|
25
|
+
:source="props.message || ''" />
|
|
26
|
+
|
|
27
|
+
<div
|
|
28
|
+
v-else
|
|
29
|
+
class="q-chatbot__text">
|
|
30
30
|
{{ props.message }}
|
|
31
31
|
</div>
|
|
32
32
|
</template>
|
|
33
33
|
</div>
|
|
34
34
|
<q-dialog
|
|
35
|
+
id="comment-dialog"
|
|
35
36
|
v-model="showDialog"
|
|
36
|
-
:buttons="commentButtons"
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
:buttons="commentButtons">
|
|
38
|
+
<template #body.content>
|
|
39
|
+
<div class="q-chatbot__dialog-title">
|
|
40
|
+
{{ props.texts.commentDialogTitle }}
|
|
41
|
+
</div>
|
|
39
42
|
<q-text-field
|
|
40
43
|
v-model="feedbackComment"
|
|
41
44
|
:maxLength="150"
|
|
@@ -55,7 +58,7 @@
|
|
|
55
58
|
:disabled="loading"
|
|
56
59
|
b-style="secondary"
|
|
57
60
|
@click="openFeedbackDialog(1)">
|
|
58
|
-
<
|
|
61
|
+
<q-icon icon="thumb-up" />
|
|
59
62
|
</q-button>
|
|
60
63
|
<q-button
|
|
61
64
|
:title="props.texts.badResponse"
|
|
@@ -63,7 +66,7 @@
|
|
|
63
66
|
:disabled="loading"
|
|
64
67
|
b-style="secondary"
|
|
65
68
|
@click="openFeedbackDialog(0)">
|
|
66
|
-
<
|
|
69
|
+
<q-icon icon="thumb-down" />
|
|
67
70
|
</q-button>
|
|
68
71
|
<q-button
|
|
69
72
|
:title="props.texts.copyResponse"
|
|
@@ -71,7 +74,7 @@
|
|
|
71
74
|
:disabled="loading"
|
|
72
75
|
b-style="secondary"
|
|
73
76
|
@click="copyResponse">
|
|
74
|
-
<
|
|
77
|
+
<q-icon icon="copy-content" />
|
|
75
78
|
</q-button>
|
|
76
79
|
</q-button-group>
|
|
77
80
|
</div>
|
|
@@ -93,17 +96,8 @@
|
|
|
93
96
|
import PulseDots from '@/components/PulseDots.vue'
|
|
94
97
|
import type { ChatBotMessageSender } from '@/types/message.type'
|
|
95
98
|
import { ResourceStrings } from '@/types/texts.type'
|
|
99
|
+
import VueMarkdownRender from 'vue-markdown-render'
|
|
96
100
|
import Axios from 'axios'
|
|
97
|
-
|
|
98
|
-
// Importando o conteúdo dos arquivos SVG como strings
|
|
99
|
-
import thumbUpSvgFile from '@/assets/thumbUp.svg?raw'
|
|
100
|
-
import thumbDownSvgFile from '@/assets/thumbDown.svg?raw'
|
|
101
|
-
import copySvgFile from '@/assets/copy.svg?raw'
|
|
102
|
-
|
|
103
|
-
// Armazenando o conteúdo SVG como strings
|
|
104
|
-
const thumbUpSvg = thumbUpSvgFile;
|
|
105
|
-
const thumbDownSvg = thumbDownSvgFile;
|
|
106
|
-
const copySvg = copySvgFile;
|
|
107
101
|
|
|
108
102
|
export interface CBMessageProps {
|
|
109
103
|
/*
|
|
@@ -160,7 +154,7 @@
|
|
|
160
154
|
* Chatbot image
|
|
161
155
|
*/
|
|
162
156
|
chatbotImage: string
|
|
163
|
-
|
|
157
|
+
|
|
164
158
|
/**
|
|
165
159
|
* Flag to mark welcome messages
|
|
166
160
|
*/
|
|
@@ -193,36 +187,40 @@
|
|
|
193
187
|
action: submitFeedback,
|
|
194
188
|
props: {
|
|
195
189
|
label: props.texts.submitButton,
|
|
196
|
-
'b-style': 'primary'
|
|
190
|
+
'b-style': 'primary',
|
|
191
|
+
},
|
|
192
|
+
icon: {
|
|
193
|
+
icon: 'submit'
|
|
197
194
|
}
|
|
198
195
|
},
|
|
199
196
|
{
|
|
200
197
|
id: 'cancel-btn',
|
|
201
198
|
props: {
|
|
202
199
|
label: props.texts.cancelButton,
|
|
203
|
-
'b-style': '
|
|
200
|
+
'b-style': 'secondary',
|
|
201
|
+
},
|
|
202
|
+
icon: {
|
|
203
|
+
icon: 'cancel'
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
]
|
|
207
207
|
|
|
208
|
-
const senderName = computed(() => {
|
|
209
|
-
return props.sender === 'bot' ? 'GenioBot' : 'You'
|
|
210
|
-
})
|
|
211
|
-
|
|
212
208
|
const isBotMessageAndNotDefault = computed(() => {
|
|
213
|
-
return
|
|
209
|
+
return (
|
|
210
|
+
props.sender === 'bot' &&
|
|
214
211
|
!Object.values(props.texts || {}).includes(props.message || '') &&
|
|
215
212
|
!props.isWelcomeMessage
|
|
213
|
+
)
|
|
216
214
|
})
|
|
217
215
|
|
|
218
216
|
const getLocaleDate = computed(() => {
|
|
219
217
|
if (!props.dateFormat) return props.date.toLocaleString()
|
|
220
218
|
|
|
221
|
-
return formatDate(props.date,
|
|
219
|
+
return formatDate(props.date, 'HH:mm')
|
|
222
220
|
})
|
|
223
221
|
|
|
224
222
|
const messageDate = computed(() => {
|
|
225
|
-
return `${
|
|
223
|
+
return `${getLocaleDate.value}`
|
|
226
224
|
})
|
|
227
225
|
|
|
228
226
|
const messageImage = computed(() =>
|
|
@@ -276,24 +274,7 @@
|
|
|
276
274
|
console.log('Message copied to clipboard')
|
|
277
275
|
})
|
|
278
276
|
.catch((error) => {
|
|
279
|
-
console.error(
|
|
280
|
-
'Failed to copy message to clipboard: ',
|
|
281
|
-
error
|
|
282
|
-
)
|
|
277
|
+
console.error('Failed to copy message to clipboard: ', error)
|
|
283
278
|
})
|
|
284
279
|
}
|
|
285
280
|
</script>
|
|
286
|
-
|
|
287
|
-
<style scoped>
|
|
288
|
-
|
|
289
|
-
.svg-icon {
|
|
290
|
-
display: inline-flex;
|
|
291
|
-
width: 16px;
|
|
292
|
-
height: 14px;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
.svg-icon :deep(svg) {
|
|
296
|
-
width: 100%;
|
|
297
|
-
height: 100%;
|
|
298
|
-
}
|
|
299
|
-
</style>
|