Merge pull request #2291 from normanjaeckel/MotionAmendment

Reimplemented amendments for motions.
This commit is contained in:
Norman Jäckel 2016-08-31 12:39:48 +02:00 committed by GitHub
commit 08c6fa11b4
6 changed files with 73 additions and 15 deletions

View File

@ -103,26 +103,32 @@ def get_config_variables():
subgroup='General') subgroup='General')
# Amendments # Amendments
# Amendments currently not implemented. (TODO: Implement it like in OpenSlides 1.7.)
yield ConfigVariable( yield ConfigVariable(
name='motions_amendments_enabled', name='motions_amendments_enabled',
default_value=False, default_value=False,
input_type='boolean', input_type='boolean',
label='Activate amendments', label='Activate amendments',
hidden=True,
weight=335, weight=335,
group='Motions', group='Motions',
subgroup='Amendments') subgroup='Amendments')
yield ConfigVariable( yield ConfigVariable(
name='motions_amendments_prefix', name='motions_amendments_prefix',
default_value='A', default_value='-',
label='Prefix for the identifier for amendments', label='Prefix for the identifier for amendments',
hidden=True,
weight=340, weight=340,
group='Motions', group='Motions',
subgroup='Amendments') 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 # Supporters
yield ConfigVariable( yield ConfigVariable(

View File

@ -243,7 +243,7 @@ class MotionSerializer(ModelSerializer):
'polls', 'polls',
'agenda_item_id', 'agenda_item_id',
'log_messages',) '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 @transaction.atomic
def create(self, validated_data): def create(self, validated_data):
@ -257,6 +257,7 @@ class MotionSerializer(ModelSerializer):
motion.identifier = validated_data.get('identifier') motion.identifier = validated_data.get('identifier')
motion.category = validated_data.get('category') motion.category = validated_data.get('category')
motion.origin = validated_data.get('origin', '') motion.origin = validated_data.get('origin', '')
motion.parent = validated_data.get('parent')
motion.reset_state(validated_data.get('workflow_id')) motion.reset_state(validated_data.get('workflow_id'))
motion.save() motion.save()
if validated_data.get('submitters'): if validated_data.get('submitters'):

View File

@ -272,6 +272,9 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
motion: function(Motion, $stateParams) { motion: function(Motion, $stateParams) {
return Motion.find($stateParams.id); return Motion.find($stateParams.id);
}, },
motions: function(Motion) {
return Motion.findAll();
},
categories: function(Category) { categories: function(Category) {
return Category.findAll(); return Category.findAll();
}, },
@ -819,7 +822,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
'gettextCatalog', 'gettextCatalog',
'diffService', 'diffService',
function($scope, $http, $timeout, ngDialog, MotionForm, Motion, Category, Mediafile, Tag, User, Workflow, Editor, 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) { PdfMakeDocumentProvider, gettextCatalog, diffService) {
Motion.bindOne(motion.id, $scope, 'motion'); Motion.bindOne(motion.id, $scope, 'motion');
Category.bindAll({}, $scope, 'categories'); Category.bindAll({}, $scope, 'categories');
@ -832,6 +835,10 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
$scope.isCollapsed = true; $scope.isCollapsed = true;
$scope.lineNumberMode = Config.get('motions_default_line_numbering').value; $scope.lineNumberMode = Config.get('motions_default_line_numbering').value;
$scope.lineBrokenText = motion.getTextWithLineBreaks($scope.version); $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(){ $scope.makePDF = function(){
var content = motion.getText($scope.version) + motion.getReason($scope.version), 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 () { $scope.unsupport = function () {
$http.delete('/rest/motions/motion/' + motion.id + '/support/'); $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 // update state
$scope.updateState = function (state_id) { $scope.updateState = function (state_id) {
$http.put('/rest/motions/motion/' + motion.id + '/set_state/', {'state': 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', [ .controller('MotionCreateCtrl', [
'$scope', '$scope',
'$state',
'gettext', 'gettext',
'Motion', 'Motion',
'MotionForm', 'MotionForm',
@ -1049,7 +1066,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
'Workflow', 'Workflow',
'Agenda', 'Agenda',
'AgendaUpdate', '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'); Category.bindAll({}, $scope, 'categories');
Mediafile.bindAll({}, $scope, 'mediafiles'); Mediafile.bindAll({}, $scope, 'mediafiles');
Tag.bindAll({}, $scope, 'tags'); Tag.bindAll({}, $scope, 'tags');
@ -1057,13 +1074,27 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
Workflow.bindAll({}, $scope, 'workflows'); Workflow.bindAll({}, $scope, 'workflows');
$scope.model = {}; $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 // ... set preamble config value as text
$scope.model.text = Config.get('motions_preamble').value; $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 // ... preselect default workflow
$scope.model.workflow_id = Config.get('motions_workflow').value; $scope.model.workflow_id = Config.get('motions_workflow').value;
// get all form fields // get all form fields
$scope.formFields = MotionForm.getFormFields(); $scope.formFields = MotionForm.getFormFields();
// save motion // save motion
$scope.save = function (motion) { $scope.save = function (motion) {
Motion.create(motion).then( 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)}, var changes = [{key: 'type', value: (motion.showAsAgendaItem ? 1 : 2)},
{key: 'parent_id', value: motion.agenda_parent_item_id}]; {key: 'parent_id', value: motion.agenda_parent_item_id}];
AgendaUpdate.saveChanges(success.agenda_item_id, changes); AgendaUpdate.saveChanges(success.agenda_item_id, changes);
if (isAmendment) {
$state.go('motions.motion.detail', {id: success.id});
}
$scope.closeThisDialog(); $scope.closeThisDialog();
} }
); );
@ -1346,7 +1380,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
var importedUsers = []; var importedUsers = [];
var importedCategories = []; var importedCategories = [];
// collect users and categories // collect users and categories
angular.forEach($scope.motions, function (motion){ angular.forEach($scope.motions, function (motion) {
if (!motion.importerror) { if (!motion.importerror) {
// collect user if not exists // collect user if not exists
if (!motion.submitters_id && motion.submitter) { if (!motion.submitters_id && motion.submitter) {
@ -1630,8 +1664,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
gettext('Amendments'); gettext('Amendments');
gettext('Activate amendments'); gettext('Activate amendments');
gettext('Prefix for the identifier for amendments'); gettext('Prefix for the identifier for amendments');
/// Prefix for the identifier for amendments gettext('Apply title and text for new amendments');
gettext('A');
// subgroup Suppoerters // subgroup Suppoerters
gettext('Supporters'); gettext('Supporters');

View File

@ -31,6 +31,10 @@
<h1>{{ motion.agenda_item.getTitle() || motion.getTitle() }}</h1> <h1>{{ motion.agenda_item.getTitle() || motion.getTitle() }}</h1>
<h2> <h2>
<translate>Motion</translate> {{ motion.identifier }} <translate>Motion</translate> {{ motion.identifier }}
<span ng-if="parent">
(<translate>Amendment of motion</translate>
<a ui-sref="motions.motion.detail({id: parent.id})">{{ parent.identifier || parent.getTitle() }}</a>)
</span>
<span ng-if="motion.versions.length > 1" >| Version {{ motion.getVersion(version).version_number }}</span> <span ng-if="motion.versions.length > 1" >| Version {{ motion.getVersion(version).version_number }}</span>
<span ng-if="motion.active_version != version" class="label label-warning"> <span ng-if="motion.active_version != version" class="label label-warning">
<i class="fa fa-exclamation-triangle"></i> <i class="fa fa-exclamation-triangle"></i>
@ -56,7 +60,7 @@
<!-- submitters --> <!-- submitters -->
<h3 translate>Submitters</h3> <h3 translate>Submitters</h3>
<div ng-repeat="submitter in motion.submitters"> <div ng-repeat="submitter in motion.submitters">
{{ submitter.get_full_name() }}<br> {{ submitter.get_full_name() }}
</div> </div>
<!-- supporters --> <!-- supporters -->
@ -77,6 +81,19 @@
<translate>Unsupport motion</translate> <translate>Unsupport motion</translate>
</button> </button>
</div> </div>
<!-- Amendments -->
<div ng-if="config('motions_amendments_enabled')">
<h3 translate>Amendments</h3>
<div ng-repeat="amendment in amendments">
<a ui-sref="motions.motion.detail({id: amendment.id})">
<translate>Motion</translate> {{ amendment.identifier || amendment.getTitle() }}
</a>
</div>
<button os-perms="motions.can_create" ng-click="newAmendment()" class="btn btn-default btn-sm">
<i class="fa fa-plus"></i>
<translate>New amendment</translate>
</button>
</div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<!-- Category --> <!-- Category -->

View File

@ -1,5 +1,6 @@
<h1 ng-if="model.id" translate>Edit motion</h1> <h1 ng-if="model.id" translate>Edit motion</h1>
<h1 ng-if="!model.id" translate>New motion</h1> <h1 ng-if="!model.id && !parent" translate>New motion</h1>
<h1 ng-if="parent"><translate>New amendment of motion</translate> {{ parent.identifier || parent.getTitle() }}</h1>
<uib-alert ng-show="alert.show" type="{{ alert.type }}" ng-click="alert={}" close="alert={}"> <uib-alert ng-show="alert.show" type="{{ alert.type }}" ng-click="alert={}" close="alert={}">
{{ alert.msg }} {{ alert.msg }}

View File

@ -171,7 +171,7 @@ class ModelTest(TestCase):
motion.set_identifier() 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): def test_set_identifier_second_amendment(self):
""" """
@ -186,7 +186,7 @@ class ModelTest(TestCase):
motion.set_identifier() motion.set_identifier()
self.assertEqual(motion.identifier, 'Parent identifier A 2') self.assertEqual(motion.identifier, 'Parent identifier - 2')
class ConfigTest(TestCase): class ConfigTest(TestCase):