Merge pull request #920 from normanjaeckel/CountdownAndAgenda

Countdown and agenda
This commit is contained in:
Oskar Hahn 2013-10-19 22:19:26 -07:00
commit c399eea2dd
5 changed files with 84 additions and 29 deletions

View File

@ -21,8 +21,10 @@ from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop from django.utils.translation import ugettext_lazy, ugettext_noop
from mptt.models import MPTTModel, TreeForeignKey from mptt.models import MPTTModel, TreeForeignKey
from openslides.projector.api import (get_active_slide, update_projector, from openslides.config.api import config
update_projector_overlay) from openslides.projector.api import (get_active_slide, reset_countdown,
start_countdown, stop_countdown,
update_projector, update_projector_overlay)
from openslides.projector.models import SlideMixin from openslides.projector.models import SlideMixin
from openslides.utils.exceptions import OpenSlidesError from openslides.utils.exceptions import OpenSlidesError
from openslides.utils.person.models import PersonField from openslides.utils.person.models import PersonField
@ -378,6 +380,10 @@ class Speaker(models.Model):
self.weight = None self.weight = None
self.begin_time = datetime.now() self.begin_time = datetime.now()
self.save() self.save()
# start countdown
if config['agenda_couple_countdown_and_speakers']:
reset_countdown()
start_countdown()
def end_speach(self): def end_speach(self):
""" """
@ -385,3 +391,6 @@ class Speaker(models.Model):
""" """
self.end_time = datetime.now() self.end_time = datetime.now()
self.save() self.save()
# stop countdown
if config['agenda_couple_countdown_and_speakers']:
stop_countdown()

View File

@ -62,6 +62,14 @@ def setup_agenda_config_page(sender, **kwargs):
min_value=0, min_value=0,
label=ugettext_lazy('Number of last speakers to be shown on the projector'))) label=ugettext_lazy('Number of last speakers to be shown on the projector')))
agenda_couple_countdown_and_speakers = ConfigVariable(
name='agenda_couple_countdown_and_speakers',
default_value=False,
form_field=forms.BooleanField(
label=ugettext_lazy('Couple countdown with the list of speakers'),
help_text=ugettext_lazy('[Begin speach] starts the countdown, [End speach] stops the countdown.'),
required=False))
extra_stylefiles = ['styles/timepicker.css', 'styles/jquery-ui/jquery-ui.custom.min.css'] extra_stylefiles = ['styles/timepicker.css', 'styles/jquery-ui/jquery-ui.custom.min.css']
extra_javascript = ['javascript/jquery-ui.custom.min.js', extra_javascript = ['javascript/jquery-ui.custom.min.js',
'javascript/jquery-ui-timepicker-addon.min.js', 'javascript/jquery-ui-timepicker-addon.min.js',
@ -72,7 +80,9 @@ def setup_agenda_config_page(sender, **kwargs):
url='agenda', url='agenda',
required_permission='config.can_manage', required_permission='config.can_manage',
weight=20, weight=20,
variables=(agenda_start_event_date_time, agenda_show_last_speakers), variables=(agenda_start_event_date_time,
agenda_show_last_speakers,
agenda_couple_countdown_and_speakers),
extra_context={'extra_stylefiles': extra_stylefiles, extra_context={'extra_stylefiles': extra_stylefiles,
'extra_javascript': extra_javascript}) 'extra_javascript': extra_javascript})

View File

@ -11,6 +11,7 @@
""" """
import json import json
from time import time
from django.conf import settings from django.conf import settings
from django.template.loader import render_to_string from django.template.loader import render_to_string
@ -208,3 +209,39 @@ def get_all_widgets(request, session=False):
if not session or session_widgets.get(widget.get_name(), True): if not session or session_widgets.get(widget.get_name(), True):
widgets[widget.get_name()] = widget widgets[widget.get_name()] = widget
return widgets return widgets
def start_countdown():
"""
Starts the countdown
"""
# if we had stopped the countdown resume were we left of
if config['countdown_state'] == 'paused':
start_stamp = config['countdown_start_stamp']
pause_stamp = config['countdown_pause_stamp']
now = time()
config['countdown_start_stamp'] = now - \
(pause_stamp - start_stamp)
else:
config['countdown_start_stamp'] = time()
config['countdown_state'] = 'active'
config['countdown_pause_stamp'] = 0
def stop_countdown():
"""
Stops the countdown
"""
if config['countdown_state'] == 'active':
config['countdown_state'] = 'paused'
config['countdown_pause_stamp'] = time()
def reset_countdown():
"""
Resets the countdown
"""
config['countdown_start_stamp'] = time()
config['countdown_pause_stamp'] = 0
config['countdown_state'] = 'inactive'

