Merge pull request #4160 from furinvader/refactoring/inplace-edit

Refactor inplace edit module
pull/4186/head
Alex Dik 9 years ago
commit c2b02fb9d5
  1. 0
      frontend/app/components/inplace-edit/display-pane/display-pane.directive.html
  2. 70
      frontend/app/components/inplace-edit/display-pane/display-pane.directive.ts
  3. 0
      frontend/app/components/inplace-edit/edit-actions-bar/edit-actions-bar.directive.html
  4. 67
      frontend/app/components/inplace-edit/edit-actions-bar/edit-actions-bar.directive.ts
  5. 0
      frontend/app/components/inplace-edit/edit-pane/edit-pane.directive.html
  6. 26
      frontend/app/components/inplace-edit/edit-pane/edit-pane.directive.ts
  7. 0
      frontend/app/components/inplace-edit/editable-fields-state/editable-fields-state.service.js
  8. 0
      frontend/app/components/inplace-edit/editable-fields-state/editable-fields-state.service.test.js
  9. 0
      frontend/app/components/inplace-edit/field-directives/display-spent-time/display-spent-time.directive.html
  10. 2
      frontend/app/components/inplace-edit/field-directives/display-spent-time/display-spent-time.directive.js
  11. 0
      frontend/app/components/inplace-edit/field-directives/display-user/display-user.directive.html
  12. 2
      frontend/app/components/inplace-edit/field-directives/display-user/display-user.directive.js
  13. 0
      frontend/app/components/inplace-edit/field-directives/display-version/display-version.directive.html
  14. 2
      frontend/app/components/inplace-edit/field-directives/display-version/display-version.directive.js
  15. 0
      frontend/app/components/inplace-edit/field-directives/edit-date-range/edit-date-range.directive.html
  16. 2
      frontend/app/components/inplace-edit/field-directives/edit-date-range/edit-date-range.directive.js
  17. 0
      frontend/app/components/inplace-edit/field-directives/edit-date/edit-date.directive.html
  18. 4
      frontend/app/components/inplace-edit/field-directives/edit-date/edit-date.directive.js
  19. 0
      frontend/app/components/inplace-edit/field-directives/edit-drop-down/edit-drop-down.directive.html
  20. 4
      frontend/app/components/inplace-edit/field-directives/edit-drop-down/edit-drop-down.directive.js
  21. 0
      frontend/app/components/inplace-edit/field-directives/edit-duration/edit-duration.directive.html
  22. 2
      frontend/app/components/inplace-edit/field-directives/edit-duration/edit-duration.directive.js
  23. 0
      frontend/app/components/inplace-edit/field-directives/edit-type/edit-type.directive.html
  24. 5
      frontend/app/components/inplace-edit/field-directives/edit-type/edit-type.directive.js
  25. 0
      frontend/app/components/inplace-edit/field-directives/edit-wiki-textarea/edit-wiki-textarea.directive.html
  26. 2
      frontend/app/components/inplace-edit/field-directives/edit-wiki-textarea/edit-wiki-textarea.directive.js
  27. 0
      frontend/app/components/inplace-edit/field-templates/display/boolean.html
  28. 0
      frontend/app/components/inplace-edit/field-templates/display/date-range.html
  29. 0
      frontend/app/components/inplace-edit/field-templates/display/date.html
  30. 0
      frontend/app/components/inplace-edit/field-templates/display/dynamic.html
  31. 0
      frontend/app/components/inplace-edit/field-templates/display/embedded.html
  32. 0
      frontend/app/components/inplace-edit/field-templates/display/spent-time.html
  33. 0
      frontend/app/components/inplace-edit/field-templates/display/text.html
  34. 0
      frontend/app/components/inplace-edit/field-templates/display/user.html
  35. 0
      frontend/app/components/inplace-edit/field-templates/display/version.html
  36. 0
      frontend/app/components/inplace-edit/field-templates/display/wiki-textarea.html
  37. 0
      frontend/app/components/inplace-edit/field-templates/edit/boolean.html
  38. 0
      frontend/app/components/inplace-edit/field-templates/edit/date-range.html
  39. 0
      frontend/app/components/inplace-edit/field-templates/edit/date.html
  40. 0
      frontend/app/components/inplace-edit/field-templates/edit/drop-down.html
  41. 0
      frontend/app/components/inplace-edit/field-templates/edit/duration.html
  42. 0
      frontend/app/components/inplace-edit/field-templates/edit/float.html
  43. 0
      frontend/app/components/inplace-edit/field-templates/edit/integer.html
  44. 0
      frontend/app/components/inplace-edit/field-templates/edit/text.html
  45. 0
      frontend/app/components/inplace-edit/field-templates/edit/textarea.html
  46. 0
      frontend/app/components/inplace-edit/field-templates/edit/type.html
  47. 0
      frontend/app/components/inplace-edit/field-templates/edit/wiki-textarea.html
  48. 0
      frontend/app/components/inplace-edit/inplace-edit-all/inplace-edit-all.service.js
  49. 0
      frontend/app/components/inplace-edit/inplace-edit-all/inplace-edit-all.service.test.js
  50. 0
      frontend/app/components/inplace-edit/inplace-edit-errors/inplace-edit-errors.service.js
  51. 0
      frontend/app/components/inplace-edit/inplace-edit-form/inplace-edit-form.service.js
  52. 0
      frontend/app/components/inplace-edit/inplace-edit-form/inplace-edit-form.service.test.js
  53. 0
      frontend/app/components/inplace-edit/inplace-edit-multi-storage/inplace-edit-multi-storage.service.js
  54. 0
      frontend/app/components/inplace-edit/inplace-edit-storage/inplace-edit-storage.service.js
  55. 0
      frontend/app/components/inplace-edit/inplace-edit.service.js
  56. 0
      frontend/app/components/inplace-edit/main-pane/main-pane.directive.html
  57. 10
      frontend/app/components/inplace-edit/main-pane/main-pane.directive.ts
  58. 0
      frontend/app/components/inplace-edit/wp-field/wp-field.directive.html
  59. 42
      frontend/app/components/inplace-edit/wp-field/wp-field.directive.ts
  60. 4
      frontend/app/components/inplace-edit/wp-field/wp-field.service.js
  61. 2
      frontend/app/components/routing/wp-details/wp.list.details.html
  62. 6
      frontend/app/components/routing/wp-show/wp.show.html
  63. 6
      frontend/app/components/work-packages/wp-create-form/wp-create-form.directive.html
  64. 6
      frontend/app/components/work-packages/wp-create-form/wp-full-create-form.directive.html
  65. 4
      frontend/app/templates/work_packages/tabs/overview.html
  66. 2
      frontend/tests/unit/tests/components/inplace-edit/directives/edit-drop-down.directive.test.js

