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 {
linkedIssueTypesMap,
addRelatedIssueErrorMap,
addRelatedItemErrorMap,
issuablesFormCategoryHeaderTextMap,
issuablesFormInputTextMap,
} from '../constants';
import RelatedIssuableInput from './related_issuable_input.vue';
......@@ -134,6 +136,12 @@ export default {
epics: mergeUrlParams({ confidential_only: true }, this.autoCompleteSources.epics),
};
},
issuableCategoryHeaderText() {
return issuablesFormCategoryHeaderTextMap[this.issuableType];
},
issuableInputText() {
return issuablesFormInputTextMap[this.issuableType];
},
},
methods: {
onPendingIssuableRemoveRequest(params) {
......@@ -162,7 +170,7 @@ export default {
<form @submit.prevent="onFormSubmit">
<template v-if="showCategorizedIssues">
<gl-form-group
:label="__('The current issue')"
:label="issuableCategoryHeaderText"
label-for="linked-issue-type-radio"
label-class="label-bold"
class="mb-2"
......@@ -175,7 +183,7 @@ export default {
/>
</gl-form-group>
<p class="bold">
{{ __('the following issue(s)') }}
{{ issuableInputText }}
</p>
</template>
<related-issuable-input
......
......@@ -5,6 +5,9 @@ import {
issuableQaClassMap,
linkedIssueTypesMap,
linkedIssueTypesTextMap,
issuablesBlockHeaderTextMap,
issuablesBlockHelpTextMap,
issuablesBlockAddButtonTextMap,
} from '../constants';
import AddIssuableForm from './add_issuable_form.vue';
import RelatedIssuesList from './related_issues_list.vue';
......@@ -105,6 +108,15 @@ export default {
hasBody() {
return this.isFormVisible || this.shouldShowTokenBody;
},
headerText() {
return issuablesBlockHeaderTextMap[this.issuableType];
},
helpLinkText() {
return issuablesBlockHelpTextMap[this.issuableType];
},
addIssuableButtonText() {
return issuablesBlockAddButtonTextMap[this.issuableType];
},
badgeLabel() {
return this.isFetching && this.relatedIssues.length === 0 ? '...' : this.relatedIssues.length;
},
......@@ -138,13 +150,14 @@ export default {
href="#related-issues"
aria-hidden="true"
/>
<slot name="header-text">{{ __('Linked issues') }}</slot>
<slot name="header-text">{{ headerText }}</slot>
<gl-link
v-if="hasHelpPath"
:href="helpPath"
target="_blank"
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-link>
......@@ -160,7 +173,7 @@ export default {
v-if="canAdmin"
data-qa-selector="related_issues_plus_button"
icon="plus"
:aria-label="__('Add a related issue')"
:aria-label="addIssuableButtonText"
:class="qaClass"
@click="$emit('toggleAddRelatedIssuesForm', $event)"
/>
......
......@@ -104,3 +104,28 @@ export const PathIdSeparator = {
Epic: '&',
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() {
// eslint-disable-next-line no-new
new Vue({
el: relatedIssuesRootElement,
name: 'RelatedIssuesApp',
components: {
relatedIssuesRoot: RelatedIssuesRoot,
},
......
......@@ -2091,6 +2091,9 @@ msgstr ""
msgid "Add a numbered list"
msgstr ""
msgid "Add a related epic"
msgstr ""
msgid "Add a related issue"
msgstr ""
......@@ -21755,6 +21758,9 @@ msgstr ""
msgid "Linked emails (%{email_count})"
msgstr ""
msgid "Linked epics"
msgstr ""
msgid "Linked issues"
msgstr ""
......@@ -29685,6 +29691,9 @@ msgstr ""
msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
msgstr ""
msgid "Read more about related epics"
msgstr ""
msgid "Read more about related issues"
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."
msgstr ""
msgid "The current epic"
msgstr ""
msgid "The current issue"
msgstr ""
......@@ -44006,6 +44018,9 @@ msgstr ""
msgid "the file"
msgstr ""
msgid "the following epic(s)"
msgstr ""
msgid "the following issue(s)"
msgstr ""
......
import { GlFormGroup } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import AddIssuableForm from '~/related_issues/components/add_issuable_form.vue';
......@@ -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', () => {
beforeEach(() => {
wrapper = mount(AddIssuableForm, {
......
......@@ -7,6 +7,7 @@ import {
} from 'jest/issuable/components/related_issuable_mock_data';
import RelatedIssuesBlock from '~/related_issues/components/related_issues_block.vue';
import {
issuableTypesMap,
linkedIssueTypesMap,
linkedIssueTypesTextMap,
PathIdSeparator,
......@@ -29,15 +30,35 @@ describe('RelatedIssuesBlock', () => {
wrapper = mount(RelatedIssuesBlock, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'issue',
issuableType: issuableTypesMap.ISSUE,
},
});
});
it('displays "Linked issues" in the header', () => {
expect(wrapper.find('.card-title').text()).toContain('Linked issues');
it.each`
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', () => {
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