add mini-live edit, for quick fixes
authorFrédéric Péters <fpeters@0d.be>
Thu, 4 Jun 2020 12:20:11 +0000 (14:20 +0200)
committerFrédéric Péters <fpeters@0d.be>
Thu, 4 Jun 2020 12:20:11 +0000 (14:20 +0200)
chloro/phyll/static/js/chloro.js [new file with mode: 0644]
chloro/phyll/templates/phyll/base.html
chloro/phyll/templates/phyll/note_detail.html
chloro/phyll/templates/phyll/note_form.html
chloro/phyll/urls.py
chloro/phyll/views.py

diff --git a/chloro/phyll/static/js/chloro.js b/chloro/phyll/static/js/chloro.js
new file mode 100644 (file)
index 0000000..9988be4
--- /dev/null
@@ -0,0 +1,27 @@
+$(function() {
+  $('div[contenteditable]').on('input', function(event) {
+    if (event.originalEvent.inputType == "insertParagraph") {
+      var sel = document.getSelection();
+      var anchorNode = sel.anchorNode;
+      var prev_p = sel.anchorNode.previousSibling;
+      if (prev_p.tagName != 'P') {
+        prev_p = $(prev_p).parents('p')[0];
+      }
+      var title_match = prev_p.innerText.match(/^(h[1-6]). /);
+      if (title_match) {
+        var title = document.createElement(title_match[1]);
+        title.innerHTML = prev_p.innerHTML;
+        title.textContent = title.textContent.slice(4);
+        prev_p.replaceWith(title);
+      }
+    }
+    return true;
+  });
+  $('#save').on('click', function() {
+    var text = $('div[contenteditable]')[0].innerHTML;
+    $.post('api-save/', {text: text}).fail(function() {
+      $('#save').css('background', 'red');
+    });
+    return false;
+  });
+});
index 54a1f4a..4f231e1 100644 (file)
@@ -1,4 +1,4 @@
-{% load i18n %}<!DOCTYPE html>
+{% load gadjo i18n %}<!DOCTYPE html>
 <html>
   <head>
     <meta charset="utf-8"/> <!-- 🌱 -->
@@ -6,6 +6,10 @@
     <title>{% block page-title %}Coin web de Frédéric Péters{% endblock %}</title>
     <link rel="stylesheet" type="text/css" href="/static/css/style.css">
     <link rel="alternate" type="application/atom+xml" title="Atom feed" href="/feed/atom" />
+    {% if request.user.is_staff %}
+    <script src="{% xstatic 'jquery' 'jquery.min.js' %}"></script>
+    <script src="/static/js/chloro.js"></script>
+    {% endif %}
     {% block bottom-head %}
     {% endblock %}
   </head>
index 240929b..d0b9bc3 100644 (file)
@@ -7,7 +7,8 @@
 {% block body %}
 <div>
 <h2>{{ object.title }}</h2>
-<div>{{ object.text|safe }}</div>
+<div {% if request.user.is_staff %}contenteditable="true"{% endif %}>{{ object.text|safe }}</div>
+{% if request.user.is_staff %}<button id="save">{% trans "Save" %}</button>{% endif %}
 
 <div class="meta">{{ object.creation_timestamp|date:"j E Y, H:i"|lower }}</div>
 </div>
index 3cc0ab5..927ae53 100644 (file)
@@ -2,7 +2,6 @@
 {% load gadjo i18n static %}
 
 {% block bottom-head %}
-<script src="{% xstatic 'jquery' 'jquery.min.js' %}"></script>
 <script src="{% static "ckeditor/ckeditor/ckeditor.js" %}"></script>
 <script type="text/javascript" src="{% static "ckeditor/ckeditor-init.js" %}"></script>
 {% endblock %}
index 37c2c64..d49525e 100644 (file)
@@ -38,6 +38,7 @@ urlpatterns = [
         r'^(?P<slug>[\w:-]+)/delete/$',
         staff_member_required(views.NoteDeleteView.as_view(), login_url='login'),
     ),
+    url(r'^(?P<slug>[\w:-]+)/api-save/$', staff_member_required(views.NoteApiSaveView.as_view())),
     url(r'^new-note/$', staff_member_required(views.NoteAddView.as_view(), login_url='login')),
     url(r'^feeds/(?P<sub>[\w:-]+)/atom$', views.AtomFeed()),
     url(r'^feed/atom$', views.AtomFeed()),
index 84b40e7..108a8ea 100644 (file)
@@ -19,8 +19,10 @@ import urllib.parse
 from django.conf import settings
 from django.contrib.syndication.views import Feed
 from django.core.exceptions import PermissionDenied
-from django.http import Http404
+from django.http import HttpResponse, Http404
 from django.utils.feedgenerator import Atom1Feed
+from django.views import View
+from django.views.decorators.csrf import csrf_exempt
 from django.views.generic import CreateView, DeleteView, DetailView, ListView, UpdateView, TemplateView
 
 from .models import Note
@@ -50,6 +52,20 @@ class NoteEditView(UpdateView):
     fields = ['title', 'slug', 'text', 'tags', 'published']
 
 
+class NoteApiSaveView(View):
+    http_method_names = ['post']
+
+    @csrf_exempt
+    def dispatch(self, *args, **kwargs):
+        return super().dispatch(*args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        note = Note.objects.get(slug=kwargs['slug'])
+        note.text = request.POST['text']
+        note.save()
+        return HttpResponse('ok')
+
+
 class NoteAddView(CreateView):
     model = Note
     fields = ['title', 'slug', 'text', 'tags', 'published']