@gitlab/ui 77.0.0 → 77.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 CHANGED
@@ -1,3 +1,10 @@
1
+ # [77.1.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v77.0.0...v77.1.0) (2024-02-27)
2
+
3
+
4
+ ### Features
5
+
6
+ * **DuoChat:** Improve the feedback mechanism in the DuoChat ([235077d](https://gitlab.com/gitlab-org/gitlab-ui/commit/235077d5a20a8a3848233450d8d1c9190008cc15))
7
+
1
8
  # [77.0.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v76.1.0...v77.0.0) (2024-02-27)
2
9
 
3
10
 
@@ -1,4 +1,6 @@
1
1
  import GlDuoUserFeedback from '../../../user_feedback/user_feedback';
2
+ import GlFormGroup from '../../../../../base/form/form_group/form_group';
3
+ import GlFormTextarea from '../../../../../base/form/form_textarea/form_textarea';
2
4
  import { SafeHtmlDirective } from '../../../../../../directives/safe_html/safe_html';
3
5
  import { MESSAGE_MODEL_ROLES } from '../../constants';
4
6
  import DocumentationSources from '../duo_chat_message_sources/duo_chat_message_sources';
@@ -6,6 +8,16 @@ import { renderDuoChatMarkdownPreview } from '../../markdown_renderer';
6
8
  import { CopyCodeElement } from './copy_code_element';
7
9
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
8
10
 
11
+ const i18n = {
12
+ MODAL: {
13
+ TITLE: 'Give feedback on GitLab Duo Chat',
14
+ ALERT_TEXT: 'GitLab team members cannot view your conversation. Please be as descriptive as possible.',
15
+ DID_WHAT: 'What were you doing?',
16
+ INTERACTION: 'The situation in which you interacted with GitLab Duo Chat.',
17
+ IMPROVE_WHAT: 'How could the response be improved?',
18
+ BETTER_RESPONSE: 'How the response might better meet your needs.'
19
+ }
20
+ };
9
21
  const concatUntilEmpty = arr => {
10
22
  if (!arr) return '';
11
23
  let end = arr.findIndex(el => !el);
@@ -19,11 +31,19 @@ var script = {
19
31
  },
20
32
  components: {
21
33
  DocumentationSources,
22
- GlDuoUserFeedback
34
+ GlDuoUserFeedback,
35
+ GlFormGroup,
36
+ GlFormTextarea
23
37
  },
24
38
  directives: {
25
39
  SafeHtml: SafeHtmlDirective
26
40
  },
41
+ provide() {
42
+ return {
43
+ modalTitle: i18n.MODAL.TITLE,
44
+ modalAlertText: i18n.MODAL.ALERT_TEXT
45
+ };
46
+ },
27
47
  inject: {
28
48
  // Note, we likely might move away from Provide/Inject for this
29
49
  // and only ship the versions that are currently in the default
@@ -49,6 +69,12 @@ var script = {
49
69
  required: true
50
70
  }
51
71
  },
72
+ data() {
73
+ return {
74
+ didWhat: '',
75
+ improveWhat: ''
76
+ };
77
+ },
52
78
  computed: {
53
79
  isAssistantMessage() {
54
80
  return this.message.role.toLowerCase() === MESSAGE_MODEL_ROLES.assistant;
@@ -84,8 +110,16 @@ var script = {
84
110
  if (this.message.contentHtml) {
85
111
  this.renderGFM(this.$refs.content);
86
112
  }
113
+ },
114
+ logEvent(e) {
115
+ this.$emit('track-feedback', {
116
+ ...e,
117
+ didWhat: this.didWhat,
118
+ improveWhat: this.improveWhat
119
+ });
87
120
  }
88
- }
121
+ },
122
+ i18n
89
123
  };
90
124
 
91
125
  /* script */
@@ -96,7 +130,7 @@ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=
96
130
  'gl-ml-auto gl-bg-blue-100 gl-text-blue-900 gl-rounded-bottom-right-none': _vm.isUserMessage,
97
131
  'gl-rounded-bottom-left-none gl-text-gray-900 gl-bg-white gl-border-1 gl-border-solid gl-border-gray-50':
98
132
  _vm.isAssistantMessage,
99
- }},[_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:"gl-display-flex gl-align-items-flex-end gl-mt-4 duo-chat-message-feedback"},[_c('gl-duo-user-feedback',{on:{"feedback":function($event){return _vm.$emit('track-feedback', $event)}}})],1)]:_vm._e()],2)};
133
+ }},[_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:"gl-display-flex gl-align-items-flex-end gl-mt-4 duo-chat-message-feedback"},[_c('gl-duo-user-feedback',{attrs:{"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)})],1)]:_vm._e()],2)};
100
134
  var __vue_staticRenderFns__ = [];
101
135
 
102
136
  /* style */
@@ -129,3 +163,4 @@ var __vue_staticRenderFns__ = [];
129
163
  );
130
164
 
131
165
  export default __vue_component__;
166
+ export { i18n };
@@ -1,55 +1,72 @@
1
1
  import GlModal from '../../../base/modal/modal';
2
+ import GlAlert from '../../../base/alert/alert';
2
3
  import GlFormGroup from '../../../base/form/form_group/form_group';
3
4
  import GlFormTextarea from '../../../base/form/form_textarea/form_textarea';
4
5
  import GlFormCheckboxGroup from '../../../base/form/form_checkbox/form_checkbox_group';
5
6
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
6
7
 
7
8
  const i18n = {
8
- MODAL_TITLE: 'Give feedback on AI content',
9
- MODAL_DESCRIPTION: 'To help improve the quality of the content, send your feedback to GitLab team members.',
10
- MODAL_OPTIONS_LABEL: 'How was the AI content?',
11
- MODAL_MORE_LABEL: 'More information',
12
- MODAL_MORE_PLACEHOLDER: 'How could the content be improved?',
13
- MODAL_FEEDBACK_OPTIONS: {
14
- helpful: 'Helpful',
15
- unhelpful: 'Unhelpful or irrelevant',
16
- incorrect: 'Factually incorrect',
17
- long: 'Too long',
18
- abuse: 'Abusive or offensive',
19
- other: 'Something else'
20
- },
21
- MODAL_ACTIONS: {
22
- submit: 'Submit',
23
- cancel: 'Cancel'
9
+ MODAL: {
10
+ TITLE: 'Give feedback on GitLab Duo',
11
+ DESCRIPTION: 'To help improve GitLab Duo, send your feeback to GitLab team members.',
12
+ ALERT: 'GitLab team members cannot see the AI content. Please be as descriptive as possible.',
13
+ OPTIONS_LABEL: 'How could the AI content be improved?',
14
+ SITUATION_DESCRIPTION_LABEL: 'What were you doing?',
15
+ SITUATION_DESCRIPTION_PLACEHOLDER: 'The situation in which you interacted with GitLab Duo Chat.',
16
+ IMPROVEMENT_SUGGESTION_LABEL: 'How could the response be improved?',
17
+ IMPROVEMENT_SUGGESTION_PLACEHOLDER: 'How the response might better meet your needs.',
18
+ MORE_LABEL: 'More information',
19
+ MORE_PLACEHOLDER: 'How could the content be improved?',
20
+ FEEDBACK_OPTIONS: {
21
+ helpful: 'Helpful',
22
+ unhelpful: 'Unhelpful or irrelevant',
23
+ incorrect: 'Factually incorrect',
24
+ long: 'Too long',
25
+ abuse: 'Abusive or offensive',
26
+ other: 'Something else'
27
+ },
28
+ ACTIONS: {
29
+ submit: 'Submit',
30
+ cancel: 'Cancel'
31
+ }
24
32
  }
25
33
  };
26
34
  const feedbackOptions = [{
27
- text: i18n.MODAL_FEEDBACK_OPTIONS.helpful,
35
+ text: i18n.MODAL.FEEDBACK_OPTIONS.helpful,
28
36
  value: 'helpful'
29
37
  }, {
30
- text: i18n.MODAL_FEEDBACK_OPTIONS.unhelpful,
38
+ text: i18n.MODAL.FEEDBACK_OPTIONS.unhelpful,
31
39
  value: 'unhelpful'
32
40
  }, {
33
- text: i18n.MODAL_FEEDBACK_OPTIONS.incorrect,
41
+ text: i18n.MODAL.FEEDBACK_OPTIONS.incorrect,
34
42
  value: 'incorrect'
35
43
  }, {
36
- text: i18n.MODAL_FEEDBACK_OPTIONS.long,
44
+ text: i18n.MODAL.FEEDBACK_OPTIONS.long,
37
45
  value: 'long'
38
46
  }, {
39
- text: i18n.MODAL_FEEDBACK_OPTIONS.abuse,
47
+ text: i18n.MODAL.FEEDBACK_OPTIONS.abuse,
40
48
  value: 'abuse'
41
49
  }, {
42
- text: i18n.MODAL_FEEDBACK_OPTIONS.other,
50
+ text: i18n.MODAL.FEEDBACK_OPTIONS.other,
43
51
  value: 'other'
44
52
  }];
45
53
  var script = {
46
54
  name: 'DuoChatFeedbackModal',
47
55
  components: {
48
56
  GlModal,
57
+ GlAlert,
49
58
  GlFormCheckboxGroup,
50
59
  GlFormGroup,
51
60
  GlFormTextarea
52
61
  },
62
+ inject: {
63
+ modalTitle: {
64
+ default: i18n.MODAL.TITLE
65
+ },
66
+ modalAlert: {
67
+ default: i18n.MODAL.ALERT
68
+ }
69
+ },
53
70
  data() {
54
71
  return {
55
72
  selectedFeedbackOptions: [],
@@ -74,10 +91,10 @@ var script = {
74
91
  },
75
92
  actions: {
76
93
  primary: {
77
- text: i18n.MODAL_ACTIONS.submit
94
+ text: i18n.MODAL.ACTIONS.submit
78
95
  },
79
96
  cancel: {
80
- text: i18n.MODAL_ACTIONS.cancel
97
+ text: i18n.MODAL.ACTIONS.cancel
81
98
  }
82
99
  },
83
100
  feedbackOptions,
@@ -88,7 +105,7 @@ var script = {
88
105
  const __vue_script__ = script;
89
106
 
90
107
  /* template */
91
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-modal',{ref:"feedbackModal",attrs:{"modal-id":"feedbackModal","title":_vm.$options.i18n.MODAL_TITLE,"action-primary":_vm.$options.actions.primary,"action-cancel":_vm.$options.actions.cancel,"visible":false,"size":"sm"},on:{"primary":_vm.onFeedbackSubmit,"canceled":_vm.onFeedbackCanceled}},[_c('p',[_vm._v(_vm._s(_vm.$options.i18n.MODAL_DESCRIPTION))]),_vm._v(" "),_c('gl-form-group',{attrs:{"label":_vm.$options.i18n.MODAL_OPTIONS_LABEL,"optional":false,"data-testid":"feedback-options"}},[_c('gl-form-checkbox-group',{attrs:{"options":_vm.$options.feedbackOptions},model:{value:(_vm.selectedFeedbackOptions),callback:function ($$v) {_vm.selectedFeedbackOptions=$$v;},expression:"selectedFeedbackOptions"}})],1),_vm._v(" "),_vm._t("feedback-extra-fields",function(){return [_c('gl-form-group',{attrs:{"label":_vm.$options.i18n.MODAL_MORE_LABEL,"optional":""}},[_c('gl-form-textarea',{attrs:{"placeholder":_vm.$options.i18n.MODAL_MORE_PLACEHOLDER},model:{value:(_vm.extendedFeedback),callback:function ($$v) {_vm.extendedFeedback=$$v;},expression:"extendedFeedback"}})],1)]})],2)};
108
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-modal',{ref:"feedbackModal",attrs:{"modal-id":"feedbackModal","title":_vm.modalTitle,"action-primary":_vm.$options.actions.primary,"action-cancel":_vm.$options.actions.cancel,"visible":false,"size":"sm"},on:{"primary":_vm.onFeedbackSubmit,"canceled":_vm.onFeedbackCanceled}},[_c('p',[_vm._v(_vm._s(_vm.$options.i18n.MODAL.DESCRIPTION))]),_vm._v(" "),_c('gl-form-group',{attrs:{"label":_vm.$options.i18n.MODAL.OPTIONS_LABEL,"optional":false,"data-testid":"feedback-options"}},[_c('gl-form-checkbox-group',{attrs:{"options":_vm.$options.feedbackOptions},model:{value:(_vm.selectedFeedbackOptions),callback:function ($$v) {_vm.selectedFeedbackOptions=$$v;},expression:"selectedFeedbackOptions"}})],1),_vm._v(" "),_c('gl-alert',{staticClass:"gl-mb-5",attrs:{"dismissible":false}},[_vm._v(_vm._s(_vm.modalAlert))]),_vm._v(" "),_vm._t("feedback-extra-fields",function(){return [_c('gl-form-group',{attrs:{"label":_vm.$options.i18n.MODAL.MORE_LABEL,"optional":""}},[_c('gl-form-textarea',{attrs:{"placeholder":_vm.$options.i18n.MODAL.MORE_PLACEHOLDER},model:{value:(_vm.extendedFeedback),callback:function ($$v) {_vm.extendedFeedback=$$v;},expression:"extendedFeedback"}})],1)]})],2)};
92
109
  var __vue_staticRenderFns__ = [];
93
110
 
94
111
  /* style */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Tue, 27 Feb 2024 15:36:15 GMT
3
+ * Generated on Tue, 27 Feb 2024 16:44:07 GMT
4
4
  */
5
5
 
6
6
  :root {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Tue, 27 Feb 2024 15:36:15 GMT
3
+ * Generated on Tue, 27 Feb 2024 16:44:07 GMT
4
4
  */
5
5
 
6
6
  :root.gl-dark {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Tue, 27 Feb 2024 15:36:15 GMT
3
+ * Generated on Tue, 27 Feb 2024 16:44:07 GMT
4
4
  */
5
5
 
6
6
  export const DATA_VIZ_GREEN_50 = "#133a03";
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Tue, 27 Feb 2024 15:36:15 GMT
3
+ * Generated on Tue, 27 Feb 2024 16:44:07 GMT
4
4
  */
5
5
 
6
6
  export const DATA_VIZ_GREEN_50 = "#ddfab7";
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Tue, 27 Feb 2024 15:36:15 GMT
3
+ // Generated on Tue, 27 Feb 2024 16:44:08 GMT
4
4
 
5
5
  $red-950: #fff4f3;
6
6
  $red-900: #fcf1ef;
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Tue, 27 Feb 2024 15:36:15 GMT
3
+ // Generated on Tue, 27 Feb 2024 16:44:07 GMT
4
4
 
5
5
  $gl-line-height-52: 3.25rem;
6
6
  $gl-line-height-44: 2.75rem;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "77.0.0",
3
+ "version": "77.1.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -136,7 +136,7 @@
136
136
  "cypress-real-events": "^1.11.0",
137
137
  "dompurify": "^3.0.0",
138
138
  "emoji-regex": "^10.0.0",
139
- "eslint": "8.56.0",
139
+ "eslint": "8.57.0",
140
140
  "eslint-import-resolver-jest": "3.0.2",
141
141
  "eslint-plugin-cypress": "2.15.1",
142
142
  "eslint-plugin-storybook": "0.8.0",
@@ -107,9 +107,21 @@ describe('DuoChatMessage', () => {
107
107
  expect(findUserFeedback().exists()).toBe(true);
108
108
  });
109
109
 
110
- it('proxies the emitted event from the User Feedback component', () => {
111
- findUserFeedback().vm.$emit('feedback', 'foo');
112
- expect(wrapper.emitted('track-feedback')).toEqual([['foo']]);
110
+ it('proxies and enhances the emitted event from the User Feedback component', () => {
111
+ findUserFeedback().vm.$emit('feedback', {
112
+ feedbackChoices: ['incorrect'],
113
+ extendedTextFeedback: 'exampleText',
114
+ });
115
+ expect(wrapper.emitted('track-feedback')).toEqual([
116
+ [
117
+ {
118
+ feedbackChoices: ['incorrect'],
119
+ extendedTextFeedback: 'exampleText',
120
+ didWhat: '',
121
+ improveWhat: '',
122
+ },
123
+ ],
124
+ ]);
113
125
  });
114
126
  });
115
127
 
@@ -1,5 +1,7 @@
1
1
  <script>
2
2
  import GlDuoUserFeedback from '../../../user_feedback/user_feedback.vue';
3
+ import GlFormGroup from '../../../../../base/form/form_group/form_group.vue';
4
+ import GlFormTextarea from '../../../../../base/form/form_textarea/form_textarea.vue';
3
5
  import { SafeHtmlDirective as SafeHtml } from '../../../../../../directives/safe_html/safe_html';
4
6
  import { MESSAGE_MODEL_ROLES } from '../../constants';
5
7
  import DocumentationSources from '../duo_chat_message_sources/duo_chat_message_sources.vue';
@@ -7,6 +9,18 @@ import DocumentationSources from '../duo_chat_message_sources/duo_chat_message_s
7
9
  import { renderDuoChatMarkdownPreview } from '../../markdown_renderer';
8
10
  import { CopyCodeElement } from './copy_code_element';
9
11
 
12
+ export const i18n = {
13
+ MODAL: {
14
+ TITLE: 'Give feedback on GitLab Duo Chat',
15
+ ALERT_TEXT:
16
+ 'GitLab team members cannot view your conversation. Please be as descriptive as possible.',
17
+ DID_WHAT: 'What were you doing?',
18
+ INTERACTION: 'The situation in which you interacted with GitLab Duo Chat.',
19
+ IMPROVE_WHAT: 'How could the response be improved?',
20
+ BETTER_RESPONSE: 'How the response might better meet your needs.',
21
+ },
22
+ };
23
+
10
24
  const concatUntilEmpty = (arr) => {
11
25
  if (!arr) return '';
12
26
 
@@ -25,10 +39,18 @@ export default {
25
39
  components: {
26
40
  DocumentationSources,
27
41
  GlDuoUserFeedback,
42
+ GlFormGroup,
43
+ GlFormTextarea,
28
44
  },
29
45
  directives: {
30
46
  SafeHtml,
31
47
  },
48
+ provide() {
49
+ return {
50
+ modalTitle: i18n.MODAL.TITLE,
51
+ modalAlertText: i18n.MODAL.ALERT_TEXT,
52
+ };
53
+ },
32
54
  inject: {
33
55
  // Note, we likely might move away from Provide/Inject for this
34
56
  // and only ship the versions that are currently in the default
@@ -54,6 +76,12 @@ export default {
54
76
  required: true,
55
77
  },
56
78
  },
79
+ data() {
80
+ return {
81
+ didWhat: '',
82
+ improveWhat: '',
83
+ };
84
+ },
57
85
  computed: {
58
86
  isAssistantMessage() {
59
87
  return this.message.role.toLowerCase() === MESSAGE_MODEL_ROLES.assistant;
@@ -92,7 +120,15 @@ export default {
92
120
  this.renderGFM(this.$refs.content);
93
121
  }
94
122
  },
123
+ logEvent(e) {
124
+ this.$emit('track-feedback', {
125
+ ...e,
126
+ didWhat: this.didWhat,
127
+ improveWhat: this.improveWhat,
128
+ });
129
+ },
95
130
  },
131
+ i18n,
96
132
  };
97
133
  </script>
98
134
  <template>
@@ -110,7 +146,23 @@ export default {
110
146
  <documentation-sources v-if="sources" :sources="sources" />
111
147
 
112
148
  <div class="gl-display-flex gl-align-items-flex-end gl-mt-4 duo-chat-message-feedback">
113
- <gl-duo-user-feedback @feedback="$emit('track-feedback', $event)" />
149
+ <gl-duo-user-feedback
150
+ :modal-title="$options.i18n.MODAL.TITLE"
151
+ :modal-alert="$options.i18n.MODAL.ALERT_TEXT"
152
+ @feedback="logEvent"
153
+ >
154
+ <template #feedback-extra-fields>
155
+ <gl-form-group :label="$options.i18n.MODAL.DID_WHAT" optional>
156
+ <gl-form-textarea v-model="didWhat" :placeholder="$options.i18n.MODAL.INTERACTION" />
157
+ </gl-form-group>
158
+ <gl-form-group :label="$options.i18n.MODAL.IMPROVE_WHAT" optional>
159
+ <gl-form-textarea
160
+ v-model="improveWhat"
161
+ :placeholder="$options.i18n.MODAL.BETTER_RESPONSE"
162
+ />
163
+ </gl-form-group>
164
+ </template>
165
+ </gl-duo-user-feedback>
114
166
  </div>
115
167
  </template>
116
168
  </div>
@@ -58,11 +58,6 @@ you must copy the textarea field from the `DuoChatFeedbackModal` component into
58
58
  @feedback="logEvent"
59
59
  >
60
60
  <template #feedback-extra-fields>
61
- <div class="gl-mb-5">
62
- <gl-alert variant="info" :dismissible="false">
63
- GitLab team members can not see your conversation. Please be as descriptive as possible.
64
- </gl-alert>
65
- </div>
66
61
  <gl-form-group label="What were you doing?" optional>
67
62
  <gl-form-textarea
68
63
  placeholder="The situation in which you interacted with GitLab Duo Chat."
@@ -31,11 +31,11 @@ describe('UserFeedback', () => {
31
31
  const findButton = () => wrapper.findComponent(GlButton);
32
32
  const findModal = () => wrapper.findComponent(FeedbackModal);
33
33
 
34
- beforeEach(() => {
35
- createComponent();
36
- });
37
-
38
34
  describe('rendering with no feedback registered', () => {
35
+ beforeEach(() => {
36
+ createComponent();
37
+ });
38
+
39
39
  it('renders a button to provide feedback', () => {
40
40
  expect(findButton().exists()).toBe(true);
41
41
  });
@@ -65,6 +65,10 @@ describe('UserFeedback', () => {
65
65
  });
66
66
 
67
67
  describe('event handling', () => {
68
+ beforeEach(() => {
69
+ createComponent();
70
+ });
71
+
68
72
  const passedFeedback = { feedbackOptions: ['helpful'], extendedFeedback: 'Foo bar' };
69
73
 
70
74
  it('emits the event, containing the form data, when modal emits', () => {
@@ -87,6 +91,10 @@ describe('UserFeedback', () => {
87
91
  });
88
92
 
89
93
  describe('slots', () => {
94
+ beforeEach(() => {
95
+ createComponent();
96
+ });
97
+
90
98
  it('renders the `feedback-extra-fields` slot', () => {
91
99
  expect(wrapper.findComponent(DummyComponent).exists()).toBe(false);
92
100
  wrapper.destroy();
@@ -1,5 +1,6 @@
1
1
  import { shallowMount } from '@vue/test-utils';
2
2
  import GlModal from '../../../base/modal/modal.vue';
3
+ import GlAlert from '../../../base/alert/alert.vue';
3
4
  import GlFormCheckbox from '../../../base/form/form_checkbox/form_checkbox.vue';
4
5
  import GlFormCheckboxGroup from '../../../base/form/form_checkbox/form_checkbox_group.vue';
5
6
  import GlFormTextarea from '../../../base/form/form_textarea/form_textarea.vue';
@@ -11,7 +12,6 @@ const DummyComponent = {
11
12
 
12
13
  describe('FeedbackModal', () => {
13
14
  let wrapper;
14
-
15
15
  const findModal = () => wrapper.findComponent(GlModal);
16
16
  const findOptions = () => wrapper.findComponent('[data-testid="feedback-options"]');
17
17
  const findOptionsCheckboxes = () => findOptions().findAllComponents(GlFormCheckbox);
@@ -29,26 +29,33 @@ describe('FeedbackModal', () => {
29
29
  GlModal,
30
30
  GlFormCheckboxGroup,
31
31
  },
32
+ provide: options.injections,
32
33
  });
33
34
  };
34
35
 
35
- beforeEach(() => {
36
- createComponent();
37
- });
36
+ describe('inputs', () => {
37
+ beforeEach(() => {
38
+ createComponent();
39
+ });
38
40
 
39
- it('renders the feedback options', () => {
40
- const checkboxes = findOptionsCheckboxes();
41
- feedbackOptions.forEach((option, index) => {
42
- expect(checkboxes.at(index).text()).toBe(option.text);
43
- expect(checkboxes.at(index).attributes('value')).toBe(option.value);
41
+ it('renders the feedback options', () => {
42
+ const checkboxes = findOptionsCheckboxes();
43
+ feedbackOptions.forEach((option, index) => {
44
+ expect(checkboxes.at(index).text()).toBe(option.text);
45
+ expect(checkboxes.at(index).attributes('value')).toBe(option.value);
46
+ });
44
47
  });
45
- });
46
48
 
47
- it('renders the textarea field for additional feedback', () => {
48
- expect(findTextarea().exists()).toBe(true);
49
+ it('renders the textarea field for additional feedback', () => {
50
+ expect(findTextarea().exists()).toBe(true);
51
+ });
49
52
  });
50
53
 
51
54
  describe('interaction', () => {
55
+ beforeEach(() => {
56
+ createComponent();
57
+ });
58
+
52
59
  it('emits the feedback event when the submit button is clicked', () => {
53
60
  selectOption();
54
61
  findModal().vm.$emit('primary');
@@ -68,6 +75,10 @@ describe('FeedbackModal', () => {
68
75
  });
69
76
 
70
77
  describe('slots', () => {
78
+ beforeEach(() => {
79
+ createComponent();
80
+ });
81
+
71
82
  it('renders the `feedback-extra-fields` slot with default content', () => {
72
83
  expect(wrapper.findComponent(DummyComponent).exists()).toBe(false);
73
84
  expect(findTextarea().exists()).toBe(true);
@@ -78,4 +89,30 @@ describe('FeedbackModal', () => {
78
89
  expect(findTextarea().exists()).toBe(false);
79
90
  });
80
91
  });
92
+
93
+ describe('injections', () => {
94
+ it('should pass modalTitle when set as injection', () => {
95
+ const customTitle = 'Custom Feedback Title';
96
+ createComponent({ injections: { modalTitle: customTitle } });
97
+ expect(findModal().props('title')).toBe(customTitle);
98
+ });
99
+
100
+ it('should pass modalTitle default when injection not set', () => {
101
+ createComponent();
102
+ expect(findModal().props('title')).toBe('Give feedback on GitLab Duo');
103
+ });
104
+
105
+ it('should pass modalAlert when set as injection', () => {
106
+ const customAlert = 'Custom Alert Message';
107
+ createComponent({ injections: { modalAlert: customAlert } });
108
+ expect(wrapper.findComponent(GlAlert).text()).toBe(customAlert);
109
+ });
110
+
111
+ it('should render modalAlert default when injection not set', () => {
112
+ createComponent();
113
+ expect(wrapper.findComponent(GlAlert).text()).toBe(
114
+ 'GitLab team members cannot see the AI content. Please be as descriptive as possible.'
115
+ );
116
+ });
117
+ });
81
118
  });
@@ -1,53 +1,61 @@
1
1
  <script>
2
2
  import GlModal from '../../../base/modal/modal.vue';
3
+ import GlAlert from '../../../base/alert/alert.vue';
3
4
  import GlFormGroup from '../../../base/form/form_group/form_group.vue';
4
5
  import GlFormTextarea from '../../../base/form/form_textarea/form_textarea.vue';
5
6
  import GlFormCheckboxGroup from '../../../base/form/form_checkbox/form_checkbox_group.vue';
6
7
 
7
8
  export const i18n = {
8
- MODAL_TITLE: 'Give feedback on AI content',
9
- MODAL_DESCRIPTION:
10
- 'To help improve the quality of the content, send your feedback to GitLab team members.',
11
- MODAL_OPTIONS_LABEL: 'How was the AI content?',
12
- MODAL_MORE_LABEL: 'More information',
13
- MODAL_MORE_PLACEHOLDER: 'How could the content be improved?',
14
- MODAL_FEEDBACK_OPTIONS: {
15
- helpful: 'Helpful',
16
- unhelpful: 'Unhelpful or irrelevant',
17
- incorrect: 'Factually incorrect',
18
- long: 'Too long',
19
- abuse: 'Abusive or offensive',
20
- other: 'Something else',
21
- },
22
- MODAL_ACTIONS: {
23
- submit: 'Submit',
24
- cancel: 'Cancel',
9
+ MODAL: {
10
+ TITLE: 'Give feedback on GitLab Duo',
11
+ DESCRIPTION: 'To help improve GitLab Duo, send your feeback to GitLab team members.',
12
+ ALERT: 'GitLab team members cannot see the AI content. Please be as descriptive as possible.',
13
+ OPTIONS_LABEL: 'How could the AI content be improved?',
14
+ SITUATION_DESCRIPTION_LABEL: 'What were you doing?',
15
+ SITUATION_DESCRIPTION_PLACEHOLDER:
16
+ 'The situation in which you interacted with GitLab Duo Chat.',
17
+ IMPROVEMENT_SUGGESTION_LABEL: 'How could the response be improved?',
18
+ IMPROVEMENT_SUGGESTION_PLACEHOLDER: 'How the response might better meet your needs.',
19
+ MORE_LABEL: 'More information',
20
+ MORE_PLACEHOLDER: 'How could the content be improved?',
21
+ FEEDBACK_OPTIONS: {
22
+ helpful: 'Helpful',
23
+ unhelpful: 'Unhelpful or irrelevant',
24
+ incorrect: 'Factually incorrect',
25
+ long: 'Too long',
26
+ abuse: 'Abusive or offensive',
27
+ other: 'Something else',
28
+ },
29
+ ACTIONS: {
30
+ submit: 'Submit',
31
+ cancel: 'Cancel',
32
+ },
25
33
  },
26
34
  };
27
35
 
28
36
  export const feedbackOptions = [
29
37
  {
30
- text: i18n.MODAL_FEEDBACK_OPTIONS.helpful,
38
+ text: i18n.MODAL.FEEDBACK_OPTIONS.helpful,
31
39
  value: 'helpful',
32
40
  },
33
41
  {
34
- text: i18n.MODAL_FEEDBACK_OPTIONS.unhelpful,
42
+ text: i18n.MODAL.FEEDBACK_OPTIONS.unhelpful,
35
43
  value: 'unhelpful',
36
44
  },
37
45
  {
38
- text: i18n.MODAL_FEEDBACK_OPTIONS.incorrect,
46
+ text: i18n.MODAL.FEEDBACK_OPTIONS.incorrect,
39
47
  value: 'incorrect',
40
48
  },
41
49
  {
42
- text: i18n.MODAL_FEEDBACK_OPTIONS.long,
50
+ text: i18n.MODAL.FEEDBACK_OPTIONS.long,
43
51
  value: 'long',
44
52
  },
45
53
  {
46
- text: i18n.MODAL_FEEDBACK_OPTIONS.abuse,
54
+ text: i18n.MODAL.FEEDBACK_OPTIONS.abuse,
47
55
  value: 'abuse',
48
56
  },
49
57
  {
50
- text: i18n.MODAL_FEEDBACK_OPTIONS.other,
58
+ text: i18n.MODAL.FEEDBACK_OPTIONS.other,
51
59
  value: 'other',
52
60
  },
53
61
  ];
@@ -56,10 +64,19 @@ export default {
56
64
  name: 'DuoChatFeedbackModal',
57
65
  components: {
58
66
  GlModal,
67
+ GlAlert,
59
68
  GlFormCheckboxGroup,
60
69
  GlFormGroup,
61
70
  GlFormTextarea,
62
71
  },
72
+ inject: {
73
+ modalTitle: {
74
+ default: i18n.MODAL.TITLE,
75
+ },
76
+ modalAlert: {
77
+ default: i18n.MODAL.ALERT,
78
+ },
79
+ },
63
80
  data() {
64
81
  return {
65
82
  selectedFeedbackOptions: [],
@@ -84,10 +101,10 @@ export default {
84
101
  },
85
102
  actions: {
86
103
  primary: {
87
- text: i18n.MODAL_ACTIONS.submit,
104
+ text: i18n.MODAL.ACTIONS.submit,
88
105
  },
89
106
  cancel: {
90
- text: i18n.MODAL_ACTIONS.cancel,
107
+ text: i18n.MODAL.ACTIONS.cancel,
91
108
  },
92
109
  },
93
110
  feedbackOptions,
@@ -98,7 +115,7 @@ export default {
98
115
  <gl-modal
99
116
  ref="feedbackModal"
100
117
  modal-id="feedbackModal"
101
- :title="$options.i18n.MODAL_TITLE"
118
+ :title="modalTitle"
102
119
  :action-primary="$options.actions.primary"
103
120
  :action-cancel="$options.actions.cancel"
104
121
  :visible="false"
@@ -106,9 +123,9 @@ export default {
106
123
  @primary="onFeedbackSubmit"
107
124
  @canceled="onFeedbackCanceled"
108
125
  >
109
- <p>{{ $options.i18n.MODAL_DESCRIPTION }}</p>
126
+ <p>{{ $options.i18n.MODAL.DESCRIPTION }}</p>
110
127
  <gl-form-group
111
- :label="$options.i18n.MODAL_OPTIONS_LABEL"
128
+ :label="$options.i18n.MODAL.OPTIONS_LABEL"
112
129
  :optional="false"
113
130
  data-testid="feedback-options"
114
131
  >
@@ -117,13 +134,13 @@ export default {
117
134
  :options="$options.feedbackOptions"
118
135
  />
119
136
  </gl-form-group>
120
-
137
+ <gl-alert class="gl-mb-5" :dismissible="false">{{ modalAlert }}</gl-alert>
121
138
  <!-- @slot The addition Feedback form fields. -->
122
139
  <slot name="feedback-extra-fields">
123
- <gl-form-group :label="$options.i18n.MODAL_MORE_LABEL" optional>
140
+ <gl-form-group :label="$options.i18n.MODAL.MORE_LABEL" optional>
124
141
  <gl-form-textarea
125
142
  v-model="extendedFeedback"
126
- :placeholder="$options.i18n.MODAL_MORE_PLACEHOLDER"
143
+ :placeholder="$options.i18n.MODAL.MORE_PLACEHOLDER"
127
144
  />
128
145
  </gl-form-group>
129
146
  </slot>