OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openproject/frontend/app/components/inplace-edit/directives/edit-pane/edit-pane.directive.js

185 lines
5.9 KiB

// -- 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('inplaceEditorEditPane', inplaceEditorEditPane);
function inplaceEditorEditPane(EditableFieldsState, FocusHelper, $timeout) {
return {
transclude: true,
require: '^workPackageField',
templateUrl: '/components/inplace-edit/directives/edit-pane/edit-pane.directive.html',
controllerAs: 'editPaneController',
controller: InplaceEditorEditPaneController,
link: function(scope, element, attrs, fieldController) {
var field = scope.field;
scope.fieldController = fieldController;
scope.editableFieldsState = EditableFieldsState;
scope.focusInput = function() {
$timeout(function() {
var inputElement = element.find('.focus-input');
FocusHelper.focus(inputElement);
inputElement.triggerHandler('keyup');
scope.editPaneController.markActive();
inputElement.off('focus.inplace').on('focus.inplace', function() {
scope.$apply(function() {
scope.editPaneController.markActive();
});
});
});
};
if (!EditableFieldsState.forcedEditState) {
element.bind('keydown keypress', function(e) {
if (e.keyCode === 27 && !EditableFieldsState.editAll.state) {
scope.$apply(function() {
scope.editPaneController.discardEditing();
});
}
});
}
scope.$watch('fieldController.isEditing', function(isEditing) {
var efs = EditableFieldsState;
if (isEditing && !efs.editAll.state && !efs.forcedEditState) {
scope.focusInput();
} else if (efs.editAll.state && efs.editAll.isFocusField(field.name)) {
$timeout(function () {
var focusElement = element.find('.focus-input');
focusElement.length && focusElement.focus()[0].select();
});
}
});
}
};
}
function InplaceEditorEditPaneController($scope, $element, $location, $timeout,
EditableFieldsState, inplaceEditStorage, inplaceEditMultiStorage, inplaceEditErrors) {
var vm = this;
var field = $scope.field;
var fieldLabel = field.getLabel();
var wpStore = inplaceEditMultiStorage.stores.workPackage;
this.saveTitle = I18n.t('js.inplace.button_save', { attribute: fieldLabel });
this.cancelTitle = I18n.t('js.inplace.button_cancel', { attribute: fieldLabel });
this.submit = function() {
var detectedViolations = [];
if (vm.editForm.$invalid) {
Object.keys(vm.editForm.$error).forEach(function(error) {
if (vm.editForm.$error[error]) {
detectedViolations.push(I18n.t('js.inplace.errors.' + error, {
field: field.getLabel()
}));
}
});
}
if (detectedViolations.length) {
inplaceEditErrors.errors = inplaceEditErrors.errors || {};
inplaceEditErrors.errors[field.name] = detectedViolations.join(' ');
}
inplaceEditMultiStorage.save().then(function () {
$location.hash(null);
$timeout(function() {
$element[0].scrollIntoView(false);
});
}).catch(function () {
$scope.focusInput();
});
};
this.discardEditing = function() {
$scope.fieldController.isEditing = false;
EditableFieldsState.discard(field.name);
};
this.isActive = function() {
return EditableFieldsState.isActiveField(field.name);
};
this.markActive = function() {
wpStore.active = true;
EditableFieldsState.currentField = field.name;
};
this.isRequired = function() {
return field.isRequired();
};
$scope.$watch('editableFieldsState.editAll.state', function(state) {
$scope.fieldController.isEditing = state;
$scope.fieldController.lockFocus = true;
});
$scope.$watch('field.value', function(value) {
if ($scope.fieldController.isEditing) {
var pendingChanges = EditableFieldsState.getPendingFormChanges();
pendingChanges[field.name] = value;
vm.markActive();
}
}, true);
$scope.$watchCollection('field.resource.form', function(form) {
var strategy = field.getInplaceEditStrategy();
if (field.name === 'date' && strategy === 'date') {
form.pendingChanges = EditableFieldsState.getPendingFormChanges();
form.pendingChanges['startDate'] =
form.pendingChanges['dueDate'] =
field.value ? field.value['dueDate'] : null;
}
if (strategy !== $scope.strategy) {
$scope.strategy = strategy;
$scope.templateUrl = '/templates/inplace-edit/edit/fields/' + strategy + '.html';
}
});
$scope.$on('form.updateRequired', function() {
inplaceEditStorage.refreshWorkPackageForm();
});
$scope.$on('workPackageRefreshed', function() {
vm.discardEditing();
});
}