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

+ + + +
+
+

Main content

+ {% block content %}{% feincms_render_region feincms_page "main" request %}{% endblock %} +
+ + +
+ +
+

Sidebar 2 content

+ {% block sidebar_2 %}{% feincms_render_region feincms_page "sidebar_2" 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