Merge branch 'feature/forum-search' into 'master'

Forum search

See merge request ae/Sith!181
This commit is contained in:
Skia 2018-12-13 20:57:01 +01:00
commit acfbdd1ad5
18 changed files with 300 additions and 120 deletions

View File

@ -366,7 +366,11 @@ class User(AbstractBaseUser):
return False return False
if group_id == settings.SITH_GROUP_ROOT_ID and self.is_superuser: if group_id == settings.SITH_GROUP_ROOT_ID and self.is_superuser:
return True return True
return self.groups.filter(name=group_name).exists() return group_name in self.cached_groups_names
@cached_property
def cached_groups_names(self):
return [g.name for g in self.groups.all()]
@cached_property @cached_property
def is_root(self): def is_root(self):

View File

@ -2,6 +2,7 @@
# #
# Copyright 2016,2017 # Copyright 2016,2017
# - Skia <skia@libskia.so> # - Skia <skia@libskia.so>
# - Sli <antoine@bartuccio.fr>
# #
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM, # Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
# http://ae.utbm.fr. # http://ae.utbm.fr.
@ -27,6 +28,7 @@ from django.db import models
from haystack import indexes, signals from haystack import indexes, signals
from core.models import User from core.models import User
from forum.models import ForumMessage, ForumMessageMeta
class UserIndex(indexes.SearchIndex, indexes.Indexable): class UserIndex(indexes.SearchIndex, indexes.Indexable):
@ -44,13 +46,68 @@ class UserIndex(indexes.SearchIndex, indexes.Indexable):
return "last_update" return "last_update"
class UserOnlySignalProcessor(signals.BaseSignalProcessor): class IndexSignalProcessor(signals.BaseSignalProcessor):
def setup(self): def setup(self):
# Listen only to the ``User`` model. # Listen only to the ``User`` model.
models.signals.post_save.connect(self.handle_save, sender=User) models.signals.post_save.connect(self.handle_save, sender=User)
models.signals.post_delete.connect(self.handle_delete, sender=User) models.signals.post_delete.connect(self.handle_delete, sender=User)
# Listen only to the ``ForumMessage`` model.
models.signals.post_save.connect(self.handle_save, sender=ForumMessageMeta)
models.signals.post_delete.connect(self.handle_delete, sender=ForumMessage)
# Listen to the ``ForumMessageMeta`` model pretending it's a ``ForumMessage``.
models.signals.post_save.connect(
self.handle_forum_message_meta_save, sender=ForumMessageMeta
)
models.signals.post_delete.connect(
self.handle_forum_message_meta_delete, sender=ForumMessageMeta
)
def teardown(self): def teardown(self):
# Disconnect only for the ``User`` model. # Disconnect only for the ``User`` model.
models.signals.post_save.disconnect(self.handle_save, sender=User) models.signals.post_save.disconnect(self.handle_save, sender=User)
models.signals.post_delete.disconnect(self.handle_delete, sender=User) models.signals.post_delete.disconnect(self.handle_delete, sender=User)
# Disconnect only to the ``ForumMessage`` model.
models.signals.post_save.disconnect(self.handle_save, sender=ForumMessage)
models.signals.post_delete.disconnect(self.handle_delete, sender=ForumMessage)
# Disconnect to the ``ForumMessageMeta`` model pretending it's a ``ForumMessage``.
models.signals.post_save.disconnect(
self.handle_forum_message_meta_save, sender=ForumMessageMeta
)
models.signals.post_delete.disconnect(
self.handle_forum_message_meta_delete, sender=ForumMessageMeta
)
def handle_forum_message_meta_save(self, sender, instance, **kwargs):
super(IndexSignalProcessor, self).handle_save(
ForumMessage, instance.message, **kwargs
)
def handle_forum_message_meta_delete(self, sender, instance, **kwargs):
super(IndexSignalProcessor, self).handle_delete(
ForumMessage, instance.message, **kwargs
)
class BigCharFieldIndex(indexes.CharField):
"""
Workaround to avoid xapian.InvalidArgument: Term too long (> 245)
See https://groups.google.com/forum/#!topic/django-haystack/hRJKcPNPXqw/discussion
"""
def prepare(self, term):
return bytes(super(BigCharFieldIndex, self).prepare(term), "utf-8")[
:245
].decode("utf-8", errors="ignore")
class ForumMessageIndex(indexes.SearchIndex, indexes.Indexable):
text = BigCharFieldIndex(document=True, use_template=True)
auto = indexes.EdgeNgramField(use_template=True)
date = indexes.DateTimeField(model_attr="date")
def get_model(self):
return ForumMessage

View File

