Merge pull request #59 from emanuelschuetze/master

Prepared 1.3-rc1
This commit is contained in:
Oskar Hahn 2012-11-27 13:59:38 -08:00
commit 48b530487b
15 changed files with 974 additions and 860 deletions

View File

@ -5,3 +5,5 @@ Authors of OpenSlides in chronological order of first contribution:
Norman Jäckel <mail@normanjaeckel.de> Norman Jäckel <mail@normanjaeckel.de>
René Köcher <shirk@bitspin.org> René Köcher <shirk@bitspin.org>
Andy Kittner <andkit@gmx.net> Andy Kittner <andkit@gmx.net>
Moira Brülisauer <moira.bruelisauer@piratenpartei.ch> (French translation)
Alexis Roussel <alexis.roussel@partipirate.ch> (French translation)

View File

@ -2,6 +2,80 @@ CHANGELOG of OpenSlides
http://openslides.org http://openslides.org
Version 1.3 (unreleased)
========================
[http://dev.openslides.org/milestone/1.3]
Projector:
- New public dashboard which allows access for all users per default. (#361)
(changed from the old, limited projector control page)
- New dashboard widgets:
* welcome widget (shows static welcome title and text)
* participant widget
* group widget
* personal widget (shows my motions and my elections)
- Hide scrollbar in projector view.
- Added cache for AJAX version of the projector view.
- Moved projector control icons into projector live widget. (#403)
- New weight field for custom slides (to order custom slides in widget).
- Fixed drag'n'drop behaviour of widgets into empty dashboard column.
- Fixed permissions for agenda, motion and assignment widgets (set to projector.can_manage_projector).
Agenda:
- Fixed slide error if agenda item deleted. (#330)
Motions:
- Translation: Changed 'application' to 'motion'.
- Fixed: Manager could not edit supporters. (#336)
- Fixed attribute error for anonymous users in motion view. (#329)
- Set default sorting of motions by number (in widget).
- CSV import allows to import group as submitter. (#419)
- Updated motion code for new user API.
- Rewrote motion views as class based views.
Elections:
- User can block himself/herself from candidate list after delete his/her candidature.
- Show blocked candidates in separate list.
- Mark elected candidates in candidate list. (#374)
- Show linebreaks in description. (#392)
- Set default sorting of elections by name (in widget).
- Fixed redirect from a poll which does not exists anymore.
- Changed default permissions of anonymous user to see elections. (#334)
- Updated assignment code for new user API.
Participants:
- New user and group API.
- New group option to handle a group as participant (and thus e.g. as submitter of motion).
- CSV import does not delete existing users anymore and append users as new users.
- New user field 'about me'. (#390)
- New config option for sorting users by first or last name (in participant lists, elections and motions). (#303)
- Allowed whitespaces in username, default: <firstname lastname>. (#326)
- New user and group slides. (#176)
- Don't allow to deactivate the administrator or themself.
- Don't allow to delete themself.
- Renamed participant field 'groups' to 'structure level' (German: Gliederungsebene).
- Rewrote participant views as class based views.
- Made OpenSlides user a child model of Django user model.
- Appended tests.
- Fixed error to allow admins to delete anonymous group
Other:
- Added French translation (Thanks to Moira).
- Updated setup.py to make an openslides python package.
- Removed frontpage (welcome widget contains it's content) and redirect '/' to dashboard url.
- Added LOCALE_PATHS to openslides_settings to avoid deprication in Django 1.5.
- Redesigned the DeleteView (append QuestionMixin to send question via the django message API).
- Fixed encoding error in settings.py. (#349)
- Renamed openslides_settings.py to openslides_global_settings.py.
- New default path to database file (XDG_DATA_HOME, e.g. ~/.local/share/openslides/).
- New default path to settings file (XDG_CONFIG_HOME, e.g. ~/.config/openslides/).
- Added special handling to determine location of database and settings file in portable version.
- Don't use similar characters in generated passwords (no 'Il10oO').
- Localised the datetime in PDF header. (#296)
- Used specific session cookie name. (#332)
- Moved code repository from hg to git (incl. some required updates, e.g. version string function).
- Updated German translations.
- Several code optimizations.
- Several minor and medium issues and errors were fixed.
Version 1.2 (2012-07-25) Version 1.2 (2012-07-25)
======================== ========================
[http://dev.openslides.org/milestone/1.2] [http://dev.openslides.org/milestone/1.2]

View File

@ -3,15 +3,56 @@ Installation Instructions for OpenSlides 1.3
Content Content
------- -------
I. Installation on Windows (32/64bit) I. Installation on GNU/Linux and MacOSX
II. Installation on GNU/Linux and MacOSX II. Installation on Windows (32/64bit)
If you need help ask on OpenSlides users mailing list. If you need help ask on OpenSlides users mailing list.
See http://openslides.org for more information. See http://openslides.org for more information.
I. Installation on Windows (32/64bit) I. Installation on GNU/Linux and MacOSX
------------------------------------- ----------------------------------------
Make sure that you have installed Python (>= 2.5) on your system.
You can setup a virtualenv environment to install OpenSlides as non-root user.
Run before you start install OpenSlides:
$ virtualenv .venv
$ source .venv/bin/activate
1. Install OpenSlides:
$ pip install openslides
OpenSlides will installed the following required python packages:
+ Django
+ django-mptt
+ ReportLab Toolkit
+ Python Imaging Library (PIL)
2. Start OpenSlides server and open URL in your default browser:
$ openslides
If you run this command the first time a new database and the
admin account are created. Please change the password after
first login!
Username: admin
Password: admin
Use 'openslides --help' to show all start options.
II. Installation on Windows (32/64bit)
--------------------------------------
NOTE: There is a portable version of OpenSlides for Windows which does not
required any install steps! If there is a reason that you can not use the
portable version you should run the following install steps.
1. Install requirements: 1. Install requirements:
@ -76,73 +117,3 @@ I. Installation on Windows (32/64bit)
Use 'python start.py --help' to show all start options. Use 'python start.py --help' to show all start options.
II. Installation on GNU/Linux and MacOSX
----------------------------------------
1. Install requirements:
OpenSlides requires following programs, which should be
installed first:
+ Python Programming Language 2 (>= 2.5)
+ virtualenv (>= 1.4.1)
+ ReportLab Toolkit
+ Python Imaging Library (PIL)
E.g. for ubuntu run:
$ sudo apt-get install python python-virtualenv python-reportlab python-imaging
2. Get OpenSlides:
a) Download latest OpenSlides release from http://openslides.org.
OR
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:
git clone git://github.com/OpenSlides/OpenSlides.git
3. Setup your virtual environment with virtualenv:
Go to the (extracted/cloned) root directory of OpenSlides
and create virtualenv environment:
$ virtualenv .venv
For virtualenv >= 1.7 use instead:
$ virtualenv --system-site-packages .venv
4. Activate the virtual environment:
$ source .venv/bin/activate
5. Install the required python-packages:
$ pip install django django-mptt
If you use python < 2.6 you also have to install simplejson:
$ pip install simplejson
If requirements reportlab or PIL still missing (see 1.):
$ pip install reportlab pil
6. Start OpenSlides server and open URL in your default browser:
$ python start.py
If you run this script the first time a new database and the
admin account are created. Please change the password after
first login!
Username: admin
Password: admin
Use 'python start.py --help' to show all start options.
7. Restart OpenSlides:
To restart OpenSlides after closing the terminal activate the
virtual environment (see 4.) before starting the server (see 6.).

View File

@ -2,7 +2,7 @@
English README file for OpenSlides English README file for OpenSlides
================================== ==================================
This is OpenSlides, version 1.3-beta2 (2012-11-09). This is OpenSlides, version 1.3-rc1 (2012-11-27).
What is OpenSlides? What is OpenSlides?

View File

@ -307,8 +307,8 @@ def main():
shutil.copyfile("extras/win32-portable/openslides.exe", shutil.copyfile("extras/win32-portable/openslides.exe",
os.path.join(odir, "openslides.exe")) os.path.join(odir, "openslides.exe"))
shutil.copyfile("initial_data.json", shutil.copyfile("openslides/participant/fixtures/groups_de.json",
os.path.join(odir, "initial_data.json")) os.path.join(odir, "groups_de.json"))
copy_dlls(odir) copy_dlls(odir)
copy_msvcr(odir) copy_msvcr(odir)

View File

@ -5,7 +5,7 @@
:license: GNU GPL, see LICENSE for more details. :license: GNU GPL, see LICENSE for more details.
""" """
VERSION = (1, 3, 0, 'beta', 2) VERSION = (1, 3, 0, 'rc', 1)
def get_version(version=None): def get_version(version=None):

View File

@ -80,16 +80,16 @@ 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_candidates.filter(person=candidate) candidature = self.assignment_candidates.filter(person=candidate)
if candidation and candidate != person and \ if candidature 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 candidature is blocked and anotherone tries to run the
# candidate # candidate
raise NameError( raise NameError(
_('%s does not want to be a candidate.') % candidate) _('%s does not want to be a candidate.') % candidate)
elif candidation: elif candidature:
candidation[0].blocked = False candidature[0].blocked = False
candidation[0].save() candidature[0].save()
else: else:
AssignmentCandidate(assignment=self, person=candidate).save() AssignmentCandidate(assignment=self, person=candidate).save()
@ -98,18 +98,18 @@ class Assignment(models.Model, SlideMixin):
stop running for a vote stop running for a vote
""" """
try: try:
candidation = self.assignment_candidates.get(person=candidate) candidature = self.assignment_candidates.get(person=candidate)
except AssignmentCandidate.DoesNotExist: except AssignmentCandidate.DoesNotExist:
raise Exception(_('%s is no candidate') % candidate) raise Exception(_('%s is no candidate') % candidate)
if not candidation.blocked: if not candidature.blocked:
if blocked: if blocked:
candidation.blocked = True candidature.blocked = True
candidation.save() candidature.save()
else: else:
candidation.delete() candidature.delete()
else: else:
candidation.delete() candidature.delete()
def is_candidate(self, person): def is_candidate(self, person):
""" """
@ -122,7 +122,7 @@ class Assignment(models.Model, SlideMixin):
def is_blocked(self, person): def is_blocked(self, person):
""" """
return True, if the person is blockt for candidation. return True, if the person is blockt for candidature.
""" """
return self.assignment_candidates.filter(person=person).filter(blocked=True).exists() return self.assignment_candidates.filter(person=person).filter(blocked=True).exists()

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,10 @@
<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, is_group}</code> (<code>number</code>, <code>reason</code> and <code>is_group</code> are optional and may be empty)' %} <p>{% trans 'Required comma separated values' %}:
<code>({% trans 'number, title, text, reason, first_name, last_name, is_group' %})</code>
<br>
{% trans '<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

@ -146,7 +146,7 @@ class Group(DjangoGroup, PersonMixin, Person, SlideMixin):
@models.permalink @models.permalink
def get_absolute_url(self, link='view'): def get_absolute_url(self, link='view'):
""" """
Return the URL to this user. Return the URL to this user group.
link can be: link can be:
* view * view

View File

@ -8,7 +8,8 @@
<h1>{% trans 'Import participants' %}</h1> <h1>{% trans 'Import participants' %}</h1>
<p>{% trans 'Select a CSV file to import participants!' %}</p> <p>{% trans 'Select a CSV file to import participants!' %}</p>
<p>{% trans 'Required comma separated values: <code>{first_name, last_name, gender, group, type, committee, comment}</code>' %} <p>{% trans 'Required comma separated values' %}:
<code>({% trans 'first_name, last_name, gender, structure level, type, committee, comment' %})</code>
<br> <br>
{% trans 'Required CSV file encoding: UTF-8 (Unicode).' %} {% trans 'Required CSV file encoding: UTF-8 (Unicode).' %}
</p> </p>

View File

@ -8,17 +8,15 @@
{% block content %} {% block content %}
<div class="item_fullscreen">{{ group }} <div class="item_fullscreen">{{ group }}
<span> <span>
<p><i>{{ group.user_set.all.count }} {% trans "participants" %}:</i></p> <p><i>{{ group.user_set.all.count }} {% trans "participants" %}</i></p>
<p> {% comment %}
{% if group.user_set.all %} TODO: print fullname (not username) of all group users [see #420]
{{ group.user_set.all|join:", " }} <p>
{% endif %} {% if group.user_set.all %}
</p> {{ group.user_set.all|join:", " }}
{% endif %}
</p>
{% endcomment %}
</span> </span>
</div> </div>
{% endblock %}
{% block scrollcontent %}
{% endblock %} {% endblock %}