Enhance setup of new agenda items for topics, motions and motion blocks.
This commit is contained in:
parent
f7de741e10
commit
4aad16db4f
@ -15,18 +15,17 @@ def listen_to_related_object_post_save(sender, instance, created, **kwargs):
|
|||||||
django.db.models.signals.post_save during app loading.
|
django.db.models.signals.post_save during app loading.
|
||||||
|
|
||||||
The agenda_item_update_information container may have fields like type,
|
The agenda_item_update_information container may have fields like type,
|
||||||
parent or skip_autoupdate.
|
parent_id, comment, duration, weight or skip_autoupdate.
|
||||||
|
|
||||||
Do not run caching and autoupdate if the instance as a key
|
Do not run caching and autoupdate if the instance has a key
|
||||||
skip_autoupdate in the agenda_item_update_information container.
|
skip_autoupdate in the agenda_item_update_information container.
|
||||||
"""
|
"""
|
||||||
if hasattr(instance, 'get_agenda_title'):
|
if hasattr(instance, 'get_agenda_title'):
|
||||||
if created:
|
if created:
|
||||||
attrs = {}
|
attrs = {}
|
||||||
if instance.agenda_item_update_information.get('type'):
|
for attr in ('type', 'parent_id', 'comment', 'duration', 'weight'):
|
||||||
attrs['type'] = instance.agenda_item_update_information.get('type')
|
if instance.agenda_item_update_information.get(attr):
|
||||||
if instance.agenda_item_update_information.get('parent'):
|
attrs[attr] = instance.agenda_item_update_information.get(attr)
|
||||||
attrs['parent'] = instance.agenda_item_update_information.get('parent')
|
|
||||||
Item.objects.create(content_object=instance, **attrs)
|
Item.objects.create(content_object=instance, **attrs)
|
||||||
|
|
||||||
# If the object is created, the related_object has to be sent again.
|
# If the object is created, the related_object has to be sent again.
|
||||||
|
@ -333,7 +333,7 @@ class Assignment(RESTModelMixin, models.Model):
|
|||||||
"""
|
"""
|
||||||
Container for runtime information for agenda app (on create or update of this instance).
|
Container for runtime information for agenda app (on create or update of this instance).
|
||||||
"""
|
"""
|
||||||
agenda_item_update_information = {}
|
agenda_item_update_information = {} # type: Dict[str, Any]
|
||||||
|
|
||||||
def get_agenda_title(self):
|
def get_agenda_title(self):
|
||||||
return str(self)
|
return str(self)
|
||||||
|
@ -194,6 +194,8 @@ class AssignmentFullSerializer(ModelSerializer):
|
|||||||
"""
|
"""
|
||||||
assignment_related_users = AssignmentRelatedUserSerializer(many=True, read_only=True)
|
assignment_related_users = AssignmentRelatedUserSerializer(many=True, read_only=True)
|
||||||
polls = AssignmentAllPollSerializer(many=True, read_only=True)
|
polls = AssignmentAllPollSerializer(many=True, read_only=True)
|
||||||
|
agenda_type = IntegerField(write_only=True, required=False, min_value=1, max_value=2)
|
||||||
|
agenda_parent_id = IntegerField(write_only=True, required=False, min_value=1)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Assignment
|
model = Assignment
|
||||||
@ -207,6 +209,8 @@ class AssignmentFullSerializer(ModelSerializer):
|
|||||||
'poll_description_default',
|
'poll_description_default',
|
||||||
'polls',
|
'polls',
|
||||||
'agenda_item_id',
|
'agenda_item_id',
|
||||||
|
'agenda_type',
|
||||||
|
'agenda_parent_id',
|
||||||
'tags',)
|
'tags',)
|
||||||
validators = (posts_validator,)
|
validators = (posts_validator,)
|
||||||
|
|
||||||
@ -215,6 +219,19 @@ class AssignmentFullSerializer(ModelSerializer):
|
|||||||
data['description'] = validate_html(data['description'])
|
data['description'] = validate_html(data['description'])
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
"""
|
||||||
|
Customized create method. Set information about related agenda item
|
||||||
|
into agenda_item_update_information container.
|
||||||
|
"""
|
||||||
|
agenda_type = validated_data.pop('agenda_type', None)
|
||||||
|
agenda_parent_id = validated_data.pop('agenda_parent_id', None)
|
||||||
|
assignment = Assignment(**validated_data)
|
||||||
|
assignment.agenda_item_update_information['type'] = agenda_type
|
||||||
|
assignment.agenda_item_update_information['parent_id'] = agenda_parent_id
|
||||||
|
assignment.save()
|
||||||
|
return assignment
|
||||||
|
|
||||||
|
|
||||||
class AssignmentShortSerializer(AssignmentFullSerializer):
|
class AssignmentShortSerializer(AssignmentFullSerializer):
|
||||||
"""
|
"""
|
||||||
|
@ -157,7 +157,7 @@ angular.module('OpenSlidesApp.assignments.site', [
|
|||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
// parent item
|
// show as agenda item + parent item
|
||||||
if (isCreateForm) {
|
if (isCreateForm) {
|
||||||
formFields.push({
|
formFields.push({
|
||||||
key: 'showAsAgendaItem',
|
key: 'showAsAgendaItem',
|
||||||
@ -627,9 +627,8 @@ angular.module('OpenSlidesApp.assignments.site', [
|
|||||||
'Assignment',
|
'Assignment',
|
||||||
'AssignmentForm',
|
'AssignmentForm',
|
||||||
'Agenda',
|
'Agenda',
|
||||||
//'AgendaUpdate',
|
|
||||||
'ErrorMessage',
|
'ErrorMessage',
|
||||||
function($scope, $state, Assignment, AssignmentForm, Agenda,/* AgendaUpdate,*/ ErrorMessage) {
|
function($scope, $state, Assignment, AssignmentForm, Agenda, ErrorMessage) {
|
||||||
$scope.model = {};
|
$scope.model = {};
|
||||||
// set default value for open posts form field
|
// set default value for open posts form field
|
||||||
$scope.model.open_posts = 1;
|
$scope.model.open_posts = 1;
|
||||||
@ -638,13 +637,9 @@ angular.module('OpenSlidesApp.assignments.site', [
|
|||||||
// save assignment
|
// save assignment
|
||||||
$scope.save = function(assignment, gotoDetailView) {
|
$scope.save = function(assignment, gotoDetailView) {
|
||||||
assignment.agenda_type = assignment.showAsAgendaItem ? 1 : 2;
|
assignment.agenda_type = assignment.showAsAgendaItem ? 1 : 2;
|
||||||
|
// The attribute assignment.agenda_parent_id is set by the form, see form definition.
|
||||||
Assignment.create(assignment).then(
|
Assignment.create(assignment).then(
|
||||||
function (success) {
|
function (success) {
|
||||||
// type: Value 1 means a non hidden agenda item, value 2 means a hidden agenda item,
|
|
||||||
// see openslides.agenda.models.Item.ITEM_TYPE.
|
|
||||||
/*var changes = [{key: 'type', value: (assignment.showAsAgendaItem ? 1 : 2)},
|
|
||||||
{key: 'parent_id', value: assignment.agenda_parent_item_id}];
|
|
||||||
AgendaUpdate.saveChanges(success.agenda_item_id,changes);*/
|
|
||||||
if (gotoDetailView) {
|
if (gotoDetailView) {
|
||||||
$state.go('assignments.assignment.detail', {id: success.id});
|
$state.go('assignments.assignment.detail', {id: success.id});
|
||||||
}
|
}
|
||||||
@ -674,20 +669,12 @@ angular.module('OpenSlidesApp.assignments.site', [
|
|||||||
$scope.model = angular.copy(assignment);
|
$scope.model = angular.copy(assignment);
|
||||||
// get all form fields
|
// get all form fields
|
||||||
$scope.formFields = AssignmentForm.getFormFields();
|
$scope.formFields = AssignmentForm.getFormFields();
|
||||||
var agenda_item = Agenda.get(assignment.agenda_item_id);
|
|
||||||
for (var i = 0; i < $scope.formFields.length; i++) {
|
|
||||||
if ($scope.formFields[i].key == "showAsAgendaItem") {
|
|
||||||
// get state from agenda item (hidden/internal or agenda item)
|
|
||||||
$scope.formFields[i].defaultValue = !assignment.agenda_item.is_hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// save assignment
|
// save assignment
|
||||||
$scope.save = function (assignment, gotoDetailView) {
|
$scope.save = function (assignment, gotoDetailView) {
|
||||||
assignment.agenda_type = assignment.showAsAgendaItem ? 1 : 2;
|
|
||||||
// inject the changed assignment (copy) object back into DS store
|
// inject the changed assignment (copy) object back into DS store
|
||||||
Assignment.inject(assignment);
|
Assignment.inject(assignment);
|
||||||
// save change assignment object on server
|
// save changed assignment object on server
|
||||||
Assignment.save(assignment).then(
|
Assignment.save(assignment).then(
|
||||||
function(success) {
|
function(success) {
|
||||||
if (gotoDetailView) {
|
if (gotoDetailView) {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from typing import Any, Dict # noqa
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.contenttypes.fields import GenericRelation
|
from django.contrib.contenttypes.fields import GenericRelation
|
||||||
from django.core.exceptions import ImproperlyConfigured, ValidationError
|
from django.core.exceptions import ImproperlyConfigured, ValidationError
|
||||||
@ -631,7 +633,7 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
"""
|
"""
|
||||||
Container for runtime information for agenda app (on create or update of this instance).
|
Container for runtime information for agenda app (on create or update of this instance).
|
||||||
"""
|
"""
|
||||||
agenda_item_update_information = {}
|
agenda_item_update_information = {} # type: Dict[str, Any]
|
||||||
|
|
||||||
def get_agenda_title(self):
|
def get_agenda_title(self):
|
||||||
"""
|
"""
|
||||||
@ -903,7 +905,7 @@ class MotionBlock(RESTModelMixin, models.Model):
|
|||||||
"""
|
"""
|
||||||
Container for runtime information for agenda app (on create or update of this instance).
|
Container for runtime information for agenda app (on create or update of this instance).
|
||||||
"""
|
"""
|
||||||
agenda_item_update_information = {}
|
agenda_item_update_information = {} # type: Dict[str, Any]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def agenda_item(self):
|
def agenda_item(self):
|
||||||
|
@ -49,9 +49,25 @@ class MotionBlockSerializer(ModelSerializer):
|
|||||||
"""
|
"""
|
||||||
Serializer for motion.models.Category objects.
|
Serializer for motion.models.Category objects.
|
||||||
"""
|
"""
|
||||||
|
agenda_type = IntegerField(write_only=True, required=False, min_value=1, max_value=2)
|
||||||
|
agenda_parent_id = IntegerField(write_only=True, required=False, min_value=1)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = MotionBlock
|
model = MotionBlock
|
||||||
fields = ('id', 'title', 'agenda_item_id',)
|
fields = ('id', 'title', 'agenda_item_id', 'agenda_type', 'agenda_parent_id',)
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
"""
|
||||||
|
Customized create method. Set information about related agenda item
|
||||||
|
into agenda_item_update_information container.
|
||||||
|
"""
|
||||||
|
agenda_type = validated_data.pop('agenda_type', None)
|
||||||
|
agenda_parent_id = validated_data.pop('agenda_parent_id', None)
|
||||||
|
motion_block = MotionBlock(**validated_data)
|
||||||
|
motion_block.agenda_item_update_information['type'] = agenda_type
|
||||||
|
motion_block.agenda_item_update_information['parent_id'] = agenda_parent_id
|
||||||
|
motion_block.save()
|
||||||
|
return motion_block
|
||||||
|
|
||||||
|
|
||||||
class StateSerializer(ModelSerializer):
|
class StateSerializer(ModelSerializer):
|
||||||
@ -288,6 +304,8 @@ class MotionSerializer(ModelSerializer):
|
|||||||
required=False,
|
required=False,
|
||||||
validators=[validate_workflow_field],
|
validators=[validate_workflow_field],
|
||||||
write_only=True)
|
write_only=True)
|
||||||
|
agenda_type = IntegerField(write_only=True, required=False, min_value=1, max_value=2)
|
||||||
|
agenda_parent_id = IntegerField(write_only=True, required=False, min_value=1)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Motion
|
model = Motion
|
||||||
@ -314,6 +332,8 @@ class MotionSerializer(ModelSerializer):
|
|||||||
'attachments',
|
'attachments',
|
||||||
'polls',
|
'polls',
|
||||||
'agenda_item_id',
|
'agenda_item_id',
|
||||||
|
'agenda_type',
|
||||||
|
'agenda_parent_id',
|
||||||
'log_messages',)
|
'log_messages',)
|
||||||
read_only_fields = ('state', 'recommendation',) # Some other fields are also read_only. See definitions above.
|
read_only_fields = ('state', 'recommendation',) # Some other fields are also read_only. See definitions above.
|
||||||
|
|
||||||
@ -332,6 +352,9 @@ class MotionSerializer(ModelSerializer):
|
|||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
"""
|
"""
|
||||||
Customized method to create a new motion from some data.
|
Customized method to create a new motion from some data.
|
||||||
|
|
||||||
|
Set also information about related agenda item into
|
||||||
|
agenda_item_update_information container.
|
||||||
"""
|
"""
|
||||||
motion = Motion()
|
motion = Motion()
|
||||||
motion.title = validated_data['title']
|
motion.title = validated_data['title']
|
||||||
@ -344,6 +367,8 @@ class MotionSerializer(ModelSerializer):
|
|||||||
motion.comments = validated_data.get('comments')
|
motion.comments = validated_data.get('comments')
|
||||||
motion.parent = validated_data.get('parent')
|
motion.parent = validated_data.get('parent')
|
||||||
motion.reset_state(validated_data.get('workflow_id'))
|
motion.reset_state(validated_data.get('workflow_id'))
|
||||||
|
motion.agenda_item_update_information['type'] = validated_data.get('agenda_type')
|
||||||
|
motion.agenda_item_update_information['parent_id'] = validated_data.get('agenda_parent_id')
|
||||||
motion.save()
|
motion.save()
|
||||||
if validated_data.get('submitters'):
|
if validated_data.get('submitters'):
|
||||||
motion.submitters.add(*validated_data['submitters'])
|
motion.submitters.add(*validated_data['submitters'])
|
||||||
|
@ -69,8 +69,8 @@ angular.module('OpenSlidesApp.motions.motionBlock', [])
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
// Get angular-formly fields.
|
// Get angular-formly fields.
|
||||||
getFormFields: function () {
|
getFormFields: function (isCreateForm) {
|
||||||
return [
|
var formFields = [
|
||||||
{
|
{
|
||||||
key: 'title',
|
key: 'title',
|
||||||
type: 'input',
|
type: 'input',
|
||||||
@ -78,7 +78,11 @@ angular.module('OpenSlidesApp.motions.motionBlock', [])
|
|||||||
label: gettextCatalog.getString('Title')
|
label: gettextCatalog.getString('Title')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
];
|
||||||
|
|
||||||
|
// show as agenda item + parent item
|
||||||
|
if (isCreateForm) {
|
||||||
|
formFields.push({
|
||||||
key: 'showAsAgendaItem',
|
key: 'showAsAgendaItem',
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
templateOptions: {
|
templateOptions: {
|
||||||
@ -86,18 +90,21 @@ angular.module('OpenSlidesApp.motions.motionBlock', [])
|
|||||||
description: gettextCatalog.getString('If deactivated it appears as internal item on agenda.')
|
description: gettextCatalog.getString('If deactivated it appears as internal item on agenda.')
|
||||||
},
|
},
|
||||||
hide: !(operator.hasPerms('motions.can_manage') && operator.hasPerms('agenda.can_manage'))
|
hide: !(operator.hasPerms('motions.can_manage') && operator.hasPerms('agenda.can_manage'))
|
||||||
},
|
});
|
||||||
{
|
formFields.push({
|
||||||
key: 'agenda_parent_item_id',
|
key: 'agenda_parent_id',
|
||||||
type: 'select-single',
|
type: 'select-single',
|
||||||
templateOptions: {
|
templateOptions: {
|
||||||
label: gettextCatalog.getString('Parent item'),
|
label: gettextCatalog.getString('Parent item'),
|
||||||
options: AgendaTree.getFlatTree(Agenda.getAll()),
|
options: AgendaTree.getFlatTree(Agenda.getAll()),
|
||||||
ngOptions: 'item.id as item.getListViewTitle() for item in to.options | notself : model.agenda_item_id',
|
ngOptions: 'item.id as item.getListViewTitle() for item in to.options | notself : model.agenda_item_id',
|
||||||
placeholder: gettextCatalog.getString('Select a parent item ...')
|
placeholder: gettextCatalog.getString('Select a parent item ...')
|
||||||
|
},
|
||||||
|
hide: !operator.hasPerms('agenda.can_manage')
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
];
|
return formFields;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -190,24 +197,20 @@ angular.module('OpenSlidesApp.motions.motionBlock', [])
|
|||||||
'$scope',
|
'$scope',
|
||||||
'MotionBlock',
|
'MotionBlock',
|
||||||
'MotionBlockForm',
|
'MotionBlockForm',
|
||||||
'AgendaUpdate',
|
function($scope, MotionBlock, MotionBlockForm) {
|
||||||
function($scope, MotionBlock, MotionBlockForm, AgendaUpdate) {
|
|
||||||
// Prepare form.
|
// Prepare form.
|
||||||
$scope.model = {};
|
$scope.model = {};
|
||||||
$scope.model.showAsAgendaItem = true;
|
$scope.model.showAsAgendaItem = true;
|
||||||
|
|
||||||
// Get all form fields.
|
// Get all form fields.
|
||||||
$scope.formFields = MotionBlockForm.getFormFields();
|
$scope.formFields = MotionBlockForm.getFormFields(true);
|
||||||
|
|
||||||
// Save form.
|
// Save form.
|
||||||
$scope.save = function (motionBlock) {
|
$scope.save = function (motionBlock) {
|
||||||
|
motionBlock.agenda_type = motionBlock.showAsAgendaItem ? 1 : 2;
|
||||||
|
// The attribute motionBlock.agenda_parent_id is set by the form, see form definition.
|
||||||
MotionBlock.create(motionBlock).then(
|
MotionBlock.create(motionBlock).then(
|
||||||
function (success) {
|
function (success) {
|
||||||
// type: Value 1 means a non hidden agenda item, value 2 means a hidden agenda item,
|
|
||||||
// see openslides.agenda.models.Item.ITEM_TYPE.
|
|
||||||
var changes = [{key: 'type', value: (motionBlock.showAsAgendaItem ? 1 : 2)},
|
|
||||||
{key: 'parent_id', value: motionBlock.agenda_parent_item_id}];
|
|
||||||
AgendaUpdate.saveChanges(success.agenda_item_id, changes);
|
|
||||||
$scope.closeThisDialog();
|
$scope.closeThisDialog();
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
@ -230,8 +233,6 @@ angular.module('OpenSlidesApp.motions.motionBlock', [])
|
|||||||
'AgendaUpdate',
|
'AgendaUpdate',
|
||||||
'motionBlockId',
|
'motionBlockId',
|
||||||
function($scope, $state, MotionBlock, MotionBlockForm, AgendaUpdate, motionBlockId) {
|
function($scope, $state, MotionBlock, MotionBlockForm, AgendaUpdate, motionBlockId) {
|
||||||
// TODO: Check #2486 and remove some agenda related code.
|
|
||||||
//MotionBlock.loadRelations(motionBlock, 'agenda_item');
|
|
||||||
$scope.alert = {};
|
$scope.alert = {};
|
||||||
|
|
||||||
// Prepare form. Set initial values by creating a deep copy of
|
// Prepare form. Set initial values by creating a deep copy of
|
||||||
@ -241,23 +242,14 @@ angular.module('OpenSlidesApp.motions.motionBlock', [])
|
|||||||
|
|
||||||
// Get all form fields.
|
// Get all form fields.
|
||||||
$scope.formFields = MotionBlockForm.getFormFields();
|
$scope.formFields = MotionBlockForm.getFormFields();
|
||||||
for (var i = 0; i < $scope.formFields.length; i++) {
|
|
||||||
if ($scope.formFields[i].key == 'showAsAgendaItem') {
|
|
||||||
// Get state from agenda item (hidden/internal or agenda item).
|
|
||||||
$scope.formFields[i].defaultValue = !motionBlock.agenda_item.is_hidden;
|
|
||||||
} else if ($scope.formFields[i].key == 'agenda_parent_item_id') {
|
|
||||||
$scope.formFields[i].defaultValue = motionBlock.agenda_item.parent_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Save form.
|
// Save form.
|
||||||
$scope.save = function (motionBlock) {
|
$scope.save = function (motionBlock) {
|
||||||
|
// inject the changed motionBlock (copy) object back into DS store
|
||||||
|
MotionBlock.inject(motionBlock);
|
||||||
|
// save changed motionBlock object on server
|
||||||
MotionBlock.create(motionBlock).then(
|
MotionBlock.create(motionBlock).then(
|
||||||
function (success) {
|
function (success) {
|
||||||
// type: Value 1 means a non hidden agenda item, value 2 means a hidden agenda item,
|
|
||||||
// see openslides.agenda.models.Item.ITEM_TYPE.
|
|
||||||
var changes = [{key: 'type', value: (motionBlock.showAsAgendaItem ? 1 : 2)},
|
|
||||||
{key: 'parent_id', value: motionBlock.agenda_parent_item_id}];
|
|
||||||
AgendaUpdate.saveChanges(success.agenda_item_id,changes);
|
|
||||||
$scope.closeThisDialog();
|
$scope.closeThisDialog();
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
|
@ -376,8 +376,11 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
description: gettextCatalog.getString("Don't create a new version.")
|
description: gettextCatalog.getString("Don't create a new version.")
|
||||||
},
|
},
|
||||||
hide: true
|
hide: true
|
||||||
},
|
}];
|
||||||
{
|
|
||||||
|
// show as agenda item + parent item
|
||||||
|
if (isCreateForm) {
|
||||||
|
formFields.push({
|
||||||
key: 'showAsAgendaItem',
|
key: 'showAsAgendaItem',
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
templateOptions: {
|
templateOptions: {
|
||||||
@ -385,12 +388,9 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
description: gettextCatalog.getString('If deactivated the motion appears as internal item on agenda.')
|
description: gettextCatalog.getString('If deactivated the motion appears as internal item on agenda.')
|
||||||
},
|
},
|
||||||
hide: !(operator.hasPerms('motions.can_manage') && operator.hasPerms('agenda.can_manage'))
|
hide: !(operator.hasPerms('motions.can_manage') && operator.hasPerms('agenda.can_manage'))
|
||||||
}];
|
});
|
||||||
|
|
||||||
// parent item
|
|
||||||
if (isCreateForm) {
|
|
||||||
formFields.push({
|
formFields.push({
|
||||||
key: 'agenda_parent_item_id',
|
key: 'agenda_parent_id',
|
||||||
type: 'select-single',
|
type: 'select-single',
|
||||||
templateOptions: {
|
templateOptions: {
|
||||||
label: gettextCatalog.getString('Parent item'),
|
label: gettextCatalog.getString('Parent item'),
|
||||||
@ -1890,10 +1890,9 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
'User',
|
'User',
|
||||||
'Workflow',
|
'Workflow',
|
||||||
'Agenda',
|
'Agenda',
|
||||||
'AgendaUpdate',
|
|
||||||
'ErrorMessage',
|
'ErrorMessage',
|
||||||
function($scope, $state, gettext, gettextCatalog, operator, Motion, MotionForm,
|
function($scope, $state, gettext, gettextCatalog, operator, Motion, MotionForm,
|
||||||
Category, Config, Mediafile, Tag, User, Workflow, Agenda, AgendaUpdate, ErrorMessage) {
|
Category, Config, Mediafile, Tag, User, Workflow, Agenda, ErrorMessage) {
|
||||||
Category.bindAll({}, $scope, 'categories');
|
Category.bindAll({}, $scope, 'categories');
|
||||||
Mediafile.bindAll({}, $scope, 'mediafiles');
|
Mediafile.bindAll({}, $scope, 'mediafiles');
|
||||||
Tag.bindAll({}, $scope, 'tags');
|
Tag.bindAll({}, $scope, 'tags');
|
||||||
@ -1927,13 +1926,10 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
|
|
||||||
// save motion
|
// save motion
|
||||||
$scope.save = function (motion, gotoDetailView) {
|
$scope.save = function (motion, gotoDetailView) {
|
||||||
|
motion.agenda_type = motion.showAsAgendaItem ? 1 : 2;
|
||||||
|
// The attribute motion.agenda_parent_id is set by the form, see form definition.
|
||||||
Motion.create(motion).then(
|
Motion.create(motion).then(
|
||||||
function(success) {
|
function(success) {
|
||||||
// type: Value 1 means a non hidden agenda item, value 2 means a hidden agenda item,
|
|
||||||
// see openslides.agenda.models.Item.ITEM_TYPE.
|
|
||||||
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 || gotoDetailView) {
|
if (isAmendment || gotoDetailView) {
|
||||||
$state.go('motions.motion.detail', {id: success.id});
|
$state.go('motions.motion.detail', {id: success.id});
|
||||||
}
|
}
|
||||||
@ -1959,13 +1955,12 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
'User',
|
'User',
|
||||||
'Workflow',
|
'Workflow',
|
||||||
'Agenda',
|
'Agenda',
|
||||||
'AgendaUpdate',
|
|
||||||
'motionId',
|
'motionId',
|
||||||
'operator',
|
'operator',
|
||||||
'ErrorMessage',
|
'ErrorMessage',
|
||||||
'EditingWarning',
|
'EditingWarning',
|
||||||
function($scope, $state, Motion, Category, Config, Mediafile, MotionForm,
|
function($scope, $state, Motion, Category, Config, Mediafile, MotionForm,
|
||||||
Tag, User, Workflow, Agenda, AgendaUpdate, motionId, operator, ErrorMessage,
|
Tag, User, Workflow, Agenda, motionId, operator, ErrorMessage,
|
||||||
EditingWarning) {
|
EditingWarning) {
|
||||||
Category.bindAll({}, $scope, 'categories');
|
Category.bindAll({}, $scope, 'categories');
|
||||||
Mediafile.bindAll({}, $scope, 'mediafiles');
|
Mediafile.bindAll({}, $scope, 'mediafiles');
|
||||||
@ -2007,18 +2002,10 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
$scope.formFields[i].hide = false;
|
$scope.formFields[i].hide = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($scope.formFields[i].key == "showAsAgendaItem" && motion.agenda_item) {
|
|
||||||
// get state from agenda item (hidden/internal or agenda item)
|
|
||||||
$scope.formFields[i].defaultValue = !motion.agenda_item.is_hidden;
|
|
||||||
}
|
|
||||||
if ($scope.formFields[i].key == "workflow_id") {
|
if ($scope.formFields[i].key == "workflow_id") {
|
||||||
// get saved workflow id from state
|
// get saved workflow id from state
|
||||||
$scope.formFields[i].defaultValue = motion.state.workflow_id;
|
$scope.formFields[i].defaultValue = motion.state.workflow_id;
|
||||||
}
|
}
|
||||||
if ($scope.formFields[i].key == "agenda_parent_item_id") {
|
|
||||||
// get current parent_id of the agenda item
|
|
||||||
$scope.formFields[i].defaultValue = motion.agenda_item.parent_id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Displaying a warning, if other users edit this motion too
|
// Displaying a warning, if other users edit this motion too
|
||||||
@ -2029,14 +2016,9 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
$scope.save = function (motion, gotoDetailView) {
|
$scope.save = function (motion, gotoDetailView) {
|
||||||
// inject the changed motion (copy) object back into DS store
|
// inject the changed motion (copy) object back into DS store
|
||||||
Motion.inject(motion);
|
Motion.inject(motion);
|
||||||
// save change motion object on server
|
// save changed motion object on server
|
||||||
Motion.save(motion).then(
|
Motion.save(motion).then(
|
||||||
function(success) {
|
function(success) {
|
||||||
// type: Value 1 means a non hidden agenda item, value 2 means a hidden agenda item,
|
|
||||||
// see openslides.agenda.models.Item.ITEM_TYPE.
|
|
||||||
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 (gotoDetailView) {
|
if (gotoDetailView) {
|
||||||
$state.go('motions.motion.detail', {id: success.id});
|
$state.go('motions.motion.detail', {id: success.id});
|
||||||
}
|
}
|
||||||
|
@ -596,7 +596,8 @@ class CategoryViewSet(ModelViewSet):
|
|||||||
# Remove old identifiers
|
# Remove old identifiers
|
||||||
for motion in motions:
|
for motion in motions:
|
||||||
motion.identifier = None
|
motion.identifier = None
|
||||||
motion.agenda_item_update_information['skip_autoupdate'] = True # This line is to skip agenda item autoupdate. See agenda/signals.py.
|
# This line is to skip agenda item autoupdate. See agenda/signals.py.
|
||||||
|
motion.agenda_item_update_information['skip_autoupdate'] = True
|
||||||
motion.save(skip_autoupdate=True)
|
motion.save(skip_autoupdate=True)
|
||||||
|
|
||||||
# Set new identifers and change identifiers of amendments.
|
# Set new identifers and change identifiers of amendments.
|
||||||
@ -615,7 +616,8 @@ class CategoryViewSet(ModelViewSet):
|
|||||||
obj['new_identifier'],
|
obj['new_identifier'],
|
||||||
child.identifier,
|
child.identifier,
|
||||||
count=1)
|
count=1)
|
||||||
child.agenda_item_update_information['skip_autoupdate'] = True # This line is to skip agenda item autoupdate. See agenda/signals.py.
|
# This line is to skip agenda item autoupdate. See agenda/signals.py.
|
||||||
|
child.agenda_item_update_information['skip_autoupdate'] = True
|
||||||
child.save(skip_autoupdate=True)
|
child.save(skip_autoupdate=True)
|
||||||
instances.append(child)
|
instances.append(child)
|
||||||
instances.append(child.agenda_item)
|
instances.append(child.agenda_item)
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from typing import Any, Dict # noqa
|
||||||
|
|
||||||
from django.contrib.contenttypes.fields import GenericRelation
|
from django.contrib.contenttypes.fields import GenericRelation
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
@ -57,7 +59,7 @@ class Topic(RESTModelMixin, models.Model):
|
|||||||
"""
|
"""
|
||||||
Container for runtime information for agenda app (on create or update of this instance).
|
Container for runtime information for agenda app (on create or update of this instance).
|
||||||
"""
|
"""
|
||||||
agenda_item_update_information = {}
|
agenda_item_update_information = {} # type: Dict[str, Any]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def agenda_item(self):
|
def agenda_item(self):
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from openslides.utils.rest_api import ModelSerializer
|
from openslides.utils.rest_api import CharField, IntegerField, ModelSerializer
|
||||||
from openslides.utils.validate import validate_html
|
from openslides.utils.validate import validate_html
|
||||||
|
|
||||||
from .models import Topic
|
from .models import Topic
|
||||||
@ -8,11 +8,49 @@ class TopicSerializer(ModelSerializer):
|
|||||||
"""
|
"""
|
||||||
Serializer for core.models.Topic objects.
|
Serializer for core.models.Topic objects.
|
||||||
"""
|
"""
|
||||||
|
agenda_type = IntegerField(write_only=True, required=False, min_value=1, max_value=2)
|
||||||
|
agenda_parent_id = IntegerField(write_only=True, required=False, min_value=1)
|
||||||
|
agenda_comment = CharField(write_only=True, required=False, allow_blank=True)
|
||||||
|
agenda_duration = IntegerField(write_only=True, required=False, min_value=1)
|
||||||
|
agenda_weight = IntegerField(write_only=True, required=False, min_value=1)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Topic
|
model = Topic
|
||||||
fields = ('id', 'title', 'text', 'attachments', 'agenda_item_id')
|
fields = (
|
||||||
|
'id',
|
||||||
|
'title',
|
||||||
|
'text',
|
||||||
|
'attachments',
|
||||||
|
'agenda_item_id',
|
||||||
|
'agenda_type',
|
||||||
|
'agenda_parent_id',
|
||||||
|
'agenda_comment',
|
||||||
|
'agenda_duration',
|
||||||
|
'agenda_weight',
|
||||||
|
)
|
||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
if 'text' in data:
|
if 'text' in data:
|
||||||
data['text'] = validate_html(data['text'])
|
data['text'] = validate_html(data['text'])
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
"""
|
||||||
|
Customized create method. Set information about related agenda item
|
||||||
|
into agenda_item_update_information container.
|
||||||
|
"""
|
||||||
|
agenda_type = validated_data.pop('agenda_type', None)
|
||||||
|
agenda_parent_id = validated_data.pop('agenda_parent_id', None)
|
||||||
|
agenda_comment = validated_data.pop('agenda_comment', None)
|
||||||
|
agenda_duration = validated_data.pop('agenda_duration', None)
|
||||||
|
agenda_weight = validated_data.pop('agenda_weight', None)
|
||||||
|
attachments = validated_data.pop('attachments', [])
|
||||||
|
topic = Topic(**validated_data)
|
||||||
|
topic.agenda_item_update_information['type'] = agenda_type
|
||||||
|
topic.agenda_item_update_information['parent_id'] = agenda_parent_id
|
||||||
|
topic.agenda_item_update_information['comment'] = agenda_comment
|
||||||
|
topic.agenda_item_update_information['duration'] = agenda_duration
|
||||||
|
topic.agenda_item_update_information['weight'] = agenda_weight
|
||||||
|
topic.save()
|
||||||
|
topic.attachments.add(*attachments)
|
||||||
|
return topic
|
||||||
|
@ -116,7 +116,9 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics', 'OpenSlides
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// show as agenda item
|
|
||||||
|
// show as agenda item + parent item
|
||||||
|
if (isCreateForm) {
|
||||||
formFields.push({
|
formFields.push({
|
||||||
key: 'showAsAgendaItem',
|
key: 'showAsAgendaItem',
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
@ -126,18 +128,16 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics', 'OpenSlides
|
|||||||
},
|
},
|
||||||
hide: !operator.hasPerms('agenda.can_manage')
|
hide: !operator.hasPerms('agenda.can_manage')
|
||||||
});
|
});
|
||||||
|
|
||||||
// parent item
|
|
||||||
if (isCreateForm) {
|
|
||||||
formFields.push({
|
formFields.push({
|
||||||
key: 'agenda_parent_item_id',
|
key: 'agenda_parent_id',
|
||||||
type: 'select-single',
|
type: 'select-single',
|
||||||
templateOptions: {
|
templateOptions: {
|
||||||
label: gettextCatalog.getString('Parent item'),
|
label: gettextCatalog.getString('Parent item'),
|
||||||
options: AgendaTree.getFlatTree(Agenda.getAll()),
|
options: AgendaTree.getFlatTree(Agenda.getAll()),
|
||||||
ngOptions: 'item.id as item.getListViewTitle() for item in to.options | notself : model.agenda_item_id',
|
ngOptions: 'item.id as item.getListViewTitle() for item in to.options | notself : model.agenda_item_id',
|
||||||
placeholder: gettextCatalog.getString('Select a parent item ...')
|
placeholder: gettextCatalog.getString('Select a parent item ...')
|
||||||
}
|
},
|
||||||
|
hide: !operator.hasPerms('agenda.can_manage')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,9 +186,8 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics', 'OpenSlides
|
|||||||
'Topic',
|
'Topic',
|
||||||
'TopicForm',
|
'TopicForm',
|
||||||
'Agenda',
|
'Agenda',
|
||||||
'AgendaUpdate',
|
|
||||||
'ErrorMessage',
|
'ErrorMessage',
|
||||||
function($scope, $state, Topic, TopicForm, Agenda, AgendaUpdate, ErrorMessage) {
|
function($scope, $state, Topic, TopicForm, Agenda, ErrorMessage) {
|
||||||
$scope.topic = {};
|
$scope.topic = {};
|
||||||
$scope.model = {};
|
$scope.model = {};
|
||||||
$scope.model.showAsAgendaItem = true;
|
$scope.model.showAsAgendaItem = true;
|
||||||
@ -196,13 +195,10 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics', 'OpenSlides
|
|||||||
$scope.formFields = TopicForm.getFormFields(true);
|
$scope.formFields = TopicForm.getFormFields(true);
|
||||||
// save form
|
// save form
|
||||||
$scope.save = function (topic) {
|
$scope.save = function (topic) {
|
||||||
|
topic.agenda_type = topic.showAsAgendaItem ? 1 : 2;
|
||||||
|
// The attribute topic.agenda_parent_id is set by the form, see form definition.
|
||||||
Topic.create(topic).then(
|
Topic.create(topic).then(
|
||||||
function (success) {
|
function (success) {
|
||||||
// type: Value 1 means a non hidden agenda item, value 2 means a hidden agenda item,
|
|
||||||
// see openslides.agenda.models.Item.ITEM_TYPE.
|
|
||||||
var changes = [{key: 'type', value: (topic.showAsAgendaItem ? 1 : 2)},
|
|
||||||
{key: 'parent_id', value: topic.agenda_parent_item_id}];
|
|
||||||
AgendaUpdate.saveChanges(success.agenda_item_id,changes);
|
|
||||||
$scope.closeThisDialog();
|
$scope.closeThisDialog();
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
$scope.alert = ErrorMessage.forAlert(error);
|
$scope.alert = ErrorMessage.forAlert(error);
|
||||||
@ -218,10 +214,9 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics', 'OpenSlides
|
|||||||
'Topic',
|
'Topic',
|
||||||
'TopicForm',
|
'TopicForm',
|
||||||
'Agenda',
|
'Agenda',
|
||||||
'AgendaUpdate',
|
|
||||||
'topicId',
|
'topicId',
|
||||||
'ErrorMessage',
|
'ErrorMessage',
|
||||||
function($scope, $state, Topic, TopicForm, Agenda, AgendaUpdate, topicId, ErrorMessage) {
|
function($scope, $state, Topic, TopicForm, Agenda, topicId, ErrorMessage) {
|
||||||
var topic = Topic.get(topicId);
|
var topic = Topic.get(topicId);
|
||||||
$scope.alert = {};
|
$scope.alert = {};
|
||||||
// set initial values for form model by create deep copy of topic object
|
// set initial values for form model by create deep copy of topic object
|
||||||
@ -229,25 +224,17 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics', 'OpenSlides
|
|||||||
$scope.model = angular.copy(topic);
|
$scope.model = angular.copy(topic);
|
||||||
// get all form fields
|
// get all form fields
|
||||||
$scope.formFields = TopicForm.getFormFields();
|
$scope.formFields = TopicForm.getFormFields();
|
||||||
for (var i = 0; i < $scope.formFields.length; i++) {
|
|
||||||
if ($scope.formFields[i].key == "showAsAgendaItem") {
|
|
||||||
// get state from agenda item (hidden/internal or agenda item)
|
|
||||||
$scope.formFields[i].defaultValue = !topic.agenda_item.is_hidden;
|
|
||||||
} else if ($scope.formFields[i].key == "agenda_parent_item_id") {
|
|
||||||
$scope.formFields[i].defaultValue = topic.agenda_item.parent_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// save form
|
// save form
|
||||||
$scope.save = function (topic) {
|
$scope.save = function (topic) {
|
||||||
Topic.create(topic).then(
|
// inject the changed topic (copy) object back into DS store
|
||||||
|
Topic.inject(topic);
|
||||||
|
// save changed topic object on server
|
||||||
|
Topic.save(topic).then(
|
||||||
function(success) {
|
function(success) {
|
||||||
// type: Value 1 means a non hidden agenda item, value 2 means a hidden agenda item,
|
|
||||||
// see openslides.agenda.models.Item.ITEM_TYPE.
|
|
||||||
var changes = [{key: 'type', value: (topic.showAsAgendaItem ? 1 : 2)},
|
|
||||||
{key: 'parent_id', value: topic.agenda_parent_item_id}];
|
|
||||||
AgendaUpdate.saveChanges(success.agenda_item_id,changes);
|
|
||||||
$scope.closeThisDialog();
|
$scope.closeThisDialog();
|
||||||
}, function (error) {
|
},
|
||||||
|
function (error) {
|
||||||
// save error: revert all changes by restore
|
// save error: revert all changes by restore
|
||||||
// (refresh) original topic object from server
|
// (refresh) original topic object from server
|
||||||
Topic.refresh(topic);
|
Topic.refresh(topic);
|
||||||
@ -265,8 +252,7 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics', 'OpenSlides
|
|||||||
'Topic',
|
'Topic',
|
||||||
'HumanTimeConverter',
|
'HumanTimeConverter',
|
||||||
'TopicsCsvExample',
|
'TopicsCsvExample',
|
||||||
'AgendaUpdate',
|
function($scope, gettext, Agenda, Topic, HumanTimeConverter, TopicsCsvExample) {
|
||||||
function($scope, gettext, Agenda, Topic, HumanTimeConverter, TopicsCsvExample, AgendaUpdate) {
|
|
||||||
// Big TODO: Change wording from "item" to "topic".
|
// Big TODO: Change wording from "item" to "topic".
|
||||||
// import from textarea
|
// import from textarea
|
||||||
$scope.importByLine = function () {
|
$scope.importByLine = function () {
|
||||||
@ -275,12 +261,11 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics', 'OpenSlides
|
|||||||
$scope.importcounter = 0;
|
$scope.importcounter = 0;
|
||||||
$scope.titleItems.forEach(function(title, index) {
|
$scope.titleItems.forEach(function(title, index) {
|
||||||
var item = {title: title};
|
var item = {title: title};
|
||||||
|
item.agenda_type = 1; // The new topic is not hidden.
|
||||||
|
item.agenda_weight = 1000 + index;
|
||||||
// TODO: create all items in bulk mode
|
// TODO: create all items in bulk mode
|
||||||
Topic.create(item).then(
|
Topic.create(item).then(
|
||||||
function(success) {
|
function(success) {
|
||||||
var changes = [{key: 'type', value: 1},
|
|
||||||
{key: 'weight', value: 1000 + index}];
|
|
||||||
AgendaUpdate.saveChanges(success.agenda_item_id, changes);
|
|
||||||
$scope.importcounter++;
|
$scope.importcounter++;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -363,13 +348,12 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics', 'OpenSlides
|
|||||||
$scope.csvImporting = true;
|
$scope.csvImporting = true;
|
||||||
angular.forEach($scope.items, function (item) {
|
angular.forEach($scope.items, function (item) {
|
||||||
if (item.selected && !item.importerror) {
|
if (item.selected && !item.importerror) {
|
||||||
|
item.agenda_type = item.type;
|
||||||
|
item.agenda_comment = item.comment;
|
||||||
|
item.agenda_duration = item.duration;
|
||||||
|
item.agenda_weight = item.weight;
|
||||||
Topic.create(item).then(
|
Topic.create(item).then(
|
||||||
function(success) {
|
function(success) {
|
||||||
var changes = [{key: 'duration', value: item.duration},
|
|
||||||
{key: 'comment', value: item.comment},
|
|
||||||
{key: 'type', value: item.type},
|
|
||||||
{key: 'weight', value: item.weight}];
|
|
||||||
AgendaUpdate.saveChanges(success.agenda_item_id, changes);
|
|
||||||
item.imported = true;
|
item.imported = true;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user