You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
8.5 KiB
225 lines
8.5 KiB
|
|
from django.db.models import Q
|
|
from django.forms.widgets import Media as WidgetsMedia
|
|
from django.contrib.sites.models import Site
|
|
from django.contrib.admin.templatetags.admin_static import static
|
|
from django.core.urlresolvers import reverse
|
|
|
|
from cms.plugin_base import CMSPluginBase
|
|
from cms.plugin_pool import plugin_pool
|
|
|
|
from .models import SmartSnippetPointer, SmartSnippet, Variable
|
|
from .settings import (
|
|
shared_sites, include_orphan, restrict_user, USE_BOOTSTRAP_ACE)
|
|
from django.conf import settings
|
|
import itertools
|
|
|
|
|
|
def variables_media(media, variables=None):
|
|
variables = variables or []
|
|
media.add_js([static('admin/js/SmartSnippetLib.js')])
|
|
media.add_js(
|
|
itertools.chain(*[var.js for var in variables])
|
|
)
|
|
media.add_css(
|
|
{'all': itertools.chain(*[var.css for var in variables])})
|
|
|
|
|
|
def add_variables_media(context):
|
|
if not context:
|
|
return
|
|
formMedia = context.get('media')
|
|
if not formMedia:
|
|
return
|
|
variables = context.get('variables')
|
|
variables_media(formMedia, variables)
|
|
|
|
|
|
class SmartSnippetPlugin(CMSPluginBase):
|
|
shared_sites = shared_sites
|
|
include_orphan = include_orphan
|
|
restrict_user = restrict_user
|
|
|
|
change_form_template = 'smartsnippets/snippet_change_form.html'
|
|
|
|
model = SmartSnippetPointer
|
|
name = 'Smart Snippet'
|
|
render_template = 'smartsnippets/plugin.html'
|
|
text_enabled = True
|
|
|
|
@property
|
|
def media(self):
|
|
|
|
if not USE_BOOTSTRAP_ACE:
|
|
media_obj = super(SmartSnippetPlugin, self).media
|
|
else:
|
|
media_obj = WidgetsMedia(
|
|
js=((
|
|
static('admin/js/core.js'),
|
|
static('admin/js/admin/RelatedObjectLookups.js'),
|
|
static('libs/jquery-2.1.1.min.js'),
|
|
static('libs/bootstrap/js/bootstrap.min.js'),
|
|
static('admin/js/custom.js'), )
|
|
),
|
|
css={
|
|
'all': (
|
|
'//fonts.googleapis.com/css?family=Open+Sans:400,300',
|
|
static('libs/bootstrap/css/bootstrap.css'),
|
|
static('libs/ace/css/ace.min.css'),
|
|
static('admin/css/custom.css'), )
|
|
}
|
|
)
|
|
|
|
media_obj.add_js(
|
|
(reverse('admin:jsi18n'),
|
|
static('admin/js/SmartSnippetLib.js'),
|
|
static('admin/js/jquery.init.js'),
|
|
static('admin/js/default.jQuery.init.js')))
|
|
|
|
if not USE_BOOTSTRAP_ACE:
|
|
media_obj.add_css({
|
|
'all': (
|
|
static('admin/css/forms.css'),
|
|
static('admin/css/base.css'),
|
|
static('css/tipTip.css'),
|
|
static('admin/css/snippet_plugin_default.css'), )
|
|
})
|
|
media_obj.add_js((
|
|
static('js/jquery.tipTip.minified.js'),
|
|
static('admin/js/snippet_plugin_default.js'), )
|
|
)
|
|
return media_obj
|
|
|
|
def response_add(self, request, obj, **kwargs):
|
|
response = super(SmartSnippetPlugin, self)\
|
|
.response_add(request, obj, **kwargs)
|
|
if hasattr(response, 'context_data'):
|
|
response.context_data['plugin'] = obj
|
|
return response
|
|
|
|
def add_view(self, request, form_url='', extra_context=None):
|
|
extra_context = extra_context or {}
|
|
try:
|
|
snippet = SmartSnippet.objects.get(
|
|
id=int(request.GET.get('snippet', '')))
|
|
except (ValueError, SmartSnippet.DoesNotExist):
|
|
snippet = None
|
|
else:
|
|
empty_plugin_vars = self._make_vars_for_rendering(snippet)
|
|
extra_context.update({'variables': empty_plugin_vars})
|
|
|
|
response = super(SmartSnippetPlugin, self).add_view(
|
|
request, form_url, extra_context)
|
|
|
|
if snippet and hasattr(response, 'context_data'):
|
|
self._change_snippet_plugin_for_preview(
|
|
response.context_data, snippet)
|
|
add_variables_media(response.context_data)
|
|
return response
|
|
|
|
def _make_vars_for_rendering(self, snippet, plugin=None):
|
|
"""
|
|
Create plugin varibles instances prepared for template rendering.
|
|
"""
|
|
plugin = plugin or SmartSnippetPointer(snippet=snippet)
|
|
selected_snippet_vars = snippet.variables.all()
|
|
|
|
existing_plugin_vars = plugin.variables.filter(
|
|
snippet_variable__in=selected_snippet_vars)
|
|
existing_snippet_var_ids = set([
|
|
plugin_var.snippet_variable.id
|
|
for plugin_var in existing_plugin_vars])
|
|
# add empty model instances; these are not saved in the db and are
|
|
# created just for rendering purpose
|
|
empty_plugin_vars = [
|
|
Variable(snippet=plugin, snippet_variable=snippet_var)
|
|
for snippet_var in selected_snippet_vars
|
|
if snippet_var.id not in existing_snippet_var_ids]
|
|
return sorted(
|
|
list(existing_plugin_vars) + empty_plugin_vars,
|
|
key=lambda v: v.snippet_variable.name)
|
|
|
|
def _change_snippet_plugin_for_preview(self, context, snippet):
|
|
"""
|
|
The plugin instance rendered in the context needs to correspond to
|
|
the new selected snippet in order for it to render its template code.
|
|
If this is not changed for the context, the plugin that is saved
|
|
in the db will get rendered in the preview box(which is not what
|
|
we want if the snippet gets changed).
|
|
"""
|
|
empty_plugin = SmartSnippetPointer(snippet=snippet)
|
|
# copy all attributes from the cms plugin to the plugin instance
|
|
# in order for cms to render it as if it exists
|
|
empty_plugin.__dict__.update(context['plugin'].__dict__)
|
|
empty_plugin.pk = empty_plugin.id
|
|
context['plugin'] = empty_plugin
|
|
context['original'] = context['plugin']
|
|
|
|
def change_view(self, request, object_id, *args, **kwargs):
|
|
extra_context = kwargs.get('extra_context', None) or {}
|
|
|
|
try:
|
|
selected_snippet = SmartSnippet.objects.get(
|
|
id=int(request.GET.get('snippet', '')))
|
|
except (ValueError, SmartSnippet.DoesNotExist):
|
|
selected_snippet = None
|
|
|
|
plugin = SmartSnippetPointer.objects.get(pk=object_id)
|
|
snippet_changed = (selected_snippet and
|
|
selected_snippet.id != plugin.snippet.id)
|
|
|
|
if snippet_changed:
|
|
variables = self._make_vars_for_rendering(
|
|
selected_snippet, plugin)
|
|
else:
|
|
snippet_vars = plugin.snippet.variables.all()
|
|
variables = plugin.variables.filter(
|
|
snippet_variable__in=snippet_vars
|
|
).order_by('snippet_variable__name')
|
|
|
|
extra_context.update({'variables': variables})
|
|
kwargs['extra_context'] = extra_context
|
|
response = super(SmartSnippetPlugin, self).change_view(
|
|
request, object_id, *args, **kwargs)
|
|
|
|
context = getattr(response, 'context_data', None)
|
|
add_variables_media(context)
|
|
if snippet_changed and context:
|
|
adminform = response.context_data.get('adminform')
|
|
if not adminform:
|
|
return response
|
|
adminform.form.initial['snippet'] = selected_snippet.id
|
|
self._change_snippet_plugin_for_preview(
|
|
response.context_data, selected_snippet)
|
|
return response
|
|
|
|
def render(self, context, instance, placeholder):
|
|
context.update({'content': instance.render(context)})
|
|
return context
|
|
|
|
def save_model(self, request, obj, form, change):
|
|
super(SmartSnippetPlugin, self).save_model(request, obj, form, change)
|
|
vars = obj.snippet.variables.all()
|
|
for var in vars:
|
|
v, _ = Variable.objects.get_or_create(snippet=obj, snippet_variable=var)
|
|
v.value = request.REQUEST.get('_'+var.name+'_', '')
|
|
v.save()
|
|
|
|
def formfield_for_foreignkey(self, db_field, request, **kwargs):
|
|
if db_field.name == "snippet":
|
|
f = Q(sites=Site.objects.get_current())
|
|
if self.shared_sites:
|
|
f |= Q(sites__name__in=self.shared_sites)
|
|
kwargs["queryset"] = SmartSnippet.objects.filter(f).distinct()
|
|
return (super(SmartSnippetPlugin, self)
|
|
.formfield_for_foreignkey(db_field, request, **kwargs))
|
|
|
|
def icon_src(self, instance):
|
|
return settings.STATIC_URL + u"images/snippet.png"
|
|
|
|
def icon_alt(self, instance):
|
|
if instance.snippet:
|
|
return instance.snippet.name
|
|
return ""
|
|
|
|
plugin_pool.register_plugin(SmartSnippetPlugin)
|
|
|