Commit 08b19204 authored by Phil Hughes's avatar Phil Hughes

Merge branch 'jira-issue-detail-error-state' into 'master'

Jira Issue Detail: Add error and loading state

See merge request gitlab-org/gitlab!56179
parents 579ce053 d51ecaaa
...@@ -346,7 +346,7 @@ export default { ...@@ -346,7 +346,7 @@ export default {
@columnMetricChange="setColumnMetric" @columnMetricChange="setColumnMetric"
@pageChange="setPage" @pageChange="setPage"
/> />
<gl-alert v-if="showMergeRequestTableNoData" variant="info" :dismissable="false"> <gl-alert v-if="showMergeRequestTableNoData" variant="info" :dismissible="false">
{{ __('There is no data available. Please change your selection.') }} {{ __('There is no data available. Please change your selection.') }}
</gl-alert> </gl-alert>
</div> </div>
......
<script> <script>
import { GlAlert, GlSprintf, GlLink, GlBadge, GlTooltipDirective as GlTooltip } from '@gitlab/ui'; import {
GlAlert,
GlSprintf,
GlLink,
GlLoadingIcon,
GlBadge,
GlTooltipDirective as GlTooltip,
} from '@gitlab/ui';
import { fetchIssue } from 'ee/integrations/jira/issues_show/api'; import { fetchIssue } from 'ee/integrations/jira/issues_show/api';
import JiraIssueSidebar from 'ee/integrations/jira/issues_show/components/sidebar/jira_issues_sidebar_root.vue'; import JiraIssueSidebar from 'ee/integrations/jira/issues_show/components/sidebar/jira_issues_sidebar_root.vue';
import { issueStates, issueStateLabels } from 'ee/integrations/jira/issues_show/constants'; import { issueStates, issueStateLabels } from 'ee/integrations/jira/issues_show/constants';
import IssuableShow from '~/issuable_show/components/issuable_show_root.vue'; import IssuableShow from '~/issuable_show/components/issuable_show_root.vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
import Note from './note.vue'; import Note from './note.vue';
export default { export default {
...@@ -14,6 +22,7 @@ export default { ...@@ -14,6 +22,7 @@ export default {
GlSprintf, GlSprintf,
GlLink, GlLink,
GlBadge, GlBadge,
GlLoadingIcon,
IssuableShow, IssuableShow,
JiraIssueSidebar, JiraIssueSidebar,
Note, Note,
...@@ -29,6 +38,7 @@ export default { ...@@ -29,6 +38,7 @@ export default {
data() { data() {
return { return {
isLoading: true, isLoading: true,
errorMessage: null,
issue: {}, issue: {},
}; };
}, },
...@@ -46,13 +56,25 @@ export default { ...@@ -46,13 +56,25 @@ export default {
return this.isIssueOpen ? 'issue-open-m' : 'mobile-issue-close'; return this.isIssueOpen ? 'issue-open-m' : 'mobile-issue-close';
}, },
}, },
async mounted() { mounted() {
this.issue = convertObjectPropsToCamelCase(await fetchIssue(this.issuesShowPath), { this.loadIssue();
deep: true,
});
this.isLoading = false;
}, },
methods: { methods: {
loadIssue() {
fetchIssue(this.issuesShowPath)
.then((issue) => {
this.issue = convertObjectPropsToCamelCase(issue, { deep: true });
})
.catch(() => {
this.errorMessage = s__(
'JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page.',
);
})
.finally(() => {
this.isLoading = false;
});
},
jiraIssueCommentId(id) { jiraIssueCommentId(id) {
return `jira_note_${id}`; return `jira_note_${id}`;
}, },
...@@ -62,6 +84,11 @@ export default { ...@@ -62,6 +84,11 @@ export default {
<template> <template>
<div class="gl-mt-5"> <div class="gl-mt-5">
<gl-loading-icon v-if="isLoading" size="lg" />
<gl-alert v-else-if="errorMessage" variant="danger" :dismissible="false">
{{ errorMessage }}
</gl-alert>
<template v-else>
<gl-alert <gl-alert
variant="info" variant="info"
:dismissible="false" :dismissible="false"
...@@ -82,7 +109,6 @@ export default { ...@@ -82,7 +109,6 @@ export default {
</gl-alert> </gl-alert>
<issuable-show <issuable-show
v-if="!isLoading"
:issuable="issue" :issuable="issue"
:enable-edit="false" :enable-edit="false"
:status-badge-class="statusBadgeClass" :status-badge-class="statusBadgeClass"
...@@ -114,5 +140,6 @@ export default { ...@@ -114,5 +140,6 @@ export default {
</note> </note>
</template> </template>
</issuable-show> </issuable-show>
</template>
</div> </div>
</template> </template>
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import JiraIssuesShow from 'ee/integrations/jira/issues_show/components/jira_issues_show_root.vue'; import JiraIssuesShow from 'ee/integrations/jira/issues_show/components/jira_issues_show_root.vue';
...@@ -14,6 +15,8 @@ describe('JiraIssuesShow', () => { ...@@ -14,6 +15,8 @@ describe('JiraIssuesShow', () => {
let wrapper; let wrapper;
let mockAxios; let mockAxios;
const findGlAlert = () => wrapper.findComponent(GlAlert);
const findGlLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findIssuableShow = () => wrapper.findComponent(IssuableShow); const findIssuableShow = () => wrapper.findComponent(IssuableShow);
const findIssuableShowStatusBadge = () => const findIssuableShowStatusBadge = () =>
wrapper.findComponent(IssuableHeader).find('[data-testid="status"]'); wrapper.findComponent(IssuableHeader).find('[data-testid="status"]');
...@@ -43,13 +46,42 @@ describe('JiraIssuesShow', () => { ...@@ -43,13 +46,42 @@ describe('JiraIssuesShow', () => {
} }
}); });
describe('when issue is loading', () => {
it('renders GlLoadingIcon', () => {
createComponent();
expect(findGlLoadingIcon().exists()).toBe(true);
expect(findGlAlert().exists()).toBe(false);
expect(findIssuableShow().exists()).toBe(false);
});
});
describe('when error occurs during fetch', () => {
it('renders error message', async () => {
mockAxios.onGet(mockJiraIssuesShowPath).replyOnce(500);
createComponent();
await waitForPromises();
const alert = findGlAlert();
expect(findGlLoadingIcon().exists()).toBe(false);
expect(alert.exists()).toBe(true);
expect(alert.text()).toBe(
'Failed to load Jira issue. View the issue in Jira, or reload the page.',
);
expect(alert.props('variant')).toBe('danger');
expect(findIssuableShow().exists()).toBe(false);
});
});
it('renders IssuableShow', async () => { it('renders IssuableShow', async () => {
mockAxios.onGet(mockJiraIssuesShowPath).replyOnce(200, mockJiraIssue); mockAxios.onGet(mockJiraIssuesShowPath).replyOnce(200, mockJiraIssue);
createComponent(); createComponent();
await waitForPromises(); await waitForPromises();
await wrapper.vm.$nextTick();
expect(findGlLoadingIcon().exists()).toBe(false);
expect(findIssuableShow().exists()).toBe(true); expect(findIssuableShow().exists()).toBe(true);
}); });
...@@ -63,7 +95,6 @@ describe('JiraIssuesShow', () => { ...@@ -63,7 +95,6 @@ describe('JiraIssuesShow', () => {
createComponent(); createComponent();
await waitForPromises(); await waitForPromises();
await wrapper.vm.$nextTick();
}); });
it('sets `statusIcon` prop correctly', () => { it('sets `statusIcon` prop correctly', () => {
......
...@@ -17229,6 +17229,9 @@ msgstr "" ...@@ -17229,6 +17229,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled." msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "" msgstr ""
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
msgid "JiraService|Fetch issue types for this Jira project" msgid "JiraService|Fetch issue types for this Jira project"
msgstr "" msgstr ""
......
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