Add work package edit actions toolbar (save & cancel)

Saving the work package does not work as of yet.
pull/3701/head
Alex Dik 9 years ago committed by Jens Ulferts
parent 880cd83485
commit 40167485a9
  1. 6
      app/assets/stylesheets/layout/_work_package.sass
  2. 4
      frontend/app/templates/work_packages.list.details.html
  3. 6
      frontend/app/templates/work_packages.show.html
  4. 6
      frontend/app/templates/work_packages/work_package_details_toolbar.html
  5. 40
      frontend/app/templates/work_packages/work_package_edit_actions.html
  6. 6
      frontend/app/work_packages/controllers/work-package-show-controller.js
  7. 4
      frontend/app/work_packages/directives/index.js
  8. 5
      frontend/app/work_packages/directives/inplace_editor/inplace-editor-edit-pane-directive.js
  9. 29
      frontend/app/work_packages/directives/work-package-details-toolbar-directive.js
  10. 43
      frontend/app/work_packages/directives/work-package-edit-actions-directive.js
  11. 8
      frontend/app/work_packages/services/editable-fields-state.js
  12. 6
      frontend/tests/integration/pages/work-package-show-page.js
  13. 44
      frontend/tests/integration/specs/work-packages/work-package-edit-spec.js
  14. 8
      frontend/tests/unit/tests/work_packages/services/editable-fields-state-test.js

@ -178,6 +178,12 @@
.work-packages--attachments
margin-bottom: 25px
.work-packages--edit-actions
@extend .work-packages--details-toolbar
.work-packages--left-panel &
position: static
.work-package--attachments--files
margin-bottom: 1rem

@ -54,6 +54,6 @@
</div>
<div class="bottom-toolbar">
<work-package-details-toolbar work-package='workPackage'>
</work-package-details-toolbar>
<work-package-details-toolbar work-package='workPackage'></work-package-details-toolbar>
<work-package-edit-actions work-package="workPackage"></work-package-edit-actions>
</div>

@ -15,7 +15,8 @@
</li>
<li class="toolbar-item">
<button class="button"
ng-click="editWorkPackage()"
ng-class="{'-active': editAll.state}"
ng-click="editAll.toggleState()"
title="{{I18n.t('js.button_edit')}}">
<i class="button--icon icon-edit"></i>
</button>
@ -168,6 +169,9 @@
</div>
<work-package-attachments edit data-ng-show="!vm.hideEmptyFields || vm.filesExist" work-package="vm.workPackage"></work-package-attachments>
<work-package-edit-actions work-package="vm.workPackage"></work-package-edit-actions>
</div>
</div>
<div class="work-packages--right-panel">

@ -1,7 +1,5 @@
<div class="work-packages--details-toolbar">
<button class="button"
accesskey="3"
ng-click="editWorkPackage()">
<div class="work-packages--details-toolbar" ng-hide="editAll.state">
<button class="button" accesskey="3" ng-click="editAll.start()">
<i class="button--icon icon-edit"></i>
<span class="button--text" ng-bind="::I18n.t('js.button_edit')"></span>
</button>

@ -0,0 +1,40 @@
<!--
~ -- 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.
~ ++
-->
<div class="work-packages--edit-actions" ng-show="efs.editAll.state">
<button class="button" accesskey="3" ng-click="efs.editAll.stop()">
<i class="button--icon icon-save1"></i>
<span class="button--text" ng-bind="::I18n.t('js.button_save')"></span>
</button>
<button class="button" accesskey="7" ng-click="efs.editAll.stop()">
<i class="button--icon icon-cancel"></i>
<span class="button--text" ng-bind="::I18n.t('js.button_cancel')"></span>
</button>
</div>

