From 08d1c7bfaca8ab66a42b98c12a15d58f4dae94c3 Mon Sep 17 00:00:00 2001 From: bkfox Date: Mon, 1 Jul 2019 05:03:43 +0200 Subject: [PATCH] add missing files --- aircox_web/assets/styles.scss | 24 ++++++++++++++++ aircox_web/fields.py | 32 +++++++++++++++++++++ aircox_web/plugins/__init__.py | 51 +++++++++++++++++++++++++++++++++ aircox_web/plugins/image.py | 47 ++++++++++++++++++++++++++++++ aircox_web/plugins/timetable.py | 37 ++++++++++++++++++++++++ 5 files changed, 191 insertions(+) create mode 100644 aircox_web/assets/styles.scss create mode 100644 aircox_web/fields.py create mode 100644 aircox_web/plugins/__init__.py create mode 100644 aircox_web/plugins/image.py create mode 100644 aircox_web/plugins/timetable.py diff --git a/aircox_web/assets/styles.scss b/aircox_web/assets/styles.scss new file mode 100644 index 0000000..b3a8e42 --- /dev/null +++ b/aircox_web/assets/styles.scss @@ -0,0 +1,24 @@ +@charset "utf-8"; +@import "~bulma/sass/utilities/_all.sass"; + +$body-background-color: $light; + +@import "~bulma/bulma"; + +.navbar { + margin-bottom: 1em; +} + +.navbar.has-shadow { + box-shadow: 0em 0.1em 0.5em rgba(0,0,0,0.1); +} + +.navbar-brand img { + min-height: 6em; +} + +.navbar-menu .navbar-item:not(:last-child) { + border-right: 1px $grey solid; +} + + diff --git a/aircox_web/fields.py b/aircox_web/fields.py new file mode 100644 index 0000000..6212d5e --- /dev/null +++ b/aircox_web/fields.py @@ -0,0 +1,32 @@ +from django.db import models + + +class BaseMinMaxField: + def __init__(self, verbose_name=None, name=None, min=None, max=None, + **kwargs): + super().__init__(verbose_name, name, **kwargs) + self.min_value = min + self.max_value = max + + def minmax(self, value): + return min(self.max_value, max(self.min_value, value)) + + def to_python(self, value): + return self.minmax(super().to_python(value)) + + def get_prep_value(self, value): + return super().get_prep_value(self.minmax(value)) + + +class MinMaxField(BaseMinMaxField, models.IntegerField): + pass + +class SmallMinMaxField(BaseMinMaxField, models.SmallIntegerField): + pass + +class PositiveMinMaxField(BaseMinMaxField, models.PositiveIntegerField): + pass + +class PositiveSmallMinMaxField(BaseMinMaxField, models.PositiveSmallIntegerField): + pass + diff --git a/aircox_web/plugins/__init__.py b/aircox_web/plugins/__init__.py new file mode 100644 index 0000000..9f6dd21 --- /dev/null +++ b/aircox_web/plugins/__init__.py @@ -0,0 +1,51 @@ +from django.db import models +from django.utils.translation import ugettext_lazy as _ +from django.utils.html import escape, format_html, mark_safe +from django.urls import reverse + +from .image import ImageBase, Image +from .richtext import RichText + + +__all__ = ['ImageBase', 'Image', 'RichText'] + + +class Link(models.Model): + url = models.CharField( + _('url'), max_length=128, null=True, blank=True, + ) + page = models.ForeignKey( + 'Page', models.SET_NULL, null=True, blank=True, + verbose_name=_('Link to a page') + ) + text = models.CharField(_('text'), max_length=64, null=True, blank=True) + info = models.CharField(_('info'), max_length=128, null=True, blank=True, + help_text=_('link description displayed as tooltip')) + blank = models.BooleanField(_('new window'), default=False, + help_text=_('open in a new window')) + css_class="" + + def get_url(self): + if self.page: + return self.page.path #reverse('page', args=[self.page.path]) + return self.url or '' + + def render(self): + # FIXME: quote + return format_html( + '{}', + self.get_url(), escape(self.info), + ' class=' + escape(self.css_class) + '' + if self.css_class else '', + self.text or (self.page and self.page.title) or '', + ) + + class Meta: + abstract = True + + +class Search(models.Model): + class Meta: + abstract = True + + diff --git a/aircox_web/plugins/image.py b/aircox_web/plugins/image.py new file mode 100644 index 0000000..51b49b4 --- /dev/null +++ b/aircox_web/plugins/image.py @@ -0,0 +1,47 @@ +from django.db import models +from django.templatetags.static import static +from django.utils.translation import ugettext_lazy as _ +from django.utils.html import format_html, mark_safe + +from easy_thumbnails.files import get_thumbnailer +from filer.fields.image import FilerImageField + +__all__ = ['ImageBase', 'Image'] + + +class ImageBase(models.Model): + image = FilerImageField( + on_delete=models.CASCADE, + verbose_name=_('image'), + ) + width = None + height = None + crop = False + + class Meta: + abstract = True + + @property + def thumbnail(self): + if self.width == None and self.height == None: + return self.image + opts = {} + if self.crop: + opts['crop'] = 'smart' + opts['size'] = (self.width or 0, self.height or 0) + thumbnailer = get_thumbnailer(self.image) + return thumbnailer.get_thumbnail(opts) + + def render(self): + return format_html('', self.thumbnail.url) + + +class Image(ImageBase): + width = models.PositiveSmallIntegerField(blank=True,null=True) + height = models.PositiveSmallIntegerField(blank=True,null=True) + crop = models.BooleanField(default=False) + + class Meta: + abstract = True + + diff --git a/aircox_web/plugins/timetable.py b/aircox_web/plugins/timetable.py new file mode 100644 index 0000000..8875b33 --- /dev/null +++ b/aircox_web/plugins/timetable.py @@ -0,0 +1,37 @@ +import datetime + +from django.db import models +from django.templatetags.static import static +from django.utils.translation import ugettext_lazy as _ + +from aircox import models as aircox +from aircox_web.fields import PositiveSmallMinMaxField + + +class Timetable(models.Model): + station = models.ForeignKey( + aircox.Station, models.CASCADE, verbose_name=_('station'), + ) + days_before = models.PositiveSmallMinMaxField( + _('days before'), min=0, max=6, + help_text=_('Count of days displayed current date'), + ) + days_after = models.PositiveSmallMinMaxField( + _('days after'), min=0, max=6, + help_text=_('Count of days displayed current date'), + ) + + def get_queryset(self, date=None): + date = date if date is not None else datetime.date.today() + qs = aircox.Diffusion.objects.station(self.station) + if self.days_before is None and self.days_after is None: + return qs.at(date) + + start = date - datetime.timedelta(days=self.days_before) \ + if self.days_before else date + stop = date + datetime.timedelta(days=self.days_after) \ + if self.days_after else date + return aircox.Diffusion.objects.station(self.station) \ + .after(start).before(stop) + +