diff --git a/frontend/app/components/inplace-edit/directives/field-edit/edit-type/edit-type.directive.js b/frontend/app/components/inplace-edit/directives/field-edit/edit-type/edit-type.directive.js
new file mode 100644
index 0000000000..b7ec2e1d06
--- /dev/null
+++ b/frontend/app/components/inplace-edit/directives/field-edit/edit-type/edit-type.directive.js
@@ -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'];
diff --git a/frontend/app/components/inplace-edit/services/work-package-field.service.js b/frontend/app/components/inplace-edit/services/work-package-field.service.js
index af5542efb5..18a5ecb975 100644
--- a/frontend/app/components/inplace-edit/services/work-package-field.service.js
+++ b/frontend/app/components/inplace-edit/services/work-package-field.service.js
@@ -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;
}
diff --git a/frontend/app/services/work-package-service.js b/frontend/app/services/work-package-service.js
index ec33785d77..9edb87229d 100644
--- a/frontend/app/services/work-package-service.js
+++ b/frontend/app/services/work-package-service.js
@@ -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};
diff --git a/frontend/app/templates/inplace-edit/edit/fields/type.html b/frontend/app/templates/inplace-edit/edit/fields/type.html
new file mode 100644
index 0000000000..fd66fb0984
--- /dev/null
+++ b/frontend/app/templates/inplace-edit/edit/fields/type.html
@@ -0,0 +1 @@
+