Merge branch 'master' of github.com:OpenSlides/OpenSlides into sort_person_api

This commit is contained in:
Oskar Hahn 2012-11-22 16:35:26 +01:00
commit 8014f327a2
41 changed files with 563 additions and 545 deletions

View File

@ -98,13 +98,12 @@ II. Installation on GNU/Linux and MacOSX
OR OR
b) Clone development version from mercurial repository b) Clone development version from OpenSlides' github repository
http://hg.openslides.org. This requires Mercurial source control https://github.com/OpenSlides/OpenSlides.
management (hg): This requires Git, see http://git-scm.com/.
Open command line (cmd) and run:
E.g. for Ubuntu run: git clone git://github.com/OpenSlides/OpenSlides.git
$ sudo apt-get install mercurial
$ hg clone http://hg.openslides.org OpenSlides
3. Setup your virtual environment with virtualenv: 3. Setup your virtual environment with virtualenv:

View File

@ -6,17 +6,11 @@ How to create a new portable Windows distribution of OpenSlides:
easy_install -Z django django-mptt reportlab pil easy_install -Z django django-mptt reportlab pil
2.) Install OpenSlides by running in the top directory: 2.) Run in the main directory of the OpenSlides checkout:
python setup.py install
NOTE: This step must be repeated whenever you make changes to OpenSlides.
3.) Run in the main directory of the OpenSlides checkout:
python extras\win32-portable\prepare_portable.py python extras\win32-portable\prepare_portable.py
4.) The portable OpenSlides distribution is now ready as a zip archive 3.) The portable OpenSlides distribution is now ready as a zip archive
in the 'dist' directory in the 'dist' directory

View File

