combo/combo/apps/pwa/models.py

143 lines
5.4 KiB
Python

# combo - content management system
# Copyright (C) 2015-2018 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import base64
import json
from django.conf import settings
from django.core import serializers
from django.core.files.storage import default_storage
from django.db import models
from django.utils import six
from django.utils.encoding import force_text, force_bytes
from django.utils.six import BytesIO
from django.utils.translation import ugettext_lazy as _
from jsonfield import JSONField
from combo.data.fields import RichTextField
from combo import utils
class PwaSettings(models.Model):
offline_text = RichTextField(
verbose_name=_('Offline Information Text'),
default=_('You are currently offline.'),
config_name='small')
offline_retry_button = models.BooleanField(_('Include Retry Button'), default=True)
last_update_timestamp = models.DateTimeField(auto_now=True)
@classmethod
def singleton(cls):
return cls.objects.first() or cls()
@classmethod
def export_for_json(cls):
obj = cls.singleton()
if not obj.id:
return {}
serialized_settings = json.loads(serializers.serialize('json', [obj]))
return serialized_settings[0].get('fields')
@classmethod
def load_serialized_settings(cls, json_settings):
if not json_settings:
return
obj = cls.singleton()
for attr in json_settings:
setattr(obj, attr, json_settings[attr])
obj.save()
class PwaNavigationEntry(models.Model):
label = models.CharField(verbose_name=_('Label'), max_length=150, blank=True)
url = models.CharField(verbose_name=_('External URL'), max_length=200, blank=True)
link_page = models.ForeignKey('data.Page', blank=True,
null=True, verbose_name=_('Internal link'))
icon = models.FileField(_('Icon'), upload_to='pwa', blank=True, null=True)
extra_css_class = models.CharField(_('Extra classes for CSS styling'), max_length=100, blank=True)
order = models.PositiveIntegerField()
notification_count = models.BooleanField(
verbose_name=_('Display notification count'),
default=False)
use_user_name_as_label = models.BooleanField(
verbose_name=_('Use user name as label'),
default=False)
class Meta:
ordering = ('order',)
def get_label(self):
return self.label or self.link_page.title
def get_url(self):
if self.link_page:
return self.link_page.get_online_url()
else:
return utils.get_templated_url(self.url)
def css_class_names(self):
css_class_names = self.extra_css_class or ''
if self.link_page:
css_class_names += ' page-%s' % self.link_page.slug
return css_class_names
@classmethod
def export_all_for_json(cls):
return [x.get_as_serialized_object() for x in cls.objects.all()]
def get_as_serialized_object(self):
serialized_entry = json.loads(serializers.serialize('json', [self],
use_natural_foreign_keys=True, use_natural_primary_keys=True))[0]
if self.icon:
encode = base64.encodestring if six.PY2 else base64.encodebytes
serialized_entry['icon:base64'] = force_text(encode(self.icon.read()))
del serialized_entry['model']
del serialized_entry['pk']
return serialized_entry
@classmethod
def load_serialized_objects(cls, json_site):
for json_entry in json_site:
cls.load_serialized_object(json_entry)
@classmethod
def load_serialized_object(cls, json_entry):
json_entry['model'] = 'pwa.pwanavigationentry'
# deserialize once to get link_page by natural key
fake_entry = [x for x in serializers.deserialize('json', json.dumps([json_entry]))][0]
entry, created = cls.objects.get_or_create(
label=json_entry['fields']['label'],
url=json_entry['fields']['url'],
link_page=fake_entry.object.link_page,
defaults={'order': 0})
json_entry['pk'] = entry.id
entry = [x for x in serializers.deserialize('json', json.dumps([json_entry]))][0]
entry.save()
if json_entry.get('icon:base64'):
decode = base64.decodestring if six.PY2 else base64.decodebytes
decoded_icon = decode(force_bytes(json_entry['icon:base64']))
if not default_storage.exists(entry.object.icon.name) or entry.object.icon.read() != decoded_icon:
# save new file
entry.object.icon.save(entry.object.icon.name, BytesIO(decoded_icon))
class PushSubscription(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
subscription_info = JSONField()
creation_timestamp = models.DateTimeField(auto_now_add=True)