diff --git a/openslides/agenda/api.py b/openslides/agenda/api.py index 1fa1a3243..e720b7164 100644 --- a/openslides/agenda/api.py +++ b/openslides/agenda/api.py @@ -22,10 +22,11 @@ def is_summary(): """ True, if a summery shall be displayed """ - if config_get('summary', False): + if config_get('agenda_summary', False): return True return False + def children_list(items): """ Return a list for items with all childitems in the right order. @@ -37,12 +38,14 @@ def children_list(items): l += children_list(item.children) return l + def gen_confirm_form_for_items(request, message, url, singleitem=None): if singleitem: messages.warning(request, '%s
' % (message, url, csrf(request)['csrf_token'], _("Yes"), _("No"))) else: messages.warning(request, '%s
' % (message, url, csrf(request)['csrf_token'], _("Yes"), _("Yes, with all child items."), _("No"))) + def del_confirm_form_for_items(request, object, name=None): if name is None: name = object diff --git a/openslides/agenda/forms.py b/openslides/agenda/forms.py index cf82e7bdc..62d2ba1e5 100644 --- a/openslides/agenda/forms.py +++ b/openslides/agenda/forms.py @@ -18,7 +18,8 @@ from openslides.agenda.models import Item class ItemFormText(ModelForm): error_css_class = 'error' required_css_class = 'required' - items = Item.objects.all().filter(parent=None).order_by('weight') + + items = Item.objects.all().filter(parent=None) parent = ModelChoiceField(queryset=items, label=_("Parent item"), required=False) class Meta: model = Item @@ -33,7 +34,7 @@ def genweightchoices(): class ItemOrderForm(Form): - weight = ChoiceField(choices=genweightchoices(), \ + weight = ChoiceField(choices=genweightchoices(), widget=Select(attrs={'class': 'menu-weight'}), label="") self = IntegerField(widget=HiddenInput(attrs={'class': 'menu-mlid'})) diff --git a/openslides/agenda/models.py b/openslides/agenda/models.py index 9d4aafb2f..6f8d28487 100644 --- a/openslides/agenda/models.py +++ b/openslides/agenda/models.py @@ -21,9 +21,6 @@ from django.utils.translation import ugettext as _ from projector.models import Slide from projector.api import register_slidemodel from system.api import config_set -from application.models import Application -from poll.models import Poll -from assignment.models import Assignment from agenda.api import is_summary @@ -31,15 +28,14 @@ class Item(models.Model, Slide): """ An Agenda Item """ + prefix = 'item' + title = models.CharField(max_length=100, verbose_name=_("Title")) text = models.TextField(null=True, blank=True, verbose_name=_("Text")) transcript = models.TextField(null=True, blank=True, verbose_name=_("Transcript")) closed = models.BooleanField(default=False, verbose_name=_("Closed")) weight = models.IntegerField(default=0, verbose_name=_("Weight")) parent = models.ForeignKey('self', blank=True, null=True) - hidden = models.BooleanField(default=False, - verbose_name=_("Hidden (visible for agenda manager only)")) - prefix = 'item' def slide(self): @@ -57,25 +53,15 @@ class Item(models.Model, Slide): data['template'] = 'projector/AgendaSummary.html' return data - @property - def active_parent(self): - """ - Return True if the item has a activ parent - """ - if get_active_slide(only_sid=True) in \ - [parent.id for parent in self.parents]: - return True - return False - def set_active(self, summary=False): """ Appoint this item as the active one. """ Slide.set_active(self) if summary: - config_set("summary", True) + config_set("agenda_summary", True) else: - config_set("summary", '') + config_set("agenda_summary", '') def set_closed(self, closed=True): """ @@ -97,12 +83,22 @@ class Item(models.Model, Slide): item = item.parent return parents + @property + def active_parent(self): + """ + Return True if the item has a active parent + """ + sid = get_active_slide(only_sid=True).split() + if len(sid) == 2 and sid[0] == self.prefix: + if sid[1] in [parent.id for parent in self.parents]: + return True + return False + @property def children(self): """ Return a list of all childitems from the next generation. The list - is ordert by weight. The childitems are not cast, so there are only - Item-objects and not Item-type objects. + is ordert by weight. """ return self.item_set.order_by("weight") @@ -123,22 +119,6 @@ class Item(models.Model, Slide): } return ItemOrderForm(initial=initial, prefix="i%d" % self.id) - def edit_form(self, post=None): - """ - Return the EditForm for this item. - """ - try: - return self._edit_form - except AttributeError: - from agenda.forms import MODELFORM - try: - form = MODELFORM[self.type] - except KeyError: - raise NameError(_("No Form for itemtype %s") % self.type) - - self._edit_form = form(post, instance=self) - return self._edit_form - @models.permalink def get_absolute_url(self, link='view'): """ @@ -154,43 +134,16 @@ class Item(models.Model, Slide): if link == 'delete': return ('item_delete', [str(self.id)]) - @property - def json(self): - """ - Return the model as jquery data - """ - return json.dumps({ - 'id': self.id, - 'active': self.active, - }) - def __unicode__(self): return self.title - def cast(self): - try: - return self.realobject - except AttributeError: - self.realobject = super(Item, self).cast() - return self.realobject - - @property - def type(self): - """ - Return the name of the class from this item - """ - try: - return self._type - except AttributeError: - self._type = self.cast().__class__.__name__ - return self._type - class Meta: permissions = ( ('can_see_agenda', "Can see agenda"), ('can_manage_agenda', "Can manage agenda"), ('can_see_projector', "Can see projector"), ) + ordering = ['weight'] ItemText = Item # ItemText is Depricated diff --git a/openslides/agenda/slides.py b/openslides/agenda/slides.py index e6a9c9706..de62981fe 100644 --- a/openslides/agenda/slides.py +++ b/openslides/agenda/slides.py @@ -5,8 +5,7 @@ from agenda.models import Item def agenda_show(): data = {} - items = Item.objects.filter(parent=None) \ - .filter(hidden=False).order_by('weight') + items = Item.objects.filter(parent=None) data['title'] = _("Agenda") data['items'] = items data['template'] = 'projector/AgendaSummary.html' diff --git a/openslides/agenda/urls.py b/openslides/agenda/urls.py index c8cc08ea2..3d8e66dda 100644 --- a/openslides/agenda/urls.py +++ b/openslides/agenda/urls.py @@ -13,39 +13,34 @@ from django.conf.urls.defaults import * urlpatterns = patterns('agenda.views', - url(r'^$', 'overview'), - - url(r'^agenda/$', 'overview', + url(r'^$', 'overview', name='item_overview'), - url(r'^agenda/(?P\d+)/$', 'view', + url(r'^(?P\d+)/$', 'view', name='item_view'), - url(r'^agenda/(?P\d+)/activate/$', 'set_active', + url(r'^(?P\d+)/activate/$', 'set_active', name='item_activate'), - url(r'^agenda/(?P\d+)/activate/summary/$', 'set_active', + url(r'^(?P\d+)/activate/summary/$', 'set_active', {'summary': True},\ name='item_activate_summary'), - url(r'^agenda/(?P\d+)/close/$', 'set_closed', {'closed': True}, + url(r'^(?P\d+)/close/$', 'set_closed', {'closed': True}, name='item_close'), - url(r'^agenda/(?P\d+)/open/$', 'set_closed', {'closed': False}, + url(r'^(?P\d+)/open/$', 'set_closed', {'closed': False}, name='item_open'), - url(r'^agenda/(?P\d+)/edit/$', 'edit', + url(r'^(?P\d+)/edit/$', 'edit', name='item_edit'), - url(r'^agenda/new/$', 'edit', - name='item_new_default'), - - url(r'^agenda/new$', 'edit', + url(r'^new$', 'edit', name='item_new'), - url(r'^agenda/(?P\d+)/del/$', 'delete', + url(r'^(?P\d+)/del/$', 'delete', name='item_delete'), - url(r'^agenda/print/$', 'print_agenda', + url(r'^print/$', 'print_agenda', name='print_agenda'), ) diff --git a/openslides/agenda/views.py b/openslides/agenda/views.py index 78b1abeb5..bad944b70 100644 --- a/openslides/agenda/views.py +++ b/openslides/agenda/views.py @@ -9,40 +9,36 @@ :copyright: 2011 by the OpenSlides team, see AUTHORS. :license: GNU GPL, see LICENSE for more details. """ -from datetime import datetime - -from django.shortcuts import render_to_response, redirect -from django.template import RequestContext +from django.shortcuts import redirect from django.core.urlresolvers import reverse from django.contrib import messages from django.utils.translation import ugettext as _ -from projector.api import get_active_slide +from projector.api import get_active_slide, set_active_slide + from agenda.models import Item from agenda.api import is_summary, children_list, \ del_confirm_form_for_items from agenda.forms import ItemOrderForm, ItemFormText -from application.models import Application -from assignment.models import Assignment -from poll.models import Poll + from system.api import config_set, config_get -from utils.template import render_block_to_string + from utils.utils import template, permission_required, \ del_confirm_form, ajax_request from utils.pdf import print_agenda -from poll.models import Poll, Option + +@permission_required('agenda.can_see_projector') +@template('projector/AgendaText.html') def view(request, item_id): """ Shows the Slide. """ - item = Item.objects.get(id=item_id) - return render_to_response('projector/AgendaText.html', - { - 'item': item, - 'ajax': 'off', - }, - context_instance=RequestContext(request)) + item = Item.objects.get(pk=item_id) + return { + 'item': item, + 'ajax': 'off', + } @permission_required('agenda.can_see_agenda') @@ -56,14 +52,15 @@ def overview(request): form = ItemOrderForm(request.POST, prefix="i%d" % item.id) if form.is_valid(): try: - item.parent = Item.objects.get( \ + item.parent = Item.objects.get( id=form.cleaned_data['parent']) except Item.DoesNotExist: item.parent = None item.weight = form.cleaned_data['weight'] item.save() - items = children_list(Item.objects.filter(parent=None).order_by('weight')) + items = children_list(Item.objects.filter(parent=None)) + if get_active_slide(only_sid=True) == 'agenda_show': overview = True else: @@ -74,7 +71,7 @@ def overview(request): 'summary': is_summary(), 'countdown_visible': config_get('countdown_visible'), 'countdown_time': config_get('agenda_countdown_time'), - } + } @permission_required('agenda.can_manage_agenda') @@ -83,17 +80,17 @@ def set_active(request, item_id, summary=False): Set an Item as the active one. """ if item_id == "0": - config_set("presentation", "agenda_show") + set_active_slide("agenda_show") else: try: - item = Item.objects.get(id=item_id) + item = Item.objects.get(pk=item_id) item.set_active(summary) except Item.DoesNotExist: messages.error(request, _('Item ID %d does not exist.') % int(item_id)) config_set("bigger", 100) config_set("up", 0) if request.is_ajax(): - return ajax_request({'active': item_id}) + return ajax_request({'active': item_id, 'summary': summary}) return redirect(reverse('item_overview')) @@ -104,7 +101,7 @@ def set_closed(request, item_id, closed=True): Close or open an Item. """ try: - item = Item.objects.get(id=item_id) + item = Item.objects.get(pk=item_id) item.set_closed(closed) except Item.DoesNotExist: messages.error(request, _('Item ID %d does not exist.') % int(item_id)) @@ -152,8 +149,10 @@ def edit(request, item_id=None): messages.error(request, _('Please check the form for errors.')) else: form = ItemFormText(instance=item) - return { 'form': form, - 'item': item } + return { + 'form': form, + 'item': item, + } @permission_required('agenda.can_manage_agenda') @@ -161,7 +160,12 @@ def delete(request, item_id): """ Delete an Item. """ - item = Item.objects.get(id=item_id).cast() + try: + item = Item.objects.get(pk=item_id) + except Item.DoesNotExist: + messages.error(request, _('Item ID %d does not exist.') % int(item_id)) + return redirect(reverse('item_overview')) + if request.method == 'POST': if 'all' in request.POST: item.delete() diff --git a/openslides/projector/api.py b/openslides/projector/api.py index 04bd8477a..84544188d 100644 --- a/openslides/projector/api.py +++ b/openslides/projector/api.py @@ -31,6 +31,10 @@ def get_active_slide(only_sid=False): return get_slide_from_sid(sid) +def set_active_slide(sid): + config_set("presentation", sid) + + def register_slidemodel(model): SLIDE[model.prefix] = model @@ -41,37 +45,37 @@ def register_slidefunc(name, func): SLIDE[name] = func -def assignment_votes(item): - votes = [] - if item.type == "ItemAssignment": - assignment = item.cast().assignment - publish_winner_results_only = config_get("assignment_publish_winner_results_only") - # list of votes - votes = [] - for candidate in assignment.candidates: - tmplist = [[candidate, assignment.is_elected(candidate)], []] - for poll in assignment.poll_set.all(): - if poll.published: - if candidate in poll.options_values: - # check config option 'publish_winner_results_only' - if not publish_winner_results_only \ - or publish_winner_results_only and assignment.is_elected(candidate): - option = Option.objects.filter(poll=poll).filter(user=candidate)[0] - if poll.optiondecision: - tmplist[1].append([option.yes, option.no, option.undesided]) - else: - tmplist[1].append(option.yes) - else: - tmplist[1].append("") - else: - tmplist[1].append("-") - votes.append(tmplist) - return votes - - -def assignment_polls(item): - polls = [] - if item.type == "ItemAssignment": - for poll in item.cast().assignment.poll_set.filter(assignment=item.cast().assignment): - polls.append(poll) - return polls +## def assignment_votes(item): + ## votes = [] + ## if item.type == "ItemAssignment": + ## assignment = item.cast().assignment + ## publish_winner_results_only = config_get("assignment_publish_winner_results_only") + ## # list of votes + ## votes = [] + ## for candidate in assignment.candidates: + ## tmplist = [[candidate, assignment.is_elected(candidate)], []] + ## for poll in assignment.poll_set.all(): + ## if poll.published: + ## if candidate in poll.options_values: + ## # check config option 'publish_winner_results_only' + ## if not publish_winner_results_only \ + ## or publish_winner_results_only and assignment.is_elected(candidate): + ## option = Option.objects.filter(poll=poll).filter(user=candidate)[0] + ## if poll.optiondecision: + ## tmplist[1].append([option.yes, option.no, option.undesided]) + ## else: + ## tmplist[1].append(option.yes) + ## else: + ## tmplist[1].append("") + ## else: + ## tmplist[1].append("-") + ## votes.append(tmplist) + ## return votes +## +## +## def assignment_polls(item): + ## polls = [] + ## if item.type == "ItemAssignment": + ## for poll in item.cast().assignment.poll_set.filter(assignment=item.cast().assignment): + ## polls.append(poll) + ## return polls diff --git a/openslides/urls.py b/openslides/urls.py index 77ed98e59..b902c5020 100644 --- a/openslides/urls.py +++ b/openslides/urls.py @@ -19,11 +19,12 @@ handler500 = 'openslides.utils.views.server_error' urlpatterns = patterns('', (r'^admin/', include(admin.site.urls)), - (r'', include('openslides.agenda.urls')), - (r'', include('openslides.application.urls')), - (r'', include('openslides.participant.urls')), - (r'', include('openslides.assignment.urls')), - (r'', include('openslides.system.urls')), + (r'^$', 'agenda.views.overview'), + (r'agenda', include('agenda.urls')), + (r'', include('application.urls')), + (r'', include('participant.urls')), + (r'', include('assignment.urls')), + (r'', include('system.urls')), (r'projector', include('projector.urls')), (r'^static/(?P.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_DOC_ROOT}), (r'^i18n/', include('django.conf.urls.i18n')), diff --git a/openslides/utils/utils.py b/openslides/utils/utils.py index 1a898499d..43de566f2 100644 --- a/openslides/utils/utils.py +++ b/openslides/utils/utils.py @@ -34,15 +34,18 @@ def revision(request): def gen_confirm_form(request, message, url): messages.warning(request, '%s
' % (message, url, csrf(request)['csrf_token'], _("Yes"), _("No"))) + def del_confirm_form(request, object, name=None): if name is None: name = object gen_confirm_form(request, _('Do you really want to delete %s?') % name, object.get_absolute_url('delete')) + def render_response(req, *args, **kwargs): kwargs['context_instance'] = RequestContext(req) return render_to_response(*args, **kwargs) + def template(template_name): def renderer(func): def wrapper(request, *args, **kw): @@ -72,14 +75,17 @@ def permission_required(perm, login_url=None): return wrapper return renderer + def render_to_forbitten(request, error=_("Sorry, you have no rights to see this page.")): return HttpResponseForbidden(render_to_string('403.html', {'error': error}, context_instance=RequestContext(request))) + def delete_default_permissions(): for p in Permission.objects.all(): if p.codename.startswith('add') or p.codename.startswith('delete') or p.codename.startswith('change'): p.delete() + def ajax_request(data): """ generates a HTTPResponse-Object with json-Data for a @@ -87,6 +93,7 @@ def ajax_request(data): """ return HttpResponse(json.dumps(data)) + def _propper_unicode(text): res = '' if not isinstance(text, unicode):