Merge branch 'forum' into 'master'

Forum

See merge request !49
This commit is contained in:
Skia
2017-02-24 03:08:07 +01:00
38 changed files with 1171 additions and 59 deletions

View File

@ -18,6 +18,7 @@ from subscription.models import Subscription
from counter.models import Customer, ProductType, Product, Counter
from com.models import Sith, Weekmail
from election.models import Election, Role, Candidature, ElectionList
from forum.models import Forum, ForumMessage, ForumTopic
class Command(BaseCommand):
@ -37,7 +38,9 @@ class Command(BaseCommand):
Site(id=4000, domain=settings.SITH_URL, name=settings.SITH_NAME).save()
root_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
Group(name="Root").save()
Group(name="Not registered users").save()
Group(name="Public").save()
Group(name="Subscribers").save()
Group(name="Old subscribers").save()
Group(name="Accounting admin").save()
Group(name="Communication admin").save()
Group(name="Counter admin").save()
@ -45,6 +48,7 @@ class Command(BaseCommand):
Group(name="Banned from counters").save()
Group(name="Banned to subscribe").save()
Group(name="SAS admin").save()
Group(name="Forum admin").save()
self.reset_index("core", "auth")
root = User(id=0, username='root', last_name="", first_name="Bibou",
email="ae.info@utbm.fr",
@ -429,3 +433,15 @@ Welcome to the wiki page!
cand = Candidature(role=pres, user=sli, election_list=listeT, program="En fait j'aime pas l'info, je voulais faire GMC")
cand.save()
# Forum
room = Forum(name="Salon de discussions", description="Pour causer de tout", is_category=True)
room.save()
Forum(name="AE", description="Réservé au bureau AE", parent=room).save()
Forum(name="BdF", description="Réservé au bureau BdF", parent=room).save()
hall = Forum(name="Hall de discussions", description="Pour toutes les discussions", parent=room)
hall.save()
various = Forum(name="Divers", description="Pour causer de rien", is_category=True)
various.save()
Forum(name="Promos", description="Réservé aux Promos", parent=various).save()
ForumTopic(forum=hall)

View File

@ -7,9 +7,102 @@ class SithRenderer(Renderer):
def file_link(self, id, suffix):
return reverse('core:file_detail', kwargs={'file_id': id}) + suffix
def exposant(self, text):
return """<sup>%s</sup>""" % text
def indice(self, text):
return """<sub>%s</sub>""" % text
def underline(self, text):
return """<span class="underline">%s</span>""" % text
class SithInlineGrammar(InlineGrammar):
double_emphasis = re.compile(
r'^\*{2}([\s\S]+?)\*{2}(?!\*)' # **word**
)
emphasis = re.compile(
r'^\*((?:\*\*|[^\*])+?)\*(?!\*)' # *word*
)
underline = re.compile(
r'^_{2}([\s\S]+?)_{2}(?!_)' # __word__
)
exposant = re.compile( # FIXME Does not work for now
r'^\^([\s\S]+?)\^' # ^text^
# r'|' # FIXME doesn't properly works like this
# r'^\^(\S+)' # ^word
)
indice = re.compile(
r'^_([\s\S]+?)_' # _text_ (^` hack, because no other solution were found :/ this sadly prevent code in indices)
# r'|' # FIXME doesn't properly works like this
# r'^_(\S+)' # _word
)
class SithInlineLexer(InlineLexer):
grammar_class = SithInlineGrammar
default_rules = [
'escape',
'inline_html',
'autolink',
'url',
'footnote',
'link',
'reflink',
'nolink',
'exposant',
'double_emphasis',
'emphasis',
'underline',
'indice',
'code',
'linebreak',
'strikethrough',
'text',
]
inline_html_rules = [
'escape',
'autolink',
'url',
'link',
'reflink',
'nolink',
'exposant',
'double_emphasis',
'emphasis',
'underline',
'indice',
'code',
'linebreak',
'strikethrough',
'text',
]
def output_underline(self, m):
text = m.group(1)
return self.renderer.underline(text)
def output_exposant(self, m):
text = m.group(1)
return self.renderer.exposant(text)
def output_indice(self, m):
text = m.group(1)
return self.renderer.indice(text)
# Double emphasis rule changed
def output_double_emphasis(self, m):
text = m.group(1)
text = self.output(text)
return self.renderer.double_emphasis(text)
# Emphasis rule changed
def output_emphasis(self, m):
text = m.group(1)
text = self.output(text)
return self.renderer.emphasis(text)
def _process_link(self, m, link, title=None):
try:
try: # Add page:// support for links
page = re.compile(
r'^page://(\S*)' # page://nom_de_ma_page
)
@ -17,7 +110,7 @@ class SithInlineLexer(InlineLexer):
page = match.group(1) or ""
link = reverse('core:page', kwargs={'page_name': page})
except: pass
try:
try: # Add file:// support for links
file_link = re.compile(
r'^file://(\d*)/?(\S*)?' # file://4000/download
)
@ -28,30 +121,48 @@ class SithInlineLexer(InlineLexer):
except: pass
return super(SithInlineLexer, self)._process_link(m, link, title)
# def enable_file_link(self):
# # add file_link rules
# self.rules.file_link = re.compile(
# r'dfile://(\d*)/?(\S*)?' # dfile://4000/download
# )
# # Add file_link parser to default rules
# # you can insert it some place you like
# # but place matters, maybe 2 is not good
# self.default_rules.insert(0, 'file_link')
# def output_file_link(self, m):
# id = m.group(1)
# suffix = m.group(2) or ""
# # you can create an custom render
# # you can also return the html if you like
# # return directly html like this:
# # return reverse('core:file_detail', kwargs={'file_id': id}) + suffix
# return self.renderer.file_link(id, suffix)
renderer = SithRenderer()
renderer = SithRenderer(escape=True)
inline = SithInlineLexer(renderer)
# enable the features
# inline.enable_file_link()
markdown = Markdown(renderer, inline=inline)
if __name__ == "__main__":
print(markdown.inline.default_rules)
print(markdown.inline.inline_html_rules)
text = """
## Basique
* Mettre le texte en **gras** : `**texte**`
* Mettre le texte en *italique* : `*texte*`
* __Souligner__ le texte : `__texte__`
* ~~Barrer du texte~~ : `~~texte~~`
* Mettre ^du texte^ en ^exposant^ : `^mot` ou `^texte^`
* _Mettre du texte_ en _indice_ : `_mot` ou `_texte_`
* Pied de page [^en pied de page]
## Blocs de citations
Un bloc de citation se crée ainsi :
```
> Ceci est
> un bloc de
> citation
```
> Ceci est
> un bloc de
> citation
Il est possible d'intégrer de la syntaxe Markdown-AE dans un tel bloc.
Petit *test* _sur_ ^une^ **seule** ^ligne pour voir^
"""
print(markdown(text))

View File

@ -10,6 +10,8 @@ from django.conf import settings
from django.db import transaction
from django.contrib.staticfiles.storage import staticfiles_storage
from django.utils.html import escape
from django.utils.functional import cached_property
from phonenumber_field.modelfields import PhoneNumberField
from datetime import datetime, timedelta, date
@ -182,9 +184,11 @@ class User(AbstractBaseUser):
def to_dict(self):
return self.__dict__
@cached_property
def was_subscribed(self):
return self.subscriptions.exists()
@cached_property
def is_subscribed(self):
s = self.subscriptions.last()
return s.is_valid_now() if s is not None else False
@ -204,8 +208,12 @@ class User(AbstractBaseUser):
return False
if group_id == settings.SITH_GROUP_PUBLIC_ID:
return True
if group_id == settings.SITH_GROUP_SUBSCRIBERS_ID:
return self.is_subscribed
if group_id == settings.SITH_GROUP_OLD_SUBSCRIBERS_ID:
return self.was_subscribed
if group_name == settings.SITH_MAIN_MEMBERS_GROUP: # We check the subscription if asked
return self.is_subscribed()
return self.is_subscribed
if group_name[-len(settings.SITH_BOARD_SUFFIX):] == settings.SITH_BOARD_SUFFIX:
from club.models import Club
name = group_name[:-len(settings.SITH_BOARD_SUFFIX)]
@ -226,25 +234,25 @@ class User(AbstractBaseUser):
return True
return self.groups.filter(name=group_name).exists()
@property
@cached_property
def is_root(self):
return self.is_superuser or self.groups.filter(id=settings.SITH_GROUP_ROOT_ID).exists()
@property
@cached_property
def is_board_member(self):
from club.models import Club
return Club.objects.filter(unix_name=settings.SITH_MAIN_CLUB['unix_name']).first().get_membership_for(self)
@property
@cached_property
def is_launderette_manager(self):
from club.models import Club
return Club.objects.filter(unix_name=settings.SITH_LAUNDERETTE_MANAGER['unix_name']).first().get_membership_for(self)
@property
@cached_property
def is_banned_alcohol(self):
return self.is_in_group(settings.SITH_GROUP_BANNED_ALCOHOL_ID)
@property
@cached_property
def is_banned_counter(self):
return self.is_in_group(settings.SITH_GROUP_BANNED_COUNTER_ID)
@ -418,10 +426,20 @@ class User(AbstractBaseUser):
escape(self.get_display_name()),
)
@property
@cached_property
def subscribed(self):
return self.is_in_group(settings.SITH_MAIN_MEMBERS_GROUP)
@cached_property
def forum_infos(self):
try:
return self._forum_infos
except:
from forum.models import ForumUserInfo
infos = ForumUserInfo(user=self)
infos.save()
return infos
class AnonymousUser(AuthAnonymousUser):
def __init__(self, request):
super(AnonymousUser, self).__init__()
@ -652,12 +670,12 @@ class SithFile(models.Model):
else:
return super(SithFile, self).__getattribute__(attr)
@property
@cached_property
def as_picture(self):
from sas.models import Picture
return Picture.objects.filter(id=self.id).first()
@property
@cached_property
def as_album(self):
from sas.models import Album
return Album.objects.filter(id=self.id).first()