@ -18,8 +18,6 @@ import zipfile
import distutils.ccompiler import distutils.ccompiler
import distutils.sysconfig import distutils.sysconfig
from contextlib import nested
import pkg_resources import pkg_resources
sys.path.insert(0, os.getcwd()) sys.path.insert(0, os.getcwd())
@ -80,10 +78,7 @@ SITE_PACKAGES = {
"pil": { "pil": {
# NOTE: PIL is a special case, see copy_pil # NOTE: PIL is a special case, see copy_pil
"copy": [], "copy": [],
}, }
"openslides": {
"copy" : ["openslides"],
},
} }
PY_DLLS = [ PY_DLLS = [
@ -297,9 +292,13 @@ def main():
raise raise
os.makedirs(odir) os.makedirs(odir)
out_site_packages = os.path.join(odir, "site-packages")
collect_lib(libdir, odir) collect_lib(libdir, odir)
collect_site_packages(sitedir, os.path.join(odir, "site-packages")) collect_site_packages(sitedir, out_site_packages)
exclude = get_pkg_exclude("openslides")
copy_dir_exclude(exclude, ".", "openslides", out_site_packages)
if not compile_openslides_launcher(): if not compile_openslides_launcher():
sys.stdout.write("Using prebuild openslides.exe\n") sys.stdout.write("Using prebuild openslides.exe\n")

View File

@ -3,7 +3,7 @@
"pk": 1, "pk": 1,
"model": "auth.group", "model": "auth.group",
"fields": { "fields": {
"name": "Beobachter", "name": "Beobachter/in",
"permissions": [ "permissions": [
[ [
"can_see_agenda", "can_see_agenda",
@ -57,7 +57,7 @@
"pk": 2, "pk": 2,
"model": "auth.group", "model": "auth.group",
"fields": { "fields": {
"name": "Delegierter", "name": "Delegierte/r",
"permissions": [ "permissions": [
[ [
"can_see_agenda", "can_see_agenda",

View File

@ -231,4 +231,4 @@ def get_widgets(request):
context={ context={
'agenda': SLIDE['agenda'], 'agenda': SLIDE['agenda'],
'items': Item.objects.all()}, 'items': Item.objects.all()},
permission_required='agenda.can_manage_agenda')] permission_required='projector.can_manage_projector')]

View File

@ -85,7 +85,7 @@ class Assignment(models.Model, SlideMixin):
raise NameError(_('<b>%s</b> is already a candidate.') % candidate) raise NameError(_('<b>%s</b> is already a candidate.') % candidate)
if not person.has_perm("assignment.can_manage_assignment") and self.status != 'sea': if not person.has_perm("assignment.can_manage_assignment") and self.status != 'sea':
raise NameError(_('The candidate list is already closed.')) raise NameError(_('The candidate list is already closed.'))
candidation = self.assignment_candidats.filter(person=candidate) candidation = self.assignment_candidates.filter(person=candidate)
if candidation and candidate != person and \ if candidation and candidate != person and \
not person.has_perm("assignment.can_manage_assignment"): not person.has_perm("assignment.can_manage_assignment"):
# if the candidation is blocked and anotherone tries to run the # if the candidation is blocked and anotherone tries to run the
@ -103,9 +103,8 @@ class Assignment(models.Model, SlideMixin):
stop running for a vote stop running for a vote
""" """
try: try:
candidation = self.assignment_candidats.get(person=candidate) candidation = self.assignment_candidates.get(person=candidate)
except AssignmentCandidate.DoesNotExist: except AssignmentCandidate.DoesNotExist:
# TODO: Use an OpenSlides Error
raise Exception(_('%s is no candidate') % candidate) raise Exception(_('%s is no candidate') % candidate)
if not candidation.blocked: if not candidation.blocked:
@ -123,7 +122,7 @@ class Assignment(models.Model, SlideMixin):
return True, if person is a candidate. return True, if person is a candidate.
""" """
try: try:
return self.assignment_candidats.filter(person=person) \ return self.assignment_candidates.filter(person=person) \
.exclude(blocked=True).exists() .exclude(blocked=True).exists()
except AttributeError: except AttributeError:
return False return False
@ -132,11 +131,11 @@ class Assignment(models.Model, SlideMixin):
""" """
return True, if the person is blockt for candidation. return True, if the person is blockt for candidation.
""" """
return self.assignment_candidats.filter(person=person) \ return self.assignment_candidates.filter(person=person) \
.filter(blocked=True).exists() .filter(blocked=True).exists()
@property @property
def assignment_candidats(self): def assignment_candidates(self):
return AssignmentCandidate.objects.filter(assignment=self) return AssignmentCandidate.objects.filter(assignment=self)
@property @property
@ -148,7 +147,7 @@ class Assignment(models.Model, SlideMixin):
return self.get_participants(only_elected=True) return self.get_participants(only_elected=True)
def get_participants(self, only_elected=False, only_candidate=False): def get_participants(self, only_elected=False, only_candidate=False):
candidates = self.assignment_candidats.exclude(blocked=True) candidates = self.assignment_candidates.exclude(blocked=True)
assert not (only_elected and only_candidate) assert not (only_elected and only_candidate)
@ -167,7 +166,7 @@ class Assignment(models.Model, SlideMixin):
def set_elected(self, person, value=True): def set_elected(self, person, value=True):
candidate = self.assignment_candidats.get(person=person) candidate = self.assignment_candidates.get(person=person)
candidate.elected = value candidate.elected = value
candidate.save() candidate.save()
@ -293,7 +292,7 @@ class AssignmentPoll(BasePoll, CountInvalid, CountVotesCast, PublishPollMixin):
self.yesnoabstain = True self.yesnoabstain = True
else: else:
# candidates <= available posts -> yes/no/abstain # candidates <= available posts -> yes/no/abstain
if self.assignment.assignment_candidats.filter(elected=False).count() <= (self.assignment.posts): if len(self.assignment.candidates) <= (self.assignment.posts - len(self.assignment.elected)):
self.yesnoabstain = True self.yesnoabstain = True
else: else:
self.yesnoabstain = False self.yesnoabstain = False

View File

@ -32,10 +32,11 @@
{% if assignment.active %}activeline{% endif %}"> {% if assignment.active %}activeline{% endif %}">
<td><a href="{% url assignment_view assignment.id %}">{{ assignment }}</a></td> <td><a href="{% url assignment_view assignment.id %}">{{ assignment }}</a></td>
<td> <td>
{{ assignment.posts }} {% trans "posts" %} / {{ assignment.elected|length }} {% trans "elected" %} {% blocktrans with posts=assignment.posts %}posts: {{ posts }}{% endblocktrans %}
{% if assignment.status != 'fin' %} {% if assignment.status != 'fin' %}
/ {{ assignment.candidates|length }} {% trans "candidates" %} | {% blocktrans with candidates=assignment.get_participants|length %}candidates: {{ candidates }}{% endblocktrans %}
{% endif %} {% endif %}
| {% blocktrans with elected=assignment.elected|length %}elected: {{ elected }}{% endblocktrans %}
</td> </td>
<td>{{ assignment.get_status_display }}</td> <td>{{ assignment.get_status_display }}</td>
<td> <td>

View File

@ -33,9 +33,10 @@
<h1>{{ assignment }}</h1> <h1>{{ assignment }}</h1>
<p>{{ assignment.description|linebreaks }}</p> <p>{{ assignment.description|linebreaks }}</p>
{% if assignment.status != "fin" %}
<h3>{% trans "Candidates" %}</h3> <h3>{% trans "Candidates" %}</h3>
<ol> <ol>
{% for person in assignment.candidates %} {% for person in assignment.get_participants %}
<li> <li>
{{ person }} {{ person }}
{% if perms.assignment.can_manage_assignment %} {% if perms.assignment.can_manage_assignment %}
@ -43,6 +44,14 @@
<a href="{% url assignment_delother assignment.id person.person_id %}"><img src="{% static 'images/icons/delete.png' %}" title="{% trans 'Remove candidate' %}"></a> <a href="{% url assignment_delother assignment.id person.person_id %}"><img src="{% static 'images/icons/delete.png' %}" title="{% trans 'Remove candidate' %}"></a>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if person in assignment.elected %}
| <b>{% trans "elected" %}</b>
{% if perms.assignment.can_manage_assignment %}
{% if assignment.status == "sea" or assignment.status == "vot" %}
<a href="{% url assignment_user_not_elected assignment.id person.person_id %}"><img src="{% static 'images/icons/dialog-cancel.png' %}" title="{% trans 'Mark candidate as not elected' %}"></a>
{% endif %}
{% endif %}
{% endif %}
</li> </li>
{% empty %} {% empty %}
<li style="list-style: none outside none;"><i>{% trans "No candidates available." %}</i></li> <li style="list-style: none outside none;"><i>{% trans "No candidates available." %}</i></li>
@ -85,27 +94,11 @@
</p> </p>
{% endif %} {% endif %}
</form> </form>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% endif %}
<h3>{% trans "Elected Candidates" %}</h3> {% if perms.assignment.can_manage_assignments and blocked_candidates and assignment.status != "fin" %}
<ul>
{% for person in assignment.elected %}
<li>
{{ person }}
{% if perms.assignment.can_manage_assignment %}
{% if assignment.status == "sea" or assignment.status == "vot" %}
<a href="{% url assignment_user_not_elected assignment.id person.person_id %}"><img src="{% static 'images/icons/delete.png' %}" title="{% trans 'Remove candidate' %}"></a>
{% endif %}
{% endif %}
</li>
{% empty %}
<li>{% trans "No elected candidates available." %}</li>
{% endfor %}
</ul>
{% if perms.assignment.can_manage_assignments %}
<h3>{% trans "Blocked Candidates" %}</h3> <h3>{% trans "Blocked Candidates" %}</h3>
<ul> <ul>
{% for person in blocked_candidates %} {% for person in blocked_candidates %}
@ -118,20 +111,11 @@
</ul> </ul>
{% endif %} {% endif %}
{% if assignment.status != "sea" or polls.exists %}
<h3>{% trans "Election results" %}</h3> <h3>{% trans "Election results" %}</h3>
{% if polls.exists %} {% if polls.exists %}
<table id="election_table" style="width: auto;"> <table id="election_table" style="width: auto;">
<tr>
<th></th>
{% with ballotnumber=polls.count %}
<th colspan="{{ ballotnumber|add:'1' }}" style="text-align: center;">
{% trans "ballot" %}
</th>
{% endwith %}
</tr>
<tr> <tr>
<th>{% trans "Candidates" %}</th> <th>{% trans "Candidates" %}</th>
{% for poll in polls %} {% for poll in polls %}
@ -161,7 +145,7 @@
</tr> </tr>
{% for candidate, poll_list in vote_results.items %} {% for candidate, poll_list in vote_results.items %}
<tr class="{% cycle 'odd' '' %}"> <tr class="{% cycle 'odd' '' as rowcolors %}">
<td class="candidate"> <td class="candidate">
{% if candidate in assignment.elected %} {% if candidate in assignment.elected %}
{% if perms.assignment.can_manage_assignment %} {% if perms.assignment.can_manage_assignment %}
@ -198,8 +182,7 @@
{% endif %} {% endif %}
</tr> </tr>
{% endfor %} {% endfor %}
<tr class="{% cycle rowcolors %}">
<tr>
<td>{% trans 'Invalid votes' %}</td> <td>{% trans 'Invalid votes' %}</td>
{% for poll in polls %} {% for poll in polls %}
{% if poll.published or perms.assignment.can_manage_assignment %} {% if poll.published or perms.assignment.can_manage_assignment %}
@ -215,7 +198,6 @@
<td></td> <td></td>
{% endif %} {% endif %}
</tr> </tr>
<tr class="total"> <tr class="total">
<td><strong>{% trans 'Votes cast' %}</strong></td> <td><strong>{% trans 'Votes cast' %}</strong></td>
{% for poll in polls %} {% for poll in polls %}
@ -233,11 +215,8 @@
{% endif %} {% endif %}
</tr> </tr>
</table> </table>
{% else %}
{% else %} <i>{% trans "No results available." %}</i>
<i>{% trans "No ballots available." %}</i>
{% if assignment.candidates and perms.assignment.can_manage_assignment and assignment.status == "vot" %} {% if assignment.candidates and perms.assignment.can_manage_assignment and assignment.status == "vot" %}
<p><a href='{% url assignment_gen_poll assignment.id %}'> <p><a href='{% url assignment_gen_poll assignment.id %}'>
<span class="button"> <span class="button">
@ -245,9 +224,7 @@
</span> </span>
</a></p> </a></p>
{% endif %} {% endif %}
{% endif %}
{% endif %} {% endif %}
</div> </div>
{% endblock %} {% endblock %}

View File

@ -62,7 +62,7 @@
</tr> </tr>
{% for candidate, poll_list in vote_results.items %} {% for candidate, poll_list in vote_results.items %}
<tr class="{% cycle 'odd' '' %}"> <tr class="{% cycle 'odd' '' as rowcolors %}">
<td class="candidate{% if candidate in assignment.elected %} elected{% endif %}"> <td class="candidate{% if candidate in assignment.elected %} elected{% endif %}">
{% if candidate in assignment.elected %} {% if candidate in assignment.elected %}
<a class="elected"> <a class="elected">
@ -92,8 +92,7 @@
{% endfor %} {% endfor %}
</tr> </tr>
{% endfor %} {% endfor %}
<tr class="{% cycle rowcolors %}">
<tr>
<td>{% trans 'Invalid votes' %}</td> <td>{% trans 'Invalid votes' %}</td>
{% for poll in polls %} {% for poll in polls %}
<td style="white-space:nowrap;"> <td style="white-space:nowrap;">
@ -105,7 +104,6 @@
{% endfor %} {% endfor %}
</tr> </tr>
<tr class="total"> <tr class="total">
<td> <td>
<strong>{% trans 'Votes cast' %}</strong> <strong>{% trans 'Votes cast' %}</strong>
@ -120,12 +118,6 @@
</td> </td>
{% endfor %} {% endfor %}
</tr> </tr>
</table> </table>
{% elif some_polls_available %}
<i>{% trans "Vote results are not published yet." %}</i>
{% elif assignment.candidates %}
<i>{% trans "No ballots available." %}</i>
{% endif %} {% endif %}
<br>
{% endblock %} {% endblock %}

View File

@ -101,7 +101,7 @@ def view(request, assignment_id=None):
vote_results = assignment.vote_results(only_published=False) vote_results = assignment.vote_results(only_published=False)
blocked_candidates = [candidate.person for candidate in \ blocked_candidates = [candidate.person for candidate in \
assignment.assignment_candidats.filter(blocked=True)] assignment.assignment_candidates.filter(blocked=True)]
return { return {
'assignment': assignment, 'assignment': assignment,
'blocked_candidates': blocked_candidates, 'blocked_candidates': blocked_candidates,
@ -170,6 +170,8 @@ def set_status(request, assignment_id=None, status=None):
messages.success(request, _('Election status was set to: <b>%s</b>.') % assignment.get_status_display()) messages.success(request, _('Election status was set to: <b>%s</b>.') % assignment.get_status_display())
except Assignment.DoesNotExist: except Assignment.DoesNotExist:
pass pass
except NameError, e:
messages.error(request, e)
return redirect(reverse('assignment_view', args=[assignment_id])) return redirect(reverse('assignment_view', args=[assignment_id]))
@ -678,4 +680,4 @@ def get_widgets(request):
display_name=_('Elections'), display_name=_('Elections'),
template='assignment/widget.html', template='assignment/widget.html',
context={'assignments': Assignment.objects.all()}, context={'assignments': Assignment.objects.all()},
permission_required='assignment.can_manage_assignment')] permission_required='projector.can_manage_projector')]

View File

@ -56,13 +56,13 @@ class GeneralConfigForm(forms.Form, CssClassMixin):
required=False, required=False,
) )
frontpage_title = forms.CharField( welcome_title = forms.CharField(
widget=forms.TextInput(), widget=forms.TextInput(),
label=_("Title"), label=_("Title"),
required=False, required=False,
) )
frontpage_welcometext = forms.CharField( welcome_text = forms.CharField(
widget=forms.Textarea(), widget=forms.Textarea(),
label=_("Welcome text"), label=_("Welcome text"),
required=False, required=False,

View File

@ -86,8 +86,8 @@ def default_config(sender, key, **kwargs):
'event_location': '', 'event_location': '',
'event_organizer': '', 'event_organizer': '',
'presentation': '', 'presentation': '',
'frontpage_title': _('Welcome to OpenSlides'), 'welcome_title': _('Welcome to OpenSlides'),
'frontpage_welcometext': _('[Place for your welcome text.]'), 'welcome_text': _('[Place for your welcome text.]'),
'system_enable_anonymous': False, 'system_enable_anonymous': False,
}.get(key) }.get(key)

View File

@ -23,9 +23,9 @@
</fieldset> </fieldset>
<p></p> <p></p>
<fieldset> <fieldset>
<legend>{% trans "Frontpage" %}</legend> <legend>{% trans "Welcome Widget" %}</legend>
{% for field in form %} {% for field in form %}
{% if "id_frontpage" in field.label_tag %} {% if "id_welcome" in field.label_tag %}
<p> <p>
{{ field.errors }} {{ field.errors }}
{{ field.required }} {{ field.required }}

View File

@ -41,8 +41,8 @@ class GeneralConfig(FormView):
'event_date': config['event_date'], 'event_date': config['event_date'],
'event_location': config['event_location'], 'event_location': config['event_location'],
'event_organizer': config['event_organizer'], 'event_organizer': config['event_organizer'],
'frontpage_title': config['frontpage_title'], 'welcome_title': config['welcome_title'],
'frontpage_welcometext': config['frontpage_welcometext'], 'welcome_text': config['welcome_text'],
'system_enable_anonymous': config['system_enable_anonymous'], 'system_enable_anonymous': config['system_enable_anonymous'],
} }
@ -54,10 +54,9 @@ class GeneralConfig(FormView):
config['event_location'] = form.cleaned_data['event_location'] config['event_location'] = form.cleaned_data['event_location']
config['event_organizer'] = form.cleaned_data['event_organizer'] config['event_organizer'] = form.cleaned_data['event_organizer']
# frontpage # welcome widget
config['frontpage_title'] = form.cleaned_data['frontpage_title'] config['welcome_title'] = form.cleaned_data['welcome_title']
config['frontpage_welcometext'] = \ config['welcome_text'] = form.cleaned_data['welcome_text']
form.cleaned_data['frontpage_welcometext']
# system # system
if form.cleaned_data['system_enable_anonymous']: if form.cleaned_data['system_enable_anonymous']:

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,8 @@ from openslides.config.signals import default_config_value
from openslides.poll.models import (BaseOption, BasePoll, CountVotesCast, from openslides.poll.models import (BaseOption, BasePoll, CountVotesCast,
CountInvalid, BaseVote) CountInvalid, BaseVote)
from openslides.participant.models import User, Group
from openslides.projector.api import register_slidemodel from openslides.projector.api import register_slidemodel
from openslides.projector.models import SlideMixin from openslides.projector.models import SlideMixin
@ -443,7 +445,10 @@ class Motion(models.Model, SlideMixin):
self.log = "" self.log = ""
self.log += u"%s | %s" % (datetime.now().strftime("%d.%m.%Y %H:%M:%S"), _propper_unicode(text)) self.log += u"%s | %s" % (datetime.now().strftime("%d.%m.%Y %H:%M:%S"), _propper_unicode(text))
if user is not None: if user is not None:
self.log += u" (%s %s)" % (_("by"), _propper_unicode(user.username)) if isinstance(user, User):
self.log += u" (%s %s)" % (_("by"), _propper_unicode(user.username))
else:
self.log += u" (%s %s)" % (_("by"), _propper_unicode(str(user)))
self.log += "\n" self.log += "\n"
self.save() self.save()

View File

@ -8,7 +8,7 @@
<h1>{% trans "Import motions" %}</h1> <h1>{% trans "Import motions" %}</h1>
<p>{% trans 'Select a CSV file to import motions!' %}</p> <p>{% trans 'Select a CSV file to import motions!' %}</p>
<p>{% trans 'Required comma separated values: <code>{number, title, text, reason, first_name, last_name}</code> (<code>number</code> and <code>reason</code> are optional and may be empty)' %} <p>{% trans 'Required comma separated values: <code>{number, title, text, reason, first_name, last_name, is_group}</code> (<code>number</code>, <code>reason</code> and <code>is_group</code> are optional and may be empty)' %}
<br> <br>
{% trans 'Required CSV file encoding: UTF-8 (Unicode).' %} {% trans 'Required CSV file encoding: UTF-8 (Unicode).' %}
</p> </p>

View File

@ -52,7 +52,7 @@ from openslides.projector.projector import Widget
from openslides.poll.views import PollFormView from openslides.poll.views import PollFormView
from openslides.participant.api import gen_username, gen_password from openslides.participant.api import gen_username, gen_password
from openslides.participant.models import User from openslides.participant.models import User, Group
from openslides.agenda.models import Item from openslides.agenda.models import Item
@ -579,6 +579,8 @@ def motion_import(request):
users_generated = 0 users_generated = 0
motions_generated = 0 motions_generated = 0
motions_modified = 0 motions_modified = 0
groups_assigned = 0
groups_generated = 0
with transaction.commit_on_success(): with transaction.commit_on_success():
dialect = csv.Sniffer().sniff(request.FILES['csvfile'].readline()) dialect = csv.Sniffer().sniff(request.FILES['csvfile'].readline())
dialect = csv_ext.patchup(dialect) dialect = csv_ext.patchup(dialect)
@ -588,7 +590,11 @@ def motion_import(request):
if lno < 1: if lno < 1:
continue continue
try: try:
(number, title, text, reason, first_name, last_name) = line[:6] (number, title, text, reason, first_name, last_name, is_group) = line[:7]
if is_group.strip().lower() in ['y', 'j', 't', 'yes', 'ja', 'true', '1', 1]:
is_group = True
else:
is_group = False
except ValueError: except ValueError:
messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1)) messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1))
continue continue
@ -605,24 +611,50 @@ def motion_import(request):
except ValueError: except ValueError:
messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1)) messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1))
continue continue
# fetch existing users or create new users as needed
try: if is_group:
user = User.objects.get(first_name=first_name, last_name=last_name) # fetch existing groups or issue an error message
except User.DoesNotExist: try:
user = None user = Group.objects.get(name=last_name)
if user is None: if user.group_as_person == False:
user = User() messages.error(request, _('Ignoring line %d because the assigned group may not act as a person.') % (lno + 1))
user.last_name = last_name continue
user.first_name = first_name else:
user.username = gen_username(first_name, last_name) user = get_person(user.person_id)
user.detail = ''
user.committee = '' groups_assigned += 1
user.gender = '' except Group.DoesNotExist:
user.type = '' group = Group()
user.default_password = gen_password() group.group_as_person = True
user.save() group.description = _('Created by motion import.')
user.reset_password() group.name = last_name
users_generated += 1 group.save()
groups_generated += 1
user = get_person(group.person_id)
else:
# fetch existing users or create new users as needed
try:
user = User.objects.get(first_name=first_name, last_name=last_name)
except User.DoesNotExist:
user = None
if user is None:
if not first_name or not last_name:
messages.error(request, _('Ignoring line %d because it contains an incomplete first / last name pair.') % (lno + 1))
continue
user = User()
user.last_name = last_name
user.first_name = first_name
user.username = gen_username(first_name, last_name)
user.structure_level = ''
user.committee = ''
user.gender = ''
user.type = ''
user.default_password = gen_password()
user.save()
user.reset_password()
users_generated += 1
# create / modify the motion # create / modify the motion
motion = None motion = None
if number: if number:
@ -653,6 +685,12 @@ def motion_import(request):
'%d motions were successfully modified.', motions_modified) % motions_modified) '%d motions were successfully modified.', motions_modified) % motions_modified)
if users_generated: if users_generated:
messages.success(request, ungettext('%d new user was added.', '%d new users were added.', users_generated) % users_generated) messages.success(request, ungettext('%d new user was added.', '%d new users were added.', users_generated) % users_generated)
if groups_generated:
messages.success(request, ungettext('%d new group was added.', '%d new groups were added.', groups_generated) % groups_generated)
if groups_assigned:
messages.success(request, ungettext('%d group assigned to motions.', '%d groups assigned to motions.', groups_assigned) % groups_assigned)
return redirect(reverse('motion_overview')) return redirect(reverse('motion_overview'))
except csv.Error: except csv.Error:
@ -928,4 +966,4 @@ def get_widgets(request):
display_name=_('Motions'), display_name=_('Motions'),
template='motion/widget.html', template='motion/widget.html',
context={'motions': Motion.objects.all()}, context={'motions': Motion.objects.all()},
permission_required='motion.can_manage_motion')] permission_required='projector.can_manage_projector')]

