Merge branch 'stable/1.6.x'
Conflicts: CHANGELOG README.rst openslides/assignment/models.py openslides/users/forms.py requirements_production.txt tests/settings.py
This commit is contained in:
commit
0a24b7267b
@ -24,7 +24,9 @@ Version 1.7 (unreleased)
|
|||||||
|
|
||||||
Core:
|
Core:
|
||||||
- New feature to tag motions, agenda and assignments.
|
- New feature to tag motions, agenda and assignments.
|
||||||
Motion:
|
- Fixed search index problem to index contents of many-to-many table
|
||||||
|
(e.g. tags of a motion).
|
||||||
|
Motions:
|
||||||
- New Feature to create amendments, which are related to a parent motion.
|
- New Feature to create amendments, which are related to a parent motion.
|
||||||
- Added possibility to hide motions from non staff users in some states.
|
- Added possibility to hide motions from non staff users in some states.
|
||||||
Other:
|
Other:
|
||||||
|
@ -105,7 +105,7 @@ portable version you should observe the following install steps.*
|
|||||||
To install Virtual Python Environment builder, open command line (cmd)
|
To install Virtual Python Environment builder, open command line (cmd)
|
||||||
and run::
|
and run::
|
||||||
|
|
||||||
> easy_install https://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.11.6.tar.gz
|
> easy_install https://pypi.python.org/packages/source/v/virtualenv/virtualenv-12.0.5.tar.gz
|
||||||
|
|
||||||
Create your OpenSlides directory, change to it, setup and activate the
|
Create your OpenSlides directory, change to it, setup and activate the
|
||||||
virtual environment::
|
virtual environment::
|
||||||
|
@ -5,34 +5,21 @@ How to create a new portable Windows distribution of OpenSlides:
|
|||||||
Follow the instructions in the README, section III (Windows installation), step 1.
|
Follow the instructions in the README, section III (Windows installation), step 1.
|
||||||
|
|
||||||
|
|
||||||
2. Install all required python packages (see requirements_production.txt):
|
2. Install all required python packages from requirements_production.txt:
|
||||||
|
(Note: You have to use 'easy_install -Z $PACKAGENAME')
|
||||||
|
|
||||||
easy_install -Z "django<1.7" ^
|
python install-requirements.py
|
||||||
backports.ssl_match_hostname ^
|
|
||||||
"beautifulsoup4<4.4" ^
|
|
||||||
"bleach<1.5" ^
|
|
||||||
"django-ckeditor-updated<4.3" ^
|
|
||||||
"django-haystack<2.2" ^
|
|
||||||
"django-mptt<0.7" ^
|
|
||||||
"jsonfield<0.10" ^
|
|
||||||
"natsort<3.3" ^
|
|
||||||
"reportlab<2.8" ^
|
|
||||||
"roman<2.1" ^
|
|
||||||
"sockjs_tornado<1.1" ^
|
|
||||||
"tornado<3.3" ^
|
|
||||||
"whoosh<2.6" ^
|
|
||||||
"setuptools<3.7"
|
|
||||||
|
|
||||||
|
|
||||||
3. Install pywin32 from binary installer:
|
3. Install pywin32 from binary installer:
|
||||||
http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/pywin32-218.win32-py2.7.exe/download
|
http://sourceforge.net/projects/pywin32/files/pywin32/Build%20219/pywin32-219.win32-py2.7.exe/download
|
||||||
|
|
||||||
Pywin32 is used to update the version resource of the prebuild openslides.exe.
|
Pywin32 is used to update the version resource of the prebuild openslides.exe.
|
||||||
It is not strictly required but at least for published releases it is highly advisable.
|
It is not strictly required but at least for published releases it is highly advisable.
|
||||||
|
|
||||||
|
|
||||||
4. Install wxPython from binary installer:
|
4. Install wxPython from binary installer:
|
||||||
http://downloads.sourceforge.net/wxpython/wxPython2.8-win32-unicode-2.8.12.1-py27.exe
|
http://sourceforge.net/projects/wxpython/files/wxPython/2.8.12.1/wxPython2.8-win32-unicode-2.8.12.1-py27.exe/download
|
||||||
|
|
||||||
WxPython is required to build the OpenSlides GUI frontend.
|
WxPython is required to build the OpenSlides GUI frontend.
|
||||||
|
|
||||||
|
12
extras/win32-portable/install-requirements.py
Normal file
12
extras/win32-portable/install-requirements.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
f = open("../../requirements_production.txt")
|
||||||
|
reqs = f.read().split("\n")
|
||||||
|
|
||||||
|
for req in reqs:
|
||||||
|
# ignore comments or pip options
|
||||||
|
if req.startswith('--') or req.startswith('#'):
|
||||||
|
continue
|
||||||
|
# ignore blank lines
|
||||||
|
if len(req) > 0:
|
||||||
|
os.system('easy_install -Z -U "%s"' % req)
|
@ -83,5 +83,8 @@
|
|||||||
{% endwith %}
|
{% endwith %}
|
||||||
<a href="{{ node|absolute_url }}">{% if node.type == node.ORGANIZATIONAL_ITEM %}<i>[{% endif %}{{ node }}{% if node.type == node.ORGANIZATIONAL_ITEM %}]</i>{% endif %}</a>
|
<a href="{{ node|absolute_url }}">{% if node.type == node.ORGANIZATIONAL_ITEM %}<i>[{% endif %}{{ node }}{% if node.type == node.ORGANIZATIONAL_ITEM %}]</i>{% endif %}</a>
|
||||||
{{ node.get_title_supplement|safe }}
|
{{ node.get_title_supplement|safe }}
|
||||||
|
{% for tag in node.tags.all %}
|
||||||
|
<span class="label">{{ tag }}</span>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if perms.core.can_manage_tags %}
|
{% if perms.core.can_manage_tags %}
|
||||||
<a href="{% url 'core_tag_list' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Manage tags' %}">
|
<a href="{% url 'core_tag_list' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Manage tags' %}">
|
||||||
<i class="icon-th"></i>
|
<i class="icon-tags"></i>
|
||||||
<span class="optional-small"> {% trans 'Tags' %}</span>
|
<span class="optional-small"> {% trans 'Tags' %}</span>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -41,6 +41,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</small>
|
</small>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
<!-- Tags -->
|
||||||
|
{% for tag in item.tags.all %}
|
||||||
|
<span class="label">{{ tag }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
<p>
|
<p>
|
||||||
{% if not item.content_object %}
|
{% if not item.content_object %}
|
||||||
{{ item.text|safe }}
|
{{ item.text|safe }}
|
||||||
@ -49,6 +56,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<!-- Comment -->
|
||||||
{% if perms.agenda.can_manage_agenda %}
|
{% if perms.agenda.can_manage_agenda %}
|
||||||
{% if item.comment %}
|
{% if item.comment %}
|
||||||
<h3>{% trans "Comment" %}</h3>
|
<h3>{% trans "Comment" %}</h3>
|
||||||
@ -56,7 +64,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# List of Speakers #}
|
<!-- List of Speakers -->
|
||||||
<h3>{% trans "List of speakers" %} {% if item.speaker_list_closed %}<span class="label label-important">{% trans 'closed' %}</span>{% endif %}</h3>
|
<h3>{% trans "List of speakers" %} {% if item.speaker_list_closed %}<span class="label label-important">{% trans 'closed' %}</span>{% endif %}</h3>
|
||||||
<p>
|
<p>
|
||||||
{% if perms.agenda.can_manage_agenda %}
|
{% if perms.agenda.can_manage_agenda %}
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
{{ object.title }}
|
{{ object.title }}
|
||||||
{{ object.text }}
|
{{ object.text }}
|
||||||
|
{{ object.tags.all }}
|
||||||
|
@ -50,6 +50,11 @@
|
|||||||
</small>
|
</small>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
<!-- Tags -->
|
||||||
|
{% for tag in assignment.tags.all %}
|
||||||
|
<span class="optional label">{{ tag }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
<div class="span9">
|
<div class="span9">
|
||||||
<!-- Description -->
|
<!-- Description -->
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if perms.core.can_manage_tags %}
|
{% if perms.core.can_manage_tags %}
|
||||||
<a href="{% url 'core_tag_list' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Manage tags' %}">
|
<a href="{% url 'core_tag_list' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Manage tags' %}">
|
||||||
<i class="icon-th"></i>
|
<i class="icon-tags"></i>
|
||||||
<span class="optional-small"> {% trans 'Tags' %}</span>
|
<span class="optional-small"> {% trans 'Tags' %}</span>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -46,7 +46,11 @@
|
|||||||
</thead>
|
</thead>
|
||||||
{% for object in object_list %}
|
{% for object in object_list %}
|
||||||
<tr class="{% if object.is_active_slide %}activeline{% endif %}">
|
<tr class="{% if object.is_active_slide %}activeline{% endif %}">
|
||||||
<td><a href="{{ object|absolute_url:'detail' }}">{{ object }}</a></td>
|
<td><a href="{{ object|absolute_url:'detail' }}">{{ object }}</a>
|
||||||
|
{% for tag in object.tags.all %}
|
||||||
|
<span class="optional label">{{ tag }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
<td class="optional">
|
<td class="optional">
|
||||||
<!-- posts -->
|
<!-- posts -->
|
||||||
{% trans "Posts" context "Number of searched candidates for an election" %}:
|
{% trans "Posts" context "Number of searched candidates for an election" %}:
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
{{ object.name }}
|
{{ object.name }}
|
||||||
{{ object.description }}
|
{{ object.description }}
|
||||||
{{ object.candidates }}
|
{{ object.candidates }}
|
||||||
|
{{ object.tags.all }}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.sessions.models import Session
|
|
||||||
from django.utils.html import urlize
|
from django.utils.html import urlize
|
||||||
|
from django.utils.importlib import import_module
|
||||||
|
|
||||||
from sockjs.tornado import SockJSConnection
|
from sockjs.tornado import SockJSConnection
|
||||||
|
|
||||||
|
|
||||||
@ -18,22 +19,25 @@ class ChatboxSocketHandler(SockJSConnection):
|
|||||||
"""
|
"""
|
||||||
from openslides.users.models import User
|
from openslides.users.models import User
|
||||||
|
|
||||||
# TODO: Use the django way to get the session to be compatible with
|
# get the session (compatible with other auth-backends)
|
||||||
# other auth-backends; see comment in pull request #1220:
|
engine = import_module(settings.SESSION_ENGINE)
|
||||||
# https://github.com/OpenSlides/OpenSlides/pull/1220#discussion_r11565705
|
|
||||||
session_key = info.get_cookie(settings.SESSION_COOKIE_NAME).value
|
|
||||||
session = Session.objects.get(session_key=session_key)
|
|
||||||
try:
|
try:
|
||||||
self.user = User.objects.get(pk=session.get_decoded().get('_auth_user_id'))
|
session_key = info.get_cookie(settings.SESSION_COOKIE_NAME).value
|
||||||
|
session = engine.SessionStore(session_key)
|
||||||
|
pk = session.get_decoded().get('_auth_user_id')
|
||||||
|
except AttributeError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.user = User.objects.get(pk)
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
return_value = False
|
return False
|
||||||
else:
|
|
||||||
if self.user.has_perm('core.can_use_chat'):
|
if self.user.has_perm('core.can_use_chat'):
|
||||||
self.clients.add(self)
|
self.clients.add(self)
|
||||||
return_value = True
|
return True
|
||||||
else:
|
else:
|
||||||
return_value = False
|
return False
|
||||||
return return_value
|
|
||||||
|
|
||||||
def on_message(self, message):
|
def on_message(self, message):
|
||||||
"""
|
"""
|
||||||
|
@ -113,7 +113,7 @@
|
|||||||
<hr />
|
<hr />
|
||||||
<footer>
|
<footer>
|
||||||
<small>
|
<small>
|
||||||
© Copyright 2011–2014 | Powered by <a href="http://openslides.org" target="_blank">OpenSlides</a> | <a href="{% url 'core_version' %}">Version</a>
|
© Copyright 2011–2015 | Powered by <a href="http://openslides.org" target="_blank">OpenSlides</a> | <a href="{% url 'core_version' %}">Version</a>
|
||||||
</small>
|
</small>
|
||||||
</footer>
|
</footer>
|
||||||
</div><!--/#content-->
|
</div><!--/#content-->
|
||||||
@ -134,7 +134,7 @@
|
|||||||
<script type="text/javascript" src="{% static 'js/jquery/jquery.bsmselect.js' %}"></script>
|
<script type="text/javascript" src="{% static 'js/jquery/jquery.bsmselect.js' %}"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// use jquery-bsmselect for all <select multiple> form elements
|
// use jquery-bsmselect for all <select multiple> form elements
|
||||||
$("select[multiple]").bsmSelect({
|
$("select[multiple]:not(.dont_use_bsmselect)").bsmSelect({
|
||||||
removeLabel: '<sup><b>X</b></sup>',
|
removeLabel: '<sup><b>X</b></sup>',
|
||||||
containerClass: 'bsmContainer',
|
containerClass: 'bsmContainer',
|
||||||
listClass: 'bsmList-custom',
|
listClass: 'bsmList-custom',
|
||||||
|
@ -5,17 +5,23 @@
|
|||||||
{% block title %}{% trans "Tags" %} – {{ block.super }}{% endblock %}
|
{% block title %}{% trans "Tags" %} – {{ block.super }}{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>{% trans "Tags" %}</h1>
|
<h1>{% trans "Tags" %}
|
||||||
|
<small class="pull-right">
|
||||||
|
<a href="javascript:window.history.back()" class="btn btn-mini">
|
||||||
|
<i class="icon-chevron-left"></i><span class="optional-small"> {% trans "Back to overview" %}</span>
|
||||||
|
</a>
|
||||||
|
</small>
|
||||||
|
</h1>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label for="tag-edit">Name:</label>
|
<label for="tag-edit">{% trans 'Enter new tag name' %}:</label>
|
||||||
<input id="tag-edit" name="new">
|
<input id="tag-edit" name="new">
|
||||||
<a href="#" id="tag-save" class="btn btn-primary">{% trans 'Save' %}</a>
|
<a href="#" id="tag-save" class="btn btn-primary">{% trans 'Save' %}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table id="tag-table" class="table table-striped table-bordered">
|
<table id="tag-table" class="table table-striped table-bordered">
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans "Tag name" %}</th>
|
<th>{% trans "Tag" %}</th>
|
||||||
<th class="mini_width">{% trans "Actions" %}</th>
|
<th class="mini_width">{% trans "Actions" %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr id="dummy-tag" class="tag-row" style="display:none">
|
<tr id="dummy-tag" class="tag-row" style="display:none">
|
||||||
@ -47,6 +53,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
<p>{% trans "You can use these tags for agenda items, motions and elections." %}</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block javascript %}
|
{% block javascript %}
|
||||||
|
@ -131,7 +131,7 @@ HAYSTACK_CONNECTIONS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Haystack updates search index after each save/delete action by apps
|
# Haystack updates search index after each save/delete action by apps
|
||||||
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
|
HAYSTACK_SIGNAL_PROCESSOR = 'openslides.utils.haystack_processor.OpenSlidesProcessor'
|
||||||
|
|
||||||
# Adds all automaticly collected plugins
|
# Adds all automaticly collected plugins
|
||||||
INSTALLED_PLUGINS = collect_plugins()
|
INSTALLED_PLUGINS = collect_plugins()
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2014-10-16 23:27+0200\n"
|
"POT-Creation-Date: 2015-01-11 19:03+0100\n"
|
||||||
"Language: en\n"
|
"Language: en\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
File diff suppressed because it is too large
Load Diff
30346
openslides/mediafile/static/js/pdf.worker.js
vendored
30346
openslides/mediafile/static/js/pdf.worker.js
vendored
File diff suppressed because it is too large
Load Diff
@ -72,7 +72,7 @@ def setup_motion_config(sender, **kwargs):
|
|||||||
|
|
||||||
motion_amendments_prefix = ConfigVariable(
|
motion_amendments_prefix = ConfigVariable(
|
||||||
name='motion_amendments_prefix',
|
name='motion_amendments_prefix',
|
||||||
default_value=pgettext('Prefix for amendment', 'A'),
|
default_value=pgettext('Prefix for the identifier for amendments', 'A'),
|
||||||
form_field=forms.CharField(
|
form_field=forms.CharField(
|
||||||
required=False,
|
required=False,
|
||||||
label=ugettext_lazy('Prefix for the identifier for amendments')))
|
label=ugettext_lazy('Prefix for the identifier for amendments')))
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if motion.is_amendment %}
|
{% if motion.is_amendment %}
|
||||||
(Amendment of <a href="{{ motion.parent|absolute_url }}">{{ motion.parent.identifier|default:motion.parent }}</a>)
|
({% trans "Amendment of" %} <a href="{{ motion.parent|absolute_url }}">{{ motion.parent.identifier|default:motion.parent }}</a>)
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</small>
|
</small>
|
||||||
<small class="pull-right">
|
<small class="pull-right">
|
||||||
@ -71,8 +71,6 @@
|
|||||||
</small>
|
</small>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
{{ motion.tags.all|join:', ' }}
|
|
||||||
|
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
<div class="span8">
|
<div class="span8">
|
||||||
{# TODO: show only for workflow with versioning #}
|
{# TODO: show only for workflow with versioning #}
|
||||||
@ -256,7 +254,9 @@
|
|||||||
{% block meta_box_poll_extras %}{% endblock %}
|
{% block meta_box_poll_extras %}{% endblock %}
|
||||||
</p>
|
</p>
|
||||||
{% empty %}
|
{% empty %}
|
||||||
|
{% if not allowed_actions.create_poll %}
|
||||||
–
|
–
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if allowed_actions.create_poll %}
|
{% if allowed_actions.create_poll %}
|
||||||
<p>
|
<p>
|
||||||
@ -268,13 +268,19 @@
|
|||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
<!-- Category -->
|
<!-- Category -->
|
||||||
<h5>{% trans "Category" %}:</h5>
|
|
||||||
{% if motion.category %}
|
{% if motion.category %}
|
||||||
|
<h5>{% trans "Category" %}:</h5>
|
||||||
{{ motion.category }}
|
{{ motion.category }}
|
||||||
{% else %}
|
|
||||||
–
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Tags -->
|
||||||
|
{% for tag in motion.tags.all %}
|
||||||
|
{% if forloop.first %}
|
||||||
|
<h5>{% trans "Tags" %}:</h5>
|
||||||
|
{% endif %}
|
||||||
|
<span class="optional label">{{ tag }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
<!-- Creation Time -->
|
<!-- Creation Time -->
|
||||||
<h5>
|
<h5>
|
||||||
{% if motion.versions.count > 1 %}
|
{% if motion.versions.count > 1 %}
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if perms.core.can_manage_tags %}
|
{% if perms.core.can_manage_tags %}
|
||||||
<a href="{% url 'core_tag_list' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Manage tags' %}">
|
<a href="{% url 'core_tag_list' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Manage tags' %}">
|
||||||
<i class="icon-th"></i>
|
<i class="icon-tags"></i>
|
||||||
<span class="optional-small"> {% trans 'Tags' %}</span>
|
<span class="optional-small"> {% trans 'Tags' %}</span>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -72,15 +72,19 @@
|
|||||||
</thead>
|
</thead>
|
||||||
{% for motion in motion_list %}
|
{% for motion in motion_list %}
|
||||||
<tr class="{% if motion.is_active_slide %}activeline{% endif %}">
|
<tr class="{% if motion.is_active_slide %}activeline{% endif %}">
|
||||||
<td class="nobr">{{ motion.identifier|default:'' }}</td>
|
<td class="nobr">{{ motion.identifier|default:'' }}
|
||||||
<td>
|
|
||||||
<a href="{{ motion|absolute_url }}">{{ motion.title }}</a>
|
|
||||||
{% if motion.is_amendment %}
|
{% if motion.is_amendment %}
|
||||||
<a class="label label-success" data-original-title="Amendment" rel="tooltip">
|
<a class="badge badge-success" data-original-title="{% trans 'Amendment' %}" rel="tooltip">
|
||||||
{{ 'motion_amendments_prefix'|get_config }}
|
{{ 'motion_amendments_prefix'|get_config }}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ motion|absolute_url }}">{{ motion.title }}</a>
|
||||||
|
{% for tag in motion.tags.all %}
|
||||||
|
<span class="optional label">{{ tag }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
<td class="optional">{% if motion.category %}{{ motion.category }}{% else %}–{% endif %}</td>
|
<td class="optional">{% if motion.category %}{{ motion.category }}{% else %}–{% endif %}</td>
|
||||||
<td class="optional-small"><span class="label label-info">{% trans motion.state.name %}</span></td>
|
<td class="optional-small"><span class="label label-info">{% trans motion.state.name %}</span></td>
|
||||||
<td class="optional">
|
<td class="optional">
|
||||||
|
@ -78,7 +78,7 @@
|
|||||||
<small>
|
<small>
|
||||||
{% trans "Motion" %} {{ motion.identifier|default:'' }}
|
{% trans "Motion" %} {{ motion.identifier|default:'' }}
|
||||||
{% if motion.is_amendment %}
|
{% if motion.is_amendment %}
|
||||||
(Amendment of {{ motion.parent.identifier|default:motion.parent }})
|
({% trans "Amendment of" %} {{ motion.parent.identifier|default:motion.parent }})
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if motion.get_active_version.version_number > 1 %} | {% trans 'Version' %} {{ motion.active_version.version_number }}{% endif %}
|
{% if motion.get_active_version.version_number > 1 %} | {% trans 'Version' %} {{ motion.active_version.version_number }}{% endif %}
|
||||||
</small>
|
</small>
|
||||||
|
@ -5,3 +5,4 @@
|
|||||||
{{ object.submitters }}
|
{{ object.submitters }}
|
||||||
{{ object.supporters }}
|
{{ object.supporters }}
|
||||||
{{ object.category }}
|
{{ object.category }}
|
||||||
|
{{ object.tags.all }}
|
||||||
|
@ -59,11 +59,16 @@ class SlideMixin(object):
|
|||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Updates the projector, if the object is on the projector and is deleted.
|
Updates the projector if the object is on the projector and is deleted.
|
||||||
"""
|
"""
|
||||||
from openslides.projector.api import update_projector
|
from openslides.projector.api import update_projector
|
||||||
|
# Checking active slide has to be done before calling super().delete()
|
||||||
|
# because super().delete() deletes the object and than we have no
|
||||||
|
# access to the former existing primary key any more. But updating
|
||||||
|
# projector has to be done after deleting the object of course.
|
||||||
|
update_required = self.is_active_slide()
|
||||||
value = super(SlideMixin, self).delete(*args, **kwargs)
|
value = super(SlideMixin, self).delete(*args, **kwargs)
|
||||||
if self.is_active_slide():
|
if update_required:
|
||||||
update_projector()
|
update_projector()
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
@ -75,10 +75,11 @@ class UserUpdateForm(UserCreateForm):
|
|||||||
|
|
||||||
class GroupForm(CssClassMixin, forms.ModelForm):
|
class GroupForm(CssClassMixin, forms.ModelForm):
|
||||||
permissions = LocalizedModelMultipleChoiceField(
|
permissions = LocalizedModelMultipleChoiceField(
|
||||||
queryset=Permission.objects.all(), label=ugettext_lazy('Permissions'),
|
queryset=Permission.objects.all(), label=ugettext_lazy('Permissions'), required=False,
|
||||||
required=False)
|
widget=forms.SelectMultiple(attrs={'class': 'dont_use_bsmselect'}))
|
||||||
users = forms.ModelMultipleChoiceField(
|
users = forms.ModelMultipleChoiceField(
|
||||||
queryset=User.objects.all(), label=ugettext_lazy('Users'), required=False)
|
queryset=User.objects.all(), label=ugettext_lazy('Participants'), required=False,
|
||||||
|
widget=forms.SelectMultiple(attrs={'class': 'dont_use_bsmselect'}))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Group
|
model = Group
|
||||||
|
23
openslides/utils/haystack_processor.py
Normal file
23
openslides/utils/haystack_processor.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from django.db import models
|
||||||
|
from haystack.signals import RealtimeSignalProcessor
|
||||||
|
|
||||||
|
|
||||||
|
class OpenSlidesProcessor(RealtimeSignalProcessor):
|
||||||
|
def setup(self):
|
||||||
|
# Naive (listen to all model saves).
|
||||||
|
super(OpenSlidesProcessor, self).setup()
|
||||||
|
models.signals.m2m_changed.connect(self.handle_many_to_many)
|
||||||
|
|
||||||
|
def teardown(self):
|
||||||
|
# Naive (listen to all model saves).
|
||||||
|
super(OpenSlidesProcessor, self).teardown()
|
||||||
|
models.signals.m2m_changed.disconnect(self.handle_many_to_many)
|
||||||
|
|
||||||
|
def handle_many_to_many(self, sender, instance, **kwargs):
|
||||||
|
"""
|
||||||
|
Given an individual model instance, determine which backends the
|
||||||
|
update should be sent to & update the object on those backends.
|
||||||
|
"""
|
||||||
|
model_class = type(instance)
|
||||||
|
if kwargs['action'] == 'post_add' or kwargs['action'] == 'post_clear' or kwargs['action'] == 'post_remove':
|
||||||
|
self.handle_save(model_class, instance, **kwargs)
|
Loading…
Reference in New Issue
Block a user