momo: add new application to generate manifest/assets files for momo (#8083)

This commit is contained in:
Frédéric Péters 2015-08-21 16:15:01 +02:00
parent b10e335016
commit 2c1208c8f5
5 changed files with 228 additions and 0 deletions

View File

@ -0,0 +1,32 @@
# combo - content management system
# Copyright (C) 2015 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 django.apps
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
class AppConfig(django.apps.AppConfig):
name = 'combo.apps.momo'
def get_before_urls(self):
from . import urls
return urls.urlpatterns
def get_extra_manager_actions(self):
return [{'href': reverse('momo-manager-homepage'),
'text': _('Mobile Application')}]
default_app_config = 'combo.apps.momo.AppConfig'

View File

@ -0,0 +1,11 @@
{% extends "combo/manager_base.html" %}
{% load i18n %}
{% block appbar %}
<h2>{% trans 'Mobile Application' %}</h2>
{% endblock %}
{% block breadcrumb %}
{{ block.super }}
<a href="{% url 'momo-manager-homepage' %}">{% trans 'Mobile Application' %}</a>
{% endblock %}

View File

@ -0,0 +1,12 @@
{% extends "momo/manager_base.html" %}
{% load i18n %}
{% block appbar %}
<h2>{% trans 'Mobile Application' %}</h2>
{% endblock %}
{% block content %}
<a href="{% url 'momo-manager-generate' %}">{% trans 'Generate Content Update' %}</a>
{% endblock %}

31
combo/apps/momo/urls.py Normal file
View File

@ -0,0 +1,31 @@
# combo - content management system
# Copyright (C) 2015 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/>.
from django.conf.urls import patterns, url, include
from combo.urls_utils import decorated_includes, manager_required
from .views import MomoManagerView, generate
momo_manager_urls = patterns('momo.manager_views',
url('^$', MomoManagerView.as_view(), name='momo-manager-homepage'),
url('^generate/$', generate, name='momo-manager-generate'),
)
urlpatterns = patterns('',
url(r'^manage/momo/', decorated_includes(manager_required,
include(momo_manager_urls))),
)

142
combo/apps/momo/views.py Normal file
View File

@ -0,0 +1,142 @@
# combo - content management system
# Copyright (C) 2015 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 json
import shutil
import os
import zipfile
from django.conf import settings
from django.contrib import messages
from django.core.files.storage import default_storage
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.template import RequestContext
from django.utils.translation import ugettext as _
from django.views.generic import TemplateView
import ckeditor
from combo.data.models import CellBase, Page
class MomoManagerView(TemplateView):
template_name = 'momo/manager_home.html'
def get_page_dict(request, page):
cells = CellBase.get_cells(page_id=page.id)
page_dict = {
'title': page.title,
}
if cells:
context = RequestContext(request, {
'page': page,
'page_cells': cells,
'request': request,
'site_base': request.build_absolute_uri('/')[:-1],
})
page_dict['content'] = '\n'.join([cell.render(context) for cell in cells])
if page.redirect_url:
page_dict['external'] = True
page_dict['url'] = page.redirect_url
if hasattr(page, '_children'):
children = page._children
else:
children = page.get_children()
if children:
page_dict['pages'] = []
for child in children:
page_dict['pages'].append(get_page_dict(request, child))
return page_dict
def generate(request, **kwargs):
level0_pages = Page.objects.filter(parent=None)
# the application hierarchy is structured that way:
# - the home screen is the homepage
# - the application pages are created from the homepage siblings and their
# children
# - the application menu is created from direct children of the homepage
children = []
for page in level0_pages:
if page.slug == 'index':
homepage = page
else:
children.append(page)
homepage._children = children
manifest = get_page_dict(request, homepage)
# get real homepage children to construct the application menu
menu_children = homepage.get_children()
manifest['menu'] = []
manifest['_pages'] = []
for menu_child in menu_children:
menu_id = 'menu-%s-%s' % (menu_child.id, menu_child.slug)
manifest['menu'].append(menu_id)
manifest['_pages'].append({
'title': menu_child.title,
'external': True,
'url': menu_child.redirect_url,
'id': menu_id,
})
manifest['meta'] = {
'title': homepage.title,
'icon': 'icon.png',
'contact': 'info@entrouvert.com',
'updateFreq': 14400,
'manifestUrl': request.build_absolute_uri(default_storage.url('index.json')),
'assetsUrl': request.build_absolute_uri(default_storage.url('assets.zip')),
}
fp = default_storage.open('index.json', mode='w')
json.dump(manifest, fp, indent=2)
fp.close()
# assets.zip
if default_storage.exists('assets.zip'):
zf = zipfile.ZipFile(default_storage.open('assets.zip'))
existing_files = set([x for x in zf.namelist() if x[0] != '/' and x[-1] != '/'])
zf.close()
else:
existing_files = set([])
ckeditor_filenames = set(ckeditor.views.get_image_files())
media_ckeditor_filenames = set(['media/' + x for x in ckeditor_filenames])
if not media_ckeditor_filenames.issubset(existing_files) or (
default_storage.modified_time('assets-base.zip') > default_storage.modified_time('assets.zip')):
# if there are new files, or if the base assets file changed, we
# generate a new assets.zip
shutil.copy(default_storage.path('assets-base.zip'),
default_storage.path('assets.zip.tmp'))
zf = zipfile.ZipFile(default_storage.path('assets.zip.tmp'), 'a')
for filename in ckeditor_filenames:
zf.write(default_storage.path(filename), 'media/' + filename)
zf.close()
os.unlink(default_storage.path('assets.zip'))
os.rename(default_storage.path('assets.zip.tmp'), default_storage.path('assets.zip'))
messages.info(request, _('A new update (including new assets) has been generated.'))
else:
messages.info(request, _('A new update has been generated.'))
return HttpResponseRedirect(reverse('momo-manager-homepage'))