Merge pull request #3834 from furinvader/bugs/22046/type-field-error

[22046] Fix work package creation error
pull/3842/head
Oliver Günther 9 years ago
commit 2af7db9886
  1. 8
      frontend/app/components/inplace-edit/directives/edit-pane/edit-pane.directive.js
  2. 5
      frontend/app/components/inplace-edit/directives/work-package-field/work-package-field.directive.js
  3. 9
      frontend/app/components/inplace-edit/services/editable-fields-state.service.js
  4. 3
      frontend/app/components/inplace-edit/services/editable-fields-state.service.test.js
  5. 38
      frontend/app/components/inplace-edit/services/inplace-edit-errors.service.js
  6. 74
      frontend/app/components/inplace-edit/services/inplace-edit-form.service.js
  7. 16
      frontend/app/components/inplace-edit/services/inplace-edit-form.service.test.js
  8. 4
      frontend/app/components/inplace-edit/services/inplace-edit-multi-storage.service.js
  9. 20
      frontend/app/components/inplace-edit/services/inplace-edit-storage.service.js
  10. 41
      frontend/app/components/inplace-edit/services/inplace-edit.service.js
  11. 13
      frontend/app/components/inplace-edit/services/work-package-field.service.js
  12. 11
      frontend/app/components/work-packages/services/work-package.service.js
  13. 2
      frontend/app/openproject-app.js
  14. 2
      frontend/tests/unit/tests/components/inplace-edit/directives/edit-drop-down.directive.test.js