@ -1403,6 +1403,18 @@ textarea {
} }
} }
.search_bar {
margin: 10px 0px;
display: flex;
height: 20p;
align-items: center;
}
.search_check {
margin-left: 10px;
}
.search_bouton {
margin-left: 10px;
}
.category { .category {
margin-top: 5px; margin-top: 5px;
background: $secondary-color; background: $secondary-color;

View File

@ -0,0 +1,4 @@
{{ object.topic }}
{{ object.title }}
{{ object.message }}
{{ object.author }}

View File

@ -0,0 +1,4 @@
{{ object.topic }}
{{ object.title }}
{{ object.message }}
{{ object.author }}

View File

@ -2,6 +2,7 @@
# #
# Copyright 2016,2017 # Copyright 2016,2017
# - Skia <skia@libskia.so> # - Skia <skia@libskia.so>
# - Sli <antoine@bartuccio.fr>
# #
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM, # Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
# http://ae.utbm.fr. # http://ae.utbm.fr.
@ -176,6 +177,7 @@ class CanViewMixin(View):
""" """
def dispatch(self, request, *arg, **kwargs): def dispatch(self, request, *arg, **kwargs):
try: try:
self.object = self.get_object() self.object = self.get_object()
if can_view(self.object, request.user): if can_view(self.object, request.user):
@ -184,8 +186,10 @@ class CanViewMixin(View):
except: except:
pass pass
# If we get here, it's a ListView # If we get here, it's a ListView
l_id = [o.id for o in self.get_queryset() if can_view(o, request.user)] queryset = self.get_queryset()
if not l_id and self.get_queryset().count() != 0:
l_id = [o.id for o in queryset if can_view(o, request.user)]
if not l_id and queryset.count() != 0:
raise PermissionDenied raise PermissionDenied
self._get_queryset = self.get_queryset self._get_queryset = self.get_queryset

View File

@ -71,6 +71,8 @@ def notification(request, notif_id):
def search_user(query, as_json=False): def search_user(query, as_json=False):
if query == "":
return []
res = SearchQuerySet().models(User).autocomplete(auto=query)[:20] res = SearchQuerySet().models(User).autocomplete(auto=query)[:20]
return [r.object for r in res] return [r.object for r in res]

View File

@ -331,9 +331,9 @@ class ForumMessage(models.Model):
return user.can_edit(self.topic.forum) return user.can_edit(self.topic.forum)
def can_be_viewed_by(self, user): def can_be_viewed_by(self, user):
return ( # No need to check the real rights since it's already done by the Topic view
not self._deleted # and it impacts performances too much
) # No need to check the real rights since it's already done by the Topic view return not self._deleted
def can_be_moderated_by(self, user): def can_be_moderated_by(self, user):
return self.topic.forum.is_owned_by(user) or user.id == self.author.id return self.topic.forum.is_owned_by(user) or user.id == self.author.id

View File

@ -1,18 +1,12 @@
{% extends "core/base.jinja" %} {% extends "core/base.jinja" %}
{% from 'forum/macros.jinja' import display_forum, display_topic %} {% from 'forum/macros.jinja' import display_forum, display_breadcrumb, display_topic, display_search_bar %}
{% block title %} {% block title %}
{{ forum }} {{ forum }}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div> {{ display_breadcrumb(forum) }}
<a href="{{ url('forum:main') }}">{% trans %}Forum{% endtrans %}</a>
{% for f in forum.get_parent_list()|reverse %}
> <a href="{{ f.get_absolute_url() }}">{{ f }}</a>
{% endfor %}
> <a href="{{ forum.get_absolute_url() }}">{{ forum }}</a>
</div>
<div id="forum"> <div id="forum">
<h3>{{ forum.name }}</h3> <h3>{{ forum.name }}</h3>
<p> <p>
@ -22,6 +16,7 @@
{% if not forum.is_category %} {% if not forum.is_category %}
<a class="ib button" href="{{ url('forum:new_topic', forum_id=forum.id) }}">{% trans %}New topic{% endtrans %}</a> <a class="ib button" href="{{ url('forum:new_topic', forum_id=forum.id) }}">{% trans %}New topic{% endtrans %}</a>
{% endif %} {% endif %}
{{ display_search_bar(request) }}
</p> </p>
{% if forum.children.exists() %} {% if forum.children.exists() %}
<div> <div>

View File

@ -85,9 +85,20 @@
</div> </div>
{% endmacro %} {% endmacro %}
{% macro display_breadcrumb(forum, topic="") %}
<p>
<a href="{{ url('forum:main') }}">{% trans %}Forum{% endtrans %}</a>
{% for f in forum.get_parent_list()|reverse %}
> <a href="{{ f.get_absolute_url() }}">{{ f }}</a>
{% endfor %}
> <a href="{{ forum.get_absolute_url() }}">{{ forum }}</a>
{% if topic != "" %} > <a href="{{ topic.get_absolute_url() }}">{{ topic }}</a>{%- endif -%}
</p>
{% endmacro %}
{% macro display_message(m, user, unread=False) %} {% macro display_message(m, user, unread=False) %}
{% if user.can_view(m) %} {% if user.can_view(m) %}
<div id="msg_{{ m.id }}" class="message {% if unread %}unread{% endif %}"> <div id="msg_{{ m.id }}" class="message {% if unread %}unread{% endif %}">
<div class="msg_author {% if m.deleted %}deleted{% endif %}"> <div class="msg_author {% if m.deleted %}deleted{% endif %}">
{% if m.author.avatar_pict %} {% if m.author.avatar_pict %}
<img src="{{ m.author.avatar_pict.get_download_url() }}" alt="{% trans %}Profile{% endtrans %}" id="picture" /> <img src="{{ m.author.avatar_pict.get_download_url() }}" alt="{% trans %}Profile{% endtrans %}" id="picture" />
@ -143,7 +154,7 @@
</div> </div>
</div> </div>
{% else %} {% else %}
<div id="msg_{{ m.id }}" class="message"> <div id="msg_{{ m.id }}" class="message">
<div class="msg_author deleted"> <div class="msg_author deleted">
</div> </div>
<div class="msg_content deleted"> <div class="msg_content deleted">
@ -155,3 +166,12 @@
{{ m.mark_as_read(user) or "" }} {{ m.mark_as_read(user) or "" }}
{% endmacro %} {% endmacro %}
{% macro display_search_bar(request) %}
<form class="search_bar" action="{{ url('forum:search') }}" method="GET">
<input type="text" placeholder="{% trans %}Search{% endtrans %}" name="query" value="{{ request.GET.query|default('') }}"/>
<input type="checkbox" class="search_check" name="order" value="date" {% if request.GET.order|default("") == "date" or (request.GET.order|default("") == "" and request.GET.query|default("") == "") -%}
checked
{%- endif -%}> {% trans %}Order by date{% endtrans %}<br>
<input type="submit" class="search_bouton" value="{% trans %}Search{% endtrans %}"/>
</form>
{% endmacro %}

View File

@ -1,6 +1,6 @@
{% extends "core/base.jinja" %} {% extends "core/base.jinja" %}
{% from 'core/macros.jinja' import user_profile_link %} {% from 'core/macros.jinja' import user_profile_link %}
{% from 'forum/macros.jinja' import display_forum %} {% from 'forum/macros.jinja' import display_forum, display_search_bar %}
{% block title %} {% block title %}
{% trans %}Forum{% endtrans %} {% trans %}Forum{% endtrans %}
@ -15,6 +15,7 @@
<p> <p>
<a class="ib button" href="{{ url('forum:last_unread') }}">{% trans %}View last unread messages{% endtrans %}</a> <a class="ib button" href="{{ url('forum:last_unread') }}">{% trans %}View last unread messages{% endtrans %}</a>
<a class="ib button" href="{{ url('forum:favorite_topics') }}">{% trans %}Favorite topics{% endtrans %}</a> <a class="ib button" href="{{ url('forum:favorite_topics') }}">{% trans %}Favorite topics{% endtrans %}</a>
{{ display_search_bar(request) }}
</p> </p>
{% if user.is_in_group(settings.SITH_GROUP_FORUM_ADMIN_ID) or user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) %} {% if user.is_in_group(settings.SITH_GROUP_FORUM_ADMIN_ID) or user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) %}
<p> <p>
@ -34,6 +35,7 @@
</div> </div>
</div> </div>
</div> </div>
{% for f in forum_list %} {% for f in forum_list %}
<div> <div>
{{ display_forum(f, user, True) }} {{ display_forum(f, user, True) }}

