diff --git a/openslides/agenda/static/js/agenda/base.js b/openslides/agenda/static/js/agenda/base.js index 0e1136a54..c7302f9c4 100644 --- a/openslides/agenda/static/js/agenda/base.js +++ b/openslides/agenda/static/js/agenda/base.js @@ -27,11 +27,13 @@ angular.module('OpenSlidesApp.agenda', ['OpenSlidesApp.users']) 'Speaker', 'jsDataModel', 'Projector', + 'ProjectHelper', 'gettextCatalog', 'gettext', 'CamelCase', 'EditForm', - function($http, DS, Speaker, jsDataModel, Projector, gettextCatalog, gettext, CamelCase, EditForm) { + function($http, DS, Speaker, jsDataModel, Projector, ProjectHelper, gettextCatalog, + gettext, CamelCase, EditForm) { var name = 'agenda/item'; return DS.defineResource({ name: name, @@ -143,7 +145,7 @@ angular.module('OpenSlidesApp.agenda', ['OpenSlidesApp.users']) }, }; } - return $http.post('/rest/core/projector/project/', requestData); + ProjectHelper.project(requestData); } else { // Project the content object var contentObject = DS.get(this.content_object.collection, this.content_object.id); return contentObject.project(projectorId); @@ -198,7 +200,7 @@ angular.module('OpenSlidesApp.agenda', ['OpenSlidesApp.users']) }, }; } - return $http.post('/rest/core/projector/project/', requestData); + ProjectHelper.project(requestData); }, // check if list of speakers is projected isListOfSpeakersProjected: function () { diff --git a/openslides/assignments/static/js/assignments/base.js b/openslides/assignments/static/js/assignments/base.js index 203a7d9b2..fc9da67fc 100644 --- a/openslides/assignments/static/js/assignments/base.js +++ b/openslides/assignments/static/js/assignments/base.js @@ -318,11 +318,13 @@ angular.module('OpenSlidesApp.assignments', []) '$http', 'DS', 'Projector', + 'ProjectHelper', 'AssignmentRelatedUser', 'AssignmentPoll', 'jsDataModel', 'gettext', - function ($http, DS, Projector, AssignmentRelatedUser, AssignmentPoll, jsDataModel, gettext) { + function ($http, DS, Projector, ProjectHelper, AssignmentRelatedUser, AssignmentPoll, + jsDataModel, gettext) { var name = 'assignments/assignment'; return DS.defineResource({ name: name, @@ -369,7 +371,7 @@ angular.module('OpenSlidesApp.assignments', []) }, }; } - return $http.post('/rest/core/projector/project/', requestData); + ProjectHelper.project(requestData); }, // override isProjected function of jsDataModel factory isProjected: function (poll_id, anyPoll) { diff --git a/openslides/core/static/js/core/base.js b/openslides/core/static/js/core/base.js index 8bd7ffbad..06770b2de 100644 --- a/openslides/core/static/js/core/base.js +++ b/openslides/core/static/js/core/base.js @@ -728,7 +728,8 @@ angular.module('OpenSlidesApp.core', [ .factory('jsDataModel', [ '$http', 'Projector', - function($http, Projector) { + 'ProjectHelper', + function($http, Projector, ProjectHelper) { var BaseModel = function() {}; BaseModel.prototype.project = function(projectorId) { // if this object is already projected on projectorId, delete this element from this projector @@ -743,7 +744,7 @@ angular.module('OpenSlidesApp.core', [ element: {name: this.getResourceName(), id: this.id}, }; } - return $http.post('/rest/core/projector/project/', requestData); + ProjectHelper.project(requestData); }; BaseModel.prototype.isProjected = function() { // Returns the ids of all projectors if there is a projector element @@ -1260,6 +1261,92 @@ angular.module('OpenSlidesApp.core', [ } ]) +// This factory sends a request to /rest/core/projectors/project +// with the given data. Also it does the changes done by the server +// locally and may reverts them, if something went wrong. +.factory('ProjectHelper', [ + '$http', + 'Projector', + function ($http, Projector) { + var uuid4 = function () { + function s8() { + return Math.floor((1 + Math.random()) * 0x100000000) + .toString(16) + .substring(1); + } + return s8() + s8() + s8() + s8(); + }; + + return { + project: function (data) { + var projector; + // get all projectors that will be changed. + var projectorsChanged = _.filter(_.map(data.clear_ids, function (id) { + return Projector.get(id); + })); + if (data.prune && !_.includes(data.clear_ids, data.prune.id)) { + projector = Projector.get(data.prune.id); + if (projector) { + projectorsChanged.push(projector); + } + } + + // copy original projectors in case we have to reconstruct those + // _.cloneDeep and angular.clone does not work here; I'm not + // exactly sure why.. + var originalProjectors = _.map(projectorsChanged, function (projector) { + var elements = {}; + _.forEach(projector.elements, function (element, key) { + elements[key] = _.cloneDeep(element); + }); + return { + id: projector.id, + elements: elements, + scroll: projector.scroll, + scale: projector.scale, + name: projector.name, + blank: projector.blank, + width: projector.width, + height: projector.height, + projectiondefaults: _.cloneDeep(projector.projectiondefaults), + }; + }); + + // Clear every projector + _.forEach(projectorsChanged, function (projector) { + var elements = {}; + _.forEach(projector.elements, function (element, key) { + if (element.stable) { + elements[key] = element; + } + }); + projector.elements = elements; + }); + + // Add the prune element if given + if (data.prune) { + projector = _.find(projectorsChanged, function (projector) { + return projector.id === data.prune.id; + }); + if (projector) { + projector.scroll = 0; + projector.elements[uuid4()] = data.prune.element; + } + } + + Projector.inject(projectorsChanged); + + $http.post('/rest/core/projector/project/', data).then(null, + function (error) { + // revert the changed made earlier + Projector.inject(originalProjectors); + } + ); + }, + }; + } +]) + /* Model for all projection defaults */ .factory('ProjectionDefault', [ 'DS', diff --git a/openslides/core/views.py b/openslides/core/views.py index 2c81ff7c7..439d8707a 100644 --- a/openslides/core/views.py +++ b/openslides/core/views.py @@ -415,6 +415,10 @@ class ProjectorViewSet(ModelViewSet): } } """ + # The data has to be a dict. + if not isinstance(request.data, dict): + raise ValidationError({'detail': _('The data has to be a dict.')}) + # Get projector ids to clear clear_projector_ids = request.data.get('clear_ids', []) for id in clear_projector_ids: diff --git a/openslides/motions/static/js/motions/base.js b/openslides/motions/static/js/motions/base.js index 70167fb81..76ee35200 100644 --- a/openslides/motions/static/js/motions/base.js +++ b/openslides/motions/static/js/motions/base.js @@ -225,9 +225,11 @@ angular.module('OpenSlidesApp.motions', [ 'diffService', 'OpenSlidesSettings', 'Projector', + 'ProjectHelper', 'operator', - function(DS, $http, MotionPoll, MotionStateAndRecommendationParser, MotionChangeRecommendation, MotionComment, jsDataModel, gettext, gettextCatalog, - Config, lineNumberingService, diffService, OpenSlidesSettings, Projector, operator) { + function(DS, $http, MotionPoll, MotionStateAndRecommendationParser, MotionChangeRecommendation, + MotionComment, jsDataModel, gettext, gettextCatalog, Config, lineNumberingService, + diffService, OpenSlidesSettings, Projector, ProjectHelper, operator) { var name = 'motions/motion'; return DS.defineResource({ name: name, @@ -673,7 +675,7 @@ angular.module('OpenSlidesApp.motions', [ }, }; } - return $http.post('/rest/core/projector/project/', requestData); + ProjectHelper.project(requestData); }, isProjected: function (mode) { var self = this;