general: add possibility to restore snapshots from history (#21602)

This commit is contained in:
Frédéric Péters 2018-04-02 12:07:34 +02:00
parent 43da526e69
commit 0a610fd2a2
6 changed files with 78 additions and 2 deletions

View File

@ -32,7 +32,7 @@ from django.contrib.auth.models import Group
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist, ValidationError, PermissionDenied
from django.core import serializers
from django.db import models
from django.db import models, transaction
from django.db.models.base import ModelBase
from django.db.models import Max
from django.forms import models as model_forms
@ -392,6 +392,12 @@ class PageSnapshot(models.Model):
page.load_serialized_cells(self.serialization['cells'])
return page
def restore(self):
with transaction.atomic():
page = Page.load_serialized_page(self.serialization)
page.load_serialized_cells(self.serialization['cells'])
return page
class CellMeta(MediaDefiningClass, ModelBase):
pass

View File

@ -21,6 +21,7 @@
<li>{{ snapshot.timestamp }}, {{ snapshot.comment }}
{% if snapshot.user %} ({{ snapshot.user.get_full_name }}){% endif %}
<a href="{% url 'combo-snapshot-view' pk=snapshot.id %}">{% trans "view" %}</a>
<a href="{% url 'combo-manager-snapshot-restore' page_pk=view.page.id pk=snapshot.id %}" rel="popup">{% trans "restore" %}</a>
</li>
{% endfor %}
</ul>

View File

@ -0,0 +1,30 @@
{% extends "combo/manager_base.html" %}
{% load i18n %}
{% load cells %}
{% load thumbnail %}
{% block appbar %}
<h2>{% trans 'Snapshot Restore' %} - {{ page.title }}</h2>
{% endblock %}
{% block breadcrumb %}
{{ block.super }}
<a href="{% url 'combo-manager-page-view' pk=page.id %}">{% trans 'Page' %} - {{page.title }}</a>
<a href="{% url 'combo-manager-page-history' pk=page.id %}">{% trans "History" %}</a>
<a href="{% url 'combo-manager-snapshot-restore' page_pk=page.id pk=object.id %}">{% trans "Snapshot Restore" %}</a>
{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
<p>
{% blocktrans with date=object.timestamp|date:"DATETIME_FORMAT" snapshot_id=object.id%}
Are you sure you want to restore snapshot #{{snapshot_id}} of the page (dated {{date}})?
{% endblocktrans %}
</p>
<div class="buttons">
<button class="submit-button">{% trans 'Restore' %}</button>
<a class="cancel" href="{% url 'combo-manager-page-history' pk=page.id %}">{% trans 'Cancel' %}</a>
</div>
{% endblock %}

View File

@ -55,6 +55,8 @@ urlpatterns = [
name='combo-manager-page-export'),
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,
name='combo-manager-snapshot-restore'),
url(r'^pages/(?P<page_pk>\w+)/add-cell-to-(?P<ph_key>[\w_-]+)/(?P<cell_type>\w+)/(?P<variant>[\w-]+)/$',
views.page_add_cell,
name='combo-manager-page-add-cell'),

View File

@ -20,6 +20,7 @@ import os
import ckeditor
from django.conf import settings
from django.contrib import messages
from django.core.files.storage import default_storage
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.core.urlresolvers import reverse, reverse_lazy
@ -27,6 +28,8 @@ from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import redirect
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import force_text
from django.utils.formats import date_format
from django.utils.timezone import localtime
from django.views.decorators.csrf import requires_csrf_token
from django.views.generic import (TemplateView, RedirectView, DetailView,
CreateView, UpdateView, ListView, DeleteView, FormView)
@ -308,6 +311,29 @@ class PageHistoryView(ListView):
page_history = PageHistoryView.as_view()
class SnapshotRestoreView(DetailView):
http_method_names = ['get', 'post']
model = PageSnapshot
template_name = 'combo/snapshot_restore.html'
def get_context_data(self, **kwargs):
context = super(SnapshotRestoreView, self).get_context_data(**kwargs)
context['page'] = Page.objects.get(id=self.kwargs['page_pk'])
return context
def post(self, request, *args, **kwargs):
snapshot = self.get_object()
datetime_str = date_format(localtime(snapshot.timestamp), format='DATETIME_FORMAT')
page = self.get_object().restore()
PageSnapshot.take(page, request=self.request,
comment=_('restored snapshot from %s') % datetime_str)
messages.info(self.request,
_('Snapshot from %s has been restored.') % datetime_str)
return HttpResponseRedirect(reverse('combo-manager-page-view', kwargs={'pk': self.kwargs['page_pk']}))
snapshot_restore = SnapshotRestoreView.as_view()
class PageAddCellView(RedirectView):
permanent = False

View File

@ -825,6 +825,17 @@ def test_page_versionning(app, admin_user):
app.get('/logout/')
resp3 = app.get(json_cell_url, status=403)
# restore a snapshot
app = login(app)
resp = resp.click('restore', index=6)
resp = resp.form.submit()
resp = resp.follow()
resp2 = resp.click('see online')
assert resp2.body.index('Foobar1') < resp2.body.index('Foobar2') < resp2.body.index('Foobar3')
# clean it up
Page.snapshots.all().delete()
assert JsonCell.objects.count() == 1
assert Page.objects.count() == 1
assert TextCell.objects.count() == 3
assert JsonCell.objects.count() == 0