From 2d71198352b7444c1cca338d19c72e22b0bdd65a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Tue, 11 Oct 2022 17:26:52 +0200 Subject: [PATCH] general: remove legacy theming code (#70128) --- MANIFEST.in | 2 - data/themes/alto/desc.xml | 6 - data/themes/alto/icon.png | Bin 728 -> 0 bytes data/themes/alto/img/bottom.jpg | Bin 10161 -> 0 bytes data/themes/alto/img/page.jpg | Bin 508 -> 0 bytes data/themes/alto/img/top.jpg | Bin 10248 -> 0 bytes data/themes/alto/template.ezt | 18 -- data/themes/alto/wcs.css | 270 --------------------- data/themes/default/desc.xml | 6 - data/themes/default/icon.png | Bin 675 -> 0 bytes data/themes/default/mobile.css | 0 data/themes/django/templates/wcs/base.html | 2 +- tests/admin_pages/test_settings.py | 122 +--------- tests/form_pages/test_all.py | 22 -- tests/test_hobo.py | 6 +- tests/utilities.py | 22 +- wcs/admin/settings.py | 269 +------------------- wcs/compat.py | 20 +- wcs/qommon/publisher.py | 7 +- wcs/qommon/template.py | 212 +--------------- wcs/root.py | 1 - wcs/utils.py | 2 +- 22 files changed, 16 insertions(+), 971 deletions(-) delete mode 100644 data/themes/alto/desc.xml delete mode 100644 data/themes/alto/icon.png delete mode 100644 data/themes/alto/img/bottom.jpg delete mode 100644 data/themes/alto/img/page.jpg delete mode 100644 data/themes/alto/img/top.jpg delete mode 100644 data/themes/alto/template.ezt delete mode 100644 data/themes/alto/wcs.css delete mode 100644 data/themes/default/desc.xml delete mode 100644 data/themes/default/icon.png delete mode 100644 data/themes/default/mobile.css diff --git a/MANIFEST.in b/MANIFEST.in index 71675dd95..f6497fdd9 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,8 +4,6 @@ include wcs.cfg-sample recursive-include wcs/locale *.po *.mo recursive-include extra/ *.py recursive-include data/web/ *.html *.css *.png -recursive-include data/themes/default/ *.html *.css *.png *.gif *.jpg *.js *.ezt *.xml -recursive-include data/themes/alto/ *.html *.css *.png *.gif *.jpg *.js *.ezt *.xml recursive-include data/vendor/ *.dat recursive-include wcs/qommon/static/ *.css *.scss *.png *.gif *.jpg *.js *.eot *.svg *.ttf *.woff *.map recursive-include wcs/templates *.html *.txt diff --git a/data/themes/alto/desc.xml b/data/themes/alto/desc.xml deleted file mode 100644 index d04d745a7..000000000 --- a/data/themes/alto/desc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - Alto theme - Frederic Peters (original Dotclear theme (alto studio) by David Jubert) - diff --git a/data/themes/alto/icon.png b/data/themes/alto/icon.png deleted file mode 100644 index 4276e319e86c894b47d761319150994e302fff81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 728 zcmV;}0w?{6P)WFU8GbZ8({Xk{QrNlj4iWF>9@00KNoL_t(Y$L&_puA(p$ zoL)=RNFv5WNGOpX@{9c#Ni2yWCRV`&Ezo_~w4vy_7Z>l-o|oG6z;wbgeLG}vr5csG<%AcVZk`N9C9lbr_%{_UBhu4 zqm)9HWeCIYul5MQfa_;zUw6{$<#NGt zxwLYUBmw6fuIr*G3NXeH$FVtIE|(BO!1KKRrPkp0`yG?X!~)&zcBtzb08mvGk|aTr zBqnD%okB|ao}6?!+k*lCob#tG+3)w(-f^7o%LxF45Z3;By;@E+o6XGLbzLjBC<-%J zLWq7n_B`)FN?J1dB2r2NemBFVk4yDi1G(`{u!+f0_$ARzr;GE-rzdyCivMiCNDSY3zBuMd( z;W!Q$V-P|h&vQ^pjr6Lj0;Tj}zy<++Cb#zQANlLkC;kKfSo{JvtwuV^&LU9&0000< KMNUMnLSTZ>t3+`C diff --git a/data/themes/alto/img/bottom.jpg b/data/themes/alto/img/bottom.jpg deleted file mode 100644 index f01a9db42c01f900e8896eeb4d58c35252e9a03a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10161 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 AjsO4v diff --git a/data/themes/alto/img/page.jpg b/data/themes/alto/img/page.jpg deleted file mode 100644 index 47413f7bf17e7218a3a91f15ab00cf181904acf6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 508 zcmex=C5UDGKfoZ!!N9~^#>^g- m_~H*9^L(;GY>wPfse{Rf5A}vQ8Wu~Xu8_WW-fx5b|C<2xOjv;c diff --git a/data/themes/alto/img/top.jpg b/data/themes/alto/img/top.jpg deleted file mode 100644 index fc2d41a5542b2446d6d05d3991e770ae3dc0ad5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10248 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 - - - [page_title] - - [script] - - -
-

[if-any title][title][else][site_name][end]

-
- [if-any breadcrumb][end] - [body] -
- -
- - diff --git a/data/themes/alto/wcs.css b/data/themes/alto/wcs.css deleted file mode 100644 index 00188ae05..000000000 --- a/data/themes/alto/wcs.css +++ /dev/null @@ -1,270 +0,0 @@ -/* adapted from alto dotclear theme */ - -@import url(/static/xstatic/themes/smoothness/jquery-ui.min.css); -@import url(/static/css/qommon.css); - -html, body { - background: #CCCCCC; - font-family: sans-serif; - color: #333333; - margin: 0; - padding: 0; - text-align: center; - height: 100%; - margin-bottom: 1px; -} - -fieldset { - border: none; -} - -label { - cursor: pointer; - cursor: hand; -} - -img { - border: 0; -} - -input,textarea { - border: 1px solid #999; -} - -textarea { - width: 99%; -} - -a { - color: #000; - text-decoration : none; -} - -a:hover { - color: #0273B9; - text-decoration : underline; -} - -a:visited { - color: #0273B9; - text-decoration : none; -} - -#page { - background: #fff url(img/page.jpg) repeat-y center top; - color: inherit; - width: 886px; - margin: 0 auto; - text-align: left; - padding: 0px; -} - -#top { - margin: 0; - padding: 0; - background: #CCCCCC url(img/top.jpg) no-repeat left top; - margin-bottom: 2em; -} - -#top h1 { - width: 706px; - margin: 0 auto; - padding-top: 70px; -} - -#side { - float: right; - width: 204px; - padding: 0; - margin: 0 -20px 0 20px; -} - -#side #tracking-code { - margin-bottom: 1em; - border: 1px solid #bfbfbf; - color: #333333; - background: #e6e6e6; - padding: 1ex; -} - -#side #tracking-code h3 { - margin: 0; -} - -#side #tracking-code button, -#side #tracking-code a { - margin: 1ex auto; - display: block; - text-align: center; - font-size: 120%; - background: white; - border: 1px solid black; - padding: 0.5ex 0; - width: 10em; -} - -#side #tracking-code button { - background: #0273B9; - color: white; -} - -input[name=savedraft] { - display: none; -} - -#steps { - background: white; - border: 1px solid #bfbfbf; - color: #333333; - background: #e6e6e6; - -moz-border-radius: 6px; - text-align: left; -} - - -#footer { - width: 886px; - height: 123px; - background: #CCCCCC url(img/bottom.jpg) no-repeat left top; - margin: 0; - margin-top: 1em; - color: #666; - clear: both; -} - -#footer p { - width: 706px; - margin: 0 auto; - padding-top: 24px; - text-align: right; - font-size: 80%; -} - - -#main-content { - width: 735px; - padding-left: 65px; - text-align: justify; -} - - -div#steps ol { - list-style: none; - margin: 0; - padding: 0.5em; -} - -div#steps li { - display: block; - border: 1px solid #ddd; - margin: 0.5em 0; - background: #eee; - color: #aaa; -} - -#steps span.marker { - padding: 0 1ex 0 1ex; - font-weight: bold; - color: white; - text-align: center; - background: #ddd; -} - -#steps li.current span.marker { - background: #0273b9; -} - - -#steps li.current { - font-weight: bold; - border: 1px solid #333333; -} - -#steps li.current span.label { - color: #333333; -} - -#steps ol ul { - margin-right: 1em; - font-size: 90%; -} - -#steps ol ul li { - padding: 0 2px; - font-weight: normal; - margin-left: -1ex; -} - -#steps ol ul li.current { - border-color: inherit; - color: #333333; -} - - -div.widget { - clear: none; - margin-bottom: 1.5em; -} - -hr { - visibility: hidden; -} - -textarea { -} - -p#breadcrumb { - background: #e6e6e6; - -moz-border-radius: 6px; - width: 750px; - padding: 3px; - font-size: 90%; - border: 1px solid #bfbfbf; -} - -div#receipt { -} - -div#receipt span.label { - font-weight: bold; - display: block; -} - -div#receipt span.value { - display: block; - margin-left: 1em; -} - -form div.page, -div#receipt div.page { - border: 1px solid #bfbfbf; - padding: 1ex; - margin-bottom: 1em; -} - -form div.page p, -div#receipt div.page p { - margin-top: 0; -} - -form div.page h3, -div#receipt div.page h3 { - margin: 0; - margin-bottom: 1ex; -} - - -p#receiver { - margin: 0; - margin-left: 2em; - margin-top: -0.7em; - margin-bottom: 1em; - padding: 2px 5px; - font-weight: bold; -} - -table#listing { - background: white; - border: 1px solid #888; -} - diff --git a/data/themes/default/desc.xml b/data/themes/default/desc.xml deleted file mode 100644 index 1c4571a8e..000000000 --- a/data/themes/default/desc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - Default theme - Frederic Peters & Dotclear Team - diff --git a/data/themes/default/icon.png b/data/themes/default/icon.png deleted file mode 100644 index f6838d2501f4ba5533c4c90323f2faa7e5d3eaaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 675 zcmV;U0$lxxP)Az(b7*_kyl&*!t^9}NG^ z#cHkpC$N6r1vbXKU5J?vb7g+}o;;Jer@%eHS}T|t*4hn_nGb;acS}Szdr4}&h;t6i zya5_xc3>d{c<&KHK#UR2xgE=oYb@ZUl!F4!IgI0oVHgl&yj*wx4p2*{<@Mep#)yfHXr5 zx&xL;IcHdFv99ZOe_0lU5Ds-M}CrBmRx ziA$|&tsC1mIvP}r(?+TN-EPFUxhebp;bTxyEg`lH;(~g?>9uy|0hI_TT9$=$}SNk6-h+xuT?87JL8z002ov JPDHLkV1kvuH^=}0 diff --git a/data/themes/default/mobile.css b/data/themes/default/mobile.css deleted file mode 100644 index e69de29bb..000000000 diff --git a/data/themes/django/templates/wcs/base.html b/data/themes/django/templates/wcs/base.html index 243ff32b6..2b3db1b4e 100644 --- a/data/themes/django/templates/wcs/base.html +++ b/data/themes/django/templates/wcs/base.html @@ -12,7 +12,7 @@
{% block header %} -

WIP/DJANGO - {% if title %}{{ title }}{% else %}{{ site_name }}{% endif %}

+

{% if title %}{{ title }}{% else %}{{ site_name }}{% endif %}

{% endblock %}
diff --git a/tests/admin_pages/test_settings.py b/tests/admin_pages/test_settings.py index cf002a655..801094b3c 100644 --- a/tests/admin_pages/test_settings.py +++ b/tests/admin_pages/test_settings.py @@ -28,7 +28,6 @@ from wcs.data_sources import NamedDataSource from wcs.formdef import FormDef from wcs.qommon.form import UploadedFile from wcs.qommon.http_request import HTTPRequest -from wcs.qommon.template import get_current_theme from wcs.wf.export_to_model import ExportToModel from wcs.workflows import Workflow from wcs.wscalls import NamedWsCall @@ -74,16 +73,14 @@ def test_settings_disabled_screens(pub): app = login(get_app(pub)) resp = app.get('/backoffice/settings/') assert 'Identification' in resp.text - assert 'Theme' in resp.text if not pub.site_options.has_section('options'): pub.site_options.add_section('options') - pub.site_options.set('options', 'settings-disabled-screens', 'identification, theme') + pub.site_options.set('options', 'settings-disabled-screens', 'identification') with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: pub.site_options.write(fd) resp = app.get('/backoffice/settings/') assert 'Identification' not in resp.text - assert 'Theme' not in resp.text def test_settings_export_import(pub): @@ -318,61 +315,6 @@ def test_settings_export_import(pub): assert 'Unknown referenced objects [Unknown fields blocks: unknown]' in resp -def test_settings_themes(pub): - create_superuser(pub) - app = login(get_app(pub)) - - # create mock theme - os.mkdir(os.path.join(pub.app_dir, 'themes')) - os.mkdir(os.path.join(pub.app_dir, 'themes', 'test')) - with open(os.path.join(pub.app_dir, 'themes', 'test', 'desc.xml'), 'w') as fd: - fd.write( - '' - '' - ' ' - '' - ) - - resp = app.get('/backoffice/settings/themes') - assert 'biglist themes' in resp.text - assert 'Test Theme (1.0)' in resp.text - - # just for the kick, there's no support for uploading file in webtest 1.3 - resp = app.get('/backoffice/settings/themes') - resp.click('Install New Theme') - - # select the theme - resp = app.get('/backoffice/settings/themes') - resp.forms[0]['theme'].value = 'test' - resp = resp.forms[0].submit() - assert resp.location == 'http://example.net/backoffice/settings/' - - resp = app.get('/backoffice/settings/themes') - assert 'checked' in resp.text - assert get_current_theme()['name'] == 'test' - - -def test_settings_template(pub): - create_superuser(pub) - app = login(get_app(pub)) - resp = app.get('/backoffice/settings/template') - - # change template - orig_value = resp.forms[0]['template'].value - assert 'foobar' not in orig_value - resp.forms[0]['template'] = orig_value + '' - resp = resp.forms[0].submit('submit') - - # restore default template - resp = app.get('/backoffice/settings/template') - assert 'foobar' in resp.forms[0]['template'].value - resp = resp.forms[0].submit('restore-default') - - # check - resp = app.get('/backoffice/settings/template') - assert resp.forms[0]['template'].value == orig_value - - def test_settings_user(pub): user = create_superuser(pub) app = login(get_app(pub)) @@ -829,68 +771,6 @@ def test_settings_permissions(pub): assert pub.cfg['admin-permissions']['workflows'] == [] -def test_settings_theme_preview(pub): - create_superuser(pub) - - FormDef.wipe() - formdef = FormDef() - formdef.name = 'form title' - formdef.fields = [] - formdef.store() - - app = login(get_app(pub)) - assert 'alto/wcs.css' not in app.get('/').text - resp = app.get('/backoffice/settings/themes') - assert resp.form['theme'].value in ('default', 'django') - - # visit theme preview - resp = resp.click(href='theme_preview/alto/') - assert 'alto/wcs.css' in resp.text - - # get into a form, making sure we are kept in theme preview - resp = resp.click('form title') - assert 'alto/wcs.css' in resp.text - - # verify submits are not allowed - resp = resp.form.submit('submit') - assert "The theme preview doesn't support this." in resp.text - - -def test_settings_theme_download_upload(pub): - create_superuser(pub) - - # download existing theme - app = login(get_app(pub)) - resp = app.get('/backoffice/settings/themes') - resp = resp.click('download', index=0) - assert resp.headers['content-type'] == 'application/zip' - - zip_content = io.BytesIO(resp.body) - with zipfile.ZipFile(zip_content, 'a') as zipf: - filelist = zipf.namelist() - assert 'alto/icon.png' in filelist - assert 'alto/desc.xml' in filelist - assert 'alto/template.ezt' in filelist - assert 'alto/wcs.css' in filelist - - # modify it - zipf.writestr('alto/foobar.txt', 'XXX') - - # upload it - resp = app.get('/backoffice/settings/themes') - resp = resp.click('Install New Theme') - resp.form['file'] = Upload('alto-modified.zip', zip_content.getvalue()) - resp = resp.form.submit() - assert os.path.exists(os.path.join(pub.app_dir, 'themes/alto/foobar.txt')) - - assert app.get('/themes/alto/foobar.txt').text == 'XXX' - assert 'Directory listing denied' in app.get('/themes/alto/', status=200).text - - assert app.get('/themes/alto/plop', status=404) - assert app.get('/themes/alto/../', status=404) - assert app.get('/themes/xxx/../', status=404) - - def test_postgresql_settings(pub): create_superuser(pub) diff --git a/tests/form_pages/test_all.py b/tests/form_pages/test_all.py index b94a479f4..05d6facc9 100644 --- a/tests/form_pages/test_all.py +++ b/tests/form_pages/test_all.py @@ -343,28 +343,6 @@ def test_category_page_redirect_var(pub): assert resp.location == 'http://www.example.com/en/foobar/' -def test_legacy_theme_misc(): - pub = create_temporary_pub(legacy_theme_mode=True) - pub.cfg['language'] = {'language': 'en'} - pub.write_cfg() - - formdef = create_formdef() - formdef.fields = [fields.StringField(id='1', label='string')] - formdef.store() - - resp = get_app(pub).get('/') - assert '' in resp.text - assert '/static/js/qommon.forms.js' not in resp.text - assert '<a class="" href="test/">test</a>' in resp.text - resp = resp.click('test') - assert '/static/js/qommon.forms.js' in resp.text - resp.form['f1'] = 'TEST' - resp = resp.form.submit('submit') - assert 'Check values then click submit.' in resp.text - resp = resp.form.submit('submit').follow() - assert 'The form has been recorded on' in resp.text - - def test_form_access(pub): formdef = create_formdef() get_app(pub).get('/test/', status=200) diff --git a/tests/test_hobo.py b/tests/test_hobo.py index a5157f308..91895c0aa 100644 --- a/tests/test_hobo.py +++ b/tests/test_hobo.py @@ -314,14 +314,14 @@ def test_update_configuration(setuptest): def test_update_themes(setuptest): pub, hobo_cmd = setuptest - pub.cfg['branding'] = {'theme': 'default'} + pub.cfg['branding'] = {'theme': 'django'} service = [x for x in HOBO_JSON.get('services', []) if x.get('service-id') == 'wcs'][0] hobo_cmd.update_configuration(service, pub) - assert pub.cfg['branding']['theme'] == 'default' + assert pub.cfg['branding']['theme'] == 'django' service['variables']['theme'] = 'foobar' hobo_cmd.update_configuration(service, pub) - assert pub.cfg['branding']['theme'] == 'default' + assert pub.cfg['branding']['theme'] == 'django' hobo_cmd.THEMES_DIRECTORY = os.path.join(os.path.dirname(__file__), 'themes') hobo_cmd.update_configuration(service, pub) diff --git a/tests/utilities.py b/tests/utilities.py index 3544b6c0d..21d9a55c7 100644 --- a/tests/utilities.py +++ b/tests/utilities.py @@ -33,30 +33,25 @@ class KnownElements: pickle_app_dir = None sql_app_dir = None sql_db_name = None - legacy_theme_app_dir = None lazy_app_dir = None known_elements = KnownElements() -def create_temporary_pub(pickle_mode=False, legacy_theme_mode=False, lazy_mode=False): +def create_temporary_pub(pickle_mode=False, lazy_mode=False): if get_publisher(): get_publisher().cleanup() cleanup() - if legacy_theme_mode and known_elements.legacy_theme_app_dir: - APP_DIR = known_elements.legacy_theme_app_dir - elif lazy_mode and known_elements.lazy_app_dir: + if lazy_mode and known_elements.lazy_app_dir: APP_DIR = known_elements.lazy_app_dir elif pickle_mode and known_elements.pickle_app_dir: APP_DIR = known_elements.pickle_app_dir - elif not (legacy_theme_mode or lazy_mode or pickle_mode) and known_elements.sql_app_dir: + elif not (lazy_mode or pickle_mode) and known_elements.sql_app_dir: APP_DIR = known_elements.sql_app_dir else: APP_DIR = tempfile.mkdtemp() - if legacy_theme_mode: - known_elements.legacy_theme_app_dir = APP_DIR - elif lazy_mode: + if lazy_mode: known_elements.lazy_app_dir = APP_DIR elif pickle_mode: known_elements.pickle_app_dir = APP_DIR @@ -124,12 +119,6 @@ def create_temporary_pub(pickle_mode=False, legacy_theme_mode=False, lazy_mode=F 'frontoffice-url': 'http://example.net', } pub.cfg['language'] = {'language': 'en'} - - if legacy_theme_mode: - pub.cfg['branding'] = {'theme': 'default'} - else: - pub.cfg['branding'] = {'theme': 'django'} - pub.write_cfg() if not created: @@ -183,9 +172,6 @@ def create_temporary_pub(pickle_mode=False, legacy_theme_mode=False, lazy_mode=F def clean_temporary_pub(): if get_publisher(): get_publisher().cleanup() - if known_elements.legacy_theme_app_dir and os.path.exists(known_elements.legacy_theme_app_dir): - shutil.rmtree(known_elements.legacy_theme_app_dir) - known_elements.legacy_theme_app_dir = None if known_elements.pickle_app_dir and os.path.exists(known_elements.pickle_app_dir): shutil.rmtree(known_elements.pickle_app_dir) known_elements.pickle_app_dir = None diff --git a/wcs/admin/settings.py b/wcs/admin/settings.py index 709fa4ff6..b414c4c83 100644 --- a/wcs/admin/settings.py +++ b/wcs/admin/settings.py @@ -24,11 +24,10 @@ try: import lasso except ImportError: lasso = None -import shutil import xml.etree.ElementTree as ET import zipfile -from django.utils.encoding import force_bytes, force_text +from django.utils.encoding import force_bytes from quixote import get_publisher, get_request, get_response, get_session, redirect from quixote.directory import Directory from quixote.html import TemplateIO, htmltext @@ -41,7 +40,6 @@ from wcs.formdef import FormDef, FormdefImportError from wcs.qommon import _, errors, get_cfg, ident, misc, template from wcs.qommon.admin.cfg import cfg_submit from wcs.qommon.admin.emails import EmailsDirectory -from wcs.qommon.admin.menu import error_page from wcs.qommon.admin.settings import SettingsDirectory as QommonSettingsDirectory from wcs.qommon.admin.texts import TextsDirectory from wcs.qommon.afterjobs import AfterJob @@ -59,7 +57,6 @@ from wcs.qommon.form import ( SingleSelectWidget, StringWidget, TextWidget, - UrlWidget, WidgetList, ) from wcs.workflows import Workflow, WorkflowImportError @@ -449,51 +446,9 @@ class FileTypesDirectory(Directory): return r.getvalue() -class ThemePreviewDirectory(Directory): - def _q_traverse(self, path): - if len(path) < 2: - return error_page('settings', _('Invalid URL')) - - theme_id = path[0] - branding = get_publisher().cfg.get('branding', {}) - original_branding = branding.copy() - get_publisher().cfg['branding'] = branding - get_publisher().cfg['branding']['theme'] = theme_id - if 'template' in get_publisher().cfg['branding']: - del get_publisher().cfg['branding']['template'] - - root_directory = get_publisher().root_directory_class() - - response = get_response() - response.reset_includes() - response.filter = {} - del response.breadcrumb - - if path[1] in ('backoffice', 'admin') or get_request().get_method() == 'POST': - from wcs.qommon.template import error_page as base_error_page - - output = base_error_page(_("The theme preview doesn't support this.")) - else: - output = root_directory._q_traverse(path[1:]) - - from wcs.qommon.template import decorate - - if isinstance(output, template.QommonTemplateResponse): - output = template.render(output.templates, output.context) - theme_preview = decorate(output, response) - - # restore original branding in case it has been changed - get_publisher().cfg['branding'] = original_branding - get_publisher().write_cfg() - response.filter['raw'] = True - - return theme_preview - - class SettingsDirectory(QommonSettingsDirectory): _q_exports = [ '', - 'themes', 'users', 'template', 'emails', @@ -506,12 +461,9 @@ class SettingsDirectory(QommonSettingsDirectory): 'sms', 'certificates', 'texts', - 'install_theme', - 'download_theme', 'postgresql', ('admin-permissions', 'admin_permissions'), 'geolocation', - 'theme_preview', 'filetypes', ('user-templates', 'user_templates'), ('data-sources', 'data_sources'), @@ -523,7 +475,6 @@ class SettingsDirectory(QommonSettingsDirectory): identification = IdentificationDirectory() users = UsersDirectory() texts = TextsDirectory() - theme_preview = ThemePreviewDirectory() filetypes = FileTypesDirectory() data_sources = NamedDataSourcesDirectory() wscalls = NamedWsCallsDirectory() @@ -636,13 +587,6 @@ class SettingsDirectory(QommonSettingsDirectory): _('Language'), _('Configure site language'), ) - if enabled('theme'): - r += htmltext('<dt><a href="themes">%s</a></dt> <dd>%s</dd>') % (_('Theme'), _('Configure theme')) - if enabled('template'): - r += htmltext('<dt><a href="template">%s</a></dt> <dd>%s</dd>') % ( - _('Template'), - _('Configure template'), - ) if enabled('geolocation'): r += htmltext('<dt><a href="geolocation">%s</a></dt> <dd>%s</dd>') % ( _('Geolocation'), @@ -766,217 +710,6 @@ class SettingsDirectory(QommonSettingsDirectory): get_publisher().write_cfg() return redirect('.') - def themes(self): - request = get_request() - - if 'theme' not in request.form: - current_theme = get_cfg('branding', {}).get('theme', 'default') - - get_response().breadcrumb.append(('themes', _('Themes'))) - html_top('settings', title=_('Themes')) - r = TemplateIO(html=True) - r += htmltext("<h2>%s</h2>") % _('Themes') - - r += get_session().display_message() - - r += htmltext('<a rel="popup" href="install_theme">%s</a>') % _('Install New Theme') - - r += htmltext('<form action="themes" enctype="multipart/form-data" method="post">') - themes = template.get_themes_dict() - r += htmltext('<ul class="biglist themes">') - for theme, theme_dict in sorted(themes.items()): - label = theme_dict.get('label') - if 'version' in theme_dict: - label = '%s (%s)' % (label, theme_dict.get('version')) - if current_theme == theme: - checked = ' checked="checked"' - else: - checked = '' - r += htmltext('<li>') - r += htmltext('<strong class="label"><label>') - r += htmltext(' <input name="theme" value="%s" type="radio"%s>%s</input>') % ( - theme, - checked, - label, - ) - r += htmltext('</label></strong>') - if theme_dict.get('icon'): - r += htmltext('<img src="/themes/%s/icon.png" alt="" class="theme-icon" />') % theme - r += htmltext('<p class="details">%s') % theme_dict.get('desc', '') - r += htmltext(' [<a href="download_theme?theme=%s">%s</a>]') % (theme, _('download')) - r += htmltext(' [<a class="theme-preview" href="theme_preview/%s/">%s</a>]') % ( - theme, - _('preview'), - ) - if theme_dict.get('author'): - r += htmltext('<br/>') - r += htmltext(_('by %s')) % theme_dict.get('author') - r += htmltext('</p>') - r += htmltext('</li>') - r += htmltext('</ul>') - r += htmltext('<div class="buttons">') - r += htmltext('<button>%s</button>') % _('Submit') - r += htmltext('</div>') - r += htmltext('</form>') - return r.getvalue() - else: - themes = template.get_themes() - if str(request.form['theme']) in themes: - branding_cfg = get_cfg('branding', {}) - branding_cfg['theme'] = str(request.form['theme']) - get_publisher().cfg['branding'] = branding_cfg - get_publisher().write_cfg() - return redirect('.') - - def download_theme(self): - theme_id = get_request().form.get('theme') - if not theme_id: - return redirect('themes') - - theme_directory = template.get_theme_directory(theme_id) - if not theme_directory: - return redirect('themes') - - parent_theme_directory = os.path.dirname(theme_directory) - c = io.BytesIO() - with zipfile.ZipFile(c, 'w') as z: - for base, dummy, filenames in os.walk(theme_directory): - basetheme = base[len(parent_theme_directory) + 1 :] - for filename in filenames: - z.write(os.path.join(base, filename), os.path.join(basetheme, filename)) - - response = get_response() - response.set_content_type('application/zip') - response.set_header('content-disposition', 'attachment; filename=%s.zip' % theme_id) - return c.getvalue() - - def install_theme(self): - form = Form(enctype='multipart/form-data') - form.add(FileWidget, 'file', title=_('Theme File'), required=False) - form.add(UrlWidget, 'url', title=_('Theme Address'), required=False, size=50) - form.add_submit('submit', _('Install')) - form.add_submit('cancel', _('Cancel')) - - if form.get_submit() == 'cancel': - return redirect('.') - - if form.is_submitted() and not form.has_errors(): - try: - return self.install_theme_submit(form) - except ValueError: - form.get_widget('file').set_error(_('Invalid Theme')) - - get_response().breadcrumb.append(('install_theme', _('Install Theme'))) - html_top('forms', title=_('Install Theme')) - r = TemplateIO(html=True) - r += htmltext('<h2>%s</h2>') % _('Install Theme') - r += htmltext('<p>%s</p>') % _( - 'You can install a new theme by uploading a file or by pointing to the theme URL.' - ) - r += form.render() - return r.getvalue() - - def install_theme_submit(self, form): - if form.get_widget('url').parse(): - return self.install_theme_from_url(form.get_widget('url').parse()) - if form.get_widget('file').parse(): - return self.install_theme_from_file(form.get_widget('file').parse().fp) - get_session().message = ('error', _('You have to enter a file or a URL.')) - return redirect('themes') - - def install_theme_from_file(self, fp): - try: - with zipfile.ZipFile(fp, 'r') as z: - theme_dir = os.path.join(get_publisher().app_dir, 'themes') - filename_list = [x for x in z.namelist() if x[0] != '/' and x[-1] != '/'] - if len(filename_list) == 0: - get_session().message = ('error', _('Empty theme file.')) - return redirect('themes') - theme_name = filename_list[0].split('/')[0] - if ('%s/desc.xml' % theme_name) not in filename_list: - get_session().message = ('error', _('Theme is missing a desc.xml file.')) - return redirect('themes') - desc_xml = z.read('%s/desc.xml' % theme_name) - theme_dict = template.get_theme_dict(io.StringIO(force_text(desc_xml))) - if theme_dict.get('name') != theme_name: - get_session().message = ('error', _('desc.xml is missing a name attribute.')) - return redirect('themes') - if os.path.exists(os.path.join(theme_dir, theme_name)): - shutil.rmtree(os.path.join(theme_dir, theme_name)) - for f in z.namelist(): - if f[-1] == '/': - continue - path = os.path.join(theme_dir, f) - data = z.read(f) - if not os.path.exists(os.path.dirname(path)): - os.makedirs(os.path.dirname(path)) - with open(path, 'wb') as _f: - _f.write(data) - return redirect('themes') - except Exception as e: - get_session().message = ('error', _('Failed to read theme file. (%s)') % str(e)) - return redirect('themes') - - def install_theme_from_url(self, url): - try: - fp = misc.urlopen(url) - except misc.ConnectionError as e: - get_session().message = ('error', _('Error loading theme (%s).') % str(e)) - return redirect('themes') - - return self.install_theme_from_file(io.StringIO(fp.read())) - - def template(self): - from wcs.qommon.template import get_default_ezt_template - - default_template_ezt = get_default_ezt_template() - branding_cfg = get_cfg('branding', {}) - template = branding_cfg.get('template', default_template_ezt) - form = Form(enctype="multipart/form-data") - form.add(TextWidget, 'template', title=_('Site Template'), value=template, cols=80, rows=25) - form.add_submit('submit', _('Submit')) - form.add_submit('restore-default', _('Restore default template')) - form.add_submit('cancel', _('Cancel')) - if form.get_widget('cancel').parse(): - return redirect('.') - - if form.get_submit() == 'cancel': - return redirect('.') - - if form.get_submit() == 'restore-default': - self.template_submit() - return redirect('.') - - if form.is_submitted() and not form.has_errors(): - self.template_submit(form) - return redirect('.') - - get_response().breadcrumb.append(('template', _('Template'))) - html_top('settings', title=_('Template')) - r = TemplateIO(html=True) - r += htmltext('<h2>%s</h2>') % _('Template') - r += form.render() - return r.getvalue() - - def template_submit(self, form=None): - from wcs.qommon.template import DEFAULT_TEMPLATE_EZT, get_default_ezt_template - - theme_default_template_ezt = get_default_ezt_template() - - get_publisher().reload_cfg() - branding_cfg = get_cfg('branding', {}) - if not form: - template = None - else: - template = form.get_widget('template').parse() - if template in (DEFAULT_TEMPLATE_EZT, theme_default_template_ezt) or not template: - if 'template' in branding_cfg: - del branding_cfg['template'] - else: - branding_cfg['template'] = template - get_publisher().cfg['branding'] = branding_cfg - get_publisher().write_cfg() - def export(self): if get_request().form.get('download'): return self.export_download() diff --git a/wcs/compat.py b/wcs/compat.py index 2ced96fea..3dd646764 100644 --- a/wcs/compat.py +++ b/wcs/compat.py @@ -14,7 +14,6 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, see <http://www.gnu.org/licenses/>. -import os from contextlib import contextmanager from threading import Lock @@ -31,7 +30,7 @@ from quixote.http_request import Upload from .publisher import WcsPublisher from .qommon import force_str, template from .qommon.http_request import HTTPRequest -from .qommon.publisher import get_cfg, set_publisher_class +from .qommon.publisher import set_publisher_class class TemplateWithFallbackView(TemplateView): @@ -65,8 +64,8 @@ class TemplateWithFallbackView(TemplateView): elif request.headers.get('X-Popup') == 'true': response = HttpResponse('<div class="popup-content">%s</div>' % context['body']) elif 'raw' in (getattr(self.quixote_response, 'filter') or {}): - # used for theme preview (generated in /backoffice/ but cannot - # obviously receive the admin template. + # used for raw HTML snippets (for example in the test tool + # results in inspect page). response = HttpResponse(context['body']) else: response = self.render_to_response(context) @@ -145,19 +144,6 @@ class CompatWcsPublisher(WcsPublisher): return output if request.headers.get('X-Popup') == 'true': return '<div class="popup-content">%s</div>' % output - if response.filter and response.filter.get('admin_ezt'): - return self.render_response(output) - - current_theme = get_cfg('branding', {}).get('theme', 'default') - theme_directory = template.get_theme_directory(current_theme) - if not theme_directory: - return self.render_response(output) - - if not os.path.exists(os.path.join(theme_directory, 'templates')): - return self.render_response(output) - - if not os.path.exists(os.path.join(theme_directory, 'templates/wcs/base.html')): - return self.render_response(output) if isinstance(output, template.QommonTemplateResponse): template_response = output diff --git a/wcs/qommon/publisher.py b/wcs/qommon/publisher.py index ed7be5e22..149fca327 100644 --- a/wcs/qommon/publisher.py +++ b/wcs/qommon/publisher.py @@ -116,7 +116,7 @@ class QommonPublisher(Publisher): after_login_url = '' qommon_static_dir = 'static/' qommon_admin_css = 'css/dc2/admin.css' - default_theme = 'default' + default_theme = 'django' site_options = None site_charset = 'utf-8' @@ -346,11 +346,6 @@ class QommonPublisher(Publisher): return error_page - def render_response(self, content): - if isinstance(content, template.QommonTemplateResponse): - content = template.render(content.templates, content.context) - return template.decorate(content, self.get_request().response) - def install_lang(self, request=None): if request: lang = request.language diff --git a/wcs/qommon/template.py b/wcs/qommon/template.py index 8e4f33a6b..5604fbfee 100644 --- a/wcs/qommon/template.py +++ b/wcs/qommon/template.py @@ -14,11 +14,9 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, see <http://www.gnu.org/licenses/>. -import glob import io import os import re -import xml.etree.ElementTree as ET import django.template from django.template import TemplateSyntaxError as DjangoTemplateSyntaxError @@ -27,9 +25,7 @@ from django.template import engines from django.template.loader import render_to_string from django.utils.encoding import force_text, smart_text from quixote import get_publisher, get_request, get_response, get_session -from quixote.directory import Directory from quixote.html import TemplateIO, htmlescape, htmltext -from quixote.util import StaticDirectory, StaticFile from . import ezt, force_str @@ -53,123 +49,6 @@ def get_theme_directory(theme_id): return location -class ThemesDirectory(Directory): - def _q_lookup(self, component): - from . import errors - - if component in ('.', '..'): - raise errors.TraversalError() - - location = get_theme_directory(component) - if location is None: - raise errors.TraversalError() - - if os.path.isdir(location): - return StaticDirectory(location) - else: - return StaticFile(location) - - -def get_themes_dict(): - system_location = os.path.join(get_publisher().data_dir, 'themes') - local_location = os.path.join(get_publisher().app_dir, 'themes') - - themes = {} - for theme_xml in glob.glob(os.path.join(system_location, '*/desc.xml')) + glob.glob( - os.path.join(local_location, '*/desc.xml') - ): - theme_dict = get_theme_dict(theme_xml) - if not theme_dict: - continue - themes[theme_dict.get('name')] = theme_dict - return themes - - -def get_theme_dict(theme_xml): - try: - tree = ET.parse(theme_xml).getroot() - except Exception: # parse error - return None - name = force_str(tree.attrib['name']) - version = force_str(tree.attrib.get('version') or '') - label = force_str(tree.findtext('label') or '') - desc = force_str(tree.findtext('desc') or '') - author = force_str(tree.findtext('author') or '') - icon = None - if isinstance(theme_xml, str): - icon = os.path.join(os.path.dirname(theme_xml), 'icon.png') - if not os.path.exists(icon): - icon = None - theme = {'name': name, 'label': label, 'desc': desc, 'author': author, 'icon': icon, 'version': version} - theme['keywords'] = [] - for keyword in tree.findall('keywords/keyword'): - theme['keywords'].append(keyword.text) - return theme - - -def get_themes(): - # backward compatibility function, it returns a tuple with theme info, - # newer code should use get_themes_dict() - themes = {} - for k, v in get_themes_dict().items(): - themes[k] = (v['label'], v['desc'], v['author'], v['icon']) - return themes - - -def get_current_theme(): - from .publisher import get_cfg - - current_theme = get_cfg('branding', {}).get('theme', 'default') - system_location = os.path.join(get_publisher().data_dir, 'themes', current_theme) - local_location = os.path.join(get_publisher().app_dir, 'themes', current_theme) - for location in (local_location, system_location): - if os.path.exists(location): - return get_theme_dict(os.path.join(location, 'desc.xml')) - default_theme_location = os.path.join(get_publisher().data_dir, 'themes', 'default') - return get_theme_dict(os.path.join(default_theme_location, 'desc.xml')) - - -DEFAULT_TEMPLATE_EZT = """<!DOCTYPE html> -<html lang="[site_lang]"> - <head> - <title>[page_title] - - [script] - - -
-

[if-any title][title][else][site_name][end]

-
- [if-any breadcrumb][end] - [body] -
- -
- -""" - -DEFAULT_IFRAME_EZT = """ - - - [page_title] - - [script] - - -
- [if-any breadcrumb][end] - [body] -
- -""" - -default_template = ezt.Template() -default_template.parse(DEFAULT_TEMPLATE_EZT) - -default_iframe_template = ezt.Template() -default_iframe_template.parse(DEFAULT_IFRAME_EZT) - - def html_top(title=None, default_org=None): if not hasattr(get_response(), 'filter'): get_response().filter = {} @@ -207,38 +86,6 @@ def error_page(error_message, error_title=None, location_hint=None): return htmltext(r.getvalue()) -def get_default_ezt_template(): - from .publisher import get_cfg - - current_theme = get_cfg('branding', {}).get('theme', 'default') - - filename = os.path.join( - get_publisher().app_dir, 'themes', current_theme, 'template.%s.ezt' % get_publisher().APP_NAME - ) - if os.path.exists(filename): - with open(filename) as fd: - return fd.read() - - filename = os.path.join( - get_publisher().data_dir, 'themes', current_theme, 'template.%s.ezt' % get_publisher().APP_NAME - ) - if os.path.exists(filename): - with open(filename) as fd: - return fd.read() - - filename = os.path.join(get_publisher().app_dir, 'themes', current_theme, 'template.ezt') - if os.path.exists(filename): - with open(filename) as fd: - return fd.read() - - filename = os.path.join(get_publisher().data_dir, 'themes', current_theme, 'template.ezt') - if os.path.exists(filename): - with open(filename) as fd: - return fd.read() - - return DEFAULT_TEMPLATE_EZT - - def get_decorate_vars(body, response, generate_breadcrumb=True, **kwargs): from .publisher import get_cfg @@ -303,20 +150,10 @@ def get_decorate_vars(body, response, generate_breadcrumb=True, **kwargs): subtitle = kwargs.get('subtitle') sidebar = kwargs.get('sidebar') css = root_url + get_publisher().qommon_static_dir + get_publisher().qommon_admin_css - - app_dir_filename = os.path.join(get_publisher().app_dir, 'themes', current_theme, 'admin.css') - data_dir_filename = os.path.join(get_publisher().data_dir, 'themes', current_theme, 'admin.css') - for filename in (app_dir_filename, data_dir_filename): - if os.path.exists(filename): - extra_css = root_url + 'themes/%s/admin.css' % current_theme - break extra_head = get_publisher().get_site_option('backoffice_extra_head') app_label = get_publisher().get_site_option('app_label') or 'w.c.s.' else: - if current_theme == 'default': - css = root_url + 'static/css/%s.css' % get_publisher().APP_NAME - else: - css = root_url + 'themes/%s/%s.css' % (current_theme, get_publisher().APP_NAME) + css = root_url + 'themes/%s/%s.css' % (current_theme, get_publisher().APP_NAME) # this variable is kept in locals() as it was once part of the default # template and existing installations may have template changes that @@ -354,53 +191,6 @@ def get_decorate_vars(body, response, generate_breadcrumb=True, **kwargs): return vars -def decorate(body, response): - if get_request().get_header('x-popup') == 'true': - return '''''' % body - - from .publisher import get_cfg - - generate_breadcrumb = True - template_ezt = get_cfg('branding', {}).get('template') - current_theme = get_cfg('branding', {}).get('theme', 'default') - if not template_ezt: - # the theme can provide a default template - possible_filenames = [] - possible_filenames.append('template.%s.ezt' % get_publisher().APP_NAME) - possible_filenames.append('template.ezt') - - possible_dirnames = [ - os.path.join(get_publisher().app_dir, 'themes', current_theme), - os.path.join(get_publisher().data_dir, 'themes', current_theme), - os.path.join(get_publisher().data_dir, 'themes', 'default'), - ] - - for fname in possible_filenames: - for dname in possible_dirnames: - filename = os.path.join(dname, fname) - if os.path.exists(filename): - with open(filename) as fd: - template_ezt = fd.read() - break - else: - continue - break - - if template_ezt: - generate_breadcrumb = '[breadcrumb]' in template_ezt - - template = ezt.Template() - template.parse(template_ezt) - else: - template = default_template - - fd = io.StringIO() - vars = get_decorate_vars(body, response, generate_breadcrumb=generate_breadcrumb) - - template.generate(fd, vars) - return fd.getvalue() - - def render(template_name, context): request = getattr(get_request(), 'django_request', None) result = render_to_string(template_name, context, request=request) diff --git a/wcs/root.py b/wcs/root.py index 35ae5eaa9..94c662fd9 100644 --- a/wcs/root.py +++ b/wcs/root.py @@ -265,7 +265,6 @@ class RootDirectory(Directory): ] api = ApiDirectory() - themes = template.ThemesDirectory() myspace = MyspaceDirectory() pages = PagesDirectory() fargo = portfolio.FargoDirectory() diff --git a/wcs/utils.py b/wcs/utils.py index 8bb0822f0..280e6d429 100644 --- a/wcs/utils.py +++ b/wcs/utils.py @@ -38,7 +38,7 @@ class TemplateLoader(django.template.loaders.filesystem.Loader): template_dirs.append(os.path.join(get_publisher().app_dir, 'templates')) template_dirs.append(os.path.join(get_publisher().app_dir, 'theme', 'templates')) - current_theme = get_cfg('branding', {}).get('theme', 'default') + current_theme = get_cfg('branding', {}).get('theme', get_publisher().default_theme) theme_directory = get_theme_directory(current_theme) if theme_directory: # templates from theme directory