View File

@ -11,6 +11,20 @@ a {
}
a:hover { color: #7FDBFF; }
a:active { color: #007BE6; }
.ib {
display: inline-block;
padding: 2px;
margin: 2px;
}
.w_big {
width: 75%;
}
.w_medium {
width: 45%;
}
.w_small {
width: 20%;
}
/*--------------------------------HEADER-------------------------------*/
#logo {
margin-left: 5%;
@ -189,7 +203,11 @@ ul, ol {
code {
font-family: monospace;
}
blockquote {
margin: 10px;
padding: 5px;
border: solid 1px black;
}
.edit-bar {
display: block;
margin: 4px;
@ -372,6 +390,47 @@ textarea {
display: inline;
}
/*------------------------------FORUM----------------------------------*/
.topic a, .forum a, .category a {
color: black;
}
.topic a:hover, .forum a:hover, .category a:hover {
color: #424242;
text-decoration: underline;
}
.topic {
border: solid skyblue 1px;
padding: 2px;
margin: 2px;
}
.forum {
background: lightblue;
padding: 2px;
margin: 2px;
}
.category {
background: skyblue;
}
.message {
padding: 2px;
margin: 2px;
background: skyblue;
}
.unread {
background: #e6ddad;
}
.message h5 {
font-size: 100%;
}
.msg_author {
display: inline-block;
width: 19%;
text-align: center;
}
.msg_author img {
max-width: 80%;
margin: 0px auto;
}
/*------------------------------SAS------------------------------------*/
.album {
display: inline-block;

View File

@ -91,7 +91,7 @@
<a href="https://ae.utbm.fr/matmatronch/">{% trans %}Matmatronch{% endtrans %}</a>
<a href="{{ url('core:page', page_name="Index") }}">{% trans %}Wiki{% endtrans %}</a>
<a href="{{ url('sas:main') }}">{% trans %}SAS{% endtrans %}</a>
<a href="https://ae.utbm.fr/forum2/">{% trans %}Forum{% endtrans %}</a>
<a href="{{ url('forum:main') }}">{% trans %}Forum{% endtrans %}</a>
<a href="{{ url('core:page', "services") }}">{% trans %}Services{% endtrans %}</a>
<a href="{{ url('core:file_list') }}">{% trans %}Files{% endtrans %}</a>
<a href="https://ae.utbm.fr/article.php?name=liens">{% trans %}Sponsors{% endtrans %}</a>

View File

@ -54,7 +54,7 @@
{% if user.memberships.filter(end_date=None).exists() or user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) or user == profile %}
{# if the user is member of a club, he can view the subscription state #}
<p>
{% if profile.is_subscribed() %}
{% if profile.is_subscribed %}
{% if user == profile or user.is_root or user.is_board_member %}
{{ user_subscription(profile) }}
{% endif %}

View File

@ -91,7 +91,7 @@
<h4>{% trans %}Elections{% endtrans %}</h4>
<ul>
<li><a href="{{ url('election:list') }}">{% trans %}See available elections{% endtrans %}</a></li>
{%- if user.is_subscribed() -%}
{%- if user.is_subscribed -%}
<li><a href="{{ url('election:create') }}">{% trans %}Create a new election{% endtrans %}</a></li>
{%- endif -%}
</ul>

View File

@ -10,7 +10,7 @@ register = template.Library()
@register.filter(is_safe=False)
@stringfilter
def markdown(text):
return mark_safe(md(escape(text)))
return mark_safe(md(text))
@register.filter()
@stringfilter

View File

@ -253,8 +253,8 @@ http://git.an
response = self.client.get(reverse('core:page', kwargs={'page_name': 'guy'}))
self.assertTrue(response.status_code == 200)
self.assertTrue('<p>Guy <em>bibou</em></p>\\n<p><a href="http://git.an">http://git.an</a></p>\\n' +
'<h1>Swag</h1>\\n<p>&lt;guy&gt;Bibou&lt;/guy&gt;</p>\\n' +
'<p>&lt;script&gt;alert(&#39;Guy&#39;);&lt;/script&gt;</p>' in str(response.content))
'<h1>Swag</h1>\\n&lt;guy&gt;Bibou&lt;/guy&gt;' +
"&lt;script&gt;alert(\\'Guy\\');&lt;/script&gt;" in str(response.content))
#TODO: many tests on the pages:
# - renaming a page