Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add feature: copy only plugins in clipboard #293

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 35 additions & 7 deletions cmsplugin_cascade/clipboard/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.contrib.admin.templatetags.admin_static import static
from django.forms import widgets
from django.forms.utils import flatatt
from django.http import HttpResponse
from django.utils.encoding import force_text
from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _
Expand Down Expand Up @@ -60,6 +61,9 @@ class Media:
css = {'all': ('cascade/css/admin/clipboard.css',)}
js = ('cascade/js/admin/clipboard.js',)

def get_changeform_initial_data(self, request):
return {'identifier': "Clipboard {}".format(CascadeClipboard.objects.all().count()+1)}

def save_clipboard(self, obj):
return format_html('<input type="submit" value="{}" class="default pull-left" name="save_clipboard" />',
_("Insert Data"))
Expand All @@ -73,17 +77,21 @@ def restore_clipboard(self, obj):
def save_model(self, request, obj, form, change):
language = get_language_from_request(request)
if request.POST.get('save_clipboard'):
obj.data = self._serialize_from_clipboard(language)
obj.data = self._serialize_from_clipboard(request, language)
request.POST = request.POST.copy()
request.POST['_continue'] = True
if request.POST.get('restore_clipboard'):
request.POST = request.POST.copy()
request.POST['_continue'] = True
super(CascadeClipboardAdmin, self).save_model(request, obj, form, change)
if request.POST.get('restore_clipboard'):
self._deserialize_to_clipboard(request, obj.data)
if len(obj.data['plugins']) >= 2:
is_placeholder=True
else:
is_placeholder=None
self._deserialize_to_clipboard(request, obj.data, is_placeholder)

def _serialize_from_clipboard(self, language):
def _serialize_from_clipboard(self, request, language, clipboard=None):
"""
Create a serialized representation of all the plugins belonging to the clipboard.
"""
Expand All @@ -105,11 +113,14 @@ def populate_data(parent, data):
ref = PlaceholderReference.objects.last()
if ref:
clipboard = ref.placeholder_ref
elif request.toolbar.clipboard.cmsplugin_set.last():
clipboard = request.toolbar.clipboard
if clipboard is not None:
plugin_qs = clipboard.cmsplugin_set.all()
populate_data(None, data['plugins'])
return data

def _deserialize_to_clipboard(self, request, data):
def _deserialize_to_clipboard(self, request, data, is_placeholder):
"""
Restore clipboard by creating plugins from given data.
"""
Expand Down Expand Up @@ -142,12 +153,29 @@ def plugins_from_data(placeholder, parent, data):

clipboard = request.toolbar.clipboard
ref_plugin = clipboard.cmsplugin_set.first()
if ref_plugin is None:
if ref_plugin is None and is_placeholder is True:
# the clipboard is empty
root_plugin = add_plugin(clipboard, 'PlaceholderPlugin', language, name='clipboard')
else:
root_plugin=root_plugin.placeholder_ref
elif is_placeholder is True:
# remove old entries from the clipboard
root_plugin = ref_plugin.cms_placeholderreference
inst = ref_plugin.get_plugin_instance()[0]
inst.placeholder_ref.get_plugins().delete()
plugins_from_data(root_plugin.placeholder_ref, None, data['plugins'])
root_plugin=root_plugin.placeholder_ref
elif is_placeholder is None:
root_plugin=clipboard
if ref_plugin:
inst = ref_plugin.get_plugin_instance()[0]
inst.placeholder.get_plugins().delete()
plugins_from_data(root_plugin, None, data['plugins'])

def response_change(self, request, obj):
#Little hack to reload the clipboard modified in Django administration and the sideframe Django-CMS.
#TODO find a better way to reload clipboard potentially with request Ajax
#js = static_with_version('cms/js/dist/bundle.admin.base.min.js')
if "restore_clipboard" in request.POST:
return HttpResponse(
format_html('<script type="text/javascript">window.parent.CMS.API.Helpers.reloadBrowser();</script>'))
return super().response_change(request, obj)

4 changes: 4 additions & 0 deletions docs/source/clipboard.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ Since the content of the clipboard is overridden by every operation which cuts o
plugins, **djangocms-cascade** offers some functionality to persist the clipboard's content. To do
this, locate **Persited Clipboard Content** in Django's administration backend.

It is also possible to copy plugins or a single plugin with children without reference to a
placeholder, these can also be copied into a persistent clipboard. They will have to be placed in
their proper locations with the djangocms-cascade logic that will tell you where they can be placed.

|persist-clipboard|

.. |persist-clipboard| image:: _static/persist-clipboard.png
Expand Down
1 change: 1 addition & 0 deletions tests/templates/testing.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@

<body>
{% placeholder "Main Content" %}
{% placeholder "Main Content2" %}
</body>
</html>
2 changes: 1 addition & 1 deletion tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def setUp(self):
self.home_page.set_as_homepage()

self.placeholder = self.home_page.placeholders.get(slot='Main Content')

self.placeholder2 = self.home_page.placeholders.get(slot='Main Content2')
self.request = self.get_request(self.home_page, 'en')
self.admin_site = admin.sites.AdminSite()

Expand Down
Loading