View File

@ -1,5 +1,5 @@
{% extends "core/base.jinja" %} {% extends "core/base.jinja" %}
{% from 'forum/macros.jinja' import display_message %} {% from 'forum/macros.jinja' import display_message, display_search_bar %}
{% block title %} {% block title %}
{% if topic %} {% if topic %}
@ -11,6 +11,7 @@
{% block content %} {% block content %}
{% if topic %} {% if topic %}
{{ display_search_bar(request) }}
<p> <p>
<a href="{{ url('forum:main') }}">{% trans %}Forum{% endtrans %}</a> <a href="{{ url('forum:main') }}">{% trans %}Forum{% endtrans %}</a>
{% for f in topic.forum.get_parent_list() %} {% for f in topic.forum.get_parent_list() %}

View File

@ -0,0 +1,21 @@
{% extends "core/base.jinja" %}
{% from 'forum/macros.jinja' import display_message, display_breadcrumb, display_search_bar %}
{% block content %}
<div id="forum">
{{ display_search_bar(request) }}
{% if object_list|length != 0 %}
<br>
<div class="search-results">
{% for m in object_list %}
{{ display_breadcrumb(m.topic.forum, m.topic) }}
{{ display_message(m, user) }}
{% endfor %}
</div>
{% else %}
{% trans %}No result found{% endtrans %}
{% endif %}
</div>
{% endblock %}

View File

@ -1,6 +1,6 @@
{% extends "core/base.jinja" %} {% extends "core/base.jinja" %}
{% from 'core/macros.jinja' import user_profile_link %} {% from 'core/macros.jinja' import user_profile_link %}
{% from 'forum/macros.jinja' import display_message %} {% from 'forum/macros.jinja' import display_message, display_breadcrumb, display_search_bar %}
{% block title %} {% block title %}
{{ topic }} {{ topic }}
@ -26,15 +26,8 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<p> {{ display_breadcrumb(topic.forum, topic) }}
<a href="{{ url('forum:main') }}">{% trans %}Forum{% endtrans %}</a> <h3>{{ topic.title }}</h3>
{% for f in topic.forum.get_parent_list()|reverse %}
> <a href="{{ f.get_absolute_url() }}">{{ f }}</a>
{% endfor %}
> <a href="{{ topic.forum.get_absolute_url() }}">{{ topic.forum }}</a>
> <a href="{{ topic.get_absolute_url() }}">{{ topic }}</a>
</p>
<h3>{{ topic.title }}</h3>
<div id="forum"> <div id="forum">
<p>{{ topic.description }}</p> <p>{{ topic.description }}</p>
<p> <p>
@ -46,6 +39,7 @@
{% endif %} {% endif %}
</p> </p>
{{ display_search_bar(request) }}
<p style="text-align: right; background: #d8e7f3;"> <p style="text-align: right; background: #d8e7f3;">
{% for p in msgs.paginator.page_range %} {% for p in msgs.paginator.page_range %}
<span class="ib" style="background: {% if p == msgs.number %}white{% endif %}; margin: 0;"><a href="?page={{ p }}">{{ p }}</a></span> <span class="ib" style="background: {% if p == msgs.number %}white{% endif %}; margin: 0;"><a href="?page={{ p }}">{{ p }}</a></span>

View File