View File

@ -10,8 +10,6 @@
:license: GNU GPL, see LICENSE for more details. :license: GNU GPL, see LICENSE for more details.
""" """
from time import time
from django.contrib import messages from django.contrib import messages
from django.core.context_processors import csrf from django.core.context_processors import csrf
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
@ -26,8 +24,8 @@ from openslides.utils.views import (AjaxMixin, CreateView, DeleteView,
from .api import (get_active_slide, get_all_widgets, get_overlays, from .api import (get_active_slide, get_all_widgets, get_overlays,
get_projector_content, get_projector_overlays, get_projector_content, get_projector_overlays,
get_projector_overlays_js, set_active_slide, get_projector_overlays_js, reset_countdown, set_active_slide,
update_projector_overlay) start_countdown, stop_countdown, update_projector_overlay)
from .forms import SelectWidgetsForm from .forms import SelectWidgetsForm
from .models import ProjectorSlide from .models import ProjectorSlide
from .projector import Widget from .projector import Widget
@ -169,31 +167,12 @@ class CountdownEdit(RedirectView):
def pre_redirect(self, request, *args, **kwargs): def pre_redirect(self, request, *args, **kwargs):
command = kwargs['command'] command = kwargs['command']
# countdown_state is one of 'inactive', 'paused' and 'active', 'expired'
if command in ['reset', 'start', 'stop']:
config['countdown_time'] = config['countdown_time']
if command == 'reset': if command == 'reset':
config['countdown_start_stamp'] = time() reset_countdown()
config['countdown_pause_stamp'] = 0
config['countdown_state'] = 'inactive'
elif command == 'start': elif command == 'start':
# if we had stopped the countdown resume were we left of start_countdown()
if config['countdown_state'] == 'paused':
start_stamp = config['countdown_start_stamp']
pause_stamp = config['countdown_pause_stamp']
now = time()
config['countdown_start_stamp'] = now - \
(pause_stamp - start_stamp)
else:
config['countdown_start_stamp'] = time()
config['countdown_state'] = 'active'
config['countdown_pause_stamp'] = 0
elif command == 'stop': elif command == 'stop':
if config['countdown_state'] == 'active': stop_countdown()
config['countdown_pause_stamp'] = time()
config['countdown_state'] = 'paused'
elif command == 'set-default': elif command == 'set-default':
try: try:
config['countdown_time'] = \ config['countdown_time'] = \

View File

@ -10,6 +10,7 @@
from django.test.client import Client from django.test.client import Client
from openslides.agenda.models import Item, Speaker from openslides.agenda.models import Item, Speaker
from openslides.config.api import config
from openslides.participant.models import Group, User from openslides.participant.models import Group, User
from openslides.projector.api import set_active_slide from openslides.projector.api import set_active_slide
from openslides.utils.exceptions import OpenSlidesError from openslides.utils.exceptions import OpenSlidesError
@ -74,6 +75,25 @@ class ListOfSpeakerModelTests(TestCase):
self.assertIsNotNone(Speaker.objects.get(person=self.speaker1, item=self.item1).end_time) self.assertIsNotNone(Speaker.objects.get(person=self.speaker1, item=self.item1).end_time)
self.assertIsNotNone(speaker2_item1.begin_time) self.assertIsNotNone(speaker2_item1.begin_time)
def test_speach_coupled_with_countdown(self):
config['agenda_couple_countdown_and_speakers'] = True
self.assertTrue(config['countdown_state'] == 'inactive')
speaker1_item1 = Speaker.objects.add(self.speaker1, self.item1)
speaker1_item1.begin_speach()
self.assertTrue(config['countdown_state'] == 'active')
speaker1_item1.end_speach()
self.assertTrue(config['countdown_state'] == 'paused')
def test_begin_speach_not_coupled_with_countdown(self):
config['agenda_couple_countdown_and_speakers'] = False
self.assertTrue(config['countdown_state'] == 'inactive')
speaker1_item1 = Speaker.objects.add(self.speaker1, self.item1)
speaker1_item1.begin_speach()
self.assertTrue(config['countdown_state'] == 'inactive')
config['countdown_state'] = 'active'
speaker1_item1.end_speach()
self.assertTrue(config['countdown_state'] == 'active')
class SpeakerViewTestCase(TestCase): class SpeakerViewTestCase(TestCase):
def setUp(self): def setUp(self):