diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-16 21:18:33 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-16 21:18:33 +0300 |
commit | f64a639bcfa1fc2bc89ca7db268f594306edfd7c (patch) | |
tree | a2c3c2ebcc3b45e596949db485d6ed18ffaacfa1 /app/assets/javascripts/issuable | |
parent | bfbc3e0d6583ea1a91f627528bedc3d65ba4b10f (diff) |
Add latest changes from gitlab-org/gitlab@13-10-stable-eev13.10.0-rc40
Diffstat (limited to 'app/assets/javascripts/issuable')
5 files changed, 344 insertions, 0 deletions
diff --git a/app/assets/javascripts/issuable/components/csv_export_modal.vue b/app/assets/javascripts/issuable/components/csv_export_modal.vue new file mode 100644 index 00000000000..78987a5c629 --- /dev/null +++ b/app/assets/javascripts/issuable/components/csv_export_modal.vue @@ -0,0 +1,100 @@ +<script> +import { GlButton, GlModal, GlSprintf, GlIcon } from '@gitlab/ui'; +import { ISSUABLE_TYPE } from '../constants'; + +export default { + name: 'CsvExportModal', + components: { + GlButton, + GlModal, + GlSprintf, + GlIcon, + }, + inject: { + issuableType: { + default: '', + }, + issuableCount: { + default: 0, + }, + email: { + default: '', + }, + exportCsvPath: { + default: '', + }, + }, + props: { + modalId: { + type: String, + required: true, + }, + }, + data() { + return { + // eslint-disable-next-line @gitlab/require-i18n-strings + issuableName: this.issuableType === ISSUABLE_TYPE.issues ? 'issues' : 'merge requests', + }; + }, + issueableType: ISSUABLE_TYPE, +}; +</script> + +<template> + <gl-modal :modal-id="modalId" body-class="gl-p-0!" data-qa-selector="export_issuable_modal"> + <template #modal-title> + <gl-sprintf :message="__('Export %{name}')"> + <template #name>{{ issuableName }}</template> + </gl-sprintf> + </template> + <div + v-if="issuableCount > -1" + data-testid="issuable-count-note" + class="gl-justify-content-start gl-align-items-center gl-p-4 gl-border-b-solid gl-border-1 gl-border-gray-50" + > + <gl-icon name="check" class="gl-color-green-400" /> + <strong class="gl-m-3"> + <gl-sprintf + v-if="issuableType === $options.issueableType.issues" + :message="n__('1 issue selected', '%d issues selected', issuableCount)" + > + <template #issuableCount>{{ issuableCount }}</template> + </gl-sprintf> + <gl-sprintf + v-else + :message="n__('1 merge request selected', '%d merge request selected', issuableCount)" + > + <template #issuableCount>{{ issuableCount }}</template> + </gl-sprintf> + </strong> + </div> + <div class="modal-text gl-px-4 gl-py-5"> + <gl-sprintf + :message=" + __( + `The CSV export will be created in the background. Once finished, it will be sent to %{strongStart}${email}%{strongEnd} in an attachment.`, + ) + " + > + <template #strong="{ content }"> + <strong>{{ content }}</strong> + </template> + </gl-sprintf> + </div> + <template #modal-footer> + <gl-button + category="primary" + variant="confirm" + :href="exportCsvPath" + data-method="post" + :data-qa-selector="`export_${issuableType}_button`" + data-track-event="click_button" + :data-track-label="`export_${issuableType}_csv`" + > + <gl-sprintf :message="__('Export %{name}')"> + <template #name>{{ issuableName }}</template> + </gl-sprintf> + </gl-button> + </template> + </gl-modal> +</template> diff --git a/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue b/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue new file mode 100644 index 00000000000..bbf4160ce35 --- /dev/null +++ b/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue @@ -0,0 +1,107 @@ +<script> +import { + GlButtonGroup, + GlButton, + GlDropdown, + GlDropdownItem, + GlTooltipDirective, + GlModalDirective, +} from '@gitlab/ui'; +import { __ } from '~/locale'; +import { ISSUABLE_TYPE } from '../constants'; +import CsvExportModal from './csv_export_modal.vue'; +import CsvImportModal from './csv_import_modal.vue'; + +export default { + name: 'CsvImportExportButtons', + components: { + GlButtonGroup, + GlButton, + GlDropdown, + GlDropdownItem, + CsvExportModal, + CsvImportModal, + }, + directives: { + GlTooltip: GlTooltipDirective, + GlModal: GlModalDirective, + }, + inject: { + issuableType: { + default: ISSUABLE_TYPE.issues, + }, + showExportButton: { + default: false, + }, + showImportButton: { + default: false, + }, + containerClass: { + default: '', + }, + canEdit: { + default: false, + }, + projectImportJiraPath: { + default: null, + }, + showLabel: { + default: false, + }, + }, + computed: { + exportModalId() { + return `${this.issuableType}-export-modal`; + }, + importModalId() { + return `${this.issuableType}-import-modal`; + }, + importButtonText() { + return this.showLabel ? this.$options.importIssuesText : null; + }, + importButtonTooltipText() { + return this.showLabel ? null : this.$options.importIssuesText; + }, + importButtonIcon() { + return this.showLabel ? null : 'import'; + }, + }, + importIssuesText: __('Import issues'), +}; +</script> + +<template> + <div :class="containerClass"> + <gl-button-group> + <gl-button + v-if="showExportButton" + v-gl-tooltip.hover="__('Export as CSV')" + v-gl-modal="exportModalId" + icon="export" + data-qa-selector="export_as_csv_button" + data-testid="export-csv-button" + /> + <gl-dropdown + v-if="showImportButton" + v-gl-tooltip.hover="importButtonTooltipText" + data-qa-selector="import_issues_dropdown" + data-testid="import-csv-dropdown" + :text="importButtonText" + :icon="importButtonIcon" + > + <gl-dropdown-item v-gl-modal="importModalId" data-testid="import-csv-link">{{ + __('Import CSV') + }}</gl-dropdown-item> + <gl-dropdown-item + v-if="canEdit" + :href="projectImportJiraPath" + data-qa-selector="import_from_jira_link" + data-testid="import-from-jira-link" + >{{ __('Import from Jira') }}</gl-dropdown-item + > + </gl-dropdown> + </gl-button-group> + <csv-export-modal v-if="showExportButton" :modal-id="exportModalId" /> + <csv-import-modal v-if="showImportButton" :modal-id="importModalId" /> + </div> +</template> diff --git a/app/assets/javascripts/issuable/components/csv_import_modal.vue b/app/assets/javascripts/issuable/components/csv_import_modal.vue new file mode 100644 index 00000000000..77fc2f31583 --- /dev/null +++ b/app/assets/javascripts/issuable/components/csv_import_modal.vue @@ -0,0 +1,86 @@ +<script> +import { GlModal, GlSprintf, GlFormGroup, GlButton } from '@gitlab/ui'; +import csrf from '~/lib/utils/csrf'; +import { ISSUABLE_TYPE } from '../constants'; + +export default { + name: 'CsvImportModal', + components: { + GlModal, + GlSprintf, + GlFormGroup, + GlButton, + }, + inject: { + issuableType: { + default: '', + }, + exportCsvPath: { + default: '', + }, + importCsvIssuesPath: { + default: '', + }, + maxAttachmentSize: { + default: 0, + }, + }, + props: { + modalId: { + type: String, + required: true, + }, + }, + data() { + return { + // eslint-disable-next-line @gitlab/require-i18n-strings + issuableName: this.issuableType === ISSUABLE_TYPE.issues ? 'issues' : 'merge requests', + }; + }, + methods: { + submitForm() { + this.$refs.form.submit(); + }, + }, + csrf, +}; +</script> + +<template> + <gl-modal :modal-id="modalId" :title="__('Import issues')"> + <form + ref="form" + :action="importCsvIssuesPath" + enctype="multipart/form-data" + method="post" + data-testid="import-csv-form" + > + <input :value="$options.csrf.token" type="hidden" name="authenticity_token" /> + <p> + {{ + __( + "Your issues will be imported in the background. Once finished, you'll get a confirmation email.", + ) + }} + </p> + <gl-form-group :label="__('Upload CSV file')" label-for="file"> + <input id="file" type="file" name="file" accept=".csv,text/csv" /> + </gl-form-group> + <p class="text-secondary"> + {{ + __( + 'It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected.', + ) + }} + <gl-sprintf :message="__('The maximum file size allowed is %{size}.')" + ><template #size>{{ maxAttachmentSize }}</template></gl-sprintf + > + </p> + </form> + <template #modal-footer> + <gl-button category="primary" variant="confirm" @click="submitForm">{{ + __('Import issues') + }}</gl-button> + </template> + </gl-modal> +</template> diff --git a/app/assets/javascripts/issuable/constants.js b/app/assets/javascripts/issuable/constants.js new file mode 100644 index 00000000000..9344f4a7c9a --- /dev/null +++ b/app/assets/javascripts/issuable/constants.js @@ -0,0 +1,6 @@ +export const EVENT_ISSUABLE_VUE_APP_CHANGE = 'issuable_vue_app:change'; + +export const ISSUABLE_TYPE = { + issues: 'issues', + mergeRequests: 'merge-requests', +}; diff --git a/app/assets/javascripts/issuable/init_csv_import_export_buttons.js b/app/assets/javascripts/issuable/init_csv_import_export_buttons.js new file mode 100644 index 00000000000..5a720b89d33 --- /dev/null +++ b/app/assets/javascripts/issuable/init_csv_import_export_buttons.js @@ -0,0 +1,45 @@ +import Vue from 'vue'; +import { parseBoolean } from '~/lib/utils/common_utils'; +import ImportExportButtons from './components/csv_import_export_buttons.vue'; + +export default () => { + const el = document.querySelector('.js-csv-import-export-buttons'); + + if (!el) return null; + + const { + showExportButton, + showImportButton, + issuableType, + issuableCount, + email, + exportCsvPath, + importCsvIssuesPath, + containerClass, + canEdit, + projectImportJiraPath, + maxAttachmentSize, + showLabel, + } = el.dataset; + + return new Vue({ + el, + provide: { + showExportButton: parseBoolean(showExportButton), + showImportButton: parseBoolean(showImportButton), + issuableType, + issuableCount, + email, + exportCsvPath, + importCsvIssuesPath, + containerClass, + canEdit: parseBoolean(canEdit), + projectImportJiraPath, + maxAttachmentSize, + showLabel, + }, + render(h) { + return h(ImportExportButtons); + }, + }); +}; |