momo: add new application to generate manifest/assets files for momo (#8083)
This commit is contained in:
parent
b10e335016
commit
2c1208c8f5
|
@ -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'
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -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))),
|
||||
)
|
|
@ -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'))
|
Loading…
Reference in New Issue