@gitlab/ui 66.25.1 → 66.26.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 +7 -0
- package/dist/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.js +128 -0
- package/dist/components/experimental/duo/chat/mock_data.js +41 -3
- 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/package.json +15 -15
- package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.md +60 -0
- package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.scss +18 -0
- package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.spec.js +381 -0
- package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.stories.js +45 -0
- package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.vue +107 -0
- package/src/components/experimental/duo/chat/mock_data.js +45 -2
- package/src/scss/components.scss +1 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { GlDuoUserFeedback } from '../../../../../../index';
|
|
3
|
+
import { SafeHtmlDirective as SafeHtml } from '../../../../../../directives/safe_html/safe_html';
|
|
4
|
+
import { MESSAGE_MODEL_ROLES } from '../../constants';
|
|
5
|
+
import DocumentationSources from '../duo_chat_message_sources/duo_chat_message_sources.vue';
|
|
6
|
+
|
|
7
|
+
const concatIndicesUntilEmpty = (arr) => {
|
|
8
|
+
const start = arr.findIndex((el) => el);
|
|
9
|
+
if (start === -1 || start !== 1) return ''; // If there are no non-empty elements
|
|
10
|
+
|
|
11
|
+
const end = arr.slice(start).findIndex((el) => !el);
|
|
12
|
+
return end > 0 ? arr.slice(start, end).join('') : arr.slice(start).join('');
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
name: 'GlDuoChatMessage',
|
|
17
|
+
components: {
|
|
18
|
+
DocumentationSources,
|
|
19
|
+
GlDuoUserFeedback,
|
|
20
|
+
},
|
|
21
|
+
directives: {
|
|
22
|
+
SafeHtml,
|
|
23
|
+
},
|
|
24
|
+
inject: ['renderGFM', 'renderMarkdown'],
|
|
25
|
+
props: {
|
|
26
|
+
/**
|
|
27
|
+
* A message object
|
|
28
|
+
*/
|
|
29
|
+
message: {
|
|
30
|
+
type: Object,
|
|
31
|
+
required: true,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
data() {
|
|
35
|
+
return {
|
|
36
|
+
messageContent: '',
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
computed: {
|
|
40
|
+
isAssistantMessage() {
|
|
41
|
+
return this.message.role.toLowerCase() === MESSAGE_MODEL_ROLES.assistant;
|
|
42
|
+
},
|
|
43
|
+
isUserMessage() {
|
|
44
|
+
return this.message.role.toLowerCase() === MESSAGE_MODEL_ROLES.user;
|
|
45
|
+
},
|
|
46
|
+
sources() {
|
|
47
|
+
return this.message.extras?.sources;
|
|
48
|
+
},
|
|
49
|
+
content() {
|
|
50
|
+
return (
|
|
51
|
+
this.message.contentHtml ||
|
|
52
|
+
this.renderMarkdown(this.message.content || this.message.errors.join('; '))
|
|
53
|
+
);
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
watch: {
|
|
57
|
+
message: {
|
|
58
|
+
handler() {
|
|
59
|
+
const { chunkId, content } = this.message;
|
|
60
|
+
if (!chunkId) {
|
|
61
|
+
this.messageChunks = [];
|
|
62
|
+
this.messageContent = this.content;
|
|
63
|
+
this.renderGFM(this.$refs.content);
|
|
64
|
+
} else {
|
|
65
|
+
this.messageChunks[chunkId] = content;
|
|
66
|
+
this.messageContent = this.renderMarkdown(concatIndicesUntilEmpty(this.messageChunks));
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
deep: true,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
beforeCreate() {
|
|
73
|
+
/**
|
|
74
|
+
* Keeps cache of previous chunks used for rerendering the AI response when streaming.
|
|
75
|
+
* Is intentionally non-reactive
|
|
76
|
+
*/
|
|
77
|
+
this.messageChunks = [];
|
|
78
|
+
},
|
|
79
|
+
mounted() {
|
|
80
|
+
this.messageContent = this.content;
|
|
81
|
+
if (this.message.chunkId) {
|
|
82
|
+
this.messageChunks[this.message.chunkId] = this.message.content;
|
|
83
|
+
}
|
|
84
|
+
this.renderGFM(this.$refs.content);
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
</script>
|
|
88
|
+
<template>
|
|
89
|
+
<div
|
|
90
|
+
class="gl-p-4 gl-mb-4 gl-rounded-lg gl-line-height-20 gl-word-break-word duo-chat-message"
|
|
91
|
+
:class="{
|
|
92
|
+
'gl-ml-auto gl-bg-blue-100 gl-text-blue-900 gl-rounded-bottom-right-none': isUserMessage,
|
|
93
|
+
'gl-rounded-bottom-left-none gl-text-gray-900 gl-bg-white gl-border-1 gl-border-solid gl-border-gray-50':
|
|
94
|
+
isAssistantMessage,
|
|
95
|
+
}"
|
|
96
|
+
>
|
|
97
|
+
<div ref="content" v-safe-html="messageContent"></div>
|
|
98
|
+
|
|
99
|
+
<template v-if="isAssistantMessage">
|
|
100
|
+
<documentation-sources v-if="sources" :sources="sources" />
|
|
101
|
+
|
|
102
|
+
<div class="gl-display-flex gl-align-items-flex-end gl-mt-4">
|
|
103
|
+
<gl-duo-user-feedback @feedback="$emit('track-feedback', $event)" />
|
|
104
|
+
</div>
|
|
105
|
+
</template>
|
|
106
|
+
</div>
|
|
107
|
+
</template>
|
|
@@ -22,8 +22,10 @@ const MOCK_SOURCES = [
|
|
|
22
22
|
|
|
23
23
|
export const MOCK_RESPONSE_MESSAGE = {
|
|
24
24
|
id: '123',
|
|
25
|
-
content:
|
|
26
|
-
|
|
25
|
+
content:
|
|
26
|
+
'To create a new template:\n\n1. Create a new Markdown (`.md`) file inside the `.gitlab/issue_templates/` or `.gitlab/merge_request_templates/` directory in your repository.\n2. Commit the template file to your default branch.\n\nTo check if this has worked correctly, create a new issue or merge request and see if you can find your template in the **Choose a template** dropdown list.',
|
|
27
|
+
contentHtml:
|
|
28
|
+
'\u003cp data-sourcepos="1:1-1:25" dir="auto"\u003eTo create a new template:\u003c/p\u003e\n\u003col data-sourcepos="3:1-5:0" dir="auto"\u003e\n\u003cli data-sourcepos="3:1-3:143"\u003eCreate a new Markdown (\u003ccode\u003e.md\u003c/code\u003e) file inside the \u003ccode\u003e.gitlab/issue_templates/\u003c/code\u003e or \u003ccode\u003e.gitlab/merge_request_templates/\u003c/code\u003e directory in your repository.\u003c/li\u003e\n\u003cli data-sourcepos="4:1-5:0"\u003eCommit the template file to your default branch.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp data-sourcepos="6:1-6:156" dir="auto"\u003eTo check if this has worked correctly, create a new issue or merge request and see if you can find your template in the \u003cstrong\u003eChoose a template\u003c/strong\u003e dropdown list.\u003c/p\u003e',
|
|
27
29
|
role: MESSAGE_MODEL_ROLES.assistant,
|
|
28
30
|
extras: {
|
|
29
31
|
sources: MOCK_SOURCES,
|
|
@@ -32,3 +34,44 @@ export const MOCK_RESPONSE_MESSAGE = {
|
|
|
32
34
|
errors: [],
|
|
33
35
|
timestamp: '2021-04-21T12:00:00.000Z',
|
|
34
36
|
};
|
|
37
|
+
|
|
38
|
+
export const MOCK_CHUNK_RESPONSE_MESSAGE = {
|
|
39
|
+
chunkId: 1,
|
|
40
|
+
content: 'chunk',
|
|
41
|
+
role: MESSAGE_MODEL_ROLES.assistant,
|
|
42
|
+
requestId: '987',
|
|
43
|
+
errors: [],
|
|
44
|
+
timestamp: '2021-04-21T12:00:00.000Z',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const MOCK_RESPONSE_MESSAGE_FOR_STREAMING = {
|
|
48
|
+
id: '123',
|
|
49
|
+
content: `To change your password in GitLab:
|
|
50
|
+
|
|
51
|
+
Log in to your GitLab account.
|
|
52
|
+
Select your avatar in the top right corner and choose Edit profile.
|
|
53
|
+
On the left sidebar, select Password.
|
|
54
|
+
Enter your current password in the Current password field.
|
|
55
|
+
Enter your new password in the New password and Password confirmation fields.
|
|
56
|
+
Select Save password.
|
|
57
|
+
If you don't know your current password, select the I forgot my password link to reset it.
|
|
58
|
+
|
|
59
|
+
GitLab enforces password requirements when you choose a new password.`,
|
|
60
|
+
contentHtml: '',
|
|
61
|
+
role: 'assistant',
|
|
62
|
+
extras: {},
|
|
63
|
+
requestId: '987',
|
|
64
|
+
errors: [],
|
|
65
|
+
timestamp: '2021-04-21T12:00:00.000Z',
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const MOCK_USER_PROMPT_MESSAGE = {
|
|
69
|
+
id: '456',
|
|
70
|
+
content: 'How to create a new template?',
|
|
71
|
+
contentHtml: '',
|
|
72
|
+
role: MESSAGE_MODEL_ROLES.user,
|
|
73
|
+
requestId: '987',
|
|
74
|
+
errors: [],
|
|
75
|
+
timestamp: '2021-04-21T12:00:00.000Z',
|
|
76
|
+
extras: null,
|
|
77
|
+
};
|
package/src/scss/components.scss
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// @import '../components/base/dropdown/dropdown'
|
|
4
4
|
//
|
|
5
5
|
// ADD COMPONENT IMPORTS - needed for yarn generate:component. Do not remove
|
|
6
|
+
@import '../components/experimental/duo/chat/components/duo_chat_message/duo_chat_message';
|
|
6
7
|
@import '../components/experimental/duo/chat/components/duo_chat_loader/duo_chat_loader';
|
|
7
8
|
@import '../components/base/new_dropdowns/disclosure/disclosure_dropdown';
|
|
8
9
|
@import '../components/base/keyset_pagination/keyset_pagination';
|