View File

@ -71,7 +71,7 @@ def import_users(csv_file):
dialect=dialect)): dialect=dialect)):
if line_no: if line_no:
try: try:
(first_name, last_name, gender, detail, type, committee, comment) = line[:7] (first_name, last_name, gender, structure_level, type, committee, comment) = line[:7]
except ValueError: except ValueError:
error_messages.append(_('Ignoring malformed line %d in import file.') % line_no + 1) error_messages.append(_('Ignoring malformed line %d in import file.') % line_no + 1)
continue continue
@ -80,7 +80,7 @@ def import_users(csv_file):
user.first_name = first_name user.first_name = first_name
user.username = gen_username(first_name, last_name) user.username = gen_username(first_name, last_name)
user.gender = gender user.gender = gender
user.detail = detail user.structure_level = structure_level
user.type = type user.type = type
user.committee = committee user.committee = committee
user.comment = comment user.comment = comment

View File

@ -27,7 +27,7 @@ class UserCreateForm(forms.ModelForm, CssClassMixin):
class Meta: class Meta:
model = User model = User
fields = ('first_name', 'last_name', 'is_active', 'groups', 'detail', fields = ('first_name', 'last_name', 'is_active', 'groups', 'structure_level',
'gender', 'type', 'committee', 'about_me', 'comment', 'default_password') 'gender', 'type', 'committee', 'about_me', 'comment', 'default_password')
@ -35,7 +35,7 @@ class UserUpdateForm(UserCreateForm):
class Meta: class Meta:
model = User model = User
fields = ('username', 'first_name', 'last_name', 'is_active', 'groups', fields = ('username', 'first_name', 'last_name', 'is_active', 'groups',
'detail', 'gender', 'type', 'committee', 'about_me', 'comment', 'structure_level', 'gender', 'type', 'committee', 'about_me', 'comment',
'default_password') 'default_password')

