Commit d78ce4a0 authored by Coung Ngo's avatar Coung Ngo Committed by Natalia Tepluhina

Add alert on issues page to show Jira import is in progress

Show Jira import is in progress to give the user indication
of the state of the import
parent 1d1c40f9
<script>
import { GlAlert } from '@gitlab/ui';
import getJiraImportDetailsQuery from '~/jira_import/queries/get_jira_import_details.query.graphql';
import { isInProgress } from '~/jira_import/utils';
export default {
name: 'IssuableListRoot',
components: {
GlAlert,
},
props: {
canEdit: {
type: Boolean,
required: true,
},
isJiraConfigured: {
type: Boolean,
required: true,
},
projectPath: {
type: String,
required: true,
},
},
data() {
return {
isAlertShowing: true,
};
},
apollo: {
jiraImport: {
query: getJiraImportDetailsQuery,
variables() {
return {
fullPath: this.projectPath,
};
},
update: ({ project }) => ({
isInProgress: isInProgress(project.jiraImportStatus),
}),
skip() {
return !this.isJiraConfigured || !this.canEdit;
},
},
},
computed: {
shouldShowAlert() {
return this.isAlertShowing && this.jiraImport?.isInProgress;
},
},
methods: {
hideAlert() {
this.isAlertShowing = false;
},
},
};
</script>
<template>
<gl-alert v-if="shouldShowAlert" @dismiss="hideAlert">
{{ __('Import in progress. Refresh page to see newly added issues.') }}
</gl-alert>
</template>
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
import IssuableListRootApp from './components/issuable_list_root_app.vue';
import IssuablesListApp from './components/issuables_list_app.vue';
export default function initIssuablesList() {
if (!gon.features || !gon.features.vueIssuablesList) {
function mountIssuableListRootApp() {
const el = document.querySelector('.js-projects-issues-root');
if (!el) {
return false;
}
Vue.use(VueApollo);
const defaultClient = createDefaultClient();
const apolloProvider = new VueApollo({
defaultClient,
});
return new Vue({
el,
apolloProvider,
render(createComponent) {
return createComponent(IssuableListRootApp, {
props: {
canEdit: parseBoolean(el.dataset.canEdit),
isJiraConfigured: parseBoolean(el.dataset.isJiraConfigured),
projectPath: el.dataset.projectPath,
},
});
},
});
}
function mountIssuablesListApp() {
if (!gon.features?.vueIssuablesList) {
return;
}
document.querySelectorAll('.js-issuables-list').forEach(el => {
const { canBulkEdit, ...data } = el.dataset;
const props = {
...data,
canBulkEdit: Boolean(canBulkEdit),
};
return new Vue({
el,
render(createElement) {
return createElement(IssuablesListApp, { props });
return createElement(IssuablesListApp, {
props: {
...data,
canBulkEdit: Boolean(canBulkEdit),
},
});
},
});
});
}
export default function initIssuablesList() {
mountIssuableListRootApp();
mountIssuablesListApp();
}
......@@ -7,6 +7,7 @@ import UsersSelect from '~/users_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants';
import { ISSUABLE_INDEX } from '~/pages/projects/constants';
import initIssuablesList from '~/issuables_list';
import initManualOrdering from '~/manual_ordering';
document.addEventListener('DOMContentLoaded', () => {
......@@ -16,9 +17,11 @@ document.addEventListener('DOMContentLoaded', () => {
page: FILTERED_SEARCH.ISSUES,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
});
new IssuableIndex(ISSUABLE_INDEX.ISSUE);
new IssuableIndex(ISSUABLE_INDEX.ISSUE);
new ShortcutsNavigation();
new UsersSelect();
initManualOrdering();
initIssuablesList();
});
......@@ -6,6 +6,11 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@project.name} issues")
- if @project.jira_issues_import_feature_flag_enabled?
.js-projects-issues-root{ data: { can_edit: can?(current_user, :admin_project, @project).to_s,
is_jira_configured: @project.jira_service.present?.to_s,
project_path: @project.full_path } }
- if project_issues(@project).exists?
.top-area
= render 'shared/issuable/nav', type: :issues
......
---
title: Add alert on project issues page to show Jira import is in progress
merge_request: 31329
author:
type: added
......@@ -11250,6 +11250,9 @@ msgstr ""
msgid "Import in progress"
msgstr ""
msgid "Import in progress. Refresh page to see newly added issues."
msgstr ""
msgid "Import issues"
msgstr ""
......
import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import IssuableListRootApp from '~/issuables_list/components/issuable_list_root_app.vue';
const mountComponent = ({
canEdit = true,
isAlertShowing = true,
isInProgress = false,
isJiraConfigured = true,
} = {}) =>
shallowMount(IssuableListRootApp, {
propsData: {
canEdit,
isJiraConfigured,
projectPath: 'gitlab-org/gitlab-test',
},
data() {
return {
isAlertShowing,
jiraImport: {
isInProgress,
},
};
},
});
describe('IssuableListRootApp', () => {
let wrapper;
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('when Jira import is in progress', () => {
it('shows an alert that tells the user a Jira import is in progress', () => {
wrapper = mountComponent({
isInProgress: true,
});
expect(wrapper.find(GlAlert).text()).toBe(
'Import in progress. Refresh page to see newly added issues.',
);
});
});
describe('when Jira import is not in progress', () => {
it('does not show an alert', () => {
wrapper = mountComponent();
expect(wrapper.contains(GlAlert)).toBe(false);
});
});
describe('alert message', () => {
it('is hidden when dismissed', () => {
wrapper = mountComponent({
isInProgress: true,
});
expect(wrapper.contains(GlAlert)).toBe(true);
wrapper.find(GlAlert).vm.$emit('dismiss');
return Vue.nextTick(() => {
expect(wrapper.contains(GlAlert)).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