summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrédéric Péters <fpeters@entrouvert.com>2019-06-16 16:01:12 (GMT)
committerFrédéric Péters <fpeters@entrouvert.com>2020-01-22 18:57:57 (GMT)
commit9af65471a27831f8e204c9698b16c51848b7704f (patch)
tree3a803c70d5cf63f983790c3b78d55cce4e0dd904
parentbdc78a81f4506f98ac9263fdc3dccfdf5b2e2f2e (diff)
downloadcombo-wip/theming.zip
combo-wip/theming.tar.gz
combo-wip/theming.tar.bz2
general: add theming subsystem (#...)wip/theming
-rw-r--r--MANIFEST.in2
-rw-r--r--combo/apps/theming/__init__.py32
-rw-r--r--combo/apps/theming/manager_views.py111
-rw-r--r--combo/apps/theming/migrations/0001_initial.py24
-rw-r--r--combo/apps/theming/migrations/__init__.py0
-rw-r--r--combo/apps/theming/models.py21
-rw-r--r--combo/apps/theming/templates/combo/theming/manager_base.html16
-rw-r--r--combo/apps/theming/templates/combo/theming/manager_home.html50
-rw-r--r--combo/apps/theming/templates/combo/theming/manager_parameter.html29
-rw-r--r--combo/apps/theming/urls.py35
-rw-r--r--combo/context_processors.py3
-rw-r--r--combo/settings.py1
12 files changed, 324 insertions, 0 deletions
diff --git a/MANIFEST.in b/MANIFEST.in
index a63f9cb..786b0e0 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -8,6 +8,7 @@ recursive-include combo/apps/dashboard/static *.js
recursive-include combo/apps/gallery/static *.js
recursive-include combo/apps/maps/static *.css *.scss *.js
recursive-include combo/apps/pwa/static *.css *.scss *.js *.svg
+recursive-include combo/apps/theming/static *.css *.scss *.js *.svg
recursive-include combo/manager/static *.css *.js *.ico *.gif *.png *.jpg
recursive-include combo/public/static *.css *.js *.ico *.gif *.png *.jpg
@@ -26,6 +27,7 @@ recursive-include combo/apps/maps/templates *.html
recursive-include combo/apps/newsletters/templates *.html
recursive-include combo/apps/notifications/templates *.html
recursive-include combo/apps/pwa/templates *.html *.js *.json
+recursive-include combo/apps/theming/templates *.html
recursive-include combo/apps/wcs/templates *.html
recursive-include combo/manager/templates *.html
recursive-include combo/public/templates *.html
diff --git a/combo/apps/theming/__init__.py b/combo/apps/theming/__init__.py
new file mode 100644
index 0000000..9ced3e1
--- /dev/null
+++ b/combo/apps/theming/__init__.py
@@ -0,0 +1,32 @@
+# combo - content management system
+# Copyright (C) 2015-2019 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_lazy as _
+
+
+class AppConfig(django.apps.AppConfig):
+ name = 'combo.apps.theming'
+
+ def get_before_urls(self):
+ from . import urls
+ return urls.urlpatterns
+
+ def get_extra_manager_actions(self):
+ return []
+
+default_app_config = 'combo.apps.theming.AppConfig'
diff --git a/combo/apps/theming/manager_views.py b/combo/apps/theming/manager_views.py
new file mode 100644
index 0000000..dedccfc
--- /dev/null
+++ b/combo/apps/theming/manager_views.py
@@ -0,0 +1,111 @@
+# combo - content management system
+# Copyright (C) 2015-2019 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 os
+import re
+import subprocess
+
+from django.conf import settings
+from django.core.urlresolvers import reverse_lazy
+from django.core.files.storage import default_storage
+from django import forms
+from django.http import HttpResponseRedirect
+from django.utils.encoding import force_bytes
+from django.utils.translation import ugettext_lazy as _
+from django.views.generic import TemplateView
+
+from .models import Parameter
+
+
+def create_css():
+ values = {x.name: x.value for x in Parameter.objects.all()}
+ style_scss = '\n'.join(['$%s: %s;' % (x.name, x.value) for x in Parameter.objects.all()])
+ style_scss += "\n@import 'style.scss';"
+
+ theme_directory = os.path.join(
+ settings.THEMES_DIRECTORY,
+ settings.THEME_INFO['module'],
+ 'static',
+ settings.TEMPLATE_VARS.get('theme'))
+ p = subprocess.Popen([
+ 'sassc',
+ '-I', theme_directory,
+ '--stdin'],
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
+ (stdout, stderr) = p.communicate(force_bytes(style_scss))
+ if not default_storage.exists('style'):
+ os.mkdir(default_storage.path('style'))
+ with default_storage.open('style/style.css', 'wb') as fd:
+ fd.write(stdout)
+
+
+def get_parameters():
+ themes_json = os.path.join(
+ settings.THEMES_DIRECTORY,
+ settings.THEME_INFO['module'],
+ 'themes.json')
+ with open(themes_json) as fd:
+ return json.load(fd).get('parameters')
+
+
+class ThemeParameter(object):
+ description = ''
+
+ def __init__(self, **kwargs):
+ for k, v in kwargs.items():
+ setattr(self, k, v)
+
+ def short_description(self):
+ return re.split(r'[,;\(\.]', self.description or self.name)[0].strip()
+
+
+class ManagerHomeView(TemplateView):
+ template_name = 'combo/theming/manager_home.html'
+
+ def get_context_data(self, **kwargs):
+ context = super(ManagerHomeView, self).get_context_data(**kwargs)
+ context['parameters'] = [ThemeParameter(name=x, **y) for x, y in get_parameters().items()]
+ context['parameters'].sort(key=lambda x: x.name)
+ values = {x.name: x.value for x in Parameter.objects.all()}
+ for parameter in context['parameters']:
+ parameter.value = values.get(parameter.name)
+ return context
+
+
+class ManagerParameterView(TemplateView):
+ template_name = 'combo/theming/manager_parameter.html'
+
+ def get_context_data(self, **kwargs):
+ context = super(ManagerParameterView, self).get_context_data(**kwargs)
+ context['parameter'] = self.kwargs['parameter']
+ context['option'] = get_parameters().get(context['parameter'])
+ try:
+ value = Parameter.objects.get(name=self.kwargs['parameter']).value
+ except Parameter.DoesNotExist:
+ value = ''
+ context['value'] = value
+ return context
+
+ def post(self, request, *args, **kwargs):
+ value = request.POST['value']
+ parameter, created = Parameter.objects.get_or_create(
+ name=self.kwargs['parameter'],
+ defaults={'value': value})
+ parameter.value = value
+ parameter.save()
+ create_css()
+ return HttpResponseRedirect(reverse_lazy('theming-manager-homepage'))
diff --git a/combo/apps/theming/migrations/0001_initial.py b/combo/apps/theming/migrations/0001_initial.py
new file mode 100644
index 0000000..1e0f5f5
--- /dev/null
+++ b/combo/apps/theming/migrations/0001_initial.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.12 on 2019-06-16 14:31
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Parameter',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=64)),
+ ('value', models.CharField(max_length=300)),
+ ],
+ ),
+ ]
diff --git a/combo/apps/theming/migrations/__init__.py b/combo/apps/theming/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/combo/apps/theming/migrations/__init__.py
diff --git a/combo/apps/theming/models.py b/combo/apps/theming/models.py
new file mode 100644
index 0000000..544d8cf
--- /dev/null
+++ b/combo/apps/theming/models.py
@@ -0,0 +1,21 @@
+# combo - content management system
+# Copyright (C) 2015-2019 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.db import models
+
+class Parameter(models.Model):
+ name = models.CharField(max_length=64, blank=False)
+ value = models.CharField(max_length=300, blank=False)
diff --git a/combo/apps/theming/templates/combo/theming/manager_base.html b/combo/apps/theming/templates/combo/theming/manager_base.html
new file mode 100644
index 0000000..4ec1d6b
--- /dev/null
+++ b/combo/apps/theming/templates/combo/theming/manager_base.html
@@ -0,0 +1,16 @@
+{% extends "combo/manager_base.html" %}
+{% load i18n %}
+
+{% block css %}
+{{ block.super }}
+<link rel="stylesheet" type="text/css" media="all" href="{{ STATIC_URL }}css/combo.manager.theming.css"/>
+{% endblock %}
+
+{% block appbar %}
+<h2>{% trans 'Theming' %}</h2>
+{% endblock %}
+
+{% block breadcrumb %}
+{{ block.super }}
+<a href="{% url 'theming-manager-homepage' %}">{% trans 'Theming' %}</a>
+{% endblock %}
diff --git a/combo/apps/theming/templates/combo/theming/manager_home.html b/combo/apps/theming/templates/combo/theming/manager_home.html
new file mode 100644
index 0000000..e04d2f5
--- /dev/null
+++ b/combo/apps/theming/templates/combo/theming/manager_home.html
@@ -0,0 +1,50 @@
+{% extends "combo/theming/manager_base.html" %}
+{% load i18n %}
+
+{% block content %}
+<form>
+ <p><input name="q" type="search" value="{{query}}"> <button>{% trans 'Search' %}</button>
+ </p>
+</form>
+
+<div style="height: 35vh; overflow: scroll;">
+<table width="100%" class="main">
+ <thead>
+ <tr>
+ <th>{% trans "Parameter Name" %}</th>
+ <th>{% trans "Type" %}</th>
+ <th>{% trans "Value" %}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for parameter in parameters %}
+ <tr data-url="{% url 'theming-manager-parameter' parameter=parameter.name %}">
+ <td>{{parameter.short_description}}</td>
+ <td>{{parameter.type}}</td>
+ <td>{% if parameter.value %}{{ parameter.value }}{% else %}-{% endif %}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+</div>
+<iframe src="/" style="border :0; width: 100%; height: 40vh"></iframe>
+<script>
+$('table tbody tr').on('click', window.displayPopup);
+$('form input').on('input', function() {
+ var val = $(this).val();
+ $('table tbody tr').each(function(i, x) {
+ if ($(x).find('td:first-child').text().indexOf(val) == -1) {
+ $(x).hide();
+ } else {
+ $(x).show();
+ }
+ });
+});
+</script>
+<style>
+table tr th:first-child,
+table tr td:first-child {
+ text-align: left;
+}
+</style>
+{% endblock %}
diff --git a/combo/apps/theming/templates/combo/theming/manager_parameter.html b/combo/apps/theming/templates/combo/theming/manager_parameter.html
new file mode 100644
index 0000000..df1b9eb
--- /dev/null
+++ b/combo/apps/theming/templates/combo/theming/manager_parameter.html
@@ -0,0 +1,29 @@
+{% extends "combo/theming/manager_base.html" %}
+{% load i18n %}
+
+{% block appbar %}
+<h2>{{ parameter }}</h2>
+{% endblock %}
+
+{% block content %}
+
+<form method="post">
+{% csrf_token %}
+
+<p style="max-width: 70ex">
+{{option.description}}
+</p>
+
+<input name="value" required value="{{value|default:''}}"
+ {% if option.type == 'color' %}type="color"
+ {% else %}type="text"
+ {% endif %}>
+
+ <div class="buttons">
+ <button class="submit-button">{% trans "Save" %}</button>
+ <a class="cancel" href="{% url 'theming-manager-homepage' %}">{% trans 'Cancel' %}</a>
+ </div>
+
+</form>
+
+{% endblock %}
diff --git a/combo/apps/theming/urls.py b/combo/apps/theming/urls.py
new file mode 100644
index 0000000..ef421dc
--- /dev/null
+++ b/combo/apps/theming/urls.py
@@ -0,0 +1,35 @@
+# combo - content management system
+# Copyright (C) 2015-2019 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 url, include
+
+from combo.urls_utils import decorated_includes, manager_required
+
+from .manager_views import (
+ ManagerHomeView,
+ ManagerParameterView,
+ )
+
+
+theming_manager_urls = [
+ url('^$', ManagerHomeView.as_view(), name='theming-manager-homepage'),
+ url('^edit/(?P<parameter>[\w-]+)/$', ManagerParameterView.as_view(), name='theming-manager-parameter'),
+]
+
+urlpatterns = [
+ url(r'^manage/theming/', decorated_includes(manager_required,
+ include(theming_manager_urls))),
+]
diff --git a/combo/context_processors.py b/combo/context_processors.py
index 66ba5ab..b9a52cd 100644
--- a/combo/context_processors.py
+++ b/combo/context_processors.py
@@ -14,8 +14,10 @@
# 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 os
from django.conf import settings
+from django.core.files.storage import default_storage
from combo.utils.cache import cache_during_request
from combo.apps.pwa.models import PwaSettings
@@ -24,5 +26,6 @@ def template_vars(request):
context_extras = {}
context_extras['debug'] = settings.DEBUG
context_extras['pwa_settings'] = cache_during_request(PwaSettings.singleton)
+ context_extras['theming_css'] = lambda: default_storage.exists('style/style.css')
context_extras.update(settings.TEMPLATE_VARS)
return context_extras
diff --git a/combo/settings.py b/combo/settings.py
index eb0f3d2..d73a4af 100644
--- a/combo/settings.py
+++ b/combo/settings.py
@@ -72,6 +72,7 @@ INSTALLED_APPS = (
'combo.apps.fargo',
'combo.apps.notifications',
'combo.apps.search',
+ 'combo.apps.theming',
'combo.apps.maps',
'combo.apps.calendar',
'combo.apps.pwa',