1
AUTHORS
@ -7,3 +7,4 @@ Authors of OpenSlides in chronological order of first contribution:
|
||||
Andy Kittner <andkit@gmx.net>
|
||||
Moira Brülisauer <moira.bruelisauer@piratenpartei.ch> (French translation)
|
||||
Alexis Roussel <alexis.roussel@partipirate.ch> (French translation)
|
||||
Stefan Frauenknecht <stefan@frauenknecht.net>
|
||||
|
4
THANKS
@ -8,9 +8,13 @@ OpenSlides uses parts of the following projects:
|
||||
|
||||
* jQuery
|
||||
<http://www.jquery.com/>
|
||||
and some addons: cookie, form, once, templating
|
||||
|
||||
* jQuery UI
|
||||
<http://jqueryui.com/>
|
||||
custom ui components: core, widget, mouse, sortable, datepicker, slider
|
||||
with css theme 'smoothness'
|
||||
and some addons: slider access, timepicker
|
||||
|
||||
* Twitter Bootstrap
|
||||
<http://twitter.github.com/bootstrap/>
|
||||
|
@ -10,14 +10,14 @@
|
||||
:license: GNU GPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from mptt.forms import TreeNodeChoiceField
|
||||
|
||||
from openslides.utils.forms import CssClassMixin
|
||||
|
||||
from openslides.agenda.models import Item
|
||||
from .models import Item
|
||||
|
||||
|
||||
class ItemForm(forms.ModelForm, CssClassMixin):
|
||||
@ -27,6 +27,13 @@ class ItemForm(forms.ModelForm, CssClassMixin):
|
||||
parent = TreeNodeChoiceField(
|
||||
queryset=Item.objects.all(), label=_("Parent item"), required=False)
|
||||
|
||||
duration = forms.RegexField(
|
||||
regex=re.compile('[0-99]:[0-5][0-9]'),
|
||||
error_message=_("Invalid format. Hours from 0 to 99 and minutes from 00 to 59"),
|
||||
max_length=5,
|
||||
required=False,
|
||||
label=_("Duration (hh:mm)"))
|
||||
|
||||
class Meta:
|
||||
model = Item
|
||||
exclude = ('closed', 'weight', 'related_sid')
|
||||
@ -45,11 +52,15 @@ class ItemOrderForm(forms.Form, CssClassMixin):
|
||||
"""
|
||||
weight = forms.ChoiceField(
|
||||
choices=gen_weight_choices(),
|
||||
widget=forms.Select(attrs={'class': 'menu-weight'}),
|
||||
)
|
||||
widget=forms.Select(attrs={'class': 'menu-weight'}))
|
||||
self = forms.IntegerField(
|
||||
widget=forms.HiddenInput(attrs={'class': 'menu-mlid'}),
|
||||
)
|
||||
widget=forms.HiddenInput(attrs={'class': 'menu-mlid'}))
|
||||
parent = forms.IntegerField(
|
||||
widget=forms.HiddenInput(attrs={'class': 'menu-plid'}),
|
||||
)
|
||||
widget=forms.HiddenInput(attrs={'class': 'menu-plid'}))
|
||||
|
||||
|
||||
class ConfigForm(CssClassMixin, forms.Form):
|
||||
agenda_start_event_date_time = forms.CharField(
|
||||
widget=forms.DateTimeInput(format='%d.%m.%Y %H:%M'),
|
||||
required=False,
|
||||
label=_("Begin of event"))
|
||||
|
@ -20,7 +20,7 @@ from openslides.config.models import config
|
||||
from openslides.projector.projector import SlideMixin
|
||||
from openslides.projector.api import (
|
||||
register_slidemodel, get_slide_from_sid, register_slidefunc)
|
||||
from openslides.agenda.slides import agenda_show
|
||||
from .slides import agenda_show
|
||||
|
||||
|
||||
class Item(MPTTModel, SlideMixin):
|
||||
@ -31,6 +31,13 @@ class Item(MPTTModel, SlideMixin):
|
||||
"""
|
||||
prefix = 'item'
|
||||
|
||||
AGENDA_ITEM = 1
|
||||
ORGANIZATIONAL_ITEM = 2
|
||||
|
||||
ITEM_TYPE = (
|
||||
(AGENDA_ITEM, _('Agenda item')),
|
||||
(ORGANIZATIONAL_ITEM, _('Organizational item')))
|
||||
|
||||
title = models.CharField(null=True, max_length=255, verbose_name=_("Title"))
|
||||
text = models.TextField(null=True, blank=True, verbose_name=_("Text"))
|
||||
comment = models.TextField(null=True, blank=True, verbose_name=_("Comment"))
|
||||
@ -38,6 +45,8 @@ class Item(MPTTModel, SlideMixin):
|
||||
weight = models.IntegerField(default=0, verbose_name=_("Weight"))
|
||||
parent = TreeForeignKey('self', null=True, blank=True,
|
||||
related_name='children')
|
||||
type = models.IntegerField(max_length=1, choices=ITEM_TYPE, default=AGENDA_ITEM, verbose_name=_("Type"))
|
||||
duration = models.CharField(null=True, blank=True, max_length=5, verbose_name=_("Duration (hh:mm)"))
|
||||
related_sid = models.CharField(null=True, blank=True, max_length=63)
|
||||
|
||||
def get_related_slide(self):
|
||||
@ -170,6 +179,7 @@ class Item(MPTTModel, SlideMixin):
|
||||
permissions = (
|
||||
('can_see_agenda', ugettext_noop("Can see agenda")),
|
||||
('can_manage_agenda', ugettext_noop("Can manage agenda")),
|
||||
('can_see_orga_items', ugettext_noop("Can see orga items and time scheduling of agenda")),
|
||||
)
|
||||
|
||||
class MPTTMeta:
|
||||
|
@ -16,7 +16,7 @@ from django.utils.translation import ugettext as _
|
||||
def agenda_show():
|
||||
from openslides.agenda.models import Item
|
||||
data = {}
|
||||
items = Item.objects.filter(parent=None)
|
||||
items = Item.objects.filter(parent=None, type__exact=Item.AGENDA_ITEM)
|
||||
data['title'] = _("Agenda")
|
||||
data['items'] = items
|
||||
data['template'] = 'projector/AgendaSummary.html'
|
||||
|
89
openslides/agenda/static/javascript/jquery-ui-sliderAccess.js
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* jQuery UI Slider Access
|
||||
* By: Trent Richardson [http://trentrichardson.com]
|
||||
* Version 0.3
|
||||
* Last Modified: 10/20/2012
|
||||
*
|
||||
* Copyright 2011 Trent Richardson
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
* http://trentrichardson.com/Impromptu/GPL-LICENSE.txt
|
||||
* http://trentrichardson.com/Impromptu/MIT-LICENSE.txt
|
||||
*
|
||||
*/
|
||||
(function($){
|
||||
|
||||
$.fn.extend({
|
||||
sliderAccess: function(options){
|
||||
options = options || {};
|
||||
options.touchonly = options.touchonly !== undefined? options.touchonly : true; // by default only show it if touch device
|
||||
|
||||
if(options.touchonly === true && !("ontouchend" in document))
|
||||
return $(this);
|
||||
|
||||
return $(this).each(function(i,obj){
|
||||
var $t = $(this),
|
||||
o = $.extend({},{
|
||||
where: 'after',
|
||||
step: $t.slider('option','step'),
|
||||
upIcon: 'ui-icon-plus',
|
||||
downIcon: 'ui-icon-minus',
|
||||
text: false,
|
||||
upText: '+',
|
||||
downText: '-',
|
||||
buttonset: true,
|
||||
buttonsetTag: 'span',
|
||||
isRTL: false
|
||||
}, options),
|
||||
$buttons = $('<'+ o.buttonsetTag +' class="ui-slider-access">'+
|
||||
'<button data-icon="'+ o.downIcon +'" data-step="'+ (o.isRTL? o.step : o.step*-1) +'">'+ o.downText +'</button>'+
|
||||
'<button data-icon="'+ o.upIcon +'" data-step="'+ (o.isRTL? o.step*-1 : o.step) +'">'+ o.upText +'</button>'+
|
||||
'</'+ o.buttonsetTag +'>');
|
||||
|
||||
$buttons.children('button').each(function(j, jobj){
|
||||
var $jt = $(this);
|
||||
$jt.button({
|
||||
text: o.text,
|
||||
icons: { primary: $jt.data('icon') }
|
||||
})
|
||||
.click(function(e){
|
||||
var step = $jt.data('step'),
|
||||
curr = $t.slider('value'),
|
||||
newval = curr += step*1,
|
||||
minval = $t.slider('option','min'),
|
||||
maxval = $t.slider('option','max'),
|
||||
slidee = $t.slider("option", "slide") || function(){},
|
||||
stope = $t.slider("option", "stop") || function(){};
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if(newval < minval || newval > maxval)
|
||||
return;
|
||||
|
||||
$t.slider('value', newval);
|
||||
|
||||
slidee.call($t, null, { value: newval });
|
||||
stope.call($t, null, { value: newval });
|
||||
});
|
||||
});
|
||||
|
||||
// before or after
|
||||
$t[o.where]($buttons);
|
||||
|
||||
if(o.buttonset){
|
||||
$buttons.removeClass('ui-corner-right').removeClass('ui-corner-left').buttonset();
|
||||
$buttons.eq(0).addClass('ui-corner-left');
|
||||
$buttons.eq(1).addClass('ui-corner-right');
|
||||
}
|
||||
|
||||
// adjust the width so we don't break the original layout
|
||||
var bOuterWidth = $buttons.css({
|
||||
marginLeft: ((o.where == 'after' && !o.isRTL) || (o.where == 'before' && o.isRTL)? 10:0),
|
||||
marginRight: ((o.where == 'before' && !o.isRTL) || (o.where == 'after' && o.isRTL)? 10:0)
|
||||
}).outerWidth(true) + 5;
|
||||
var tOuterWidth = $t.outerWidth(true);
|
||||
$t.css('display','inline-block').width(tOuterWidth-bOuterWidth);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
1919
openslides/agenda/static/javascript/jquery-ui-timepicker-addon.js
vendored
Normal file
@ -9,3 +9,15 @@ tr.topline td {
|
||||
border-bottom: 1px solid #333333;
|
||||
background-color: #CDCDCD;
|
||||
}
|
||||
|
||||
table#agendatime {
|
||||
float: right;
|
||||
width: auto;
|
||||
margin-bottom: 1em;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
table#agendatime td {
|
||||
padding: 3px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
46
openslides/agenda/static/styles/timepicker.css
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* OpenSlides timepicker style
|
||||
*
|
||||
* :copyright: 2011, 2012 by OpenSlides team, see AUTHORS.
|
||||
* :license: GNU GPL, see LICENSE for more details.
|
||||
*/
|
||||
|
||||
.ui-timepicker-div .ui-widget-header {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.ui-timepicker-div dl {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ui-timepicker-div dl dt {
|
||||
height: 25px;
|
||||
margin-bottom: -25px;
|
||||
}
|
||||
|
||||
.ui-timepicker-div dl dd {
|
||||
margin: 0 10px 10px 65px;
|
||||
}
|
||||
|
||||
.ui-timepicker-div td {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.ui-tpicker-grid-label {
|
||||
background: none;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ui-timepicker-rtl{
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.ui-timepicker-rtl dl {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ui-timepicker-rtl dl dd {
|
||||
margin: 0 65px 10px 10px;
|
||||
}
|
@ -1,24 +1,85 @@
|
||||
{% extends "config/base_config.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block header %}
|
||||
<link type="text/css" rel="stylesheet" media="all" href="{% static 'styles/jquery-ui/jquery-ui.custom.min.css' %}" />
|
||||
<link type="text/css" rel="stylesheet" media="all" href="{% static 'styles/timepicker.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
<script type="text/javascript" src="{% static 'javascript/jquery-ui.custom.min.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'javascript/jquery-ui-timepicker-addon.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'javascript/jquery-ui-sliderAccess.js' %}"></script>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$.datepicker.regional['{{ LANGUAGE_CODE }}'] = {
|
||||
prevText: 'previous month',
|
||||
nextText: 'next month',
|
||||
monthNames: [
|
||||
'{% trans 'January' %}', '{% trans 'February' %}', '{% trans 'March' %}',
|
||||
'{% trans 'April' %}', '{% trans 'May' %}', '{% trans 'June' %}',
|
||||
'{% trans 'July' %}', '{% trans 'August' %}', '{% trans 'September' %}',
|
||||
'{% trans 'October' %}', '{% trans 'November' %}', '{% trans 'December' %}'
|
||||
],
|
||||
monthNamesShort: [
|
||||
'{% trans 'Jan' %}', '{% trans 'Feb' %}', '{% trans 'Mar' %}',
|
||||
'{% trans 'Apr' %}', '{% trans 'May' %}', '{% trans 'Jun' %}',
|
||||
'{% trans 'Jul' %}', '{% trans 'Aug' %}', '{% trans 'Sep' %}',
|
||||
'{% trans 'Oct' %}', '{% trans 'Nov' %}', '{% trans 'Dec' %}'
|
||||
],
|
||||
dayNames: [
|
||||
'{% trans 'Sunday' %}', '{% trans 'Monday' %}', '{% trans 'Tuesdey' %}', '{% trans 'Wednesday' %}',
|
||||
'{% trans 'Thursday' %}', '{% trans 'Friday' %}', '{% trans 'Saturday' %}'
|
||||
],
|
||||
dayNamesMin: [
|
||||
'{% trans 'Su' %}', '{% trans 'Mo' %}', '{% trans 'Tu' %}', '{% trans 'We' %}',
|
||||
'{% trans 'Th' %}', '{% trans 'Fr' %}', '{% trans 'Sa' %}'
|
||||
],
|
||||
dayNamesShort: [
|
||||
'{% trans 'Su' %}', '{% trans 'Mo' %}', '{% trans 'Tu' %}', '{% trans 'We' %}',
|
||||
'{% trans 'Th' %}', '{% trans 'Fr' %}', '{% trans 'Sa' %}'
|
||||
],
|
||||
dateFormat: 'dd.mm.yy', firstDay: 1, isRTL: false
|
||||
};
|
||||
|
||||
$.datepicker.setDefaults($.datepicker.regional['{{ LANGUAGE_CODE }}']);
|
||||
|
||||
$("#id_agenda_start_event_date_time").datetimepicker (
|
||||
{
|
||||
hour: 12,
|
||||
timeFormat: "HH:mm",
|
||||
timeText: '{% trans 'Time' %}',
|
||||
hourText: '{% trans 'Hour' %}',
|
||||
minuteText: '{% trans 'Minute' %}',
|
||||
currentText: '{% trans 'current time' %}',
|
||||
closeText: '{% trans 'close' %}'
|
||||
}
|
||||
);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}{{ block.super }} – {% trans "Agenda settings" %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<h1>{% trans "Configuration" %}: {% trans "Agenda" %}
|
||||
<h1>
|
||||
{% trans "Configuration" %}
|
||||
<small>{% trans "Agenda" %}</small>
|
||||
{% block config_submenu %}{{ block.super }}{% endblock %}
|
||||
</h1>
|
||||
<form action="" method="post">{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
{% include "form.html" %}
|
||||
<p>
|
||||
<button class="button" type="submit">
|
||||
<span class="icon ok">{% trans 'Save' %}</span>
|
||||
</button>
|
||||
<a href="{% url 'config_agenda' %}">
|
||||
<button class="button" type="button" onclick="window.location='{% url 'config_agenda' %}'">
|
||||
<span class="icon cancel">{% trans 'Cancel' %}</span>
|
||||
</button>
|
||||
{% include "formbuttons_save.html" %}
|
||||
<a href="{% url 'config_agenda' %}" class="btn">
|
||||
{% trans 'Cancel' %}
|
||||
</a>
|
||||
</p>
|
||||
<small>* {% trans "required" %}</small>
|
||||
</form>
|
||||
{% endblock %}
|
@ -20,7 +20,7 @@
|
||||
{% if perms.agenda.can_manage_agenda %}
|
||||
<div class="dragcell"></div>
|
||||
{% endif %}
|
||||
<a href="{% model_url item 'view' %}">{{ item }}</a>
|
||||
<a href="{% model_url item 'view' %}">{% if item.type == item.ORGANIZATIONAL_ITEM %}<i>[{% endif %}{{ item }}{% if item.type == item.ORGANIZATIONAL_ITEM %}]</i>{% endif %}</a>
|
||||
{{ item.get_title_supplement|safe }}
|
||||
</td>
|
||||
{% if perms.agenda.can_manage_agenda %}
|
||||
@ -28,6 +28,13 @@
|
||||
{{ item.comment|first_line }}
|
||||
</td>
|
||||
{% endif %}
|
||||
{% if perms.agenda.can_see_orga_items %}
|
||||
<td>
|
||||
{% if item.duration %}
|
||||
{{ item.duration }}h <a {% if item.tooltip %}rel="tooltip" data-original-title="{% trans 'End' %}: {{ item.tooltip|date:"DATETIME_FORMAT" }}"{% endif %}><i class="icon-clock"></i></a>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
{% if perms.agenda.can_manage_agenda or perms.projector.can_manage_projector %}
|
||||
<td>
|
||||
<span style="width: 1px; white-space: nowrap;">
|
||||
|
@ -61,6 +61,20 @@
|
||||
</small>
|
||||
</h1>
|
||||
|
||||
{% if perms.agenda.can_see_orga_items %}
|
||||
{% if start and end %}
|
||||
<table id="agendatime" class="table table-bordered">
|
||||
<tr>
|
||||
<td>{% trans "Start of event" %}:</td>
|
||||
<td>{{ start|date:"DATETIME_FORMAT" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans "Estimated end" %}:</td>
|
||||
<td>{{ end|date:"DATETIME_FORMAT" }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" id="hide_closed_items"> {% trans "Hide closed items" %}
|
||||
</label>
|
||||
@ -75,6 +89,9 @@
|
||||
{% if perms.agenda.can_manage_agenda %}
|
||||
<th width="200" class="optional">{% trans "Comment" %}</th>
|
||||
{% endif %}
|
||||
{% if perms.agenda.can_see_orga_items %}
|
||||
<th width="50">{% trans "Duration" %}</th>
|
||||
{% endif %}
|
||||
{% if perms.agenda.can_manage_agenda or perms.projector.can_manage_projector %}
|
||||
<th class="mini_width">{% trans "Actions" %}</th>
|
||||
{% endif %}
|
||||
@ -90,6 +107,9 @@
|
||||
{% if perms.agenda.can_manage_agenda %}
|
||||
<td class="optional"></td>
|
||||
{% endif %}
|
||||
{% if perms.agenda.can_see_orga_items %}
|
||||
<td>{{ duration }}h</td>
|
||||
{% endif %}
|
||||
{% if perms.agenda.can_manage_agenda or perms.projector.can_manage_projector %}
|
||||
<td>
|
||||
{% if perms.projector.can_manage_projector %}
|
||||
@ -110,7 +130,7 @@
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="4"><i>{% trans "No items available." %}</i></td>
|
||||
<td colspan="5"><i>{% trans "No items available." %}</i></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</table>
|
||||
|
@ -33,7 +33,7 @@
|
||||
{% for p in item.get_ancestors %}
|
||||
<span class="indentation"></span>
|
||||
{% endfor %}
|
||||
<a href="{% model_url item 'view' %}">{{ item }}</a>
|
||||
<a href="{% model_url item 'view' %}">{% if item.type == item.ORGANIZATIONAL_ITEM %}<i>[{% endif %}{{ item }}{% if item.type == item.ORGANIZATIONAL_ITEM %}]</i>{% endif %}</a>
|
||||
{{ item.get_title_supplement|safe }}
|
||||
</li>
|
||||
{% empty %}
|
||||
|
@ -11,10 +11,12 @@
|
||||
"""
|
||||
|
||||
from django.conf.urls import url, patterns
|
||||
from openslides.agenda.views import (Overview, View, SetClosed, ItemUpdate,
|
||||
from openslides.agenda.views import (
|
||||
Overview, View, SetClosed, ItemUpdate,
|
||||
ItemCreate, ItemDelete, AgendaPDF)
|
||||
|
||||
urlpatterns = patterns('',
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^$',
|
||||
Overview.as_view(),
|
||||
name='item_overview',
|
||||
|
@ -9,7 +9,9 @@
|
||||
:copyright: 2011, 2012 by the OpenSlides team, see AUTHORS.
|
||||
:license: GNU GPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from reportlab.platypus import Paragraph
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.contrib import messages
|
||||
@ -18,10 +20,12 @@ from django.db.models import Model
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.views.generic.detail import SingleObjectMixin
|
||||
|
||||
from openslides.config.models import config
|
||||
from openslides.agenda.forms import ConfigForm
|
||||
from openslides.utils.pdf import stylesheet
|
||||
from openslides.utils.views import (
|
||||
TemplateView, RedirectView, UpdateView, CreateView, DeleteView, PDFView,
|
||||
DetailView)
|
||||
DetailView, FormView)
|
||||
from openslides.utils.template import Tab
|
||||
from openslides.utils.utils import html_strong
|
||||
from openslides.projector.api import get_active_slide
|
||||
@ -39,10 +43,44 @@ class Overview(TemplateView):
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(Overview, self).get_context_data(**kwargs)
|
||||
|
||||
if self.request.user.has_perm('agenda.can_see_orga_items'):
|
||||
items = Item.objects.all()
|
||||
else:
|
||||
items = Item.objects.filter(type__exact=Item.AGENDA_ITEM)
|
||||
|
||||
start = config['agenda_start_event_date_time']
|
||||
if start is None or len(start) == 0:
|
||||
start = None
|
||||
else:
|
||||
start = datetime.strptime(start, '%d.%m.%Y %H:%M')
|
||||
|
||||
duration = timedelta()
|
||||
|
||||
for item in items:
|
||||
if not item.closed and (item.duration is not None
|
||||
and len(item.duration) > 0):
|
||||
duration_list = item.duration.split(':')
|
||||
duration += timedelta(hours=int(duration_list[0]),
|
||||
minutes=int(duration_list[1]))
|
||||
if not start is None:
|
||||
item.tooltip = start + duration
|
||||
|
||||
if start is None:
|
||||
end = None
|
||||
else:
|
||||
end = start + duration
|
||||
|
||||
duration = u'%d:%02d' % (
|
||||
(duration.days * 24 + duration.seconds / 3600.0),
|
||||
(duration.seconds / 60.0 % 60))
|
||||
|
||||
context.update({
|
||||
'items': Item.objects.all(),
|
||||
'items': items,
|
||||
'active_sid': get_active_slide(only_sid=True),
|
||||
})
|
||||
'duration': duration,
|
||||
'start': start,
|
||||
'end': end})
|
||||
return context
|
||||
|
||||
@transaction.commit_manually
|
||||
@ -103,8 +141,7 @@ class SetClosed(RedirectView, SingleObjectMixin):
|
||||
link = reverse('item_close', args=[self.object.id])
|
||||
context.update({
|
||||
'closed': kwargs['closed'],
|
||||
'link': link,
|
||||
})
|
||||
'link': link})
|
||||
return context
|
||||
|
||||
def pre_redirect(self, request, *args, **kwargs):
|
||||
@ -157,12 +194,14 @@ class ItemDelete(DeleteView):
|
||||
if self.get_answer() == 'all':
|
||||
self.object.delete(with_children=True)
|
||||
messages.success(
|
||||
request, _("Item %s and his children were successfully deleted.")
|
||||
request,
|
||||
_("Item %s and his children were successfully deleted.")
|
||||
% html_strong(self.object))
|
||||
elif self.get_answer() == 'yes':
|
||||
self.object.delete(with_children=False)
|
||||
messages.success(
|
||||
request, _("Item %s was successfully deleted.")
|
||||
request,
|
||||
_("Item %s was successfully deleted.")
|
||||
% html_strong(self.object))
|
||||
|
||||
|
||||
@ -175,7 +214,7 @@ class AgendaPDF(PDFView):
|
||||
document_title = ugettext_lazy('Agenda')
|
||||
|
||||
def append_to_pdf(self, story):
|
||||
for item in Item.objects.all():
|
||||
for item in Item.objects.filter(type__exact=Item.AGENDA_ITEM):
|
||||
ancestors = item.get_ancestors()
|
||||
if ancestors:
|
||||
space = " " * 6 * ancestors.count()
|
||||
@ -186,6 +225,26 @@ class AgendaPDF(PDFView):
|
||||
story.append(Paragraph(item.get_title(), stylesheet['Item']))
|
||||
|
||||
|
||||
class Config(FormView):
|
||||
"""
|
||||
Config page for the agenda app.
|
||||
"""
|
||||
permission_required = 'config.can_manage_config'
|
||||
form_class = ConfigForm
|
||||
template_name = 'agenda/config.html'
|
||||
success_url_name = 'config_agenda'
|
||||
|
||||
def get_initial(self):
|
||||
return {
|
||||
'agenda_start_event_date_time': config['agenda_start_event_date_time'],
|
||||
}
|
||||
|
||||
def form_valid(self, form):
|
||||
config['agenda_start_event_date_time'] = form.cleaned_data['agenda_start_event_date_time']
|
||||
messages.success(self.request, _('Agenda settings successfully saved.'))
|
||||
return super(Config, self).form_valid(form)
|
||||
|
||||
|
||||
def register_tab(request):
|
||||
"""
|
||||
register the agenda tab.
|
||||
|
@ -6,8 +6,8 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OpenSlides 1.3\n"
|
||||
"Report-Msgid-Bugs-To: support@openslides.org\n"
|
||||
"POT-Creation-Date: 2012-12-09 11:12+0100\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-02-05 14:24+0100\n"
|
||||
"PO-Revision-Date: 2012-07-28 11:07+0200\n"
|
||||
"Last-Translator: Oskar Hahn <mail@oshahn.de>\n"
|
||||
"Language: de\n"
|
||||
|
@ -195,7 +195,7 @@ class VersionPermitView(GetVersionMixin, SingleObjectMixin, QuestionMixin, Redir
|
||||
|
||||
def case_yes(self):
|
||||
"""Activate the version, if the user chooses 'yes'."""
|
||||
self.object.activate_version(self.object.version)
|
||||
self.object.activate_version(self.object.version) # TODO: Write log message
|
||||
self.object.save()
|
||||
|
||||
version_permit = VersionPermitView.as_view()
|
||||
@ -221,7 +221,7 @@ class VersionRejectView(GetVersionMixin, SingleObjectMixin, QuestionMixin, Redir
|
||||
|
||||
def case_yes(self):
|
||||
"""Reject the version, if the user chooses 'yes'."""
|
||||
self.object.reject_version(self.object.version)
|
||||
self.object.reject_version(self.object.version) # TODO: Write log message
|
||||
self.object.save()
|
||||
|
||||
version_reject = VersionRejectView.as_view()
|
||||
|
@ -8,7 +8,7 @@
|
||||
<link type="text/css" rel="stylesheet" media="all" href="{% static 'styles/dashboard.css' %}" />
|
||||
{% endblock %}
|
||||
{% block javascript %}
|
||||
<script type="text/javascript" src="{% static 'javascript/jquery-ui.min.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'javascript/jquery-ui.custom.min.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'javascript/jquery.cookie.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'javascript/jquery.form.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'javascript/dashboard.js' %}"></script>
|
||||
|
BIN
openslides/static/img/glyphicons_054_clock.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
6
openslides/static/javascript/jquery-ui.custom.min.js
vendored
Executable file
@ -311,7 +311,10 @@ legend + .control-group {
|
||||
background-image: url("../img/glyphicons_006_user_add.png");
|
||||
background-position: 0;
|
||||
}
|
||||
|
||||
.icon-clock {
|
||||
background-image: url("../img/glyphicons_054_clock.png");
|
||||
background-position: 0;
|
||||
}
|
||||
|
||||
|
||||
/** Responsive **/
|
||||
|
BIN
openslides/static/styles/jquery-ui/images/animated-overlay.gif
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
openslides/static/styles/jquery-ui/images/ui-bg_flat_0_aaaaaa_40x100.png
Executable file
After Width: | Height: | Size: 274 B |
BIN
openslides/static/styles/jquery-ui/images/ui-bg_flat_75_ffffff_40x100.png
Executable file
After Width: | Height: | Size: 271 B |
BIN
openslides/static/styles/jquery-ui/images/ui-bg_glass_55_fbf9ee_1x400.png
Executable file
After Width: | Height: | Size: 387 B |
BIN
openslides/static/styles/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png
Executable file
After Width: | Height: | Size: 272 B |
BIN
openslides/static/styles/jquery-ui/images/ui-bg_glass_75_dadada_1x400.png
Executable file
After Width: | Height: | Size: 375 B |
BIN
openslides/static/styles/jquery-ui/images/ui-bg_glass_75_e6e6e6_1x400.png
Executable file
After Width: | Height: | Size: 368 B |
BIN
openslides/static/styles/jquery-ui/images/ui-bg_glass_95_fef1ec_1x400.png
Executable file
After Width: | Height: | Size: 384 B |
After Width: | Height: | Size: 360 B |
BIN
openslides/static/styles/jquery-ui/images/ui-icons_222222_256x240.png
Executable file
After Width: | Height: | Size: 6.6 KiB |
BIN
openslides/static/styles/jquery-ui/images/ui-icons_2e83ff_256x240.png
Executable file
After Width: | Height: | Size: 4.3 KiB |
BIN
openslides/static/styles/jquery-ui/images/ui-icons_454545_256x240.png
Executable file
After Width: | Height: | Size: 6.7 KiB |
BIN
openslides/static/styles/jquery-ui/images/ui-icons_888888_256x240.png
Executable file
After Width: | Height: | Size: 6.7 KiB |
BIN
openslides/static/styles/jquery-ui/images/ui-icons_cd0a0a_256x240.png
Executable file
After Width: | Height: | Size: 4.3 KiB |
5
openslides/static/styles/jquery-ui/jquery-ui.custom.min.css
vendored
Executable file
@ -179,7 +179,8 @@ class ViewTest(TestCase):
|
||||
response = c.get('/agenda/%d/edit/' % 1000)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
data = {'title': 'newitem1', 'text': 'item1-text', 'weight': '0'}
|
||||
data = {'title': 'newitem1', 'text': 'item1-text', 'weight': '0',
|
||||
'type': 1}
|
||||
response = c.post('/agenda/%d/edit/' % self.item1.id, data)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.refreshItems()
|
||||
|