@gitlab/ui 79.1.0 → 79.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/CHANGELOG.md +19 -0
- package/dist/components/base/form/form_textarea/form_textarea.js +6 -3
- package/dist/components/base/new_dropdowns/base_dropdown/base_dropdown.js +9 -6
- package/dist/components/base/new_dropdowns/constants.js +2 -2
- package/dist/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.js +17 -8
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/tokens/css/tokens.css +1 -1
- package/dist/tokens/css/tokens.dark.css +1 -1
- package/dist/tokens/js/tokens.dark.js +1 -1
- package/dist/tokens/js/tokens.js +1 -1
- package/dist/tokens/scss/_tokens.dark.scss +1 -1
- package/dist/tokens/scss/_tokens.scss +1 -1
- package/dist/utils/utils.js +19 -1
- package/package.json +1 -1
- package/src/components/base/form/form_textarea/form_textarea.spec.js +37 -0
- package/src/components/base/form/form_textarea/form_textarea.vue +6 -3
- package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.spec.js +31 -26
- package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.vue +16 -6
- package/src/components/base/new_dropdowns/constants.js +1 -1
- package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.scss +15 -1
- package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.spec.js +51 -45
- package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.stories.js +8 -0
- package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.vue +52 -28
- package/src/utils/utils.js +18 -0
- package/src/utils/utils.spec.js +52 -0
package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.vue
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
import GlIcon from '../../../../../base/icon/icon.vue';
|
|
3
|
+
import { GlTooltipDirective } from '../../../../../../directives/tooltip';
|
|
2
4
|
import GlDuoUserFeedback from '../../../user_feedback/user_feedback.vue';
|
|
3
5
|
import GlFormGroup from '../../../../../base/form/form_group/form_group.vue';
|
|
4
6
|
import GlFormTextarea from '../../../../../base/form/form_textarea/form_textarea.vue';
|
|
@@ -19,11 +21,13 @@ export const i18n = {
|
|
|
19
21
|
INTERACTION: 'The situation in which you interacted with GitLab Duo Chat.',
|
|
20
22
|
IMPROVE_WHAT: 'How could the response be improved?',
|
|
21
23
|
BETTER_RESPONSE: 'How the response might better meet your needs.',
|
|
24
|
+
MESSAGE_ERROR: 'Error sending the message',
|
|
22
25
|
},
|
|
23
26
|
};
|
|
24
27
|
|
|
25
28
|
export default {
|
|
26
29
|
name: 'GlDuoChatMessage',
|
|
30
|
+
i18n,
|
|
27
31
|
safeHtmlConfigExtension: {
|
|
28
32
|
ADD_TAGS: ['copy-code'],
|
|
29
33
|
},
|
|
@@ -32,9 +36,11 @@ export default {
|
|
|
32
36
|
GlDuoUserFeedback,
|
|
33
37
|
GlFormGroup,
|
|
34
38
|
GlFormTextarea,
|
|
39
|
+
GlIcon,
|
|
35
40
|
},
|
|
36
41
|
directives: {
|
|
37
42
|
SafeHtml,
|
|
43
|
+
GlTooltip: GlTooltipDirective,
|
|
38
44
|
},
|
|
39
45
|
provide() {
|
|
40
46
|
return {
|
|
@@ -92,9 +98,6 @@ export default {
|
|
|
92
98
|
return this.message.extras?.hasFeedback;
|
|
93
99
|
},
|
|
94
100
|
defaultContent() {
|
|
95
|
-
if (this.message.errors.length > 0)
|
|
96
|
-
return this.renderMarkdown(this.message.errors.join('; '));
|
|
97
|
-
|
|
98
101
|
if (this.message.contentHtml) {
|
|
99
102
|
return this.message.contentHtml;
|
|
100
103
|
}
|
|
@@ -105,8 +108,13 @@ export default {
|
|
|
105
108
|
if (this.isAssistantMessage && this.isChunk) {
|
|
106
109
|
return this.renderMarkdown(concatUntilEmpty(this.messageChunks));
|
|
107
110
|
}
|
|
111
|
+
|
|
108
112
|
return this.defaultContent || this.renderMarkdown(concatUntilEmpty(this.message.chunks));
|
|
109
113
|
},
|
|
114
|
+
|
|
115
|
+
error() {
|
|
116
|
+
return Boolean(this.message?.errors?.length) && this.message.errors.join('; ');
|
|
117
|
+
},
|
|
110
118
|
},
|
|
111
119
|
beforeCreate() {
|
|
112
120
|
if (!customElements.get('copy-code')) {
|
|
@@ -142,7 +150,7 @@ export default {
|
|
|
142
150
|
}
|
|
143
151
|
},
|
|
144
152
|
hydrateContentWithGFM() {
|
|
145
|
-
if (!this.isChunk) {
|
|
153
|
+
if (!this.isChunk && this.$refs.content) {
|
|
146
154
|
this.$nextTick(this.renderGFM(this.$refs.content));
|
|
147
155
|
}
|
|
148
156
|
},
|
|
@@ -161,7 +169,6 @@ export default {
|
|
|
161
169
|
}
|
|
162
170
|
},
|
|
163
171
|
},
|
|
164
|
-
i18n,
|
|
165
172
|
};
|
|
166
173
|
</script>
|
|
167
174
|
<template>
|
|
@@ -171,33 +178,50 @@ export default {
|
|
|
171
178
|
'gl-ml-auto gl-bg-blue-100 gl-text-blue-900 gl-rounded-bottom-right-none': isUserMessage,
|
|
172
179
|
'gl-rounded-bottom-left-none gl-text-gray-900 gl-bg-white gl-border-1 gl-border-solid gl-border-gray-50':
|
|
173
180
|
isAssistantMessage,
|
|
181
|
+
'gl-bg-red-50 gl-border-none!': error,
|
|
174
182
|
}"
|
|
175
183
|
>
|
|
176
|
-
<
|
|
184
|
+
<gl-icon
|
|
185
|
+
v-if="error"
|
|
186
|
+
:aria-label="$options.i18n.MESSAGE_ERROR"
|
|
187
|
+
name="status_warning_borderless"
|
|
188
|
+
:size="16"
|
|
189
|
+
class="gl-text-red-600 gl-border gl-border-red-500 gl-rounded-full gl-mr-3 gl-flex-shrink-0 error-icon"
|
|
190
|
+
data-testid="error"
|
|
191
|
+
/>
|
|
192
|
+
<div ref="content-wrapper" :class="{ 'has-error': error }">
|
|
193
|
+
<div v-if="error" ref="error-message" class="error-message">{{ error }}</div>
|
|
194
|
+
<div v-else>
|
|
195
|
+
<div ref="content" v-safe-html:[$options.safeHtmlConfigExtension]="messageContent"></div>
|
|
177
196
|
|
|
178
|
-
|
|
179
|
-
|
|
197
|
+
<template v-if="isAssistantMessage">
|
|
198
|
+
<documentation-sources v-if="sources" :sources="sources" />
|
|
180
199
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
+
<div class="gl-display-flex gl-align-items-flex-end gl-mt-4 duo-chat-message-feedback">
|
|
201
|
+
<gl-duo-user-feedback
|
|
202
|
+
:feedback-received="hasFeedback"
|
|
203
|
+
:modal-title="$options.i18n.MODAL.TITLE"
|
|
204
|
+
:modal-alert="$options.i18n.MODAL.ALERT_TEXT"
|
|
205
|
+
@feedback="logEvent"
|
|
206
|
+
>
|
|
207
|
+
<template #feedback-extra-fields>
|
|
208
|
+
<gl-form-group :label="$options.i18n.MODAL.DID_WHAT" optional>
|
|
209
|
+
<gl-form-textarea
|
|
210
|
+
v-model="didWhat"
|
|
211
|
+
:placeholder="$options.i18n.MODAL.INTERACTION"
|
|
212
|
+
/>
|
|
213
|
+
</gl-form-group>
|
|
214
|
+
<gl-form-group :label="$options.i18n.MODAL.IMPROVE_WHAT" optional>
|
|
215
|
+
<gl-form-textarea
|
|
216
|
+
v-model="improveWhat"
|
|
217
|
+
:placeholder="$options.i18n.MODAL.BETTER_RESPONSE"
|
|
218
|
+
/>
|
|
219
|
+
</gl-form-group>
|
|
220
|
+
</template>
|
|
221
|
+
</gl-duo-user-feedback>
|
|
222
|
+
</div>
|
|
223
|
+
</template>
|
|
200
224
|
</div>
|
|
201
|
-
</
|
|
225
|
+
</div>
|
|
202
226
|
</div>
|
|
203
227
|
</template>
|
package/src/utils/utils.js
CHANGED
|
@@ -204,3 +204,21 @@ export function stopEvent(
|
|
|
204
204
|
export function filterVisible(els) {
|
|
205
205
|
return (els || []).filter((el) => isVisible(el));
|
|
206
206
|
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Given an element, returns a Rect object
|
|
210
|
+
* with top and bottom boundaries removed.
|
|
211
|
+
*/
|
|
212
|
+
export function getHorizontalBoundingClientRect(el) {
|
|
213
|
+
const rect = el?.getBoundingClientRect();
|
|
214
|
+
|
|
215
|
+
if (rect) {
|
|
216
|
+
return {
|
|
217
|
+
x: rect.x,
|
|
218
|
+
width: rect.width,
|
|
219
|
+
y: 0, // top of the document
|
|
220
|
+
height: document.documentElement.clientHeight, // bottom of the document
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
return null;
|
|
224
|
+
}
|
package/src/utils/utils.spec.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
isElementTabbable,
|
|
4
4
|
focusFirstFocusableElement,
|
|
5
5
|
stopEvent,
|
|
6
|
+
getHorizontalBoundingClientRect,
|
|
6
7
|
} from './utils';
|
|
7
8
|
|
|
8
9
|
describe('isElementFocusable', () => {
|
|
@@ -153,4 +154,55 @@ describe('stopEvent', () => {
|
|
|
153
154
|
expect(event.stopPropagation).not.toHaveBeenCalled();
|
|
154
155
|
expect(event.stopImmediatePropagation).toHaveBeenCalledTimes(1);
|
|
155
156
|
});
|
|
157
|
+
|
|
158
|
+
describe('getHorizontalBoundingClientRect', () => {
|
|
159
|
+
describe('when there is a reference element', () => {
|
|
160
|
+
let mainElement;
|
|
161
|
+
|
|
162
|
+
const [
|
|
163
|
+
MAIN_LEFT_BOUNDARY,
|
|
164
|
+
MAIN_WIDTH,
|
|
165
|
+
MAIN_TOP_BOUNDARY,
|
|
166
|
+
MAIN_HEIGHT,
|
|
167
|
+
DOCUMENT_TOP_BOUNDARY,
|
|
168
|
+
DOCUMENT_HEIGHT,
|
|
169
|
+
] = [10, 20, 30, 40, 0, 50];
|
|
170
|
+
|
|
171
|
+
beforeEach(() => {
|
|
172
|
+
mainElement = document.createElement('main');
|
|
173
|
+
jest.spyOn(mainElement, 'getBoundingClientRect').mockImplementation(() => {
|
|
174
|
+
return {
|
|
175
|
+
x: MAIN_LEFT_BOUNDARY,
|
|
176
|
+
width: MAIN_WIDTH,
|
|
177
|
+
y: MAIN_TOP_BOUNDARY,
|
|
178
|
+
height: MAIN_HEIGHT,
|
|
179
|
+
};
|
|
180
|
+
});
|
|
181
|
+
Object.defineProperty(document.documentElement, 'clientHeight', {
|
|
182
|
+
get() {
|
|
183
|
+
return DOCUMENT_HEIGHT;
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
afterEach(() => {
|
|
189
|
+
mainElement = null;
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("returns the element's horizontal boundaries and the document's vertical boundaries", () => {
|
|
193
|
+
expect(getHorizontalBoundingClientRect(mainElement)).toEqual({
|
|
194
|
+
x: MAIN_LEFT_BOUNDARY,
|
|
195
|
+
width: MAIN_WIDTH,
|
|
196
|
+
y: DOCUMENT_TOP_BOUNDARY,
|
|
197
|
+
height: DOCUMENT_HEIGHT,
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
describe('when there is no reference element', () => {
|
|
203
|
+
it('returns `null`', () => {
|
|
204
|
+
expect(getHorizontalBoundingClientRect(null)).toEqual(null);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
});
|
|
156
208
|
});
|