page: add a duplicate action (#24526)

This commit is contained in:
Lauréline Guérin 2019-10-22 14:58:02 +02:00
parent 09507f8988
commit 6be400fcfc
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
8 changed files with 129 additions and 1 deletions

View File

@ -319,3 +319,7 @@ class Map(CellBase):
ctx['group_markers'] = self.group_markers
ctx['marker_behaviour_onclick'] = self.marker_behaviour_onclick
return ctx
def duplicate_m2m(self, new_cell):
# set layers
new_cell.layers.set(self.layers.all())

View File

@ -436,6 +436,27 @@ class Page(models.Model):
cells = CellBase.get_cells(page_id=self.id)
return max([self.last_update_timestamp] + [x.last_update_timestamp for x in cells])
def duplicate(self):
# clone current page
new_page = copy.deepcopy(self)
new_page.pk = None
# set title
new_page.title = _('Copy of %s') % self.title
# reset snapshot
new_page.snapshot = None
# set order
new_page.order = self.order + 1
# store new page
new_page.save()
# set groups
new_page.groups.set(self.groups.all())
for cell in self.get_cells():
cell.duplicate(page_target=new_page)
return new_page
class PageSnapshot(models.Model):
page = models.ForeignKey(Page, on_delete=models.SET_NULL, null=True)
@ -737,6 +758,24 @@ class CellBase(six.with_metaclass(CellMeta, models.Model)):
def import_subobjects(self, cell_json):
pass
def duplicate(self, page_target=None):
# clone current cell
new_cell = copy.deepcopy(self)
new_cell.pk = None
# set page
new_cell.page = page_target or self.page
# store new cell
new_cell.save()
# set groups
new_cell.groups.set(self.groups.all())
if hasattr(self, 'duplicate_m2m'):
self.duplicate_m2m(new_cell)
return new_cell
@register_cell_class
class TextCell(CellBase):
text = RichTextField(_('Text'), blank=True, null=True)

View File

@ -12,6 +12,7 @@
<li><a href="{% url 'combo-manager-page-history' pk=object.id %}">{% trans 'history' %}</a></li>
<li><a download href="{% url 'combo-manager-page-export' pk=object.id %}">{% trans 'export' %}</a></li>
<li><a rel="popup" href="{% url 'combo-manager-page-add-child' pk=object.id %}">{% trans 'add a child page' %}</a></li>
<li><a href="{% url 'combo-manager-page-duplicate' pk=object.id %}">{% trans 'Duplicate' %}</a></li>
<li><a rel="popup" href="{% url 'combo-manager-page-delete' pk=object.id %}">{% trans 'delete' %}</a></li>
</ul>
</span>

View File

@ -54,6 +54,8 @@ urlpatterns = [
url(r'^pages/(?P<pk>\w+)/export$', views.page_export,
name='combo-manager-page-export'),
url(r'^pages/(?P<pk>\w+)/add/$', views.page_add_child, name='combo-manager-page-add-child'),
url(r'^pages/(?P<pk>\w+)/duplicate$', views.page_duplicate,
name='combo-manager-page-duplicate'),
url(r'^pages/(?P<pk>\w+)/history$', views.page_history,
name='combo-manager-page-history'),
url(r'^pages/(?P<page_pk>\w+)/history/(?P<pk>\w+)/$', views.snapshot_restore,

View File

@ -325,6 +325,19 @@ class PageExportView(DetailView):
page_export = PageExportView.as_view()
class PageDuplicateView(RedirectView):
permanent = False
def get_redirect_url(self, pk):
page = Page.objects.get(pk=pk)
new_page = page.duplicate()
messages.info(self.request, _('Page %s has been duplicated.') % page.title)
return reverse('combo-manager-page-view', kwargs={'pk': new_page.pk})
page_duplicate = PageDuplicateView.as_view()
class PageHistoryView(ListView):
model = PageSnapshot
template_name = 'combo/page_history.html'

View File

@ -440,6 +440,19 @@ def test_site_export_import(app, admin_user):
resp = resp.form.submit()
assert 'File is not in the expected JSON format.' in resp.text
def test_duplicate_page(app, admin_user):
page = Page.objects.create(title='One', slug='one', template_name='standard')
TextCell.objects.create(page=page, placeholder='content', text='Foobar', order=0)
app = login(app)
resp = app.get('/manage/pages/%s/' % page.pk)
resp = resp.click('Duplicate')
new_page = Page.objects.latest('pk')
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/' % new_page.pk)
def test_add_edit_cell(app, admin_user):
Page.objects.all().delete()
page = Page(title='One', slug='one', template_name='standard')

View File

@ -392,3 +392,13 @@ def test_get_geojson_properties(app, layer, user):
features = json.loads(resp.text)['features']
assert len(features[0]['properties']['display_fields']) == 1
assert features[0]['properties']['layer']['properties'] == ['id']
def test_duplicate(layer):
page = Page.objects.create(title='xxx', slug='new', template_name='standard')
cell = Map.objects.create(page=page, placeholder='content', order=0, public=True, title='Map')
layer.save()
cell.layers.add(layer)
new_cell = cell.duplicate()
assert list(new_cell.layers.all()) == [layer]

View File

@ -9,7 +9,7 @@ from django.test import override_settings
from django.test.client import RequestFactory
from django.utils.six import StringIO
from django.utils.timezone import now
from combo.data.models import Page, CellBase, TextCell, LinkCell
from combo.data.models import Page, PageSnapshot, CellBase, TextCell, LinkCell
from combo.data.management.commands.import_site import Command as ImportSiteCommand
from combo.data.management.commands.export_site import Command as ExportSiteCommand
from combo.manager.forms import PageVisibilityForm
@ -192,6 +192,52 @@ def test_import_export_pages_with_links():
assert CellBase.get_cells(page_id=new_page_1.id)[0].link_page_id == new_page_2.id
assert CellBase.get_cells(page_id=new_page_2.id)[0].link_page_id == new_page_1.id
def test_duplicate_page():
group1 = Group.objects.create(name='foobar')
group2 = Group.objects.create(name='fooblah')
page = Page.objects.create(
title='foo',
slug='foo',
description="Foo's page")
page.groups.set([group1, group2])
snapshot = PageSnapshot.objects.create(page=page)
page.snapshot = snapshot
page.save()
cell1 = TextCell.objects.create(page=page, text='foo1', order=0, placeholder='content')
cell1.groups.set([group1, group2])
cell2 = TextCell.objects.create(page=page, text='foo2', order=1, placeholder='content')
new_page = page.duplicate()
assert new_page.pk != page.pk
assert new_page.title == 'Copy of foo'
assert new_page.slug == page.slug
assert new_page.description == page.description
assert new_page.parent is None
assert new_page.snapshot is None
assert list(new_page.groups.all()) == [group1, group2]
assert len(new_page.get_cells()) == 2
new_cell1 = TextCell.objects.get(page=new_page, text='foo1')
new_cell2 = TextCell.objects.get(page=new_page, text='foo2')
assert new_cell1.pk != cell1.pk
assert new_cell1.text == cell1.text
assert new_cell1.placeholder == cell1.placeholder
assert list(new_cell1.groups.all()) == [group1, group2]
assert new_cell2.pk != cell2.pk
assert new_cell2.text == cell2.text
assert new_cell2.placeholder == cell2.placeholder
assert list(new_cell2.groups.all()) == []
parent = Page.objects.create()
page.parent = parent
page.save()
new_page = page.duplicate()
assert new_page.parent == parent
def test_next_previous():
Page.objects.all().delete()
page = Page()