Fixed motion states, handled workflow field.
This commit is contained in:
parent
5b37a21c87
commit
c379544e97
@ -79,7 +79,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
|
||||
|
||||
.controller('AssignmentDetailCtrl', function($scope, Assignment, assignment) {
|
||||
Assignment.bindOne(assignment.id, $scope, 'assignment');
|
||||
Assignment.loadRelations(assignment);
|
||||
Assignment.loadRelations(assignment, 'agenda_item');
|
||||
})
|
||||
|
||||
.controller('AssignmentCreateCtrl', function($scope, $state, Assignment) {
|
||||
|
@ -111,7 +111,7 @@ angular.module('OpenSlidesApp.core', [
|
||||
// Load the global data on startup
|
||||
.run([
|
||||
'loadGlobalData',
|
||||
function(loadGlobalData, operator) {
|
||||
function(loadGlobalData) {
|
||||
loadGlobalData();
|
||||
}
|
||||
])
|
||||
|
@ -646,7 +646,7 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
|
||||
.controller('CustomslideDetailCtrl', function($scope, Customslide, customslide) {
|
||||
Customslide.bindOne(customslide.id, $scope, 'customslide');
|
||||
Customslide.loadRelations(customslide);
|
||||
Customslide.loadRelations(customslide, 'agenda_item');
|
||||
})
|
||||
|
||||
.controller('CustomslideCreateCtrl', function($scope, $state, Customslide) {
|
||||
|
@ -409,6 +409,7 @@ class Motion(RESTModelMixin, models.Model):
|
||||
"""
|
||||
Returns the id of the workflow of the motion.
|
||||
"""
|
||||
# TODO: Rename to workflow_id
|
||||
return self.state.workflow.pk
|
||||
|
||||
def set_state(self, state):
|
||||
@ -442,7 +443,7 @@ class Motion(RESTModelMixin, models.Model):
|
||||
new_state = self.state.workflow.first_state
|
||||
else:
|
||||
new_state = (Workflow.objects.get(pk=config['motions_workflow']).first_state or
|
||||
Workflow.objects.get(pk=config['motions_workflow']).state_set.all()[0])
|
||||
Workflow.objects.get(pk=config['motions_workflow']).states.all()[0])
|
||||
self.set_state(new_state)
|
||||
|
||||
def get_agenda_title(self):
|
||||
@ -729,7 +730,7 @@ class State(RESTModelMixin, models.Model):
|
||||
action_word = models.CharField(max_length=255)
|
||||
"""An alternative string to be used for a button to switch to this state."""
|
||||
|
||||
workflow = models.ForeignKey('Workflow')
|
||||
workflow = models.ForeignKey('Workflow', related_name='states')
|
||||
"""A many-to-one relation to a workflow."""
|
||||
|
||||
next_states = models.ManyToManyField('self', symmetrical=False)
|
||||
|
@ -1,7 +1,6 @@
|
||||
from django.db import transaction
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from openslides.core.config import config
|
||||
from openslides.utils.rest_api import (
|
||||
CharField,
|
||||
DictField,
|
||||
@ -58,19 +57,20 @@ class StateSerializer(ModelSerializer):
|
||||
'versioning',
|
||||
'leave_old_version_active',
|
||||
'dont_set_identifier',
|
||||
'next_states',)
|
||||
'next_states',
|
||||
'workflow')
|
||||
|
||||
|
||||
class WorkflowSerializer(ModelSerializer):
|
||||
"""
|
||||
Serializer for motion.models.Workflow objects.
|
||||
"""
|
||||
state_set = StateSerializer(many=True, read_only=True)
|
||||
states = StateSerializer(many=True, read_only=True)
|
||||
first_state = PrimaryKeyRelatedField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Workflow
|
||||
fields = ('id', 'name', 'state_set', 'first_state',)
|
||||
fields = ('id', 'name', 'states', 'first_state',)
|
||||
|
||||
|
||||
class MotionLogSerializer(ModelSerializer):
|
||||
@ -180,11 +180,14 @@ class MotionSerializer(ModelSerializer):
|
||||
log_messages = MotionLogSerializer(many=True, read_only=True)
|
||||
polls = MotionPollSerializer(many=True, read_only=True)
|
||||
reason = CharField(allow_blank=True, required=False, write_only=True)
|
||||
state = StateSerializer(read_only=True)
|
||||
text = CharField(write_only=True)
|
||||
title = CharField(max_length=255, write_only=True)
|
||||
versions = MotionVersionSerializer(many=True, read_only=True)
|
||||
workflow = IntegerField(min_value=1, required=False, validators=[validate_workflow_field])
|
||||
workflow_id = IntegerField(
|
||||
min_value=1,
|
||||
required=False,
|
||||
validators=[validate_workflow_field],
|
||||
write_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Motion
|
||||
@ -201,13 +204,13 @@ class MotionSerializer(ModelSerializer):
|
||||
'submitters',
|
||||
'supporters',
|
||||
'state',
|
||||
'workflow',
|
||||
'workflow_id',
|
||||
'tags',
|
||||
'attachments',
|
||||
'polls',
|
||||
'agenda_item_id',
|
||||
'log_messages',)
|
||||
read_only_fields = ('parent',) # Some other fields are also read_only. See definitions above.
|
||||
read_only_fields = ('parent', 'state') # Some other fields are also read_only. See definitions above.
|
||||
|
||||
@transaction.atomic
|
||||
def create(self, validated_data):
|
||||
@ -220,7 +223,7 @@ class MotionSerializer(ModelSerializer):
|
||||
motion.reason = validated_data.get('reason', '')
|
||||
motion.identifier = validated_data.get('identifier')
|
||||
motion.category = validated_data.get('category')
|
||||
motion.reset_state(validated_data.get('workflow', int(config['motions_workflow'])))
|
||||
motion.reset_state(validated_data.get('workflow_id'))
|
||||
motion.save()
|
||||
if validated_data.get('submitters'):
|
||||
motion.submitters.add(*validated_data['submitters'])
|
||||
@ -242,9 +245,9 @@ class MotionSerializer(ModelSerializer):
|
||||
setattr(motion, key, validated_data[key])
|
||||
|
||||
# Workflow.
|
||||
workflow = validated_data.get('workflow')
|
||||
if workflow is not None and workflow != motion.workflow:
|
||||
motion.reset_state(workflow)
|
||||
workflow_id = validated_data.get('workflow_id')
|
||||
if workflow_id is not None and workflow_id != motion.workflow:
|
||||
motion.reset_state(workflow_id)
|
||||
|
||||
# Decide if a new version is saved to the database.
|
||||
if (motion.state.versioning and
|
||||
|
@ -2,14 +2,58 @@
|
||||
|
||||
angular.module('OpenSlidesApp.motions', [])
|
||||
|
||||
.factory('WorkflowState', [
|
||||
'DS',
|
||||
function (DS) {
|
||||
return DS.defineResource({
|
||||
name: 'motions/workflowstate',
|
||||
methods: {
|
||||
getNextStates: function () {
|
||||
var states = [];
|
||||
_.forEach(this.next_states_id, function (stateId) {
|
||||
states.push(DS.get('motions/workflowstate', stateId));
|
||||
})
|
||||
return states;
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
])
|
||||
|
||||
.factory('Workflow', [
|
||||
'DS',
|
||||
'jsDataModel',
|
||||
'WorkflowState',
|
||||
function (DS, jsDataModel, WorkflowState) {
|
||||
return DS.defineResource({
|
||||
name: 'motions/workflow',
|
||||
useClass: jsDataModel,
|
||||
relations: {
|
||||
hasMany: {
|
||||
'motions/workflowstate': {
|
||||
localField: 'states',
|
||||
foreignKey: 'workflow_id',
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
])
|
||||
|
||||
// Load all MotionWorkflows at stateup
|
||||
.run([
|
||||
'Workflow',
|
||||
function (Workflow) {
|
||||
Workflow.findAll();
|
||||
}
|
||||
])
|
||||
|
||||
.factory('MotionPoll', [
|
||||
'DS',
|
||||
'Config',
|
||||
'jsDataModel',
|
||||
function(DS, Config, jsDataModel) {
|
||||
function (DS, Config) {
|
||||
return DS.defineResource({
|
||||
name: 'motions/motionpoll',
|
||||
useClass: jsDataModel,
|
||||
name: 'motions/poll',
|
||||
relations: {
|
||||
belongsTo: {
|
||||
'motions/motion': {
|
||||
@ -149,10 +193,16 @@ angular.module('OpenSlidesApp.motions', [])
|
||||
localKeys: 'supporters_id',
|
||||
}
|
||||
],
|
||||
'motions/motionpoll': {
|
||||
'motions/poll': {
|
||||
localField: 'polls',
|
||||
foreignKey: 'motion_id',
|
||||
}
|
||||
},
|
||||
hasOne: {
|
||||
'motions/workflowstate': {
|
||||
localField: 'state',
|
||||
localKey: 'state_id',
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -165,13 +215,7 @@ angular.module('OpenSlidesApp.motions', [])
|
||||
});
|
||||
}])
|
||||
|
||||
.factory('Workflow', ['DS', function(DS) {
|
||||
return DS.defineResource({
|
||||
name: 'motions/workflow',
|
||||
});
|
||||
}])
|
||||
|
||||
.run(['Motion', 'Category', 'Workflow', function(Motion, Category, Workflow) {}]);
|
||||
.run(['Motion', 'Category', function(Motion, Category) {}]);
|
||||
|
||||
|
||||
angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions'])
|
||||
@ -221,9 +265,6 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions'])
|
||||
categories: function(Category) {
|
||||
return Category.findAll();
|
||||
},
|
||||
workflows: function(Workflow) {
|
||||
return Workflow.findAll();
|
||||
},
|
||||
tags: function(Tag) {
|
||||
return Tag.findAll();
|
||||
},
|
||||
@ -262,9 +303,6 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions'])
|
||||
categories: function(Category) {
|
||||
return Category.findAll();
|
||||
},
|
||||
workflows: function(Workflow) {
|
||||
return Workflow.findAll();
|
||||
},
|
||||
tags: function(Tag) {
|
||||
return Tag.findAll();
|
||||
},
|
||||
@ -405,7 +443,9 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions'])
|
||||
Category.bindAll({}, $scope, 'categories');
|
||||
Workflow.bindAll({}, $scope, 'workflows');
|
||||
User.bindAll({}, $scope, 'users');
|
||||
Motion.loadRelations(motion);
|
||||
Motion.loadRelations(motion, 'agenda_item');
|
||||
var state = motion.state;
|
||||
state.getNextStates()
|
||||
$scope.alert = {}; // TODO: show alert in template
|
||||
|
||||
$scope.update_state = function (state_id) {
|
||||
|
@ -6,7 +6,11 @@
|
||||
</small>
|
||||
</h1>
|
||||
|
||||
{{ motion.agenda_item }}
|
||||
agenda_id: {{ motion.agenda_item }}
|
||||
|
||||
<br><br>state: {{ motion.state }}
|
||||
|
||||
<br><br>next states: {{ motion.state.getNextStates() }}
|
||||
|
||||
<div id="submenu">
|
||||
<a ui-sref="motions.motion.list" class="btn btn-sm btn-default">
|
||||
|
@ -108,15 +108,17 @@ class CreateMotion(TestCase):
|
||||
self.assertEqual(motion.tags.get().name, 'test_tag_iRee3kiecoos4rorohth')
|
||||
|
||||
def test_with_workflow(self):
|
||||
self.assertEqual(config['motions_workflow'], '1')
|
||||
"""
|
||||
Test to create a motion with a specific workflow.
|
||||
"""
|
||||
response = self.client.post(
|
||||
reverse('motion-list'),
|
||||
{'title': 'test_title_eemuR5hoo4ru2ahgh5EJ',
|
||||
'text': 'test_text_ohviePopahPhoili7yee',
|
||||
'workflow': '2'})
|
||||
'workflow_id': '2'})
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
motion = Motion.objects.get()
|
||||
self.assertEqual(motion.state.workflow.pk, 2)
|
||||
self.assertEqual(Motion.objects.get().state.workflow_id, 2)
|
||||
|
||||
|
||||
class UpdateMotion(TestCase):
|
||||
@ -141,12 +143,15 @@ class UpdateMotion(TestCase):
|
||||
self.assertEqual(motion.identifier, 'test_identifier_jieseghohj7OoSah1Ko9')
|
||||
|
||||
def test_patch_workflow(self):
|
||||
self.assertEqual(config['motions_workflow'], '1')
|
||||
"""
|
||||
Tests to only update the workflow of a motion.
|
||||
"""
|
||||
response = self.client.patch(
|
||||
reverse('motion-detail', args=[self.motion.pk]),
|
||||
{'workflow': '2'})
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
{'workflow_id': '2'})
|
||||
|
||||
motion = Motion.objects.get()
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(motion.title, 'test_title_aeng7ahChie3waiR8xoh')
|
||||
self.assertEqual(motion.workflow, 2)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user