general: add theming subsystem (#...)
gitea-wip/combo/pipeline/head Build started... Details
gitea/combo/pipeline/head Build started... Details

This commit is contained in:
Frédéric Péters 2019-06-16 18:01:12 +02:00
parent bdc78a81f4
commit 9af65471a2
12 changed files with 324 additions and 0 deletions

View File

@ -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

View File

@ -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'

View File

@ -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'))

View File

@ -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)),
],
),
]

View File

@ -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)

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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))),
]

View File

@ -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

View File

@ -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',