From b6a2530618ca5200a4b7d39fa482c95a230b2ea5 Mon Sep 17 00:00:00 2001 From: FinnStutzenstein Date: Sat, 11 Nov 2017 12:28:24 +0100 Subject: [PATCH] Reduce autoupdates by adding a follow_recommendation view (fixes #3488, fixes #3489) --- openslides/motions/models.py | 11 ++--- openslides/motions/static/js/motions/site.js | 5 ++- openslides/motions/views.py | 46 +++++++++++++++++--- 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/openslides/motions/models.py b/openslides/motions/models.py index bb5e53a3e..4df9f7522 100644 --- a/openslides/motions/models.py +++ b/openslides/motions/models.py @@ -553,15 +553,16 @@ class Motion(RESTModelMixin, models.Model): """ return user in self.supporters.all() - def create_poll(self): + def create_poll(self, skip_autoupdate=False): """ Create a new poll for this motion. Return the new poll object. """ if self.state.allow_create_poll: - poll = MotionPoll.objects.create(motion=self) - poll.set_options() + poll = MotionPoll(motion=self) + poll.save(skip_autoupdate=skip_autoupdate) + poll.set_options(skip_autoupdate=skip_autoupdate) return poll else: raise WorkflowError('You can not create a poll in state %s.' % self.state.name) @@ -1030,11 +1031,11 @@ class MotionPoll(RESTModelMixin, CollectDefaultVotesMixin, BasePoll): # type: i """ return 'MotionPoll for motion %s' % self.motion - def set_options(self): + def set_options(self, skip_autoupdate=False): """Create the option class for this poll.""" # TODO: maybe it is possible with .create() to call this without poll=self # or call this in save() - self.get_option_class()(poll=self).save() + self.get_option_class()(poll=self).save(skip_autoupdate=skip_autoupdate) def get_percent_base_choice(self): return config['motions_poll_100_percent_base'] diff --git a/openslides/motions/static/js/motions/site.js b/openslides/motions/static/js/motions/site.js index 9ea778af7..45ac37772 100644 --- a/openslides/motions/static/js/motions/site.js +++ b/openslides/motions/static/js/motions/site.js @@ -1518,8 +1518,9 @@ angular.module('OpenSlidesApp.motions.site', [ }; // follow recommendation $scope.followRecommendation = function () { - $scope.updateState($scope.motion.recommendation.id); - $scope.saveAdditionalStateField($scope.recommendationExtension); + $http.post('/rest/motions/motion/' + motion.id + '/follow_recommendation/', { + 'recommendationExtension': $scope.recommendationExtension + }); }; // update state $scope.updateState = function (state_id) { diff --git a/openslides/motions/views.py b/openslides/motions/views.py index 13b861a40..8ab4f390f 100644 --- a/openslides/motions/views.py +++ b/openslides/motions/views.py @@ -74,7 +74,8 @@ class MotionViewSet(ModelViewSet): has_perm(self.request.user, 'motions.can_create') and (not config['motions_stop_submitting'] or has_perm(self.request.user, 'motions.can_manage'))) - elif self.action in ('destroy', 'manage_version', 'set_state', 'set_recommendation', 'create_poll'): + elif self.action in ('destroy', 'manage_version', 'set_state', 'set_recommendation', + 'follow_recommendation', 'create_poll'): result = (has_perm(self.request.user, 'motions.can_see') and has_perm(self.request.user, 'motions.can_manage')) elif self.action == 'support': @@ -325,13 +326,15 @@ class MotionViewSet(ModelViewSet): motion.reset_state() # Save motion. - motion.save(update_fields=['state', 'identifier', 'identifier_number']) + motion.save(update_fields=['state', 'identifier', 'identifier_number'], skip_autoupdate=True) message = _('The state of the motion was set to %s.') % motion.state.name # Write the log message and initiate response. motion.write_log( message_list=[ugettext_noop('State set to'), ' ', motion.state.name], - person=request.user) + person=request.user, + skip_autoupdate=True) + inform_changed_data(motion) return Response({'detail': message}) @detail_route(methods=['put']) @@ -374,6 +377,37 @@ class MotionViewSet(ModelViewSet): person=request.user) return Response({'detail': message}) + @detail_route(methods=['post']) + def follow_recommendation(self, request, pk=None): + motion = self.get_object() + if motion.recommendation is None: + raise ValidationError({'detail': _('Cannot set an empty recommendation.')}) + + # Set state. + motion.set_state(motion.recommendation) + + # Set the special state comment. + extension = request.data.get('recommendationExtension') + if extension is not None: + # Find the special "state" comment field. + for id, field in config['motions_comments'].items(): + if 'forState' in field and field['forState'] is True: + motion.comments[id] = extension + break + + # Save and write log. + motion.save( + update_fields=['state', 'identifier', 'identifier_number', 'comments'], + skip_autoupdate=True) + motion.write_log( + message_list=[ugettext_noop('State set to'), ' ', motion.state.name], + person=request.user, + skip_autoupdate=True) + + # Now send all changes to the clients. + inform_changed_data(motion) + return Response({'detail': 'Recommendation followed successfully.'}) + @detail_route(methods=['post']) def create_poll(self, request, pk=None): """ @@ -384,10 +418,12 @@ class MotionViewSet(ModelViewSet): raise ValidationError({'detail': 'You can not create a poll in this motion state.'}) try: with transaction.atomic(): - motion.create_poll() + motion.create_poll(skip_autoupdate=True) except WorkflowError as e: raise ValidationError({'detail': e}) - motion.write_log([ugettext_noop('Vote created')], request.user) + motion.write_log([ugettext_noop('Vote created')], request.user, skip_autoupdate=True) + + inform_changed_data(motion) return Response({'detail': _('Vote created successfully.')})