@quidgest/chatbot 0.1.0 → 0.3.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 +47 -49
- package/dist/index.mjs +7731 -2426
- package/dist/style.css +1 -1
- package/dist/types/message.type.d.ts +18 -0
- package/package.json +9 -7
- package/src/assets/styles/styles.scss +88 -34
- package/src/components/CBMessage.vue +31 -54
- package/src/components/ChatBot.vue +171 -114
- 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-button.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-button.q-chatbot__remove-image:hover,.q-chatbot .q-button.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.3.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",
|
|
@@ -49,7 +51,7 @@
|
|
|
49
51
|
"vue-tsc": "^1.8.27"
|
|
50
52
|
},
|
|
51
53
|
"peerDependencies": {
|
|
52
|
-
"@quidgest/ui": "^0.
|
|
53
|
-
"vue": "3.5.13"
|
|
54
|
+
"@quidgest/ui": "^0.15.9",
|
|
55
|
+
"vue": "^3.5.13"
|
|
54
56
|
}
|
|
55
57
|
}
|
|
@@ -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-button.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"
|
|
@@ -53,25 +56,22 @@
|
|
|
53
56
|
:title="props.texts.goodResponse"
|
|
54
57
|
borderless
|
|
55
58
|
:disabled="loading"
|
|
56
|
-
b-style="secondary"
|
|
57
59
|
@click="openFeedbackDialog(1)">
|
|
58
|
-
<
|
|
60
|
+
<q-icon icon="thumb-up" />
|
|
59
61
|
</q-button>
|
|
60
62
|
<q-button
|
|
61
63
|
:title="props.texts.badResponse"
|
|
62
64
|
borderless
|
|
63
65
|
:disabled="loading"
|
|
64
|
-
b-style="secondary"
|
|
65
66
|
@click="openFeedbackDialog(0)">
|
|
66
|
-
<
|
|
67
|
+
<q-icon icon="thumb-down" />
|
|
67
68
|
</q-button>
|
|
68
69
|
<q-button
|
|
69
70
|
:title="props.texts.copyResponse"
|
|
70
71
|
borderless
|
|
71
72
|
:disabled="loading"
|
|
72
|
-
b-style="secondary"
|
|
73
73
|
@click="copyResponse">
|
|
74
|
-
<
|
|
74
|
+
<q-icon icon="copy-content" />
|
|
75
75
|
</q-button>
|
|
76
76
|
</q-button-group>
|
|
77
77
|
</div>
|
|
@@ -93,17 +93,8 @@
|
|
|
93
93
|
import PulseDots from '@/components/PulseDots.vue'
|
|
94
94
|
import type { ChatBotMessageSender } from '@/types/message.type'
|
|
95
95
|
import { ResourceStrings } from '@/types/texts.type'
|
|
96
|
+
import VueMarkdownRender from 'vue-markdown-render'
|
|
96
97
|
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
98
|
|
|
108
99
|
export interface CBMessageProps {
|
|
109
100
|
/*
|
|
@@ -160,7 +151,7 @@
|
|
|
160
151
|
* Chatbot image
|
|
161
152
|
*/
|
|
162
153
|
chatbotImage: string
|
|
163
|
-
|
|
154
|
+
|
|
164
155
|
/**
|
|
165
156
|
* Flag to mark welcome messages
|
|
166
157
|
*/
|
|
@@ -193,36 +184,39 @@
|
|
|
193
184
|
action: submitFeedback,
|
|
194
185
|
props: {
|
|
195
186
|
label: props.texts.submitButton,
|
|
196
|
-
'
|
|
187
|
+
'variant': 'bold',
|
|
188
|
+
},
|
|
189
|
+
icon: {
|
|
190
|
+
icon: 'submit'
|
|
197
191
|
}
|
|
198
192
|
},
|
|
199
193
|
{
|
|
200
194
|
id: 'cancel-btn',
|
|
201
195
|
props: {
|
|
202
|
-
label: props.texts.cancelButton
|
|
203
|
-
|
|
196
|
+
label: props.texts.cancelButton
|
|
197
|
+
},
|
|
198
|
+
icon: {
|
|
199
|
+
icon: 'cancel'
|
|
204
200
|
}
|
|
205
201
|
}
|
|
206
202
|
]
|
|
207
203
|
|
|
208
|
-
const senderName = computed(() => {
|
|
209
|
-
return props.sender === 'bot' ? 'GenioBot' : 'You'
|
|
210
|
-
})
|
|
211
|
-
|
|
212
204
|
const isBotMessageAndNotDefault = computed(() => {
|
|
213
|
-
return
|
|
205
|
+
return (
|
|
206
|
+
props.sender === 'bot' &&
|
|
214
207
|
!Object.values(props.texts || {}).includes(props.message || '') &&
|
|
215
208
|
!props.isWelcomeMessage
|
|
209
|
+
)
|
|
216
210
|
})
|
|
217
211
|
|
|
218
212
|
const getLocaleDate = computed(() => {
|
|
219
213
|
if (!props.dateFormat) return props.date.toLocaleString()
|
|
220
214
|
|
|
221
|
-
return formatDate(props.date,
|
|
215
|
+
return formatDate(props.date, 'HH:mm')
|
|
222
216
|
})
|
|
223
217
|
|
|
224
218
|
const messageDate = computed(() => {
|
|
225
|
-
return `${
|
|
219
|
+
return `${getLocaleDate.value}`
|
|
226
220
|
})
|
|
227
221
|
|
|
228
222
|
const messageImage = computed(() =>
|
|
@@ -276,24 +270,7 @@
|
|
|
276
270
|
console.log('Message copied to clipboard')
|
|
277
271
|
})
|
|
278
272
|
.catch((error) => {
|
|
279
|
-
console.error(
|
|
280
|
-
'Failed to copy message to clipboard: ',
|
|
281
|
-
error
|
|
282
|
-
)
|
|
273
|
+
console.error('Failed to copy message to clipboard: ', error)
|
|
283
274
|
})
|
|
284
275
|
}
|
|
285
276
|
</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>
|