@gitlab/duo-ui 15.8.3 → 15.9.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/agentic_chat/components/agentic_binary_feedback/agentic_binary_feedback.js +143 -16
- package/dist/components/chat/components/duo_chat_message/duo_chat_message.js +1 -1
- package/dist/tailwind.css +1 -1
- package/dist/tailwind.css.map +1 -1
- package/package.json +4 -4
- package/src/components/agentic_chat/components/agentic_binary_feedback/agentic_binary_feedback.vue +233 -14
- package/src/components/chat/components/duo_chat_message/duo_chat_message.vue +1 -1
- package/translations.js +15 -0
- package/CHANGELOG.md +0 -1986
package/src/components/agentic_chat/components/agentic_binary_feedback/agentic_binary_feedback.vue
CHANGED
|
@@ -1,19 +1,64 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import {
|
|
2
|
+
import { nextTick } from 'vue';
|
|
3
|
+
import { GlButton, GlIcon, GlTooltipDirective, GlFormTextarea, GlForm } from '@gitlab/ui';
|
|
3
4
|
import { translate } from '@gitlab/ui/dist/utils/i18n';
|
|
4
5
|
|
|
5
6
|
export const i18n = {
|
|
6
7
|
THANKS: translate('AgenticBinaryFeedback.thanks', 'Thanks for the feedback!'),
|
|
7
8
|
THUMBS_UP: translate('AgenticBinaryFeedback.thumbsUp', 'Helpful'),
|
|
8
9
|
THUMBS_DOWN: translate('AgenticBinaryFeedback.thumbsDown', 'Not helpful'),
|
|
10
|
+
TELL_US_MORE: translate('AgenticBinaryFeedback.tellUsMore', 'Tell us more'),
|
|
11
|
+
SUBMIT: translate('AgenticBinaryFeedback.submit', 'Submit'),
|
|
12
|
+
BACK: translate('AgenticBinaryFeedback.back', 'Back'),
|
|
13
|
+
CLOSE: translate('AgenticBinaryFeedback.close', 'Close'),
|
|
14
|
+
FEEDBACK_PLACEHOLDER: translate('AgenticBinaryFeedback.placeholder', 'Share your feedback...'),
|
|
15
|
+
THUMBS_UP_HEADER: translate('AgenticBinaryFeedback.thumbsUpHeader', 'What made this helpful?'),
|
|
16
|
+
THUMBS_DOWN_HEADER: translate(
|
|
17
|
+
'AgenticBinaryFeedback.thumbsDownHeader',
|
|
18
|
+
'What would have been more helpful?'
|
|
19
|
+
),
|
|
20
|
+
TOO_GENERIC: translate('AgenticBinaryFeedback.tooGeneric', 'Too generic'),
|
|
21
|
+
MISSING_STEPS: translate('AgenticBinaryFeedback.missingSteps', 'Missing steps'),
|
|
22
|
+
WRONG_CONTEXT: translate('AgenticBinaryFeedback.wrongContext', 'Wrong context'),
|
|
23
|
+
OUTDATED_INCORRECT: translate('AgenticBinaryFeedback.outdatedIncorrect', 'Outdated/incorrect'),
|
|
24
|
+
SOLVED_PROBLEM: translate('AgenticBinaryFeedback.solvedProblem', 'Solved my problem'),
|
|
25
|
+
SAVED_TIME: translate('AgenticBinaryFeedback.savedTime', 'Saved me time'),
|
|
26
|
+
GOOD_EXAMPLES: translate('AgenticBinaryFeedback.goodExamples', 'Good examples'),
|
|
27
|
+
ACCURATE_INFO: translate('AgenticBinaryFeedback.accurateInfo', 'Accurate information'),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const thumbsDownReasons = [
|
|
31
|
+
{ key: 'too_generic', label: i18n.TOO_GENERIC },
|
|
32
|
+
{ key: 'missing_steps', label: i18n.MISSING_STEPS },
|
|
33
|
+
{ key: 'wrong_context', label: i18n.WRONG_CONTEXT },
|
|
34
|
+
{ key: 'outdated_incorrect', label: i18n.OUTDATED_INCORRECT },
|
|
35
|
+
{ key: 'tell_us_more', label: i18n.TELL_US_MORE, isCustom: true },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
export const thumbsUpReasons = [
|
|
39
|
+
{ key: 'solved_problem', label: i18n.SOLVED_PROBLEM },
|
|
40
|
+
{ key: 'saved_time', label: i18n.SAVED_TIME },
|
|
41
|
+
{ key: 'good_examples', label: i18n.GOOD_EXAMPLES },
|
|
42
|
+
{ key: 'accurate_info', label: i18n.ACCURATE_INFO },
|
|
43
|
+
{ key: 'tell_us_more', label: i18n.TELL_US_MORE, isCustom: true },
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
export const FEEDBACK_VIEW = {
|
|
47
|
+
CLOSED: 'closed',
|
|
48
|
+
REASON_LIST: 'reason_list',
|
|
49
|
+
TELL_US_MORE: 'tell_us_more',
|
|
9
50
|
};
|
|
10
51
|
|
|
11
52
|
export default {
|
|
12
53
|
name: 'AgenticBinaryFeedback',
|
|
13
54
|
i18n,
|
|
55
|
+
thumbsUpReasons,
|
|
56
|
+
thumbsDownReasons,
|
|
14
57
|
components: {
|
|
15
58
|
GlButton,
|
|
16
59
|
GlIcon,
|
|
60
|
+
GlFormTextarea,
|
|
61
|
+
GlForm,
|
|
17
62
|
},
|
|
18
63
|
directives: {
|
|
19
64
|
GlTooltip: GlTooltipDirective,
|
|
@@ -21,34 +66,108 @@ export default {
|
|
|
21
66
|
data() {
|
|
22
67
|
return {
|
|
23
68
|
feedbackType: null,
|
|
69
|
+
feedbackView: FEEDBACK_VIEW.CLOSED,
|
|
70
|
+
customFeedback: '',
|
|
71
|
+
feedbackSubmitted: false,
|
|
24
72
|
};
|
|
25
73
|
},
|
|
26
74
|
computed: {
|
|
27
|
-
feedbackGiven() {
|
|
28
|
-
return this.feedbackType !== null;
|
|
29
|
-
},
|
|
30
75
|
isThumbsUp() {
|
|
31
76
|
return this.feedbackType === 'thumbs_up';
|
|
32
77
|
},
|
|
33
78
|
isThumbsDown() {
|
|
34
79
|
return this.feedbackType === 'thumbs_down';
|
|
35
80
|
},
|
|
81
|
+
reasonOptions() {
|
|
82
|
+
return this.isThumbsUp ? this.$options.thumbsUpReasons : this.$options.thumbsDownReasons;
|
|
83
|
+
},
|
|
84
|
+
reasonHeader() {
|
|
85
|
+
return this.isThumbsUp
|
|
86
|
+
? this.$options.i18n.THUMBS_UP_HEADER
|
|
87
|
+
: this.$options.i18n.THUMBS_DOWN_HEADER;
|
|
88
|
+
},
|
|
89
|
+
isOverCharacterLimit() {
|
|
90
|
+
return this.customFeedback.length > 140;
|
|
91
|
+
},
|
|
92
|
+
trimmedFeedback() {
|
|
93
|
+
return this.customFeedback.trim();
|
|
94
|
+
},
|
|
95
|
+
isTextareaValid() {
|
|
96
|
+
return this.trimmedFeedback.length === 0 ? null : !this.isOverCharacterLimit;
|
|
97
|
+
},
|
|
98
|
+
canSubmitCustomFeedback() {
|
|
99
|
+
return this.trimmedFeedback.length > 0 && !this.isOverCharacterLimit;
|
|
100
|
+
},
|
|
101
|
+
characterCountText() {
|
|
102
|
+
const remaining = 140 - this.customFeedback.length;
|
|
103
|
+
if (remaining >= 0) {
|
|
104
|
+
return remaining === 1
|
|
105
|
+
? `${remaining} character remaining`
|
|
106
|
+
: `${remaining} characters remaining`;
|
|
107
|
+
}
|
|
108
|
+
const over = Math.abs(remaining);
|
|
109
|
+
return over === 1 ? `${over} character over limit` : `${over} characters over limit`;
|
|
110
|
+
},
|
|
111
|
+
isDropdownOpen() {
|
|
112
|
+
return this.feedbackView !== FEEDBACK_VIEW.CLOSED;
|
|
113
|
+
},
|
|
114
|
+
isReasonListVisible() {
|
|
115
|
+
return this.feedbackView === FEEDBACK_VIEW.REASON_LIST;
|
|
116
|
+
},
|
|
117
|
+
isTellUsMoreVisible() {
|
|
118
|
+
return this.feedbackView === FEEDBACK_VIEW.TELL_US_MORE;
|
|
119
|
+
},
|
|
36
120
|
},
|
|
37
121
|
methods: {
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Notify listeners about the feedback submission.
|
|
41
|
-
* @param {string} type The feedback type ('thumbs_up' or 'thumbs_down').
|
|
42
|
-
*/
|
|
43
|
-
this.$emit('feedback', { feedbackType: type });
|
|
122
|
+
selectFeedbackType(type) {
|
|
44
123
|
this.feedbackType = type;
|
|
124
|
+
this.feedbackView = FEEDBACK_VIEW.REASON_LIST;
|
|
125
|
+
this.customFeedback = '';
|
|
126
|
+
this.scrollToDropdown();
|
|
127
|
+
},
|
|
128
|
+
scrollToDropdown() {
|
|
129
|
+
nextTick(() => {
|
|
130
|
+
const el = this.$refs.dropdown?.$el || this.$refs.dropdown;
|
|
131
|
+
el?.scrollIntoView?.({ behavior: 'smooth', block: 'nearest' });
|
|
132
|
+
});
|
|
133
|
+
},
|
|
134
|
+
selectReason(reason) {
|
|
135
|
+
if (reason.isCustom) {
|
|
136
|
+
this.feedbackView = FEEDBACK_VIEW.TELL_US_MORE;
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
this.submitFeedback(reason.key);
|
|
140
|
+
},
|
|
141
|
+
submitCustomFeedback() {
|
|
142
|
+
this.submitFeedback(`custom_${this.customFeedback.trim()}`);
|
|
143
|
+
},
|
|
144
|
+
submitFeedback(feedbackReason) {
|
|
145
|
+
this.$emit('feedback', {
|
|
146
|
+
feedbackType: this.feedbackType,
|
|
147
|
+
feedbackReason,
|
|
148
|
+
});
|
|
149
|
+
this.feedbackView = FEEDBACK_VIEW.CLOSED;
|
|
150
|
+
this.feedbackSubmitted = true;
|
|
151
|
+
},
|
|
152
|
+
goBackToReasons() {
|
|
153
|
+
this.feedbackView = FEEDBACK_VIEW.REASON_LIST;
|
|
154
|
+
this.customFeedback = '';
|
|
155
|
+
},
|
|
156
|
+
closeDropdown() {
|
|
157
|
+
this.feedbackView = FEEDBACK_VIEW.CLOSED;
|
|
158
|
+
this.customFeedback = '';
|
|
159
|
+
this.feedbackType = null;
|
|
45
160
|
},
|
|
46
161
|
},
|
|
47
162
|
};
|
|
48
163
|
</script>
|
|
164
|
+
|
|
49
165
|
<template>
|
|
50
|
-
<div
|
|
51
|
-
|
|
166
|
+
<div
|
|
167
|
+
class="agentic-binary-feedback gl-flex gl-items-center gl-gap-2"
|
|
168
|
+
:class="{ 'gl-relative': !isDropdownOpen }"
|
|
169
|
+
>
|
|
170
|
+
<template v-if="!feedbackSubmitted && !isDropdownOpen">
|
|
52
171
|
<gl-button
|
|
53
172
|
v-gl-tooltip
|
|
54
173
|
:title="$options.i18n.THUMBS_UP"
|
|
@@ -57,7 +176,7 @@ export default {
|
|
|
57
176
|
category="tertiary"
|
|
58
177
|
size="small"
|
|
59
178
|
data-testid="thumb-up-button"
|
|
60
|
-
@click="
|
|
179
|
+
@click="selectFeedbackType('thumbs_up')"
|
|
61
180
|
/>
|
|
62
181
|
<gl-button
|
|
63
182
|
v-gl-tooltip
|
|
@@ -67,9 +186,109 @@ export default {
|
|
|
67
186
|
category="tertiary"
|
|
68
187
|
size="small"
|
|
69
188
|
data-testid="thumb-down-button"
|
|
70
|
-
@click="
|
|
189
|
+
@click="selectFeedbackType('thumbs_down')"
|
|
71
190
|
/>
|
|
72
191
|
</template>
|
|
192
|
+
|
|
193
|
+
<template v-else-if="isDropdownOpen">
|
|
194
|
+
<div class="gl-flex gl-h-6 gl-items-center">
|
|
195
|
+
<gl-icon
|
|
196
|
+
:name="isThumbsUp ? 'thumb-up' : 'thumb-down'"
|
|
197
|
+
:size="16"
|
|
198
|
+
:class="isThumbsUp ? 'gl-text-success' : 'gl-text-danger'"
|
|
199
|
+
data-testid="selected-thumb-icon"
|
|
200
|
+
/>
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
<div
|
|
204
|
+
ref="dropdown"
|
|
205
|
+
class="feedback-reason-dropdown gl-l-0 gl-r-0 gl-border gl-absolute gl-top-full gl-mb-4 gl-mt-4 gl-w-full gl-rounded-lg gl-border-default gl-bg-subtle gl-p-3"
|
|
206
|
+
data-testid="feedback-reason-dropdown"
|
|
207
|
+
>
|
|
208
|
+
<div class="gl-mb-3 gl-flex gl-items-center gl-justify-between gl-gap-2">
|
|
209
|
+
<p class="gl-m-0 gl-text-sm gl-font-bold" data-testid="reason-header">
|
|
210
|
+
{{ reasonHeader }}
|
|
211
|
+
</p>
|
|
212
|
+
<div class="gl-flex gl-shrink-0 gl-items-center gl-gap-1">
|
|
213
|
+
<gl-button
|
|
214
|
+
v-if="isTellUsMoreVisible"
|
|
215
|
+
icon="go-back"
|
|
216
|
+
category="tertiary"
|
|
217
|
+
size="small"
|
|
218
|
+
:aria-label="$options.i18n.BACK"
|
|
219
|
+
data-testid="back-button"
|
|
220
|
+
@click="goBackToReasons"
|
|
221
|
+
/>
|
|
222
|
+
<gl-button
|
|
223
|
+
icon="close"
|
|
224
|
+
category="tertiary"
|
|
225
|
+
size="small"
|
|
226
|
+
class="gl-mr-[-5px]"
|
|
227
|
+
:aria-label="$options.i18n.CLOSE"
|
|
228
|
+
data-testid="close-dropdown-button"
|
|
229
|
+
@click="closeDropdown"
|
|
230
|
+
/>
|
|
231
|
+
</div>
|
|
232
|
+
</div>
|
|
233
|
+
|
|
234
|
+
<div
|
|
235
|
+
v-if="isReasonListVisible"
|
|
236
|
+
class="gl-flex gl-flex-wrap gl-gap-2"
|
|
237
|
+
data-testid="reason-buttons"
|
|
238
|
+
>
|
|
239
|
+
<gl-button
|
|
240
|
+
v-for="reason in reasonOptions"
|
|
241
|
+
:key="reason.key"
|
|
242
|
+
category="secondary"
|
|
243
|
+
size="small"
|
|
244
|
+
class="gl-rounded-full"
|
|
245
|
+
:icon="reason.isCustom ? 'pencil' : undefined"
|
|
246
|
+
:data-testid="`reason-${reason.key}`"
|
|
247
|
+
@click="selectReason(reason)"
|
|
248
|
+
>
|
|
249
|
+
{{ reason.label }}
|
|
250
|
+
</gl-button>
|
|
251
|
+
</div>
|
|
252
|
+
|
|
253
|
+
<div
|
|
254
|
+
v-if="isTellUsMoreVisible"
|
|
255
|
+
class="gl-flex gl-w-full gl-flex-col gl-gap-3"
|
|
256
|
+
data-testid="tell-us-more-view"
|
|
257
|
+
>
|
|
258
|
+
<gl-form
|
|
259
|
+
class="gl-flex gl-w-full gl-flex-col gl-gap-3"
|
|
260
|
+
@submit.prevent="canSubmitCustomFeedback ? submitCustomFeedback() : null"
|
|
261
|
+
>
|
|
262
|
+
<gl-form-textarea
|
|
263
|
+
v-model="customFeedback"
|
|
264
|
+
:state="isTextareaValid"
|
|
265
|
+
:placeholder="$options.i18n.FEEDBACK_PLACEHOLDER"
|
|
266
|
+
:rows="3"
|
|
267
|
+
:max-rows="5"
|
|
268
|
+
data-testid="custom-feedback-textarea"
|
|
269
|
+
/>
|
|
270
|
+
<div class="gl-flex gl-items-center gl-justify-between">
|
|
271
|
+
<gl-button
|
|
272
|
+
variant="confirm"
|
|
273
|
+
size="small"
|
|
274
|
+
type="submit"
|
|
275
|
+
data-testid="submit-custom-feedback-button"
|
|
276
|
+
>
|
|
277
|
+
{{ $options.i18n.SUBMIT }}
|
|
278
|
+
</gl-button>
|
|
279
|
+
<span
|
|
280
|
+
:class="isOverCharacterLimit ? 'gl-text-danger' : 'gl-text-subtle'"
|
|
281
|
+
class="gl-text-sm"
|
|
282
|
+
data-testid="character-count"
|
|
283
|
+
>
|
|
284
|
+
{{ characterCountText }}
|
|
285
|
+
</span>
|
|
286
|
+
</div>
|
|
287
|
+
</gl-form>
|
|
288
|
+
</div>
|
|
289
|
+
</div>
|
|
290
|
+
</template>
|
|
291
|
+
|
|
73
292
|
<div v-else class="gl-relative gl-flex gl-items-center gl-gap-2" data-testid="feedback-given">
|
|
74
293
|
<div class="feedback-colored-icon" data-testid="feedback-colored-icon">
|
|
75
294
|
<gl-icon
|
|
@@ -346,7 +346,7 @@ export default {
|
|
|
346
346
|
<template>
|
|
347
347
|
<div
|
|
348
348
|
ref="content-wrapper"
|
|
349
|
-
class="duo-chat-message-container gl-group gl-flex gl-flex-col gl-gap-4 gl-text-base gl-break-anywhere"
|
|
349
|
+
class="duo-chat-message-container gl-group gl-relative gl-flex gl-flex-col gl-gap-4 gl-text-base gl-break-anywhere"
|
|
350
350
|
:class="{
|
|
351
351
|
'gl-pr-7': isAssistantMessage,
|
|
352
352
|
'gl-justify-end gl-pl-7': isUserMessage,
|
package/translations.js
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
/* eslint-disable import/no-default-export */
|
|
2
2
|
export default {
|
|
3
|
+
'AgenticBinaryFeedback.accurateInfo': 'Accurate information',
|
|
4
|
+
'AgenticBinaryFeedback.back': 'Back',
|
|
5
|
+
'AgenticBinaryFeedback.close': 'Close',
|
|
6
|
+
'AgenticBinaryFeedback.goodExamples': 'Good examples',
|
|
7
|
+
'AgenticBinaryFeedback.missingSteps': 'Missing steps',
|
|
8
|
+
'AgenticBinaryFeedback.outdatedIncorrect': 'Outdated/incorrect',
|
|
9
|
+
'AgenticBinaryFeedback.placeholder': 'Share your feedback...',
|
|
10
|
+
'AgenticBinaryFeedback.savedTime': 'Saved me time',
|
|
11
|
+
'AgenticBinaryFeedback.solvedProblem': 'Solved my problem',
|
|
12
|
+
'AgenticBinaryFeedback.submit': 'Submit',
|
|
13
|
+
'AgenticBinaryFeedback.tellUsMore': 'Tell us more',
|
|
3
14
|
'AgenticBinaryFeedback.thanks': 'Thanks for the feedback!',
|
|
4
15
|
'AgenticBinaryFeedback.thumbsDown': 'Not helpful',
|
|
16
|
+
'AgenticBinaryFeedback.thumbsDownHeader': 'What would have been more helpful?',
|
|
5
17
|
'AgenticBinaryFeedback.thumbsUp': 'Helpful',
|
|
18
|
+
'AgenticBinaryFeedback.thumbsUpHeader': 'What made this helpful?',
|
|
19
|
+
'AgenticBinaryFeedback.tooGeneric': 'Too generic',
|
|
20
|
+
'AgenticBinaryFeedback.wrongContext': 'Wrong context',
|
|
6
21
|
'AgenticDuoChat.chatCancelLabel': 'Cancel',
|
|
7
22
|
'AgenticDuoChat.chatDefaultPredefinedPromptsChangePassword':
|
|
8
23
|
'How do I change my password in GitLab?',
|