Merge pull request #2306 from opf/fix/17633_split_screen_does_not_work_without_permission

17633 split screen does not work without permission
pull/2314/head
ulferts 10 years ago
commit 4a5c5cc87b
  1. 3
      frontend/app/services/index.js
  2. 47
      frontend/app/services/work-package-service.js
  3. 16
      frontend/app/ui_components/inplace-editor-directive.js
  4. 18
      frontend/app/ui_components/inplace-editor-dispatcher.js
  5. 22
      frontend/app/work_packages/controllers/work-package-details-controller.js
  6. 5
      frontend/public/templates/components/inplace_editor.html
  7. 9
      frontend/tests/integration/work-package-details-spec.js
  8. 56
      frontend/tests/unit/tests/work_packages/directives/inplace-editor-directive-test.js

@ -90,6 +90,7 @@ angular.module('openproject.services')
'DEFAULT_PAGINATION_OPTIONS',
'$rootScope',
'$window',
'WorkPackagesTableService',
'$q',
'AuthorisationService',
require('./work-package-service')
]);

@ -26,7 +26,16 @@
// See doc/COPYRIGHT.rdoc for more details.
//++
module.exports = function($http, PathHelper, WorkPackagesHelper, HALAPIResource, DEFAULT_FILTER_PARAMS, DEFAULT_PAGINATION_OPTIONS, $rootScope, $window, WorkPackagesTableService) {
module.exports = function($http,
PathHelper,
WorkPackagesHelper,
HALAPIResource,
DEFAULT_FILTER_PARAMS,
DEFAULT_PAGINATION_OPTIONS,
$rootScope,
$window,
$q,
AuthorisationService) {
var workPackage;
var WorkPackageService = {
@ -126,17 +135,31 @@ module.exports = function($http, PathHelper, WorkPackagesHelper, HALAPIResource,
},
loadWorkPackageForm: function(workPackage) {
var options = { ajax: {
method: 'POST',
headers: {
Accept: 'application/hal+json'
},
contentType: 'application/json; charset=utf-8'
}, force: true};
return workPackage.links.update.fetch(options).then(function(form) {
workPackage.form = form;
return form;
});
if (this.authorizedFor(workPackage, 'update')) {
var options = { ajax: {
method: 'POST',
headers: {
Accept: 'application/hal+json'
},
contentType: 'application/json; charset=utf-8'
}, force: true};
return workPackage.links.update.fetch(options).then(function(form) {
workPackage.form = form;
return form;
});
}
return $q.when();
},
authorizedFor: function(workPackage, action) {
var modelName = 'work_package' + workPackage.id;
AuthorisationService.initModelAuth(modelName, workPackage.links);
return AuthorisationService.can(modelName, action);
},
updateWorkPackage: function(workPackage, data, notify) {

@ -96,8 +96,14 @@ module.exports = function($timeout, InplaceEditorDispatcher) {
activate();
function activate() {
InplaceEditorDispatcher.dispatchHook($scope, 'activate');
setWriteValue();
// Editor activation and write value retrieval depend on the work package
// form to be available. But the form is only available if the work
// package is editable.
if ($scope.isEditable) {
InplaceEditorDispatcher.dispatchHook($scope, 'activate');
setWriteValue();
}
setReadValue();
}
@ -161,7 +167,7 @@ module.exports = function($timeout, InplaceEditorDispatcher) {
function setReadValue() {
InplaceEditorDispatcher.dispatchHook($scope, 'setReadValue');
if ((!$scope.readValue || $scope.readValue.length === 0) && $scope.placeholder) {
if ($scope.isEditable && isReadValueEmpty() && $scope.placeholder) {
$scope.readValue = $scope.placeholder;
$scope.placeholderSet = true;
} else {
@ -169,5 +175,9 @@ module.exports = function($timeout, InplaceEditorDispatcher) {
}
}
function isReadValueEmpty() {
return (!$scope.readValue || $scope.readValue.length === 0);
}
}
};

@ -45,13 +45,21 @@ module.exports = function($sce, AutoCompleteHelper, TextileService) {
}
}
function getAttributeValue($scope) {
function getReadAttributeValue($scope) {
return getAttributeValue($scope, $scope.entity);
}
function getWriteAttributeValue($scope) {
return getAttributeValue($scope, $scope.entity.form.embedded.payload);
}
function getAttributeValue($scope, entity) {
if ($scope.embedded) {
var path = $scope.attribute.split('.');
return $scope.entity.embedded[path[0]].props[path[1]];
return entity.embedded[path[0]].props[path[1]];
} else {
return $scope.entity.props[getAttribute($scope)];
return entity.props[getAttribute($scope)];
}
}
@ -71,11 +79,11 @@ module.exports = function($sce, AutoCompleteHelper, TextileService) {
},
setWriteValue: function($scope) {
$scope.dataObject = {
value: getAttributeValue($scope)
value: getWriteAttributeValue($scope)
};
},
setReadValue: function($scope) {
$scope.readValue = getAttributeValue($scope);
$scope.readValue = getReadAttributeValue($scope);
}
},

@ -26,12 +26,22 @@
// See doc/COPYRIGHT.rdoc for more details.
//++
module.exports = function(
$scope, $state, latestTab, workPackage, I18n,
RELATION_TYPES, RELATION_IDENTIFIERS, $q,
WorkPackagesHelper, PathHelper, UsersHelper,
ConfigurationService, WorkPackageService,
CommonRelationsHandler, ChildrenRelationsHandler, ParentRelationsHandler
module.exports = function($scope,
$state,
latestTab,
workPackage,
I18n,
RELATION_TYPES,
RELATION_IDENTIFIERS,
$q,
WorkPackagesHelper,
PathHelper,
UsersHelper,
ConfigurationService,
WorkPackageService,
CommonRelationsHandler,
ChildrenRelationsHandler,
ParentRelationsHandler
) {
$scope.$on('$stateChangeSuccess', function(event, toState){
latestTab.registerState(toState.name);

@ -1,4 +1,7 @@
<span ng-if="!isEditable">{{ entity.props[attribute] }}</span>
<span ng-if="!isEditable" ng-switch="type">
<span ng-switch-when="wiki_textarea" ng-bind-html="readValue"></span>
<span ng-switch-default ng-bind="readValue"></span>
</span>
<div ng-if="isEditable" class="inplace-editor type-{{type}}" ng-class="{busy: isBusy, preview: isPreview}">
<div class="ined-read-value" ng-class="{ default: placeholderSet }" ng-hide="isEditing" ng-switch="type">
<span class="read-value-wrapper" ng-switch-when="wiki_textarea" ng-bind-html="readValue"></span>

@ -51,7 +51,7 @@ describe('OpenProject', function() {
describe('editable', function() {
context('subject', function() {
context('work package with updateImmediately link', function() {
beforeEach(function() {
before(function() {
var page = new WorkPackageDetailsPane(819, 'overview');
page.get();
});
@ -60,16 +60,19 @@ describe('OpenProject', function() {
});
});
context('work package without updateImmediately link', function() {
beforeEach(function() {
before(function() {
var page = new WorkPackageDetailsPane(820, 'overview');
page.get();
});
it('should show work packages details pane', function() {
expect($('.work-packages--details').isPresent()).to.eventually.be.true;
});
it('should not render an editable subject', function() {
expect($('h2 .inplace-editor').isPresent()).to.eventually.be.false;
});
});
context('work package with a wrong version', function() {
beforeEach(function() {
before(function() {
var page = new WorkPackageDetailsPane(821, 'overview');
page.get();
$('h2 .inplace-editor .ined-read-value').then(function(e) {

@ -79,7 +79,42 @@ describe('inplaceEditor Directive', function() {
};
}));
describe('self', function() {
describe('Work package is not editable', function() {
beforeEach(function() {
scope.workPackage = {
props: {
subject: 'Some subject',
lockVersion: '1'
},
links: {
}
};
compile();
element.appendTo(document.body);
});
afterEach(function() {
element.remove();
});
it('should not be editable', function() {
expect(scope.isEditable).to.be.falsy;
});
describe('placeholder', function() {
it('should not render the default text', function() {
var text = element.find('.ined-read-value .read-value-wrapper').text();
expect(text).be.empty;
});
it('should set default text switch', function() {
expect(elementScope.placeholderSet).to.be.false;
});
});
});
describe('Work package is editable', function() {
beforeEach(function() {
scope.workPackage = {
props: {
@ -125,7 +160,15 @@ describe('inplaceEditor Directive', function() {
fetch: function() { }
}
},
form: form
form: {
embedded: {
payload: {
props: {
rawDescription: '1\n2\n3'
}
}
}
}
};
html =
'<h2 ' +
@ -389,6 +432,15 @@ describe('inplaceEditor Directive', function() {
updateImmediately: {
fetch: function() {}
}
},
form: {
embedded: {
payload: {
props: {
rawDescription: '1\n2\n3'
}
}
}
}
};

Loading…
Cancel
Save