@ -26,16 +26,40 @@
// See doc/COPYRIGHT.rdoc for more details.
// ++
angular
.module('openproject.inplace-edit')
.directive('inplaceEditorDisplayPane', inplaceEditorDisplayPane);
function InplaceEditorDisplayPaneController($scope, HookService, I18n:op.I18n) {
var field = $scope.field;
this.getAriaLabel = function() {
return I18n.t('js.work_packages.edit_attribute', { attribute: field.getKeyValue() });
};
this.placeholder = field.placeholder;
this.startEditing = function() {
if (!field.isEditable()) {
throw 'Trying to edit the non editable field "' + field.name + '"';
}
var fieldController = $scope.fieldController;
fieldController.isEditing = 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: field.getSchema(field.resource).props[field.name].type,
field: field.name,
workPackage: field.resource
})[0];
};
}
function inplaceEditorDisplayPane(EditableFieldsState, $timeout) {
return {
replace: true,
transclude: true,
require: '^workPackageField',
templateUrl: '/components/inplace-edit/directives/display-pane/display-pane.directive.html',
require: '^wpField',
templateUrl: '/components/inplace-edit/display-pane/display-pane.directive.html',
controller: InplaceEditorDisplayPaneController,
controllerAs: 'displayPaneController',
@ -50,7 +74,8 @@ function inplaceEditorDisplayPane(EditableFieldsState, $timeout) {
if (strategy !== scope.displayStrategy) {
scope.displayStrategy = strategy;
scope.templateUrl = '/templates/inplace-edit/display/fields/' + strategy +'.html';
scope.templateUrl =
'/components/inplace-edit/field-templates/display/' + strategy + '.html';
}
});
@ -78,34 +103,7 @@ function inplaceEditorDisplayPane(EditableFieldsState, $timeout) {
}
};
}
inplaceEditorDisplayPane.$inject = ['EditableFieldsState', '$timeout'];
function InplaceEditorDisplayPaneController($scope, HookService) {
var field = $scope.field;
this.getAriaLabel = function() {
return I18n.t('js.work_packages.edit_attribute', { attribute: field.getKeyValue() });
};
this.placeholder = field.placeholder;
this.startEditing = function() {
if (!field.isEditable()) {
throw 'Trying to edit the non editable field "' + field.name + '"';
}
var fieldController = $scope.fieldController;
fieldController.isEditing = 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: field.getSchema(field.resource).props[field.name].type,
field: field.name,
workPackage: field.resource
})[0];
};
}
InplaceEditorDisplayPaneController.$inject = ['$scope', 'HookService'];
angular
.module('openproject.inplace-edit')
.directive('inplaceEditorDisplayPane', inplaceEditorDisplayPane);

