diff --git a/README.rst b/README.rst
index 75ce0cf94..be56cd102 100644
--- a/README.rst
+++ b/README.rst
@@ -1,3 +1,8 @@
+This fork opts in an inheritable way of visualizing template choices for pages using little code.
+
+See: https://github.com/feincms/feincms/issues/242
+
+
========================================
FeinCMS - An extensible Django-based CMS
========================================
diff --git a/example/example.db b/example/example.db
index b4f1b46a4..4bd894b56 100644
Binary files a/example/example.db and b/example/example.db differ
diff --git a/example/models.py b/example/models.py
index f932dd879..14a37d451 100644
--- a/example/models.py
+++ b/example/models.py
@@ -24,6 +24,16 @@
('sidebar', 'Sidebar', 'inherited'),
),
})
+Page.register_templates({
+ 'key': 'double_sidebar',
+ 'title': 'Double Sidebar Template',
+ 'path': 'double_sidebar.html',
+ 'regions': (
+ ('main', 'Main region'),
+ ('sidebar', 'Sidebar', 'inherited'),
+ ('sidebar_2', 'Sidebar 2', 'inherited'),
+ ),
+ })
Page.create_content_type(RawContent)
Page.create_content_type(MediaFileContent, TYPE_CHOICES=(
('default', 'Default position'),
diff --git a/example/settings.py b/example/settings.py
index 982de92cb..4ed533ee1 100644
--- a/example/settings.py
+++ b/example/settings.py
@@ -86,3 +86,4 @@
)
FEINCMS_TREE_EDITOR_INCLUDE_ANCESTORS = True
+FEINCMS_VISUAL_TEMPLATES = True
\ No newline at end of file
diff --git a/example/templates/double_sidebar.html b/example/templates/double_sidebar.html
new file mode 100644
index 000000000..c2c515165
--- /dev/null
+++ b/example/templates/double_sidebar.html
@@ -0,0 +1,132 @@
+{% load applicationcontent_tags feincms_tags feincms_page_tags %}
+
+
+ {{ feincms_page.title }}
+
+
+
+ {{ feincms_page.title }}
+
+
+ {% feincms_nav feincms_page level=1 as toplevel %}
+ {% for p in toplevel %}
+
{{ p.title }}
+ {% endfor %}
+
+
+
+
+
Main content
+ {% block content %}{% feincms_render_region feincms_page "main" request %}{% endblock %}
+
+
+
+
+
+
+
+ {% feincms_frontend_editing feincms_page request %}
+
+ {% get_fragment request "something" %}
+
+
diff --git a/feincms/default_settings.py b/feincms/default_settings.py
index 66af9e4fd..00224e54c 100644
--- a/feincms/default_settings.py
+++ b/feincms/default_settings.py
@@ -130,4 +130,4 @@
#: from uploads. The value should end with a slash, but this is not enforced.
FEINCMS_THUMBNAIL_DIR = getattr(settings, 'FEINCMS_THUMBNAIL_DIR', '_thumbs/')
-# ------------------------------------------------------------------------
+# ------------------------------------------------------------------------
\ No newline at end of file
diff --git a/feincms/module/page/modeladmins.py b/feincms/module/page/modeladmins.py
index 6a9f7c128..092512b5e 100644
--- a/feincms/module/page/modeladmins.py
+++ b/feincms/module/page/modeladmins.py
@@ -13,8 +13,10 @@
from django.utils.functional import curry
from django.utils.translation import ugettext_lazy as _
+from feincms import default_settings
from feincms import ensure_completely_loaded
from feincms.admin import item_editor, tree_editor
+from feincms.utils.widgets import ThumbnailSelect
# ------------------------------------------------------------------------
from .forms import PageAdminForm
@@ -91,6 +93,8 @@ def __init__(self, model, admin_site):
def get_form(self, *args, **kwargs):
form = super(PageAdmin, self).get_form(*args, **kwargs)
+ if getattr(django_settings, 'FEINCMS_VISUAL_TEMPLATES', False):
+ form.base_fields['template_key'].widget = ThumbnailSelect(choices=form.base_fields['template_key'].choices)
return curry(form, modeladmin=self)
def _actions_column(self, page):
diff --git a/feincms/static/feincms/css/thumbnail_select.css b/feincms/static/feincms/css/thumbnail_select.css
new file mode 100644
index 000000000..f14b2cba7
--- /dev/null
+++ b/feincms/static/feincms/css/thumbnail_select.css
@@ -0,0 +1,28 @@
+ul.thumbnail_select_widget li {
+ border: 3px solid transparent;
+ display: inline-block;
+ margin: 0 10px 10px 0;
+ list-style: none;
+}
+
+ul.thumbnail_select_widget li img {
+ -webkit-border-radius: 12px;
+ -moz-border-radius: 12px;
+ border-radius: 12px;
+}
+
+ul.thumbnail_select_widget li.inactive img {
+ border: 3px solid #ccc;
+}
+
+ul.thumbnail_select_widget li.inactive:hover img {
+ border: 3px solid #7CA0C7;
+}
+
+ul.thumbnail_select_widget li.inactive {
+ cursor: pointer;
+}
+
+ul.thumbnail_select_widget li.active img {
+ border: 3px solid #417690;
+}
\ No newline at end of file
diff --git a/feincms/static/feincms/img/templates/base.jpg b/feincms/static/feincms/img/templates/base.jpg
new file mode 100644
index 000000000..9a2bd9891
Binary files /dev/null and b/feincms/static/feincms/img/templates/base.jpg differ
diff --git a/feincms/static/feincms/img/templates/double_sidebar.jpg b/feincms/static/feincms/img/templates/double_sidebar.jpg
new file mode 100644
index 000000000..8f0e48932
Binary files /dev/null and b/feincms/static/feincms/img/templates/double_sidebar.jpg differ
diff --git a/feincms/static/feincms/item_editor.js b/feincms/static/feincms/item_editor.js
index 187defa54..138bd1bc3 100644
--- a/feincms/static/feincms/item_editor.js
+++ b/feincms/static/feincms/item_editor.js
@@ -132,7 +132,7 @@ if(!Array.indexOf) {
function add_fieldset(region_id, item, how){
/* `how` should be an object.
- `how.where` should be one of:
+ `how.where` should be one of:
- 'append' -- last region
- 'prepend' -- first region
- 'insertBefore' -- insert before relative_to
@@ -268,9 +268,9 @@ if(!Array.indexOf) {
function hide_form_rows_with_hidden_widgets(){
/* This is not normally done in django -- the fields are shown
- with visible labels and invisible widgets, but FeinCMS used to
- use custom form rendering to hide rows for hidden fields.
- This is an attempt to preserve that behaviour. */
+ with visible labels and invisible widgets, but FeinCMS used to
+ use custom form rendering to hide rows for hidden fields.
+ This is an attempt to preserve that behaviour. */
$('div.feincms_inline div.form-row').each(function(){
var child_count = $(this).find('*').length;
var invisible_types = 'div, label, input[type=hidden], p.help';
@@ -415,7 +415,13 @@ if(!Array.indexOf) {
function on_template_key_changed(){
var input_element = this;
- var new_template = this.value;
+
+ if ($(input_element).is("img") === true) {
+ input_element = this.parentNode.getElementsByTagName('input')[0];
+ new_template = this.parentNode.getElementsByTagName('input')[0].value;
+ } else {
+ var new_template = this.value;
+ }
if(current_template==new_template)
// Selected template did not change
@@ -473,6 +479,8 @@ if(!Array.indexOf) {
template_key_radio.click(on_template_key_changed);
var template_key_select = $('select[name=template_key]');
template_key_select.change(on_template_key_changed);
+ var template_key_image = $('ul.thumbnail_select_widget img');
+ template_key_image.click(on_template_key_changed);
// Save template key's original value for easy restore if the user cancels the change.
template_key_radio.data('original_value', template_key_radio.val());
diff --git a/feincms/utils/widgets/__init__.py b/feincms/utils/widgets/__init__.py
new file mode 100644
index 000000000..51330942b
--- /dev/null
+++ b/feincms/utils/widgets/__init__.py
@@ -0,0 +1,31 @@
+from django.forms.widgets import RadioFieldRenderer
+from django.forms import RadioSelect
+from django.utils.encoding import force_unicode
+from django.utils.safestring import mark_safe
+
+
+class ThumbnailRenderer(RadioFieldRenderer):
+ def render(self):
+ """Outputs a for this set of radio fields."""
+ def _is_active(choice, value):
+ if choice == value:
+ return 'active'
+ return 'inactive'
+ return mark_safe(u'' % u'\n'.join([
+ u"""
+ -
+
+ %s
+
+ """ % (_is_active(w.choice_value, self.value),
+ force_unicode(w.choice_value),
+ force_unicode(w)) for w in self])
+ )
+
+class ThumbnailSelect(RadioSelect):
+ renderer = ThumbnailRenderer
+
+ class Media:
+ css = {
+ 'all': ('/static/feincms/css/thumbnail_select.css',)
+ }
\ No newline at end of file