Merge pull request #2475 from normanjaeckel/FixBroadcast

Fixed broadcast. Fixed #2467.
This commit is contained in:
Oskar Hahn 2016-10-01 15:49:07 +02:00 committed by GitHub
commit c4f6477a4d
5 changed files with 57 additions and 16 deletions

View File

@ -101,7 +101,12 @@ class ConfigHandler:
raise ConfigError(_('public property has to be bool.')) raise ConfigError(_('public property has to be bool.'))
# Save the new value to the database. # Save the new value to the database.
ConfigStore.objects.update_or_create(key=key, defaults={'value': value}) try:
db_value = ConfigStore.objects.get(key=key)
except ConfigStore.DoesNotExist:
db_value = ConfigStore(key=key)
db_value.value = value
db_value.save(information={'changed_config': key})
# Call on_change callback. # Call on_change callback.
if config_variable.on_change: if config_variable.on_change:

View File

@ -3,8 +3,9 @@ from django.contrib.sessions.models import Session as DjangoSession
from django.db import models from django.db import models
from jsonfield import JSONField from jsonfield import JSONField
from openslides.utils.models import RESTModelMixin from ..utils.collection import CollectionElement
from openslides.utils.projector import ProjectorElement from ..utils.models import RESTModelMixin
from ..utils.projector import ProjectorElement
from .access_permissions import ( from .access_permissions import (
ChatMessageAccessPermissions, ChatMessageAccessPermissions,
@ -149,12 +150,13 @@ class Projector(RESTModelMixin, models.Model):
def get_collection_elements_required_for_this(self, collection_element): def get_collection_elements_required_for_this(self, collection_element):
""" """
Returns an iterable of CollectionElements that have to be sent to this Returns an iterable of CollectionElements that have to be sent to this
projector according to the given collection_element and information. projector according to the given collection_element.
""" """
from .config import config from .config import config
output = [] output = []
changed_fields = collection_element.information.get('changed_fields', []) changed_fields = collection_element.information.get('changed_fields', [])
if (collection_element.collection_string == self.get_collection_string() and if (collection_element.collection_string == self.get_collection_string() and
changed_fields and changed_fields and
'config' not in changed_fields): 'config' not in changed_fields):
@ -165,15 +167,29 @@ class Projector(RESTModelMixin, models.Model):
this_projector = collection_element.collection_string == self.get_collection_string() and collection_element.id == self.pk this_projector = collection_element.collection_string == self.get_collection_string() and collection_element.id == self.pk
collection_element.information['this_projector'] = this_projector collection_element.information['this_projector'] = this_projector
elements = {} elements = {}
# Build projector elements.
for element in ProjectorElement.get_all(): for element in ProjectorElement.get_all():
elements[element.name] = element elements[element.name] = element
# Iterate over all active projector elements.
for key, value in self.config.items(): for key, value in self.config.items():
element = elements.get(value['name']) element = elements.get(value['name'])
if element is not None: if element is not None:
output.extend(element.get_collection_elements_required_for_this(collection_element, value)) if collection_element.information.get('changed_config') == 'projector_broadcast':
# If config changed, send also this to the projector. # In case of broadcast we need full update.
output.extend(element.get_requirements_as_collection_elements(value))
else:
# In normal case we need all collections required by the element.
output.extend(element.get_collection_elements_required_for_this(collection_element, value))
# If config changed, send also this config to the projector.
if collection_element.collection_string == config.get_collection_string(): if collection_element.collection_string == config.get_collection_string():
output.append(collection_element) output.append(collection_element)
if collection_element.information.get('changed_config') == 'projector_broadcast':
# In case of broadcast we also need the projector himself.
output.append(CollectionElement.from_instance(self))
return output return output

View File

@ -36,7 +36,7 @@
<div class="details"> <div class="details">
<div class="projectorContainer"> <div class="projectorContainer">
<div ng-repeat="projector in projectors"> <div ng-repeat="projector in projectors | orderBy: 'id'">
<div> <div>
<a ui-sref="projector({id: projector.id})"> <a ui-sref="projector({id: projector.id})">
{{ projector.id }}: {{ projector.id }}:

View File

@ -49,7 +49,7 @@ def ws_add_projector(message, projector_id):
""" """
user = message.user user = message.user
# user is the django anonymous user. We have our own. # user is the django anonymous user. We have our own.
if user.is_anonymous and config['general_systen_enable_anonymous']: if user.is_anonymous and config['general_system_enable_anonymous']:
user = AnonymousUser() user = AnonymousUser()
if not user.has_perm('core.can_see_projector'): if not user.has_perm('core.can_see_projector'):
@ -64,21 +64,30 @@ def ws_add_projector(message, projector_id):
# informed if the data change. # informed if the data change.
Group('projector-{}'.format(projector_id)).add(message.reply_channel) Group('projector-{}'.format(projector_id)).add(message.reply_channel)
# Send all elements that are on the projector. # Then it is also added to the global projector group which is
# used for broadcasting data.
Group('projector-all').add(message.reply_channel)
# Now check whether broadcast is active at the moment. If yes,
# change the local projector variable.
if config['projector_broadcast'] > 0:
projector = Projector.objects.get(pk=config['projector_broadcast'])
# Collect all elements that are on the projector.
output = [] output = []
for requirement in projector.get_all_requirements(): for requirement in projector.get_all_requirements():
required_collection_element = CollectionElement.from_instance(requirement) required_collection_element = CollectionElement.from_instance(requirement)
output.append(required_collection_element.as_autoupdate_for_projector()) output.append(required_collection_element.as_autoupdate_for_projector())
# Send all config elements. # Collect all config elements.
collection = Collection(config.get_collection_string()) collection = Collection(config.get_collection_string())
output.extend(collection.as_autoupdate_for_projector()) output.extend(collection.as_autoupdate_for_projector())
# Send the projector instance. # Collect the projector instance.
collection_element = CollectionElement.from_instance(projector) collection_element = CollectionElement.from_instance(projector)
output.append(collection_element.as_autoupdate_for_projector()) output.append(collection_element.as_autoupdate_for_projector())
# Send all the data that was only collected before # Send all the data that were only collected before.
message.reply_channel.send({'text': json.dumps(output)}) message.reply_channel.send({'text': json.dumps(output)})
@ -101,16 +110,27 @@ def send_data(message):
output = [collection_element.as_autoupdate_for_user(user)] output = [collection_element.as_autoupdate_for_user(user)]
channel.send({'text': json.dumps(output)}) channel.send({'text': json.dumps(output)})
# Check whether broadcast is active at the moment and set the local
# projector queryset.
if config['projector_broadcast'] > 0:
queryset = Projector.objects.filter(pk=config['projector_broadcast'])
else:
queryset = Projector.objects.all()
# Loop over all projectors and send data that they need. # Loop over all projectors and send data that they need.
for projector in Projector.objects.all(): for projector in queryset:
if collection_element.is_deleted(): if collection_element.is_deleted():
output = [collection_element.as_autoupdate_for_projector()] output = [collection_element.as_autoupdate_for_projector()]
else: else:
collection_elements = projector.get_collection_elements_required_for_this(collection_element) collection_elements = projector.get_collection_elements_required_for_this(collection_element)
output = [collection_element.as_autoupdate_for_projector() for collection_element in collection_elements] output = [collection_element.as_autoupdate_for_projector() for collection_element in collection_elements]
if output: if output:
Group('projector-{}'.format(projector.pk)).send( if config['projector_broadcast'] > 0:
{'text': json.dumps(output)}) Group('projector-all').send(
{'text': json.dumps(output)})
else:
Group('projector-{}'.format(projector.pk)).send(
{'text': json.dumps(output)})
def inform_changed_data(instance, information=None): def inform_changed_data(instance, information=None):

View File

@ -85,7 +85,7 @@ class ProjectorElement(object, metaclass=SignalConnectMetaClass):
""" """
Returns a list of CollectionElements that have to be sent to every Returns a list of CollectionElements that have to be sent to every
projector that shows this projector element according to the given projector that shows this projector element according to the given
collection_element and information. collection_element.
Default: Returns only the collection_element if it belongs to the Default: Returns only the collection_element if it belongs to the
requirements but return all requirements if the projector changes. requirements but return all requirements if the projector changes.