Commit cea40926 authored by Olena Horal-Koretska's avatar Olena Horal-Koretska

Merge branch '352004-make-related-issues-app-reusable' into 'master'

Update Related Issues app UI text to be context aware

See merge request gitlab-org/gitlab!80288
parents 54d986bc 4143aa47
...@@ -9,6 +9,8 @@ import { ...@@ -9,6 +9,8 @@ import {
linkedIssueTypesMap, linkedIssueTypesMap,
addRelatedIssueErrorMap, addRelatedIssueErrorMap,
addRelatedItemErrorMap, addRelatedItemErrorMap,
issuablesFormCategoryHeaderTextMap,
issuablesFormInputTextMap,
} from '../constants'; } from '../constants';
import RelatedIssuableInput from './related_issuable_input.vue'; import RelatedIssuableInput from './related_issuable_input.vue';
...@@ -134,6 +136,12 @@ export default { ...@@ -134,6 +136,12 @@ export default {
epics: mergeUrlParams({ confidential_only: true }, this.autoCompleteSources.epics), epics: mergeUrlParams({ confidential_only: true }, this.autoCompleteSources.epics),
}; };
}, },
issuableCategoryHeaderText() {
return issuablesFormCategoryHeaderTextMap[this.issuableType];
},
issuableInputText() {
return issuablesFormInputTextMap[this.issuableType];
},
}, },
methods: { methods: {
onPendingIssuableRemoveRequest(params) { onPendingIssuableRemoveRequest(params) {
...@@ -162,7 +170,7 @@ export default { ...@@ -162,7 +170,7 @@ export default {
<form @submit.prevent="onFormSubmit"> <form @submit.prevent="onFormSubmit">
<template v-if="showCategorizedIssues"> <template v-if="showCategorizedIssues">
<gl-form-group <gl-form-group
:label="__('The current issue')" :label="issuableCategoryHeaderText"
label-for="linked-issue-type-radio" label-for="linked-issue-type-radio"
label-class="label-bold" label-class="label-bold"
class="mb-2" class="mb-2"
...@@ -175,7 +183,7 @@ export default { ...@@ -175,7 +183,7 @@ export default {
/> />
</gl-form-group> </gl-form-group>
<p class="bold"> <p class="bold">
{{ __('the following issue(s)') }} {{ issuableInputText }}
</p> </p>
</template> </template>
<related-issuable-input <related-issuable-input
......
...@@ -5,6 +5,9 @@ import { ...@@ -5,6 +5,9 @@ import {
issuableQaClassMap, issuableQaClassMap,
linkedIssueTypesMap, linkedIssueTypesMap,
linkedIssueTypesTextMap, linkedIssueTypesTextMap,
issuablesBlockHeaderTextMap,
issuablesBlockHelpTextMap,
issuablesBlockAddButtonTextMap,
} from '../constants'; } from '../constants';
import AddIssuableForm from './add_issuable_form.vue'; import AddIssuableForm from './add_issuable_form.vue';
import RelatedIssuesList from './related_issues_list.vue'; import RelatedIssuesList from './related_issues_list.vue';
...@@ -105,6 +108,15 @@ export default { ...@@ -105,6 +108,15 @@ export default {
hasBody() { hasBody() {
return this.isFormVisible || this.shouldShowTokenBody; return this.isFormVisible || this.shouldShowTokenBody;
}, },
headerText() {
return issuablesBlockHeaderTextMap[this.issuableType];
},
helpLinkText() {
return issuablesBlockHelpTextMap[this.issuableType];
},
addIssuableButtonText() {
return issuablesBlockAddButtonTextMap[this.issuableType];
},
badgeLabel() { badgeLabel() {
return this.isFetching && this.relatedIssues.length === 0 ? '...' : this.relatedIssues.length; return this.isFetching && this.relatedIssues.length === 0 ? '...' : this.relatedIssues.length;
}, },
...@@ -138,13 +150,14 @@ export default { ...@@ -138,13 +150,14 @@ export default {
href="#related-issues" href="#related-issues"
aria-hidden="true" aria-hidden="true"
/> />
<slot name="header-text">{{ __('Linked issues') }}</slot> <slot name="header-text">{{ headerText }}</slot>
<gl-link <gl-link
v-if="hasHelpPath" v-if="hasHelpPath"
:href="helpPath" :href="helpPath"
target="_blank" target="_blank"
class="gl-display-flex gl-align-items-center gl-ml-2 gl-text-gray-500" class="gl-display-flex gl-align-items-center gl-ml-2 gl-text-gray-500"
:aria-label="__('Read more about related issues')" data-testid="help-link"
:aria-label="helpLinkText"
> >
<gl-icon name="question" :size="12" /> <gl-icon name="question" :size="12" />
</gl-link> </gl-link>
...@@ -160,7 +173,7 @@ export default { ...@@ -160,7 +173,7 @@ export default {
v-if="canAdmin" v-if="canAdmin"
data-qa-selector="related_issues_plus_button" data-qa-selector="related_issues_plus_button"
icon="plus" icon="plus"
:aria-label="__('Add a related issue')" :aria-label="addIssuableButtonText"
:class="qaClass" :class="qaClass"
@click="$emit('toggleAddRelatedIssuesForm', $event)" @click="$emit('toggleAddRelatedIssuesForm', $event)"
/> />
......
...@@ -104,3 +104,28 @@ export const PathIdSeparator = { ...@@ -104,3 +104,28 @@ export const PathIdSeparator = {
Epic: '&', Epic: '&',
Issue: '#', Issue: '#',
}; };
export const issuablesBlockHeaderTextMap = {
[issuableTypesMap.ISSUE]: __('Linked issues'),
[issuableTypesMap.EPIC]: __('Linked epics'),
};
export const issuablesBlockHelpTextMap = {
[issuableTypesMap.ISSUE]: __('Read more about related issues'),
[issuableTypesMap.EPIC]: __('Read more about related epics'),
};
export const issuablesBlockAddButtonTextMap = {
[issuableTypesMap.ISSUE]: __('Add a related issue'),
[issuableTypesMap.EPIC]: __('Add a related epic'),
};
export const issuablesFormCategoryHeaderTextMap = {
[issuableTypesMap.ISSUE]: __('The current issue'),
[issuableTypesMap.EPIC]: __('The current epic'),
};
export const issuablesFormInputTextMap = {
[issuableTypesMap.ISSUE]: __('the following issue(s)'),
[issuableTypesMap.EPIC]: __('the following epic(s)'),
};
...@@ -8,6 +8,7 @@ export default function initRelatedIssues() { ...@@ -8,6 +8,7 @@ export default function initRelatedIssues() {
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
new Vue({ new Vue({
el: relatedIssuesRootElement, el: relatedIssuesRootElement,
name: 'RelatedIssuesApp',
components: { components: {
relatedIssuesRoot: RelatedIssuesRoot, relatedIssuesRoot: RelatedIssuesRoot,
}, },
......
...@@ -2091,6 +2091,9 @@ msgstr "" ...@@ -2091,6 +2091,9 @@ msgstr ""
msgid "Add a numbered list" msgid "Add a numbered list"
msgstr "" msgstr ""
msgid "Add a related epic"
msgstr ""
msgid "Add a related issue" msgid "Add a related issue"
msgstr "" msgstr ""
...@@ -21755,6 +21758,9 @@ msgstr "" ...@@ -21755,6 +21758,9 @@ msgstr ""
msgid "Linked emails (%{email_count})" msgid "Linked emails (%{email_count})"
msgstr "" msgstr ""
msgid "Linked epics"
msgstr ""
msgid "Linked issues" msgid "Linked issues"
msgstr "" msgstr ""
...@@ -29685,6 +29691,9 @@ msgstr "" ...@@ -29685,6 +29691,9 @@ msgstr ""
msgid "Read more about project permissions %{help_link_open}here%{help_link_close}" msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
msgstr "" msgstr ""
msgid "Read more about related epics"
msgstr ""
msgid "Read more about related issues" msgid "Read more about related issues"
msgstr "" msgstr ""
...@@ -36091,6 +36100,9 @@ msgstr "" ...@@ -36091,6 +36100,9 @@ msgstr ""
msgid "The contents of this group, its subgroups and projects will be permanently removed after %{deletion_adjourned_period} days on %{date}. After this point, your data cannot be recovered." msgid "The contents of this group, its subgroups and projects will be permanently removed after %{deletion_adjourned_period} days on %{date}. After this point, your data cannot be recovered."
msgstr "" msgstr ""
msgid "The current epic"
msgstr ""
msgid "The current issue" msgid "The current issue"
msgstr "" msgstr ""
...@@ -44006,6 +44018,9 @@ msgstr "" ...@@ -44006,6 +44018,9 @@ msgstr ""
msgid "the file" msgid "the file"
msgstr "" msgstr ""
msgid "the following epic(s)"
msgstr ""
msgid "the following issue(s)" msgid "the following issue(s)"
msgstr "" msgstr ""
......
import { GlFormGroup } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils'; import { mount, shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import AddIssuableForm from '~/related_issues/components/add_issuable_form.vue'; import AddIssuableForm from '~/related_issues/components/add_issuable_form.vue';
...@@ -153,6 +154,30 @@ describe('AddIssuableForm', () => { ...@@ -153,6 +154,30 @@ describe('AddIssuableForm', () => {
}); });
}); });
describe('categorized issuables', () => {
it.each`
issuableType | pathIdSeparator | contextHeader | contextFooter
${issuableTypesMap.ISSUE} | ${PathIdSeparator.Issue} | ${'The current issue'} | ${'the following issue(s)'}
${issuableTypesMap.EPIC} | ${PathIdSeparator.Epic} | ${'The current epic'} | ${'the following epic(s)'}
`(
'show header text as "$contextHeader" and footer text as "$contextFooter" issuableType is set to $issuableType',
({ issuableType, contextHeader, contextFooter }) => {
wrapper = shallowMount(AddIssuableForm, {
propsData: {
issuableType,
inputValue: '',
showCategorizedIssues: true,
pathIdSeparator,
pendingReferences: [],
},
});
expect(wrapper.findComponent(GlFormGroup).attributes('label')).toBe(contextHeader);
expect(wrapper.find('p.bold').text()).toContain(contextFooter);
},
);
});
describe('when it is a Linked Issues form', () => { describe('when it is a Linked Issues form', () => {
beforeEach(() => { beforeEach(() => {
wrapper = mount(AddIssuableForm, { wrapper = mount(AddIssuableForm, {
......
...@@ -7,6 +7,7 @@ import { ...@@ -7,6 +7,7 @@ import {
} from 'jest/issuable/components/related_issuable_mock_data'; } from 'jest/issuable/components/related_issuable_mock_data';
import RelatedIssuesBlock from '~/related_issues/components/related_issues_block.vue'; import RelatedIssuesBlock from '~/related_issues/components/related_issues_block.vue';
import { import {
issuableTypesMap,
linkedIssueTypesMap, linkedIssueTypesMap,
linkedIssueTypesTextMap, linkedIssueTypesTextMap,
PathIdSeparator, PathIdSeparator,
...@@ -29,15 +30,35 @@ describe('RelatedIssuesBlock', () => { ...@@ -29,15 +30,35 @@ describe('RelatedIssuesBlock', () => {
wrapper = mount(RelatedIssuesBlock, { wrapper = mount(RelatedIssuesBlock, {
propsData: { propsData: {
pathIdSeparator: PathIdSeparator.Issue, pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'issue', issuableType: issuableTypesMap.ISSUE,
}, },
}); });
}); });
it('displays "Linked issues" in the header', () => { it.each`
expect(wrapper.find('.card-title').text()).toContain('Linked issues'); issuableType | pathIdSeparator | titleText | helpLinkText | addButtonText
${'issue'} | ${PathIdSeparator.Issue} | ${'Linked issues'} | ${'Read more about related issues'} | ${'Add a related issue'}
${'epic'} | ${PathIdSeparator.Epic} | ${'Linked epics'} | ${'Read more about related epics'} | ${'Add a related epic'}
`(
'displays "$titleText" in the header, "$helpLinkText" aria-label for help link, and "$addButtonText" aria-label for add button when issuableType is set to "$issuableType"',
({ issuableType, pathIdSeparator, titleText, helpLinkText, addButtonText }) => {
wrapper = mount(RelatedIssuesBlock, {
propsData: {
pathIdSeparator,
issuableType,
canAdmin: true,
helpPath: '/help/user/project/issues/related_issues',
},
}); });
expect(wrapper.find('.card-title').text()).toContain(titleText);
expect(wrapper.find('[data-testid="help-link"]').attributes('aria-label')).toBe(
helpLinkText,
);
expect(findIssueCountBadgeAddButton().attributes('aria-label')).toBe(addButtonText);
},
);
it('unable to add new related issues', () => { it('unable to add new related issues', () => {
expect(findIssueCountBadgeAddButton().exists()).toBe(false); expect(findIssueCountBadgeAddButton().exists()).toBe(false);
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment