reuse most classes; partial subject and description on new layout

pull/2687/head
Mihail Maxacov 10 years ago
parent 391f036abe
commit 2d3cabd124
  1. 3
      frontend/app/routing.js
  2. 1
      frontend/app/services/index.js
  3. 11
      frontend/app/services/work-package-service.js
  4. 2
      frontend/app/templates/components/inplace_editor/display/default.html
  5. 2
      frontend/app/templates/components/inplace_editor/display/wiki_textarea.html
  6. 6
      frontend/app/templates/components/inplace_editor/editable/text.html
  7. 4
      frontend/app/templates/components/inplace_editor/editable/wiki_textarea.html
  8. 11
      frontend/app/templates/work_packages.list.details.html
  9. 21
      frontend/app/templates/work_packages/field.html
  10. 16
      frontend/app/templates/work_packages/inplace_editor/display_pane.html
  11. 20
      frontend/app/templates/work_packages/inplace_editor/edit_pane.html
  12. 7
      frontend/app/templates/work_packages/inplace_editor/main_pane.html
  13. 12
      frontend/app/templates/work_packages/tabs/overview.html
  14. 1
      frontend/app/work_packages/controllers/index.js
  15. 5
      frontend/app/work_packages/controllers/work-package-details-controller.js
  16. 8
      frontend/app/work_packages/directives/inplace_editor/inplace-editor-display-pane-directive.js
  17. 23
      frontend/app/work_packages/directives/inplace_editor/inplace-editor-edit-pane-directive.js
  18. 42
      frontend/app/work_packages/directives/work-package-field-directive.js
  19. 33
      frontend/app/work_packages/services/editable-fields-state.js
  20. 5
      frontend/app/work_packages/services/index.js
  21. 5
      frontend/app/work_packages/services/work-package-field-service.js

