diff --git a/openslides/motions/config_variables.py b/openslides/motions/config_variables.py index ac16c1e08..469811f18 100644 --- a/openslides/motions/config_variables.py +++ b/openslides/motions/config_variables.py @@ -103,26 +103,32 @@ def get_config_variables(): subgroup='General') # Amendments - # Amendments currently not implemented. (TODO: Implement it like in OpenSlides 1.7.) yield ConfigVariable( name='motions_amendments_enabled', default_value=False, input_type='boolean', label='Activate amendments', - hidden=True, weight=335, group='Motions', subgroup='Amendments') yield ConfigVariable( name='motions_amendments_prefix', - default_value='A', + default_value='-', label='Prefix for the identifier for amendments', - hidden=True, weight=340, group='Motions', subgroup='Amendments') + yield ConfigVariable( + name='motions_amendments_apply_title_text', + default_value=False, + input_type='boolean', + label='Apply title and text for new amendments', + weight=342, + group='Motions', + subgroup='Amendments') + # Supporters yield ConfigVariable( diff --git a/openslides/motions/serializers.py b/openslides/motions/serializers.py index c1f4a291c..714d56f89 100644 --- a/openslides/motions/serializers.py +++ b/openslides/motions/serializers.py @@ -243,7 +243,7 @@ class MotionSerializer(ModelSerializer): 'polls', 'agenda_item_id', 'log_messages',) - read_only_fields = ('parent', 'state') # Some other fields are also read_only. See definitions above. + read_only_fields = ('state',) # Some other fields are also read_only. See definitions above. @transaction.atomic def create(self, validated_data): @@ -257,6 +257,7 @@ class MotionSerializer(ModelSerializer): motion.identifier = validated_data.get('identifier') motion.category = validated_data.get('category') motion.origin = validated_data.get('origin', '') + motion.parent = validated_data.get('parent') motion.reset_state(validated_data.get('workflow_id')) motion.save() if validated_data.get('submitters'): diff --git a/openslides/motions/static/js/motions/site.js b/openslides/motions/static/js/motions/site.js index 2d81b467a..1e92964f4 100644 --- a/openslides/motions/static/js/motions/site.js +++ b/openslides/motions/static/js/motions/site.js @@ -272,6 +272,9 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid motion: function(Motion, $stateParams) { return Motion.find($stateParams.id); }, + motions: function(Motion) { + return Motion.findAll(); + }, categories: function(Category) { return Category.findAll(); }, @@ -819,7 +822,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid 'gettextCatalog', 'diffService', function($scope, $http, $timeout, ngDialog, MotionForm, Motion, Category, Mediafile, Tag, User, Workflow, Editor, - Config,motion, SingleMotionContentProvider, MotionContentProvider, PdfMakeConverter, + Config, motion, SingleMotionContentProvider, MotionContentProvider, PdfMakeConverter, PdfMakeDocumentProvider, gettextCatalog, diffService) { Motion.bindOne(motion.id, $scope, 'motion'); Category.bindAll({}, $scope, 'categories'); @@ -832,6 +835,10 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid $scope.isCollapsed = true; $scope.lineNumberMode = Config.get('motions_default_line_numbering').value; $scope.lineBrokenText = motion.getTextWithLineBreaks($scope.version); + if (motion.parent_id) { + Motion.bindOne(motion.parent_id, $scope, 'parent'); + } + $scope.amendments = Motion.filter({parent_id: motion.id}); $scope.makePDF = function(){ var content = motion.getText($scope.version) + motion.getReason($scope.version), @@ -875,6 +882,15 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid $scope.unsupport = function () { $http.delete('/rest/motions/motion/' + motion.id + '/support/'); }; + // open dialog for new amendment + $scope.newAmendment = function () { + var dialog = MotionForm.getDialog(); + if (dialog.scope === undefined) { + dialog.scope = {}; + } + dialog.scope = $scope; + ngDialog.open(dialog); + }; // update state $scope.updateState = function (state_id) { $http.put('/rest/motions/motion/' + motion.id + '/set_state/', {'state': state_id}); @@ -1038,6 +1054,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid .controller('MotionCreateCtrl', [ '$scope', + '$state', 'gettext', 'Motion', 'MotionForm', @@ -1049,7 +1066,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid 'Workflow', 'Agenda', 'AgendaUpdate', - function($scope, gettext, Motion, MotionForm, Category, Config, Mediafile, Tag, User, Workflow, Agenda, AgendaUpdate) { + function($scope, $state, gettext, Motion, MotionForm, Category, Config, Mediafile, Tag, User, Workflow, Agenda, AgendaUpdate) { Category.bindAll({}, $scope, 'categories'); Mediafile.bindAll({}, $scope, 'mediafiles'); Tag.bindAll({}, $scope, 'tags'); @@ -1057,13 +1074,27 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid Workflow.bindAll({}, $scope, 'workflows'); $scope.model = {}; - // set default values for create form + + // Check whether this is a new amendment. + var isAmendment = $scope.$parent.motion && $scope.$parent.motion.id; + + // Set default values for create form // ... set preamble config value as text $scope.model.text = Config.get('motions_preamble').value; + // ... for amendments add parent_id + if (isAmendment) { + if (Config.get('motions_amendments_apply_title_text').value) { + $scope.model.title = $scope.$parent.motion.getTitle(); + $scope.model.text = $scope.$parent.motion.getText(); + } + $scope.model.parent_id = $scope.$parent.motion.id; + Motion.bindOne($scope.model.parent_id, $scope, 'parent'); + } // ... preselect default workflow $scope.model.workflow_id = Config.get('motions_workflow').value; // get all form fields $scope.formFields = MotionForm.getFormFields(); + // save motion $scope.save = function (motion) { Motion.create(motion).then( @@ -1073,6 +1104,9 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid var changes = [{key: 'type', value: (motion.showAsAgendaItem ? 1 : 2)}, {key: 'parent_id', value: motion.agenda_parent_item_id}]; AgendaUpdate.saveChanges(success.agenda_item_id, changes); + if (isAmendment) { + $state.go('motions.motion.detail', {id: success.id}); + } $scope.closeThisDialog(); } ); @@ -1346,7 +1380,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid var importedUsers = []; var importedCategories = []; // collect users and categories - angular.forEach($scope.motions, function (motion){ + angular.forEach($scope.motions, function (motion) { if (!motion.importerror) { // collect user if not exists if (!motion.submitters_id && motion.submitter) { @@ -1630,8 +1664,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid gettext('Amendments'); gettext('Activate amendments'); gettext('Prefix for the identifier for amendments'); - /// Prefix for the identifier for amendments - gettext('A'); + gettext('Apply title and text for new amendments'); // subgroup Suppoerters gettext('Supporters'); diff --git a/openslides/motions/static/templates/motions/motion-detail.html b/openslides/motions/static/templates/motions/motion-detail.html index f76fbb933..6a770b05c 100644 --- a/openslides/motions/static/templates/motions/motion-detail.html +++ b/openslides/motions/static/templates/motions/motion-detail.html @@ -31,6 +31,10 @@

