first stab at updating form on type switch

pull/3701/head
Jens Ulferts 9 years ago
parent 31709781e9
commit 7577385057
  1. 92
      frontend/app/components/inplace-edit/directives/edit-pane/edit-pane.directive.js
  2. 15
      frontend/app/components/inplace-edit/directives/field-edit/edit-type/edit-type.directive.html
  3. 135
      frontend/app/components/inplace-edit/directives/field-edit/edit-type/edit-type.directive.js
  4. 6
      frontend/app/components/inplace-edit/services/work-package-field.service.js
  5. 2
      frontend/app/services/work-package-service.js
  6. 1
      frontend/app/templates/inplace-edit/edit/fields/type.html

@ -30,7 +30,7 @@ angular
.module('openproject.inplace-edit')
.directive('inplaceEditorEditPane', inplaceEditorEditPane);
function inplaceEditorEditPane(EditableFieldsState, FocusHelper, $timeout) {
function inplaceEditorEditPane(EditableFieldsState, FocusHelper, $timeout, $q) {
return {
transclude: true,
replace: true,
@ -48,6 +48,12 @@ function inplaceEditorEditPane(EditableFieldsState, FocusHelper, $timeout) {
return field.isRequired();
};
scope.$on('form.updateRequired', function() {
var submit = $q.defer();
scope.editPaneController.updateWorkPackageForm(submit);
});
scope.$watchCollection('editableFieldsState.workPackage.form', function(form) {
var strategy = field.getInplaceEditStrategy();
@ -117,7 +123,7 @@ function inplaceEditorEditPane(EditableFieldsState, FocusHelper, $timeout) {
}
};
}
inplaceEditorEditPane.$inject = ['EditableFieldsState', 'FocusHelper', '$timeout'];
inplaceEditorEditPane.$inject = ['EditableFieldsState', 'FocusHelper', '$timeout', '$q'];
function InplaceEditorEditPaneController($scope, $element, $location, $timeout, $q, $rootScope,
@ -153,15 +159,42 @@ function InplaceEditorEditPaneController($scope, $element, $location, $timeout,
});
};
this.handleFailure = function(submit, e) {
setFailure(e);
submit.reject(e);
};
this.updateWorkPackageForm = function(submit) {
WorkPackageService.loadWorkPackageForm(EditableFieldsState.workPackage).then(
function(form) {
field.resource.form = form;
EditableFieldsState.workPackage.form = form;
if (_.isEmpty(form.embedded.validationErrors.props)) {
submit.resolve();
} else {
afterError();
submit.reject();
EditableFieldsState.errors = {};
_.forEach(form.embedded.validationErrors.props, function(error, field) {
if(field === 'startDate' || field === 'dueDate') {
EditableFieldsState.errors['date'] = error.message;
} else {
EditableFieldsState.errors[field] = error.message;
}
});
showErrors();
}
}).catch(vm.handleFailure);
return submit.promise;
};
this.submitField = function() {
var submit = $q.defer();
var fieldController = $scope.fieldController;
var pendingFormChanges = EditableFieldsState.getPendingFormChanges();
var detectedViolations = [];
var handleFailure = function(e) {
setFailure(e);
submit.reject(e);
};
pendingFormChanges[field.name] = field.value;
if (vm.editForm.$invalid) {
@ -182,39 +215,22 @@ function InplaceEditorEditPaneController($scope, $element, $location, $timeout,
submit.reject();
} else {
fieldController.state.isBusy = true;
WorkPackageService.loadWorkPackageForm(EditableFieldsState.workPackage).then(
function(form) {
EditableFieldsState.workPackage.form = form;
if (_.isEmpty(form.embedded.validationErrors.props)) {
var result = WorkPackageService.updateWorkPackage(
EditableFieldsState.workPackage
);
result.then(angular.bind(this, function(updatedWorkPackage) {
submit.resolve();
field.resource = _.extend(field.resource, updatedWorkPackage);
$scope.$emit('workPackageUpdatedInEditor', updatedWorkPackage);
$scope.$on('workPackageRefreshed', function() {
fieldController.state.isBusy = false;
fieldController.isEditing = false;
});
uploadPendingAttachments(updatedWorkPackage);
})).catch(handleFailure);
} else {
afterError();
submit.reject();
EditableFieldsState.errors = {};
_.forEach(form.embedded.validationErrors.props, function(error, field) {
if(field === 'startDate' || field === 'dueDate') {
EditableFieldsState.errors['date'] = error.message;
} else {
EditableFieldsState.errors[field] = error.message;
}
});
vm.updateWorkPackageForm(submit).then(function() {
var result = WorkPackageService.updateWorkPackage(
EditableFieldsState.workPackage
);
result.then(angular.bind(this, function(updatedWorkPackage) {
submit.resolve();
field.resource = _.extend(field.resource, updatedWorkPackage);
showErrors();
}
}).catch(handleFailure);
$scope.$emit('workPackageUpdatedInEditor', updatedWorkPackage);
$scope.$on('workPackageRefreshed', function() {
fieldController.state.isBusy = false;
fieldController.isEditing = false;
});
uploadPendingAttachments(updatedWorkPackage);
})).catch(vm.handleFailure);
});
}
return submit.promise;

@ -0,0 +1,15 @@
<div class="dropdown-wrapper">
<label
class="hidden-for-sighted"
for="inplace-edit--write-value--{{::field.name}}">
{{::field.getLabel()}}
</label>
<select
ng-disabled="fieldController.state.isBusy"
ng-model="field.value.props"
title="{{ fieldController.editTitle }}"
class="inplace-edit-select"
id="inplace-edit--write-value--{{::field.name}}"
ng-options="option as option.name for option in customEditorController.allowedValues track by option.hrefTracker">
</select>
</div>

@ -0,0 +1,135 @@
// -- 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.
// ++
angular
.module('openproject.inplace-edit')
.directive('inplaceEditorType', inplaceEditorType);
function inplaceEditorType(EditableFieldsState, FocusHelper, WorkPackageService) {
return {
restrict: 'E',
transclude: true,
replace: true,
require: '^workPackageField',
templateUrl: '/components/inplace-edit/directives/field-edit/edit-type/' +
'edit-type.directive.html',
controller: InplaceEditorTypeController,
controllerAs: 'customEditorController',
link: function(scope, element, attrs, fieldController) {
var field = scope.field;
fieldController.state.isBusy = true;
scope.emptyField = !scope.field.isRequired();
scope.customEditorController.updateAllowedValues(field.name).then(function() {
fieldController.state.isBusy = false;
if (!EditableFieldsState.forcedEditState) {
EditableFieldsState.editAll.state || FocusHelper.focusUiSelect(element);
}
});
scope.$watch('field.value.props', function(newValue, oldValue) {
if (newValue.hrefTracker !== oldValue.hrefTracker) {
scope.$emit('form.updateRequired');
}
});
}
};
}
inplaceEditorType.$inject = ['EditableFieldsState', 'FocusHelper', 'WorkPackageService'];
function InplaceEditorTypeController($q, $scope, I18n, WorkPackageFieldConfigurationService) {
this.allowedValues = [];
this.updateAllowedValues = function(field) {
var customEditorController = this;
return $q(function(resolve) {
$scope.field.getAllowedValues()
.then(function(values) {
var sorting = WorkPackageFieldConfigurationService
.getDropdownSortingStrategy(field);
if (sorting !== null) {
values = _.sortBy(values, sorting);
}
if (!$scope.field.isRequired()) {
values = addEmptyOption(values);
}
addHrefTracker(values);
customEditorController.allowedValues = values;
resolve();
});
});
};
var addEmptyOption = function(values) {
var emptyOption = { props: { href: null,
name: $scope.field.placeholder } };
if (!$scope.field.isRequired()) {
var arrayWithEmptyOption = [emptyOption.props];
values = arrayWithEmptyOption.concat(values);
if ($scope.field.value === null) {
$scope.field.value = emptyOption;
}
}
return values;
};
// We have to maintain a separate property just to track the object by
// in the template. This is due to angular aparently not being able to
// track correclty with a field having null as it's value. It does work for
// 'null' (String) however.
var addHrefTracker = function(values) {
_.forEach(values, function(value) {
value.hrefTracker = String(value.href);
});
$scope.field.value.props.hrefTracker = String($scope.field.value.props.href);
};
}
InplaceEditorTypeController.$inject = [
'$q',
'$scope',
'I18n',
'WorkPackageFieldConfigurationService'];

@ -263,13 +263,15 @@ function WorkPackageFieldService($q, $http, $filter, I18n, WorkPackagesHelper,
case 'Duration':
inplaceType = 'duration';
break;
case 'Type':
inplaceType = 'type';
break;
case 'StringObject':
case 'Version':
case 'User':
case 'Status':
case 'Priority':
case 'Category':
case 'Type':
case 'Version':
inplaceType = 'drop-down';
break;
}

@ -225,7 +225,7 @@ module.exports = function($http,
headers: {
Accept: 'application/hal+json'
},
data:getPendingChanges(workPackage),
data: getPendingChanges(workPackage),
contentType: 'application/json; charset=utf-8'
}, force: true};

@ -0,0 +1 @@
<inplace-editor-type></inplace-editor-type>
Loading…
Cancel
Save