diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 17:34:42 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 17:34:42 +0300 |
commit | 9f46488805e86b1bc341ea1620b866016c2ce5ed (patch) | |
tree | f9748c7e287041e37d6da49e0a29c9511dc34768 /app/assets/javascripts/jira_import | |
parent | dfc92d081ea0332d69c8aca2f0e745cb48ae5e6d (diff) |
Add latest changes from gitlab-org/gitlab@13-0-stable-ee
Diffstat (limited to 'app/assets/javascripts/jira_import')
7 files changed, 139 insertions, 17 deletions
diff --git a/app/assets/javascripts/jira_import/components/jira_import_app.vue b/app/assets/javascripts/jira_import/components/jira_import_app.vue index b71c06e4217..d1570f52c8c 100644 --- a/app/assets/javascripts/jira_import/components/jira_import_app.vue +++ b/app/assets/javascripts/jira_import/components/jira_import_app.vue @@ -1,5 +1,6 @@ <script> -import { GlAlert, GlLoadingIcon } from '@gitlab/ui'; +import { GlAlert, GlLoadingIcon, GlSprintf } from '@gitlab/ui'; +import { last } from 'lodash'; import { __ } from '~/locale'; import getJiraImportDetailsQuery from '../queries/get_jira_import_details.query.graphql'; import initiateJiraImportMutation from '../queries/initiate_jira_import.mutation.graphql'; @@ -13,6 +14,7 @@ export default { components: { GlAlert, GlLoadingIcon, + GlSprintf, JiraImportForm, JiraImportProgress, JiraImportSetup, @@ -30,6 +32,10 @@ export default { type: String, required: true, }, + jiraIntegrationPath: { + type: String, + required: true, + }, jiraProjects: { type: Array, required: true, @@ -47,6 +53,7 @@ export default { return { errorMessage: '', showAlert: false, + selectedProject: undefined, }; }, apollo: { @@ -59,7 +66,7 @@ export default { }, update: ({ project }) => ({ status: project.jiraImportStatus, - import: project.jiraImports.nodes[0], + imports: project.jiraImports.nodes, }), skip() { return !this.isJiraConfigured; @@ -73,6 +80,24 @@ export default { jiraProjectsOptions() { return this.jiraProjects.map(([text, value]) => ({ text, value })); }, + mostRecentImport() { + // The backend returns JiraImports ordered by created_at asc in app/models/project.rb + return last(this.jiraImportDetails?.imports); + }, + numberOfPreviousImportsForProject() { + return this.jiraImportDetails?.imports?.reduce?.( + (acc, jiraProject) => (jiraProject.jiraProjectKey === this.selectedProject ? acc + 1 : acc), + 0, + ); + }, + importLabel() { + return this.selectedProject + ? `jira-import::${this.selectedProject}-${this.numberOfPreviousImportsForProject + 1}` + : 'jira-import::KEY-1'; + }, + hasPreviousImports() { + return this.numberOfPreviousImportsForProject > 0; + }, }, methods: { dismissAlert() { @@ -93,6 +118,13 @@ export default { return; } + const cacheData = store.readQuery({ + query: getJiraImportDetailsQuery, + variables: { + fullPath: this.projectPath, + }, + }); + store.writeQuery({ query: getJiraImportDetailsQuery, variables: { @@ -102,7 +134,10 @@ export default { project: { jiraImportStatus: IMPORT_STATE.SCHEDULED, jiraImports: { - nodes: [data.jiraImportStart.jiraImport], + nodes: [ + ...cacheData.project.jiraImports.nodes, + data.jiraImportStart.jiraImport, + ], __typename: 'JiraImportConnection', }, // eslint-disable-next-line @gitlab/require-i18n-strings @@ -115,6 +150,8 @@ export default { .then(({ data }) => { if (data.jiraImportStart.errors.length) { this.setAlertMessage(data.jiraImportStart.errors.join('. ')); + } else { + this.selectedProject = undefined; } }) .catch(() => this.setAlertMessage(__('There was an error importing the Jira project.'))); @@ -132,19 +169,38 @@ export default { <gl-alert v-if="showAlert" variant="danger" @dismiss="dismissAlert"> {{ errorMessage }} </gl-alert> + <gl-alert v-if="hasPreviousImports" variant="warning" :dismissible="false"> + <gl-sprintf + :message=" + __( + 'You have imported from this project %{numberOfPreviousImportsForProject} times before. Each new import will create duplicate issues.', + ) + " + > + <template #numberOfPreviousImportsForProject>{{ + numberOfPreviousImportsForProject + }}</template> + </gl-sprintf> + </gl-alert> - <jira-import-setup v-if="!isJiraConfigured" :illustration="setupIllustration" /> + <jira-import-setup + v-if="!isJiraConfigured" + :illustration="setupIllustration" + :jira-integration-path="jiraIntegrationPath" + /> <gl-loading-icon v-else-if="$apollo.loading" size="md" class="mt-3" /> <jira-import-progress v-else-if="isImportInProgress" :illustration="inProgressIllustration" - :import-initiator="jiraImportDetails.import.scheduledBy.name" - :import-project="jiraImportDetails.import.jiraProjectKey" - :import-time="jiraImportDetails.import.scheduledAt" + :import-initiator="mostRecentImport.scheduledBy.name" + :import-project="mostRecentImport.jiraProjectKey" + :import-time="mostRecentImport.scheduledAt" :issues-path="issuesPath" /> <jira-import-form v-else + v-model="selectedProject" + :import-label="importLabel" :issues-path="issuesPath" :jira-projects="jiraProjectsOptions" @initiateJiraImport="initiateJiraImport" diff --git a/app/assets/javascripts/jira_import/components/jira_import_form.vue b/app/assets/javascripts/jira_import/components/jira_import_form.vue index 0146f564260..c2fe7b29c28 100644 --- a/app/assets/javascripts/jira_import/components/jira_import_form.vue +++ b/app/assets/javascripts/jira_import/components/jira_import_form.vue @@ -13,6 +13,10 @@ export default { currentUserAvatarUrl: gon.current_user_avatar_url, currentUsername: gon.current_username, props: { + importLabel: { + type: String, + required: true, + }, issuesPath: { type: String, required: true, @@ -21,21 +25,25 @@ export default { type: Array, required: true, }, + value: { + type: String, + required: false, + default: undefined, + }, }, data() { return { - selectedOption: null, selectState: null, }; }, methods: { initiateJiraImport(event) { event.preventDefault(); - if (!this.selectedOption) { - this.showValidationError(); - } else { + if (this.value) { this.hideValidationError(); - this.$emit('initiateJiraImport', this.selectedOption); + this.$emit('initiateJiraImport', this.value); + } else { + this.showValidationError(); } }, hideValidationError() { @@ -62,10 +70,11 @@ export default { > <gl-form-select id="jira-project-select" - v-model="selectedOption" class="mb-2" :options="jiraProjects" :state="selectState" + :value="value" + @change="$emit('input', $event)" /> </gl-form-group> @@ -79,7 +88,7 @@ export default { id="jira-project-label" class="mb-2" background-color="#428BCA" - title="jira-import::KEY-1" + :title="importLabel" scoped /> </gl-form-group> diff --git a/app/assets/javascripts/jira_import/components/jira_import_progress.vue b/app/assets/javascripts/jira_import/components/jira_import_progress.vue index 2d610224658..78f10decd31 100644 --- a/app/assets/javascripts/jira_import/components/jira_import_progress.vue +++ b/app/assets/javascripts/jira_import/components/jira_import_progress.vue @@ -46,6 +46,9 @@ export default { importTime: formatDate(this.importTime), }); }, + issuesLink() { + return `${this.issuesPath}?search=${this.importProject}`; + }, }, }; </script> @@ -55,7 +58,7 @@ export default { :svg-path="illustration" :title="__('Import in progress')" :primary-button-text="__('View issues')" - :primary-button-link="issuesPath" + :primary-button-link="issuesLink" > <template #description> <p class="mb-0">{{ importInitiatorText }}</p> diff --git a/app/assets/javascripts/jira_import/components/jira_import_setup.vue b/app/assets/javascripts/jira_import/components/jira_import_setup.vue index 44773a773d5..285c5c815ac 100644 --- a/app/assets/javascripts/jira_import/components/jira_import_setup.vue +++ b/app/assets/javascripts/jira_import/components/jira_import_setup.vue @@ -11,6 +11,10 @@ export default { type: String, required: true, }, + jiraIntegrationPath: { + type: String, + required: true, + }, }, }; </script> @@ -21,6 +25,6 @@ export default { title="" :description="__('You will first need to set up Jira Integration to use this feature.')" :primary-button-text="__('Set up Jira Integration')" - primary-button-link="../services/jira/edit" + :primary-button-link="jiraIntegrationPath" /> </template> diff --git a/app/assets/javascripts/jira_import/index.js b/app/assets/javascripts/jira_import/index.js index 8bd70e4e277..b576668fe7c 100644 --- a/app/assets/javascripts/jira_import/index.js +++ b/app/assets/javascripts/jira_import/index.js @@ -27,6 +27,7 @@ export default function mountJiraImportApp() { inProgressIllustration: el.dataset.inProgressIllustration, isJiraConfigured: parseBoolean(el.dataset.isJiraConfigured), issuesPath: el.dataset.issuesPath, + jiraIntegrationPath: el.dataset.jiraIntegrationPath, jiraProjects: el.dataset.jiraProjects ? JSON.parse(el.dataset.jiraProjects) : [], projectPath: el.dataset.projectPath, setupIllustration: el.dataset.setupIllustration, diff --git a/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql b/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql index 0eaaad580fc..aa8d03c7f17 100644 --- a/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql +++ b/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql @@ -3,7 +3,7 @@ query($fullPath: ID!) { project(fullPath: $fullPath) { jiraImportStatus - jiraImports(last: 1) { + jiraImports { nodes { ...JiraImport } diff --git a/app/assets/javascripts/jira_import/utils.js b/app/assets/javascripts/jira_import/utils.js index 504cf19e44e..aa10dfc8099 100644 --- a/app/assets/javascripts/jira_import/utils.js +++ b/app/assets/javascripts/jira_import/utils.js @@ -1,3 +1,5 @@ +import { last } from 'lodash'; + export const IMPORT_STATE = { FAILED: 'failed', FINISHED: 'finished', @@ -8,3 +10,50 @@ export const IMPORT_STATE = { export const isInProgress = state => state === IMPORT_STATE.SCHEDULED || state === IMPORT_STATE.STARTED; + +export const isFinished = state => state === IMPORT_STATE.FINISHED; + +/** + * Calculates the label title for the most recent Jira import. + * + * @param {Object[]} jiraImports - List of Jira imports + * @param {string} jiraImports[].jiraProjectKey - Jira project key + * @returns {string} - A label title + */ +const calculateJiraImportLabelTitle = jiraImports => { + const mostRecentJiraProjectKey = last(jiraImports)?.jiraProjectKey; + const jiraProjectImportCount = jiraImports.filter( + jiraImport => jiraImport.jiraProjectKey === mostRecentJiraProjectKey, + ).length; + return `jira-import::${mostRecentJiraProjectKey}-${jiraProjectImportCount}`; +}; + +/** + * Finds the label color from a list of labels. + * + * @param {string} labelTitle - Label title + * @param {Object[]} labels - List of labels + * @param {string} labels[].title - Label title + * @param {string} labels[].color - Label color + * @returns {string} - The label color associated with the given labelTitle + */ +const calculateJiraImportLabelColor = (labelTitle, labels) => + labels.find(label => label.title === labelTitle)?.color; + +/** + * Calculates the label for the most recent Jira import. + * + * @param {Object[]} jiraImports - List of Jira imports + * @param {string} jiraImports[].jiraProjectKey - Jira project key + * @param {Object[]} labels - List of labels + * @param {string} labels[].title - Label title + * @param {string} labels[].color - Label color + * @returns {{color: string, title: string}} - A label object containing a label color and title + */ +export const calculateJiraImportLabel = (jiraImports, labels) => { + const title = calculateJiraImportLabelTitle(jiraImports); + return { + color: calculateJiraImportLabelColor(title, labels), + title, + }; +}; |