@ -77,13 +77,14 @@ angular.module('openproject')
templateUrl: "/templates/work_packages.list.details.html",
controller: 'WorkPackageDetailsController',
resolve: {
workPackage: function(WorkPackageService, $stateParams) {
workPackage: function(WorkPackageService, EditableFieldsState, $stateParams) {
return WorkPackageService.getWorkPackage($stateParams.workPackageId).then(function(wp) {
return WorkPackageService.loadWorkPackageForm(wp).then(function() {
// TODO: refactor to $q.all since schema and form do not
// depend on each other
return wp.links.schema.fetch().then(function(response) {
wp.schema = response;
EditableFieldsState.workPackage = wp;
return wp;
});
});

@ -99,5 +99,6 @@ angular.module('openproject.services')
'$window',
'$q',
'AuthorisationService',
'EditableFieldsState',
require('./work-package-service')
]);

@ -35,7 +35,8 @@ module.exports = function($http,
$rootScope,
$window,
$q,
AuthorisationService) {
AuthorisationService,
EditableFieldsState) {
var workPackage;
var WorkPackageService = {
@ -173,18 +174,14 @@ module.exports = function($http,
data: JSON.stringify(data),
contentType: 'application/json; charset=utf-8'
}, force: true};
return workPackage.links.updateImmediately.fetch(options).then(function() {
console.log('1');
return workPackage.links.updateImmediately.fetch(options).then(function(workPackage) {
return workPackage.links.self
.fetch({force: true})
.then(function(workPackage) {
console.log('2');
return WorkPackageService.loadWorkPackageForm(workPackage).then(function() {
return workPackage.links.schema.fetch().then(function(response) {
console.log('3');
workPackage.schema = response;
workPackage.form.pendingChanges = {};
console.log('4');
EditableFieldsState.workPackage = workPackage;
return workPackage;
});
});

@ -1 +1 @@
<span ng-bind="readValue"></span>
<span ng-bind="fieldController.getReadValue()"></span>

@ -1 +1 @@
<span ng-bind-html="readValue"></span>
<span ng-bind-html="fieldController.getReadValue().html"></span>

@ -1,6 +1,6 @@
<input class="focus-input inplace-edit--text-field"
name="value"
type="text"
ng-disabled="isBusy"
title="{{ editTitle }}"
ng-model="dataObject.value" />
ng-disabled="fieldController.isBusy"
title="{{ fieldController.editTitle }}"
ng-model="fieldController.writeValue" />

@ -5,7 +5,7 @@
preview-toggle="togglePreview()"
name="value"
ng-disabled="isBusy"
ng-model="dataObject.value"
ng-model="fieldController.writeValue.raw"
title="{{ editTitle }}"
data-wp_autocomplete_url="{{ autocompletePath }}">
</textarea>
@ -13,7 +13,7 @@
class="focus-input inplace-edit--textarea"
name="value"
ng-disabled="isBusy"
ng-model="dataObject.value"
ng-model="fieldController.writeValue.raw"
title="{{ editTitle }}"
data-wp_autocomplete_url="{{ autocompletePath }}">
</textarea>

@ -32,18 +32,9 @@
<div class="work-packages--details--title">
<div class="work-packages--details--type">{{ type.props.name }}:</div>
<div class="work-packages--details--subject"
inplace-editor
ined-type="text"
ined-entity="workPackage"
ined-attribute="subject"
ined-attribute-title="{{ I18n.t('js.work_packages.properties.subject') }}"
title="{{ workPackage.props.subject }}">
</div>
<work-package-field field="'subject'"></work-package-field>
</div>
<work-package-field work-package="workPackage" field="'subject'"></work-package-text-field>
<span class="subtitle">
<accessible-by-keyboard ng-if="toggleWatchLink" execute="toggleWatch()"

@ -1,21 +1,12 @@
<div class="work-package-field">
<div class="editable-branch" ng-if="fieldController.isEditable">
<div class="editable-branch" ng-if="fieldController.isEditable()">
<inplace-editor-main-pane>
<inplace-editor-display-pane>
<div ng-bind="fieldController.readValue"></div>
</inplace-editor-display-pane>
<inplace-editor-edit-pane>
<input class="focus-input"
name="value"
type="text"
ng-disabled="fieldController.isBusy"
title="{{ fieldController.editTitle }}"
ng-model="fieldController.writeValue" />
</inplace-editor-edit-pane>
<inplace-editor-display-pane></inplace-editor-display-pane>
<inplace-editor-edit-pane></inplace-editor-edit-pane>
</inplace-editor-main-pane>
</div>
<div class="static-branch" ng-if="!fieldController.isEditable">
<empty-element ng-if="fieldController.isEmpty"></empty-element>
<div class="field-value" ng-if="!fieldController.isEmpty" ng-bind="vm.value"></div>
<div class="static-branch" ng-if="!fieldController.isEditable()">
<empty-element ng-if="fieldController.isEmpty()"></empty-element>
<div class="field-value" ng-if="!fieldController.isEmpty()" ng-bind="fieldController.getReadValue()"></div>
</div>
</div>

@ -1,9 +1,15 @@
<div class="ined-read-value editable" ng-hide="fieldController.isEditing" ng-click="displayPaneController.startEditing()">
<div ng-transclude></div>
<div class="inplace-edit--read" ng-hide="fieldController.isEditing" ng-click="displayPaneController.startEditing()">
<span class="editing-link-wrapper">
<accessible-by-keyboard execute="displayPaneController.startEditing()">
<icon-wrapper icon-name="edit" icon-title="{{ fieldController.editTitle }}">
</icon-wrapper>
<accessible-by-keyboard
class="inplace-editing--trigger-container"
span-class="inplace-editing--container"
link-class="inplace-editing--trigger-link"
execute="displayPaneController.startEditing()">
<span class="inplace-edit--read-value" ng-include="templateUrl"></span>
<span class="inplace-edit--icon-wrapper">
<icon-wrapper icon-name="edit" icon-title="{{ fieldController.editTitle }}">
</icon-wrapper>
</span>
</accessible-by-keyboard>
</span>
</div>

@ -1,23 +1,21 @@
<div class="ined-edit" ng-show="fieldController.isEditing">
<form name="editPaneController.editForm" ng-submit="editPaneController.submit(false)" novalidate>
<div class="ined-input-wrapper">
<div class="ined-input-wrapper-inner" ng-transclude>
<div class="inplace-edit--write" ng-show="fieldController.isEditing">
<form class="inplace-edit--form" name="editPaneController.editForm" ng-submit="editPaneController.submit(false)" novalidate>
<div class="inplace-edit--write-value" ng-include="templateUrl">
</div>
</div>
<div class="ined-dashboard">
<div class="ined-errors" ng-show="fieldController.error" role="alert" ng-bind="fieldController.error" aria-live="polite"></div>
<div class="ined-controls" ng-hide="fieldController.isBusy">
<accessible-by-keyboard execute="editPaneController.editForm.$valid && editPaneController.submit(false)" class="ined-edit-save">
<div class="inplace-edit--dashboard">
<div class="inplace-edit--errors" ng-show="fieldController.error" role="alert" ng-bind="fieldController.error" aria-live="polite"></div>
<div class="inplace-edit--controls" ng-hide="fieldController.isBusy">
<accessible-by-keyboard execute="editPaneController.editForm.$valid && editPaneController.submit(false)" class="inplace-edit--control inplace-edit--control--save">
<icon-wrapper icon-name="yes" icon-title="{{ editPaneController.saveTitle }}">
</icon-wrapper>
</accessible-by-keyboard>
<accessible-by-keyboard execute="editPaneController.editForm.$valid && editPaneController.submit(true)" class="ined-edit-save-send">
<accessible-by-keyboard execute="editPaneController.editForm.$valid && editPaneController.submit(true)" class="inplace-edit--control -icons-2 inplace-edit--control--send">
<span title="{{ editPaneController.saveAndSendTitle }}">
<i class="icon-yes"></i>
<i class="icon-mail"></i>
</span>
</accessible-by-keyboard>
<accessible-by-keyboard execute="editPaneController.discardEditing()" class="ined-edit-close">
<accessible-by-keyboard execute="editPaneController.discardEditing()" class="inplace-edit--control inplace-edit--control--cancel">
<icon-wrapper icon-name="close" icon-title="{{ editPaneController.cancelTitle }}">
</icon-wrapper>
</accessible-by-keyboard>

@ -1,8 +1,7 @@
<div
class="inplace-editor type-{{ fieldController.type }} attribute-{{ fieldController.field }}"
ng-class="{busy: fieldController.isBusy}"
aria-busy="{{ fieldController.isBusy }}"
>
class="inplace-edit type-{{ fieldController.type }} work-packages--details--{{ fieldController.field }}"
ng-class="{'-busy': fieldController.isBusy}"
aria-busy="{{ fieldController.isBusy }}">
<ng-transclude></ng-transclude>
</div>

@ -8,16 +8,8 @@
</div>
</div>
<div ng-if="false" class="single-attribute wiki">
<span inplace-editor
ined-type="wiki_textarea"
ined-display-strategy="wiki_textarea"
ined-entity="workPackage"
ined-attribute="description"
ined-attribute-title="{{ I18n.t('js.work_packages.properties.description') }}"
placeholder="{{ I18n.t('js.label_click_to_enter_description') }}"
autocomplete-path="{{ autocompletePath }}">
</span>
<div class="single-attribute wiki">
<work-package-field field="'description'"></work-package-field>
</div>
</div>

@ -84,6 +84,7 @@ angular.module('openproject.workPackages.controllers')
'CommonRelationsHandler',
'ChildrenRelationsHandler',
'ParentRelationsHandler',
'EditableFieldsState',
require('./work-package-details-controller')
])
.controller('WorkPackagesController', [

@ -41,7 +41,8 @@ module.exports = function($scope,
WorkPackageService,
CommonRelationsHandler,
ChildrenRelationsHandler,
ParentRelationsHandler
ParentRelationsHandler,
EditableFieldsState
) {
$scope.$on('$stateChangeSuccess', function(event, toState){
latestTab.registerState(toState.name);
@ -66,6 +67,7 @@ module.exports = function($scope,
WorkPackageService.loadWorkPackageForm(workPackage).then(function() {
return workPackage.links.schema.fetch().then(function(response) {
workPackage.schema = response;
EditableFieldsState.workPackage = workPackage;
if (callback) {
callback(workPackage);
}
@ -94,7 +96,6 @@ module.exports = function($scope,
function setWorkPackageScopeProperties(workPackage){
$scope.workPackage = workPackage;
$scope.isWatched = !!workPackage.links.unwatchChanges;
if (workPackage.links.watchChanges === undefined) {

@ -26,7 +26,7 @@
// See doc/COPYRIGHT.rdoc for more details.
//++
module.exports = function() {
module.exports = function(WorkPackageFieldService, EditableFieldsState) {
return {
replace: true,
transclude: true,
@ -42,6 +42,12 @@ module.exports = function() {
controllerAs: 'displayPaneController',
link: function(scope, elements, attrs, fieldController) {
scope.fieldController = fieldController;
scope.templateUrl = '/templates/components/inplace_editor/display/' +
WorkPackageFieldService.getInplaceDisplayStrategy(
EditableFieldsState.workPackage,
fieldController.field
) +
'.html';
}
};
}

@ -26,7 +26,7 @@
// See doc/COPYRIGHT.rdoc for more details.
//++
module.exports = function() {
module.exports = function(WorkPackageFieldService, EditableFieldsState) {
return {
transclude: true,
replace: true,
@ -40,9 +40,9 @@ module.exports = function() {
fieldController.isBusy = true;
var pendingFormChanges = getPendingFormChanges();
pendingFormChanges[fieldController.field] = fieldController.writeValue;
var result = WorkPackageService.updateWorkPackage(fieldController.workPackage, pendingFormChanges, notify);
result.then(function(wp) {
fieldController.onSuccess(wp);
var result = WorkPackageService.updateWorkPackage(EditableFieldsState.workPackage, pendingFormChanges, notify);
result.then(function() {
fieldController.onSuccess();
});
result.catch(function(e) {
fieldController.onFail(e);
@ -54,18 +54,27 @@ module.exports = function() {
this.discardEditing = function() {
$scope.fieldController.isEditing = false;
var form = $scope.fieldController.workPackage.form;
getPendingFormChanges()[$scope.fieldController.field] = $scope.fieldController.workPackage.form.embedded.payload.props[$scope.fieldController.field];
var form = EditableFieldsState.workPackage.form;
getPendingFormChanges()[$scope.fieldController.field] = EditableFieldsState.workPackage.form.embedded.payload.props[$scope.fieldController.field];
$scope.fieldController.updateWriteValue();
};
function getPendingFormChanges() {
var form = $scope.fieldController.workPackage.form;
var form = EditableFieldsState.workPackage.form;
form.pendingChanges = form.pendingChanges || angular.copy(form.embedded.payload.props);
return form.pendingChanges;
}
},
link: function(scope, element, attrs, fieldController) {
console.log('link', EditableFieldsState, WorkPackageFieldService, fieldController);
scope.fieldController = fieldController;
scope.templateUrl = '/templates/components/inplace_editor/editable/' +
WorkPackageFieldService.getInplaceEditStrategy(
EditableFieldsState.workPackage,
fieldController.field
) +
'.html';
console.log('ssss', scope.templateUrl);
}
};
}

@ -26,33 +26,52 @@
// See doc/COPYRIGHT.rdoc for more details.
//++
module.exports = function(WorkPackageFieldService, ApiHelper) {
module.exports = function(WorkPackageFieldService, ApiHelper, EditableFieldsState) {
function workPackageFieldDirectiveController() {
this.isEditable = WorkPackageFieldService.isEditable(this.workPackage, this.field);
this.isEmpty = WorkPackageFieldService.isEmpty(this.workPackage, this.field);
this.label = WorkPackageFieldService.getLabel(this.workPackage, this.field);
this.isEditable = function() {
return WorkPackageFieldService.isEditable(EditableFieldsState.workPackage, this.field)
};
this.isEmpty = function() {
return WorkPackageFieldService.isEmpty(EditableFieldsState.workPackage, this.field);
};
this.getLabel = function() {
return WorkPackageFieldService.getLabel(EditableFieldsState.workPackage, this.field);
};
this.getReadValue = function() {
return WorkPackageFieldService.format(EditableFieldsState.workPackage, this.field);
};
this.updateWriteValue = function() {
this.writeValue = WorkPackageFieldService.getValue(EditableFieldsState.workPackage, this.field);
};
if (this.isEditable) {
this.type = 'text';
this.isBusy = false;
this.isEditing = false;
this.readValue = WorkPackageFieldService.getValue(this.workPackage, this.field);
this.writeValue = WorkPackageFieldService.getValue(this.workPackage, this.field);
this.updateWriteValue();
this.placeholder = WorkPackageFieldService.defaultPlaceholder;
this.editTitle = I18n.t('js.inplace.button_edit', { attribute: this.field });
this.onSuccess = function(wp) {
console.log(this.workPackage, wp, this.workPackage === wp);
this.readValue = WorkPackageFieldService.getValue(this.workPackage, this.field);
this.onSuccess = function() {
this.isEditing = false;
this.updateWriteValue();
};
this.onFail = function(e) {
this.error = ApiHelper.getErrorMessage(e);
}
} else {
this.value = WorkPackageFieldService.format(this.workPackage, this.field);
this.value = WorkPackageFieldService.format(EditableFieldsState.workPackage, this.field);
}
this.contextEval = function(childControllerActivation) {
childControllerActivation.call(this);
};
}
return {
@ -62,7 +81,6 @@ module.exports = function(WorkPackageFieldService, ApiHelper) {
bindToController: true,
templateUrl: '/templates/work_packages/field.html',
scope: {
workPackage: '=',
field: '='
},
controller: workPackageFieldDirectiveController

@ -0,0 +1,33 @@
//-- 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.
//++
module.exports = function() {
return {
workPackage: null
};
}

@ -63,4 +63,7 @@ angular.module('openproject.workPackages.services')
'WORK_PACKAGE_REGULAR_EDITABLE_FIELD',
'WorkPackagesHelper',
require('./work-package-field-service')
]);
])
.service('EditableFieldsState',
require('./work-package-field-service')
);

@ -70,7 +70,7 @@ module.exports = function(I18n, WORK_PACKAGE_REGULAR_EDITABLE_FIELD, WorkPackage
return value === null || value === '';
}
function getInplaceType(workPackage, field) {
function getInplaceEditStrategy(workPackage, field) {
var fieldType = null,
inplaceType = 'text';
if (field === 'date') {
@ -139,6 +139,7 @@ module.exports = function(I18n, WORK_PACKAGE_REGULAR_EDITABLE_FIELD, WorkPackage
updatedAt: 'datetime'
};
// TODO: switch to duration
if (field === 'estimatedTime' || field === 'spentTime') {
if (value === null) {
return null;
@ -157,7 +158,7 @@ module.exports = function(I18n, WORK_PACKAGE_REGULAR_EDITABLE_FIELD, WorkPackage
getValue: getValue,
getLabel: getLabel,
format: format,
getInplaceType: getInplaceType,
getInplaceEditStrategy: getInplaceEditStrategy,
getInplaceDisplayStrategy: getInplaceDisplayStrategy,
defaultPlaceholder: '-'
};

Loading…
Cancel
Save