diff --git a/com/admin.py b/com/admin.py
index 00a75764..b74b7a48 100644
--- a/com/admin.py
+++ b/com/admin.py
@@ -3,6 +3,7 @@ from django.contrib import admin
from com.models import *
admin.site.register(Sith)
+admin.site.register(News)
diff --git a/com/migrations/0002_news_newsdate.py b/com/migrations/0002_news_newsdate.py
new file mode 100644
index 00000000..0a57e7db
--- /dev/null
+++ b/com/migrations/0002_news_newsdate.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+from django.conf import settings
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('club', '0005_auto_20161120_1149'),
+ ('com', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='News',
+ fields=[
+ ('id', models.AutoField(serialize=False, auto_created=True, primary_key=True, verbose_name='ID')),
+ ('title', models.CharField(max_length=64, verbose_name='title')),
+ ('summary', models.TextField(verbose_name='summary')),
+ ('content', models.TextField(verbose_name='content')),
+ ('type', models.CharField(max_length=16, choices=[('NOTICE', 'Notice'), ('EVENT', 'Event'), ('WEEKLY', 'Weekly'), ('CALL', 'Call')], default='EVENT', verbose_name='type')),
+ ('is_moderated', models.BooleanField(default=False, verbose_name='is moderated')),
+ ('club', models.ForeignKey(to='club.Club', verbose_name='club', related_name='news')),
+ ('moderator', models.ForeignKey(verbose_name='owner', to=settings.AUTH_USER_MODEL, related_name='moderated_news', null=True)),
+ ('owner', models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='owner', related_name='owned_news')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='NewsDate',
+ fields=[
+ ('id', models.AutoField(serialize=False, auto_created=True, primary_key=True, verbose_name='ID')),
+ ('start_date', models.DateTimeField(null=True, blank=True, verbose_name='start_date')),
+ ('end_date', models.DateTimeField(null=True, blank=True, verbose_name='end_date')),
+ ('news', models.ForeignKey(to='com.News', verbose_name='news_date', related_name='dates')),
+ ],
+ ),
+ ]
diff --git a/com/models.py b/com/models.py
index ac8a0b8b..da4d6964 100644
--- a/com/models.py
+++ b/com/models.py
@@ -1,8 +1,13 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
+from django.core.urlresolvers import reverse_lazy, reverse
from django.conf import settings
+from core.models import User
+from club.models import Club
+
class Sith(models.Model):
+ """A one instance class storing all the modifiable infos"""
alert_msg = models.TextField(_("alert message"), default="", blank=True)
info_msg = models.TextField(_("info message"), default="", blank=True)
index_page = models.TextField(_("index page"), default="", blank=True)
@@ -13,3 +18,40 @@ class Sith(models.Model):
def __str__(self):
return "⛩ Sith ⛩"
+NEWS_TYPES = [
+ ('NOTICE', _('Notice')),
+ ('EVENT', _('Event')),
+ ('WEEKLY', _('Weekly')),
+ ('CALL', _('Call')),
+ ]
+
+class News(models.Model):
+ """The news class"""
+ title = models.CharField(_("title"), max_length=64)
+ summary = models.TextField(_("summary"))
+ content = models.TextField(_("content"))
+ type = models.CharField(_("type"), max_length=16, choices=NEWS_TYPES, default="EVENT")
+ club = models.ForeignKey(Club, related_name="news", verbose_name=_("club"))
+ owner = models.ForeignKey(User, related_name="owned_news", verbose_name=_("owner"))
+ is_moderated = models.BooleanField(_("is moderated"), default=False)
+ moderator = models.ForeignKey(User, related_name="moderated_news", verbose_name=_("owner"), null=True)
+
+ def get_absolute_url(self):
+ return reverse('com:news_detail', kwargs={'news_id': self.id})
+
+ def __str__(self):
+ return "%s: %s" % (self.type, self.title)
+
+class NewsDate(models.Model):
+ """
+ A date class, useful for weekly events, or for events that just have no date
+
+ This class allows more flexibilty managing the dates related to a news, particularly when this news is weekly, since
+ we don't have to make copies
+ """
+ news = models.ForeignKey(News, related_name="dates", verbose_name=_("news_date"))
+ start_date = models.DateTimeField(_('start_date'), null=True, blank=True)
+ end_date = models.DateTimeField(_('end_date'), null=True, blank=True)
+
+ def __str__(self):
+ return "%s: %s - %s" % (self.news.title, self.start_date, self.end_date)
diff --git a/com/templates/com/news_admin_list.jinja b/com/templates/com/news_admin_list.jinja
new file mode 100644
index 00000000..fd880f2e
--- /dev/null
+++ b/com/templates/com/news_admin_list.jinja
@@ -0,0 +1,25 @@
+{% extends "core/base.jinja" %}
+
+{% block title %}
+{% trans %}News admin{% endtrans %}
+{% endblock %}
+
+{% block content %}
+
{% trans %}News{% endtrans %}
+
+{% endblock %}
+
+
+
diff --git a/com/templates/com/news_detail.jinja b/com/templates/com/news_detail.jinja
new file mode 100644
index 00000000..e29b32df
--- /dev/null
+++ b/com/templates/com/news_detail.jinja
@@ -0,0 +1,15 @@
+{% extends "core/base.jinja" %}
+
+{% block title %}
+{% trans %}News{% endtrans %} -
+{{ object.title }}
+{% endblock %}
+
+{% block content %}
+ {% trans %}News{% endtrans %}
+ {{ object }}
+ {{ object.dates.all() }}
+{% endblock %}
+
+
+
diff --git a/com/templates/com/news_edit.jinja b/com/templates/com/news_edit.jinja
new file mode 100644
index 00000000..e117d062
--- /dev/null
+++ b/com/templates/com/news_edit.jinja
@@ -0,0 +1,59 @@
+{% extends "core/base.jinja" %}
+
+{% block title %}
+{% if object %}
+{% trans %}Edit news{% endtrans %}
+{% else %}
+{% trans %}Create news{% endtrans %}
+{% endif %}
+{% endblock %}
+
+{% block content %}
+{% if object %}
+{% trans %}Edit news{% endtrans %}
+{% else %}
+{% trans %}Create news{% endtrans %}
+{% endif %}
+
+{% endblock %}
+
+{% block script %}
+ {{ super() }}
+
+{% endblock %}
+
+
diff --git a/com/templates/com/news_list.jinja b/com/templates/com/news_list.jinja
new file mode 100644
index 00000000..6f335b9b
--- /dev/null
+++ b/com/templates/com/news_list.jinja
@@ -0,0 +1,86 @@
+{% extends "core/base.jinja" %}
+
+{% block title %}
+{% trans %}News{% endtrans %}
+{% endblock %}
+
+{% block head %}
+{{ super() }}
+
+{% endblock %}
+
+{% block content %}
+ {% trans %}News{% endtrans %}
+
+ Notice
+ {% for news in object_list.filter(type="NOTICE") %}
+
+ {{ news.title }}
+ {{ news.summary }}
+
+ {% endfor %}
+
+ Calls
+ {% for news in object_list.filter(dates__start_date__lte=timezone.now(), dates__end_date__gte=timezone.now(), type="CALL") %}
+
+ {{ news.title }}
+
+ {{ news.dates.first().start_date|localtime|date(DATETIME_FORMAT) }}
+ {{ news.dates.first().start_date|localtime|time(DATETIME_FORMAT) }} -
+ {{ news.dates.first().end_date|localtime|date(DATETIME_FORMAT) }}
+ {{ news.dates.first().end_date|localtime|time(DATETIME_FORMAT) }}
+
+ {{ news.summary }}
+
+ {% endfor %}
+
+ Events
+ {% for news in object_list.filter(dates__end_date__gte=timezone.now(), type="EVENT") %}
+
+ {{ news.title }}
+
+ {{ news.dates.first().start_date|localtime|date(DATETIME_FORMAT) }}
+ {{ news.dates.first().start_date|localtime|time(DATETIME_FORMAT) }} -
+ {{ news.dates.first().end_date|localtime|date(DATETIME_FORMAT) }}
+ {{ news.dates.first().end_date|localtime|time(DATETIME_FORMAT) }}
+
+ {{ news.club }}
+ {{ news.summary|markdown }}
+
+ {% endfor %}
+
+ Weekly
+ {% for news in object_list.filter(dates__end_date__gte=timezone.now(), type="WEEKLY").distinct() %}
+
+ {% for d in news.dates.all() %}
+
+ {{ news.title }}
+
+ {{ d.start_date|localtime|date(DATETIME_FORMAT) }}
+ {{ d.start_date|localtime|time(DATETIME_FORMAT) }} -
+ {{ d.end_date|localtime|date(DATETIME_FORMAT) }}
+ {{ d.end_date|localtime|time(DATETIME_FORMAT) }}
+
+ {{ news.club }}
+ {{ news.summary|markdown }}
+
+ {% endfor %}
+ {% endfor %}
+{% endblock %}
+
+
+
diff --git a/com/urls.py b/com/urls.py
index 693a2697..abe10d97 100644
--- a/com/urls.py
+++ b/com/urls.py
@@ -3,8 +3,13 @@ from django.conf.urls import url, include
from com.views import *
urlpatterns = [
- url(r'^edit/alert$', AlertMsgEditView.as_view(), name='alert_edit'),
- url(r'^edit/info$', InfoMsgEditView.as_view(), name='info_edit'),
- url(r'^edit/index$', IndexEditView.as_view(), name='index_edit'),
+ url(r'^sith/edit/alert$', AlertMsgEditView.as_view(), name='alert_edit'),
+ url(r'^sith/edit/info$', InfoMsgEditView.as_view(), name='info_edit'),
+ url(r'^sith/edit/index$', IndexEditView.as_view(), name='index_edit'),
+ url(r'^news$', NewsListView.as_view(), name='news_list'),
+ url(r'^news/admin$', NewsAdminListView.as_view(), name='news_admin_list'),
+ url(r'^news/create$', NewsCreateView.as_view(), name='news_new'),
+ url(r'^news/(?P[0-9]+)/edit$', NewsEditView.as_view(), name='news_edit'),
+ url(r'^news/(?P[0-9]+)$', NewsDetailView.as_view(), name='news_detail'),
]
diff --git a/com/views.py b/com/views.py
index 2209d9ca..88f94b1d 100644
--- a/com/views.py
+++ b/com/views.py
@@ -1,12 +1,22 @@
from django.shortcuts import render
-from django.views.generic.edit import UpdateView
+from django.views.generic import ListView, DetailView, RedirectView
+from django.views.generic.edit import UpdateView, CreateView
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse, reverse_lazy
+from django.core.exceptions import ValidationError
+from django.utils import timezone
+from django import forms
-from com.models import Sith
+from datetime import timedelta
+
+from com.models import Sith, News, NewsDate
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin
+from core.views.forms import SelectDateTime
+from club.models import Club
+# Sith object
+
sith = Sith.objects.first
class ComTabsMixin(TabedViewMixin):
@@ -53,3 +63,87 @@ class IndexEditView(ComEditView):
fields = ['index_page']
current_tab = "index"
success_url = reverse_lazy('com:index_edit')
+
+# News
+
+class NewsForm(forms.ModelForm):
+ class Meta:
+ model = News
+ fields = ['type', 'title', 'club', 'summary', 'content', 'owner']
+ widgets = {
+ 'owner': forms.HiddenInput,
+ 'type': forms.RadioSelect,
+ }
+ start_date = forms.DateTimeField(['%Y-%m-%d %H:%M:%S'], label=_("Start date"), widget=SelectDateTime, required=False)
+ end_date = forms.DateTimeField(['%Y-%m-%d %H:%M:%S'], label=_("End date"), widget=SelectDateTime, required=False)
+ until = forms.DateTimeField(['%Y-%m-%d %H:%M:%S'], label=_("Until"), widget=SelectDateTime, required=False)
+
+ def clean(self):
+ self.cleaned_data = super(NewsForm, self).clean()
+ if self.cleaned_data['type'] != "NOTICE":
+ if not self.cleaned_data['start_date']:
+ self.add_error('start_date', ValidationError(_("This field is required.")))
+ if not self.cleaned_data['end_date']:
+ self.add_error('end_date', ValidationError(_("This field is required.")))
+ if self.cleaned_data['type'] == "WEEKLY" and not self.cleaned_data['until']:
+ self.add_error('until', ValidationError(_("This field is required.")))
+ return self.cleaned_data
+
+ def save(self):
+ ret = super(NewsForm, self).save()
+ self.instance.dates.all().delete()
+ if self.instance.type == "EVENT" or self.instance.type == "CALL":
+ NewsDate(start_date=self.cleaned_data['start_date'],
+ end_date=self.cleaned_data['end_date'],
+ news=self.instance).save()
+ elif self.instance.type == "WEEKLY":
+ start_date = self.cleaned_data['start_date']
+ end_date = self.cleaned_data['end_date']
+ while start_date <= self.cleaned_data['until']:
+ NewsDate(start_date=start_date,
+ end_date=end_date,
+ news=self.instance).save()
+ start_date += timedelta(days=7)
+ end_date += timedelta(days=7)
+ return ret
+
+class NewsEditView(UpdateView):
+ model = News
+ form_class = NewsForm
+ template_name = 'com/news_edit.jinja'
+ pk_url_kwarg = 'news_id'
+
+ def get_initial(self):
+ init = {}
+ try:
+ init['start_date'] = self.object.dates.order_by('id').first().start_date.strftime('%Y-%m-%d %H:%M:%S')
+ except: pass
+ try:
+ init['end_date'] = self.object.dates.order_by('id').first().end_date.strftime('%Y-%m-%d %H:%M:%S')
+ except: pass
+ return init
+
+class NewsCreateView(CreateView):
+ model = News
+ form_class = NewsForm
+ template_name = 'com/news_edit.jinja'
+
+ def get_initial(self):
+ init = {'owner': self.request.user}
+ try:
+ init['club'] = Club.objects.filter(id=self.request.GET['club']).first()
+ except: pass
+ return init
+
+class NewsAdminListView(ListView):
+ model = News
+ template_name = 'com/news_admin_list.jinja'
+
+class NewsListView(ListView):
+ model = News
+ template_name = 'com/news_list.jinja'
+
+class NewsDetailView(DetailView):
+ model = News
+ template_name = 'com/news_detail.jinja'
+ pk_url_kwarg = 'news_id'