Live editor finished

- Edit and saves entries in webpage
- Autosaves every 10 seconds
- Don't save if no changes
- django-reversion working
This commit is contained in:
Felipe Martín 2016-03-06 13:07:48 +01:00
parent 9d6302ead3
commit 086f3529f4
4 changed files with 91 additions and 7 deletions

View File

@ -32,6 +32,8 @@ class EntryAdmin(VersionAdmin):
prepopulated_fields = {"slug": ("title",)}
ignore_duplicate_revisions = True
suit_form_tabs = (
('general', _('General')),
('content', _('Content')),

View File

@ -1,6 +1,6 @@
from django.conf.urls import url
from .views import ListView, EntryView, SearchView, RSSView
from .views import ListView, EntryView, EntryLiveEditView, SearchView, RSSView
urlpatterns = [
@ -22,6 +22,13 @@ urlpatterns = [
EntryView.as_view(),
name='item'
),
# Live edit entry
url(
r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<slug>[\w\-]+)/edit/$',
EntryLiveEditView.as_view(),
name='item-liveedit'
),
# RSS
url(
r'^rss\.xml$',

View File

@ -1,9 +1,13 @@
# -*- coding: utf-8 -*-
import json
from django.core.urlresolvers import reverse
from django.http import Http404, HttpResponseRedirect, HttpResponse
from django.shortcuts import render
from django.template.loader import get_template
from django.template import RequestContext
from django.http import Http404, HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
import fmartingrcom.apps.blog.utils as blog_utils
from .models import Entry
@ -57,6 +61,35 @@ class EntryView(View):
return render(request, self.template, self.data)
class EntryLiveEditView(View):
@method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs):
return super(EntryLiveEditView, self).dispatch(*args, **kwargs)
def post(self, request, year, month, day, slug):
if not request.user.is_superuser:
return HttpResponse(status=403)
try:
filters = {
'slug': slug,
'date__year': int(year),
'date__month': int(month),
'date__day': int(day),
}
item = Entry.objects.get(**filters)
except Entry.DoesNotExist:
raise Http404
data = json.loads(request.body)
if 'content' in data:
item.content = data['content']
item.save()
return HttpResponse(status=200)
return HttpResponse(status=204)
class SearchView(ListView):
template = 'blog/search.jinja'

View File

@ -26,6 +26,9 @@
'saveButton': document.querySelector('.blog-entry [data-button="save"]'),
'entryContent': document.querySelector('.blog-entry .content')
}
this.endpoints = {
'liveEdit': document.querySelector('.blog-entry').getAttribute('data-liveedit-url')
}
this.editorOptions = {
'class': 'liveeditor',
'editor': this.UI.entryContent
@ -44,9 +47,11 @@
_this.showButton('save');
});
this.UI.saveButton.addEventListener('click', function(event){
_this.unloadEditor();
_this.hideButton('save');
_this.showButton('liveEdit');
_this.save(function(success){
_this.unloadEditor();
_this.hideButton('save');
_this.showButton('liveEdit');
});
});
}
@ -59,11 +64,47 @@
}
LiveEditCtrl.prototype.loadEditor = function() {
this._lastSavedContent = this.UI.entryContent.innerHTML
this.editor = new Pen(this.editorOptions);
this.startAutoSave();
}
LiveEditCtrl.prototype.unloadEditor = function() {
this.editor.destroy();
this.stopAutoSave();
}
LiveEditCtrl.prototype.save = function(callback) {
var _this = this,
r = new XMLHttpRequest();
r.open("POST", this.endpoints.liveEdit, true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) {
_this._lastSavedContent = _this.UI.entryContent.innerHTML;
if (callback) return callback(true, r.status);
}
};
data = {
'content': this.UI.entryContent.innerHTML
}
r.send(JSON.stringify(data));
}
LiveEditCtrl.prototype.startAutoSave = function() {
var _this = this;
this._autoSaveInterval = setInterval(function(){
if (_this._lastSavedContent != _this.UI.entryContent.innerHTML) {
console.log('Auto saved');
_this.save();
} else {
console.log('Not autosaving because content is the same')
}
}, 10000);
}
LiveEditCtrl.prototype.stopAutoSave = function() {
clearInterval(this._autoSaveInterval);
}
window.LiveEditCtrl = new LiveEditCtrl(window);
@ -72,7 +113,8 @@
{% endblock %}
{% block content %}
<article class="blog-entry {% if item.draft %}draft{% endif %}">
<article class="blog-entry {% if item.draft %}draft{% endif %}"
{% if request.user.is_superuser %}data-liveedit-url="{{ item.get_absolute_url() }}edit/"{% endif %}>
<h1 class="entry-title">
<a class="dark" href="#">{{ item.title }}</a>
</h1>