@ -26,8 +26,10 @@ from django.conf.urls import url
from forum.views import * from forum.views import *
urlpatterns = [ urlpatterns = [
url(r"^$", ForumMainView.as_view(), name="main"), url(r"^$", ForumMainView.as_view(), name="main"),
url(r"^search/$", ForumSearchView.as_view(), name="search"),
url(r"^new_forum$", ForumCreateView.as_view(), name="new_forum"), url(r"^new_forum$", ForumCreateView.as_view(), name="new_forum"),
url(r"^mark_all_as_read$", ForumMarkAllAsRead.as_view(), name="mark_all_as_read"), url(r"^mark_all_as_read$", ForumMarkAllAsRead.as_view(), name="mark_all_as_read"),
url(r"^last_unread$", ForumLastUnread.as_view(), name="last_unread"), url(r"^last_unread$", ForumLastUnread.as_view(), name="last_unread"),

View File

@ -2,6 +2,7 @@
# #
# Copyright 2016,2017,2018 # Copyright 2016,2017,2018
# - Skia <skia@libskia.so> # - Skia <skia@libskia.so>
# - Sli <antoine@bartuccio.fr>
# #
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM, # Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
# http://ae.utbm.fr. # http://ae.utbm.fr.
@ -36,9 +37,56 @@ from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from ajax_select import make_ajax_field from ajax_select import make_ajax_field
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, CanCreateMixin from core.views import (
CanViewMixin,
CanEditMixin,
CanEditPropMixin,
CanCreateMixin,
can_view,
)
from core.views.forms import MarkdownInput from core.views.forms import MarkdownInput
from forum.models import Forum, ForumMessage, ForumTopic, ForumMessageMeta from forum.models import Forum, ForumMessage, ForumTopic, ForumMessageMeta
from haystack.query import RelatedSearchQuerySet
class ForumSearchView(ListView):
template_name = "forum/search.jinja"
def get_queryset(self):
query = self.request.GET.get("query", "")
order_by = self.request.GET.get("order", "")
if query == "":
return []
queryset = RelatedSearchQuerySet().models(ForumMessage).autocomplete(auto=query)
if order_by == "date":
queryset = queryset.order_by("-date")
queryset = queryset.load_all()
queryset = queryset.load_all_queryset(
ForumMessage,
ForumMessage.objects.all()
.prefetch_related("topic__forum__edit_groups")
.prefetch_related("topic__forum__view_groups")
.prefetch_related("topic__forum__owner_club"),
)
# Filter unauthorized responses
resp = []
count = 0
max_count = 30
for r in queryset:
if count >= max_count:
return resp
if can_view(r.object, self.request.user) and can_view(
r.object.topic, self.request.user
):
resp.append(r.object)
count += 1
return resp
class ForumMainView(ListView): class ForumMainView(ListView):

View File

@ -6,7 +6,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-11-08 00:26+0100\n" "POT-Creation-Date: 2018-12-11 20:07+0100\n"
"PO-Revision-Date: 2016-07-18\n" "PO-Revision-Date: 2016-07-18\n"
"Last-Translator: Skia <skia@libskia.so>\n" "Last-Translator: Skia <skia@libskia.so>\n"
"Language-Team: AE info <ae.info@utbm.fr>\n" "Language-Team: AE info <ae.info@utbm.fr>\n"
@ -219,7 +219,7 @@ msgstr "Compte"
msgid "Company" msgid "Company"
msgstr "Entreprise" msgstr "Entreprise"
#: accounting/models.py:317 sith/settings.py:377 #: accounting/models.py:317 sith/settings.py:378
#: stock/templates/stock/shopping_list_items.jinja:37 #: stock/templates/stock/shopping_list_items.jinja:37
msgid "Other" msgid "Other"
msgstr "Autre" msgstr "Autre"
@ -776,7 +776,7 @@ msgstr "Opération liée : "
#: core/templates/core/user_preferences.jinja:12 #: core/templates/core/user_preferences.jinja:12
#: core/templates/core/user_preferences.jinja:19 #: core/templates/core/user_preferences.jinja:19
#: counter/templates/counter/cash_register_summary.jinja:22 #: counter/templates/counter/cash_register_summary.jinja:22
#: forum/templates/forum/reply.jinja:33 #: forum/templates/forum/reply.jinja:34
#: subscription/templates/subscription/subscription.jinja:25 #: subscription/templates/subscription/subscription.jinja:25
#: trombi/templates/trombi/comment.jinja:26 #: trombi/templates/trombi/comment.jinja:26
#: trombi/templates/trombi/edit_profile.jinja:13 #: trombi/templates/trombi/edit_profile.jinja:13
@ -1492,9 +1492,9 @@ msgstr "Type"
#: com/templates/com/news_admin_list.jinja:249 #: com/templates/com/news_admin_list.jinja:249
#: com/templates/com/news_admin_list.jinja:286 #: com/templates/com/news_admin_list.jinja:286
#: com/templates/com/weekmail.jinja:19 com/templates/com/weekmail.jinja:48 #: com/templates/com/weekmail.jinja:19 com/templates/com/weekmail.jinja:48
#: core/templates/core/base.jinja:341 forum/templates/forum/forum.jinja:29 #: core/templates/core/base.jinja:341 forum/templates/forum/forum.jinja:30
#: forum/templates/forum/forum.jinja:48 forum/templates/forum/main.jinja:26 #: forum/templates/forum/forum.jinja:49 forum/templates/forum/main.jinja:27
#: forum/views.py:192 #: forum/views.py:213
msgid "Title" msgid "Title"
msgstr "Titre" msgstr "Titre"
@ -1518,7 +1518,7 @@ msgstr "Résumé"
#: com/templates/com/news_admin_list.jinja:252 #: com/templates/com/news_admin_list.jinja:252
#: com/templates/com/news_admin_list.jinja:289 #: com/templates/com/news_admin_list.jinja:289
#: com/templates/com/weekmail.jinja:17 com/templates/com/weekmail.jinja:46 #: com/templates/com/weekmail.jinja:17 com/templates/com/weekmail.jinja:46
#: forum/templates/forum/forum.jinja:52 #: forum/templates/forum/forum.jinja:53
msgid "Author" msgid "Author"
msgstr "Auteur" msgstr "Auteur"
@ -1628,7 +1628,7 @@ msgstr ""
#: com/templates/com/news_edit.jinja:56 com/templates/com/weekmail.jinja:10 #: com/templates/com/news_edit.jinja:56 com/templates/com/weekmail.jinja:10
#: core/templates/core/macros_pages.jinja:49 #: core/templates/core/macros_pages.jinja:49
#: forum/templates/forum/reply.jinja:32 #: forum/templates/forum/reply.jinja:33
msgid "Preview" msgid "Preview"
msgstr "Prévisualiser" msgstr "Prévisualiser"
@ -2113,7 +2113,7 @@ msgstr "Un utilisateur de ce nom d'utilisateur existe déjà"
#: core/templates/core/user_edit.jinja:17 #: core/templates/core/user_edit.jinja:17
#: election/templates/election/election_detail.jinja:340 #: election/templates/election/election_detail.jinja:340
#: forum/templates/forum/macros.jinja:93 forum/templates/forum/macros.jinja:95 #: forum/templates/forum/macros.jinja:93 forum/templates/forum/macros.jinja:95
#: forum/templates/forum/reply.jinja:38 forum/templates/forum/reply.jinja:40 #: forum/templates/forum/reply.jinja:39 forum/templates/forum/reply.jinja:41
#: trombi/templates/trombi/user_tools.jinja:41 #: trombi/templates/trombi/user_tools.jinja:41
msgid "Profile" msgid "Profile"
msgstr "Profil" msgstr "Profil"
@ -2310,6 +2310,8 @@ msgid "Register"
msgstr "S'enregister" msgstr "S'enregister"
#: core/templates/core/base.jinja:75 core/templates/core/base.jinja:76 #: core/templates/core/base.jinja:75 core/templates/core/base.jinja:76
#: forum/templates/forum/macros.jinja:160
#: forum/templates/forum/macros.jinja:162
#: matmat/templates/matmat/search_form.jinja:37 #: matmat/templates/matmat/search_form.jinja:37
#: matmat/templates/matmat/search_form.jinja:47 #: matmat/templates/matmat/search_form.jinja:47
#: matmat/templates/matmat/search_form.jinja:58 #: matmat/templates/matmat/search_form.jinja:58
@ -2370,8 +2372,8 @@ msgstr "GA"
#: forum/templates/forum/forum.jinja:10 #: forum/templates/forum/forum.jinja:10
#: forum/templates/forum/last_unread.jinja:14 #: forum/templates/forum/last_unread.jinja:14
#: forum/templates/forum/main.jinja:6 forum/templates/forum/main.jinja:11 #: forum/templates/forum/main.jinja:6 forum/templates/forum/main.jinja:11
#: forum/templates/forum/main.jinja:14 forum/templates/forum/reply.jinja:15 #: forum/templates/forum/main.jinja:14 forum/templates/forum/reply.jinja:16
#: forum/templates/forum/topic.jinja:30 #: forum/templates/forum/topic.jinja:31
msgid "Forum" msgid "Forum"
msgstr "Forum" msgstr "Forum"
@ -2385,7 +2387,7 @@ msgstr "Photos"
#: eboutic/templates/eboutic/eboutic_main.jinja:24 #: eboutic/templates/eboutic/eboutic_main.jinja:24
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:8 #: eboutic/templates/eboutic/eboutic_makecommand.jinja:8
#: eboutic/templates/eboutic/eboutic_payment_result.jinja:4 #: eboutic/templates/eboutic/eboutic_payment_result.jinja:4
#: sith/settings.py:376 sith/settings.py:384 #: sith/settings.py:377 sith/settings.py:385
msgid "Eboutic" msgid "Eboutic"
msgstr "Eboutic" msgstr "Eboutic"
@ -3589,8 +3591,8 @@ msgstr "quantité"
msgid "Sith account" msgid "Sith account"
msgstr "Compte utilisateur" msgstr "Compte utilisateur"
#: counter/models.py:448 sith/settings.py:369 sith/settings.py:374 #: counter/models.py:448 sith/settings.py:370 sith/settings.py:375
#: sith/settings.py:392 #: sith/settings.py:393
msgid "Credit card" msgid "Credit card"
msgstr "Carte bancaire" msgstr "Carte bancaire"
@ -4352,25 +4354,25 @@ msgstr "dernière date de lecture"
msgid "Favorite topics" msgid "Favorite topics"
msgstr "Topics favoris" msgstr "Topics favoris"
#: forum/templates/forum/forum.jinja:20 forum/templates/forum/main.jinja:21 #: forum/templates/forum/forum.jinja:20 forum/templates/forum/main.jinja:22
msgid "New forum" msgid "New forum"
msgstr "Nouveau forum" msgstr "Nouveau forum"
#: forum/templates/forum/forum.jinja:23 forum/templates/forum/reply.jinja:8 #: forum/templates/forum/forum.jinja:23 forum/templates/forum/reply.jinja:8
#: forum/templates/forum/reply.jinja:27 #: forum/templates/forum/reply.jinja:28
msgid "New topic" msgid "New topic"
msgstr "Nouveau sujet" msgstr "Nouveau sujet"
#: forum/templates/forum/forum.jinja:33 forum/templates/forum/main.jinja:30 #: forum/templates/forum/forum.jinja:34 forum/templates/forum/main.jinja:31
msgid "Topics" msgid "Topics"
msgstr "Sujets" msgstr "Sujets"
#: forum/templates/forum/forum.jinja:36 forum/templates/forum/forum.jinja:58 #: forum/templates/forum/forum.jinja:37 forum/templates/forum/forum.jinja:59
#: forum/templates/forum/main.jinja:33 #: forum/templates/forum/main.jinja:34
msgid "Last message" msgid "Last message"
msgstr "Dernier message" msgstr "Dernier message"
#: forum/templates/forum/forum.jinja:55 #: forum/templates/forum/forum.jinja:56
msgid "Messages" msgid "Messages"
msgstr "Messages" msgstr "Messages"
@ -4400,28 +4402,36 @@ msgstr " le "
msgid "Deleted or unreadable message." msgid "Deleted or unreadable message."
msgstr "Message supprimé ou non-visible." msgstr "Message supprimé ou non-visible."
#: forum/templates/forum/macros.jinja:161
msgid "Order by date"
msgstr "Trier par date"
#: forum/templates/forum/main.jinja:16 #: forum/templates/forum/main.jinja:16
msgid "View last unread messages" msgid "View last unread messages"
msgstr "Voir les derniers messages non lus" msgstr "Voir les derniers messages non lus"
#: forum/templates/forum/reply.jinja:6 forum/templates/forum/reply.jinja:24 #: forum/templates/forum/reply.jinja:6 forum/templates/forum/reply.jinja:25
#: forum/templates/forum/topic.jinja:41 forum/templates/forum/topic.jinja:66 #: forum/templates/forum/topic.jinja:42 forum/templates/forum/topic.jinja:67
msgid "Reply" msgid "Reply"
msgstr "Répondre" msgstr "Répondre"
#: forum/templates/forum/topic.jinja:43 #: forum/templates/forum/search.jinja:16
msgid "No result found"
msgstr "Pas de résultats"
#: forum/templates/forum/topic.jinja:44
msgid "Unmark as favorite" msgid "Unmark as favorite"
msgstr "Enlever des favoris" msgstr "Enlever des favoris"
#: forum/templates/forum/topic.jinja:45 #: forum/templates/forum/topic.jinja:46
msgid "Mark as favorite" msgid "Mark as favorite"
msgstr "Ajouter aux favoris" msgstr "Ajouter aux favoris"
#: forum/views.py:138 #: forum/views.py:159
msgid "Apply rights and club owner recursively" msgid "Apply rights and club owner recursively"
msgstr "Appliquer les droits et le club propriétaire récursivement" msgstr "Appliquer les droits et le club propriétaire récursivement"
#: forum/views.py:356 #: forum/views.py:377
#, python-format #, python-format
msgid "%(author)s said" msgid "%(author)s said"
msgstr "Citation de %(author)s" msgstr "Citation de %(author)s"
@ -4475,12 +4485,12 @@ msgid "Washing and drying"
msgstr "Lavage et séchage" msgstr "Lavage et séchage"
#: launderette/templates/launderette/launderette_book.jinja:27 #: launderette/templates/launderette/launderette_book.jinja:27
#: sith/settings.py:520 #: sith/settings.py:521
msgid "Washing" msgid "Washing"
msgstr "Lavage" msgstr "Lavage"
#: launderette/templates/launderette/launderette_book.jinja:31 #: launderette/templates/launderette/launderette_book.jinja:31
#: sith/settings.py:520 #: sith/settings.py:521
msgid "Drying" msgid "Drying"
msgstr "Séchage" msgstr "Séchage"
@ -4660,251 +4670,251 @@ msgstr "Erreur de création de l'album %(album)s : %(msg)s"
msgid "Add user" msgid "Add user"
msgstr "Ajouter une personne" msgstr "Ajouter une personne"
#: sith/settings.py:215 #: sith/settings.py:216
msgid "English" msgid "English"
msgstr "Anglais" msgstr "Anglais"
#: sith/settings.py:215 #: sith/settings.py:216
msgid "French" msgid "French"
msgstr "Français" msgstr "Français"
#: sith/settings.py:350 #: sith/settings.py:351
msgid "TC" msgid "TC"
msgstr "TC" msgstr "TC"
#: sith/settings.py:351 #: sith/settings.py:352
msgid "IMSI" msgid "IMSI"
msgstr "IMSI" msgstr "IMSI"
#: sith/settings.py:352 #: sith/settings.py:353
msgid "IMAP" msgid "IMAP"
msgstr "IMAP" msgstr "IMAP"
#: sith/settings.py:353 #: sith/settings.py:354
msgid "INFO" msgid "INFO"
msgstr "INFO" msgstr "INFO"
#: sith/settings.py:354 #: sith/settings.py:355
msgid "GI" msgid "GI"
msgstr "GI" msgstr "GI"
#: sith/settings.py:355 #: sith/settings.py:356
msgid "E" msgid "E"
msgstr "E" msgstr "E"
#: sith/settings.py:356 #: sith/settings.py:357
msgid "EE" msgid "EE"
msgstr "EE" msgstr "EE"
#: sith/settings.py:357 #: sith/settings.py:358
msgid "GESC" msgid "GESC"
msgstr "GESC" msgstr "GESC"
#: sith/settings.py:358 #: sith/settings.py:359
msgid "GMC" msgid "GMC"
msgstr "GMC" msgstr "GMC"
#: sith/settings.py:359 #: sith/settings.py:360
msgid "MC" msgid "MC"
msgstr "MC" msgstr "MC"
#: sith/settings.py:360 #: sith/settings.py:361
msgid "EDIM" msgid "EDIM"
msgstr "EDIM" msgstr "EDIM"
#: sith/settings.py:361 #: sith/settings.py:362
msgid "Humanities" msgid "Humanities"
msgstr "Humanités" msgstr "Humanités"
#: sith/settings.py:362 #: sith/settings.py:363
msgid "N/A" msgid "N/A"
msgstr "N/A" msgstr "N/A"
#: sith/settings.py:366 sith/settings.py:373 sith/settings.py:390 #: sith/settings.py:367 sith/settings.py:374 sith/settings.py:391
msgid "Check" msgid "Check"
msgstr "Chèque" msgstr "Chèque"
#: sith/settings.py:367 sith/settings.py:375 sith/settings.py:391 #: sith/settings.py:368 sith/settings.py:376 sith/settings.py:392
msgid "Cash" msgid "Cash"
msgstr "Espèces" msgstr "Espèces"
#: sith/settings.py:368 #: sith/settings.py:369
msgid "Transfert" msgid "Transfert"
msgstr "Virement" msgstr "Virement"
#: sith/settings.py:381 #: sith/settings.py:382
msgid "Belfort" msgid "Belfort"
msgstr "Belfort" msgstr "Belfort"
#: sith/settings.py:382 #: sith/settings.py:383
msgid "Sevenans" msgid "Sevenans"
msgstr "Sevenans" msgstr "Sevenans"
#: sith/settings.py:383 #: sith/settings.py:384
msgid "Montbéliard" msgid "Montbéliard"
msgstr "Montbéliard" msgstr "Montbéliard"
#: sith/settings.py:434 #: sith/settings.py:435
msgid "One semester" msgid "One semester"
msgstr "Un semestre, 15 €" msgstr "Un semestre, 15 €"
#: sith/settings.py:435 #: sith/settings.py:436
msgid "Two semesters" msgid "Two semesters"
msgstr "Deux semestres, 28 €" msgstr "Deux semestres, 28 €"
#: sith/settings.py:437 #: sith/settings.py:438
msgid "Common core cursus" msgid "Common core cursus"
msgstr "Cursus tronc commun, 45 €" msgstr "Cursus tronc commun, 45 €"
#: sith/settings.py:441 #: sith/settings.py:442
msgid "Branch cursus" msgid "Branch cursus"
msgstr "Cursus branche, 45 €" msgstr "Cursus branche, 45 €"
#: sith/settings.py:442 #: sith/settings.py:443
msgid "Alternating cursus" msgid "Alternating cursus"
msgstr "Cursus alternant, 30 €" msgstr "Cursus alternant, 30 €"
#: sith/settings.py:443 #: sith/settings.py:444
msgid "Honorary member" msgid "Honorary member"
msgstr "Membre honoraire, 0 €" msgstr "Membre honoraire, 0 €"
#: sith/settings.py:444 #: sith/settings.py:445
msgid "Assidu member" msgid "Assidu member"
msgstr "Membre d'Assidu, 0 €" msgstr "Membre d'Assidu, 0 €"
#: sith/settings.py:445 #: sith/settings.py:446
msgid "Amicale/DOCEO member" msgid "Amicale/DOCEO member"
msgstr "Membre de l'Amicale/DOCEO, 0 €" msgstr "Membre de l'Amicale/DOCEO, 0 €"
#: sith/settings.py:446 #: sith/settings.py:447
msgid "UT network member" msgid "UT network member"
msgstr "Cotisant du réseau UT, 0 €" msgstr "Cotisant du réseau UT, 0 €"
#: sith/settings.py:447 #: sith/settings.py:448
msgid "CROUS member" msgid "CROUS member"
msgstr "Membres du CROUS, 0 €" msgstr "Membres du CROUS, 0 €"
#: sith/settings.py:448 #: sith/settings.py:449
msgid "Sbarro/ESTA member" msgid "Sbarro/ESTA member"
msgstr "Membre de Sbarro ou de l'ESTA, 15 €" msgstr "Membre de Sbarro ou de l'ESTA, 15 €"
#: sith/settings.py:450 #: sith/settings.py:451
msgid "One semester Welcome Week" msgid "One semester Welcome Week"
msgstr "Un semestre Welcome Week" msgstr "Un semestre Welcome Week"
#: sith/settings.py:454 #: sith/settings.py:455
msgid "Two months for free" msgid "Two months for free"
msgstr "Deux mois gratuits" msgstr "Deux mois gratuits"
#: sith/settings.py:455 #: sith/settings.py:456
msgid "Eurok's volunteer" msgid "Eurok's volunteer"
msgstr "Bénévole Eurockéennes" msgstr "Bénévole Eurockéennes"
#: sith/settings.py:457 #: sith/settings.py:458
msgid "Six weeks for free" msgid "Six weeks for free"
msgstr "6 semaines gratuites" msgstr "6 semaines gratuites"
#: sith/settings.py:461 #: sith/settings.py:462
msgid "One day" msgid "One day"
msgstr "Un jour" msgstr "Un jour"
#: sith/settings.py:480 #: sith/settings.py:481
msgid "President" msgid "President"
msgstr "Président" msgstr "Président"
#: sith/settings.py:481 #: sith/settings.py:482
msgid "Vice-President" msgid "Vice-President"
msgstr "Vice-Président" msgstr "Vice-Président"
#: sith/settings.py:482 #: sith/settings.py:483
msgid "Treasurer" msgid "Treasurer"
msgstr "Trésorier" msgstr "Trésorier"
#: sith/settings.py:483 #: sith/settings.py:484
msgid "Communication supervisor" msgid "Communication supervisor"
msgstr "Responsable communication" msgstr "Responsable communication"
#: sith/settings.py:484 #: sith/settings.py:485
msgid "Secretary" msgid "Secretary"
msgstr "Secrétaire" msgstr "Secrétaire"
#: sith/settings.py:485 #: sith/settings.py:486
msgid "IT supervisor" msgid "IT supervisor"
msgstr "Responsable info" msgstr "Responsable info"
#: sith/settings.py:486 #: sith/settings.py:487
msgid "Board member" msgid "Board member"
msgstr "Membre du bureau" msgstr "Membre du bureau"
#: sith/settings.py:487 #: sith/settings.py:488
msgid "Active member" msgid "Active member"
msgstr "Membre actif" msgstr "Membre actif"
#: sith/settings.py:488 #: sith/settings.py:489
msgid "Curious" msgid "Curious"
msgstr "Curieux" msgstr "Curieux"
#: sith/settings.py:524 #: sith/settings.py:525
msgid "A new poster needs to be moderated" msgid "A new poster needs to be moderated"
msgstr "Une nouvelle affiche a besoin d'être modérée" msgstr "Une nouvelle affiche a besoin d'être modérée"
#: sith/settings.py:525 #: sith/settings.py:526
msgid "A new mailing list needs to be moderated" msgid "A new mailing list needs to be moderated"
msgstr "Une nouvelle mailing list a besoin d'être modérée" msgstr "Une nouvelle mailing list a besoin d'être modérée"
#: sith/settings.py:526 #: sith/settings.py:527
#, python-format #, python-format
msgid "There are %s fresh news to be moderated" msgid "There are %s fresh news to be moderated"
msgstr "Il y a %s nouvelles toutes fraîches à modérer" msgstr "Il y a %s nouvelles toutes fraîches à modérer"
#: sith/settings.py:527 #: sith/settings.py:528
msgid "New files to be moderated" msgid "New files to be moderated"
msgstr "Nouveaux fichiers à modérer" msgstr "Nouveaux fichiers à modérer"
#: sith/settings.py:528 #: sith/settings.py:529
#, python-format #, python-format
msgid "There are %s pictures to be moderated in the SAS" msgid "There are %s pictures to be moderated in the SAS"
msgstr "Il y a %s photos à modérer dans le SAS" msgstr "Il y a %s photos à modérer dans le SAS"
#: sith/settings.py:529 #: sith/settings.py:530
msgid "You've been identified on some pictures" msgid "You've been identified on some pictures"
msgstr "Vous avez été identifié sur des photos" msgstr "Vous avez été identifié sur des photos"
#: sith/settings.py:530 #: sith/settings.py:531
#, python-format #, python-format
msgid "You just refilled of %s €" msgid "You just refilled of %s €"
msgstr "Vous avez rechargé votre compte de %s€" msgstr "Vous avez rechargé votre compte de %s€"
#: sith/settings.py:531 #: sith/settings.py:532
#, python-format #, python-format
msgid "You just bought %s" msgid "You just bought %s"
msgstr "Vous avez acheté %s" msgstr "Vous avez acheté %s"
#: sith/settings.py:532 #: sith/settings.py:533
msgid "You have a notification" msgid "You have a notification"
msgstr "Vous avez une notification" msgstr "Vous avez une notification"
#: sith/settings.py:544 #: sith/settings.py:545
msgid "Success!" msgid "Success!"
msgstr "Succès !" msgstr "Succès !"
#: sith/settings.py:545 #: sith/settings.py:546
msgid "Fail!" msgid "Fail!"
msgstr "Échec !" msgstr "Échec !"
#: sith/settings.py:546 #: sith/settings.py:547
msgid "You successfully posted an article in the Weekmail" msgid "You successfully posted an article in the Weekmail"
msgstr "Article posté avec succès dans le Weekmail" msgstr "Article posté avec succès dans le Weekmail"
#: sith/settings.py:547 #: sith/settings.py:548
msgid "You successfully edited an article in the Weekmail" msgid "You successfully edited an article in the Weekmail"
msgstr "Article édité avec succès dans le Weekmail" msgstr "Article édité avec succès dans le Weekmail"
#: sith/settings.py:548 #: sith/settings.py:549
msgid "You successfully sent the Weekmail" msgid "You successfully sent the Weekmail"
msgstr "Weekmail envoyé avec succès" msgstr "Weekmail envoyé avec succès"
#: sith/settings.py:556 #: sith/settings.py:557
msgid "AE tee-shirt" msgid "AE tee-shirt"
msgstr "Tee-shirt AE" msgstr "Tee-shirt AE"

View File

@ -190,7 +190,7 @@ HAYSTACK_CONNECTIONS = {
} }
} }
HAYSTACK_SIGNAL_PROCESSOR = "core.search_indexes.UserOnlySignalProcessor" HAYSTACK_SIGNAL_PROCESSOR = "core.search_indexes.IndexSignalProcessor"
SASS_PRECISION = 8 SASS_PRECISION = 8