Commit 478974cc authored by Olena Horal-Koretska's avatar Olena Horal-Koretska

Merge branch 'mw-migrate-import-csv-button-on-issue-empty-state' into 'master'

Migrate import button on issue empty state to Vue

See merge request gitlab-org/gitlab!55761
parents 87f8d02d 612aa538
...@@ -201,7 +201,6 @@ linters: ...@@ -201,7 +201,6 @@ linters:
- 'app/views/projects/imports/new.html.haml' - 'app/views/projects/imports/new.html.haml'
- 'app/views/projects/imports/show.html.haml' - 'app/views/projects/imports/show.html.haml'
- 'app/views/projects/issues/_new_branch.html.haml' - 'app/views/projects/issues/_new_branch.html.haml'
- 'app/views/projects/issues/import_csv/_modal.html.haml'
- 'app/views/projects/issues/show.html.haml' - 'app/views/projects/issues/show.html.haml'
- 'app/views/projects/jobs/_header.html.haml' - 'app/views/projects/jobs/_header.html.haml'
- 'app/views/projects/jobs/_table.html.haml' - 'app/views/projects/jobs/_table.html.haml'
......
...@@ -7,6 +7,8 @@ import { ...@@ -7,6 +7,8 @@ import {
GlTooltipDirective, GlTooltipDirective,
GlModalDirective, GlModalDirective,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { __ } from '~/locale';
import { ISSUABLE_TYPE } from '../constants';
import CsvExportModal from './csv_export_modal.vue'; import CsvExportModal from './csv_export_modal.vue';
import CsvImportModal from './csv_import_modal.vue'; import CsvImportModal from './csv_import_modal.vue';
...@@ -25,6 +27,9 @@ export default { ...@@ -25,6 +27,9 @@ export default {
GlModal: GlModalDirective, GlModal: GlModalDirective,
}, },
inject: { inject: {
issuableType: {
default: ISSUABLE_TYPE.issues,
},
showExportButton: { showExportButton: {
default: false, default: false,
}, },
...@@ -40,6 +45,9 @@ export default { ...@@ -40,6 +45,9 @@ export default {
projectImportJiraPath: { projectImportJiraPath: {
default: null, default: null,
}, },
showLabel: {
default: false,
},
}, },
computed: { computed: {
exportModalId() { exportModalId() {
...@@ -48,7 +56,17 @@ export default { ...@@ -48,7 +56,17 @@ export default {
importModalId() { importModalId() {
return `${this.issuableType}-import-modal`; 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> </script>
...@@ -65,9 +83,11 @@ export default { ...@@ -65,9 +83,11 @@ export default {
/> />
<gl-dropdown <gl-dropdown
v-if="showImportButton" v-if="showImportButton"
v-gl-tooltip.hover="__('Import issues')" v-gl-tooltip.hover="importButtonTooltipText"
data-qa-selector="import_issues_dropdown"
data-testid="import-csv-dropdown" data-testid="import-csv-dropdown"
icon="import" :text="importButtonText"
:icon="importButtonIcon"
> >
<gl-dropdown-item v-gl-modal="importModalId" data-testid="import-csv-link">{{ <gl-dropdown-item v-gl-modal="importModalId" data-testid="import-csv-link">{{
__('Import CSV') __('Import CSV')
......
...@@ -19,6 +19,7 @@ export default () => { ...@@ -19,6 +19,7 @@ export default () => {
canEdit, canEdit,
projectImportJiraPath, projectImportJiraPath,
maxAttachmentSize, maxAttachmentSize,
showLabel,
} = el.dataset; } = el.dataset;
return new Vue({ return new Vue({
...@@ -35,6 +36,7 @@ export default () => { ...@@ -35,6 +36,7 @@ export default () => {
canEdit: parseBoolean(canEdit), canEdit: parseBoolean(canEdit),
projectImportJiraPath, projectImportJiraPath,
maxAttachmentSize, maxAttachmentSize,
showLabel,
}, },
render(h) { render(h) {
return h(ImportExportButtons); return h(ImportExportButtons);
......
- type = local_assigns.fetch(:type, :icon)
- can_edit = can?(current_user, :admin_project, @project)
.dropdown.btn-group
%button.btn.gl-button.rounded-right.btn-default.btn-icon.text-center{ class: ('has-tooltip' if type == :icon), title: (_('Import issues') if type == :icon),
data: { toggle: 'dropdown', qa_selector: 'import_issues_button' }, 'aria-label' => _('Import issues'), 'aria-haspopup' => 'true', 'aria-expanded' => 'false' }
- if type == :icon
= sprite_icon('import')
- else
= _('Import issues')
%ul.dropdown-menu
%li
%button{ data: { toggle: 'modal', target: '.issues-import-modal' } }
= _('Import CSV')
- if can_edit
%li{ data: { qa_selector: 'import_from_jira_link' } }
= link_to _('Import from Jira'), project_import_jira_path(@project)
.issues-import-modal.modal
.modal-dialog
.modal-content
= form_tag import_csv_namespace_project_issues_path, multipart: true do
.modal-header
%h4.gl-m-0
= _('Import issues')
%a.close{ href: '#', 'data-dismiss' => 'modal' } ×
.modal-body
.modal-text
%p
= _("Your issues will be imported in the background. Once finished, you'll get a confirmation email.")
.form-group
= label_tag :file, _('Upload CSV file'), class: 'label-bold'
%div
= file_field_tag :file, accept: '.csv,text/csv', required: true
%p.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.')
= _('The maximum file size allowed is %{size}.') % { size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes) }
.modal-footer
%button{ type: 'submit', class: 'gl-button btn btn-success', title: _('Import issues'), data: { track_label: "export_issues_csv", track_event: "click_button", track_value: ""} }
= _('Import issues')
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
- opened_issues_count = issuables_count_for_state(:issues, :opened) - opened_issues_count = issuables_count_for_state(:issues, :opened)
- is_opened_state = params[:state] == 'opened' - is_opened_state = params[:state] == 'opened'
- is_closed_state = params[:state] == 'closed' - is_closed_state = params[:state] == 'closed'
- issuable_type = 'issues'
- can_edit = can?(current_user, :admin_project, @project)
.row.empty-state .row.empty-state
.col-12 .col-12
...@@ -45,7 +47,7 @@ ...@@ -45,7 +47,7 @@
= link_to _('New issue'), button_path, class: 'gl-button btn btn-confirm', id: 'new_issue_link' = link_to _('New issue'), button_path, class: 'gl-button btn btn-confirm', id: 'new_issue_link'
- if show_import_button - if show_import_button
= render 'projects/issues/import_csv/button', type: :text .js-csv-import-export-buttons{ data: { show_import_button: show_import_button.to_s, issuable_type: issuable_type, import_csv_issues_path: import_csv_namespace_project_issues_path, can_edit: can_edit.to_s, project_import_jira_path: project_import_jira_path(@project), max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes), container_class: 'gl-display-inline-flex gl-vertical-align-middle', show_label: 'true' } }
%hr %hr
%p.gl-text-center.gl-mb-0 %p.gl-text-center.gl-mb-0
%strong %strong
...@@ -63,6 +65,3 @@ ...@@ -63,6 +65,3 @@
= _("The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project.") = _("The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project.")
.text-center .text-center
= link_to _('Register / Sign In'), new_user_session_path, class: 'gl-button btn btn-confirm' = link_to _('Register / Sign In'), new_user_session_path, class: 'gl-button btn btn-confirm'
- if show_import_button
= render 'projects/issues/import_csv/modal'
- if current_user
%button.csv_download_link.btn.gl-button.btn-default.btn-icon.has-tooltip{ title: _('Export as CSV'),
data: { toggle: 'modal', target: ".#{issuable_type}-export-modal", qa_selector: 'export_as_csv_button' } }
= sprite_icon('export')
- class_name = "#{issuable_type.dasherize}-export-modal"
- if current_user
.modal.issuable-export-modal{ class: class_name }
.modal-dialog
.modal-content{ data: { qa_selector: "export_issuable_modal" } }
.modal-header
%h4.gl-m-0
= _("Export %{issuable_type}" % { issuable_type: issuable_type.humanize(capitalize: false) })
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
= sprite_icon('close', css_class: 'gl-icon')
.modal-body
- issuable_count = issuables_count_for_state(issuable_type.to_sym, params[:state])
- unless issuable_count == -1 # The count timed out
.modal-subheader
= sprite_icon('check', css_class: 'gl-icon gl-color-green-400')
%strong.gl-ml-3
- if issuable_type.eql?('merge_requests')
= n_("%{count} merge request selected", "%{count} merge requests selected", issuable_count) % { count: issuable_count }
- else
= n_("%{count} issue selected", "%{count} issues selected", issuable_count) % { count: issuable_count }
.modal-text
= html_escape(_('The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment.')) % { email: @current_user.notification_email, strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
.modal-footer
- if issuable_type.eql?('merge_requests')
= link_to _("Export merge requests"), export_csv_project_merge_requests_path(@project, request.query_parameters), method: :post, class: 'btn gl-button btn-confirm', data: { track_label: "export_merge_requests_csv", track_event: "click_button", track_value: "" }
- else
= link_to _('Export issues'), export_csv_project_issues_path(@project, request.query_parameters), method: :post, class: 'btn gl-button btn-confirm', data: { track_label: "export_issues_csv", track_event: "click_button", track_value: "", qa_selector: "export_issues_button" }
...@@ -440,19 +440,9 @@ msgstr "" ...@@ -440,19 +440,9 @@ msgstr ""
msgid "%{count} files touched" msgid "%{count} files touched"
msgstr "" msgstr ""
msgid "%{count} issue selected"
msgid_plural "%{count} issues selected"
msgstr[0] ""
msgstr[1] ""
msgid "%{count} items per page" msgid "%{count} items per page"
msgstr "" msgstr ""
msgid "%{count} merge request selected"
msgid_plural "%{count} merge requests selected"
msgstr[0] ""
msgstr[1] ""
msgid "%{count} more" msgid "%{count} more"
msgstr "" msgstr ""
...@@ -12533,12 +12523,6 @@ msgstr "" ...@@ -12533,12 +12523,6 @@ msgstr ""
msgid "Export group" msgid "Export group"
msgstr "" msgstr ""
msgid "Export issues"
msgstr ""
msgid "Export merge requests"
msgstr ""
msgid "Export project" msgid "Export project"
msgstr "" msgstr ""
...@@ -29807,9 +29791,6 @@ msgstr[1] "" ...@@ -29807,9 +29791,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project." msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr "" msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
msgstr ""
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group." msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr "" msgstr ""
......
...@@ -22,14 +22,7 @@ module QA ...@@ -22,14 +22,7 @@ module QA
view 'app/assets/javascripts/issuable/components/csv_import_export_buttons.vue' do view 'app/assets/javascripts/issuable/components/csv_import_export_buttons.vue' do
element :export_as_csv_button element :export_as_csv_button
element :import_from_jira_link element :import_from_jira_link
end element :import_issues_dropdown
view 'app/views/projects/issues/import_csv/_button.html.haml' do
element :import_issues_button
end
view 'app/views/shared/issuable/csv_export/_modal.html.haml' do
element :export_issues_button
end end
view 'app/views/shared/issuable/_nav.html.haml' do view 'app/views/shared/issuable/_nav.html.haml' do
...@@ -63,7 +56,7 @@ module QA ...@@ -63,7 +56,7 @@ module QA
def click_import_issues_dropdown def click_import_issues_dropdown
# When there are no issues, the image that loads causes the buttons to jump # When there are no issues, the image that loads causes the buttons to jump
has_loaded_all_images? has_loaded_all_images?
click_element(:import_issues_button) click_element(:import_issues_dropdown)
end end
def export_issues_modal def export_issues_modal
......
...@@ -94,12 +94,38 @@ describe('CsvImportExportButtons', () => { ...@@ -94,12 +94,38 @@ describe('CsvImportExportButtons', () => {
expect(findImportCsvButton().exists()).toBe(true); expect(findImportCsvButton().exists()).toBe(true);
}); });
describe('when showLabel=false', () => {
beforeEach(() => {
wrapper = createComponent({ showImportButton: true, showLabel: false });
});
it('does not have a button text', () => {
expect(findImportCsvButton().props('text')).toBe(null);
});
it('import button has a tooltip', () => { it('import button has a tooltip', () => {
const tooltip = getBinding(findImportDropdown().element, 'gl-tooltip'); const tooltip = getBinding(findImportDropdown().element, 'gl-tooltip');
expect(tooltip).toBeDefined(); expect(tooltip).toBeDefined();
expect(tooltip.value).toBe('Import issues'); expect(tooltip.value).toBe('Import issues');
}); });
});
describe('when showLabel=true', () => {
beforeEach(() => {
wrapper = createComponent({ showImportButton: true, showLabel: true });
});
it('displays a button text', () => {
expect(findImportCsvButton().props('text')).toBe('Import issues');
});
it('import button has no tooltip', () => {
const tooltip = getBinding(findImportDropdown().element, 'gl-tooltip');
expect(tooltip.value).toBe(null);
});
});
it('renders the import modal', () => { it('renders the import modal', () => {
expect(findImportCsvModal().exists()).toBe(true); expect(findImportCsvModal().exists()).toBe(true);
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'projects/issues/import_csv/_button' do
include Devise::Test::ControllerHelpers
context 'when the user does not have edit permissions' do
before do
render
end
it 'shows a dropdown button to import CSV' do
expect(rendered).to have_text('Import CSV')
end
it 'does not show a button to import from Jira' do
expect(rendered).not_to have_text('Import from Jira')
end
end
context 'when the user has edit permissions' do
let(:project) { create(:project) }
let(:current_user) { create(:user, maintainer_projects: [project]) }
before do
allow(view).to receive(:project_import_jira_path).and_return('import/jira')
allow(view).to receive(:current_user).and_return(current_user)
assign(:project, project)
render
end
it 'shows a dropdown button to import CSV' do
expect(rendered).to have_text('Import CSV')
end
it 'shows a button to import from Jira' do
expect(rendered).to have_text('Import from Jira')
end
end
end
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