Create announcements app

parent 0f324b06
from django.contrib import admin
from utils.translation import TranslatedModelAdmin
from .models import Announcement
@admin.register(Announcement)
class AnnouncementAdmin(TranslatedModelAdmin):
list_display = ('content', 'since', 'until', 'visible')
def visible(self, obj):
return obj.is_visible
visible.boolean = True
from django.apps import AppConfig
class AnnouncementsConfig(AppConfig):
name = 'announcements'
from .models import Announcement
def announcements(request):
closed_announcements = request.session.get('closed_announcements', [])
announcements = [a for a in Announcement.objects.all()
if a.is_visible and a.pk not in closed_announcements]
return {'announcements': announcements}
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-01-30 20:47
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Announcement',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('since', models.DateField(default=django.utils.timezone.now, help_text='Hide this announcement before this time.', verbose_name='Display since')),
('until', models.DateField(blank=True, help_text='Hide this announcement after this time.', null=True, verbose_name='Display until')),
('icon', models.CharField(default='bullhorn', help_text='Font Awesome abbreviation for icon to use.', max_length=150, verbose_name='Font Awesome icon')),
('closeable', models.BooleanField(default=True)),
('content_en', models.CharField(help_text='The content of the announcement; what text to display.', max_length=500, verbose_name='Content (EN)')),
('content_nl', models.CharField(help_text='The content of the announcement; what text to display.', max_length=500, verbose_name='Content (NL)')),
],
options={
'ordering': ('-since',),
},
),
]
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from utils.translation import ModelTranslateMeta, MultilingualField
class Announcement(models.Model, metaclass=ModelTranslateMeta):
content = MultilingualField(
models.CharField,
verbose_name=_('Content'),
help_text=_('The content of the announcement; what text to display.'),
blank=False,
max_length=500,
)
since = models.DateField(
verbose_name=_('Display since'),
help_text=_("Hide this announcement before this time."),
default=timezone.now,
)
until = models.DateField(
verbose_name=_('Display until'),
help_text=_("Hide this announcement after this time."),
blank=True,
null=True,
)
icon = models.CharField(
verbose_name=_('Font Awesome icon'),
help_text=_("Font Awesome abbreviation for icon to use."),
max_length=150,
default='bullhorn',
)
closeable = models.BooleanField(
default=True
)
class Meta:
ordering = ('-since', )
def __str__(self):
return self.content
@property
def is_visible(self):
"""Is this announcement currently visible"""
return ((self.until is None or self.until > timezone.now().date()) and
(self.since is None or self.since <= timezone.now().date()))
.announcement {
background: #E62272;
color: #FFFFFF;
font-weight: bold;
text-align:center;
padding: 10px;
position: relative;
.close {
color: #FFFFFF;
}
}
(function() {
$('.announcement .close').click(function() {
$(this).parent().remove();
$.ajax({
// make sure this matches the url defined in announcements/urls.py
url: "/announcements/close-announcement",
type: "POST",
beforeSend: function(xhr){
xhr.setRequestHeader("X-CSRFToken", Cookies.get('csrftoken'));
},
data: {id: $(this).data('announcement-id')},
})
});
})();
{% for announcement in announcements %}
<div class='announcement'>
<i class="fa fa-{{ announcement.icon }}"></i> {{ announcement.content }}
{% if announcement.closeable %}
<button type="button" class="close" aria-label="Close" data-announcement-id="{{ announcement.pk }}">
<span aria-hidden="true">&times;</span>
</button>
{% endif %}
</div>
{% endfor %}
from django.conf.urls import url
from . import views
app_name = "announcements"
urlpatterns = [
url(r'^close-announcement$', views.close_announcement, name='close-announcement')
]
from django.http import HttpResponse
def close_announcement(request):
id = int(request.POST['id'])
# if we do not have a list of closed announcements yet:
if 'closed_announcements' not in request.session:
request.session['closed_announcements'] = [] # cannot use sets here :(
# duplicates should never occur anyway, but it does not hurt to check
if id not in request.session['closed_announcements']:
request.session['closed_announcements'].append(id)
# needs to be explicitly marked since we only edited an existing object
request.session.modified = True
return HttpResponse(status=204) # 204: No Content
......@@ -70,6 +70,7 @@ INSTALLED_APPS = [
'newsletters',
'education',
'thaliapp',
'announcements',
]
MIDDLEWARE = [
......@@ -102,6 +103,7 @@ TEMPLATES = [
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'partners.context_processors.showcased_partners',
'announcements.context_processors.announcements',
],
},
},
......
/*! js-cookie v2.1.3 | MIT */
!function(a){var b=!1;if("function"==typeof define&&define.amd&&(define(a),b=!0),"object"==typeof exports&&(module.exports=a(),b=!0),!b){var c=window.Cookies,d=window.Cookies=a();d.noConflict=function(){return window.Cookies=c,d}}}(function(){function a(){for(var a=0,b={};a<arguments.length;a++){var c=arguments[a];for(var d in c)b[d]=c[d]}return b}function b(c){function d(b,e,f){var g;if("undefined"!=typeof document){if(arguments.length>1){if(f=a({path:"/"},d.defaults,f),"number"==typeof f.expires){var h=new Date;h.setMilliseconds(h.getMilliseconds()+864e5*f.expires),f.expires=h}try{g=JSON.stringify(e),/^[\{\[]/.test(g)&&(e=g)}catch(i){}return e=c.write?c.write(e,b):encodeURIComponent(e+"").replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g,decodeURIComponent),b=encodeURIComponent(b+""),b=b.replace(/%(23|24|26|2B|5E|60|7C)/g,decodeURIComponent),b=b.replace(/[\(\)]/g,escape),document.cookie=b+"="+e+(f.expires?"; expires="+f.expires.toUTCString():"")+(f.path?"; path="+f.path:"")+(f.domain?"; domain="+f.domain:"")+(f.secure?"; secure":"")}b||(g={});for(var j=document.cookie?document.cookie.split("; "):[],k=/(%[0-9A-Z]{2})+/g,l=0;l<j.length;l++){var m=j[l].split("="),n=m.slice(1).join("=");'"'===n.charAt(0)&&(n=n.slice(1,-1));try{var o=m[0].replace(k,decodeURIComponent);if(n=c.read?c.read(n,o):c(n,o)||n.replace(k,decodeURIComponent),this.json)try{n=JSON.parse(n)}catch(i){}if(b===o){g=n;break}b||(g[o]=n)}catch(i){}}return g}}return d.set=d,d.get=function(a){return d.call(d,a)},d.getJSON=function(){return d.apply({json:!0},[].slice.call(arguments))},d.defaults={},d.remove=function(b,c){d(b,"",a(c,{expires:-1}))},d.withConverter=b,d}return b(function(){})});
\ No newline at end of file
......@@ -35,6 +35,7 @@
<link href="{% static "css/jquery.fancybox.css" %}" rel="stylesheet" type="text/css">
<link href="{% static "css/style.scss" %}" rel="stylesheet" type="text/x-scss">
<link href="{% static "announcements/css/style.scss" %}" rel="stylesheet" type="text/x-scss">
{% endcompress %}{% endblock %}
<!-- js head -->
......@@ -55,6 +56,9 @@
<!-- #wrapper -->
<div class="thimbus-page">
<!-- #announcements -->
{% include "announcements/announcement.html" with announcements=announcements %}
<!-- #header -->
<div id="header" class="wrapper">
......@@ -191,11 +195,13 @@
<script type="text/javascript" src="{% static "plugins/jquery.easing.1.3.js" %}"></script>
<script type="text/javascript" src="{% static "plugins/jquery.isotope.min.js" %}"></script>
<script type="text/javascript" src="{% static "plugins/magnific-popup/jquery.magnific-popup.min.js" %}"></script>
<script type="text/javascript" src="{% static "plugins/js.cookie-2.1.3.min.js" %}"></script>
{% endblock %}
{% block js_footer %}
<script type="text/javascript" src="{% static "js/footer.js" %}"></script>
<script type="text/javascript" src="{% static "js/bootstrap-dropdown.js" %}"></script>
<script type="text/javascript" src="{% static "announcements/js/announcements.js" %}"></script>
{% endblock %}
</body>
<!-- /body -->
......
......@@ -94,6 +94,7 @@ urlpatterns = [
url(r'wikilogin', views.wiki_login),
])),
url(r'^education/', include('education.urls')),
url(r'^announcements/', include('announcements.urls')),
# Default login helpers
url(r'^', include('django.contrib.auth.urls')),
url(r'^i18n/', include('django.conf.urls.i18n')),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment