@gitlab/ui 95.0.0 → 95.1.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 +12 -0
- package/dist/components/experimental/duo/chat/components/duo_chat_context/constants.js +4 -1
- package/dist/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_details_modal/duo_chat_context_item_details_modal.js +120 -0
- package/dist/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu.js +11 -1
- package/dist/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_selections/duo_chat_context_item_selections.js +29 -2
- package/dist/components/experimental/duo/chat/components/duo_chat_context/mock_context_data.js +14 -1
- package/dist/components/experimental/duo/chat/components/duo_chat_conversation/duo_chat_conversation.js +4 -1
- package/dist/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.js +7 -1
- package/dist/components/experimental/duo/chat/duo_chat.js +9 -1
- package/package.json +1 -1
- package/src/components/experimental/duo/chat/components/duo_chat_context/constants.js +4 -0
- package/src/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_details_modal/duo_chat_context_item_details_modal.vue +114 -0
- package/src/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu.vue +10 -0
- package/src/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_selections/duo_chat_context_item_selections.vue +42 -0
- package/src/components/experimental/duo/chat/components/duo_chat_context/mock_context_data.js +15 -0
- package/src/components/experimental/duo/chat/components/duo_chat_conversation/duo_chat_conversation.vue +4 -0
- package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.vue +8 -0
- package/src/components/experimental/duo/chat/duo_chat.vue +9 -0
- package/translations.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# [95.1.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v95.0.0...v95.1.0) (2024-10-04)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* don't open details modal if selecting close button via keyboard ([8e8a4c3](https://gitlab.com/gitlab-org/gitlab-ui/commit/8e8a4c3dc7fc9f30d4c02a3a9a4acf7da96c2aac))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **GlDuoChat:** view context item content/details ([63909dd](https://gitlab.com/gitlab-org/gitlab-ui/commit/63909dd79aa2570ecd7375c22619d892ea1935c2))
|
|
12
|
+
|
|
1
13
|
# [95.0.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v94.10.0...v95.0.0) (2024-10-04)
|
|
2
14
|
|
|
3
15
|
|
|
@@ -4,5 +4,8 @@ const CONTEXT_ITEM_CATEGORY_FILE = 'file';
|
|
|
4
4
|
const CONTEXT_ITEM_CATEGORY_LOCAL_GIT = 'local_git';
|
|
5
5
|
const CONTEXT_ITEM_LOCAL_GIT_COMMIT = 'commit';
|
|
6
6
|
const CONTEXT_ITEM_LOCAL_GIT_DIFF = 'diff';
|
|
7
|
+
const LANGUAGE_IDENTIFIER_PREFIX = 'language-';
|
|
8
|
+
const LANGUAGE_IDENTIFIER_DIFF = 'language-diff';
|
|
9
|
+
const LANGUAGE_IDENTIFIER_PLAINTEXT = 'language-plaintext';
|
|
7
10
|
|
|
8
|
-
export { CONTEXT_ITEM_CATEGORY_FILE, CONTEXT_ITEM_CATEGORY_ISSUE, CONTEXT_ITEM_CATEGORY_LOCAL_GIT, CONTEXT_ITEM_CATEGORY_MERGE_REQUEST, CONTEXT_ITEM_LOCAL_GIT_COMMIT, CONTEXT_ITEM_LOCAL_GIT_DIFF };
|
|
11
|
+
export { CONTEXT_ITEM_CATEGORY_FILE, CONTEXT_ITEM_CATEGORY_ISSUE, CONTEXT_ITEM_CATEGORY_LOCAL_GIT, CONTEXT_ITEM_CATEGORY_MERGE_REQUEST, CONTEXT_ITEM_LOCAL_GIT_COMMIT, CONTEXT_ITEM_LOCAL_GIT_DIFF, LANGUAGE_IDENTIFIER_DIFF, LANGUAGE_IDENTIFIER_PLAINTEXT, LANGUAGE_IDENTIFIER_PREFIX };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { nextTick } from 'vue';
|
|
2
|
+
import { contextItemValidator } from '../utils';
|
|
3
|
+
import GlModal from '../../../../../../base/modal/modal';
|
|
4
|
+
import { SafeHtmlDirective } from '../../../../../../../directives/safe_html/safe_html';
|
|
5
|
+
import GlSkeletonLoader from '../../../../../../base/skeleton_loader/skeleton_loader';
|
|
6
|
+
import { translate } from '../../../../../../../utils/i18n';
|
|
7
|
+
import { CONTEXT_ITEM_CATEGORY_LOCAL_GIT, LANGUAGE_IDENTIFIER_DIFF, LANGUAGE_IDENTIFIER_PREFIX, LANGUAGE_IDENTIFIER_PLAINTEXT } from '../constants';
|
|
8
|
+
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
9
|
+
|
|
10
|
+
var script = {
|
|
11
|
+
name: 'GlDuoChatContextItemDetailsModal',
|
|
12
|
+
components: {
|
|
13
|
+
GlSkeletonLoader,
|
|
14
|
+
GlModal
|
|
15
|
+
},
|
|
16
|
+
directives: {
|
|
17
|
+
SafeHtml: SafeHtmlDirective
|
|
18
|
+
},
|
|
19
|
+
inject: {
|
|
20
|
+
renderGFM: {
|
|
21
|
+
from: 'renderGFM',
|
|
22
|
+
default: () => element => {
|
|
23
|
+
element.classList.add('gl-markdown', 'gl-compact-markdown');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
props: {
|
|
28
|
+
/**
|
|
29
|
+
* Context items to preview. If it has no `content`, the loading state will be displayed.
|
|
30
|
+
*/
|
|
31
|
+
contextItem: {
|
|
32
|
+
type: Object,
|
|
33
|
+
required: true,
|
|
34
|
+
validator: contextItemValidator
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
computed: {
|
|
38
|
+
isLoadingContent() {
|
|
39
|
+
return this.contextItem.content === undefined;
|
|
40
|
+
},
|
|
41
|
+
languageIdentifierClass() {
|
|
42
|
+
var _this$contextItem$met, _this$contextItem$met2, _this$contextItem$met3;
|
|
43
|
+
if (this.contextItem.category === CONTEXT_ITEM_CATEGORY_LOCAL_GIT) {
|
|
44
|
+
return LANGUAGE_IDENTIFIER_DIFF;
|
|
45
|
+
}
|
|
46
|
+
const fileExtension = (_this$contextItem$met = this.contextItem.metadata) === null || _this$contextItem$met === void 0 ? void 0 : (_this$contextItem$met2 = _this$contextItem$met.relativePath) === null || _this$contextItem$met2 === void 0 ? void 0 : _this$contextItem$met2.split('.').at(-1);
|
|
47
|
+
if (fileExtension && fileExtension !== ((_this$contextItem$met3 = this.contextItem.metadata) === null || _this$contextItem$met3 === void 0 ? void 0 : _this$contextItem$met3.relativePath)) {
|
|
48
|
+
return `${LANGUAGE_IDENTIFIER_PREFIX}${fileExtension}`;
|
|
49
|
+
}
|
|
50
|
+
return LANGUAGE_IDENTIFIER_PLAINTEXT;
|
|
51
|
+
},
|
|
52
|
+
title() {
|
|
53
|
+
var _this$contextItem$met4, _this$contextItem$met5;
|
|
54
|
+
return ((_this$contextItem$met4 = this.contextItem.metadata) === null || _this$contextItem$met4 === void 0 ? void 0 : _this$contextItem$met4.title) || ((_this$contextItem$met5 = this.contextItem.metadata) === null || _this$contextItem$met5 === void 0 ? void 0 : _this$contextItem$met5.relativePath) || translate('GlDuoChatContextItemDetailsModal.title', 'Preview');
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
watch: {
|
|
58
|
+
contextItem: {
|
|
59
|
+
async handler(newVal, oldVal) {
|
|
60
|
+
const shouldFormat = (newVal === null || newVal === void 0 ? void 0 : newVal.content) !== (oldVal === null || oldVal === void 0 ? void 0 : oldVal.content) && (newVal === null || newVal === void 0 ? void 0 : newVal.content);
|
|
61
|
+
if (shouldFormat) {
|
|
62
|
+
await nextTick();
|
|
63
|
+
await this.hydrateContentWithGFM();
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
immediate: true
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
methods: {
|
|
70
|
+
async hydrateContentWithGFM() {
|
|
71
|
+
await nextTick();
|
|
72
|
+
if (this.$refs.content) {
|
|
73
|
+
this.renderGFM(this.$refs.content);
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
onModalVisibilityChange(isVisible) {
|
|
77
|
+
if (!isVisible) {
|
|
78
|
+
this.$emit('close');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/* script */
|
|
85
|
+
const __vue_script__ = script;
|
|
86
|
+
|
|
87
|
+
/* template */
|
|
88
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-modal',{attrs:{"modal-id":"context-item-details-modal","title":_vm.title,"visible":true,"scrollable":true,"hide-footer":"","size":"lg"},on:{"change":_vm.onModalVisibilityChange}},[(_vm.isLoadingContent)?_c('gl-skeleton-loader'):_c('div',{ref:"content",attrs:{"data-testid":"context-item-content"}},[_c('pre',{directives:[{name:"safe-html",rawName:"v-safe-html",value:(_vm.contextItem.content),expression:"contextItem.content"}],staticClass:"code js-syntax-highlight gl-p-3",class:_vm.languageIdentifierClass})])],1)};
|
|
89
|
+
var __vue_staticRenderFns__ = [];
|
|
90
|
+
|
|
91
|
+
/* style */
|
|
92
|
+
const __vue_inject_styles__ = undefined;
|
|
93
|
+
/* scoped */
|
|
94
|
+
const __vue_scope_id__ = undefined;
|
|
95
|
+
/* module identifier */
|
|
96
|
+
const __vue_module_identifier__ = undefined;
|
|
97
|
+
/* functional template */
|
|
98
|
+
const __vue_is_functional_template__ = false;
|
|
99
|
+
/* style inject */
|
|
100
|
+
|
|
101
|
+
/* style inject SSR */
|
|
102
|
+
|
|
103
|
+
/* style inject shadow dom */
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
const __vue_component__ = __vue_normalize__(
|
|
108
|
+
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
|
|
109
|
+
__vue_inject_styles__,
|
|
110
|
+
__vue_script__,
|
|
111
|
+
__vue_scope_id__,
|
|
112
|
+
__vue_is_functional_template__,
|
|
113
|
+
__vue_module_identifier__,
|
|
114
|
+
false,
|
|
115
|
+
undefined,
|
|
116
|
+
undefined,
|
|
117
|
+
undefined
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
export default __vue_component__;
|
|
@@ -209,6 +209,16 @@ var script = {
|
|
|
209
209
|
}
|
|
210
210
|
} while (!this.results[newIndex].metadata.enabled);
|
|
211
211
|
this.activeIndex = newIndex;
|
|
212
|
+
},
|
|
213
|
+
onGetContextItemContent(contextItem) {
|
|
214
|
+
/**
|
|
215
|
+
* Emit get-context-item-content event that tells clients to load the full file content for a selected context item.
|
|
216
|
+
* The fully hydrated context item should be updated in the context item selections.
|
|
217
|
+
* @param {*} event An event containing the context item to hydrate
|
|
218
|
+
*/
|
|
219
|
+
this.$emit('get-context-item-content', {
|
|
220
|
+
contextItem
|
|
221
|
+
});
|
|
212
222
|
}
|
|
213
223
|
},
|
|
214
224
|
i18n: {
|
|
@@ -220,7 +230,7 @@ var script = {
|
|
|
220
230
|
const __vue_script__ = script;
|
|
221
231
|
|
|
222
232
|
/* template */
|
|
223
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[(_vm.selections.length)?_c('gl-duo-chat-context-item-selections',{staticClass:"gl-mb-3",attrs:{"selections":_vm.selections,"removable":true,"title":_vm.$options.i18n.selectedContextItemsTitle,"default-collapsed":false},on:{"remove":_vm.removeItem}}):_vm._e(),_vm._v(" "),(_vm.open)?_c('gl-card',{staticClass:"slash-commands !gl-absolute gl-bottom-0 gl-w-full gl-pl-0 gl-shadow-md",attrs:{"body-class":"!gl-p-2","data-testid":"context-item-menu"}},[(_vm.showCategorySelection)?_c('gl-duo-chat-context-item-menu-category-items',{attrs:{"active-index":_vm.activeIndex,"categories":_vm.categories},on:{"select":_vm.selectCategory,"active-index-change":function($event){_vm.activeIndex = $event;}}}):_c('gl-duo-chat-context-item-menu-search-items',{attrs:{"active-index":_vm.activeIndex,"category":_vm.selectedCategory,"loading":_vm.loading,"error":_vm.error,"results":_vm.results},on:{"select":_vm.selectItem,"keyup":_vm.handleKeyUp,"active-index-change":function($event){_vm.activeIndex = $event;}},model:{value:(_vm.searchQuery),callback:function ($$v) {_vm.searchQuery=$$v;},expression:"searchQuery"}})],1):_vm._e()],1)};
|
|
233
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[(_vm.selections.length)?_c('gl-duo-chat-context-item-selections',{staticClass:"gl-mb-3",attrs:{"selections":_vm.selections,"categories":_vm.categories,"removable":true,"title":_vm.$options.i18n.selectedContextItemsTitle,"default-collapsed":false},on:{"remove":_vm.removeItem,"get-content":_vm.onGetContextItemContent}}):_vm._e(),_vm._v(" "),(_vm.open)?_c('gl-card',{staticClass:"slash-commands !gl-absolute gl-bottom-0 gl-w-full gl-pl-0 gl-shadow-md",attrs:{"body-class":"!gl-p-2","data-testid":"context-item-menu"}},[(_vm.showCategorySelection)?_c('gl-duo-chat-context-item-menu-category-items',{attrs:{"active-index":_vm.activeIndex,"categories":_vm.categories},on:{"select":_vm.selectCategory,"active-index-change":function($event){_vm.activeIndex = $event;}}}):_c('gl-duo-chat-context-item-menu-search-items',{attrs:{"active-index":_vm.activeIndex,"category":_vm.selectedCategory,"loading":_vm.loading,"error":_vm.error,"results":_vm.results},on:{"select":_vm.selectItem,"keyup":_vm.handleKeyUp,"active-index-change":function($event){_vm.activeIndex = $event;}},model:{value:(_vm.searchQuery),callback:function ($$v) {_vm.searchQuery=$$v;},expression:"searchQuery"}})],1):_vm._e()],1)};
|
|
224
234
|
var __vue_staticRenderFns__ = [];
|
|
225
235
|
|
|
226
236
|
/* style */
|
|
@@ -3,6 +3,8 @@ import GlIcon from '../../../../../../base/icon/icon';
|
|
|
3
3
|
import GlToken from '../../../../../../base/token/token';
|
|
4
4
|
import GlTruncate from '../../../../../../utilities/truncate/truncate';
|
|
5
5
|
import GlDuoChatContextItemPopover from '../duo_chat_context_item_popover/duo_chat_context_item_popover';
|
|
6
|
+
import { CONTEXT_ITEM_CATEGORY_LOCAL_GIT, CONTEXT_ITEM_CATEGORY_FILE } from '../constants';
|
|
7
|
+
import GlDuoChatContextItemDetailsModal from '../duo_chat_context_item_details_modal/duo_chat_context_item_details_modal';
|
|
6
8
|
import { contextItemsValidator, getContextItemIcon } from '../utils';
|
|
7
9
|
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
8
10
|
|
|
@@ -10,6 +12,7 @@ var script = {
|
|
|
10
12
|
name: 'GlDuoChatContextItemSelections',
|
|
11
13
|
components: {
|
|
12
14
|
GlTruncate,
|
|
15
|
+
GlDuoChatContextItemDetailsModal,
|
|
13
16
|
GlIcon,
|
|
14
17
|
GlDuoChatContextItemPopover,
|
|
15
18
|
GlToken
|
|
@@ -54,7 +57,8 @@ var script = {
|
|
|
54
57
|
data() {
|
|
55
58
|
return {
|
|
56
59
|
isCollapsed: this.defaultCollapsed,
|
|
57
|
-
selectionsId: uniqueId()
|
|
60
|
+
selectionsId: uniqueId(),
|
|
61
|
+
previewContextItemId: null
|
|
58
62
|
};
|
|
59
63
|
},
|
|
60
64
|
computed: {
|
|
@@ -72,6 +76,9 @@ var script = {
|
|
|
72
76
|
return 'gl-bg-blue-50 gl-text-blue-600';
|
|
73
77
|
}
|
|
74
78
|
return '';
|
|
79
|
+
},
|
|
80
|
+
contextItemPreview() {
|
|
81
|
+
return this.selections.find(item => item.id === this.previewContextItemId);
|
|
75
82
|
}
|
|
76
83
|
},
|
|
77
84
|
methods: {
|
|
@@ -85,6 +92,26 @@ var script = {
|
|
|
85
92
|
* @property {Object} item - The context contextItem to be removed
|
|
86
93
|
*/
|
|
87
94
|
this.$emit('remove', contextItem);
|
|
95
|
+
},
|
|
96
|
+
onOpenItem(event, contextItem) {
|
|
97
|
+
const isKeypressOnCloseButton = event.type === 'keydown' && event.target !== event.currentTarget;
|
|
98
|
+
if (isKeypressOnCloseButton) {
|
|
99
|
+
// don't respond to events triggered by the gl-token children (e.g. the close button)
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (!this.canOpen(contextItem)) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (!contextItem.content) {
|
|
106
|
+
this.$emit('get-content', contextItem);
|
|
107
|
+
}
|
|
108
|
+
this.previewContextItemId = contextItem.id;
|
|
109
|
+
},
|
|
110
|
+
canOpen(contextItem) {
|
|
111
|
+
return [CONTEXT_ITEM_CATEGORY_LOCAL_GIT, CONTEXT_ITEM_CATEGORY_FILE].includes(contextItem.category);
|
|
112
|
+
},
|
|
113
|
+
onClosePreview() {
|
|
114
|
+
this.previewContextItemId = null;
|
|
88
115
|
}
|
|
89
116
|
}
|
|
90
117
|
};
|
|
@@ -93,7 +120,7 @@ var script = {
|
|
|
93
120
|
const __vue_script__ = script;
|
|
94
121
|
|
|
95
122
|
/* template */
|
|
96
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-flex gl-flex-col",class:_vm.variantClasses},[_c('button',{staticClass:"gl-flex gl-w-full gl-items-center gl-border-0 gl-bg-transparent gl-p-0 gl-text-left gl-text-xs gl-lowercase gl-text-inherit",attrs:{"data-testid":"chat-context-selections-title","type":"button"},on:{"click":_vm.toggleCollapse}},[_c('gl-icon',{attrs:{"name":_vm.collapseIconName,"data-testid":"chat-context-collapse-icon"}}),_vm._v(" "+_vm._s(_vm.title)+"\n ")],1),_vm._v(" "),_c('div',{directives:[{name:"show",rawName:"v-show",value:(!_vm.isCollapsed),expression:"!isCollapsed"}],staticClass:"gl-mt-1 gl-flex gl-grow gl-flex-wrap",attrs:{"data-testid":"chat-context-tokens-wrapper"}},_vm._l((_vm.selections),function(item){return _c('gl-token',{key:item.id,staticClass:"gl-mb-2 gl-mr-2 gl-max-w-full",class:_vm.tokenVariantClasses,attrs:{"id":("context-item-" + (item.id) + "-" + _vm.selectionsId + "-token"),"view-only":!_vm.removable,"variant":"default"},on:{"close":function($event){return _vm.onRemoveItem(item)}}},[_c('div',{staticClass:"gl-flex gl-min-w-0 gl-items-center",attrs:{"id":("context-item-" + (item.id) + "-" + _vm.selectionsId)}},[(_vm.getContextItemIcon(item))?_c('gl-icon',{staticClass:"gl-mr-1",attrs:{"name":_vm.getContextItemIcon(item),"size":12}}):_vm._e(),_vm._v(" "),_c('gl-truncate',{attrs:{"text":item.metadata.title,"position":"middle"}})],1),_vm._v(" "),_c('gl-duo-chat-context-item-popover',{attrs:{"context-item":item,"target":("context-item-" + (item.id) + "-" + _vm.selectionsId + "-token"),"placement":"bottom"}})],1)}),1)])};
|
|
123
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-flex gl-flex-col",class:_vm.variantClasses},[_c('button',{staticClass:"gl-flex gl-w-full gl-items-center gl-border-0 gl-bg-transparent gl-p-0 gl-text-left gl-text-xs gl-lowercase gl-text-inherit",attrs:{"data-testid":"chat-context-selections-title","type":"button"},on:{"click":_vm.toggleCollapse}},[_c('gl-icon',{attrs:{"name":_vm.collapseIconName,"data-testid":"chat-context-collapse-icon"}}),_vm._v(" "+_vm._s(_vm.title)+"\n ")],1),_vm._v(" "),_c('div',{directives:[{name:"show",rawName:"v-show",value:(!_vm.isCollapsed),expression:"!isCollapsed"}],staticClass:"gl-mt-1 gl-flex gl-grow gl-flex-wrap",attrs:{"data-testid":"chat-context-tokens-wrapper"}},_vm._l((_vm.selections),function(item){return _c('gl-token',{key:item.id,staticClass:"gl-mb-2 gl-mr-2 gl-max-w-full",class:_vm.tokenVariantClasses,attrs:{"id":("context-item-" + (item.id) + "-" + _vm.selectionsId + "-token"),"view-only":!_vm.removable,"variant":"default","tabindex":_vm.canOpen(item) ? 0 : -1,"role":_vm.canOpen(item) ? 'button' : undefined},on:{"click":function($event){return _vm.onOpenItem($event, item)},"keydown":[function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"enter",13,$event.key,"Enter")){ return null; }return _vm.onOpenItem($event, item)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"space",32,$event.key,[" ","Spacebar"])){ return null; }$event.preventDefault();return _vm.onOpenItem($event, item)}],"close":function($event){return _vm.onRemoveItem(item)}}},[_c('div',{staticClass:"gl-flex gl-min-w-0 gl-items-center",attrs:{"id":("context-item-" + (item.id) + "-" + _vm.selectionsId)}},[(_vm.getContextItemIcon(item))?_c('gl-icon',{staticClass:"gl-mr-1",attrs:{"name":_vm.getContextItemIcon(item),"size":12}}):_vm._e(),_vm._v(" "),_c('gl-truncate',{attrs:{"text":item.metadata.title,"position":"middle"}})],1),_vm._v(" "),_c('gl-duo-chat-context-item-popover',{attrs:{"context-item":item,"target":("context-item-" + (item.id) + "-" + _vm.selectionsId + "-token"),"placement":"bottom"},on:{"show-git-diff":function($event){return _vm.onOpenItem(item)}}})],1)}),1),_vm._v(" "),(_vm.contextItemPreview)?_c('gl-duo-chat-context-item-details-modal',{attrs:{"context-item":_vm.contextItemPreview},on:{"close":_vm.onClosePreview}}):_vm._e()],1)};
|
|
97
124
|
var __vue_staticRenderFns__ = [];
|
|
98
125
|
|
|
99
126
|
/* style */
|
package/dist/components/experimental/duo/chat/components/duo_chat_context/mock_context_data.js
CHANGED
|
@@ -20,6 +20,19 @@ const MOCK_CATEGORIES = [{
|
|
|
20
20
|
function getMockCategory(categoryValue) {
|
|
21
21
|
return MOCK_CATEGORIES.find(cat => cat.value === categoryValue);
|
|
22
22
|
}
|
|
23
|
+
const MOCK_CONTEXT_FILE_CONTENT = `export function waterPlants() {
|
|
24
|
+
console.log('sprinkle');
|
|
25
|
+
}`;
|
|
26
|
+
const MOCK_CONTEXT_FILE_DIFF_CONTENT = `diff --git a/src/plants/strawberry.ts b/src/plants/strawberry.ts
|
|
27
|
+
index 1234567..8901234 100644
|
|
28
|
+
--- a/src/plants/strawberry.ts
|
|
29
|
+
+++ b/src/plants/strawberry.ts
|
|
30
|
+
@@ -1,4 +1,4 @@
|
|
31
|
+
export const strawberry = {
|
|
32
|
+
name: 'Strawberry',
|
|
33
|
+
- waterNeeds: 'moderate',
|
|
34
|
+
+ waterNeeds: 'high',
|
|
35
|
+
};`;
|
|
23
36
|
const MOCK_CONTEXT_ITEM_FILE = {
|
|
24
37
|
id: '123e4567-e89b-12d3-a456-426614174000',
|
|
25
38
|
category: CONTEXT_ITEM_CATEGORY_FILE,
|
|
@@ -175,4 +188,4 @@ const getMockContextItems = () => {
|
|
|
175
188
|
return [...enabledItems, ...disabledItems];
|
|
176
189
|
};
|
|
177
190
|
|
|
178
|
-
export { MOCK_CATEGORIES, MOCK_CONTEXT_ITEM_FILE, MOCK_CONTEXT_ITEM_FILE_DISABLED, MOCK_CONTEXT_ITEM_GIT_COMMIT, MOCK_CONTEXT_ITEM_GIT_DIFF, MOCK_CONTEXT_ITEM_ISSUE, MOCK_CONTEXT_ITEM_ISSUE_DISABLED, MOCK_CONTEXT_ITEM_MERGE_REQUEST, MOCK_CONTEXT_ITEM_MERGE_REQUEST_DISABLED, getMockCategory, getMockContextItems };
|
|
191
|
+
export { MOCK_CATEGORIES, MOCK_CONTEXT_FILE_CONTENT, MOCK_CONTEXT_FILE_DIFF_CONTENT, MOCK_CONTEXT_ITEM_FILE, MOCK_CONTEXT_ITEM_FILE_DISABLED, MOCK_CONTEXT_ITEM_GIT_COMMIT, MOCK_CONTEXT_ITEM_GIT_DIFF, MOCK_CONTEXT_ITEM_ISSUE, MOCK_CONTEXT_ITEM_ISSUE_DISABLED, MOCK_CONTEXT_ITEM_MERGE_REQUEST, MOCK_CONTEXT_ITEM_MERGE_REQUEST_DISABLED, getMockCategory, getMockContextItems };
|
|
@@ -54,6 +54,9 @@ var script = {
|
|
|
54
54
|
},
|
|
55
55
|
onInsertCodeSnippet(e) {
|
|
56
56
|
this.$emit('insert-code-snippet', e);
|
|
57
|
+
},
|
|
58
|
+
onGetContextItemContent(e) {
|
|
59
|
+
this.$emit('get-context-item-content', e);
|
|
57
60
|
}
|
|
58
61
|
},
|
|
59
62
|
i18n
|
|
@@ -63,7 +66,7 @@ var script = {
|
|
|
63
66
|
const __vue_script__ = script;
|
|
64
67
|
|
|
65
68
|
/* template */
|
|
66
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{class:['gl-flex gl-flex-col gl-justify-end', { 'insert-code-hidden': !_vm.enableCodeInsertion }]},[(_vm.showDelimiter)?_c('div',{staticClass:"gl-my-5 gl-flex gl-items-center gl-gap-4 gl-text-gray-500",attrs:{"data-testid":"conversation-delimiter"}},[_c('hr',{staticClass:"gl-grow"}),_vm._v(" "),_c('span',[_vm._v(_vm._s(_vm.$options.i18n.CONVERSATION_NEW_CHAT))]),_vm._v(" "),_c('hr',{staticClass:"gl-grow"})]):_vm._e(),_vm._v(" "),_vm._l((_vm.messages),function(msg,index){return _c('gl-duo-chat-message',{key:((msg.role) + "-" + index),attrs:{"message":msg,"is-cancelled":_vm.canceledRequestIds.includes(msg.requestId)},on:{"track-feedback":_vm.onTrackFeedback,"insert-code-snippet":_vm.onInsertCodeSnippet}})})],2)};
|
|
69
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{class:['gl-flex gl-flex-col gl-justify-end', { 'insert-code-hidden': !_vm.enableCodeInsertion }]},[(_vm.showDelimiter)?_c('div',{staticClass:"gl-my-5 gl-flex gl-items-center gl-gap-4 gl-text-gray-500",attrs:{"data-testid":"conversation-delimiter"}},[_c('hr',{staticClass:"gl-grow"}),_vm._v(" "),_c('span',[_vm._v(_vm._s(_vm.$options.i18n.CONVERSATION_NEW_CHAT))]),_vm._v(" "),_c('hr',{staticClass:"gl-grow"})]):_vm._e(),_vm._v(" "),_vm._l((_vm.messages),function(msg,index){return _c('gl-duo-chat-message',{key:((msg.role) + "-" + index),attrs:{"message":msg,"is-cancelled":_vm.canceledRequestIds.includes(msg.requestId)},on:{"track-feedback":_vm.onTrackFeedback,"insert-code-snippet":_vm.onInsertCodeSnippet,"get-context-item-content":_vm.onGetContextItemContent}})})],2)};
|
|
67
70
|
var __vue_staticRenderFns__ = [];
|
|
68
71
|
|
|
69
72
|
/* style */
|
package/dist/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.js
CHANGED
|
@@ -212,6 +212,12 @@ var script = {
|
|
|
212
212
|
},
|
|
213
213
|
onInsertCodeSnippet(e) {
|
|
214
214
|
this.$emit('insert-code-snippet', e);
|
|
215
|
+
},
|
|
216
|
+
onGetContextItemContent(contextItem) {
|
|
217
|
+
this.$emit('get-context-item-content', {
|
|
218
|
+
messageId: this.message.id,
|
|
219
|
+
contextItem
|
|
220
|
+
});
|
|
215
221
|
}
|
|
216
222
|
}
|
|
217
223
|
};
|
|
@@ -226,7 +232,7 @@ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=
|
|
|
226
232
|
_vm.isAssistantMessage,
|
|
227
233
|
'gl-bg-white': _vm.isAssistantMessage && !_vm.error,
|
|
228
234
|
'!gl-border-none gl-bg-red-50': _vm.error,
|
|
229
|
-
},on:{"insert-code-snippet":_vm.onInsertCodeSnippet}},[(_vm.error)?_c('gl-icon',{staticClass:"error-icon gl-border gl-mr-3 gl-shrink-0 gl-rounded-full gl-border-red-500 gl-text-red-600",attrs:{"aria-label":_vm.$options.i18n.MESSAGE_ERROR,"name":"status_warning_borderless","size":16,"data-testid":"error"}}):_vm._e(),_vm._v(" "),_c('div',{ref:"content-wrapper",class:{ 'has-error': _vm.error }},[(_vm.displaySelectedContextItems && _vm.isAssistantMessage)?_c('gl-duo-chat-context-item-selections',{attrs:{"selections":_vm.selectedContextItems,"title":_vm.selectedContextItemsTitle,"default-collapsed":_vm.selectedContextItemsDefaultCollapsed,"variant":"assistant"}}):_vm._e(),_vm._v(" "),(_vm.error)?_c('div',{directives:[{name:"safe-html",rawName:"v-safe-html:[$options.safeHtmlConfigExtension]",value:(_vm.renderedError),expression:"renderedError",arg:_vm.$options.safeHtmlConfigExtension}],ref:"error-message"}):_c('div',[_c('div',{directives:[{name:"safe-html",rawName:"v-safe-html:[$options.safeHtmlConfigExtension]",value:(_vm.messageContent),expression:"messageContent",arg:_vm.$options.safeHtmlConfigExtension}],ref:"content"}),_vm._v(" "),(_vm.isAssistantMessage)?[(_vm.sources)?_c('documentation-sources',{attrs:{"sources":_vm.sources}}):_vm._e(),_vm._v(" "),_c('div',{staticClass:"duo-chat-message-feedback gl-mt-4 gl-flex gl-items-end"},[(_vm.isChunkAndNotCancelled)?_c('gl-loading-icon',{staticClass:"gl-pt-4",attrs:{"variant":"dots","inline":""}}):_vm._e(),_vm._v(" "),(_vm.isNotChunkOrCancelled)?_c('gl-duo-user-feedback',{attrs:{"feedback-received":_vm.hasFeedback,"modal-title":_vm.$options.i18n.MODAL.TITLE,"modal-alert":_vm.$options.i18n.MODAL.ALERT_TEXT},on:{"feedback":_vm.logEvent},scopedSlots:_vm._u([{key:"feedback-extra-fields",fn:function(){return [_c('gl-form-group',{attrs:{"label":_vm.$options.i18n.MODAL.DID_WHAT,"optional":""}},[_c('gl-form-textarea',{attrs:{"placeholder":_vm.$options.i18n.MODAL.INTERACTION},model:{value:(_vm.didWhat),callback:function ($$v) {_vm.didWhat=$$v;},expression:"didWhat"}})],1),_vm._v(" "),_c('gl-form-group',{attrs:{"label":_vm.$options.i18n.MODAL.IMPROVE_WHAT,"optional":""}},[_c('gl-form-textarea',{attrs:{"placeholder":_vm.$options.i18n.MODAL.BETTER_RESPONSE},model:{value:(_vm.improveWhat),callback:function ($$v) {_vm.improveWhat=$$v;},expression:"improveWhat"}})],1)]},proxy:true}],null,false,419229417)}):_vm._e()],1)]:_vm._e()],2),_vm._v(" "),(_vm.displaySelectedContextItems && _vm.isUserMessage)?_c('gl-duo-chat-context-item-selections',{attrs:{"selections":_vm.selectedContextItems,"title":_vm.selectedContextItemsTitle,"default-collapsed":_vm.selectedContextItemsDefaultCollapsed,"variant":"user"}}):_vm._e()],1)],1)};
|
|
235
|
+
},on:{"insert-code-snippet":_vm.onInsertCodeSnippet}},[(_vm.error)?_c('gl-icon',{staticClass:"error-icon gl-border gl-mr-3 gl-shrink-0 gl-rounded-full gl-border-red-500 gl-text-red-600",attrs:{"aria-label":_vm.$options.i18n.MESSAGE_ERROR,"name":"status_warning_borderless","size":16,"data-testid":"error"}}):_vm._e(),_vm._v(" "),_c('div',{ref:"content-wrapper",class:{ 'has-error': _vm.error }},[(_vm.displaySelectedContextItems && _vm.isAssistantMessage)?_c('gl-duo-chat-context-item-selections',{attrs:{"selections":_vm.selectedContextItems,"title":_vm.selectedContextItemsTitle,"default-collapsed":_vm.selectedContextItemsDefaultCollapsed,"variant":"assistant"},on:{"get-content":_vm.onGetContextItemContent}}):_vm._e(),_vm._v(" "),(_vm.error)?_c('div',{directives:[{name:"safe-html",rawName:"v-safe-html:[$options.safeHtmlConfigExtension]",value:(_vm.renderedError),expression:"renderedError",arg:_vm.$options.safeHtmlConfigExtension}],ref:"error-message"}):_c('div',[_c('div',{directives:[{name:"safe-html",rawName:"v-safe-html:[$options.safeHtmlConfigExtension]",value:(_vm.messageContent),expression:"messageContent",arg:_vm.$options.safeHtmlConfigExtension}],ref:"content"}),_vm._v(" "),(_vm.isAssistantMessage)?[(_vm.sources)?_c('documentation-sources',{attrs:{"sources":_vm.sources}}):_vm._e(),_vm._v(" "),_c('div',{staticClass:"duo-chat-message-feedback gl-mt-4 gl-flex gl-items-end"},[(_vm.isChunkAndNotCancelled)?_c('gl-loading-icon',{staticClass:"gl-pt-4",attrs:{"variant":"dots","inline":""}}):_vm._e(),_vm._v(" "),(_vm.isNotChunkOrCancelled)?_c('gl-duo-user-feedback',{attrs:{"feedback-received":_vm.hasFeedback,"modal-title":_vm.$options.i18n.MODAL.TITLE,"modal-alert":_vm.$options.i18n.MODAL.ALERT_TEXT},on:{"feedback":_vm.logEvent},scopedSlots:_vm._u([{key:"feedback-extra-fields",fn:function(){return [_c('gl-form-group',{attrs:{"label":_vm.$options.i18n.MODAL.DID_WHAT,"optional":""}},[_c('gl-form-textarea',{attrs:{"placeholder":_vm.$options.i18n.MODAL.INTERACTION},model:{value:(_vm.didWhat),callback:function ($$v) {_vm.didWhat=$$v;},expression:"didWhat"}})],1),_vm._v(" "),_c('gl-form-group',{attrs:{"label":_vm.$options.i18n.MODAL.IMPROVE_WHAT,"optional":""}},[_c('gl-form-textarea',{attrs:{"placeholder":_vm.$options.i18n.MODAL.BETTER_RESPONSE},model:{value:(_vm.improveWhat),callback:function ($$v) {_vm.improveWhat=$$v;},expression:"improveWhat"}})],1)]},proxy:true}],null,false,419229417)}):_vm._e()],1)]:_vm._e()],2),_vm._v(" "),(_vm.displaySelectedContextItems && _vm.isUserMessage)?_c('gl-duo-chat-context-item-selections',{attrs:{"selections":_vm.selectedContextItems,"title":_vm.selectedContextItemsTitle,"default-collapsed":_vm.selectedContextItemsDefaultCollapsed,"variant":"user"},on:{"get-content":_vm.onGetContextItemContent}}):_vm._e()],1)],1)};
|
|
230
236
|
var __vue_staticRenderFns__ = [];
|
|
231
237
|
|
|
232
238
|
/* style */
|
|
@@ -470,6 +470,14 @@ var script = {
|
|
|
470
470
|
*/
|
|
471
471
|
this.$emit('insert-code-snippet', e);
|
|
472
472
|
},
|
|
473
|
+
onGetContextItemContent(event) {
|
|
474
|
+
/**
|
|
475
|
+
* Emit get-context-item-content event that tells clients to load the full file content for a selected context item.
|
|
476
|
+
* The fully hydrated context item should be updated in the chat message context item.
|
|
477
|
+
* @param {*} event An event containing the message ID and context item to hydrate
|
|
478
|
+
*/
|
|
479
|
+
this.$emit('get-context-item-content', event);
|
|
480
|
+
},
|
|
473
481
|
closeContextItemsMenuOpen() {
|
|
474
482
|
this.contextItemsMenuIsOpen = false;
|
|
475
483
|
this.setPromptAndFocus();
|
|
@@ -490,7 +498,7 @@ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=
|
|
|
490
498
|
{
|
|
491
499
|
'gl-h-full': !_vm.hasMessages,
|
|
492
500
|
'force-scroll-bar': _vm.hasMessages,
|
|
493
|
-
} ],attrs:{"tag":"section","name":"message"}},[_vm._l((_vm.conversations),function(conversation,index){return _c('gl-duo-chat-conversation',{key:("conversation-" + index),attrs:{"enable-code-insertion":_vm.enableCodeInsertion,"messages":conversation,"canceled-request-ids":_vm.canceledRequestIds,"show-delimiter":index > 0},on:{"track-feedback":_vm.onTrackFeedback,"insert-code-snippet":_vm.onInsertCodeSnippet}})}),_vm._v(" "),(!_vm.hasMessages && !_vm.isLoading)?[_c('gl-empty-state',{key:"empty-state",staticClass:"gl-flex-grow gl-justify-center",attrs:{"svg-path":_vm.$options.emptySvg,"svg-height":145,"title":_vm.emptyStateTitle},scopedSlots:_vm._u([{key:"description",fn:function(){return [_c('p',{staticClass:"gl-mb-3",attrs:{"data-testid":"gl-duo-chat-empty-state-description"}},[_vm._v("\n "+_vm._s(_vm.emptyStateDescription)+"\n ")]),_vm._v(" "),_c('p',{staticClass:"gl-mt-3 gl-text-sm gl-text-subtle",attrs:{"data-testid":"gl-duo-chat-empty-state-secondary-description"}},[_vm._v("\n "+_vm._s(_vm.emptyStateSecondaryDescription)+"\n ")])]},proxy:true}],null,false,460840487)}),_vm._v(" "),_c('gl-duo-chat-predefined-prompts',{key:"predefined-prompts",attrs:{"prompts":_vm.predefinedPrompts},on:{"click":_vm.sendPredefinedPrompt}})]:_vm._e(),_vm._v(" "),(_vm.isLoading)?_c('gl-duo-chat-loader',{key:"loader",attrs:{"tool-name":_vm.toolName}}):_vm._e(),_vm._v(" "),_c('div',{key:"anchor",ref:"anchor",staticClass:"scroll-anchor"})],2)],1),_vm._v(" "),(_vm.isChatAvailable)?_c('footer',{staticClass:"duo-chat-drawer-footer duo-chat-drawer-footer-sticky gl-border-t gl-bg-gray-10 gl-p-5",class:{ 'duo-chat-drawer-body-scrim-on-footer': !_vm.scrolledToBottom },attrs:{"data-testid":"chat-footer"}},[_c('gl-form',{attrs:{"data-testid":"chat-prompt-form"},on:{"submit":function($event){$event.stopPropagation();$event.preventDefault();return _vm.sendChatPrompt.apply(null, arguments)}}},[_c('div',{staticClass:"gl-relative gl-max-w-full"},[_vm._t("context-items-menu",null,{"isOpen":_vm.contextItemsMenuIsOpen,"onClose":_vm.closeContextItemsMenuOpen,"setRef":_vm.setContextItemsMenuRef,"focusPrompt":_vm.focusChatInput})],2),_vm._v(" "),_c('gl-form-input-group',{scopedSlots:_vm._u([{key:"append",fn:function(){return [(_vm.displaySubmitButton)?_c('gl-button',{staticClass:"!gl-absolute gl-bottom-2 gl-right-2 !gl-rounded-base",attrs:{"icon":"paper-airplane","category":"primary","variant":"confirm","type":"submit","data-testid":"chat-prompt-submit-button","aria-label":_vm.$options.i18n.CHAT_SUBMIT_LABEL}}):_c('gl-button',{staticClass:"!gl-absolute gl-bottom-2 gl-right-2 !gl-rounded-base",attrs:{"icon":"stop","category":"primary","variant":"default","data-testid":"chat-prompt-cancel-button","aria-label":_vm.$options.i18n.CHAT_CANCEL_LABEL},on:{"click":_vm.cancelPrompt}})]},proxy:true}],null,false,677611116)},[_c('div',{staticClass:"duo-chat-input gl-min-h-8 gl-max-w-full gl-grow gl-rounded-base gl-bg-white gl-align-top gl-shadow-inner-1-gray-400",attrs:{"data-value":_vm.prompt}},[(_vm.shouldShowSlashCommands)?_c('gl-card',{ref:"commands",staticClass:"slash-commands !gl-absolute gl-w-full -gl-translate-y-full gl-list-none gl-pl-0 gl-shadow-md",attrs:{"body-class":"!gl-p-2"}},_vm._l((_vm.filteredSlashCommands),function(command,index){return _c('gl-dropdown-item',{key:command.name,class:{ 'active-command': index === _vm.activeCommandIndex },on:{"click":function($event){return _vm.selectSlashCommand(index)}},nativeOn:{"mouseenter":function($event){_vm.activeCommandIndex = index;}}},[_c('span',{staticClass:"gl-flex gl-justify-between"},[_c('span',{staticClass:"gl-block"},[_vm._v(_vm._s(command.name))]),_vm._v(" "),_c('small',{staticClass:"gl-pl-3 gl-text-right gl-italic gl-text-gray-500"},[_vm._v(_vm._s(command.description))])])])}),1):_vm._e(),_vm._v(" "),_c('gl-form-textarea',{ref:"prompt",staticClass:"gl-absolute !gl-h-full gl-rounded-br-none gl-rounded-tr-none !gl-bg-transparent !gl-py-4 !gl-shadow-none",class:{ 'gl-truncate': !_vm.prompt },attrs:{"data-testid":"chat-prompt-input","placeholder":_vm.inputPlaceholder,"autofocus":""},on:{"compositionend":_vm.compositionEnd},nativeOn:{"keydown":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"enter",13,$event.key,"Enter")){ return null; }if($event.ctrlKey||$event.shiftKey||$event.altKey||$event.metaKey){ return null; }$event.preventDefault();},"keyup":function($event){return _vm.onInputKeyup.apply(null, arguments)}},model:{value:(_vm.prompt),callback:function ($$v) {_vm.prompt=$$v;},expression:"prompt"}})],1)])],1)],1):_vm._e()]):_vm._e()};
|
|
501
|
+
} ],attrs:{"tag":"section","name":"message"}},[_vm._l((_vm.conversations),function(conversation,index){return _c('gl-duo-chat-conversation',{key:("conversation-" + index),attrs:{"enable-code-insertion":_vm.enableCodeInsertion,"messages":conversation,"canceled-request-ids":_vm.canceledRequestIds,"show-delimiter":index > 0},on:{"track-feedback":_vm.onTrackFeedback,"insert-code-snippet":_vm.onInsertCodeSnippet,"get-context-item-content":_vm.onGetContextItemContent}})}),_vm._v(" "),(!_vm.hasMessages && !_vm.isLoading)?[_c('gl-empty-state',{key:"empty-state",staticClass:"gl-flex-grow gl-justify-center",attrs:{"svg-path":_vm.$options.emptySvg,"svg-height":145,"title":_vm.emptyStateTitle},scopedSlots:_vm._u([{key:"description",fn:function(){return [_c('p',{staticClass:"gl-mb-3",attrs:{"data-testid":"gl-duo-chat-empty-state-description"}},[_vm._v("\n "+_vm._s(_vm.emptyStateDescription)+"\n ")]),_vm._v(" "),_c('p',{staticClass:"gl-mt-3 gl-text-sm gl-text-subtle",attrs:{"data-testid":"gl-duo-chat-empty-state-secondary-description"}},[_vm._v("\n "+_vm._s(_vm.emptyStateSecondaryDescription)+"\n ")])]},proxy:true}],null,false,460840487)}),_vm._v(" "),_c('gl-duo-chat-predefined-prompts',{key:"predefined-prompts",attrs:{"prompts":_vm.predefinedPrompts},on:{"click":_vm.sendPredefinedPrompt}})]:_vm._e(),_vm._v(" "),(_vm.isLoading)?_c('gl-duo-chat-loader',{key:"loader",attrs:{"tool-name":_vm.toolName}}):_vm._e(),_vm._v(" "),_c('div',{key:"anchor",ref:"anchor",staticClass:"scroll-anchor"})],2)],1),_vm._v(" "),(_vm.isChatAvailable)?_c('footer',{staticClass:"duo-chat-drawer-footer duo-chat-drawer-footer-sticky gl-border-t gl-bg-gray-10 gl-p-5",class:{ 'duo-chat-drawer-body-scrim-on-footer': !_vm.scrolledToBottom },attrs:{"data-testid":"chat-footer"}},[_c('gl-form',{attrs:{"data-testid":"chat-prompt-form"},on:{"submit":function($event){$event.stopPropagation();$event.preventDefault();return _vm.sendChatPrompt.apply(null, arguments)}}},[_c('div',{staticClass:"gl-relative gl-max-w-full"},[_vm._t("context-items-menu",null,{"isOpen":_vm.contextItemsMenuIsOpen,"onClose":_vm.closeContextItemsMenuOpen,"setRef":_vm.setContextItemsMenuRef,"focusPrompt":_vm.focusChatInput})],2),_vm._v(" "),_c('gl-form-input-group',{scopedSlots:_vm._u([{key:"append",fn:function(){return [(_vm.displaySubmitButton)?_c('gl-button',{staticClass:"!gl-absolute gl-bottom-2 gl-right-2 !gl-rounded-base",attrs:{"icon":"paper-airplane","category":"primary","variant":"confirm","type":"submit","data-testid":"chat-prompt-submit-button","aria-label":_vm.$options.i18n.CHAT_SUBMIT_LABEL}}):_c('gl-button',{staticClass:"!gl-absolute gl-bottom-2 gl-right-2 !gl-rounded-base",attrs:{"icon":"stop","category":"primary","variant":"default","data-testid":"chat-prompt-cancel-button","aria-label":_vm.$options.i18n.CHAT_CANCEL_LABEL},on:{"click":_vm.cancelPrompt}})]},proxy:true}],null,false,677611116)},[_c('div',{staticClass:"duo-chat-input gl-min-h-8 gl-max-w-full gl-grow gl-rounded-base gl-bg-white gl-align-top gl-shadow-inner-1-gray-400",attrs:{"data-value":_vm.prompt}},[(_vm.shouldShowSlashCommands)?_c('gl-card',{ref:"commands",staticClass:"slash-commands !gl-absolute gl-w-full -gl-translate-y-full gl-list-none gl-pl-0 gl-shadow-md",attrs:{"body-class":"!gl-p-2"}},_vm._l((_vm.filteredSlashCommands),function(command,index){return _c('gl-dropdown-item',{key:command.name,class:{ 'active-command': index === _vm.activeCommandIndex },on:{"click":function($event){return _vm.selectSlashCommand(index)}},nativeOn:{"mouseenter":function($event){_vm.activeCommandIndex = index;}}},[_c('span',{staticClass:"gl-flex gl-justify-between"},[_c('span',{staticClass:"gl-block"},[_vm._v(_vm._s(command.name))]),_vm._v(" "),_c('small',{staticClass:"gl-pl-3 gl-text-right gl-italic gl-text-gray-500"},[_vm._v(_vm._s(command.description))])])])}),1):_vm._e(),_vm._v(" "),_c('gl-form-textarea',{ref:"prompt",staticClass:"gl-absolute !gl-h-full gl-rounded-br-none gl-rounded-tr-none !gl-bg-transparent !gl-py-4 !gl-shadow-none",class:{ 'gl-truncate': !_vm.prompt },attrs:{"data-testid":"chat-prompt-input","placeholder":_vm.inputPlaceholder,"autofocus":""},on:{"compositionend":_vm.compositionEnd},nativeOn:{"keydown":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"enter",13,$event.key,"Enter")){ return null; }if($event.ctrlKey||$event.shiftKey||$event.altKey||$event.metaKey){ return null; }$event.preventDefault();},"keyup":function($event){return _vm.onInputKeyup.apply(null, arguments)}},model:{value:(_vm.prompt),callback:function ($$v) {_vm.prompt=$$v;},expression:"prompt"}})],1)])],1)],1):_vm._e()]):_vm._e()};
|
|
494
502
|
var __vue_staticRenderFns__ = [];
|
|
495
503
|
|
|
496
504
|
/* style */
|
package/package.json
CHANGED
|
@@ -5,3 +5,7 @@ export const CONTEXT_ITEM_CATEGORY_LOCAL_GIT = 'local_git';
|
|
|
5
5
|
|
|
6
6
|
export const CONTEXT_ITEM_LOCAL_GIT_COMMIT = 'commit';
|
|
7
7
|
export const CONTEXT_ITEM_LOCAL_GIT_DIFF = 'diff';
|
|
8
|
+
|
|
9
|
+
export const LANGUAGE_IDENTIFIER_PREFIX = 'language-';
|
|
10
|
+
export const LANGUAGE_IDENTIFIER_DIFF = 'language-diff';
|
|
11
|
+
export const LANGUAGE_IDENTIFIER_PLAINTEXT = 'language-plaintext';
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { nextTick } from 'vue';
|
|
3
|
+
import { contextItemValidator } from '../utils';
|
|
4
|
+
import GlModal from '../../../../../../base/modal/modal.vue';
|
|
5
|
+
import { SafeHtmlDirective as SafeHtml } from '../../../../../../../directives/safe_html/safe_html';
|
|
6
|
+
import GlSkeletonLoader from '../../../../../../base/skeleton_loader/skeleton_loader.vue';
|
|
7
|
+
import { translate } from '../../../../../../../utils/i18n';
|
|
8
|
+
import {
|
|
9
|
+
CONTEXT_ITEM_CATEGORY_LOCAL_GIT,
|
|
10
|
+
LANGUAGE_IDENTIFIER_DIFF,
|
|
11
|
+
LANGUAGE_IDENTIFIER_PLAINTEXT,
|
|
12
|
+
LANGUAGE_IDENTIFIER_PREFIX,
|
|
13
|
+
} from '../constants';
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
name: 'GlDuoChatContextItemDetailsModal',
|
|
17
|
+
components: {
|
|
18
|
+
GlSkeletonLoader,
|
|
19
|
+
GlModal,
|
|
20
|
+
},
|
|
21
|
+
directives: {
|
|
22
|
+
SafeHtml,
|
|
23
|
+
},
|
|
24
|
+
inject: {
|
|
25
|
+
renderGFM: {
|
|
26
|
+
from: 'renderGFM',
|
|
27
|
+
default: () => (element) => {
|
|
28
|
+
element.classList.add('gl-markdown', 'gl-compact-markdown');
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
props: {
|
|
33
|
+
/**
|
|
34
|
+
* Context items to preview. If it has no `content`, the loading state will be displayed.
|
|
35
|
+
*/
|
|
36
|
+
contextItem: {
|
|
37
|
+
type: Object,
|
|
38
|
+
required: true,
|
|
39
|
+
validator: contextItemValidator,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
computed: {
|
|
43
|
+
isLoadingContent() {
|
|
44
|
+
return this.contextItem.content === undefined;
|
|
45
|
+
},
|
|
46
|
+
languageIdentifierClass() {
|
|
47
|
+
if (this.contextItem.category === CONTEXT_ITEM_CATEGORY_LOCAL_GIT) {
|
|
48
|
+
return LANGUAGE_IDENTIFIER_DIFF;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const fileExtension = this.contextItem.metadata?.relativePath?.split('.').at(-1);
|
|
52
|
+
if (fileExtension && fileExtension !== this.contextItem.metadata?.relativePath) {
|
|
53
|
+
return `${LANGUAGE_IDENTIFIER_PREFIX}${fileExtension}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return LANGUAGE_IDENTIFIER_PLAINTEXT;
|
|
57
|
+
},
|
|
58
|
+
title() {
|
|
59
|
+
return (
|
|
60
|
+
this.contextItem.metadata?.title ||
|
|
61
|
+
this.contextItem.metadata?.relativePath ||
|
|
62
|
+
translate('GlDuoChatContextItemDetailsModal.title', 'Preview')
|
|
63
|
+
);
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
watch: {
|
|
67
|
+
contextItem: {
|
|
68
|
+
async handler(newVal, oldVal) {
|
|
69
|
+
const shouldFormat = newVal?.content !== oldVal?.content && newVal?.content;
|
|
70
|
+
if (shouldFormat) {
|
|
71
|
+
await nextTick();
|
|
72
|
+
await this.hydrateContentWithGFM();
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
immediate: true,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
methods: {
|
|
79
|
+
async hydrateContentWithGFM() {
|
|
80
|
+
await nextTick();
|
|
81
|
+
|
|
82
|
+
if (this.$refs.content) {
|
|
83
|
+
this.renderGFM(this.$refs.content);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
onModalVisibilityChange(isVisible) {
|
|
87
|
+
if (!isVisible) {
|
|
88
|
+
this.$emit('close');
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
</script>
|
|
94
|
+
|
|
95
|
+
<template>
|
|
96
|
+
<gl-modal
|
|
97
|
+
modal-id="context-item-details-modal"
|
|
98
|
+
:title="title"
|
|
99
|
+
:visible="true"
|
|
100
|
+
:scrollable="true"
|
|
101
|
+
hide-footer
|
|
102
|
+
size="lg"
|
|
103
|
+
@change="onModalVisibilityChange"
|
|
104
|
+
>
|
|
105
|
+
<gl-skeleton-loader v-if="isLoadingContent" />
|
|
106
|
+
<div v-else ref="content" data-testid="context-item-content">
|
|
107
|
+
<pre
|
|
108
|
+
v-safe-html="contextItem.content"
|
|
109
|
+
class="code js-syntax-highlight gl-p-3"
|
|
110
|
+
:class="languageIdentifierClass"
|
|
111
|
+
></pre>
|
|
112
|
+
</div>
|
|
113
|
+
</gl-modal>
|
|
114
|
+
</template>
|
|
@@ -218,6 +218,14 @@ export default {
|
|
|
218
218
|
|
|
219
219
|
this.activeIndex = newIndex;
|
|
220
220
|
},
|
|
221
|
+
onGetContextItemContent(contextItem) {
|
|
222
|
+
/**
|
|
223
|
+
* Emit get-context-item-content event that tells clients to load the full file content for a selected context item.
|
|
224
|
+
* The fully hydrated context item should be updated in the context item selections.
|
|
225
|
+
* @param {*} event An event containing the context item to hydrate
|
|
226
|
+
*/
|
|
227
|
+
this.$emit('get-context-item-content', { contextItem });
|
|
228
|
+
},
|
|
221
229
|
},
|
|
222
230
|
i18n: {
|
|
223
231
|
selectedContextItemsTitle: translate(
|
|
@@ -233,11 +241,13 @@ export default {
|
|
|
233
241
|
<gl-duo-chat-context-item-selections
|
|
234
242
|
v-if="selections.length"
|
|
235
243
|
:selections="selections"
|
|
244
|
+
:categories="categories"
|
|
236
245
|
:removable="true"
|
|
237
246
|
:title="$options.i18n.selectedContextItemsTitle"
|
|
238
247
|
:default-collapsed="false"
|
|
239
248
|
class="gl-mb-3"
|
|
240
249
|
@remove="removeItem"
|
|
250
|
+
@get-content="onGetContextItemContent"
|
|
241
251
|
/>
|
|
242
252
|
<gl-card
|
|
243
253
|
v-if="open"
|
|
@@ -4,12 +4,15 @@ import GlIcon from '../../../../../../base/icon/icon.vue';
|
|
|
4
4
|
import GlToken from '../../../../../../base/token/token.vue';
|
|
5
5
|
import GlTruncate from '../../../../../../utilities/truncate/truncate.vue';
|
|
6
6
|
import GlDuoChatContextItemPopover from '../duo_chat_context_item_popover/duo_chat_context_item_popover.vue';
|
|
7
|
+
import { CONTEXT_ITEM_CATEGORY_FILE, CONTEXT_ITEM_CATEGORY_LOCAL_GIT } from '../constants';
|
|
8
|
+
import GlDuoChatContextItemDetailsModal from '../duo_chat_context_item_details_modal/duo_chat_context_item_details_modal.vue';
|
|
7
9
|
import { contextItemsValidator, getContextItemIcon } from '../utils';
|
|
8
10
|
|
|
9
11
|
export default {
|
|
10
12
|
name: 'GlDuoChatContextItemSelections',
|
|
11
13
|
components: {
|
|
12
14
|
GlTruncate,
|
|
15
|
+
GlDuoChatContextItemDetailsModal,
|
|
13
16
|
GlIcon,
|
|
14
17
|
GlDuoChatContextItemPopover,
|
|
15
18
|
GlToken,
|
|
@@ -55,6 +58,7 @@ export default {
|
|
|
55
58
|
return {
|
|
56
59
|
isCollapsed: this.defaultCollapsed,
|
|
57
60
|
selectionsId: uniqueId(),
|
|
61
|
+
previewContextItemId: null,
|
|
58
62
|
};
|
|
59
63
|
},
|
|
60
64
|
computed: {
|
|
@@ -73,6 +77,9 @@ export default {
|
|
|
73
77
|
}
|
|
74
78
|
return '';
|
|
75
79
|
},
|
|
80
|
+
contextItemPreview() {
|
|
81
|
+
return this.selections.find((item) => item.id === this.previewContextItemId);
|
|
82
|
+
},
|
|
76
83
|
},
|
|
77
84
|
methods: {
|
|
78
85
|
getContextItemIcon,
|
|
@@ -86,6 +93,30 @@ export default {
|
|
|
86
93
|
*/
|
|
87
94
|
this.$emit('remove', contextItem);
|
|
88
95
|
},
|
|
96
|
+
onOpenItem(event, contextItem) {
|
|
97
|
+
const isKeypressOnCloseButton =
|
|
98
|
+
event.type === 'keydown' && event.target !== event.currentTarget;
|
|
99
|
+
if (isKeypressOnCloseButton) {
|
|
100
|
+
// don't respond to events triggered by the gl-token children (e.g. the close button)
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!this.canOpen(contextItem)) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (!contextItem.content) {
|
|
108
|
+
this.$emit('get-content', contextItem);
|
|
109
|
+
}
|
|
110
|
+
this.previewContextItemId = contextItem.id;
|
|
111
|
+
},
|
|
112
|
+
canOpen(contextItem) {
|
|
113
|
+
return [CONTEXT_ITEM_CATEGORY_LOCAL_GIT, CONTEXT_ITEM_CATEGORY_FILE].includes(
|
|
114
|
+
contextItem.category
|
|
115
|
+
);
|
|
116
|
+
},
|
|
117
|
+
onClosePreview() {
|
|
118
|
+
this.previewContextItemId = null;
|
|
119
|
+
},
|
|
89
120
|
},
|
|
90
121
|
};
|
|
91
122
|
</script>
|
|
@@ -114,6 +145,11 @@ export default {
|
|
|
114
145
|
variant="default"
|
|
115
146
|
class="gl-mb-2 gl-mr-2 gl-max-w-full"
|
|
116
147
|
:class="tokenVariantClasses"
|
|
148
|
+
:tabindex="canOpen(item) ? 0 : -1"
|
|
149
|
+
:role="canOpen(item) ? 'button' : undefined"
|
|
150
|
+
@click="onOpenItem($event, item)"
|
|
151
|
+
@keydown.enter="onOpenItem($event, item)"
|
|
152
|
+
@keydown.space.prevent="onOpenItem($event, item)"
|
|
117
153
|
@close="onRemoveItem(item)"
|
|
118
154
|
>
|
|
119
155
|
<div
|
|
@@ -132,8 +168,14 @@ export default {
|
|
|
132
168
|
:context-item="item"
|
|
133
169
|
:target="`context-item-${item.id}-${selectionsId}-token`"
|
|
134
170
|
placement="bottom"
|
|
171
|
+
@show-git-diff="onOpenItem(item)"
|
|
135
172
|
/>
|
|
136
173
|
</gl-token>
|
|
137
174
|
</div>
|
|
175
|
+
<gl-duo-chat-context-item-details-modal
|
|
176
|
+
v-if="contextItemPreview"
|
|
177
|
+
:context-item="contextItemPreview"
|
|
178
|
+
@close="onClosePreview"
|
|
179
|
+
/>
|
|
138
180
|
</div>
|
|
139
181
|
</template>
|
package/src/components/experimental/duo/chat/components/duo_chat_context/mock_context_data.js
CHANGED
|
@@ -16,6 +16,21 @@ export function getMockCategory(categoryValue) {
|
|
|
16
16
|
return MOCK_CATEGORIES.find((cat) => cat.value === categoryValue);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
export const MOCK_CONTEXT_FILE_CONTENT = `export function waterPlants() {
|
|
20
|
+
console.log('sprinkle');
|
|
21
|
+
}`;
|
|
22
|
+
|
|
23
|
+
export const MOCK_CONTEXT_FILE_DIFF_CONTENT = `diff --git a/src/plants/strawberry.ts b/src/plants/strawberry.ts
|
|
24
|
+
index 1234567..8901234 100644
|
|
25
|
+
--- a/src/plants/strawberry.ts
|
|
26
|
+
+++ b/src/plants/strawberry.ts
|
|
27
|
+
@@ -1,4 +1,4 @@
|
|
28
|
+
export const strawberry = {
|
|
29
|
+
name: 'Strawberry',
|
|
30
|
+
- waterNeeds: 'moderate',
|
|
31
|
+
+ waterNeeds: 'high',
|
|
32
|
+
};`;
|
|
33
|
+
|
|
19
34
|
export const MOCK_CONTEXT_ITEM_FILE = {
|
|
20
35
|
id: '123e4567-e89b-12d3-a456-426614174000',
|
|
21
36
|
category: CONTEXT_ITEM_CATEGORY_FILE,
|
|
@@ -57,6 +57,9 @@ export default {
|
|
|
57
57
|
onInsertCodeSnippet(e) {
|
|
58
58
|
this.$emit('insert-code-snippet', e);
|
|
59
59
|
},
|
|
60
|
+
onGetContextItemContent(e) {
|
|
61
|
+
this.$emit('get-context-item-content', e);
|
|
62
|
+
},
|
|
60
63
|
},
|
|
61
64
|
i18n,
|
|
62
65
|
};
|
|
@@ -81,6 +84,7 @@ export default {
|
|
|
81
84
|
:is-cancelled="canceledRequestIds.includes(msg.requestId)"
|
|
82
85
|
@track-feedback="onTrackFeedback"
|
|
83
86
|
@insert-code-snippet="onInsertCodeSnippet"
|
|
87
|
+
@get-context-item-content="onGetContextItemContent"
|
|
84
88
|
/>
|
|
85
89
|
</div>
|
|
86
90
|
</template>
|
package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.vue
CHANGED
|
@@ -234,6 +234,12 @@ export default {
|
|
|
234
234
|
onInsertCodeSnippet(e) {
|
|
235
235
|
this.$emit('insert-code-snippet', e);
|
|
236
236
|
},
|
|
237
|
+
onGetContextItemContent(contextItem) {
|
|
238
|
+
this.$emit('get-context-item-content', {
|
|
239
|
+
messageId: this.message.id,
|
|
240
|
+
contextItem,
|
|
241
|
+
});
|
|
242
|
+
},
|
|
237
243
|
},
|
|
238
244
|
};
|
|
239
245
|
</script>
|
|
@@ -264,6 +270,7 @@ export default {
|
|
|
264
270
|
:title="selectedContextItemsTitle"
|
|
265
271
|
:default-collapsed="selectedContextItemsDefaultCollapsed"
|
|
266
272
|
variant="assistant"
|
|
273
|
+
@get-content="onGetContextItemContent"
|
|
267
274
|
/>
|
|
268
275
|
<div
|
|
269
276
|
v-if="error"
|
|
@@ -309,6 +316,7 @@ export default {
|
|
|
309
316
|
:title="selectedContextItemsTitle"
|
|
310
317
|
:default-collapsed="selectedContextItemsDefaultCollapsed"
|
|
311
318
|
variant="user"
|
|
319
|
+
@get-content="onGetContextItemContent"
|
|
312
320
|
/>
|
|
313
321
|
</div>
|
|
314
322
|
</div>
|
|
@@ -518,6 +518,14 @@ export default {
|
|
|
518
518
|
*/
|
|
519
519
|
this.$emit('insert-code-snippet', e);
|
|
520
520
|
},
|
|
521
|
+
onGetContextItemContent(event) {
|
|
522
|
+
/**
|
|
523
|
+
* Emit get-context-item-content event that tells clients to load the full file content for a selected context item.
|
|
524
|
+
* The fully hydrated context item should be updated in the chat message context item.
|
|
525
|
+
* @param {*} event An event containing the message ID and context item to hydrate
|
|
526
|
+
*/
|
|
527
|
+
this.$emit('get-context-item-content', event);
|
|
528
|
+
},
|
|
521
529
|
closeContextItemsMenuOpen() {
|
|
522
530
|
this.contextItemsMenuIsOpen = false;
|
|
523
531
|
this.setPromptAndFocus();
|
|
@@ -603,6 +611,7 @@ export default {
|
|
|
603
611
|
:show-delimiter="index > 0"
|
|
604
612
|
@track-feedback="onTrackFeedback"
|
|
605
613
|
@insert-code-snippet="onInsertCodeSnippet"
|
|
614
|
+
@get-context-item-content="onGetContextItemContent"
|
|
606
615
|
/>
|
|
607
616
|
<template v-if="!hasMessages && !isLoading">
|
|
608
617
|
<gl-empty-state
|
package/translations.js
CHANGED
|
@@ -27,6 +27,7 @@ export default {
|
|
|
27
27
|
'GlDuoChat.chatPromptPlaceholderDefault': 'GitLab Duo Chat',
|
|
28
28
|
'GlDuoChat.chatPromptPlaceholderWithCommands': 'Type "/" for slash commands',
|
|
29
29
|
'GlDuoChat.chatSubmitLabel': 'Send chat message.',
|
|
30
|
+
'GlDuoChatContextItemDetailsModal.title': 'Preview',
|
|
30
31
|
'GlDuoChatContextItemMenu.emptyStateMessage': 'No results found',
|
|
31
32
|
'GlDuoChatContextItemMenu.loadingMessage': 'Loading...',
|
|
32
33
|
'GlDuoChatContextItemMenu.searchInputPlaceholder': 'Search %{categoryLabel}...',
|