diff --git a/feedler/feedparser.py b/feedler/feedparser.py index bc39f98..8d7f9e0 100644 --- a/feedler/feedparser.py +++ b/feedler/feedparser.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from datetime import datetime +from guess_language import guess_language def parse(obj, raw, stream): """ @@ -47,14 +48,18 @@ def parse(obj, raw, stream): else: obj.content = '' + # Detect language + obj.lang = guess_language(obj.content) or '' + # Collect tags tags = [] - for tag in obj.raw['tags']: - if 'label' in tag: - label = tag['label'].replace(',','-') - label = label.strip().lower() - if len(label) > 3 and not label in tags: - tags.append(label) - obj.tags = ','.join(tags) + if 'tags' in obj.raw: + for tag in obj.raw['tags']: + if 'label' in tag: + label = tag['label'].replace(',','-') + label = label.strip().lower() + if len(label) > 3 and not label in tags: + tags.append(label) + obj.tags = ','.join(tags) return obj diff --git a/feedler/migrations/0003_entry_lang.py b/feedler/migrations/0003_entry_lang.py new file mode 100644 index 0000000..e27ee89 --- /dev/null +++ b/feedler/migrations/0003_entry_lang.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-09-04 20:33 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('feedler', '0002_feedpage'), + ] + + operations = [ + migrations.AddField( + model_name='entry', + name='lang', + field=models.CharField(blank=True, default='', max_length=2), + ), + ] diff --git a/feedler/models/admin.py b/feedler/models/admin.py index 604b92f..c6b6587 100644 --- a/feedler/models/admin.py +++ b/feedler/models/admin.py @@ -61,5 +61,7 @@ def handle_save_settings(sender, instance, *args, **kwargs): except Entry.DoesNotExist: logger.info("Adding entry '%s'" % eid) entry = Entry() + # Parse the Feedly object entry = feedparser.parse(entry, raw_entry, stream) + # Persist resulting object entry.save() diff --git a/feedler/models/models.py b/feedler/models/models.py index 8777e58..3b77c6c 100644 --- a/feedler/models/models.py +++ b/feedler/models/models.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- from django.db import models +from django.utils import translation +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from wagtail.wagtailcore.models import Page, Orderable from wagtail.wagtailadmin.edit_handlers import FieldPanel @@ -13,6 +15,14 @@ class Stream(models.Model): def __str__(self): return self.title +LANGUAGE_CHOICES = ( + ('de', 'Deutsch'), + ('fr', 'Français'), + ('it', 'Italiano'), + ('en', 'English'), + ('', ' * * * '), +) + class Entry(models.Model): """Implementation of the Entry from the feedly API as generic Django model """ @@ -25,7 +35,7 @@ class Entry(models.Model): author = models.CharField(max_length=255, blank=True) link = models.URLField() visual = models.URLField(blank=True) - + lang = models.CharField(max_length=2, blank=True, default='', choices=LANGUAGE_CHOICES) content = models.TextField() tags = models.TextField(blank=True) @@ -53,14 +63,28 @@ class FeedPage(Page): entries = Entry.objects.filter(stream=self.stream) else: entries = Entry.objects.all() + # Filter out by chosen language + curlang = translation.get_language() + if curlang in ['de']: + entries = entries.exclude(lang='fr') + elif curlang in ['fr']: + entries = entries.exclude(lang='de') # Order by most recent date first - entries = entries.order_by('-published') - return entries[:10] + return entries.order_by('-published')[:72] def get_context(self, request): # Update template context context = super(FeedPage, self).get_context(request) - context['feedentries'] = self.feedentries + + # Wrap with pagination + paginator = Paginator(self.feedentries, 9) + page = request.GET.get('page') + try: + feedentries = paginator.page(page) + except (PageNotAnInteger, EmptyPage): + feedentries = paginator.page(1) + + context['feedentries'] = feedentries return context class Meta: diff --git a/feedler/templates/feedler/feed_page.html b/feedler/templates/feedler/feed_page.html index df5c33e..34ed625 100644 --- a/feedler/templates/feedler/feed_page.html +++ b/feedler/templates/feedler/feed_page.html @@ -19,12 +19,32 @@ +
+ + +
+
    + {% if feedentries.has_previous %} +
  • +
  • + {% endif %} + {% for page_num in feedentries.paginator.page_range %} +
  • + {{ page_num }}
  • + {% endfor %} + {% if feedentries.has_next %} +
  • +
  • + {% endif %} +
+
+
{% for entry in feedentries %} -
+
{% if entry.visual %}
@@ -34,14 +54,13 @@

{{ entry.title|striptags|truncatewords_html:10 }}

- {{ entry.author }}

- {{ entry.content|striptags|truncatewords_html:25 }} + {{ entry.content|striptags|truncatewords_html:25 }} + {{ entry.author }}

- {% empty %} {% endfor %} diff --git a/publichealth/home/migrations/0020_auto_20170904_2233.py b/publichealth/home/migrations/0020_auto_20170904_2233.py new file mode 100644 index 0000000..a96fbe9 --- /dev/null +++ b/publichealth/home/migrations/0020_auto_20170904_2233.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-09-04 20:33 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0019_auto_20170703_1244'), + ] + + operations = [ + migrations.AlterField( + model_name='contactformfield', + name='field_type', + field=models.CharField(choices=[('singleline', 'Single line text'), ('multiline', 'Multi-line text'), ('email', 'Email'), ('number', 'Number'), ('url', 'URL'), ('checkbox', 'Checkbox'), ('checkboxes', 'Checkboxes'), ('dropdown', 'Drop down'), ('multiselect', 'Multiple select'), ('radio', 'Radio buttons'), ('date', 'Date'), ('datetime', 'Date/time')], max_length=16, verbose_name='field type'), + ), + ] diff --git a/publichealth/home/models/models.py b/publichealth/home/models/models.py index 7283987..6fd1eb1 100644 --- a/publichealth/home/models/models.py +++ b/publichealth/home/models/models.py @@ -16,6 +16,8 @@ from wagtail.wagtailimages.edit_handlers import ImageChooserPanel from wagtail.wagtailsearch import index from puput.models import EntryPage, BlogPage +from feedler.models import Entry +from itertools import chain from ..util import TranslatedField @@ -193,11 +195,6 @@ class HomePage(Page): 'infos_fr', ) - # news_home_de = models.ForeignKey( - # 'puput.EntryPage', - # null=True, blank=True, on_delete=models.SET_NULL, - # ) - content_panels = Page.content_panels + [ MultiFieldPanel([ FieldPanel('intro_de', classname="full"), @@ -227,16 +224,29 @@ class HomePage(Page): if not curlang in ['de', 'fr']: curlang = 'de' # Default language parent = BlogPage.objects.filter(slug='news-%s' % curlang) if not parent: return [] - entries = EntryPage.objects.live().descendant_of(parent[0]) + posts = EntryPage.objects.live().descendant_of(parent[0]) # Order by most recent date first - entries = entries.order_by('-date') - return entries[:6] + posts = posts.order_by('-date') + return posts[:3] + + @property + def newsentries(self): + # Get the last few news entries + entries = Entry.objects.all().order_by('-published') + # Filter out by current language + curlang = translation.get_language() + if curlang in ['de']: + entries = entries.exclude(lang='fr') + elif curlang in ['fr']: + entries = entries.exclude(lang='de') + return entries[:3] def get_context(self, request): # Update template context context = super(HomePage, self).get_context(request) context['featured'] = self.featured context['blogentries'] = self.blogentries + context['newsentries'] = self.newsentries return context parent_page_types = ['wagtailcore.Page'] diff --git a/publichealth/home/templates/home/home_page.html b/publichealth/home/templates/home/home_page.html index 4c5e3ff..df0d537 100644 --- a/publichealth/home/templates/home/home_page.html +++ b/publichealth/home/templates/home/home_page.html @@ -13,6 +13,8 @@ {% include 'banner.html' %} +
+ {% include 'news.html' %} @@ -28,4 +30,6 @@ {% include 'infos.html' %} +
+ {% endblock %} diff --git a/publichealth/home/templates/news.html b/publichealth/home/templates/news.html index 91bbb18..c4fe148 100644 --- a/publichealth/home/templates/news.html +++ b/publichealth/home/templates/news.html @@ -1,10 +1,12 @@ {% load wagtailcore_tags wagtailimages_tags puput_tags %} +
{% for entry in blogentries %} -
+ +
{% if entry.header_image %} {% image entry.header_image fill-360x270 %} @@ -18,11 +20,35 @@ {{ entry.body|striptags|truncatewords_html:40 }} {% endif %}

- Mehr erfahren + 🡆
+ {% empty %} + + {% endfor %} + + {% for entry in newsentries %} + +
+ {% if entry.visual %} +
+ + {% else %} +
+ {% endif %} +
+

{{ entry.title|striptags|truncatewords_html:10 }}

+

+ {{ entry.content|striptags|truncatewords_html:25 }} + {{ entry.author }} +

+
+ + +
+
{% empty %} {% endfor %} diff --git a/publichealth/settings/base.py b/publichealth/settings/base.py index 13a16c0..8559d48 100644 --- a/publichealth/settings/base.py +++ b/publichealth/settings/base.py @@ -127,10 +127,15 @@ AUTH_PASSWORD_VALIDATORS = [ }, ] +PASSWORD_REQUIRED_TEMPLATE = 'password.html' # Internationalization # https://docs.djangoproject.com/en/1.8/topics/i18n/ +LANGUAGES = ( + ('de', u'Deutsch'), + ('fr', u'Français'), +) LANGUAGE_CODE = 'de' # default language TIME_ZONE = 'Europe/Zurich' diff --git a/publichealth/static/css/modules/_banner.scss b/publichealth/static/css/modules/_banner.scss index 38b279a..19f4f20 100644 --- a/publichealth/static/css/modules/_banner.scss +++ b/publichealth/static/css/modules/_banner.scss @@ -80,8 +80,11 @@ } } - - +/* Home page banner background */ +body.template-frontpage { + background: $gray-lighter; + .home_page section:nth-child(even) { background: white; } +} /* Page header */ $banner-height: 700px; diff --git a/publichealth/static/css/modules/_news.scss b/publichealth/static/css/modules/_news.scss index b3edf6a..0fd3bd7 100644 --- a/publichealth/static/css/modules/_news.scss +++ b/publichealth/static/css/modules/_news.scss @@ -46,6 +46,12 @@ margin: 10px 0 0 15px; text-align: center; } + em { + display: block; + font-size: 95%; + margin: 0.5em 0; + font-weight: 500; + } } // expand link over the thumbnail @@ -75,6 +81,29 @@ transform: rotateY(0); } } + + .news-entry { + // height: 8em; + .panel { + background: none; + box-shadow: none; + border: none; + } + .panel-body { + // height: 50%; + background-color: #ffffff; + border-radius: 4px; + border-top: 3px solid $brand-primary; + // border: 2px solid rgba(38, 67, 169, 0.8); + *,a { color: black !important; } + } + } + + .partner-news { + text-align: center; + margin-top: 2em; + margin-bottom: 1em; + } } // News detail article diff --git a/publichealth/static/js/main.js b/publichealth/static/js/main.js index 3c51033..982e842 100644 --- a/publichealth/static/js/main.js +++ b/publichealth/static/js/main.js @@ -18,11 +18,11 @@ $(document).ready(function() { nextArrow: '', }); - // Formatting of live news - $('.feedpage-body .panel').each(function() { - var hue = Math.floor(Math.random() * 360); - var pastel = 'hsl(' + hue + ', 100%, 87.5%)'; - $(this).css('border-top', '3px solid ' + pastel); - }); + // Pastel colors on live news + // $('.feedpage-body .panel').each(function() { + // var hue = Math.floor(Math.random() * 360); + // var pastel = 'hsl(' + hue + ', 100%, 87.5%)'; + // $(this).css('border-top', '3px solid ' + pastel); + // }); }); diff --git a/publichealth/templates/404.html b/publichealth/templates/404.html index c6418c4..e38515d 100644 --- a/publichealth/templates/404.html +++ b/publichealth/templates/404.html @@ -1,11 +1,35 @@ {% extends "base.html" %} -{% block title %}404 - Page not found{% endblock %} +{% block title %}404 - Seite nicht gefunden{% endblock %} {% block body_class %}template-404{% endblock %} {% block content %} -

Page not found

+
+
-

Sorry, this page could not be found.

+

Nicht gefunden/Introuvable

+ +
+ +
+ + +
+ +

+
Diese Seite konnte nicht gefunden werden. Möchten Sie eine Suche starten? +
Désolé, cette page est introuvable. Voulez-vous faire une recherche sur le site? +
Sorry, this page could not be found. Would you like to do a search of the site? +

+ +
+
+
+ + {% endblock %} diff --git a/publichealth/templates/500.html b/publichealth/templates/500.html index 3542ce4..c186fc9 100644 --- a/publichealth/templates/500.html +++ b/publichealth/templates/500.html @@ -10,5 +10,7 @@

Internal server error

Sorry, there seems to be an error. Please try again soon.

+ +

In case of persistent issues, write to info@datalets.ch

diff --git a/publichealth/templates/password.html b/publichealth/templates/password.html new file mode 100644 index 0000000..9c49603 --- /dev/null +++ b/publichealth/templates/password.html @@ -0,0 +1,39 @@ +{% extends "base.html" %} + +{% block title %}Password Required{% endblock %} + +{% block body_class %}password-required{% endblock %} + +{% block content %} +
+
+ +

Password requis/erforderlich

+ +
+
+ {% csrf_token %} + + {{ form.non_field_errors }} + +
+ {{ form.password.errors }} + {{ form.password }} +
+ + {% for field in form.hidden_fields %} + {{ field }} + {% endfor %} + +
+ +

+
Sie benötigen ein Passwort, um auf diese Seite zuzugreifen. +
Vous avez besoin d'un mot de passe pour accéder à cette page. +
You need a password to access this page. +

+ +
+
+
+{% endblock %} diff --git a/requirements.txt b/requirements.txt index 2fb4de8..69283b0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,15 +1,16 @@ -# Updated: 30.5.2017 +# Updated: 4.9.2017 # Core -wagtail==1.11 -Django==1.11.3 +wagtail==1.12.1 +Django==1.11.4 # Database -psycopg2==2.7.1 +psycopg2==2.7.3.1 dj-database-url==0.4.2 -# Addons -puput==0.8 +# Content +puput==0.9 +guess-language-spirit==0.5.3 # Search elasticsearch>=2.0.0,<3.0.0 @@ -20,7 +21,7 @@ django-redis==4.8.0 # Frontend django-libsass==0.7 libsass==0.13.2 -Pillow==4.2.0 +Pillow==4.2.1 # Development tools stellar==0.4.3 @@ -29,4 +30,4 @@ stellar==0.4.3 gunicorn==19.7.1 whitenoise==3.3.0 ConcurrentLogHandler==0.9.1 -django-anymail==0.10 +django-anymail==0.11.1