Merge branch 'master' of github.com:OpenSlides/OpenSlides
This commit is contained in:
commit
93ee260856
@ -6,11 +6,15 @@ How to create a new portable Windows distribution of OpenSlides:
|
||||
|
||||
easy_install -Z django django-mptt reportlab pil
|
||||
|
||||
2.) In the main directory of the OpenSlides checkout execute:
|
||||
2.) Install OpenSlides by running python setup.py install in the top directory
|
||||
of OpenSlides.
|
||||
NOTE: This step must be repeated whenever you make changes to OpenSlides
|
||||
|
||||
3.) In the main directory of the OpenSlides checkout execute:
|
||||
|
||||
python extras/win32-portable/prepare_portable.py
|
||||
|
||||
3.) The portable OpenSlides distribution is now ready as a zip in the
|
||||
4.) The portable OpenSlides distribution is now ready as a zip in the
|
||||
'dist/' directory
|
||||
|
||||
Note: Creating the portable Windows distribution of OpenSlides is not possible,
|
||||
|
@ -23,7 +23,7 @@ static const char *site_code =
|
||||
|
||||
static const char *run_openslides_code =
|
||||
"import openslides.main;"
|
||||
"openslides.main.main()";
|
||||
"openslides.main.win32_portable_main()";
|
||||
|
||||
/* determine the path to the executable
|
||||
* NOTE: Py_GetFullProgramPath() can't be used because
|
||||
|
Binary file not shown.
@ -45,10 +45,6 @@ LIBEXCLUDE = [
|
||||
r"^unittest/",
|
||||
]
|
||||
|
||||
OPENSLIDES_EXCLUDE = [
|
||||
r"^openslides/settings.py"
|
||||
]
|
||||
|
||||
|
||||
SITE_PACKAGES = {
|
||||
"django": {
|
||||
@ -84,7 +80,10 @@ SITE_PACKAGES = {
|
||||
"pil": {
|
||||
# NOTE: PIL is a special case, see copy_pil
|
||||
"copy": [],
|
||||
}
|
||||
},
|
||||
"openslides": {
|
||||
"copy" : ["openslides"],
|
||||
},
|
||||
}
|
||||
|
||||
PY_DLLS = [
|
||||
@ -302,9 +301,6 @@ def main():
|
||||
collect_lib(libdir, odir)
|
||||
collect_site_packages(sitedir, os.path.join(odir, "site-packages"))
|
||||
|
||||
exclude = get_pkg_exclude("openslides", OPENSLIDES_EXCLUDE)
|
||||
copy_dir_exclude(exclude, ".", "openslides", odir)
|
||||
|
||||
if not compile_openslides_launcher():
|
||||
sys.stdout.write("Using prebuild openslides.exe\n")
|
||||
|
||||
|
@ -99,10 +99,11 @@ def overview(request):
|
||||
else:
|
||||
sort = sortfilter['sort']
|
||||
query = query.order_by(sort)
|
||||
|
||||
if sort.startswith('aversion_'):
|
||||
# limit result to last version of an application
|
||||
query = query.filter(aversion__id__in=[x.last_version.id for x in Application.objects.all()])
|
||||
else:
|
||||
query = query.order_by('number')
|
||||
|
||||
if 'reverse' in sortfilter:
|
||||
query = query.reverse()
|
||||
@ -920,5 +921,5 @@ def get_widgets(request):
|
||||
Widget(
|
||||
name='applications',
|
||||
template='application/widget.html',
|
||||
context={'applications': Application.objects.all()},
|
||||
context={'applications': Application.objects.all().order_by('number')},
|
||||
permission_required='application.can_manage_application')]
|
||||
|
@ -33,6 +33,7 @@ class AssignmentCandidate(models.Model):
|
||||
assignment = models.ForeignKey("Assignment")
|
||||
person = PersonField(db_index=True)
|
||||
elected = models.BooleanField(default=False)
|
||||
blocked = models.BooleanField(default=False)
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.person)
|
||||
@ -72,6 +73,8 @@ class Assignment(models.Model, SlideMixin):
|
||||
def run(self, candidate, person=None):
|
||||
"""
|
||||
run for a vote
|
||||
candidate: The user who will be a candidate
|
||||
person: The user who chooses the candidate
|
||||
"""
|
||||
# TODO: don't make any permission checks here.
|
||||
# Use other Exceptions
|
||||
@ -79,23 +82,39 @@ 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.'))
|
||||
AssignmentCandidate(assignment=self, person=candidate, elected=False).save()
|
||||
candidation = self.assignment_candidats.filter(person=candidate)
|
||||
if candidation and candidate != person:
|
||||
# if the candidation is blocked and anotherone tries to run the
|
||||
# candidate
|
||||
raise NameError(
|
||||
_('The %s does not want to be a candidate.') % candidate)
|
||||
elif candidation and candidate == person:
|
||||
candidation[0].blocked = False
|
||||
candidation[0].save()
|
||||
else:
|
||||
AssignmentCandidate(assignment=self, person=candidate).save()
|
||||
|
||||
def delrun(self, candidate):
|
||||
def delrun(self, candidate, blocked=True):
|
||||
"""
|
||||
stop running for a vote
|
||||
"""
|
||||
if self.is_candidate(candidate):
|
||||
self.assignment_candidats.get(person=candidate).delete()
|
||||
candidation = self.assignment_candidats.get(person=candidate)
|
||||
if blocked:
|
||||
candidation.blocked = True
|
||||
candidation.save()
|
||||
else:
|
||||
candidation.delete()
|
||||
else:
|
||||
# TODO: Use an OpenSlides Error
|
||||
raise Exception(_('%s is no candidate') % candidate)
|
||||
|
||||
def is_candidate(self, person):
|
||||
if self.assignment_candidats.filter(person=person).exists():
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
"""
|
||||
return True, if person is a candidate.
|
||||
"""
|
||||
return self.assignment_candidats.filter(person=person) \
|
||||
.exclude(blocked=True).exists()
|
||||
|
||||
@property
|
||||
def assignment_candidats(self):
|
||||
@ -110,7 +129,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
|
||||
candidates = self.assignment_candidats.exclude(blocked=True)
|
||||
|
||||
if only_elected and only_candidate:
|
||||
# TODO: Use right Exception
|
||||
|
@ -81,9 +81,12 @@ def view(request, assignment_id=None):
|
||||
user = form.cleaned_data['candidate']
|
||||
try:
|
||||
assignment.run(user, request.user)
|
||||
messages.success(request, _("Candidate <b>%s</b> was nominated successfully.") % (user))
|
||||
except NameError, e:
|
||||
messages.error(request, e)
|
||||
else:
|
||||
messages.success(request, _(
|
||||
"Candidate <b>%s</b> was nominated successfully.")
|
||||
% user)
|
||||
else:
|
||||
if request.user.has_perm('assignment.can_nominate_other'):
|
||||
form = AssignmentRunForm()
|
||||
@ -184,7 +187,7 @@ def delrun(request, assignment_id):
|
||||
assignment = Assignment.objects.get(pk=assignment_id)
|
||||
try:
|
||||
if assignment.status == 'sea' or user.has_perm("assignment.can_manage_assignment"):
|
||||
assignment.delrun(request.user)
|
||||
assignment.delrun(request.user, blocked=True)
|
||||
else:
|
||||
messages.error(request, _('The candidate list is already closed.'))
|
||||
except Exception, e:
|
||||
@ -201,7 +204,7 @@ def delother(request, assignment_id, user_id):
|
||||
|
||||
if request.method == 'POST':
|
||||
try:
|
||||
assignment.delrun(person)
|
||||
assignment.delrun(person, blocked=False)
|
||||
except Exception, e:
|
||||
messages.error(request, e)
|
||||
else:
|
||||
@ -660,5 +663,5 @@ def get_widgets(request):
|
||||
Widget(
|
||||
name=_('Assignments'),
|
||||
template='assignment/widget.html',
|
||||
context={'assignments': Assignment.objects.all()},
|
||||
context={'assignments': Assignment.objects.all().order_by('name')},
|
||||
permission_required='assignment.can_manage_assignment')]
|
||||
|
@ -25,8 +25,10 @@ import webbrowser
|
||||
import django.conf
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
CONFIG_TEMPLATE = """
|
||||
from openslides.openslides_settings import *
|
||||
CONFIG_TEMPLATE = """#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openslides.openslides_global_settings import *
|
||||
|
||||
# Use 'DEBUG = True' to get more details for server errors
|
||||
# (Default for relaeses: 'False')
|
||||
@ -63,7 +65,14 @@ INSTALLED_APPS += INSTALLED_PLUGINS
|
||||
KEY_LENGTH = 30
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
_fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
|
||||
def _fs2unicode(s):
|
||||
if isinstance(s, unicode):
|
||||
return s
|
||||
return s.decode(_fs_encoding)
|
||||
|
||||
|
||||
def main(argv=None, opt_defaults=None):
|
||||
if argv is None:
|
||||
argv = sys.argv[1:]
|
||||
|
||||
@ -81,6 +90,9 @@ def main(argv=None):
|
||||
parser.add_option(
|
||||
"--no-reload", action="store_true", help="Do not reload the development server")
|
||||
|
||||
if not opt_defaults is None:
|
||||
parser.set_defaults(**opt_defaults)
|
||||
|
||||
opts, args = parser.parse_args(argv)
|
||||
if args:
|
||||
sys.stderr.write("This command does not take arguments!\n\n")
|
||||
@ -89,7 +101,7 @@ def main(argv=None):
|
||||
|
||||
# Find the path to the settings
|
||||
settings = opts.settings or \
|
||||
os.path.expanduser('~/.openslides/openslidessettings.py')
|
||||
os.path.join(os.path.expanduser('~'),'.openslides','openslides_personal_settings.py')
|
||||
|
||||
# Create settings if necessary
|
||||
if not os.path.exists(settings):
|
||||
@ -128,7 +140,7 @@ def create_settings(settings):
|
||||
|
||||
setting_content = CONFIG_TEMPLATE % dict(
|
||||
default_key=base64.b64encode(os.urandom(KEY_LENGTH)),
|
||||
dbpath=os.path.join(path_to_dir, 'database.db'))
|
||||
dbpath=_fs2unicode((os.path.join(path_to_dir, 'database.db'))))
|
||||
|
||||
if not os.path.exists(path_to_dir):
|
||||
os.makedirs(path_to_dir)
|
||||
@ -240,6 +252,47 @@ def start_browser(url):
|
||||
t = threading.Thread(target=f)
|
||||
t.start()
|
||||
|
||||
def win32_portable_main(argv=None):
|
||||
"""special entry point for the win32 portable version"""
|
||||
import tempfile
|
||||
|
||||
# NOTE: sys.executable will be the path to openslides.exe
|
||||
# since it is essentially a small wrapper that embeds the
|
||||
# python interpreter
|
||||
portable_dir = os.path.dirname(os.path.abspath(sys.executable))
|
||||
try:
|
||||
fd, test_file = tempfile.mkstemp(dir=portable_dir)
|
||||
except OSError:
|
||||
portable_dir_writeable = False
|
||||
else:
|
||||
portable_dir_writeable = True
|
||||
os.close(fd)
|
||||
os.unlink(test_file)
|
||||
|
||||
if portable_dir_writeable:
|
||||
default_settings = os.path.join(portable_dir, "openslides",
|
||||
"openslides_personal_settings.py")
|
||||
else:
|
||||
import ctypes
|
||||
|
||||
shell32 = ctypes.WinDLL("shell32.dll")
|
||||
SHGetFolderPath = shell32.SHGetFolderPathW
|
||||
SHGetFolderPath.argtypes = (ctypes.c_void_p, ctypes.c_int,
|
||||
ctypes.c_void_p, ctypes.c_uint32, ctypes.c_wchar_p)
|
||||
SHGetFolderPath.restype = ctypes.c_uint32
|
||||
|
||||
CSIDL_LOCAL_APPDATA = 0x001c
|
||||
MAX_PATH = 260
|
||||
|
||||
buf = ctypes.create_unicode_buffer(MAX_PATH)
|
||||
res = SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, 0, 0, buf)
|
||||
if res != 0:
|
||||
raise Exception("Could not deterime APPDATA path")
|
||||
default_settings = os.path.join(buf.value, "openslides",
|
||||
"openslides_personal_settings.py")
|
||||
|
||||
main(argv, opt_defaults={ "settings": default_settings })
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
0
openslides/openslides_settings.py → openslides/openslides_global_settings.py
Executable file → Normal file
0
openslides/openslides_settings.py → openslides/openslides_global_settings.py
Executable file → Normal file
@ -31,6 +31,7 @@ class ProjectorSlide(models.Model, SlideMixin):
|
||||
|
||||
title = models.CharField(max_length=256, verbose_name=_("Title"))
|
||||
text = models.TextField(null=True, blank=True, verbose_name=_("Text"))
|
||||
weight = models.IntegerField(default=0, verbose_name=_("Weight"))
|
||||
|
||||
def slide(self):
|
||||
return {
|
||||
|
@ -9,7 +9,7 @@
|
||||
.column {
|
||||
width: 50%;
|
||||
float: left;
|
||||
padding-bottom: 0px;
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
.portlet {
|
||||
margin: 0 10px 10px 0;
|
@ -6,9 +6,9 @@
|
||||
|
||||
{% block header %}
|
||||
<link type="text/css" href="{% static 'styles/humanity/jquery-ui-1.8.18.custom.css' %}" rel="stylesheet" />
|
||||
<link type="text/css" rel="stylesheet" media="all" href="{% static 'styles/projector-control.css' %}" />
|
||||
<link type="text/css" rel="stylesheet" media="all" href="{% static 'styles/dashboard.css' %}" />
|
||||
<script type="text/javascript" src="{% static 'javascript/jquery-ui-1.8.18.custom.min.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'javascript/projector-control.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'javascript/dashboard.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'javascript/jquery.cookie.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'javascript/jquery.form.js' %}"></script>
|
||||
{% endblock %}
|
||||
@ -17,7 +17,7 @@
|
||||
<h1>{% trans 'Dashboard' %}</h1>
|
||||
{% if perms.projector.can_manage_projector %}
|
||||
<div style="text-align: right; padding: 0 10px 5px 0; margin-top:-20px;">
|
||||
<!-- projector control -->
|
||||
<!-- 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' %}" />
|
||||
|
@ -409,11 +409,11 @@ def get_widgets(request):
|
||||
|
||||
# Custom slide widget
|
||||
context = {
|
||||
'slides': ProjectorSlide.objects.all(),
|
||||
'slides': ProjectorSlide.objects.all().order_by('weight'),
|
||||
'welcomepage_is_active': not bool(config["presentation"])}
|
||||
widgets.append(Widget(
|
||||
name='custom_slide',
|
||||
display_name=_('Custom Slide'),
|
||||
display_name=_('Custom Slides'),
|
||||
template='projector/custom_slide_widget.html',
|
||||
context=context,
|
||||
permission_required='projector.can_manage_projector',
|
||||
|
Loading…
Reference in New Issue
Block a user