@ -64,6 +64,8 @@ module.exports = function($scope,
$scope.can = AuthorisationService.can;
$scope.cannot = AuthorisationService.cannot;
$scope.editAll = EditableFieldsState.editAll;
$scope.$on('$stateChangeSuccess', function(event, toState){
latestTab.registerState(toState.name);
});
@ -389,10 +391,6 @@ module.exports = function($scope,
$scope.workPackage
);
$scope.editWorkPackage = function() {
EditableFieldsState.editAll.toggleState();
};
// Stuff copied from DetailsTabOverviewController
var vm = this;

@ -85,9 +85,11 @@ angular.module('openproject.workPackages.directives')
'HookService',
'WorkPackageService',
'WorkPackageAuthorization',
'EditableFieldsState',
require('./work-package-details-toolbar-directive')
])
.directive('workPackageEditActions', [
require('./work-package-edit-actions-directive')
])
.directive('workPackageDynamicAttribute', ['$compile', require(
'./work-package-dynamic-attribute-directive')])
.directive('workPackageGroupHeader', require(

@ -194,13 +194,8 @@ module.exports = function(
}
$scope.$watch('editableFieldsState.editAll.state', function(state) {
var field = $scope.fieldController.field;
$scope.fieldController.isEditing = state;
$scope.fieldController.lockFocus = true;
if (EditableFieldsState.editAll.isFocusField(field)) {
vm.markActive();
}
});
},
link: function(scope, element, attrs, fieldController) {

@ -26,15 +26,15 @@
// See doc/COPYRIGHT.rdoc for more details.
//++
module.exports = function(PERMITTED_MORE_MENU_ACTIONS,
$state,
$window,
$location,
I18n,
HookService,
WorkPackageService,
WorkPackageAuthorization,
EditableFieldsState) {
module.exports = function(
PERMITTED_MORE_MENU_ACTIONS,
$state,
$window,
$location,
I18n,
HookService,
WorkPackageService,
WorkPackageAuthorization) {
function getPermittedActions(authorization, permittedMoreMenuActions) {
var permittedActions = authorization.permittedActions(permittedMoreMenuActions);
@ -76,7 +76,12 @@ module.exports = function(PERMITTED_MORE_MENU_ACTIONS,
scope: {
workPackage: '='
},
link: function(scope, element, attributes) {
controller: ['$scope', 'EditableFieldsState', function ($scope, EditableFieldsState) {
$scope.editAll = EditableFieldsState.editAll;
}],
link: function(scope) {
var authorization = new WorkPackageAuthorization(scope.workPackage);
scope.I18n = I18n;
@ -84,10 +89,6 @@ module.exports = function(PERMITTED_MORE_MENU_ACTIONS,
getPermittedPluginActions(authorization));
scope.actionsAvailable = Object.keys(scope.permittedActions).length > 0;
scope.editWorkPackage = function() {
EditableFieldsState.editAll.toggleState();
};
scope.triggerMoreMenuAction = function(action, link) {
switch (action) {
case 'delete':

@ -0,0 +1,43 @@
// -- 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.
// ++
module.exports = function () {
return {
restrict: 'E',
templateUrl: '/templates/work_packages/work_package_edit_actions.html',
scope: {
workPackage: '='
},
controller: ['$scope', 'I18n', 'EditableFieldsState',
function ($scope, I18n, EditableFieldsState) {
$scope.I18n = I18n;
$scope.efs = EditableFieldsState;
}]
};
};

@ -39,6 +39,14 @@ module.exports = function() {
focusField: 'subject',
state: false,
start: function () {
return this.state = true;
},
stop: function () {
return this.state = false;
},
toggleState: function () {
return this.state = !this.state;
},

@ -32,7 +32,11 @@ module.exports = function WorkPackageShowPage() {
this.editButton = $('.button[title="Edit"]');
this.focusElement = $('#work-package-subject .focus-input');
this.editableFields = $$('.focus-input');
this.editActions = {
container: $('.work-packages--edit-actions'),
cancel: $('.work-packages--edit-actions .button:last-child')
};
this.get = function() {
browser.get('/work_packages/' + wpId + '/activity');

@ -37,23 +37,37 @@ describe('Work package edit', function() {
};
beforeEach(function () {
page.get();
page.editButton.isPresent().then(function () {
page.editButton.click();
})
});
describe('when clicking edit button on show page', function () {
beforeEach(function () {
page.get();
page.editButton.isPresent().then(function () {
page.editButton.click();
})
});
it('should focus the subject field when used', function() {
page.focusElement.getId().then(expectFocusEquals);
});
it('should focus the subject field when used', function() {
page.focusElement.getId().then(expectFocusEquals);
});
it('should show multiple editable input fields', function() {
expect($$('.focus-input').count()).to.eventually.be.above(1);
});
it('should show multiple editable input fields', function() {
expect(page.editableFields.count()).to.eventually.be.above(1);
});
it('should reset previously edited fields without focusing one', function() {
page.editButton.click();
page.editButton.getId().then(expectFocusEquals);
expect(page.editableFields.count()).to.eventually.equal(0);
});
it('should show the edit actions', function () {
expect(page.editActions.container.isDisplayed()).to.eventually.be.true;
});
it('should reset previously edited fields without focusing one', function() {
page.editButton.click();
page.editButton.getId().then(expectFocusEquals);
describe('when triggering the edit actions', function () {
it('should cancel editing when the cancel button is clicked', function () {
page.editActions.cancel.click();
expect(page.editableFields.count()).to.eventually.equal(0);
});
});
});
});

@ -41,6 +41,14 @@ describe('EditableFieldsState service', function () {
expect(EditableFieldsState.state === eAll.toggleState()).to.be.false;
});
it('turns on editing on start', function () {
expect(eAll.start()).to.be.true;
});
it('turns off editing on stop', function () {
expect(eAll.stop()).to.be.false;
});
it('matches its focused field', function () {
expect(eAll.isFocusField(eAll.focusField)).to.be.true;
});

Loading…
Cancel
Save