diff --git a/frontend/app/components/api/api-v3/hal-resources/work-package-resource.service.test.ts b/frontend/app/components/api/api-v3/hal-resources/work-package-resource.service.test.ts index a917986792..60ab914d82 100644 --- a/frontend/app/components/api/api-v3/hal-resources/work-package-resource.service.test.ts +++ b/frontend/app/components/api/api-v3/hal-resources/work-package-resource.service.test.ts @@ -343,35 +343,22 @@ describe('WorkPackageResource service', () => { .returns($q.when()); }); - describe('when the work package is new', () => { - beforeEach(() => { - workPackage.isNew = true; - workPackage.uploadPendingAttachments(); - }); + beforeEach(() => { + workPackage.isNew = false; + workPackage.uploadPendingAttachments(); + }); - it('should not be called', () => { - expect(uploadAttachmentsStub.called).to.be.false; - }); + it('should call the uploadAttachments method with the pendingAttachments', () => { + expect(uploadAttachmentsStub.calledWith([{},{}])).to.be.true; }); - describe('when the work package is not new', () => { + describe('when the upload succeeds', () => { beforeEach(() => { - workPackage.isNew = false; - workPackage.uploadPendingAttachments(); - }); - - it('should call the uploadAttachments method with the pendingAttachments', () => { - expect(uploadAttachmentsStub.calledWith(workPackage.pendingAttachments)).to.be.true; + $rootScope.$apply(); }); - describe('when the upload succeeds', () => { - beforeEach(() => { - $rootScope.$apply(); - }); - - it('should reset the pending attachments', () => { - expect(workPackage.pendingAttachments).to.have.length(0); - }); + it('should reset the pending attachments', () => { + expect(workPackage.pendingAttachments).to.have.length(0); }); }); }); diff --git a/frontend/app/components/api/api-v3/hal-resources/work-package-resource.service.ts b/frontend/app/components/api/api-v3/hal-resources/work-package-resource.service.ts index 34d1c0c804..4602db9139 100644 --- a/frontend/app/components/api/api-v3/hal-resources/work-package-resource.service.ts +++ b/frontend/app/components/api/api-v3/hal-resources/work-package-resource.service.ts @@ -227,10 +227,13 @@ export class WorkPackageResource extends HalResource { * Do nothing, if the work package is being created. */ public uploadPendingAttachments() { - if (!this.isNew) { - this.uploadAttachments(this.pendingAttachments) - .then(() => this.pendingAttachments = []); - } + if (!this.pendingAttachments.length) { + return; + } + + const attachments = this.pendingAttachments; + this.pendingAttachments = []; + return this.uploadAttachments(attachments); } /** diff --git a/frontend/app/components/routing/wp-show/wp.show.html b/frontend/app/components/routing/wp-show/wp.show.html index 968cb6bf2f..96fd3abf7f 100644 --- a/frontend/app/components/routing/wp-show/wp.show.html +++ b/frontend/app/components/routing/wp-show/wp.show.html @@ -21,9 +21,6 @@ -
  • - -
  • diff --git a/frontend/app/components/work-packages/wp-single-view/wp-single-view.directive.html b/frontend/app/components/work-packages/wp-single-view/wp-single-view.directive.html index f121532046..f2d06fb1f3 100644 --- a/frontend/app/components/work-packages/wp-single-view/wp-single-view.directive.html +++ b/frontend/app/components/work-packages/wp-single-view/wp-single-view.directive.html @@ -105,16 +105,10 @@ - -
    -
    -
    +
    +

    {{ ::$ctrl.I18n.t('js.label_attachments') }} diff --git a/frontend/app/components/wp-attachments/wp-attachments-upload/wp-attachments-upload.directive.test.ts b/frontend/app/components/wp-attachments/wp-attachments-upload/wp-attachments-upload.directive.test.ts index 25581625e2..2cfd730767 100644 --- a/frontend/app/components/wp-attachments/wp-attachments-upload/wp-attachments-upload.directive.test.ts +++ b/frontend/app/components/wp-attachments/wp-attachments-upload/wp-attachments-upload.directive.test.ts @@ -46,7 +46,6 @@ describe('wpAttachmentsUpload directive', () => { var rootElement: IAugmentedJQuery; var workPackage: any; - var uploadPendingAttachmentsStub: SinonStub; var mockMaxSize: number = 123; beforeEach(angular.mock.module( @@ -73,11 +72,9 @@ describe('wpAttachmentsUpload directive', () => { html = ` `; - uploadPendingAttachmentsStub = sinon.stub().returns($q.when()); workPackage = { canAddAttachments: false, - attachments: {pending: []}, - uploadPendingAttachments: uploadPendingAttachmentsStub + attachments: {pending: []} }; const scope: any = $rootScope.$new(); @@ -87,7 +84,7 @@ describe('wpAttachmentsUpload directive', () => { compile = () => { element = $compile(html)(scope); - $rootScope.$apply(); + scope.$digest(); controller = element.controller('wpAttachmentsUpload'); rootElement = element.find('.wp-attachment-upload'); }; @@ -108,13 +105,9 @@ describe('wpAttachmentsUpload directive', () => { }); describe('when it is possible to add attachments to the work package', () => { - var ngfController; - beforeEach(() => { workPackage.canAddAttachments = true; compile(); - - ngfController = rootElement.controller('ngfDrop'); }); it('should display the directive', () => { @@ -125,20 +118,6 @@ describe('wpAttachmentsUpload directive', () => { expect(rootElement.attr('ngf-max-size')).to.equal(mockMaxSize.toString()); }); - it('should have the ngModel property set to the pending attachments', () => { - expect(ngfController.ngModel).to.equal(workPackage.pendingAttachments); - }); - - describe('when uploading files', () => { - beforeEach(() => { - ngfController.ngfChange(); - }); - - it('should call `uploadAttachments()`', () => { - expect(uploadPendingAttachmentsStub.calledOnce).to.be.true; - }); - }); - describe('when clicking the parent element', () => { var clicked; diff --git a/frontend/app/components/wp-attachments/wp-attachments-upload/wp-attachments-upload.directive.ts b/frontend/app/components/wp-attachments/wp-attachments-upload/wp-attachments-upload.directive.ts index 61f193c60a..58d7b59e09 100644 --- a/frontend/app/components/wp-attachments/wp-attachments-upload/wp-attachments-upload.directive.ts +++ b/frontend/app/components/wp-attachments/wp-attachments-upload/wp-attachments-upload.directive.ts @@ -28,19 +28,31 @@ import {wpDirectivesModule} from '../../../angular-modules'; import {WorkPackageResourceInterface} from '../../api/api-v3/hal-resources/work-package-resource.service'; +import {UploadFile} from '../../api/op-file-upload/op-file-upload.service'; import IDirective = angular.IDirective; export class WorkPackageUploadDirectiveController { public workPackage: WorkPackageResourceInterface; public text: any; public maxFileSize: number; - public rejectedFiles: File[] = []; constructor(ConfigurationService) { ConfigurationService.api().then(settings => { this.maxFileSize = settings.maximumAttachmentFileSize; }); } + + public uploadFiles(files: UploadFile[]) { + if (files === undefined || files.length === 0) { + return; + } + + if (this.workPackage.isNew) { + return this.workPackage.pendingAttachments.push(...files); + } + + this.workPackage.uploadAttachments(files); + } } function wpUploadDirective(): IDirective { @@ -55,11 +67,9 @@ function wpUploadDirective(): IDirective { class="wp-attachment-upload" ng-if="$ctrl.workPackage.canAddAttachments" ngf-drop - ng-model="$ctrl.workPackage.pendingAttachments" - ng-model-rejected="$ctrl.rejectedFiles" ngf-select + ngf-change="$ctrl.uploadFiles($files)" ngf-multiple="true" - ngf-change="$ctrl.workPackage.uploadPendingAttachments()" ngf-max-size="{{ ::$ctrl.maxFileSize }}" click-on-keypress="[13, 32]" ng-transclude> diff --git a/frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button-create.directive.html b/frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button-create.directive.html deleted file mode 100644 index 749eba521d..0000000000 --- a/frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button-create.directive.html +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button-toolbar.directive.html b/frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button-toolbar.directive.html deleted file mode 100644 index 3edf50f8b9..0000000000 --- a/frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button-toolbar.directive.html +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button.directive.test.ts b/frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button.directive.test.ts deleted file mode 100644 index fb95c307aa..0000000000 --- a/frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button.directive.test.ts +++ /dev/null @@ -1,93 +0,0 @@ -//-- copyright -// OpenProject is a project management system. -// Copyright (C) 2012-2015 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-2013 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 doc/COPYRIGHT.rdoc for more details. -//++ - -import {opApiModule} from '../../../angular-modules'; -import IAugmentedJQuery = angular.IAugmentedJQuery; -import IProvideService = angular.auto.IProvideService; -import I18n = op.I18n; - -describe('wpUploadButton directive', () => { - var workPackage; - - var I18n; - var compile; - var scope; - - var element: IAugmentedJQuery; - var button: any; - - var uploadsDirectiveScope; - - beforeEach(angular.mock.module('openproject.templates')); - - beforeEach(angular.mock.module(opApiModule.name, ($provide: IProvideService) => { - $provide.decorator('wpAttachmentsUploadDirective', () => { - return { - scope: { - workPackage: '=' - } - }; - }); - })); - - beforeEach(angular.mock.inject(function ($rootScope, $compile, _I18n_) { - I18n = _I18n_; - const html = ''; - workPackage = {}; - scope = $rootScope.$new(); - scope.workPackage = workPackage; - - sinon.stub(I18n, 't').returns('add attachments'); - - compile = () => { - element = $compile(html)(scope); - scope.$digest(); - - button = element.find('.button'); - uploadsDirectiveScope = button.scope(); - }; - - compile(); - })); - - afterEach(function() { - I18n.t.restore(); - }); - - it('should have the add attachment tooltip', () => { - expect(button.attr('title')).to.equal('add attachments'); - }); - - it('should pass the work package to the upload directive', () => { - expect(uploadsDirectiveScope.workPackage).to.equal(workPackage); - }); - - it('should have the attachment icon as icon', () => { - expect(button.find('.icon-attachment')).to.have.length(1); - }); -}); diff --git a/frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button.directive.ts b/frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button.directive.ts deleted file mode 100644 index 96f4193139..0000000000 --- a/frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button.directive.ts +++ /dev/null @@ -1,52 +0,0 @@ -//-- copyright -// OpenProject is a project management system. -// Copyright (C) 2012-2015 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-2013 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 doc/COPYRIGHT.rdoc for more details. -//++ - -import {opApiModule} from '../../../angular-modules'; -import IDirective = angular.IDirective; - -function wpUploadButtonDirective(I18n): IDirective { - return { - restrict: 'E', - templateUrl: (element, attrs) => { - return '/components/wp-attachments/wp-upload-button/' + attrs.template + '.directive.html'; - }, - - scope: { - workPackage: '=', - template: '@' - }, - - link(scope: any) { - scope.text = { - addAttachments: I18n.t('js.label_add_attachments') - }; - } - }; -} - -opApiModule.directive('wpUploadButton', wpUploadButtonDirective); diff --git a/frontend/app/components/wp-details/wp-details-toolbar.directive.html b/frontend/app/components/wp-details/wp-details-toolbar.directive.html index 47319cb5d6..65b6d02bf7 100644 --- a/frontend/app/components/wp-details/wp-details-toolbar.directive.html +++ b/frontend/app/components/wp-details/wp-details-toolbar.directive.html @@ -11,8 +11,6 @@ ng-if="displayWatchButton"> - -