diff --git a/frontend/app/components/common/services/hal-api-resource.service.js b/frontend/app/components/common/services/hal-api-resource.service.js index 22eced6d42..8e94194766 100644 --- a/frontend/app/components/common/services/hal-api-resource.service.js +++ b/frontend/app/components/common/services/hal-api-resource.service.js @@ -33,8 +33,6 @@ angular.module('openproject.api') .run(run) .factory('HALAPIResource', HALAPIResource); -run.$inject = ['$http', '$q']; - function run($http, $q) { Hyperagent.configure('ajax', function(settings) { settings.transformResponse = function (data) { return data; }; @@ -47,6 +45,8 @@ function run($http, $q) { Hyperagent.configure('defer', $q.defer); Hyperagent.configure('_', _); } +run.$inject = ['$http', '$q']; + function HALAPIResource () { return { diff --git a/frontend/app/components/inplace-edit/directives/display-pane/display-pane.directive.js b/frontend/app/components/inplace-edit/directives/display-pane/display-pane.directive.js index 78d9d2b130..8ca00cb23e 100644 --- a/frontend/app/components/inplace-edit/directives/display-pane/display-pane.directive.js +++ b/frontend/app/components/inplace-edit/directives/display-pane/display-pane.directive.js @@ -26,100 +26,106 @@ // See doc/COPYRIGHT.rdoc for more details. // ++ -angular.module('openproject.inplace-edit').directive('inplaceEditorDisplayPane',[ - 'WorkPackageFieldService', 'EditableFieldsState', '$timeout', 'HookService', 'I18n', +angular + .module('openproject.inplace-edit') + .directive('inplaceEditorDisplayPane', inplaceEditorDisplayPane); - function(WorkPackageFieldService, EditableFieldsState, $timeout, HookService, I18n) { - return { - replace: true, - transclude: true, - scope: {}, - require: '^workPackageField', - templateUrl: '/components/inplace-edit/directives/display-pane/display-pane.directive.html', - controller: function($scope) { +function inplaceEditorDisplayPane(WorkPackageFieldService, EditableFieldsState, $timeout, I18n) { + return { + replace: true, + transclude: true, + scope: {}, + require: '^workPackageField', + templateUrl: '/components/inplace-edit/directives/display-pane/display-pane.directive.html', + controller: InplaceEditorDisplayPaneController, + controllerAs: 'displayPaneController', - this.placeholder = WorkPackageFieldService.defaultPlaceholder; + link: function(scope, element, attrs, fieldController) { + scope.fieldController = fieldController; + scope.displayPaneController.field = scope.fieldController.field; + scope.editableFieldsState = EditableFieldsState; - this.startEditing = function() { - var fieldController = $scope.fieldController; - fieldController.isEditing = true; - }; + scope.$watchCollection('editableFieldsState.workPackage.form', function() { + var strategy = WorkPackageFieldService.getInplaceDisplayStrategy( + EditableFieldsState.workPackage, + fieldController.field + ); + if (strategy !== scope.displayStrategy) { + scope.displayStrategy = strategy; + scope.templateUrl = '/templates/inplace-edit/display/fields/' + strategy +'.html'; + } + }); - this.isReadValueEmpty = function() { - return WorkPackageFieldService.isEmpty( - EditableFieldsState.workPackage, - $scope.fieldController.field - ); - }; + // TODO: extract this when more placeholders come + if (fieldController.field === 'description') { + scope.displayPaneController.placeholder = I18n.t('js.label_click_to_enter_description'); + } - this.getReadValue = function() { - return WorkPackageFieldService.format( - EditableFieldsState.workPackage, - $scope.fieldController.field - ); - }; + scope.$watch('editableFieldsState.errors', function(errors) { + if (errors) { + if (errors[scope.fieldController.field]) { + scope.displayPaneController.startEditing(); + } + } + }, true); - // for dynamic type that is set by plugins - // refactor to a service method the whole extraction - this.getDynamicDirectiveName = function() { - return HookService.call('workPackageOverviewAttributes', { - type: EditableFieldsState.workPackage.schema.props[$scope.fieldController.field].type, - field: $scope.fieldController.field, - workPackage: EditableFieldsState.workPackage - })[0]; - }; + scope.$watch('fieldController.isEditing', function(isEditing, oldIsEditing) { + if (!isEditing && !fieldController.lockFocus) { + $timeout(function() { + if (oldIsEditing) { + // check old value to not trigger focus on the first time + element.find('.inplace-editing--trigger-link').focus(); + } + element.find('.inplace-edit--read-value a').off('click').on('click', function(e) { + e.stopPropagation(); + }); + }); + } - // expose work package to the dynamic directive - this.getWorkPackage = function() { - return EditableFieldsState.workPackage; - }; - }, - controllerAs: 'displayPaneController', - link: function(scope, element, attrs, fieldController) { - scope.fieldController = fieldController; - scope.displayPaneController.field = scope.fieldController.field; - scope.editableFieldsState = EditableFieldsState; + fieldController.lockFocus = false; + }); + } + }; +} +inplaceEditorDisplayPane.$inject = ['WorkPackageFieldService', 'EditableFieldsState', '$timeout', 'I18n']; - scope.$watchCollection('editableFieldsState.workPackage.form', function() { - var strategy = WorkPackageFieldService.getInplaceDisplayStrategy( - EditableFieldsState.workPackage, - fieldController.field - ); - if (strategy !== scope.displayStrategy) { - scope.displayStrategy = strategy; - scope.templateUrl = '/templates/inplace-edit/display/fields/' + strategy +'.html'; - } - }); +function InplaceEditorDisplayPaneController($scope, WorkPackageFieldService, EditableFieldsState, + HookService) { - // TODO: extract this when more placeholders come - if (fieldController.field === 'description') { - scope.displayPaneController.placeholder = I18n.t('js.label_click_to_enter_description'); - } + this.placeholder = WorkPackageFieldService.defaultPlaceholder; - scope.$watch('editableFieldsState.errors', function(errors) { - if (errors) { - if (errors[scope.fieldController.field]) { - scope.displayPaneController.startEditing(); - } - } - }, true); + this.startEditing = function() { + var fieldController = $scope.fieldController; + fieldController.isEditing = true; + }; - scope.$watch('fieldController.isEditing', function(isEditing, oldIsEditing) { - if (!isEditing && !fieldController.lockFocus) { - $timeout(function() { - if (oldIsEditing) { - // check old value to not trigger focus on the first time - element.find('.inplace-editing--trigger-link').focus(); - } - element.find('.inplace-edit--read-value a').off('click').on('click', function(e) { - e.stopPropagation(); - }); - }); - } + this.isReadValueEmpty = function() { + return WorkPackageFieldService.isEmpty( + EditableFieldsState.workPackage, + $scope.fieldController.field + ); + }; - fieldController.lockFocus = false; - }); - } - }; - } -]); + this.getReadValue = function() { + return WorkPackageFieldService.format( + EditableFieldsState.workPackage, + $scope.fieldController.field + ); + }; + + // for dynamic type that is set by plugins + // refactor to a service method the whole extraction + this.getDynamicDirectiveName = function() { + return HookService.call('workPackageOverviewAttributes', { + type: EditableFieldsState.workPackage.schema.props[$scope.fieldController.field].type, + field: $scope.fieldController.field, + workPackage: EditableFieldsState.workPackage + })[0]; + }; + + // expose work package to the dynamic directive + this.getWorkPackage = function() { + return EditableFieldsState.workPackage; + }; +} +InplaceEditorDisplayPaneController.$inject = ['$scope', 'WorkPackageFieldService', 'EditableFieldsState', 'HookService']; diff --git a/frontend/app/components/inplace-edit/directives/edit-pane/edit-pane.directive.js b/frontend/app/components/inplace-edit/directives/edit-pane/edit-pane.directive.js index 7b4064f2d8..ccc0841d03 100644 --- a/frontend/app/components/inplace-edit/directives/edit-pane/edit-pane.directive.js +++ b/frontend/app/components/inplace-edit/directives/edit-pane/edit-pane.directive.js @@ -26,241 +26,249 @@ // See doc/COPYRIGHT.rdoc for more details. // ++ -angular.module('openproject.inplace-edit').directive('inplaceEditorEditPane', [ - 'WorkPackageFieldService', 'EditableFieldsState', 'FocusHelper', '$timeout', '$location', '$q', - 'ApiHelper', '$rootScope', 'NotificationsService', 'I18n', +angular + .module('openproject.inplace-edit') + .directive('inplaceEditorEditPane', inplaceEditorEditPane); - function(WorkPackageFieldService, EditableFieldsState, FocusHelper, $timeout, $location, $q, - ApiHelper, $rootScope, NotificationsService, I18n) { +function inplaceEditorEditPane(WorkPackageFieldService, EditableFieldsState, FocusHelper, + $timeout) { - var showErrors = function() { - var errors = EditableFieldsState.errors; - if (_.isEmpty(_.keys(errors))) { - return; - } - var errorMessages = _.flatten(_.map(errors), true); - NotificationsService.addError(I18n.t('js.label_validation_error'), errorMessages); - }; + return { + transclude: true, + replace: true, + scope: true, + require: '^workPackageField', + templateUrl: '/components/inplace-edit/directives/edit-pane/edit-pane.directive.html', + controllerAs: 'editPaneController', + controller: InplaceEditorEditPaneController, + link: function(scope, element, attrs, fieldController) { + scope.fieldController = fieldController; + scope.editableFieldsState = EditableFieldsState; + + scope.editPaneController.isRequired = function() { + return WorkPackageFieldService.isRequired( + EditableFieldsState.workPackage, + this.field + ); + }; - return { - transclude: true, - replace: true, - scope: true, - require: '^workPackageField', - templateUrl: '/components/inplace-edit/directives/edit-pane/edit-pane.directive.html', - controllerAs: 'editPaneController', - controller: function($scope, $element, WorkPackageService) { - var vm = this; + scope.$watchCollection('editableFieldsState.workPackage.form', function(form) { + var strategy = WorkPackageFieldService.getInplaceEditStrategy( + EditableFieldsState.workPackage, + fieldController.field + ); + + if (fieldController.field === 'date' && strategy === 'date') { + form.pendingChanges = EditableFieldsState.getPendingFormChanges(); + form.pendingChanges['startDate'] = + form.pendingChanges['dueDate'] = + fieldController.writeValue ? fieldController.writeValue['dueDate'] : null; + } - // go full retard - var uploadPendingAttachments = function(wp) { - $rootScope.$broadcast('uploadPendingAttachments', wp); - }; + if (strategy !== scope.strategy) { + scope.strategy = strategy; + scope.templateUrl = '/templates/inplace-edit/edit/fields/' + + scope.strategy + '.html'; + fieldController.updateWriteValue(); + } + }); - // Propagate submission to all active fields - // not contained in the workPackage.form (e.g., comment) - this.submit = function(notify) { - EditableFieldsState.save(notify, function() { - // Clears the location hash, as we're now - // scrolling to somewhere else - $location.hash(null); - $timeout(function() { - $element[0].scrollIntoView(false); + 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() { + // ♥♥♥ angular ♥♥♥ + scope.$apply(function() { + scope.editPaneController.markActive(); }); }); - }; - - this.submitField = function(notify) { - var submit = $q.defer(); - var fieldController = $scope.fieldController; - var pendingFormChanges = EditableFieldsState.getPendingFormChanges(); - var detectedViolations = []; - var handleFailure = function(e) { - setFailure(e); - submit.reject(e); - }; + }); + }; - pendingFormChanges[fieldController.field] = fieldController.writeValue; - if (vm.editForm.$invalid) { - var acknowledgedValidationErrors = Object.keys(vm.editForm.$error); - acknowledgedValidationErrors.forEach(function(error) { - if (vm.editForm.$error[error]) { - detectedViolations.push(I18n.t('js.inplace.errors.' + error, { - field: fieldController.getLabel() - })); - } + if (!EditableFieldsState.forcedEditState) { + element.bind('keydown keypress', function(e) { + if (e.keyCode === 27) { + scope.$apply(function() { + scope.editPaneController.discardEditing(); }); - submit.reject(); - } - if (detectedViolations.length) { - EditableFieldsState.errors = EditableFieldsState.errors || {}; - EditableFieldsState.errors[fieldController.field] = detectedViolations.join(' '); - showErrors(); - 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, - notify - ); - result.then(angular.bind(this, function(updatedWorkPackage) { - submit.resolve(); - $scope.$emit('workPackageUpdatedInEditor', updatedWorkPackage); - $scope.$on('workPackageRefreshed', function() { - fieldController.state.isBusy = false; - fieldController.isEditing = false; - fieldController.updateWriteValue(); - }); - 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; - } - }); - } - }).catch(handleFailure); } + }); + } - return submit.promise; - }; - - this.discardEditing = function() { - $scope.fieldController.isEditing = false; - delete EditableFieldsState.submissionPromises['work_package']; - delete EditableFieldsState.getPendingFormChanges()[$scope.fieldController.field]; - $scope.fieldController.updateWriteValue(); - if ( - EditableFieldsState.errors && - EditableFieldsState.errors.hasOwnProperty($scope.fieldController.field) - ) { - delete EditableFieldsState.errors[$scope.fieldController.field]; - } - }; + scope.$watch('fieldController.writeValue', function(writeValue) { + if (scope.fieldController.isEditing) { + var pendingChanges = EditableFieldsState.getPendingFormChanges(); + pendingChanges[scope.fieldController.field] = writeValue; + } + }, true); + scope.$on('workPackageRefreshed', function() { + scope.editPaneController.discardEditing(); + }); - this.isActive = function() { - return EditableFieldsState.isActiveField($scope.fieldController.field); - }; + scope.$watch('fieldController.isEditing', function(isEditing) { + var efs = EditableFieldsState, field = fieldController.field; - this.markActive = function() { - EditableFieldsState.submissionPromises['work_package'] = { - field: $scope.fieldController.field, - thePromise: this.submitField, - prepend: true, - }; - EditableFieldsState.currentField = $scope.fieldController.field; - }; + if (isEditing && !efs.editAll.state && !efs.forcedEditState) { + scope.focusInput(); - function afterError() { - $scope.fieldController.state.isBusy = false; - $scope.focusInput(); - } - function setFailure(e) { - afterError(); - EditableFieldsState.errors = { - '_common': ApiHelper.getErrorMessages(e) - }; - showErrors(); + } else if (efs.editAll.state && efs.editAll.isFocusField(field)) { + $timeout(function () { + var focusElement = element.find('.focus-input'); + focusElement.length && focusElement.focus()[0].select(); + }); } + }); + } + }; +} +inplaceEditorEditPane.$inject = ['WorkPackageFieldService', 'EditableFieldsState', 'FocusHelper', + '$timeout']; - $scope.$watch('editableFieldsState.editAll.state', function(state) { - $scope.fieldController.isEditing = state; - $scope.fieldController.lockFocus = true; - !state && $scope.fieldController.updateWriteValue(); - }); - }, - link: function(scope, element, attrs, fieldController) { - scope.fieldController = fieldController; - scope.editableFieldsState = EditableFieldsState; +function InplaceEditorEditPaneController($scope, $element, $location, $timeout, $q, $rootScope, + WorkPackageService, EditableFieldsState, ApiHelper, NotificationsService) { - scope.editPaneController.isRequired = function() { - return WorkPackageFieldService.isRequired( - EditableFieldsState.workPackage, - this.field - ); - }; + var showErrors = function() { + var errors = EditableFieldsState.errors; + if (_.isEmpty(_.keys(errors))) { + return; + } + var errorMessages = _.flatten(_.map(errors), true); + NotificationsService.addError(I18n.t('js.label_validation_error'), errorMessages); + }; - scope.$watchCollection('editableFieldsState.workPackage.form', function(form) { - var strategy = WorkPackageFieldService.getInplaceEditStrategy( - EditableFieldsState.workPackage, - fieldController.field - ); + var vm = this; - if (fieldController.field === 'date' && strategy === 'date') { - form.pendingChanges = EditableFieldsState.getPendingFormChanges(); - form.pendingChanges['startDate'] = - form.pendingChanges['dueDate'] = - fieldController.writeValue ? fieldController.writeValue['dueDate'] : null; - } + // go full retard + var uploadPendingAttachments = function(wp) { + $rootScope.$broadcast('uploadPendingAttachments', wp); + }; - if (strategy !== scope.strategy) { - scope.strategy = strategy; - scope.templateUrl = '/templates/inplace-edit/edit/fields/' + - scope.strategy + '.html'; - fieldController.updateWriteValue(); - } - }); + // Propagate submission to all active fields + // not contained in the workPackage.form (e.g., comment) + this.submit = function(notify) { + EditableFieldsState.save(notify, function() { + // Clears the location hash, as we're now + // scrolling to somewhere else + $location.hash(null); + $timeout(function() { + $element[0].scrollIntoView(false); + }); + }); + }; + + this.submitField = function(notify) { + var submit = $q.defer(); + var fieldController = $scope.fieldController; + var pendingFormChanges = EditableFieldsState.getPendingFormChanges(); + var detectedViolations = []; + var handleFailure = function(e) { + setFailure(e); + submit.reject(e); + }; - 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() { - // ♥♥♥ angular ♥♥♥ - scope.$apply(function() { - scope.editPaneController.markActive(); + pendingFormChanges[fieldController.field] = fieldController.writeValue; + if (vm.editForm.$invalid) { + var acknowledgedValidationErrors = Object.keys(vm.editForm.$error); + acknowledgedValidationErrors.forEach(function(error) { + if (vm.editForm.$error[error]) { + detectedViolations.push(I18n.t('js.inplace.errors.' + error, { + field: fieldController.getLabel() + })); + } + }); + submit.reject(); + } + if (detectedViolations.length) { + EditableFieldsState.errors = EditableFieldsState.errors || {}; + EditableFieldsState.errors[fieldController.field] = detectedViolations.join(' '); + showErrors(); + 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, + notify + ); + result.then(angular.bind(this, function(updatedWorkPackage) { + submit.resolve(); + $scope.$emit('workPackageUpdatedInEditor', updatedWorkPackage); + $scope.$on('workPackageRefreshed', function() { + fieldController.state.isBusy = false; + fieldController.isEditing = false; + fieldController.updateWriteValue(); }); + 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; + } }); - }); - }; + } + }).catch(handleFailure); + } - if (!EditableFieldsState.forcedEditState) { - element.bind('keydown keypress', function(e) { - if (e.keyCode === 27) { - scope.$apply(function() { - scope.editPaneController.discardEditing(); - }); - } - }); - } + return submit.promise; + }; - scope.$watch('fieldController.writeValue', function(writeValue) { - if (scope.fieldController.isEditing) { - var pendingChanges = EditableFieldsState.getPendingFormChanges(); - pendingChanges[scope.fieldController.field] = writeValue; - } - }, true); - scope.$on('workPackageRefreshed', function() { - scope.editPaneController.discardEditing(); - }); + this.discardEditing = function() { + $scope.fieldController.isEditing = false; + delete EditableFieldsState.submissionPromises['work_package']; + delete EditableFieldsState.getPendingFormChanges()[$scope.fieldController.field]; + $scope.fieldController.updateWriteValue(); + if ( + EditableFieldsState.errors && + EditableFieldsState.errors.hasOwnProperty($scope.fieldController.field) + ) { + delete EditableFieldsState.errors[$scope.fieldController.field]; + } + }; - scope.$watch('fieldController.isEditing', function(isEditing) { - var efs = EditableFieldsState, field = fieldController.field; + this.isActive = function() { + return EditableFieldsState.isActiveField($scope.fieldController.field); + }; - if (isEditing && !efs.editAll.state && !efs.forcedEditState) { - scope.focusInput(); + this.markActive = function() { + EditableFieldsState.submissionPromises['work_package'] = { + field: $scope.fieldController.field, + thePromise: this.submitField, + prepend: true, + }; + EditableFieldsState.currentField = $scope.fieldController.field; + }; - } else if (efs.editAll.state && efs.editAll.isFocusField(field)) { - $timeout(function () { - var focusElement = element.find('.focus-input'); - focusElement.length && focusElement.focus()[0].select(); - }); - } - }); - } + function afterError() { + $scope.fieldController.state.isBusy = false; + $scope.focusInput(); + } + function setFailure(e) { + afterError(); + EditableFieldsState.errors = { + '_common': ApiHelper.getErrorMessages(e) }; + showErrors(); } -]); + + $scope.$watch('editableFieldsState.editAll.state', function(state) { + $scope.fieldController.isEditing = state; + $scope.fieldController.lockFocus = true; + + !state && $scope.fieldController.updateWriteValue(); + }); +} +InplaceEditorEditPaneController.$inject = ['$scope', '$element', '$location', '$timeout', '$q', + '$rootScope', 'WorkPackageService', 'EditableFieldsState', 'ApiHelper', 'NotificationsService']; diff --git a/frontend/app/components/inplace-edit/directives/field-display/display-spent-time/display-spent-time.directive.js b/frontend/app/components/inplace-edit/directives/field-display/display-spent-time/display-spent-time.directive.js index 13400dbaae..ef46fbd817 100644 --- a/frontend/app/components/inplace-edit/directives/field-display/display-spent-time/display-spent-time.directive.js +++ b/frontend/app/components/inplace-edit/directives/field-display/display-spent-time/display-spent-time.directive.js @@ -26,29 +26,37 @@ // See doc/COPYRIGHT.rdoc for more details. // ++ -angular.module('openproject.inplace-edit').directive('inplaceDisplaySpentTime', [ - 'EditableFieldsState', function(EditableFieldsState) { - return { - restrict: 'E', - transclude: true, - replace: true, - scope: {}, - require: ['^inplaceEditorDisplayPane', '^workPackageField'], - templateUrl: '/components/inplace-edit/directives/field-display/display-spent-time/display-spent-time.directive.html', - controller: function() { - this.isLinkViewable = function() { - return EditableFieldsState.workPackage.links.timeEntries; - }; +angular + .module('openproject.inplace-edit') + .directive('inplaceDisplaySpentTime', inplaceDisplaySpentTime); - this.getPath = function() { - return EditableFieldsState.workPackage.links.timeEntries.href; - }; - }, - controllerAs: 'customEditorController', - link: function(scope, element, attrs, controllers) { - scope.displayPaneController = controllers[0]; - scope.fieldController = controllers[1]; - } - }; - } -]); +function inplaceDisplaySpentTime() { + return { + restrict: 'E', + transclude: true, + replace: true, + scope: {}, + require: ['^inplaceEditorDisplayPane', '^workPackageField'], + templateUrl: '/components/inplace-edit/directives/field-display/display-spent-time/' + + 'display-spent-time.directive.html', + + controller: InplaceDisplaySpentTimeController, + controllerAs: 'customEditorController', + + link: function(scope, element, attrs, controllers) { + scope.displayPaneController = controllers[0]; + scope.fieldController = controllers[1]; + } + }; +} + +function InplaceDisplaySpentTimeController(EditableFieldsState) { + this.isLinkViewable = function() { + return EditableFieldsState.workPackage.links.timeEntries; + }; + + this.getPath = function() { + return EditableFieldsState.workPackage.links.timeEntries.href; + }; +} +InplaceDisplaySpentTimeController.$inject = ['EditableFieldsState']; diff --git a/frontend/app/components/inplace-edit/directives/field-display/display-user/display-user.directive.js b/frontend/app/components/inplace-edit/directives/field-display/display-user/display-user.directive.js index 1f747f0a9d..644a0f9128 100644 --- a/frontend/app/components/inplace-edit/directives/field-display/display-user/display-user.directive.js +++ b/frontend/app/components/inplace-edit/directives/field-display/display-user/display-user.directive.js @@ -26,32 +26,40 @@ // See doc/COPYRIGHT.rdoc for more details. // ++ -angular.module('openproject.inplace-edit').directive('inplaceDisplayUser', [ - 'PathHelper', function(PathHelper) { - return { - restrict: 'E', - transclude: true, - replace: true, - scope: {}, - require: '^inplaceEditorDisplayPane', - templateUrl: '/components/inplace-edit/directives/field-display/display-user/display-user.directive.html', - controller: ['$scope', function($scope) { - this.userPath = PathHelper.staticUserPath; - this.getUser = function() { - return $scope.inplaceEditorDisplayPane.getReadValue(); - }; - this.getUserName = function() { - var user = this.getUser(); - if (user && user.props && (user.props.firstName || user.props.lastName)) { - return user.props.firstName + ' ' + user.props.lastName; - } - return null; - }; - }], - controllerAs: 'customEditorController', - link: function(scope, element, attrs, inplaceEditorDisplayPane) { - scope.inplaceEditorDisplayPane = inplaceEditorDisplayPane; - } - }; - } -]); +angular + .module('openproject.inplace-edit') + .directive('inplaceDisplayUser', inplaceDisplayUser); + +function inplaceDisplayUser() { + return { + restrict: 'E', + transclude: true, + replace: true, + scope: {}, + require: '^inplaceEditorDisplayPane', + templateUrl: '/components/inplace-edit/directives/field-display/display-user/' + + 'display-user.directive.html', + + controller: InplaceDisplayUserController, + controllerAs: 'customEditorController', + + link: function(scope, element, attrs, inplaceEditorDisplayPane) { + scope.inplaceEditorDisplayPane = inplaceEditorDisplayPane; + } + }; +} + +function InplaceDisplayUserController($scope, PathHelper) { + this.userPath = PathHelper.staticUserPath; + this.getUser = function() { + return $scope.inplaceEditorDisplayPane.getReadValue(); + }; + this.getUserName = function() { + var user = this.getUser(); + if (user && user.props && (user.props.firstName || user.props.lastName)) { + return user.props.firstName + ' ' + user.props.lastName; + } + return null; + }; +} +InplaceDisplayUserController.$inject = ['$scope', 'PathHelper']; diff --git a/frontend/app/components/inplace-edit/directives/field-display/display-version/display-version.directive.js b/frontend/app/components/inplace-edit/directives/field-display/display-version/display-version.directive.js index 8e686a53a1..26eb9184be 100644 --- a/frontend/app/components/inplace-edit/directives/field-display/display-version/display-version.directive.js +++ b/frontend/app/components/inplace-edit/directives/field-display/display-version/display-version.directive.js @@ -26,27 +26,34 @@ // See doc/COPYRIGHT.rdoc for more details. // ++ -angular.module('openproject.inplace-edit').directive('inplaceDisplayVersion', [ - 'EditableFieldsState', 'PathHelper', - function(EditableFieldsState, PathHelper) { - return { - restrict: 'E', - transclude: true, - replace: true, - scope: {}, - require: '^inplaceEditorDisplayPane', - templateUrl: '/components/inplace-edit/directives/field-display/display-version/display-version.directive.html', - controller: ['$scope', function($scope) { - this.pathHelper = PathHelper; - this.isVersionLinkViewable = function() { - var version = $scope.displayPaneController.getReadValue(); - return version.links.definingProject && version.links.definingProject.href; - } - }], - controllerAs: 'customEditorController', - link: function(scope, element, attrs, displayPaneController) { - scope.displayPaneController = displayPaneController; - } - }; +angular + .module('openproject.inplace-edit') + .directive('inplaceDisplayVersion', inplaceDisplayVersion); + +function inplaceDisplayVersion() { + return { + restrict: 'E', + transclude: true, + replace: true, + scope: {}, + require: '^inplaceEditorDisplayPane', + templateUrl: '/components/inplace-edit/directives/field-display/display-version/' + + 'display-version.directive.html', + + controller: InplaceDisplayVersionController, + controllerAs: 'customEditorController', + + link: function(scope, element, attrs, displayPaneController) { + scope.displayPaneController = displayPaneController; + } + }; +} + +function InplaceDisplayVersionController($scope, PathHelper) { + this.pathHelper = PathHelper; + this.isVersionLinkViewable = function() { + var version = $scope.displayPaneController.getReadValue(); + return version.links.definingProject && version.links.definingProject.href; } -]); +} +InplaceDisplayVersionController.$inject = ['$scope', 'PathHelper']; diff --git a/frontend/app/components/inplace-edit/directives/field-edit/edit-date-range/edit-date-range.directive.js b/frontend/app/components/inplace-edit/directives/field-edit/edit-date-range/edit-date-range.directive.js index 65a81e60ef..85e8544c7f 100644 --- a/frontend/app/components/inplace-edit/directives/field-edit/edit-date-range/edit-date-range.directive.js +++ b/frontend/app/components/inplace-edit/directives/field-edit/edit-date-range/edit-date-range.directive.js @@ -26,126 +26,129 @@ // See doc/COPYRIGHT.rdoc for more details. // ++ -angular.module('openproject.inplace-edit').directive('inplaceEditorDateRange', [ - 'TimezoneService', 'ConfigurationService', 'I18n', '$timeout', 'WorkPackageFieldService', - 'EditableFieldsState', 'Datepicker', - - function(TimezoneService, ConfigurationService, I18n, $timeout, WorkPackageFieldService, - EditableFieldsState, Datepicker) { - - return { - restrict: 'E', - transclude: true, - replace: true, - scope: {}, - require: '^workPackageField', - templateUrl: '/components/inplace-edit/directives/field-edit/edit-date-range/edit-date-range.directive.html', - controller: function() { - }, - controllerAs: 'customEditorController', - link: function(scope, element, attrs, fieldController) { - var customDateFormat = 'YYYY-MM-DD'; - - function getTitle(labelName) { - return I18n.t('js.inplace.button_edit', { - attribute: WorkPackageFieldService.getLabel( - EditableFieldsState.workPackage, - labelName - ) - }); - } +angular + .module('openproject.inplace-edit') + .directive('inplaceEditorDateRange', inplaceEditorDateRange); - scope.startDate = fieldController.writeValue.startDate; - scope.endDate = fieldController.writeValue.dueDate; - var form = element.parents('.inplace-edit--form'), - inputStart = element.find('.inplace-edit--date-range-start-date'), - inputEnd = element.find('.inplace-edit--date-range-end-date'), - divStart = element.find('.inplace-edit--date-range-start-date-picker'), - divEnd = element.find('.inplace-edit--date-range-end-date-picker'), - startDatepicker, endDatepicker; +function inplaceEditorDateRange(TimezoneService, I18n, $timeout, WorkPackageFieldService, + EditableFieldsState, Datepicker) { - scope.startDateIsChanged = scope.endDateIsChanged = false; + return { + restrict: 'E', + transclude: true, + replace: true, + scope: {}, + require: '^workPackageField', + templateUrl: '/components/inplace-edit/directives/field-edit/edit-date-range/' + + 'edit-date-range.directive.html', - if (scope.endDate) { - scope.endDate = TimezoneService.formattedISODate(scope.endDate); - } - if (scope.startDate) { - scope.startDate = TimezoneService.formattedISODate(scope.startDate); - } + controller: function() {}, + controllerAs: 'customEditorController', - scope.execute = function() { - form.scope().editPaneController.submit(false); - }; - - startDatepicker = new Datepicker(divStart, inputStart, scope.startDate); - endDatepicker = new Datepicker(divEnd, inputEnd, scope.endDate); - startDatepicker.onChange = function(date) { - scope.startDate = fieldController.writeValue.startDate = date; - if (startDatepicker.prevDate.isAfter(endDatepicker.prevDate)) { - scope.startDateIsChanged = true; - scope.endDate = fieldController.writeValue.dueDate = scope.startDate; - endDatepicker.setDate(scope.endDate); - } - }; - scope.onStartEdit = function() { - scope.startDateIsChanged = scope.endDateIsChanged = false; - startDatepicker.onEdit(); - }; - endDatepicker.onChange = function(date) { - scope.endDate = fieldController.writeValue.dueDate = date; - if (endDatepicker.prevDate.isBefore(startDatepicker.prevDate)) { - scope.endDateIsChanged = true; - scope.startDate = fieldController.writeValue.startDate = scope.endDate; - startDatepicker.setDate(scope.startDate); - } - }; - scope.onEndEdit = function() { - scope.startDateIsChanged = scope.endDateIsChanged = false; - endDatepicker.onEdit(); - }; - - startDatepicker.onDone = endDatepicker.onDone = function() { - form.scope().editPaneController.discardEditing(); - }; - - $timeout(function() { - EditableFieldsState.editAll.state || startDatepicker.focus(); - }); + link: function(scope, element, attrs, fieldController) { + var customDateFormat = 'YYYY-MM-DD'; - startDatepicker.textbox.on('click focusin', function() { - if (divStart.is(':hidden') || divEnd.is(':visible')) { - endDatepicker.hide(); - startDatepicker.show(); - } - scope.startDateIsChanged = scope.endDateIsChanged = false; - }).attr({ - 'placeholder': customDateFormat, - 'aria-label': customDateFormat, - 'title': getTitle('startDate') + function getTitle(labelName) { + return I18n.t('js.inplace.button_edit', { + attribute: WorkPackageFieldService.getLabel( + EditableFieldsState.workPackage, + labelName + ) }); + } - endDatepicker.textbox.on('click focusin', function() { - if (divEnd.is(':hidden') || divStart.is(':visible')) { - endDatepicker.show(); - startDatepicker.hide(); - } - scope.startDateIsChanged = scope.endDateIsChanged = false; - }).attr({ - 'placeholder': customDateFormat, - 'aria-label': customDateFormat, - 'title': getTitle('dueDate') - }); + scope.startDate = fieldController.writeValue.startDate; + scope.endDate = fieldController.writeValue.dueDate; + var form = element.parents('.inplace-edit--form'), + inputStart = element.find('.inplace-edit--date-range-start-date'), + inputEnd = element.find('.inplace-edit--date-range-end-date'), + divStart = element.find('.inplace-edit--date-range-start-date-picker'), + divEnd = element.find('.inplace-edit--date-range-end-date-picker'), + startDatepicker, endDatepicker; - angular.element('.work-packages--details-content').on('click', function(e) { - var target = angular.element(e.target); - if (!target.is('.inplace-edit--date-range input') && - target.parents('.hasDatepicker').length <= 0 && - target.parents('.ui-datepicker-header').length <= 0) { - startDatepicker.hide(); - endDatepicker.hide(); - } - }); + scope.startDateIsChanged = scope.endDateIsChanged = false; + + if (scope.endDate) { + scope.endDate = TimezoneService.formattedISODate(scope.endDate); + } + if (scope.startDate) { + scope.startDate = TimezoneService.formattedISODate(scope.startDate); } - }; - } -]); + + scope.execute = function() { + form.scope().editPaneController.submit(false); + }; + + startDatepicker = new Datepicker(divStart, inputStart, scope.startDate); + endDatepicker = new Datepicker(divEnd, inputEnd, scope.endDate); + startDatepicker.onChange = function(date) { + scope.startDate = fieldController.writeValue.startDate = date; + if (startDatepicker.prevDate.isAfter(endDatepicker.prevDate)) { + scope.startDateIsChanged = true; + scope.endDate = fieldController.writeValue.dueDate = scope.startDate; + endDatepicker.setDate(scope.endDate); + } + }; + scope.onStartEdit = function() { + scope.startDateIsChanged = scope.endDateIsChanged = false; + startDatepicker.onEdit(); + }; + endDatepicker.onChange = function(date) { + scope.endDate = fieldController.writeValue.dueDate = date; + if (endDatepicker.prevDate.isBefore(startDatepicker.prevDate)) { + scope.endDateIsChanged = true; + scope.startDate = fieldController.writeValue.startDate = scope.endDate; + startDatepicker.setDate(scope.startDate); + } + }; + scope.onEndEdit = function() { + scope.startDateIsChanged = scope.endDateIsChanged = false; + endDatepicker.onEdit(); + }; + + startDatepicker.onDone = endDatepicker.onDone = function() { + form.scope().editPaneController.discardEditing(); + }; + + $timeout(function() { + EditableFieldsState.editAll.state || startDatepicker.focus(); + }); + + startDatepicker.textbox.on('click focusin', function() { + if (divStart.is(':hidden') || divEnd.is(':visible')) { + endDatepicker.hide(); + startDatepicker.show(); + } + scope.startDateIsChanged = scope.endDateIsChanged = false; + }).attr({ + 'placeholder': customDateFormat, + 'aria-label': customDateFormat, + 'title': getTitle('startDate') + }); + + endDatepicker.textbox.on('click focusin', function() { + if (divEnd.is(':hidden') || divStart.is(':visible')) { + endDatepicker.show(); + startDatepicker.hide(); + } + scope.startDateIsChanged = scope.endDateIsChanged = false; + }).attr({ + 'placeholder': customDateFormat, + 'aria-label': customDateFormat, + 'title': getTitle('dueDate') + }); + + angular.element('.work-packages--details-content').on('click', function(e) { + var target = angular.element(e.target); + if (!target.is('.inplace-edit--date-range input') && + target.parents('.hasDatepicker').length <= 0 && + target.parents('.ui-datepicker-header').length <= 0) { + startDatepicker.hide(); + endDatepicker.hide(); + } + }); + } + }; +} +inplaceEditorDateRange.$inject = ['TimezoneService', 'I18n', '$timeout', 'WorkPackageFieldService', + 'EditableFieldsState', 'Datepicker']; diff --git a/frontend/app/components/inplace-edit/directives/field-edit/edit-date/edit-date.directive.js b/frontend/app/components/inplace-edit/directives/field-edit/edit-date/edit-date.directive.js index 48a1738e41..f249b65bff 100644 --- a/frontend/app/components/inplace-edit/directives/field-edit/edit-date/edit-date.directive.js +++ b/frontend/app/components/inplace-edit/directives/field-edit/edit-date/edit-date.directive.js @@ -26,76 +26,77 @@ // See doc/COPYRIGHT.rdoc for more details. // ++ -angular.module('openproject.inplace-edit').directive('inplaceEditorDate', [ - 'WorkPackageFieldService', 'EditableFieldsState', 'TimezoneService', 'ConfigurationService', - 'I18n', '$timeout', 'Datepicker', +angular + .module('openproject.inplace-edit') + .directive('inplaceEditorDate', inplaceEditorDate); - function(WorkPackageFieldService, EditableFieldsState, TimezoneService, ConfigurationService, - I18n, $timeout, Datepicker) { +function inplaceEditorDate(EditableFieldsState, TimezoneService, $timeout, Datepicker) { + var parseISODate = TimezoneService.parseISODate, + customDateFormat = 'YYYY-MM-DD', + customFormattedDate = function(date) { + return parseISODate(date).format(customDateFormat); + }; - var parseISODate = TimezoneService.parseISODate, - customDateFormat = 'YYYY-MM-DD', - customFormattedDate = function(date) { - return parseISODate(date).format(customDateFormat); - }; + return { + restrict: 'E', + transclude: true, + replace: true, + scope: {}, + require: '^workPackageField', + templateUrl: '/components/inplace-edit/directives/field-edit/edit-date/' + + 'edit-date.directive.html', - return { - restrict: 'E', - transclude: true, - replace: true, - scope: {}, - require: '^workPackageField', - templateUrl: '/components/inplace-edit/directives/field-edit/edit-date/edit-date.directive.html', - controller: function() { - }, - controllerAs: 'customEditorController', - link: function(scope, element, attrs, fieldController) { - scope.fieldController = fieldController; - var form = element.parents('.inplace-edit--form'), - input = element.find('.inplace-edit--date'), - datepickerContainer = element.find('.inplace-edit--date-picker'), - datepicker; + controller: function() {}, + controllerAs: 'customEditorController', - scope.execute = function() { - form.scope().editPaneController.submit(false); - }; + link: function(scope, element, attrs, fieldController) { + scope.fieldController = fieldController; + var form = element.parents('.inplace-edit--form'), + input = element.find('.inplace-edit--date'), + datepickerContainer = element.find('.inplace-edit--date-picker'), + datepicker; - if(scope.fieldController.writeValue) { - scope.fieldController.writeValue = customFormattedDate(scope.fieldController.writeValue); - } + scope.execute = function() { + form.scope().editPaneController.submit(false); + }; - datepicker = new Datepicker(datepickerContainer, input, scope.fieldController.writeValue); - datepicker.onChange = function(date) { - scope.fieldController.writeValue = date; - }; - scope.onEdit = function() { - datepicker.onEdit(); - }; - datepicker.onDone = function() { - form.scope().editPaneController.discardEditing(); - }; + if(scope.fieldController.writeValue) { + scope.fieldController.writeValue = customFormattedDate(scope.fieldController.writeValue); + } - datepicker.textbox.attr({ - 'placeholder': '-', - 'aria-label': customDateFormat - }); + datepicker = new Datepicker(datepickerContainer, input, scope.fieldController.writeValue); + datepicker.onChange = function(date) { + scope.fieldController.writeValue = date; + }; + scope.onEdit = function() { + datepicker.onEdit(); + }; + datepicker.onDone = function() { + form.scope().editPaneController.discardEditing(); + }; - scope.showDatepicker = function() { - datepicker.show(); - }; + datepicker.textbox.attr({ + 'placeholder': '-', + 'aria-label': customDateFormat + }); - $timeout(function() { - EditableFieldsState.editAll.state || datepicker.focus(); - }); + scope.showDatepicker = function() { + datepicker.show(); + }; - angular.element('.work-packages--details-content').on('click', function(e) { - var target = angular.element(e.target); - if(!target.is('.inplace-edit--date input') && - target.parents('.inplace-edit--date .hasDatepicker').length <= 0 && - target.parents('.ui-datepicker-header').length <= 0) { - datepicker.hide(); - } - }); - } - }; -}]); + $timeout(function() { + EditableFieldsState.editAll.state || datepicker.focus(); + }); + + angular.element('.work-packages--details-content').on('click', function(e) { + var target = angular.element(e.target); + if(!target.is('.inplace-edit--date input') && + target.parents('.inplace-edit--date .hasDatepicker').length <= 0 && + target.parents('.ui-datepicker-header').length <= 0) { + datepicker.hide(); + } + }); + } + }; +} +inplaceEditorDate.$inject = ['EditableFieldsState', 'TimezoneService', '$timeout', 'Datepicker']; diff --git a/frontend/app/components/inplace-edit/directives/field-edit/edit-drop-down/edit-drop-down.directive.js b/frontend/app/components/inplace-edit/directives/field-edit/edit-drop-down/edit-drop-down.directive.js index 03e8cc58cc..f7ed52c18b 100644 --- a/frontend/app/components/inplace-edit/directives/field-edit/edit-drop-down/edit-drop-down.directive.js +++ b/frontend/app/components/inplace-edit/directives/field-edit/edit-drop-down/edit-drop-down.directive.js @@ -26,74 +26,83 @@ // See doc/COPYRIGHT.rdoc for more details. // ++ -angular.module('openproject.inplace-edit').directive('inplaceEditorDropDown', [ - 'WorkPackageFieldService', 'WorkPackageFieldConfigurationService', 'EditableFieldsState', 'I18n', - '$timeout', '$q', 'FocusHelper', - - function(WorkPackageFieldService, WorkPackageFieldConfigurationService, EditableFieldsState, - I18n, $timeout, $q, FocusHelper) { - - return { - restrict: 'E', - transclude: true, - replace: true, - scope: {}, - require: '^workPackageField', - templateUrl: '/components/inplace-edit/directives/field-edit/edit-drop-down/edit-drop-down.directive.html', - controller: function() { - this.allowedValues = []; - this.nullValueLabel = I18n.t('js.inplace.null_value_label'); - - this.updateAllowedValues = function(field) { - var customEditorController = this; - - return $q(function(resolve) { - WorkPackageFieldService.getAllowedValues( - EditableFieldsState.workPackage, - field - ).then(function(values) { - - var sorting = WorkPackageFieldConfigurationService - .getDropdownSortingStrategy(field); - - if (sorting !== null) { - values = _.sortBy(values, sorting); - } - - if (!WorkPackageFieldService.isRequired(EditableFieldsState.workPackage, - field)) { - var arrayWithEmptyOption = [{ - href: null, - name: I18n.t('js.inplace.clear_value_label') - }]; - - values = arrayWithEmptyOption.concat(values); - } - customEditorController.allowedValues = values; - - resolve(); - }); - }); - }; - }, - controllerAs: 'customEditorController', - link: function(scope, element, attrs, fieldController) { - var selected = WorkPackageFieldService.format( - EditableFieldsState.workPackage, - fieldController.field - ); - - scope.fieldController = fieldController; - scope.customEditorController.selected = selected && selected.props && selected.props.name; - scope.fieldController.state.isBusy = true; - - scope.customEditorController.updateAllowedValues(fieldController.field).then(function() { - fieldController.state.isBusy = false; - - if (!EditableFieldsState.forcedEditState) { - EditableFieldsState.editAll.state || FocusHelper.focusUiSelect(element); +angular + .module('openproject.inplace-edit') + .directive('inplaceEditorDropDown', inplaceEditorDropDown); + +function inplaceEditorDropDown(WorkPackageFieldService, EditableFieldsState, FocusHelper) { + return { + restrict: 'E', + transclude: true, + replace: true, + scope: {}, + require: '^workPackageField', + templateUrl: '/components/inplace-edit/directives/field-edit/edit-drop-down/' + + 'edit-drop-down.directive.html', + + controller: InplaceEditorDropDownController, + controllerAs: 'customEditorController', + + link: function(scope, element, attrs, fieldController) { + var selected = WorkPackageFieldService.format( + EditableFieldsState.workPackage, + fieldController.field + ); + + scope.fieldController = fieldController; + scope.customEditorController.selected = selected && selected.props && selected.props.name; + scope.fieldController.state.isBusy = true; + + scope.customEditorController.updateAllowedValues(fieldController.field).then(function() { + fieldController.state.isBusy = false; + + if (!EditableFieldsState.forcedEditState) { + EditableFieldsState.editAll.state || FocusHelper.focusUiSelect(element); + } + }); + } + }; +} +inplaceEditorDropDown.$inject = ['WorkPackageFieldService', 'EditableFieldsState', 'FocusHelper']; + + +function InplaceEditorDropDownController($q, I18n, WorkPackageFieldService, + WorkPackageFieldConfigurationService, EditableFieldsState) { + + this.allowedValues = []; + this.nullValueLabel = I18n.t('js.inplace.null_value_label'); + + this.updateAllowedValues = function(field) { + var customEditorController = this; + + return $q(function(resolve) { + WorkPackageFieldService.getAllowedValues( + EditableFieldsState.workPackage, + field + ).then(function(values) { + + var sorting = WorkPackageFieldConfigurationService + .getDropdownSortingStrategy(field); + + if (sorting !== null) { + values = _.sortBy(values, sorting); } + + if (!WorkPackageFieldService.isRequired(EditableFieldsState.workPackage, + field)) { + var arrayWithEmptyOption = [{ + href: null, + name: I18n.t('js.inplace.clear_value_label') + }]; + + values = arrayWithEmptyOption.concat(values); + } + customEditorController.allowedValues = values; + + resolve(); }); - } - }; -}]); + }); + }; +} +InplaceEditorDropDownController.$inject = ['$q', 'I18n', 'WorkPackageFieldService', + 'WorkPackageFieldConfigurationService', 'EditableFieldsState']; diff --git a/frontend/app/components/inplace-edit/directives/field-edit/edit-duration/edit-duration.directive.js b/frontend/app/components/inplace-edit/directives/field-edit/edit-duration/edit-duration.directive.js index c65eb1d53a..4df8b9bc3e 100644 --- a/frontend/app/components/inplace-edit/directives/field-edit/edit-duration/edit-duration.directive.js +++ b/frontend/app/components/inplace-edit/directives/field-edit/edit-duration/edit-duration.directive.js @@ -26,16 +26,23 @@ // See doc/COPYRIGHT.rdoc for more details. // ++ -angular.module('openproject.inplace-edit').directive('inplaceEditorDuration', function() { +angular + .module('openproject.inplace-edit') + .directive('inplaceEditorDuration', inplaceEditorDuration); + +function inplaceEditorDuration() { return { restrict: 'E', transclude: true, replace: true, scope: {}, require: '^workPackageField', - templateUrl: '/components/inplace-edit/directives/field-edit/edit-duration/edit-duration.directive.html', + templateUrl: '/components/inplace-edit/directives/field-edit/edit-duration/' + + 'edit-duration.directive.html', + controllerAs: 'customEditorController', controller: function() {}, + link: function(scope, element, attrs, fieldController) { scope.fieldController = fieldController; if (fieldController.writeValue === null) { @@ -60,4 +67,4 @@ angular.module('openproject.inplace-edit').directive('inplaceEditorDuration', fu }); } }; -}); +} diff --git a/frontend/app/components/inplace-edit/directives/field-edit/edit-wiki-textarea/edit-wiki-textarea.directive.js b/frontend/app/components/inplace-edit/directives/field-edit/edit-wiki-textarea/edit-wiki-textarea.directive.js index 5b38cf9616..1a27f34587 100644 --- a/frontend/app/components/inplace-edit/directives/field-edit/edit-wiki-textarea/edit-wiki-textarea.directive.js +++ b/frontend/app/components/inplace-edit/directives/field-edit/edit-wiki-textarea/edit-wiki-textarea.directive.js @@ -26,73 +26,82 @@ // See doc/COPYRIGHT.rdoc for more details. // ++ -angular.module('openproject.inplace-edit').directive('inplaceEditorWikiTextarea', [ - 'TextileService', 'EditableFieldsState', '$sce', 'AutoCompleteHelper', '$timeout', +angular + .module('openproject.inplace-edit') + .directive('inplaceEditorWikiTextarea', inplaceEditorWikiTextarea); - function(TextileService, EditableFieldsState, $sce, AutoCompleteHelper, $timeout) { - return { - restrict: 'E', - transclude: true, - replace: true, - scope: {}, - templateUrl: '/components/inplace-edit/directives/field-edit/edit-wiki-textarea/edit-wiki-textarea.directive.html', - controller: function($scope) { - this.isPreview = false; - this.previewHtml = ''; - this.autocompletePath = '/work_packages/auto_complete.json'; +function inplaceEditorWikiTextarea(AutoCompleteHelper, $timeout) { + return { + restrict: 'E', + transclude: true, + replace: true, + scope: {}, + templateUrl: '/components/inplace-edit/directives/field-edit/edit-wiki-textarea/' + + 'edit-wiki-textarea.directive.html', - this.togglePreview = function() { - this.isPreview = !this.isPreview; - this.previewHtml = ''; - // $scope.error = null; - if (!this.isPreview) { - return; - } - $scope.fieldController.state.isBusy = true; - TextileService - .renderWithWorkPackageContext( - EditableFieldsState.workPackage.form, - $scope.fieldController.writeValue.raw) - .then(angular.bind(this, function(r) { - this.previewHtml = $sce.trustAsHtml(r.data); - $scope.fieldController.state.isBusy = false; - }), angular.bind(this, function() { - this.isPreview = false; - $scope.fieldController.state.isBusy = false; - })); - }; - }, - controllerAs: 'customEditorController', - link: function(scope, element) { - scope.fieldController = scope.$parent.fieldController; - $timeout(function() { - AutoCompleteHelper.enableTextareaAutoCompletion(element.find('textarea')); - // set as dirty for the script to show a confirm on leaving the page - element.find('textarea').data('changed', true); - }); + controller: InplaceEditorWikiTextareaController, + controllerAs: 'customEditorController', + + link: function(scope, element) { + scope.fieldController = scope.$parent.fieldController; + $timeout(function() { + AutoCompleteHelper.enableTextareaAutoCompletion(element.find('textarea')); + // set as dirty for the script to show a confirm on leaving the page + element.find('textarea').data('changed', true); + }); + + // Listen to elastic textara expansion to always make the bottom + // of that textarea visible. + // Otherwise, when expanding the textarea with newlines, + // its bottom border may no longer be visible + scope.$on('elastic:resize', function(event, textarea, oldHeight, newHeight) { + var containerHeight = element.scrollParent().height(); + + // We can only help the user if the whole textarea fits in the screen + if (newHeight >= (containerHeight - (containerHeight / 5))) { + return; + } - // Listen to elastic textara expansion to always make the bottom - // of that textarea visible. - // Otherwise, when expanding the textarea with newlines, - // its bottom border may no longer be visible - scope.$on('elastic:resize', function(event, textarea, oldHeight, newHeight) { - var containerHeight = element.scrollParent().height(); + $timeout(function() { + var controls = element.closest('.inplace-edit--form ') + .find('.inplace-edit--controls'); - // We can only help the user if the whole textarea fits in the screen - if (newHeight >= (containerHeight - (containerHeight / 5))) { - return; + if (!controls.isVisibleWithin(controls.scrollParent())) { + controls[0].scrollIntoView(false); } + }, 200); + }); + } + }; +} +inplaceEditorWikiTextarea.$inject = ['AutoCompleteHelper', '$timeout']; + + +function InplaceEditorWikiTextareaController($scope,$sce, TextileService, EditableFieldsState) { + this.isPreview = false; + this.previewHtml = ''; + this.autocompletePath = '/work_packages/auto_complete.json'; - $timeout(function() { - var controls = element.closest('.inplace-edit--form ') - .find('.inplace-edit--controls'); + this.togglePreview = function() { + this.isPreview = !this.isPreview; + this.previewHtml = ''; + // $scope.error = null; + if (!this.isPreview) { + return; + } - if (!controls.isVisibleWithin(controls.scrollParent())) { - controls[0].scrollIntoView(false); - } - }, 200); - }); - } - }; - } -]); + $scope.fieldController.state.isBusy = true; + TextileService.renderWithWorkPackageContext(EditableFieldsState.workPackage.form, + $scope.fieldController.writeValue.raw) + + .then(angular.bind(this, function(r) { + this.previewHtml = $sce.trustAsHtml(r.data); + $scope.fieldController.state.isBusy = false; + }), angular.bind(this, function() { + this.isPreview = false; + $scope.fieldController.state.isBusy = false; + })); + }; +} +InplaceEditorWikiTextareaController.$inject = ['$scope', '$sce', 'TextileService', + 'EditableFieldsState']; diff --git a/frontend/app/components/inplace-edit/directives/main-pane/main-pane.directive.js b/frontend/app/components/inplace-edit/directives/main-pane/main-pane.directive.js index 22a6f6c0ba..0a340d7bed 100644 --- a/frontend/app/components/inplace-edit/directives/main-pane/main-pane.directive.js +++ b/frontend/app/components/inplace-edit/directives/main-pane/main-pane.directive.js @@ -26,30 +26,37 @@ // See doc/COPYRIGHT.rdoc for more details. // ++ -angular.module('openproject.inplace-edit').directive('inplaceEditorMainPane', function() { +angular + .module('openproject.inplace-edit') + .directive('inplaceEditorMainPane', inplaceEditorMainPane); + +function inplaceEditorMainPane() { return { transclude: true, replace: true, scope: false, templateUrl: '/components/inplace-edit/directives/main-pane/main-pane.directive.html', - controller: function($scope, $timeout) { - // controller is invoked before linker - $timeout(function() { - var fieldController = $scope.fieldController; - this.saveTitle = I18n.t( - 'js.inplace.button_save', - { attribute: fieldController.field } - ); - this.saveAndSendTitle = I18n.t( - 'js.inplace.button_save_and_send', - { attribute: fieldController.field } - ); - this.cancelTitle = I18n.t( - 'js.inplace.button_cancel', - { attribute: fieldController.field } - ); - }); - }, + controller: InplaceEditorMainPaneController, controllerAs: 'mainPaneController' }; -}); +} + +function InplaceEditorMainPaneController($scope, $timeout) { + // controller is invoked before linker + $timeout(function() { + var fieldController = $scope.fieldController; + this.saveTitle = I18n.t( + 'js.inplace.button_save', + { attribute: fieldController.field } + ); + this.saveAndSendTitle = I18n.t( + 'js.inplace.button_save_and_send', + { attribute: fieldController.field } + ); + this.cancelTitle = I18n.t( + 'js.inplace.button_cancel', + { attribute: fieldController.field } + ); + }); +} +InplaceEditorMainPaneController.$inject = ['$scope', '$timeout']; diff --git a/frontend/app/components/inplace-edit/directives/work-package-field/work-package-field.directive.js b/frontend/app/components/inplace-edit/directives/work-package-field/work-package-field.directive.js index aa5158d688..be9d6bc51c 100644 --- a/frontend/app/components/inplace-edit/directives/work-package-field/work-package-field.directive.js +++ b/frontend/app/components/inplace-edit/directives/work-package-field/work-package-field.directive.js @@ -26,48 +26,54 @@ // See doc/COPYRIGHT.rdoc for more details. //++ -angular.module('openproject.inplace-edit').directive('workPackageField', - function() { - return { - restrict: 'E', - replace: true, - controllerAs: 'fieldController', - bindToController: true, - templateUrl: '/components/inplace-edit/directives/work-package-field/work-package-field.directive.html', - scope: { - field: '=' - }, - controller: function ($scope, EditableFieldsState, WorkPackageFieldService) { - this.state = EditableFieldsState; +angular + .module('openproject.inplace-edit') + .directive('workPackageField', workPackageField); - this.isEditable = function() { - return WorkPackageFieldService.isEditable(EditableFieldsState.workPackage, this.field); - }; +function workPackageField() { + return { + restrict: 'E', + replace: true, + controllerAs: 'fieldController', + bindToController: true, + templateUrl: '/components/inplace-edit/directives/work-package-field/work-package-field.directive.html', + scope: { + field: '=' + }, + controller: WorkPackageFieldController + }; +} - this.isEmpty = function() { - return WorkPackageFieldService.isEmpty(EditableFieldsState.workPackage, this.field); - }; +function WorkPackageFieldController($scope, EditableFieldsState, WorkPackageFieldService) { + this.state = EditableFieldsState; - this.getLabel = function() { - return WorkPackageFieldService.getLabel(EditableFieldsState.workPackage, this.field); - }; + this.isEditable = function() { + return WorkPackageFieldService.isEditable(EditableFieldsState.workPackage, this.field); + }; - this.updateWriteValue = function() { - this.writeValue = EditableFieldsState.editAll.getFieldValue(this.field) || _.cloneDeep( - WorkPackageFieldService.getValue(EditableFieldsState.workPackage, this.field)); - }; + this.isEmpty = function() { + return WorkPackageFieldService.isEmpty(EditableFieldsState.workPackage, this.field); + }; - if (this.isEditable()) { - this.state.isBusy = false; - this.isEditing = this.state.forcedEditState; - this.updateWriteValue(); - this.editTitle = I18n.t('js.inplace.button_edit', { attribute: this.getLabel() }); - } + this.getLabel = function() { + return WorkPackageFieldService.getLabel(EditableFieldsState.workPackage, this.field); + }; - $scope.$watch('fieldController.writeValue', angular.bind(this, function (newValue) { - EditableFieldsState.editAll.addFieldValue(this.field, newValue); - })); - } - }; + this.updateWriteValue = function() { + this.writeValue = EditableFieldsState.editAll.getFieldValue(this.field) || _.cloneDeep( + WorkPackageFieldService.getValue(EditableFieldsState.workPackage, this.field)); + }; + + if (this.isEditable()) { + this.state.isBusy = false; + this.isEditing = this.state.forcedEditState; + this.updateWriteValue(); + this.editTitle = I18n.t('js.inplace.button_edit', { attribute: this.getLabel() }); } -); + + $scope.$watch('fieldController.writeValue', angular.bind(this, function (newValue) { + EditableFieldsState.editAll.addFieldValue(this.field, newValue); + })); +} +WorkPackageFieldController.$inject = ['$scope', 'EditableFieldsState', 'WorkPackageFieldService']; +