@ -85,11 +85,9 @@ function inplaceEditorEditPane(EditableFieldsState, FocusHelper, $timeout) {
}
};
}
inplaceEditorEditPane.$inject = ['EditableFieldsState', 'FocusHelper', '$timeout'];
function InplaceEditorEditPaneController($scope, $element, $location, $timeout,
EditableFieldsState, inplaceEditStorage, inplaceEditMultiStorage) {
EditableFieldsState, inplaceEditStorage, inplaceEditMultiStorage, inplaceEditErrors) {
var vm = this;
var field = $scope.field;
@ -113,8 +111,8 @@ function InplaceEditorEditPaneController($scope, $element, $location, $timeout,
}
if (detectedViolations.length) {
EditableFieldsState.errors = EditableFieldsState.errors || {};
EditableFieldsState.errors[field.name] = detectedViolations.join(' ');
inplaceEditErrors.errors = inplaceEditErrors.errors || {};
inplaceEditErrors.errors[field.name] = detectedViolations.join(' ');
}
inplaceEditMultiStorage.save().then(function () {

@ -46,10 +46,10 @@ function workPackageField() {
};
}
function WorkPackageFieldController($scope, EditableFieldsState, inplaceEdit) {
function WorkPackageFieldController($scope, EditableFieldsState, inplaceEditForm) {
var workPackage = EditableFieldsState.workPackage;
this.state = EditableFieldsState;
$scope.field = inplaceEdit.form(workPackage.props.id, workPackage).field(this.fieldName);
$scope.field = inplaceEditForm.getForm(workPackage.props.id, workPackage).field(this.fieldName);
var field = $scope.field;
@ -59,5 +59,4 @@ function WorkPackageFieldController($scope, EditableFieldsState, inplaceEdit) {
this.editTitle = I18n.t('js.inplace.button_edit', { attribute: field.getLabel() });
}
}
WorkPackageFieldController.$inject = ['$scope', 'EditableFieldsState', 'inplaceEdit'];

@ -30,10 +30,10 @@ angular
.module('openproject.workPackages.services')
.factory('EditableFieldsState', EditableFieldsState);
function EditableFieldsState($rootScope, $window) {
function EditableFieldsState($rootScope, $window, inplaceEditErrors, inplaceEditForm) {
var EditableFieldsState = {
workPackage: null,
errors: null,
errors: inplaceEditErrors.errors,
isBusy: false,
currentField: null,
forcedEditState: false,
@ -50,8 +50,8 @@ function EditableFieldsState($rootScope, $window) {
discard: function (fieldName) {
delete this.getPendingFormChanges()[fieldName];
if (this.errors && this.errors.hasOwnProperty(fieldName)) {
delete this.errors[fieldName];
if (inplaceEditErrors.errors && inplaceEditErrors.hasOwnProperty(fieldName)) {
delete inplaceEditErrors.errors[fieldName];
}
},
@ -59,6 +59,7 @@ function EditableFieldsState($rootScope, $window) {
focusField: 'subject',
cancel: function () {
inplaceEditForm.deleteNewForm();
this.stop();
},

@ -29,7 +29,8 @@
describe('EditableFieldsState service', function () {
var EditableFieldsState, eAll;
beforeEach(angular.mock.module('openproject.services', 'openproject.workPackages.services'));
beforeEach(angular.mock.module('openproject.config', 'openproject.services',
'openproject.workPackages.services'));
beforeEach(inject(function (_EditableFieldsState_) {
EditableFieldsState = _EditableFieldsState_;

@ -0,0 +1,38 @@
// -- 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
// TODO: this should be the 'inplace-edit' module
.module('openproject.workPackages.services')
.factory('inplaceEditErrors', inplaceEditErrors);
function inplaceEditErrors() {
return {
errors: null
};
}

@ -0,0 +1,74 @@
// -- 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')
.factory('inplaceEditForm', inplaceEditForm);
function inplaceEditForm($rootScope, inplaceEdit) {
var inplaceEditForm,
forms = {};
function Form(resource) {
this.resource = resource;
this.fields = {};
this.field = function (name) {
this.fields[name] = this.fields[name] || new inplaceEdit.Field(this.resource, name);
return this.fields[name];
};
}
Object.defineProperty(Form.prototype, 'length', {
get: function () {
return Object.keys(this.fields).length;
}
});
$rootScope.$on('workPackageUpdatedInEditor', function (event, updatedWorkPackage) {
var form = inplaceEditForm.getForm(updatedWorkPackage.props.id);
form.resource = _.extend(form.resource, updatedWorkPackage);
});
return inplaceEditForm = {
getForm: function (id, resource) {
forms[id] = forms[id] || new Form(resource);
if (!forms[id].resource) {
forms[id].resource = resource;
}
return forms[id];
},
deleteNewForm: function () {
delete forms['undefined'];
}
};
}

@ -27,7 +27,7 @@
// ++
describe('Inplace edit service', function () {
var inplaceEdit,
var inplaceEditForm,
resources = ['some object', 'some other object'],
WorkPackageFieldService = {};
@ -36,16 +36,16 @@ describe('Inplace edit service', function () {
WorkPackageFieldService.getValue = sinon.stub()
}));
beforeEach(inject(function(_inplaceEdit_) {
inplaceEdit = _inplaceEdit_;
beforeEach(inject(function(_inplaceEditForm_) {
inplaceEditForm = _inplaceEditForm_;
inplaceEdit.form(1, resources[0]).field('myField');
inplaceEdit.form(2, resources[1]).field('myField');
inplaceEdit.form(2, resources[1]).field('myOtherField');
inplaceEditForm.getForm(1, resources[0]).field('myField');
inplaceEditForm.getForm(2, resources[1]).field('myField');
inplaceEditForm.getForm(2, resources[1]).field('myOtherField');
}));
it('should return correct number of fields', function () {
expect(inplaceEdit.form(1).length).to.equal(1);
expect(inplaceEdit.form(2).length).to.equal(2);
expect(inplaceEditForm.getForm(1).length).to.equal(1);
expect(inplaceEditForm.getForm(2).length).to.equal(2);
});
});

@ -32,7 +32,7 @@ angular
function inplaceEditMultiStorage($rootScope, $q, inplaceEditStorage, EditableFieldsState,
NotificationsService) {
NotificationsService, inplaceEditErrors) {
$rootScope.$on('inplaceEditMultiStorage.save.workPackage', function (event, promise) {
promise.catch(function (errors) {
@ -69,7 +69,7 @@ function inplaceEditMultiStorage($rootScope, $q, inplaceEditStorage, EditableFie
}).finally(function () {
promises = [];
EditableFieldsState.errors = null;
inplaceEditErrors.errors = null;
EditableFieldsState.isBusy = false;
});
},

@ -31,15 +31,15 @@ angular
.factory('inplaceEditStorage', inplaceEditStorage);
function inplaceEditStorage($q, $rootScope, EditableFieldsState, WorkPackageService,
ActivityService, inplaceEdit, ApiHelper) {
ActivityService, inplaceEditForm, ApiHelper, inplaceEditErrors) {
var handleAPIErrors = function (deferred) {
return function (errors) {
EditableFieldsState.errors = {
inplaceEditErrors.errors = {
_common: ApiHelper.getErrorMessages(errors)
};
deferred.reject(EditableFieldsState.errors)
deferred.reject(inplaceEditErrors.errors)
}
};
@ -47,8 +47,8 @@ function inplaceEditStorage($q, $rootScope, EditableFieldsState, WorkPackageServ
saveWorkPackage: function () {
var deferred = $q.defer();
if (EditableFieldsState.errors) {
deferred.reject(EditableFieldsState.errors);
if (inplaceEditErrors.errors) {
deferred.reject(inplaceEditErrors.errors);
return deferred.promise;
}
@ -81,7 +81,7 @@ function inplaceEditStorage($q, $rootScope, EditableFieldsState, WorkPackageServ
var deferred = $q.defer();
WorkPackageService.loadWorkPackageForm(EditableFieldsState.workPackage)
.then(function(form) {
inplaceEdit.form(EditableFieldsState.workPackage.props.id).resource.form = form;
inplaceEditForm.getForm(EditableFieldsState.workPackage.props.id).resource.form = form;
EditableFieldsState.workPackage.form = form;
deferred.resolve(form);
@ -102,16 +102,16 @@ function inplaceEditStorage($q, $rootScope, EditableFieldsState, WorkPackageServ
deferred.resolve(form);
} else {
EditableFieldsState.errors = {};
inplaceEditErrors.errors = {};
_.forEach(form.embedded.validationErrors.props, function(error, field) {
if(field === 'startDate' || field === 'dueDate') {
EditableFieldsState.errors['date'] = error.message;
inplaceEditErrors.errors['date'] = error.message;
} else {
EditableFieldsState.errors[field] = error.message;
inplaceEditErrors.errors[field] = error.message;
}
});
deferred.reject(EditableFieldsState.errors);
deferred.reject(inplaceEditErrors.errors);
}
}).catch(deferred.reject);

@ -30,26 +30,7 @@ angular
.module('openproject.inplace-edit')
.factory('inplaceEdit', inplaceEdit);
function inplaceEdit($rootScope, WorkPackageFieldService) {
var forms = {}, service;
function Form(resource) {
this.resource = resource;
this.fields = {};
this.field = function (name) {
this.fields[name] = this.fields[name] || new Field(this.resource, name);
return this.fields[name];
};
}
Object.defineProperty(Form.prototype, 'length', {
get: function () {
return Object.keys(this.fields).length;
}
});
function inplaceEdit(WorkPackageFieldService) {
function Field(resource, name) {
this.resource = resource;
this.name = name;
@ -102,21 +83,7 @@ function inplaceEdit($rootScope, WorkPackageFieldService) {
} || property;
});
$rootScope.$on('workPackageUpdatedInEditor', function (event, updatedWorkPackage) {
var form = service.form(updatedWorkPackage.props.id);
form.resource = _.extend(form.resource, updatedWorkPackage);
});
return service = {
form: function (id, resource) {
forms[id] = forms[id] || new Form(resource);
if (!forms[id].resource) {
forms[id].resource = resource;
}
return forms[id];
}
};
return {
Field: Field
}
}
inplaceEdit.$inject = ['$rootScope', 'WorkPackageFieldService'];

@ -31,7 +31,7 @@ angular
.service('WorkPackageFieldService', WorkPackageFieldService);
function WorkPackageFieldService($q, $http, $filter, I18n, WorkPackagesHelper, HookService,
EditableFieldsState ) {
inplaceEditErrors) {
function getSchema(workPackage) {
if (workPackage.form) {
@ -81,7 +81,7 @@ function WorkPackageFieldService($q, $http, $filter, I18n, WorkPackagesHelper,
// e.g. when an error should trigger the editing state
// of an empty field after type change
function isHideable(workPackage, field) {
if (EditableFieldsState.errors && EditableFieldsState.errors[field]) {
if (inplaceEditErrors.errors && inplaceEditErrors.errors[field]) {
return false;
}
return isEmpty(workPackage, field);
@ -403,12 +403,3 @@ function WorkPackageFieldService($q, $http, $filter, I18n, WorkPackagesHelper,
return WorkPackageFieldService;
}
WorkPackageFieldService.$inject = [
'$q',
'$http',
'$filter',
'I18n',
'WorkPackagesHelper',
'HookService',
'EditableFieldsState'];

@ -33,7 +33,8 @@ angular
function WorkPackageService($http, PathHelper, WorkPackagesHelper, HALAPIResource,
DEFAULT_FILTER_PARAMS, DEFAULT_PAGINATION_OPTIONS, $rootScope, $window, $q, $cacheFactory,
AuthorisationService, EditableFieldsState, WorkPackageFieldService, NotificationsService) {
AuthorisationService, EditableFieldsState, WorkPackageFieldService, NotificationsService,
inplaceEditErrors) {
var workPackage,
workPackageCache = $cacheFactory('workPackageCache');
@ -102,7 +103,7 @@ function WorkPackageService($http, PathHelper, WorkPackagesHelper, HALAPIResourc
form.pendingChanges = changes;
wp.form = form;
EditableFieldsState.workPackage = wp;
EditableFieldsState.errors = null;
inplaceEditErrors.errors = null;
return wp;
});
},
@ -120,7 +121,7 @@ function WorkPackageService($http, PathHelper, WorkPackagesHelper, HALAPIResourc
wp.schema = result[1];
workPackage = wp;
EditableFieldsState.workPackage = wp;
EditableFieldsState.errors = null;
inplaceEditErrors.errors = null;
return wp;
});
});
@ -356,7 +357,3 @@ function WorkPackageService($http, PathHelper, WorkPackagesHelper, HALAPIResourc
return WorkPackageService;
}
WorkPackageService.$inject = ['$http', 'PathHelper', 'WorkPackagesHelper', 'HALAPIResource',
'DEFAULT_FILTER_PARAMS', 'DEFAULT_PAGINATION_OPTIONS', '$rootScope', '$window', '$q',
'$cacheFactory', 'AuthorisationService', 'EditableFieldsState', 'WorkPackageFieldService',
'NotificationsService'];

@ -120,7 +120,7 @@ angular.module('openproject.workPackages', [
'ng-context-menu',
'ngFileUpload'
]);
angular.module('openproject.workPackages.services', []);
angular.module('openproject.workPackages.services', ['openproject.inplace-edit']);
angular.module(
'openproject.workPackages.helpers', [
'openproject.helpers',

@ -32,7 +32,7 @@ describe('Inplace editor drop-down directive', function() {
html = '<div><inplace-editor-drop-down></inplace-editor-drop-down></div>';
beforeEach(angular.mock.module('openproject.inplace-edit'));
beforeEach(angular.mock.module('openproject.config', 'openproject.inplace-edit'));
beforeEach(module('openproject.services', function($provide) {
$provide.constant('WorkPackageService', {});

Loading…
Cancel
Save