View File

@ -40,8 +40,8 @@ class User(DjangoUser, PersonMixin, Person, SlideMixin):
) )
django_user = models.OneToOneField(DjangoUser, editable=False, parent_link=True) django_user = models.OneToOneField(DjangoUser, editable=False, parent_link=True)
detail = models.CharField( structure_level = models.CharField(
max_length=100, blank=True, default='', verbose_name=_("Detail"), max_length=100, blank=True, default='', verbose_name=_("Structure level"),
help_text=_('Will be shown after the name.')) help_text=_('Will be shown after the name.'))
gender = models.CharField( gender = models.CharField(
max_length=50, choices=GENDER_CHOICES, blank=True, max_length=50, choices=GENDER_CHOICES, blank=True,
@ -67,10 +67,10 @@ class User(DjangoUser, PersonMixin, Person, SlideMixin):
return self.get_full_name() or self.username return self.get_full_name() or self.username
def get_name_suffix(self): def get_name_suffix(self):
return self.detail return self.structure_level
def set_name_suffix(self, value): def set_name_suffix(self, value):
self.detail = value self.structure_level = value
name_suffix = property(get_name_suffix, set_name_suffix) name_suffix = property(get_name_suffix, set_name_suffix)
@ -131,7 +131,8 @@ class User(DjangoUser, PersonMixin, Person, SlideMixin):
register_slidemodel(User) register_slidemodel(User)
class Group(DjangoGroup, PersonMixin, Person): class Group(DjangoGroup, PersonMixin, Person, SlideMixin):
prefix = 'group' # This is for the slides
person_prefix = 'group' person_prefix = 'group'
django_group = models.OneToOneField(DjangoGroup, editable=False, parent_link=True) django_group = models.OneToOneField(DjangoGroup, editable=False, parent_link=True)
@ -161,6 +162,16 @@ class Group(DjangoGroup, PersonMixin, Person):
class Meta: class Meta:
ordering = ('name',) ordering = ('name',)
def slide(self):
"""
Returns a map with the data for the slides.
"""
return {
'group': self,
'title': self.name,
'template': 'projector/GroupSlide.html'}
register_slidemodel(Group)
class UsersAndGroupsToPersons(object): class UsersAndGroupsToPersons(object):
""" """

View File

@ -26,11 +26,11 @@
<option value="female"{% if 'female' in sortfilter.gender %} selected{% endif %}>{% trans "Female" %}</option> <option value="female"{% if 'female' in sortfilter.gender %} selected{% endif %}>{% trans "Female" %}</option>
<option value=""{% if '' in sortfilter.gender %} selected{% endif %}>{% trans "Not specified" %}</option> <option value=""{% if '' in sortfilter.gender %} selected{% endif %}>{% trans "Not specified" %}</option>
</select> </select>
<select class="default-input" name="detail" onchange="document.forms['filter'].submit()"> <select class="default-input" name="structure_level" onchange="document.forms['filter'].submit()">
<option value="---">-- {% trans "Detail" %} --</option> <option value="---">-- {% trans "Structure level" %} --</option>
{% for detail in details %} {% for level in structure_levels %}
<option value="{{ detail }}"{% if detail in sortfilter.detail %} selected{% endif %}> <option value="{{ level }}"{% if level in sortfilter.structure_level %} selected{% endif %}>
{{ detail }}</option> {{ level }}</option>
{% endfor %} {% endfor %}
</select> </select>
<select class="default-input" name="type" onchange="document.forms['filter'].submit()"> <select class="default-input" name="type" onchange="document.forms['filter'].submit()">
@ -65,7 +65,7 @@
<tr> <tr>
<th><a href="?sort=first_name&reverse={% if 'first_name' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "First Name" %}</a></th> <th><a href="?sort=first_name&reverse={% if 'first_name' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "First Name" %}</a></th>
<th><a href="?sort=last_name&reverse={% if 'last_name' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "Last Name" %}</a></th> <th><a href="?sort=last_name&reverse={% if 'last_name' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "Last Name" %}</a></th>
<th><a href="?sort=detail&reverse={% if 'detail' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "Detail" %}</a></th> <th><a href="?sort=structure_level&reverse={% if 'structure_level' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "Structure level" %}</a></th>
<th><a href="?sort=type&reverse={% if 'type' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "Type" %}</a></th> <th><a href="?sort=type&reverse={% if 'type' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "Type" %}</a></th>
<th><a href="?sort=committee&reverse={% if 'committee' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "Committee" %}</a></th> <th><a href="?sort=committee&reverse={% if 'committee' in sortfilter.sort and 'reverse' not in sortfilter %}1{% else %}---{%endif%}">{% trans "Committee" %}</a></th>
{% if perms.participant.can_manage_participant %} {% if perms.participant.can_manage_participant %}
@ -78,7 +78,7 @@
<tr class="{% cycle '' 'odd' %}"> <tr class="{% cycle '' 'odd' %}">
<td><a href="{% model_url user 'view' %}">{{ user.first_name }}</a></td> <td><a href="{% model_url user 'view' %}">{{ user.first_name }}</a></td>
<td><a href="{% model_url user 'view' %}">{{ user.last_name }}</a></td> <td><a href="{% model_url user 'view' %}">{{ user.last_name }}</a></td>
<td>{{ user.detail }}</td> <td>{{ user.structure_level }}</td>
<td>{{ user.get_type_display }}</td> <td>{{ user.get_type_display }}</td>
<td>{{ user.committee }}</td> <td>{{ user.committee }}</td>
{% if perms.participant.can_manage_participant %} {% if perms.participant.can_manage_participant %}
@ -93,10 +93,12 @@
<a href="{% url user_edit user.id %}"> <a href="{% url user_edit user.id %}">
<img src="{% static 'images/icons/edit.png' %}" title="{% trans 'Edit participant' %}"> <img src="{% static 'images/icons/edit.png' %}" title="{% trans 'Edit participant' %}">
</a> </a>
{% if user != request_user and not user.is_superuser %} {% if user != request_user %}
<a href="{% url user_delete user.id %}"> <a href="{% url user_delete user.id %}">
<img src="{% static 'images/icons/delete.png' %}" title="{% trans 'Delete participant' %}"> <img src="{% static 'images/icons/delete.png' %}" title="{% trans 'Delete participant' %}">
</a> </a>
{% endif %}
{% if user != request_user and not user.is_superuser %}
<a class="status_link deactivate" href="{% url user_status_deactivate user.id %}" title="{% trans 'Change status to inactive' %}"{% if not user.is_active %} style="display:none"{% endif %}> <a class="status_link deactivate" href="{% url user_status_deactivate user.id %}" title="{% trans 'Change status to inactive' %}"{% if not user.is_active %} style="display:none"{% endif %}>
<span></span> <span></span>
</a> </a>

View File

@ -14,7 +14,7 @@
{% endif %} {% endif %}
</li> </li>
{% empty %} {% empty %}
<li>{% trans "None" %}</li> <li><i>{% trans "None" %}</i></li>
{% endfor %} {% endfor %}
</ul> </ul>
@ -33,7 +33,7 @@
{% endif %} {% endif %}
</li> </li>
{% empty %} {% empty %}
<li>{% trans "None" %}</li> <li><i>{% trans "None" %}</i></li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}
@ -44,6 +44,6 @@
{% for assignment in assignments %} {% for assignment in assignments %}
<li><a href="{% model_url assignment 'view' %}">{{ assignment }}</a></li> <li><a href="{% model_url assignment 'view' %}">{{ assignment }}</a></li>
{% empty %} {% empty %}
<li>{% trans "None" %}</li> <li><i>{% trans "None" %}</i></li>
{% endfor %} {% endfor %}
</ul> </ul>

View File

@ -13,11 +13,11 @@
<h2>{% trans "Groups" %}</h2> <h2>{% trans "Groups" %}</h2>
<p> <p>
{% for group in shown_user.groups.all %} {% if shown_user.groups.all %}
{{ group }}, {{ shown_user.groups.all|join:", " }}
{% empty %} {% else %}
{% trans "The participant is not member of any group." %} {% trans "The participant is not member of any group." %}
{% endfor %} {% endif %}
</p> </p>
{% if shown_user.get_gender_display %} {% if shown_user.get_gender_display %}

View File

@ -0,0 +1,24 @@
{% extends "base-projector.html" %}
{% load i18n %}
{% load tags %}
{% block title %}{{ block.super }} - {{ title }}{% endblock %}
{% block content %}
<div class="item_fullscreen">{{ group }}
<span>
<p><i>{{ group.user_set.all.count }} {% trans "participants" %}:</i></p>
<p>
{% if group.user_set.all %}
{{ group.user_set.all|join:", " }}
{% endif %}
</p>
</span>
</div>
{% endblock %}
{% block scrollcontent %}
{% endblock %}

View File

@ -6,38 +6,16 @@
{% block title %}{{ block.super }} - {{ title }}{% endblock %} {% block title %}{{ block.super }} - {{ title }}{% endblock %}
{% block content %} {% block content %}
<div class="item_fullscreen">{{ shown_user }}
<div id='sidebar'> <span>
<div class='box'>
<p><strong>{% trans "Groups" %}</strong><br />
{% for group in shown_user.groups.all %}
{{ group }},
{% empty %}
{% trans "The participant is not member of any group." %}
{% endfor %}
</p>
{% if shown_user.get_gender_display %}
<p><strong>{% trans "Gender" %}</strong><br />{{ shown_user.get_gender_display }}</p>
{% endif %}
{% if shown_user.get_type_display %}
<p><strong>{% trans "Type" %}</strong><br />{{ shown_user.get_type_display }}</p>
{% endif %}
{% if shown_user.committee %} {% if shown_user.committee %}
<p><strong>{% trans "Committee" %}</strong><br />{{ shown_user.committee }}</p> <p>{{ shown_user.committee }}</p>
{% endif %} {% endif %}
<p>
{% if shown_user.groups.all %}
{{ shown_user.groups.all|join:", " }}
{% endif %}
</p>
</span>
</div> </div>
</div>
<h1>{{ shown_user }}</h1>
<p>{{ shown_user.email }}</p>
{% endblock %}
{% block scrollcontent %}
<p>
<div class="text">{{ shown_user.about_me|linebreaks }}</div>
</p>
{% endblock %} {% endblock %}

View File

@ -38,7 +38,7 @@ class UserTest(TestCase):
self.assertEqual(unicode(self.user1), 'Max Mustermann') self.assertEqual(unicode(self.user1), 'Max Mustermann')
def test_name_suffix(self): def test_name_suffix(self):
self.user1.detail = 'München' self.user1.structure_level = 'München'
self.user1.save() self.user1.save()
self.assertEqual(unicode(self.user1), 'Max Mustermann (München)') self.assertEqual(unicode(self.user1), 'Max Mustermann (München)')

View File

@ -71,7 +71,7 @@ class UserOverview(ListView):
except KeyError: except KeyError:
sortfilter = {} sortfilter = {}
for value in ['gender', 'detail', 'type', 'committee', 'status', for value in ['gender', 'structure_level', 'type', 'committee', 'status',
'sort', 'reverse']: 'sort', 'reverse']:
if value in self.request.REQUEST: if value in self.request.REQUEST:
if self.request.REQUEST[value] == '---': if self.request.REQUEST[value] == '---':
@ -85,8 +85,8 @@ class UserOverview(ListView):
query = User.objects query = User.objects
if 'gender' in sortfilter: if 'gender' in sortfilter:
query = query.filter(gender__iexact=sortfilter['gender'][0]) query = query.filter(gender__iexact=sortfilter['gender'][0])
if 'detail' in sortfilter: if 'structure_level' in sortfilter:
query = query.filter(detail__iexact=sortfilter['detail'][0]) query = query.filter(structure_level__iexact=sortfilter['structure_level'][0])
if 'type' in sortfilter: if 'type' in sortfilter:
query = query.filter(type__iexact=sortfilter['type'][0]) query = query.filter(type__iexact=sortfilter['type'][0])
if 'committee' in sortfilter: if 'committee' in sortfilter:
@ -97,7 +97,7 @@ class UserOverview(ListView):
if sortfilter['sort'][0] in ['first_name', 'last_name', 'last_login']: if sortfilter['sort'][0] in ['first_name', 'last_name', 'last_login']:
query = query.order_by(sortfilter['sort'][0]) query = query.order_by(sortfilter['sort'][0])
elif (sortfilter['sort'][0] in elif (sortfilter['sort'][0] in
['detail', 'type', 'committee', 'comment']): ['structure_level', 'type', 'committee', 'comment']):
query = query.order_by( query = query.order_by(
'%s' % sortfilter['sort'][0]) '%s' % sortfilter['sort'][0])
else: else:
@ -125,8 +125,8 @@ class UserOverview(ListView):
percent = 0 percent = 0
# list of all existing categories # list of all existing categories
details = [p['detail'] for p in User.objects.values('detail') structure_levels = [p['structure_level'] for p in User.objects.values('structure_level')
.exclude(detail='').distinct()] .exclude(structure_level='').distinct()]
# list of all existing committees # list of all existing committees
committees = [p['committee'] for p in User.objects.values('committee') committees = [p['committee'] for p in User.objects.values('committee')
.exclude(committee='').distinct()] .exclude(committee='').distinct()]
@ -135,7 +135,7 @@ class UserOverview(ListView):
'allusers': all_users, 'allusers': all_users,
'request_user': self.request.user, 'request_user': self.request.user,
'percent': round(percent, 1), 'percent': round(percent, 1),
'details': details, 'structure_levels': structure_levels,
'committees': committees, 'committees': committees,
'cookie': ['participant_sortfilter', urlencode(decodedict(self.sortfilter), 'cookie': ['participant_sortfilter', urlencode(decodedict(self.sortfilter),
doseq=True)], doseq=True)],
@ -208,8 +208,6 @@ class UserDeleteView(DeleteView):
def pre_redirect(self, request, *args, **kwargs): def pre_redirect(self, request, *args, **kwargs):
if self.get_object() == self.request.user: if self.get_object() == self.request.user:
messages.error(request, _("You can not delete yourself.")) messages.error(request, _("You can not delete yourself."))
elif self.get_object().is_superuser:
messages.error(request, _("You can not delete the administrator."))
else: else:
super(DeleteView, self).pre_redirect(request, *args, **kwargs) super(DeleteView, self).pre_redirect(request, *args, **kwargs)
@ -268,8 +266,8 @@ class ParticipantsListPDF(PDFView):
counter, counter,
Paragraph(user.last_name, stylesheet['Tablecell']), Paragraph(user.last_name, stylesheet['Tablecell']),
Paragraph(user.first_name, stylesheet['Tablecell']), Paragraph(user.first_name, stylesheet['Tablecell']),
Paragraph(user.detail, stylesheet['Tablecell']), Paragraph(user.structure_level, stylesheet['Tablecell']),
Paragraph(user.type, stylesheet['Tablecell']), Paragraph(user.get_type_display(), stylesheet['Tablecell']),
Paragraph(user.committee, stylesheet['Tablecell'])]) Paragraph(user.committee, stylesheet['Tablecell'])])
t = LongTable(data, style=[ t = LongTable(data, style=[
('VALIGN', (0, 0), (-1, -1), 'TOP'), ('VALIGN', (0, 0), (-1, -1), 'TOP'),

View File

@ -155,6 +155,10 @@ body{
font-weight:bold; font-weight:bold;
text-align: center; text-align: center;
} }
.item_fullscreen span
{
font-size: 50%; font-weight:normal;
}
/* items in a list*/ /* items in a list*/
.itemlist li .itemlist li

View File

@ -15,27 +15,6 @@
{% block content %} {% block content %}
<h1>{% trans 'Dashboard' %}</h1> <h1>{% trans 'Dashboard' %}</h1>
{% if perms.projector.can_manage_projector %}
<div style="text-align: right; padding: 0 10px 5px 0; margin-top:-20px;">
<!-- control projector view -->
{% trans "Adjust projector view" %}:
<a class="projector_edit" href="{% url projector_bigger %}" title="{% trans 'Zoom in' %}">
<img src="{% static 'images/icons/zoom-in.png' %}" />
</a>
<a class="projector_edit" href="{% url projector_smaller %}" title="{% trans 'Zoom out' %}">
<img src="{% static 'images/icons/zoom-out.png' %}" />
</a>
<a class="projector_edit" href="{% url projector_up %}" title="{% trans 'Scroll text up' %}">
<img src="{% static 'images/icons/go-up.png' %}" />
</a>
<a class="projector_edit" href="{% url projector_down %}" title="{% trans 'Scroll text down' %}">
<img src="{% static 'images/icons/go-down.png' %}" />
</a>
<a class="projector_edit" href="{% url projector_clean %}" title="{% trans 'Reset projector view' %}">
<img src="{% static 'images/icons/view-reset.png' %}" />
</a>
</div>
{% endif %}
<div class="column" id="col1"> <div class="column" id="col1">
{% for name, widget in widgets.items %} {% for name, widget in widgets.items %}

View File

@ -4,6 +4,5 @@
{% load i18n %} {% load i18n %}
{% block content %} {% block content %}
<h1>{% get_config 'frontpage_title' %}</h1> <div class="item_fullscreen">{% get_config 'welcome_title' %}</div>
{% get_config 'frontpage_welcometext' %}
{% endblock %} {% endblock %}

View File

@ -1,7 +1,36 @@
{% load i18n %} {% load i18n %}
{% load tags %} {% load tags %}
{% load staticfiles %}
<!-- projector control buttons -->
{% if perms.projector.can_manage_projector %}
<div style="float: right;">
<p>
<a class="projector_edit" href="{% url projector_bigger %}" title="{% trans 'Zoom in' %}">
<img src="{% static 'images/icons/zoom-in.png' %}" />
</a><br>
<a class="projector_edit" href="{% url projector_smaller %}" title="{% trans 'Zoom out' %}">
<img src="{% static 'images/icons/zoom-out.png' %}" />
</a>
</p>
<p>
<a class="projector_edit" href="{% url projector_up %}" title="{% trans 'Scroll text up' %}">
<img src="{% static 'images/icons/go-up.png' %}" />
</a><br>
<a class="projector_edit" href="{% url projector_down %}" title="{% trans 'Scroll text down' %}">
<img src="{% static 'images/icons/go-down.png' %}" />
</a>
</p>
<p>
<a class="projector_edit" href="{% url projector_clean %}" title="{% trans 'Reset projector view' %}">
<img src="{% static 'images/icons/view-reset.png' %}" />
</a>
</p>
</div>
{% endif %}
<!-- projector view -->
<a href="{% url projector_show %}" target="_blank"> <a href="{% url projector_show %}" target="_blank">
<div id="iframewrapper"> <div id="iframewrapper">
<iframe id="iframe" src="{% url projector_show %}" frameborder="0"></iframe> <iframe id="iframe" src="{% url projector_show %}" frameborder="0"></iframe>

View File

@ -1 +0,0 @@
{{ welcometext|safe|linebreaks }}

View File

@ -22,6 +22,7 @@ from django.db import transaction
from django.db.models import Q from django.db.models import Q
from django.dispatch import receiver from django.dispatch import receiver
from django.shortcuts import redirect from django.shortcuts import redirect
from django.template import RequestContext
from django.utils.datastructures import SortedDict from django.utils.datastructures import SortedDict
from django.utils.importlib import import_module from django.utils.importlib import import_module
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -396,10 +397,10 @@ def get_widgets(request):
# welcome widget # welcome widget
context = { context = {
'welcometext': config['frontpage_welcometext']} 'welcometext': config['welcome_text']}
widgets.append(Widget( widgets.append(Widget(
name='welcome', name='welcome',
display_name=config['frontpage_title'], display_name=config['welcome_title'],
template='projector/welcome_widget.html', template='projector/welcome_widget.html',
context=context, context=context,
permission_required='projector.can_see_dashboard', permission_required='projector.can_see_dashboard',
@ -410,6 +411,7 @@ def get_widgets(request):
name='live_view', name='live_view',
display_name=_('Projector live view'), display_name=_('Projector live view'),
template='projector/live_view_widget.html', template='projector/live_view_widget.html',
context = RequestContext(request, {}),
permission_required='projector.can_see_projector', permission_required='projector.can_see_projector',
default_column=2)) default_column=2))

View File

@ -316,7 +316,7 @@ input[type="submit"], input[type="button"] {
padding:4px 10px !important; padding:4px 10px !important;
margin: 2px 0 2px 0; margin: 2px 0 2px 0;
} }
#id_permissions { #id_permissions, #id_users {
height: 310px; height: 310px;
} }
.button { .button {

View File

@ -76,7 +76,7 @@
{% endblock %} {% endblock %}
<div id="footer"> <div id="footer">
<small> <small>
&copy; Copyright 2011-2012 | Powered by <a href="http://openslides.org" target="_blank">OpenSlides</a> | Get <a href="http://openslides.org/support" target="_blank">professional support</a> for OpenSlides. &copy; Copyright 2011-2012 | Powered by <a href="http://openslides.org" target="_blank">OpenSlides</a> | {% trans "Get <a href='http://openslides.org/support' target='_blank'>professional support</a> for OpenSlides." %}
</small> </small>
</div> </div>
</div> </div>

View File

@ -1,29 +0,0 @@
{% extends "base.html" %}
{% load i18n %}
{% load staticfiles %}
{% block title %}{{ block.super }} {% trans "Home" %}{% endblock %}
{% block content %}
<h1>{{ title }}</h1>
<p>{{ welcometext|safe|linebreaks }}</p>
{% trans "You have access to the following pages:" %}
<ul>
{% for app in apps %}
<li><a href="{{ app.url }}">{{ app.title }}</a></li>
{% endfor %}
</ul>
{% endblock %}
{% block submenu %}
{% if perms.projector.can_see_projector %}
<h4 class="sectiontitle">{% trans "Home" %}</h4>
<ul>
<li>
<a href="{% url projector_show %}"><img src="{% static 'images/icons/projector.png' %}"> {% trans 'Projector view' %}</a>
</li>
</ul>
{% endif %}
{% endblock %}

View File

@ -16,14 +16,13 @@ from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils.importlib import import_module from django.utils.importlib import import_module
from openslides.utils.views import FrontPage from openslides.utils.views import RedirectView
handler500 = 'openslides.utils.views.server_error' handler500 = 'openslides.utils.views.server_error'
urlpatterns = patterns('', urlpatterns = patterns('',
# frontpage # Redirect to dashboard URL
(r'^$', FrontPage.as_view()), url(r'^$', RedirectView.as_view(url='dashboard'), name='home',),
(r'^agenda/', include('openslides.agenda.urls')), (r'^agenda/', include('openslides.agenda.urls')),
(r'^motion/', include('openslides.motion.urls')), (r'^motion/', include('openslides.motion.urls')),

View File

@ -20,6 +20,7 @@ from reportlab.pdfbase.ttfonts import TTFont
from reportlab.rl_config import defaultPageSize from reportlab.rl_config import defaultPageSize
from django.conf import settings from django.conf import settings
from django.utils import formats
# Import gettext for python 2.5 support # Import gettext for python 2.5 support
from django.utils.translation import ugettext as _, gettext from django.utils.translation import ugettext as _, gettext
@ -222,8 +223,8 @@ def firstPage(canvas, doc):
# time # time
canvas.setFont('Ubuntu', 7) canvas.setFont('Ubuntu', 7)
time = datetime.now().strftime(gettext("%Y-%m-%d %H:%Mh")) time = formats.date_format(datetime.now(), 'DATETIME_FORMAT')
canvas.drawString(15 * cm, 28 * cm, _("Printed: %s") % time) canvas.drawString(15 * cm, 28 * cm, _("As of: %s") % time)
# title # title
if doc.title: if doc.title:

View File

@ -358,33 +358,6 @@ class PDFView(PermissionMixin, View):
return self.render_to_response(self.get_filename()) return self.render_to_response(self.get_filename())
class FrontPage(TemplateView):
template_name = 'front_page.html'
def has_permission(self, request):
if request.user.is_authenticated() or config['system_enable_anonymous']:
return True
return False
def get_context_data(self, **kwargs):
context = super(FrontPage, self).get_context_data(**kwargs)
apps = []
for app in settings.INSTALLED_APPS:
try:
mod = import_module(app + '.views')
tab = mod.register_tab(self.request)
except (ImportError, AttributeError):
continue
if tab.permission:
apps.append(tab)
context.update({
'apps': apps,
'title': config['frontpage_title'],
'welcometext': config['frontpage_welcometext'],
})
return context
def server_error(request, template_name='500.html'): def server_error(request, template_name='500.html'):
""" """
500 error handler. 500 error handler.