{{ motion.agenda_item.getTitle() || motion.getTitle() }}

Motion {{ motion.identifier }} + + (Amendment of motion + {{ parent.identifier || parent.getTitle() }}) + | Version {{ motion.getVersion(version).version_number }} @@ -56,7 +60,7 @@

Submitters

- {{ submitter.get_full_name() }}
+ {{ submitter.get_full_name() }}
@@ -77,6 +81,19 @@ Unsupport motion + +
+

Amendments

+
+ + Motion {{ amendment.identifier || amendment.getTitle() }} + +
+ +
diff --git a/openslides/motions/static/templates/motions/motion-form.html b/openslides/motions/static/templates/motions/motion-form.html index 5908b9dc7..eac2c5d64 100644 --- a/openslides/motions/static/templates/motions/motion-form.html +++ b/openslides/motions/static/templates/motions/motion-form.html @@ -1,5 +1,6 @@

Edit motion

-

New motion

+

New motion

+

New amendment of motion {{ parent.identifier || parent.getTitle() }}

{{ alert.msg }} diff --git a/tests/old/motions/test_models.py b/tests/old/motions/test_models.py index bc8c9b3e7..4a06ead1e 100644 --- a/tests/old/motions/test_models.py +++ b/tests/old/motions/test_models.py @@ -171,7 +171,7 @@ class ModelTest(TestCase): motion.set_identifier() - self.assertEqual(motion.identifier, 'Parent identifier A 1') + self.assertEqual(motion.identifier, 'Parent identifier - 1') def test_set_identifier_second_amendment(self): """ @@ -186,7 +186,7 @@ class ModelTest(TestCase): motion.set_identifier() - self.assertEqual(motion.identifier, 'Parent identifier A 2') + self.assertEqual(motion.identifier, 'Parent identifier - 2') class ConfigTest(TestCase):