Merge branch 'master' of github.com:OpenSlides/OpenSlides into sort_person_api
This commit is contained in:
commit
8014f327a2
11
INSTALL.txt
11
INSTALL.txt
@ -98,13 +98,12 @@ II. Installation on GNU/Linux and MacOSX
|
||||
|
||||
OR
|
||||
|
||||
b) Clone development version from mercurial repository
|
||||
http://hg.openslides.org. This requires Mercurial source control
|
||||
management (hg):
|
||||
b) Clone development version from OpenSlides' github repository
|
||||
https://github.com/OpenSlides/OpenSlides.
|
||||
This requires Git, see http://git-scm.com/.
|
||||
Open command line (cmd) and run:
|
||||
|
||||
E.g. for Ubuntu run:
|
||||
$ sudo apt-get install mercurial
|
||||
$ hg clone http://hg.openslides.org OpenSlides
|
||||
git clone git://github.com/OpenSlides/OpenSlides.git
|
||||
|
||||
3. Setup your virtual environment with virtualenv:
|
||||
|
||||
|
@ -6,17 +6,11 @@ How to create a new portable Windows distribution of OpenSlides:
|
||||
|
||||
easy_install -Z django django-mptt reportlab pil
|
||||
|
||||
2.) Install OpenSlides by running in the top directory:
|
||||
|
||||
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:
|
||||
2.) Run in the main directory of the OpenSlides checkout:
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
@ -18,8 +18,6 @@ import zipfile
|
||||
import distutils.ccompiler
|
||||
import distutils.sysconfig
|
||||
|
||||
from contextlib import nested
|
||||
|
||||
import pkg_resources
|
||||
|
||||
sys.path.insert(0, os.getcwd())
|
||||
@ -80,10 +78,7 @@ SITE_PACKAGES = {
|
||||
"pil": {
|
||||
# NOTE: PIL is a special case, see copy_pil
|
||||
"copy": [],
|
||||
},
|
||||
"openslides": {
|
||||
"copy" : ["openslides"],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
PY_DLLS = [
|
||||
@ -297,9 +292,13 @@ def main():
|
||||
raise
|
||||
|
||||
os.makedirs(odir)
|
||||
out_site_packages = os.path.join(odir, "site-packages")
|
||||
|
||||
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():
|
||||
sys.stdout.write("Using prebuild openslides.exe\n")
|
||||
|
@ -3,7 +3,7 @@
|
||||
"pk": 1,
|
||||
"model": "auth.group",
|
||||
"fields": {
|
||||
"name": "Beobachter",
|
||||
"name": "Beobachter/in",
|
||||
"permissions": [
|
||||
[
|
||||
"can_see_agenda",
|
||||
@ -57,7 +57,7 @@
|
||||
"pk": 2,
|
||||
"model": "auth.group",
|
||||
"fields": {
|
||||
"name": "Delegierter",
|
||||
"name": "Delegierte/r",
|
||||
"permissions": [
|
||||
[
|
||||
"can_see_agenda",
|
||||
|
@ -231,4 +231,4 @@ def get_widgets(request):
|
||||
context={
|
||||
'agenda': SLIDE['agenda'],
|
||||
'items': Item.objects.all()},
|
||||
permission_required='agenda.can_manage_agenda')]
|
||||
permission_required='projector.can_manage_projector')]
|
||||
|
@ -85,7 +85,7 @@ class Assignment(models.Model, SlideMixin):
|
||||
raise NameError(_('<b>%s</b> is already a candidate.') % candidate)
|
||||
if not person.has_perm("assignment.can_manage_assignment") and self.status != 'sea':
|
||||
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 \
|
||||
not person.has_perm("assignment.can_manage_assignment"):
|
||||
# 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
|
||||
"""
|
||||
try:
|
||||
candidation = self.assignment_candidats.get(person=candidate)
|
||||
candidation = self.assignment_candidates.get(person=candidate)
|
||||
except AssignmentCandidate.DoesNotExist:
|
||||
# TODO: Use an OpenSlides Error
|
||||
raise Exception(_('%s is no candidate') % candidate)
|
||||
|
||||
if not candidation.blocked:
|
||||
@ -123,7 +122,7 @@ class Assignment(models.Model, SlideMixin):
|
||||
return True, if person is a candidate.
|
||||
"""
|
||||
try:
|
||||
return self.assignment_candidats.filter(person=person) \
|
||||
return self.assignment_candidates.filter(person=person) \
|
||||
.exclude(blocked=True).exists()
|
||||
except AttributeError:
|
||||
return False
|
||||
@ -132,11 +131,11 @@ class Assignment(models.Model, SlideMixin):
|
||||
"""
|
||||
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()
|
||||
|
||||
@property
|
||||
def assignment_candidats(self):
|
||||
def assignment_candidates(self):
|
||||
return AssignmentCandidate.objects.filter(assignment=self)
|
||||
|
||||
@property
|
||||
@ -148,7 +147,7 @@ class Assignment(models.Model, SlideMixin):
|
||||
return self.get_participants(only_elected=True)
|
||||
|
||||
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)
|
||||
|
||||
@ -167,7 +166,7 @@ class Assignment(models.Model, SlideMixin):
|
||||
|
||||
|
||||
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.save()
|
||||
|
||||
@ -293,7 +292,7 @@ class AssignmentPoll(BasePoll, CountInvalid, CountVotesCast, PublishPollMixin):
|
||||
self.yesnoabstain = True
|
||||
else:
|
||||
# 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
|
||||
else:
|
||||
self.yesnoabstain = False
|
||||
|
@ -32,10 +32,11 @@
|
||||
{% if assignment.active %}activeline{% endif %}">
|
||||
<td><a href="{% url assignment_view assignment.id %}">{{ assignment }}</a></td>
|
||||
<td>
|
||||
{{ assignment.posts }} {% trans "posts" %} / {{ assignment.elected|length }} {% trans "elected" %}
|
||||
{% blocktrans with posts=assignment.posts %}posts: {{ posts }}{% endblocktrans %}
|
||||
{% if assignment.status != 'fin' %}
|
||||
/ {{ assignment.candidates|length }} {% trans "candidates" %}
|
||||
| {% blocktrans with candidates=assignment.get_participants|length %}candidates: {{ candidates }}{% endblocktrans %}
|
||||
{% endif %}
|
||||
| {% blocktrans with elected=assignment.elected|length %}elected: {{ elected }}{% endblocktrans %}
|
||||
</td>
|
||||
<td>{{ assignment.get_status_display }}</td>
|
||||
<td>
|
||||
|
@ -33,9 +33,10 @@
|
||||
<h1>{{ assignment }}</h1>
|
||||
<p>{{ assignment.description|linebreaks }}</p>
|
||||
|
||||
{% if assignment.status != "fin" %}
|
||||
<h3>{% trans "Candidates" %}</h3>
|
||||
<ol>
|
||||
{% for person in assignment.candidates %}
|
||||
{% for person in assignment.get_participants %}
|
||||
<li>
|
||||
{{ person }}
|
||||
{% 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>
|
||||
{% 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>
|
||||
{% empty %}
|
||||
<li style="list-style: none outside none;"><i>{% trans "No candidates available." %}</i></li>
|
||||
@ -85,27 +94,11 @@
|
||||
</p>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<h3>{% trans "Elected Candidates" %}</h3>
|
||||
<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 %}
|
||||
{% if perms.assignment.can_manage_assignments and blocked_candidates and assignment.status != "fin" %}
|
||||
<h3>{% trans "Blocked Candidates" %}</h3>
|
||||
<ul>
|
||||
{% for person in blocked_candidates %}
|
||||
@ -118,20 +111,11 @@
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% if assignment.status != "sea" or polls.exists %}
|
||||
<h3>{% trans "Election results" %}</h3>
|
||||
|
||||
{% if polls.exists %}
|
||||
<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>
|
||||
<th>{% trans "Candidates" %}</th>
|
||||
{% for poll in polls %}
|
||||
@ -161,7 +145,7 @@
|
||||
</tr>
|
||||
|
||||
{% 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 %}
|
||||
{% if perms.assignment.can_manage_assignment %}
|
||||
@ -198,8 +182,7 @@
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
<tr>
|
||||
<tr class="{% cycle rowcolors %}">
|
||||
<td>{% trans 'Invalid votes' %}</td>
|
||||
{% for poll in polls %}
|
||||
{% if poll.published or perms.assignment.can_manage_assignment %}
|
||||
@ -215,7 +198,6 @@
|
||||
<td></td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
|
||||
<tr class="total">
|
||||
<td><strong>{% trans 'Votes cast' %}</strong></td>
|
||||
{% for poll in polls %}
|
||||
@ -233,11 +215,8 @@
|
||||
{% endif %}
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{% else %}
|
||||
|
||||
<i>{% trans "No ballots available." %}</i>
|
||||
|
||||
<i>{% trans "No results available." %}</i>
|
||||
{% if assignment.candidates and perms.assignment.can_manage_assignment and assignment.status == "vot" %}
|
||||
<p><a href='{% url assignment_gen_poll assignment.id %}'>
|
||||
<span class="button">
|
||||
@ -245,9 +224,7 @@
|
||||
</span>
|
||||
</a></p>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
@ -62,7 +62,7 @@
|
||||
</tr>
|
||||
|
||||
{% 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 %}">
|
||||
{% if candidate in assignment.elected %}
|
||||
<a class="elected">
|
||||
@ -92,8 +92,7 @@
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
<tr>
|
||||
<tr class="{% cycle rowcolors %}">
|
||||
<td>{% trans 'Invalid votes' %}</td>
|
||||
{% for poll in polls %}
|
||||
<td style="white-space:nowrap;">
|
||||
@ -105,7 +104,6 @@
|
||||
|
||||
{% endfor %}
|
||||
</tr>
|
||||
|
||||
<tr class="total">
|
||||
<td>
|
||||
<strong>{% trans 'Votes cast' %}</strong>
|
||||
@ -120,12 +118,6 @@
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
{% elif some_polls_available %}
|
||||
<i>{% trans "Vote results are not published yet." %}</i>
|
||||
{% elif assignment.candidates %}
|
||||
<i>{% trans "No ballots available." %}</i>
|
||||
{% endif %}
|
||||
<br>
|
||||
{% endblock %}
|
||||
|
@ -101,7 +101,7 @@ def view(request, assignment_id=None):
|
||||
vote_results = assignment.vote_results(only_published=False)
|
||||
|
||||
blocked_candidates = [candidate.person for candidate in \
|
||||
assignment.assignment_candidats.filter(blocked=True)]
|
||||
assignment.assignment_candidates.filter(blocked=True)]
|
||||
return {
|
||||
'assignment': assignment,
|
||||
'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())
|
||||
except Assignment.DoesNotExist:
|
||||
pass
|
||||
except NameError, e:
|
||||
messages.error(request, e)
|
||||
return redirect(reverse('assignment_view', args=[assignment_id]))
|
||||
|
||||
|
||||
@ -678,4 +680,4 @@ def get_widgets(request):
|
||||
display_name=_('Elections'),
|
||||
template='assignment/widget.html',
|
||||
context={'assignments': Assignment.objects.all()},
|
||||
permission_required='assignment.can_manage_assignment')]
|
||||
permission_required='projector.can_manage_projector')]
|
||||
|
@ -56,13 +56,13 @@ class GeneralConfigForm(forms.Form, CssClassMixin):
|
||||
required=False,
|
||||
)
|
||||
|
||||
frontpage_title = forms.CharField(
|
||||
welcome_title = forms.CharField(
|
||||
widget=forms.TextInput(),
|
||||
label=_("Title"),
|
||||
required=False,
|
||||
)
|
||||
|
||||
frontpage_welcometext = forms.CharField(
|
||||
welcome_text = forms.CharField(
|
||||
widget=forms.Textarea(),
|
||||
label=_("Welcome text"),
|
||||
required=False,
|
||||
|
@ -86,8 +86,8 @@ def default_config(sender, key, **kwargs):
|
||||
'event_location': '',
|
||||
'event_organizer': '',
|
||||
'presentation': '',
|
||||
'frontpage_title': _('Welcome to OpenSlides'),
|
||||
'frontpage_welcometext': _('[Place for your welcome text.]'),
|
||||
'welcome_title': _('Welcome to OpenSlides'),
|
||||
'welcome_text': _('[Place for your welcome text.]'),
|
||||
'system_enable_anonymous': False,
|
||||
}.get(key)
|
||||
|
||||
|
@ -23,9 +23,9 @@
|
||||
</fieldset>
|
||||
<p></p>
|
||||
<fieldset>
|
||||
<legend>{% trans "Frontpage" %}</legend>
|
||||
<legend>{% trans "Welcome Widget" %}</legend>
|
||||
{% for field in form %}
|
||||
{% if "id_frontpage" in field.label_tag %}
|
||||
{% if "id_welcome" in field.label_tag %}
|
||||
<p>
|
||||
{{ field.errors }}
|
||||
{{ field.required }}
|
||||
|
@ -41,8 +41,8 @@ class GeneralConfig(FormView):
|
||||
'event_date': config['event_date'],
|
||||
'event_location': config['event_location'],
|
||||
'event_organizer': config['event_organizer'],
|
||||
'frontpage_title': config['frontpage_title'],
|
||||
'frontpage_welcometext': config['frontpage_welcometext'],
|
||||
'welcome_title': config['welcome_title'],
|
||||
'welcome_text': config['welcome_text'],
|
||||
'system_enable_anonymous': config['system_enable_anonymous'],
|
||||
}
|
||||
|
||||
@ -54,10 +54,9 @@ class GeneralConfig(FormView):
|
||||
config['event_location'] = form.cleaned_data['event_location']
|
||||
config['event_organizer'] = form.cleaned_data['event_organizer']
|
||||
|
||||
# frontpage
|
||||
config['frontpage_title'] = form.cleaned_data['frontpage_title']
|
||||
config['frontpage_welcometext'] = \
|
||||
form.cleaned_data['frontpage_welcometext']
|
||||
# welcome widget
|
||||
config['welcome_title'] = form.cleaned_data['welcome_title']
|
||||
config['welcome_text'] = form.cleaned_data['welcome_text']
|
||||
|
||||
# system
|
||||
if form.cleaned_data['system_enable_anonymous']:
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,8 @@ from openslides.config.signals import default_config_value
|
||||
from openslides.poll.models import (BaseOption, BasePoll, CountVotesCast,
|
||||
CountInvalid, BaseVote)
|
||||
|
||||
from openslides.participant.models import User, Group
|
||||
|
||||
from openslides.projector.api import register_slidemodel
|
||||
from openslides.projector.models import SlideMixin
|
||||
|
||||
@ -443,7 +445,10 @@ class Motion(models.Model, SlideMixin):
|
||||
self.log = ""
|
||||
self.log += u"%s | %s" % (datetime.now().strftime("%d.%m.%Y %H:%M:%S"), _propper_unicode(text))
|
||||
if user is not None:
|
||||
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.save()
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
<h1>{% trans "Import motions" %}</h1>
|
||||
<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>
|
||||
{% trans 'Required CSV file encoding: UTF-8 (Unicode).' %}
|
||||
</p>
|
||||
|
@ -52,7 +52,7 @@ from openslides.projector.projector import Widget
|
||||
from openslides.poll.views import PollFormView
|
||||
|
||||
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
|
||||
|
||||
@ -579,6 +579,8 @@ def motion_import(request):
|
||||
users_generated = 0
|
||||
motions_generated = 0
|
||||
motions_modified = 0
|
||||
groups_assigned = 0
|
||||
groups_generated = 0
|
||||
with transaction.commit_on_success():
|
||||
dialect = csv.Sniffer().sniff(request.FILES['csvfile'].readline())
|
||||
dialect = csv_ext.patchup(dialect)
|
||||
@ -588,7 +590,11 @@ def motion_import(request):
|
||||
if lno < 1:
|
||||
continue
|
||||
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:
|
||||
messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1))
|
||||
continue
|
||||
@ -605,17 +611,43 @@ def motion_import(request):
|
||||
except ValueError:
|
||||
messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1))
|
||||
continue
|
||||
|
||||
if is_group:
|
||||
# fetch existing groups or issue an error message
|
||||
try:
|
||||
user = Group.objects.get(name=last_name)
|
||||
if user.group_as_person == False:
|
||||
messages.error(request, _('Ignoring line %d because the assigned group may not act as a person.') % (lno + 1))
|
||||
continue
|
||||
else:
|
||||
user = get_person(user.person_id)
|
||||
|
||||
groups_assigned += 1
|
||||
except Group.DoesNotExist:
|
||||
group = Group()
|
||||
group.group_as_person = True
|
||||
group.description = _('Created by motion import.')
|
||||
group.name = last_name
|
||||
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.detail = ''
|
||||
user.structure_level = ''
|
||||
user.committee = ''
|
||||
user.gender = ''
|
||||
user.type = ''
|
||||
@ -653,6 +685,12 @@ def motion_import(request):
|
||||
'%d motions were successfully modified.', motions_modified) % motions_modified)
|
||||
if 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'))
|
||||
|
||||
except csv.Error:
|
||||
@ -928,4 +966,4 @@ def get_widgets(request):
|
||||
display_name=_('Motions'),
|
||||
template='motion/widget.html',
|
||||
context={'motions': Motion.objects.all()},
|
||||
permission_required='motion.can_manage_motion')]
|
||||
permission_required='projector.can_manage_projector')]
|
||||
|
@ -71,7 +71,7 @@ def import_users(csv_file):
|
||||
dialect=dialect)):
|
||||
if line_no:
|
||||
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:
|
||||
error_messages.append(_('Ignoring malformed line %d in import file.') % line_no + 1)
|
||||
continue
|
||||
@ -80,7 +80,7 @@ def import_users(csv_file):
|
||||
user.first_name = first_name
|
||||
user.username = gen_username(first_name, last_name)
|
||||
user.gender = gender
|
||||
user.detail = detail
|
||||
user.structure_level = structure_level
|
||||
user.type = type
|
||||
user.committee = committee
|
||||
user.comment = comment
|
||||
|
@ -27,7 +27,7 @@ class UserCreateForm(forms.ModelForm, CssClassMixin):
|
||||
|
||||
class Meta:
|
||||
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')
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ class UserUpdateForm(UserCreateForm):
|
||||
class Meta:
|
||||
model = User
|
||||
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')
|
||||
|
||||
|
||||
|
@ -40,8 +40,8 @@ class User(DjangoUser, PersonMixin, Person, SlideMixin):
|
||||
)
|
||||
|
||||
django_user = models.OneToOneField(DjangoUser, editable=False, parent_link=True)
|
||||
detail = models.CharField(
|
||||
max_length=100, blank=True, default='', verbose_name=_("Detail"),
|
||||
structure_level = models.CharField(
|
||||
max_length=100, blank=True, default='', verbose_name=_("Structure level"),
|
||||
help_text=_('Will be shown after the name.'))
|
||||
gender = models.CharField(
|
||||
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
|
||||
|
||||
def get_name_suffix(self):
|
||||
return self.detail
|
||||
return self.structure_level
|
||||
|
||||
def set_name_suffix(self, value):
|
||||
self.detail = value
|
||||
self.structure_level = value
|
||||
|
||||
name_suffix = property(get_name_suffix, set_name_suffix)
|
||||
|
||||
@ -131,7 +131,8 @@ class User(DjangoUser, PersonMixin, Person, SlideMixin):
|
||||
|
||||
register_slidemodel(User)
|
||||
|
||||
class Group(DjangoGroup, PersonMixin, Person):
|
||||
class Group(DjangoGroup, PersonMixin, Person, SlideMixin):
|
||||
prefix = 'group' # This is for the slides
|
||||
person_prefix = 'group'
|
||||
|
||||
django_group = models.OneToOneField(DjangoGroup, editable=False, parent_link=True)
|
||||
@ -161,6 +162,16 @@ class Group(DjangoGroup, PersonMixin, Person):
|
||||
class Meta:
|
||||
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):
|
||||
"""
|
||||
|
@ -26,11 +26,11 @@
|
||||
<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>
|
||||
</select>
|
||||
<select class="default-input" name="detail" onchange="document.forms['filter'].submit()">
|
||||
<option value="---">-- {% trans "Detail" %} --</option>
|
||||
{% for detail in details %}
|
||||
<option value="{{ detail }}"{% if detail in sortfilter.detail %} selected{% endif %}>
|
||||
{{ detail }}</option>
|
||||
<select class="default-input" name="structure_level" onchange="document.forms['filter'].submit()">
|
||||
<option value="---">-- {% trans "Structure level" %} --</option>
|
||||
{% for level in structure_levels %}
|
||||
<option value="{{ level }}"{% if level in sortfilter.structure_level %} selected{% endif %}>
|
||||
{{ level }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<select class="default-input" name="type" onchange="document.forms['filter'].submit()">
|
||||
@ -65,7 +65,7 @@
|
||||
<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=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=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 %}
|
||||
@ -78,7 +78,7 @@
|
||||
<tr class="{% cycle '' 'odd' %}">
|
||||
<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>{{ user.detail }}</td>
|
||||
<td>{{ user.structure_level }}</td>
|
||||
<td>{{ user.get_type_display }}</td>
|
||||
<td>{{ user.committee }}</td>
|
||||
{% if perms.participant.can_manage_participant %}
|
||||
@ -93,10 +93,12 @@
|
||||
<a href="{% url user_edit user.id %}">
|
||||
<img src="{% static 'images/icons/edit.png' %}" title="{% trans 'Edit participant' %}">
|
||||
</a>
|
||||
{% if user != request_user and not user.is_superuser %}
|
||||
{% if user != request_user %}
|
||||
<a href="{% url user_delete user.id %}">
|
||||
<img src="{% static 'images/icons/delete.png' %}" title="{% trans 'Delete participant' %}">
|
||||
</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 %}>
|
||||
<span></span>
|
||||
</a>
|
||||
|
@ -14,7 +14,7 @@
|
||||
{% endif %}
|
||||
</li>
|
||||
{% empty %}
|
||||
<li>{% trans "None" %}</li>
|
||||
<li><i>{% trans "None" %}</i></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
{% endif %}
|
||||
</li>
|
||||
{% empty %}
|
||||
<li>{% trans "None" %}</li>
|
||||
<li><i>{% trans "None" %}</i></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
@ -44,6 +44,6 @@
|
||||
{% for assignment in assignments %}
|
||||
<li><a href="{% model_url assignment 'view' %}">{{ assignment }}</a></li>
|
||||
{% empty %}
|
||||
<li>{% trans "None" %}</li>
|
||||
<li><i>{% trans "None" %}</i></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
@ -13,11 +13,11 @@
|
||||
|
||||
<h2>{% trans "Groups" %}</h2>
|
||||
<p>
|
||||
{% for group in shown_user.groups.all %}
|
||||
{{ group }},
|
||||
{% empty %}
|
||||
{% if shown_user.groups.all %}
|
||||
{{ shown_user.groups.all|join:", " }}
|
||||
{% else %}
|
||||
{% trans "The participant is not member of any group." %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% if shown_user.get_gender_display %}
|
||||
|
24
openslides/participant/templates/projector/GroupSlide.html
Normal file
24
openslides/participant/templates/projector/GroupSlide.html
Normal 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 %}
|
@ -6,38 +6,16 @@
|
||||
{% block title %}{{ block.super }} - {{ title }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div id='sidebar'>
|
||||
<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 %}
|
||||
|
||||
<div class="item_fullscreen">{{ shown_user }}
|
||||
<span>
|
||||
{% if shown_user.committee %}
|
||||
<p><strong>{% trans "Committee" %}</strong><br />{{ shown_user.committee }}</p>
|
||||
<p>{{ shown_user.committee }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>{{ shown_user }}</h1>
|
||||
<p>{{ shown_user.email }}</p>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scrollcontent %}
|
||||
<p>
|
||||
<div class="text">{{ shown_user.about_me|linebreaks }}</div>
|
||||
{% if shown_user.groups.all %}
|
||||
{{ shown_user.groups.all|join:", " }}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -38,7 +38,7 @@ class UserTest(TestCase):
|
||||
self.assertEqual(unicode(self.user1), 'Max Mustermann')
|
||||
|
||||
def test_name_suffix(self):
|
||||
self.user1.detail = 'München'
|
||||
self.user1.structure_level = 'München'
|
||||
self.user1.save()
|
||||
self.assertEqual(unicode(self.user1), 'Max Mustermann (München)')
|
||||
|
||||
|
@ -71,7 +71,7 @@ class UserOverview(ListView):
|
||||
except KeyError:
|
||||
sortfilter = {}
|
||||
|
||||
for value in ['gender', 'detail', 'type', 'committee', 'status',
|
||||
for value in ['gender', 'structure_level', 'type', 'committee', 'status',
|
||||
'sort', 'reverse']:
|
||||
if value in self.request.REQUEST:
|
||||
if self.request.REQUEST[value] == '---':
|
||||
@ -85,8 +85,8 @@ class UserOverview(ListView):
|
||||
query = User.objects
|
||||
if 'gender' in sortfilter:
|
||||
query = query.filter(gender__iexact=sortfilter['gender'][0])
|
||||
if 'detail' in sortfilter:
|
||||
query = query.filter(detail__iexact=sortfilter['detail'][0])
|
||||
if 'structure_level' in sortfilter:
|
||||
query = query.filter(structure_level__iexact=sortfilter['structure_level'][0])
|
||||
if 'type' in sortfilter:
|
||||
query = query.filter(type__iexact=sortfilter['type'][0])
|
||||
if 'committee' in sortfilter:
|
||||
@ -97,7 +97,7 @@ class UserOverview(ListView):
|
||||
if sortfilter['sort'][0] in ['first_name', 'last_name', 'last_login']:
|
||||
query = query.order_by(sortfilter['sort'][0])
|
||||
elif (sortfilter['sort'][0] in
|
||||
['detail', 'type', 'committee', 'comment']):
|
||||
['structure_level', 'type', 'committee', 'comment']):
|
||||
query = query.order_by(
|
||||
'%s' % sortfilter['sort'][0])
|
||||
else:
|
||||
@ -125,8 +125,8 @@ class UserOverview(ListView):
|
||||
percent = 0
|
||||
|
||||
# list of all existing categories
|
||||
details = [p['detail'] for p in User.objects.values('detail')
|
||||
.exclude(detail='').distinct()]
|
||||
structure_levels = [p['structure_level'] for p in User.objects.values('structure_level')
|
||||
.exclude(structure_level='').distinct()]
|
||||
# list of all existing committees
|
||||
committees = [p['committee'] for p in User.objects.values('committee')
|
||||
.exclude(committee='').distinct()]
|
||||
@ -135,7 +135,7 @@ class UserOverview(ListView):
|
||||
'allusers': all_users,
|
||||
'request_user': self.request.user,
|
||||
'percent': round(percent, 1),
|
||||
'details': details,
|
||||
'structure_levels': structure_levels,
|
||||
'committees': committees,
|
||||
'cookie': ['participant_sortfilter', urlencode(decodedict(self.sortfilter),
|
||||
doseq=True)],
|
||||
@ -208,8 +208,6 @@ class UserDeleteView(DeleteView):
|
||||
def pre_redirect(self, request, *args, **kwargs):
|
||||
if self.get_object() == self.request.user:
|
||||
messages.error(request, _("You can not delete yourself."))
|
||||
elif self.get_object().is_superuser:
|
||||
messages.error(request, _("You can not delete the administrator."))
|
||||
else:
|
||||
super(DeleteView, self).pre_redirect(request, *args, **kwargs)
|
||||
|
||||
@ -268,8 +266,8 @@ class ParticipantsListPDF(PDFView):
|
||||
counter,
|
||||
Paragraph(user.last_name, stylesheet['Tablecell']),
|
||||
Paragraph(user.first_name, stylesheet['Tablecell']),
|
||||
Paragraph(user.detail, stylesheet['Tablecell']),
|
||||
Paragraph(user.type, stylesheet['Tablecell']),
|
||||
Paragraph(user.structure_level, stylesheet['Tablecell']),
|
||||
Paragraph(user.get_type_display(), stylesheet['Tablecell']),
|
||||
Paragraph(user.committee, stylesheet['Tablecell'])])
|
||||
t = LongTable(data, style=[
|
||||
('VALIGN', (0, 0), (-1, -1), 'TOP'),
|
||||
|
@ -155,6 +155,10 @@ body{
|
||||
font-weight:bold;
|
||||
text-align: center;
|
||||
}
|
||||
.item_fullscreen span
|
||||
{
|
||||
font-size: 50%; font-weight:normal;
|
||||
}
|
||||
|
||||
/* items in a list*/
|
||||
.itemlist li
|
||||
|
@ -15,27 +15,6 @@
|
||||
|
||||
{% block content %}
|
||||
<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">
|
||||
{% for name, widget in widgets.items %}
|
||||
|
@ -4,6 +4,5 @@
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{% get_config 'frontpage_title' %}</h1>
|
||||
{% get_config 'frontpage_welcometext' %}
|
||||
<div class="item_fullscreen">{% get_config 'welcome_title' %}</div>
|
||||
{% endblock %}
|
||||
|
@ -1,7 +1,36 @@
|
||||
{% load i18n %}
|
||||
{% 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">
|
||||
<div id="iframewrapper">
|
||||
<iframe id="iframe" src="{% url projector_show %}" frameborder="0"></iframe>
|
||||
|
@ -1 +0,0 @@
|
||||
{{ welcometext|safe|linebreaks }}
|
@ -22,6 +22,7 @@ from django.db import transaction
|
||||
from django.db.models import Q
|
||||
from django.dispatch import receiver
|
||||
from django.shortcuts import redirect
|
||||
from django.template import RequestContext
|
||||
from django.utils.datastructures import SortedDict
|
||||
from django.utils.importlib import import_module
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
@ -396,10 +397,10 @@ def get_widgets(request):
|
||||
|
||||
# welcome widget
|
||||
context = {
|
||||
'welcometext': config['frontpage_welcometext']}
|
||||
'welcometext': config['welcome_text']}
|
||||
widgets.append(Widget(
|
||||
name='welcome',
|
||||
display_name=config['frontpage_title'],
|
||||
display_name=config['welcome_title'],
|
||||
template='projector/welcome_widget.html',
|
||||
context=context,
|
||||
permission_required='projector.can_see_dashboard',
|
||||
@ -410,6 +411,7 @@ def get_widgets(request):
|
||||
name='live_view',
|
||||
display_name=_('Projector live view'),
|
||||
template='projector/live_view_widget.html',
|
||||
context = RequestContext(request, {}),
|
||||
permission_required='projector.can_see_projector',
|
||||
default_column=2))
|
||||
|
||||
|
@ -316,7 +316,7 @@ input[type="submit"], input[type="button"] {
|
||||
padding:4px 10px !important;
|
||||
margin: 2px 0 2px 0;
|
||||
}
|
||||
#id_permissions {
|
||||
#id_permissions, #id_users {
|
||||
height: 310px;
|
||||
}
|
||||
.button {
|
||||
|
@ -76,7 +76,7 @@
|
||||
{% endblock %}
|
||||
<div id="footer">
|
||||
<small>
|
||||
© 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.
|
||||
© 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>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -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 %}
|
@ -16,14 +16,13 @@ from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||
from django.shortcuts import redirect
|
||||
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'
|
||||
|
||||
urlpatterns = patterns('',
|
||||
# frontpage
|
||||
(r'^$', FrontPage.as_view()),
|
||||
# Redirect to dashboard URL
|
||||
url(r'^$', RedirectView.as_view(url='dashboard'), name='home',),
|
||||
|
||||
(r'^agenda/', include('openslides.agenda.urls')),
|
||||
(r'^motion/', include('openslides.motion.urls')),
|
||||
|
@ -20,6 +20,7 @@ from reportlab.pdfbase.ttfonts import TTFont
|
||||
from reportlab.rl_config import defaultPageSize
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils import formats
|
||||
# Import gettext for python 2.5 support
|
||||
from django.utils.translation import ugettext as _, gettext
|
||||
|
||||
@ -222,8 +223,8 @@ def firstPage(canvas, doc):
|
||||
|
||||
# time
|
||||
canvas.setFont('Ubuntu', 7)
|
||||
time = datetime.now().strftime(gettext("%Y-%m-%d %H:%Mh"))
|
||||
canvas.drawString(15 * cm, 28 * cm, _("Printed: %s") % time)
|
||||
time = formats.date_format(datetime.now(), 'DATETIME_FORMAT')
|
||||
canvas.drawString(15 * cm, 28 * cm, _("As of: %s") % time)
|
||||
|
||||
# title
|
||||
if doc.title:
|
||||
|
@ -358,33 +358,6 @@ class PDFView(PermissionMixin, View):
|
||||
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'):
|
||||
"""
|
||||
500 error handler.
|
||||
|
Loading…
Reference in New Issue
Block a user