"""File containing Infoscreen models.""" from datetime import datetime from django.db import models from django import forms from django.utils import timezone from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.utils.translation import gettext as _ class InfoItem(models.Model): """Abstract model representing single Infoscreen item.""" class __meta__: abstract = True id = models.AutoField(primary_key=True) name = models.CharField(max_length=255) # expire_date = None means never expiring item expire_date = models.DateTimeField(blank=True, null=True) display_name = "Default item" def get_template_url(self): """Get infoscreen template url.""" raise NotImplementedError("inheriting classes must implement get_template_url") @staticmethod def get_create_template_url(): """Get create infoscreen template url command.""" raise NotImplementedError( "inheriting classes must implement get_create_template_url" ) @classmethod def create_from_dict(cls, d): """Convert given dict to model.""" item = cls() item.update_from_dict(d) return item def update_from_dict(self, d): """Update model based on given dict.""" try: expire_date = d.pop("expire_date", None) self.expire_date = datetime.strptime(expire_date, "%Y-%m-%d %H:%M:%S") except: pass dmap = { "name": "name", } for k, v in d.items(): try: self.__setattr__(dmap[k], v) except KeyError: pass self.save() def get_dict(self): """Convert django model to dict and return it.""" return { "id": self.id, "name": self.name, "item_type": ContentType.objects.get_for_model(self).id, "template_url": self.get_template_url(), "display_name": self.display_name, "create_template_url": self.get_create_template_url(), "options": {}, } def delete(self): """Delete infoinstance object.""" # since generic foreign keys suck, delete info # items pointing here manually InfoInstance.objects.filter( item_id=self.id, item_type=ContentType.objects.get_for_model(self) ).delete() super().delete() @classmethod def get_subclasses(cls): """Get item subclasses.""" for subclass in cls.__subclasses__(): yield from subclass.get_subclasses() yield subclass def __str__(self): """Return class name.""" return self.name class ABBInfoItem(InfoItem): """Class for ABB Infoscreen item.""" display_name = _("ABB jobs") def get_template_url(self): """Return ABB infoitem template url.""" return "/static/infoscreen/html/abb.html" @staticmethod def get_create_template_url(): """Call create ABB infoitem template url command.""" return "/static/infoscreen/html/abb_create.html" class ApyInfoItem(InfoItem): """Class for APY Infoscreen item.""" display_name = _("APY Item") def get_template_url(self): """Return APY infoitem template url.""" return "/static/infoscreen/html/apy.html" @staticmethod def get_create_template_url(): """Call create APY infoitem template url command.""" return "/static/infoscreen/html/apy_create.html" class ExternalWebsiteInfoItem(InfoItem): """Class for external website info item.""" display_name = _("External website") url = models.URLField() def get_template_url(self): """Return external website infoitem template url.""" return "/static/infoscreen/html/external_website.html?url={}".format(self.name) @staticmethod def get_create_template_url(): """Call create external website infoitem template url command.""" return "/static/infoscreen/html/external_website_create.html" def get_dict(self): """Convert django model to dict and return it.""" d = super().get_dict() d["options"] = {"url": self.url} return d @classmethod def create_from_dict(cls, d): """Convert given dict to model.""" item = cls() item.update_from_dict(d) return item def get_list(self): """Return list containing infoitem data.""" return { "id": self.id, "name": self.name, "url": self.url, } def update_from_dict(self, d): """Update model based on given dict.""" try: expire_date = d.pop("expire_date", None) self.expire_date = datetime.strptime(expire_date, "%Y-%m-%d %H:%M:%S") except: pass dmap = { "name": "name", "url": "url", } for k, v in d.items(): try: self.__setattr__(dmap[k], v) except KeyError: pass self.save() class SossoInfoItem(InfoItem): """Class for Sosso Infoscreen item.""" display_name = _("Sössö articles") def get_template_url(self): """Return Sosso infoitem template url.""" return "/static/infoscreen/html/sosso.html" @staticmethod def get_create_template_url(): """Call create Sosso infoitem template url command.""" return "/static/infoscreen/html/sosso_create.html" class LunchItem(InfoItem): """Class for Lunch Infoscreen item.""" display_name = _("Today's lunch") def get_template_url(self): return "/static/infoscreen/html/lunch.html" @staticmethod def get_create_template_url(): return "/static/infoscreen/html/lunch_create.html" class EventInfoItem(InfoItem): """Class for Event Infoscreen item.""" display_name = _("Events") def get_template_url(self): """Return Event infoitem template url.""" return "/static/infoscreen/html/events.html" @staticmethod def get_create_template_url(): """Call create Event infoitem template url command.""" return "/static/infoscreen/html/events_create.html" class ImageInfoItem(InfoItem): """Class for Image Infoscreen item.""" display_name = _("Image") img = models.ImageField(upload_to="infoimages/") def get_template_url(self): """Return Image infoitem template url.""" # get param to avoid angular from optimizing same template # with different options return "/static/infoscreen/html/generic_image.html?img={}".format(self.name) @staticmethod def get_create_template_url(): """Call create Image infoitem template url command.""" return "/static/infoscreen/html/generic_image_create.html" def get_dict(self): """Convert django model to dict and return it.""" d = super().get_dict() d["options"] = {"img": self.img.url} return d class VideoInfoItem(InfoItem): """Class for Video Infoscreen item.""" display_name = "Video" video = models.FileField(upload_to="infovideos/") def get_template_url(self): """Return Video infoitem template url.""" return "/static/infoscreen/html/generic_video.html?video={}".format(self.name) @staticmethod def get_create_template_url(): """Call create Video infoitem template url command.""" return "/static/infoscreen/html/generic_video_create.html" def get_dict(self): """Convert django model to dict and return it.""" d = super().get_dict() d["options"] = {"video": self.video.url} return d class ExternalImageInfoItem(InfoItem): """Class for External Image Infoscreen item.""" display_name = _("External image") url = models.URLField() def get_template_url(self): """Return External Image infoitem template url.""" return "/static/infoscreen/html/generic_image.html?img={}".format(self.name) @staticmethod def get_create_template_url(): """Call create External Image infoitem template url command.""" return "/static/infoscreen/html/generic_external_image_create.html" def get_dict(self): """Convert django model to dict and return it.""" d = super().get_dict() d["options"] = {"img": self.url} return d @classmethod def create_from_dict(cls, d): """Convert given dict to model.""" item = cls() item.update_from_dict(d) return item def update_from_dict(self, d): """Update model based on given dict.""" try: expire_date = d.pop("expire_date", None) self.expire_date = datetime.strptime(expire_date, "%Y-%m-%d %H:%M:%S") except: pass dmap = { "name": "name", "url": "url", } for k, v in d.items(): try: self.__setattr__(dmap[k], v) except KeyError: pass self.save() class InfoInstance(models.Model): """Class for Info instance in Infoscreen.""" id = models.AutoField(primary_key=True) rotation = models.ForeignKey( "Rotation", related_name="instances", on_delete=models.CASCADE ) duration = models.FloatField(default=15.0) # seconds # generic relation to some kind of InfoItem item_id = models.PositiveIntegerField() item_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) item = GenericForeignKey("item_type", "item_id") @classmethod def create_from_dict(cls, d): """Convert given dict to model.""" try: rotation = Rotation.objects.get(pk=int(d["rotation_id"])) ct = ContentType.objects.get_for_id(int(d["item_type"])) item = ct.get_object_for_this_type(pk=int(d["item_id"])) duration = float(d["duration"]) except: raise RuntimeError("invalid parameters supplied supplied") try: return cls.objects.create(rotation=rotation, item=item, duration=duration) except: raise RuntimeError("error while adding instance to db") def get_dict(self): """Convert django model to dict and return it.""" return { "id": self.id, "item": self.item.get_dict(), "duration": self.duration, } def __str__(self): """Return model name.""" return "{}: {} ({}s)".format(self.rotation.name, self.item.name, self.duration) class Rotation(models.Model): """Class for rotation model.""" id = models.AutoField(primary_key=True) name = models.CharField(max_length=255) def get_dict(self): """Convert django model to dict and return it.""" # exclude expired items from rotation (note: using tricky syntax # to avoid excluding items with no expire_date) now = timezone.now() instances = self.instances.all() filtered = filter(lambda i: (i.item.expire_date or now) >= now, list(instances)) instance_list = list(map(lambda i: i.get_dict(), filtered)) return { "id": self.id, "name": self.name, "instances": instance_list, } def get_list(self): """Return list containing infoitem data.""" return { "id": self.id, "name": self.name, } def __str__(self): """Return model name.""" return self.name class ImageUploadForm(forms.Form): """Form used to handle imageuploads to infoscreen app.""" id = models.AutoField(primary_key=True) name = forms.CharField() image = forms.ImageField() class UploadFileForm(forms.Form): """Form used for uploading file.""" id = models.AutoField(primary_key=True) name = forms.CharField() video = forms.FileField()