Merge pull request #4992 from opf/feature/23777/consolidate-file-upload

[23777] Consolidate file upload
pull/5000/head
Markus Kahl 8 years ago committed by GitHub
commit c0ebfa51c5
  1. 33
      frontend/app/components/api/api-v3/hal-resources/work-package-resource.service.test.ts
  2. 11
      frontend/app/components/api/api-v3/hal-resources/work-package-resource.service.ts
  3. 3
      frontend/app/components/routing/wp-show/wp.show.html
  4. 12
      frontend/app/components/work-packages/wp-single-view/wp-single-view.directive.html
  5. 25
      frontend/app/components/wp-attachments/wp-attachments-upload/wp-attachments-upload.directive.test.ts
  6. 18
      frontend/app/components/wp-attachments/wp-attachments-upload/wp-attachments-upload.directive.ts
  7. 8
      frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button-create.directive.html
  8. 7
      frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button-toolbar.directive.html
  9. 93
      frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button.directive.test.ts
  10. 52
      frontend/app/components/wp-attachments/wp-upload-button/wp-upload-button.directive.ts
  11. 2
      frontend/app/components/wp-details/wp-details-toolbar.directive.html
  12. 2
      frontend/tests/unit/tests/work_packages/directives/work-package-details-toolbar-test.js

@ -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);
});
});
});

@ -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);
}
/**

@ -21,9 +21,6 @@
<i class="button--icon icon-edit"></i>
</button>
</li>
<li>
<wp-upload-button template="wp-upload-button-toolbar" work-package="$ctrl.workPackage"></wp-upload-button>
</li>
<li class="toolbar-item" ng-if="$ctrl.displayWatchButton">
<wp-watcher-button work-package="$ctrl.workPackage" disabled="$ctrl.wpEditModeState.active"></wp-watcher-button>
</li>

@ -105,16 +105,10 @@
</div>
</div>
<wp-upload-button
ng-hide="$ctrl.workPackage.attachments.elements.length > 0"
template="wp-upload-button-create"
work-package="$ctrl.workPackage"></wp-upload-button>
<div class="work-packages--attachments attributes-group">
<div
class="work-packages--atachments-container"
ng-if="!$ctrl.hideEmptyFields || $ctrl.workPackage.attachments.elements.length || $ctrl.workPackage.pendingAttachments">
<div class="attributes-group--header">
<div class="work-packages--atachments-container">
<div class="attributes-group--header"
ng-if="$ctrl.workPackage.attachments.elements.length">
<div class="attributes-group--header-container">
<h3 class="attributes-group--header-text">
{{ ::$ctrl.I18n.t('js.label_attachments') }}

@ -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 = `<wp-attachments-upload attachments="attachments" work-package="workPackage">
</wp-attachments-upload>`;
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;

@ -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>

@ -1,8 +0,0 @@
<div class="wp-inline-create-button" aria-hidden="false">
<a class="wp-inline-create--add-link" wp-attachments-upload work-package="workPackage" role="link" aria-label="Add attachment" data-click-on-keypress="[13, 32]">
<i class="icon icon-attachment"></i>
<span ng-bind="::text.addAttachments" aria-hidden="true">Add attachments</span>
</a>
</div>

@ -1,7 +0,0 @@
<button
class="button"
wp-attachments-upload
work-package="workPackage"
title="{{ ::text.addAttachments }}">
<i class="icon-attachment"></i>
</button>

@ -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 = '<wp-upload-button template="wp-upload-button-toolbar" work-package="workPackage"></wp-upload-button>';
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);
});
});

@ -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);

@ -11,8 +11,6 @@
ng-if="displayWatchButton">
</wp-watcher-button>
<wp-upload-button template="wp-upload-button-toolbar" work-package="workPackage"></wp-upload-button>
<button class="button dropdown-relative"
ng-disabled="!actionsAvailable"
has-dropdown-menu

@ -83,7 +83,7 @@ describe('workPackageDetailsToolbar', function() {
element = $compile(element)(scope);
angular.element(document.body).append(element);
scope.$digest();
element.find('button:eq(2)').click();
element.find('button:eq(1)').click();
};
}));

Loading…
Cancel
Save