@ -26,16 +26,41 @@
// See doc/COPYRIGHT.rdoc for more details.
// ++
angular
.module('openproject.inplace-edit')
.directive('editActionsBar', editActionsBar);
class EditActionsBarController {
public onSave;
public onCancel;
public text;
constructor(protected EditableFieldsState,
protected inplaceEditMultiStorage,
protected inplaceEditAll,
I18n:op.I18n) {
this.text = {
save: I18n.t('js.button_save'),
cancel: I18n.t('js.button_cancel')
}
}
public visible() {
return this.inplaceEditAll.state && this.EditableFieldsState.canEdit;
}
public save() {
this.inplaceEditMultiStorage.save().then(this.onSave);
}
public cancel() {
this.onCancel();
this.inplaceEditAll.cancel();
}
}
function editActionsBar() {
return {
restrict: 'E',
replace: true,
templateUrl: '/components/inplace-edit/directives/edit-actions-bar/' +
'edit-actions-bar.directive.html',
templateUrl: '/components/inplace-edit/edit-actions-bar/edit-actions-bar.directive.html',
scope: {
onCancel: '&',
@ -43,31 +68,11 @@ function editActionsBar() {
},
bindToController: true,
controllerAs: 'vm',
controller: function ($scope, I18n, EditableFieldsState, inplaceEditMultiStorage,
inplaceEditAll) {
var vm = this;
angular.extend(vm, {
visible: function () {
return inplaceEditAll.state && EditableFieldsState.canEdit;
},
save: function () {
inplaceEditMultiStorage.save().then(vm.onSave);
},
cancel: function () {
vm.onCancel();
inplaceEditAll.cancel();
},
text: {
save: I18n.t('js.button_save'),
cancel: I18n.t('js.button_cancel')
}
});
}
controller: EditActionsBarController,
controllerAs: 'vm'
};
}
angular
.module('openproject.inplace-edit')
.directive('editActionsBar', editActionsBar);

@ -26,15 +26,11 @@
// See doc/COPYRIGHT.rdoc for more details.
// ++
angular
.module('openproject.inplace-edit')
.directive('inplaceEditorEditPane', inplaceEditorEditPane);
function inplaceEditorEditPane($timeout, EditableFieldsState, FocusHelper, inplaceEditAll) {
return {
transclude: true,
require: '^workPackageField',
templateUrl: '/components/inplace-edit/directives/edit-pane/edit-pane.directive.html',
require: '^wpField',
templateUrl: '/components/inplace-edit/edit-pane/edit-pane.directive.html',
controllerAs: 'editPaneController',
controller: InplaceEditorEditPaneController,
@ -85,8 +81,15 @@ function inplaceEditorEditPane($timeout, EditableFieldsState, FocusHelper, inpla
};
}
function InplaceEditorEditPaneController($scope, $element, $location, $timeout,
EditableFieldsState, inplaceEditStorage, inplaceEditMultiStorage, inplaceEditErrors,
function InplaceEditorEditPaneController($scope,
$element,
$location,
$timeout,
EditableFieldsState,
inplaceEditStorage,
inplaceEditMultiStorage,
inplaceEditErrors,
I18n,
inplaceEditAll) {
var vm = this;
@ -163,6 +166,7 @@ function InplaceEditorEditPaneController($scope, $element, $location, $timeout,
var strategy = field.getInplaceEditStrategy();
if (field.name === 'date' && strategy === 'date') {
//noinspection TypeScriptUnresolvedVariable
form.pendingChanges = EditableFieldsState.getPendingFormChanges();
form.pendingChanges['startDate'] =
form.pendingChanges['dueDate'] =
@ -171,7 +175,7 @@ function InplaceEditorEditPaneController($scope, $element, $location, $timeout,
if (strategy !== $scope.strategy) {
$scope.strategy = strategy;
$scope.templateUrl = '/templates/inplace-edit/edit/fields/' + strategy + '.html';
$scope.templateUrl = '/components/inplace-edit/field-templates/edit/' + strategy + '.html';
}
});
@ -183,3 +187,7 @@ function InplaceEditorEditPaneController($scope, $element, $location, $timeout,
vm.discardEditing();
});
}
angular
.module('openproject.inplace-edit')
.directive('inplaceEditorEditPane', inplaceEditorEditPane);

@ -35,7 +35,7 @@ function inplaceDisplaySpentTime() {
restrict: 'E',
transclude: true,
replace: true,
templateUrl: '/components/inplace-edit/directives/field-display/display-spent-time/' +
templateUrl: '/components/inplace-edit/field-directives/display-spent-time/' +
'display-spent-time.directive.html',
controller: InplaceDisplaySpentTimeController,

@ -36,7 +36,7 @@ function inplaceDisplayUser() {
transclude: true,
replace: true,
require: '^inplaceEditorDisplayPane',
templateUrl: '/components/inplace-edit/directives/field-display/display-user/' +
templateUrl: '/components/inplace-edit/field-directives/display-user/' +
'display-user.directive.html',
controller: InplaceDisplayUserController,

@ -35,7 +35,7 @@ function inplaceDisplayVersion() {
restrict: 'E',
transclude: true,
replace: true,
templateUrl: '/components/inplace-edit/directives/field-display/display-version/' +
templateUrl: '/components/inplace-edit/field-directives/display-version/' +
'display-version.directive.html',
controller: InplaceDisplayVersionController,

@ -37,7 +37,7 @@ function inplaceEditorDateRange($timeout, TimezoneService, WorkPackageFieldServi
restrict: 'E',
transclude: true,
replace: true,
templateUrl: '/components/inplace-edit/directives/field-edit/edit-date-range/' +
templateUrl: '/components/inplace-edit/field-directives/edit-date-range/' +
'edit-date-range.directive.html',
controller: angular.noop,

@ -42,8 +42,8 @@ function inplaceEditorDate($timeout, inplaceEditAll, TimezoneService,
restrict: 'E',
transclude: true,
replace: true,
require: '^workPackageField',
templateUrl: '/components/inplace-edit/directives/field-edit/edit-date/' +
require: '^wpField',
templateUrl: '/components/inplace-edit/field-directives/edit-date/' +
'edit-date.directive.html',
controller: angular.noop,

@ -35,8 +35,8 @@ function inplaceEditorDropDown(EditableFieldsState, FocusHelper, inplaceEditAll)
restrict: 'E',
transclude: true,
replace: true,
require: '^workPackageField',
templateUrl: '/components/inplace-edit/directives/field-edit/edit-drop-down/' +
require: '^wpField',
templateUrl: '/components/inplace-edit/field-directives/edit-drop-down/' +
'edit-drop-down.directive.html',
controller: InplaceEditorDropDownController,

@ -35,7 +35,7 @@ function inplaceEditorDuration() {
restrict: 'E',
transclude: true,
replace: true,
templateUrl: '/components/inplace-edit/directives/field-edit/edit-duration/' +
templateUrl: '/components/inplace-edit/field-directives/edit-duration/' +
'edit-duration.directive.html',
controllerAs: 'customEditorController',

@ -35,9 +35,8 @@ function inplaceEditorType() {
restrict: 'E',
transclude: true,
replace: true,
require: '^workPackageField',
templateUrl: '/components/inplace-edit/directives/field-edit/edit-type/' +
'edit-type.directive.html',
require: '^wpField',
templateUrl: '/components/inplace-edit/field-directives/edit-type/edit-type.directive.html',
link: function(scope) {
scope.$watch('field.value.props', function(newValue, oldValue) {

@ -35,7 +35,7 @@ function inplaceEditorWikiTextarea(AutoCompleteHelper, $timeout) {
restrict: 'E',
transclude: true,
replace: true,
templateUrl: '/components/inplace-edit/directives/field-edit/edit-wiki-textarea/' +
templateUrl: '/components/inplace-edit/field-directives/edit-wiki-textarea/' +
'edit-wiki-textarea.directive.html',
controller: InplaceEditorWikiTextareaController,

@ -26,14 +26,14 @@
// See doc/COPYRIGHT.rdoc for more details.
// ++
angular
.module('openproject.inplace-edit')
.directive('inplaceEditorMainPane', inplaceEditorMainPane);
function inplaceEditorMainPane() {
return {
transclude: true,
replace: true,
templateUrl: '/components/inplace-edit/directives/main-pane/main-pane.directive.html'
templateUrl: '/components/inplace-edit/main-pane/main-pane.directive.html'
};
}
angular
.module('openproject.inplace-edit')
.directive('inplaceEditorMainPane', inplaceEditorMainPane);

@ -26,16 +26,32 @@
// See doc/COPYRIGHT.rdoc for more details.
//++
angular
.module('openproject.inplace-edit')
.directive('workPackageField', workPackageField);
class WorkPackageFieldController {
public fieldName:string;
public state;
public isEditing;
public editTitle:string;
constructor($scope, EditableFieldsState, inplaceEditForm, inplaceEditAll, I18n) {
var workPackage = EditableFieldsState.workPackage;
this.state = EditableFieldsState;
$scope.field = inplaceEditForm.getForm(workPackage.props.id, workPackage).field(this.fieldName);
var field = $scope.field;
if (field.isEditable()) {
this.state.isBusy = false;
this.isEditing = inplaceEditAll.state;
this.editTitle = I18n.t('js.inplace.button_edit', {attribute: field.getLabel()});
}
}
}
function workPackageField() {
return {
restrict: 'E',
replace: true,
templateUrl: '/components/inplace-edit/directives/work-package-field/' +
'work-package-field.directive.html',
templateUrl: '/components/inplace-edit/wp-field/wp-field.directive.html',
scope: {
fieldName: '='
},
@ -46,17 +62,7 @@ function workPackageField() {
};
}
function WorkPackageFieldController($scope, EditableFieldsState, inplaceEditForm, inplaceEditAll) {
var workPackage = EditableFieldsState.workPackage;
this.state = EditableFieldsState;
$scope.field = inplaceEditForm.getForm(workPackage.props.id, workPackage).field(this.fieldName);
var field = $scope.field;
if (field.isEditable()) {
this.state.isBusy = false;
this.isEditing = inplaceEditAll.state;
this.editTitle = I18n.t('js.inplace.button_edit', { attribute: field.getLabel() });
}
}
angular
.module('openproject.inplace-edit')
.directive('wpField', workPackageField);

@ -1,4 +1,4 @@
//-- copyright
// -- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
@ -24,7 +24,7 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
// ++
angular
.module('openproject.services')

@ -27,7 +27,7 @@
</span>
<div class="work-packages--details--title">
<work-package-field field-name="'subject'"></work-package-field>
<wp-field field-name="'subject'"></wp-field>
</div>
<div class="work-package-details-tab" ui-view></div>

@ -47,7 +47,7 @@
<ul class="subject-header">
<li class="subject-header-inner">
<div class="inline-edit">
<work-package-field field-name="'subject'"></work-package-field>
<wp-field field-name="'subject'"></wp-field>
</div>
</li>
</ul>
@ -78,7 +78,7 @@
</div>
<div class="single-attribute wiki">
<work-package-field field-name="'description'"></work-package-field>
<wp-field field-name="'description'"></wp-field>
</div>
</div>
@ -113,7 +113,7 @@
ng-if="vm.isSpecified(vm.workPackage, field)"
ng-repeat-end
class="attributes-key-value--value-container">
<work-package-field field-name="field"></work-package-field>
<wp-field field-name="field"></wp-field>
</div>
</div>
</div>

@ -3,7 +3,7 @@
<h2>{{ vm.getHeading() }}</h2>
<div class="work-packages--create--title">
<work-package-field field-name="'subject'" tabindex="0"></work-package-field>
<wp-field field-name="'subject'" tabindex="0"></wp-field>
</div>
<div class="attributes-group--header">
@ -15,7 +15,7 @@
</div>
<div class="single-attribute wiki">
<work-package-field field-name="'description'"></work-package-field>
<wp-field field-name="'description'"></wp-field>
</div>
<div ng-repeat="group in vm.groupedFields"
@ -49,7 +49,7 @@
ng-if="vm.isSpecified(vm.workPackage, field) && vm.isEditable(vm.workPackage, field)"
ng-repeat-end
class="attributes-key-value--value-container">
<work-package-field field-name="field"></work-package-field>
<wp-field field-name="field"></wp-field>
</div>
</div>
</div>

@ -33,7 +33,7 @@
<h2>{{ vm.getHeading() }}</h2>
<div class="work-packages--create--title">
<work-package-field field-name="'subject'" tabindex="0"></work-package-field>
<wp-field field-name="'subject'" tabindex="0"></wp-field>
</div>
<div class="attributes-group--header">
@ -45,7 +45,7 @@
</div>
<div class="single-attribute wiki">
<work-package-field field-name="'description'"></work-package-field>
<wp-field field-name="'description'"></wp-field>
</div>
<div ng-repeat="group in vm.groupedFields"
@ -79,7 +79,7 @@
ng-if="vm.isSpecified(vm.workPackage, field) && vm.isEditable(vm.workPackage, field)"
ng-repeat-end
class="attributes-key-value--value-container">
<work-package-field field-name="field"></work-package-field>
<wp-field field-name="field"></wp-field>
</div>
</div>
</div>

@ -13,7 +13,7 @@
</div>
<div class="single-attribute wiki">
<work-package-field field-name="'description'"></work-package-field>
<wp-field field-name="'description'"></wp-field>
</div>
</div>
@ -46,7 +46,7 @@
ng-if="vm.isSpecified(vm.workPackage, field)"
ng-repeat-end
class="attributes-key-value--value-container">
<work-package-field field-name="field"></work-package-field>
<wp-field field-name="field"></wp-field>
</div>
</div>
</div>

@ -69,7 +69,7 @@ describe('Inplace editor drop-down directive', function() {
var workPackageFieldController = {
state: { isBusy: false }
};
element.data('$workPackageFieldController', workPackageFieldController);
element.data('$wpFieldController', workPackageFieldController);
workPackageFieldConfigurationService.getDropdownSortingStrategy = sinon.stub().returns(null);
}));

Loading…
Cancel
Save