Browse files

initial import

  • Loading branch information...
0 parents commit f646d2c2a16748312bd1a2efb6cc632263862400 Zenobius Jiricek committed Dec 30, 2011
1 AUTHORS
@@ -0,0 +1 @@
+Zenobius Jiricek <zenobius.jiricek@gmail.com>
0 CHANGES
No changes.
0 INSTALL
No changes.
27 LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2011, Zenobius Jiricek
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+A notice is prominently presented indicating that the latest version is always
+located at http://github.com/airtonix/cmsplugin_embeddedmenu
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
2 MANIFEST.in
@@ -0,0 +1,2 @@
+include AUTHORS CHANGES README.md LICENSE
+recursive-include cmsplugin_configurableproduct *.py *.html
108 README.md
@@ -0,0 +1,108 @@
+## DjangoCMS Embedded Menu
+
+This simple extension allows you to place menus in placeholders via the
+administration interface.
+
+
+## Requirements
+
+* django-cms
+* And all the requirements the above project(s) depend on.
+
+
+## Installation
+
+1. make sure you are using a python virtual environment
+
+ virtualenv ~/Dev/virtualenv/projectname
+ . ~/Dev/virtualenv/projectname/bin/activate
+ cd ~/Dev/projects/projectname/
+
+2. install it from pypi
+
+ pip install cmsplugin-embedded-menu
+
+3. or, install it from github
+
+ pip install git+https://github.com/airtonix/cmsplugin-embedded-menu
+
+## Configuration
+
+1. add `cmsplugin_embeddedmenu` to your `INSTALLED_APPS`
+
+2. perform a `./manage.py migrate` (for south users), or `./manage.py syncdb`
+
+3. There is no step three!
+
+
+## Override Template
+
+Choosing a template in the administration interface means that you
+populate the following two relative paths (to any of your app template dirs)
+with templates you desire to be made available.
+
+* cmsplugin_embeddedmenu/layouts
+
+Any .html file that doesn't contain the word 'base' will be presented in
+the template selector combo dropdown in the admin interface.
+
+For example, if your django project was at :
+
+ ~/Dev/Django/MyProjectName/
+
+And you had a django application named `SomethingSomethingSomething` at :
+
+ ~/Dev/Django/MyProjectName/SomethingSomethingSomething/
+
+Then templates for this plugin could be found at :
+
+ ~/Dev/Django/MyProjectName/SomethingSomethingSomething/templates/cmsplugin_embeddedmenu/layouts/*.html
+
+In fact, anywhere django looks for templates, you can place the following tree :
+
+ /cmsplugin_embeddedmenu
+ /layouts
+ /*.html
+
+
+### Customising Templates
+
+Templates in all groups are provided the context :
+
+a CMSPlugin has many useful attributes for you to use, the main one
+is `plugin.instance` a reference to the settings model.
+
+> plugin' :
+> An instance of CMSPlugin, which itself provides reference to either
+> of the settings models as outlined below.
+
+#### base.html
+
+base.html in the `cmsplugin_configurableproduct` directory is used to load the
+selected template chosen in the administration interface.
+
+
+#### ./layouts/*.html
+
+templates here are provided the context :
+
+> plugin.instance
+> template
+> Chosen template.
+>
+
+
+
+## Contributions
+
+anyone is free to contribute, simply submit a merge request at
+github : http://github.com/airtonix/cmsplugin-configurableproduct
+
+
+## Todo
+
+provide option to manipulate menu choices:
+
+* Refine the product filter.
+* Provide better default templates.
+* Allow selecting/use of snippets for menu templates?
1 cmsplugin_embeddedmenu/__init__.py
@@ -0,0 +1 @@
+__version__ = '0.0.4'
67 cmsplugin_embeddedmenu/cms_plugins.py
@@ -0,0 +1,67 @@
+from django.utils.translation import ugettext_lazy as _
+
+from cms.plugin_base import CMSPluginBase
+from cms.plugin_pool import plugin_pool
+from cms.models.pluginmodel import CMSPlugin
+
+from cms.menu_bases import CMSAttachMenu
+from menus.base import (
+ Menu,
+ Modifier,
+ NavigationNode
+)
+from menus.menu_pool import menu_pool
+from menus.templatetags.menu_tags import (
+ cut_levels,
+ cut_after,
+ flatten,
+)
+
+from models import (
+ Settings,
+ TEMPLATE_PATH,
+)
+
+class MenuPlugin(CMSPluginBase):
+ model = Settings
+ name = _("Embedded Menu")
+ render_template = "cmsplugin_menu/menu.html"
+
+ def render(self, context, instance, placeholder):
+
+ try:
+ # If there's an exception (500), default context_processors may not be called.
+ request = context['request']
+ except KeyError:
+ return "error"
+
+ levels = 100
+
+ root_id = 'home'
+ namespace = 'home'
+ from_level = 1
+ to_level = 100
+ extra_inactive = 100
+ extra_active = 100
+ next_page = False
+
+
+ nodes = menu_pool.get_nodes(request)
+ children = []
+ for node in nodes:
+ if node.selected:
+ cut_after(node, levels, [])
+ children = node.children
+ for child in children:
+ child.parent = None
+ children = menu_pool.apply_modifiers(children, request, post_cut=True)
+ context.update({
+ 'children':children,
+ 'from_level':0,
+ 'to_level':0,
+ 'extra_inactive':0,
+ 'extra_active':0
+ })
+ return context
+
+plugin_pool.register_plugin(CMSMenu)
0 cmsplugin_embeddedmenu/lib/__init__.py
No changes.
134 cmsplugin_embeddedmenu/lib/choices.py
@@ -0,0 +1,134 @@
+import os
+
+from django.template.loader import get_template
+from django.template.loaders.app_directories import app_template_dirs
+from django.core.exceptions import ImproperlyConfigured
+from django.utils.importlib import import_module
+
+from cms.models import Placeholder, Page
+
+from .formatting import deslugify
+from ..urls import SYNCDB_FINISHED
+
+class DynamicChoice(object):
+ """
+ Trivial example of creating a dynamic choice
+ """
+ ready=False
+
+ def __new__(self,*args, **kwargs):
+ if SYNCDB_FINISHED:
+ self.ready=True
+ else:
+ pass
+
+ def __iter__(self, *args, **kwargs):
+ for choice in self.generate():
+ if hasattr(choice,'__iter__'):
+ yield (choice[0], choice[1])
+ else:
+ yield choice, choice
+
+ def __init__(self, *args, **kwargs):
+ """
+ If you do it here it is only initialized once. Then just return generated.
+ """
+ self.generated = range(10)
+
+ def generate(self, *args, **kwargs):
+ """
+ If you do it here it is initialized every time the iterator is used.
+ """
+ return range(10)
+
+
+class PageAttributeDynamicChoices(DynamicChoice):
+
+ def __init__(self, *args, **kwargs):
+ super(PageAttributeDynamicChoices, self).__init__(self, *args, **kwargs)
+
+ def generate(self,*args, **kwargs):
+ choices = list()
+ return choices
+
+
+class PlaceholdersDynamicChoices(DynamicChoice):
+
+ def __init__(self, *args, **kwargs):
+ super(PlaceholdersDynamicChoices, self).__init__(self, *args, **kwargs)
+
+ def generate(self,*args, **kwargs):
+ choices = list()
+ for item in Placeholder.objects.all().values("slot").distinct():
+ choices += ((
+ item['slot'],
+ deslugify(item['slot'])
+ ), )
+
+ return choices
+
+class PageIDsDynamicChoices(DynamicChoice):
+
+ def __init__(self, *args, **kwargs):
+ super(PageIDsDynamicChoices, self).__init__(self, *args, **kwargs)
+
+ def generate(self,*args, **kwargs):
+ choices = list()
+ for item in Page.objects.all():
+ if not item.reverse_id :
+ continue
+
+ choices += ((
+ item.reverse_id,
+ "{0} [{1}]".format(item.get_title(), item.reverse_id)
+ ), )
+
+ return choices
+
+
+class DynamicTemplateChoices(DynamicChoice):
+ path = None
+ exclude = None
+ inlude = None
+
+ def __init__(self, path=None, include=None,
+ exclude=None, *args, **kwargs):
+ super(DynamicTemplateChoices, self).__init__(self, *args, **kwargs)
+ self.path = path
+ self.include = include
+ self.exlude = exclude
+
+ def generate(self,*args, **kwargs):
+ choices = list()
+
+ for template_dir in app_template_dirs:
+ results = self.walkdir(os.path.join(template_dir, self.path))
+ if results:
+ choices += results
+
+ return choices
+
+ def walkdir(self, path=None):
+ output = list()
+
+ if not os.path.exists(path):
+ return None
+
+ for root, dirs, files in os.walk(path):
+
+ if self.include:
+ files = filter(lambda x: self.include in x, files)
+
+ if self.exlude:
+ files = filter(lambda x: not self.exlude in x, files)
+
+ for item in files :
+ output += ( (
+ os.path.join(self.path, item),
+ deslugify(os.path.splitext(item)[0]),
+ ),)
+
+ for item in dirs :
+ output += self.walkdir(os.path.join(root, item))
+
+ return output
30 cmsplugin_embeddedmenu/models.py
@@ -0,0 +1,30 @@
+import os
+
+from django.db import models
+from cms.models.pluginmodel import CMSPlugin
+
+from .lib.choices import (
+ DynamicTemplateChoices,
+ PagesDynamicChoices,
+ PageAttributeDynamicChoices,
+)
+
+TEMPLATE_PATH = os.path.join("cmsplugin_menu", "layouts")
+
+class Settings(CMSPlugin):
+ """ Stores options for cmsplugin that Embeds a menu
+ """
+
+ TEMPLATE_CHOICES = DynamicTemplateChoices(
+ path=TEMPLATE_PATH,
+ include='.html',
+ exclude='default')
+
+ root = models.ForeignKey("cms.Page", default=1,
+ help_text="""Menu tree starts from this page.""")
+
+ start_level = models.IntegerField(default=0,
+ help_text="""Should the root page also be included in the output?""")
+
+ depth = models.IntegerField(default=0,
+ help_text="""How many levels deep to look for menu items to show?""")
1 cmsplugin_embeddedmenu/templates/cmsplugin_configurable_product/product-list/base.html
@@ -0,0 +1 @@
+{% include plugin.instance.template %}
5 ...n_embeddedmenu/templates/cmsplugin_configurable_product/product-list/two-column-grid.html
@@ -0,0 +1,5 @@
+{% for Product in Products %}
+ <div class="product span8">
+ {% include 'shop/plugins/configurable_product/snippet/display-only-small.html' %}
+ </div>
+{% endfor %}
1 cmsplugin_embeddedmenu/templates/cmsplugin_configurable_product/product-types/base.html
@@ -0,0 +1 @@
+{% include plugin.instance.template %}
8 ..._embeddedmenu/templates/cmsplugin_configurable_product/product-types/two-column-grid.html
@@ -0,0 +1,8 @@
+{% for Type in Types %}
+ <div class="product span8">
+ <div class="header">
+ <a href="{% url configurable_products_types Type.name|slugify %}">{{ Type }}</a>
+ </div>
+ <div class="description"></div>
+ </div>
+{% endfor %}
42 ..._embeddedmenu/templates/cmsplugin_configurable_product/snippets/product-display-only.html
@@ -0,0 +1,42 @@
+{% load cms_tags %}
+{% load sekizai_tags %}
+{% load i18n %}
+{% load shop_tags %}
+{% load thumbnail %}
+{% load humanize %}
+
+{% spaceless %}
+ <div class="product product-active-{{ Product.active }}" data-product-slug="{{ Product.slug }}" data-product-active="{{Product.active}}">
+
+ <div class="images">
+ <div class="cover">
+ <a href="{% url product_detail Product.slug %}">
+ {% with Product.productimage_set.all.0 as product_image %}
+ <img class="product-field-type-image product-field-{{ product_image.field.name|slugify }}"
+ src="{% thumbnail product_image.value 240x128 crop='crop_and_scale' %}"/>
+ {% endwith %}
+ </a>
+ </div>
+ </div>
+
+
+ <div class="detail">
+ <div class="description">
+
+ <div class="header">
+ <div class="title">
+ <h4>
+ <a href="{% url product_detail Product.slug %}">
+ {{ Product.name }}</a></h4>
+ </div>
+ </div>
+
+ <div class="detail">
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+{% endspaceless %}
37 setup.py
@@ -0,0 +1,37 @@
+import os
+from setuptools import (
+ setup,
+ find_packages,
+)
+import cmsplugin_embeddedmenu
+
+
+def read(fname):
+ return open(os.path.join(os.path.dirname(__file__), fname)).read()
+
+setup(
+ name='cmsplugin-embedded-menu',
+ version=cmsplugin_embeddedmenu.__version__,
+ classifiers = (
+ 'Development Status :: 4 - Beta',
+ 'Framework :: Django',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: BSD License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Topic :: Internet :: WWW/HTTP',
+ ),
+ packages=find_packages(),
+ install_requires=(
+ 'django-cms',
+ ),
+ author='Zenobius Jiricek',
+ author_email='airtonix@gmail.com',
+ description='DjangoCMS plugin for embedding menus in placeholders',
+ long_description = read('README.md'),
+ license='BSD',
+ keywords='django-cms, plugin',
+ url='http://github.com/airtonix/cmsplugin-embedded-menu',
+ include_package_data=True,
+ zip_safe = False,
+)

0 comments on commit f646d2c

Please sign in to comment.