general: add theming subsystem (#...)
This commit is contained in:
parent
bdc78a81f4
commit
9af65471a2
|
@ -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
|
||||
|
|
|
@ -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'
|
|
@ -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'))
|
|
@ -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)),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -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)
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -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))),
|
||||
]
|
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue