From a7b2a097978d885d33fed57e525f33449da809fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Mon, 9 Sep 2019 13:56:31 +0200 Subject: [PATCH] [30953] Use correct URL syntax for export link The export page expects `filters=[...v3filters]` syntax, not the `queryProps` syntax. https://community.openproject.com/wp/30953 --- .../bcf-export-button.component.ts | 26 ++--- .../bcf/helper/bcf-path-helper.service.ts | 6 +- modules/bcf/spec/features/bcf_export_spec.rb | 94 +++++++++++++++++++ 3 files changed, 112 insertions(+), 14 deletions(-) create mode 100644 modules/bcf/spec/features/bcf_export_spec.rb diff --git a/frontend/src/app/modules/bcf/bcf-buttons/bcf-export-button.component.ts b/frontend/src/app/modules/bcf/bcf-buttons/bcf-export-button.component.ts index 68c28f70d5..03ac4798f7 100644 --- a/frontend/src/app/modules/bcf/bcf-buttons/bcf-export-button.component.ts +++ b/frontend/src/app/modules/bcf/bcf-buttons/bcf-export-button.component.ts @@ -36,28 +36,33 @@ import {IsolatedQuerySpace} from "core-app/modules/work_packages/query-space/iso import {QueryResource} from "core-app/modules/hal/resources/query-resource"; import {UrlParamsHelperService} from "core-components/wp-query/url-params-helper"; import {StateService} from "@uirouter/core"; +import {WorkPackageStaticQueriesService} from "core-components/wp-query-select/wp-static-queries.service"; @Component({ template: ` - + {{text.export}} `, selector: 'bcf-export-button', }) -export class BcfExportButtonComponent implements OnInit, OnDestroy{ +export class BcfExportButtonComponent implements OnInit, OnDestroy { public text = { export: this.I18n.t('js.bcf.export') }; public query:QueryResource; + public exportLink:string; constructor(readonly I18n:I18nService, readonly currentProject:CurrentProjectService, readonly bcfPathHelper:BcfPathHelperService, readonly querySpace:IsolatedQuerySpace, readonly queryUrlParamsHelper:UrlParamsHelperService, - public readonly state:StateService,) { + readonly state:StateService) { } ngOnInit() { @@ -68,20 +73,19 @@ export class BcfExportButtonComponent implements OnInit, OnDestroy{ ) .subscribe((query) => { this.query = query; + + let projectIdentifier = this.currentProject.identifier; + let filters = this.queryUrlParamsHelper.buildV3GetFilters(this.query.filters); + this.exportLink = this.bcfPathHelper.projectExportIssuesPath( + projectIdentifier!, + JSON.stringify(filters) + ); }); } ngOnDestroy() { // Nothing to do } - - public handleClick() { - var projectIdentifier = this.currentProject.identifier; - if (projectIdentifier) { - var url = this.bcfPathHelper.projectExportIssuesPath(projectIdentifier, this.queryUrlParamsHelper.encodeQueryJsonParams(this.query)); - window.location.href = url; - } - } } DynamicBootstrapper.register({ selector: 'bcf-export-button', cls: BcfExportButtonComponent }); diff --git a/frontend/src/app/modules/bcf/helper/bcf-path-helper.service.ts b/frontend/src/app/modules/bcf/helper/bcf-path-helper.service.ts index feca833d0d..4b1ebe3f07 100644 --- a/frontend/src/app/modules/bcf/helper/bcf-path-helper.service.ts +++ b/frontend/src/app/modules/bcf/helper/bcf-path-helper.service.ts @@ -38,9 +38,9 @@ export class BcfPathHelperService { return this.pathHelper.projectPath(projectIdentifier) + '/issues/upload'; } - public projectExportIssuesPath(projectIdentifier:string, queryProps:any = null) { - if (queryProps) { - return this.pathHelper.projectPath(projectIdentifier) + '/work_packages.bcf?query_props=' + queryProps; + public projectExportIssuesPath(projectIdentifier:string, filters:string|null) { + if (filters) { + return this.pathHelper.projectPath(projectIdentifier) + '/work_packages.bcf?filters=' + filters; } else { return this.pathHelper.projectPath(projectIdentifier) + '/work_packages.bcf'; } diff --git a/modules/bcf/spec/features/bcf_export_spec.rb b/modules/bcf/spec/features/bcf_export_spec.rb new file mode 100644 index 0000000000..2b03cd4944 --- /dev/null +++ b/modules/bcf/spec/features/bcf_export_spec.rb @@ -0,0 +1,94 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ +require 'spec_helper' + +describe 'work package export', type: :feature, js: true do + let(:status) { FactoryBot.create(:status, name: 'New', is_default: true) } + let(:closed_status) { FactoryBot.create(:closed_status, name: 'Closed') } + let(:project) { FactoryBot.create :project } + + let!(:open_work_package) { FactoryBot.create(:work_package, project: project, subject: 'Open WP', status: status) } + let!(:closed_work_package) { FactoryBot.create(:work_package, project: project, subject: 'Closed WP', status: closed_status) } + let!(:open_bcf_issue) { FactoryBot.create(:bcf_issue, work_package: open_work_package) } + let!(:closed_bcf_issue) { FactoryBot.create(:bcf_issue, work_package: closed_work_package) } + + let(:current_user) { FactoryBot.create :admin } + + let(:wp_table) { ::Pages::WorkPackagesTable.new(project) } + let(:filters) { ::Components::WorkPackages::Filters.new } + + before do + login_as current_user + end + + after do + DownloadedFile::clear_downloads + end + + def export_into_bcf_extractor + ::DownloadedFile::clear_downloads + page.find('.export-bcf-button').click + + # Wait for the file to download + ::DownloadedFile.wait_for_download + ::DownloadedFile.wait_for_download_content + + # Check the downloaded file + OpenProject::Bcf::BcfXml::Importer.new( + ::DownloadedFile.download, + project, + current_user: current_user + ).extractor_list + end + + it 'can export the open and closed BCF issues (Regression #30953)' do + wp_table.visit! + wp_table.expect_work_package_listed open_work_package + wp_table.ensure_work_package_not_listed! closed_work_package + filters.expect_filter_count 1 + + # Expect only the open issue + extractor_list = export_into_bcf_extractor + expect(extractor_list.length).to eq 1 + expect(extractor_list.first[:title]).to eq 'Open WP' + + # Change the query to show all statuses + filters.open + filters.remove_filter 'status' + filters.expect_filter_count 0 + + wp_table.expect_work_package_listed open_work_package, closed_work_package + + # Download again + extractor_list = export_into_bcf_extractor + expect(extractor_list.length).to eq 2 + + titles = extractor_list.map { |hash| hash[:title] } + expect(titles).to contain_exactly 'Open WP', 'Closed WP' + end +end