mirror of
https://github.com/Findus23/RPGnotes.git
synced 2024-09-19 15:43:45 +02:00
send drafts to server
This commit is contained in:
parent
b34b7ea78d
commit
c9eed87644
9 changed files with 112 additions and 4 deletions
5
common/admin.py
Normal file
5
common/admin.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from common.models import Draft
|
||||||
|
|
||||||
|
admin.site.register(Draft)
|
27
common/migrations/0001_initial.py
Normal file
27
common/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# Generated by Django 4.0.5 on 2022-07-03 22:19
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Draft',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('description_md', models.TextField(blank=True, verbose_name='Description')),
|
||||||
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('last_modified', models.DateTimeField(auto_now=True)),
|
||||||
|
('author', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='drafts', to=settings.AUTH_USER_MODEL, verbose_name='Player')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
0
common/migrations/__init__.py
Normal file
0
common/migrations/__init__.py
Normal file
|
@ -1,3 +1,4 @@
|
||||||
from .descriptionmodel import DescriptionModel
|
from .descriptionmodel import DescriptionModel
|
||||||
from .nameslugmodel import NameSlugModel
|
from .nameslugmodel import NameSlugModel
|
||||||
from .historymodel import HistoryModel
|
from .historymodel import HistoryModel
|
||||||
|
from .draft import Draft
|
||||||
|
|
21
common/models/draft.py
Normal file
21
common/models/draft.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
from django.db import models
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from rpg_notes.settings import AUTH_USER_MODEL
|
||||||
|
|
||||||
|
|
||||||
|
class Draft(models.Model):
|
||||||
|
description_md = models.TextField(_("Description"), blank=True)
|
||||||
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
last_modified = models.DateTimeField(auto_now=True)
|
||||||
|
author = models.ForeignKey(
|
||||||
|
AUTH_USER_MODEL, on_delete=models.PROTECT,
|
||||||
|
related_name="drafts", verbose_name=_("Player")
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
# todo: add which object this is a draft of
|
||||||
|
return f"{self.created}: {self.author}"
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
get_latest_by = "created"
|
7
common/urls.py
Normal file
7
common/urls.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from common import views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("api/draft/save", views.save_draft, name="save_draft"),
|
||||||
|
]
|
|
@ -1,10 +1,13 @@
|
||||||
from django.http import HttpResponse
|
import json
|
||||||
|
|
||||||
|
from django.http import HttpResponse, HttpRequest, HttpResponseBadRequest, JsonResponse
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.views.decorators.http import condition
|
from django.views.decorators.http import condition
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from ipware import get_client_ip
|
from ipware import get_client_ip
|
||||||
from sentry_sdk import last_event_id
|
from sentry_sdk import last_event_id
|
||||||
|
|
||||||
|
from common.models import Draft
|
||||||
from rpg_notes.secrets import SENTRY_DSN
|
from rpg_notes.secrets import SENTRY_DSN
|
||||||
from utils.assets import get_css, get_file_hash
|
from utils.assets import get_css, get_file_hash
|
||||||
|
|
||||||
|
@ -17,7 +20,7 @@ class LanguageSelectView(TemplateView):
|
||||||
template_name = "common/languageselect.jinja"
|
template_name = "common/languageselect.jinja"
|
||||||
|
|
||||||
|
|
||||||
def print_ip(request):
|
def print_ip(request: HttpRequest) -> HttpResponse:
|
||||||
client_ip, is_routable = get_client_ip(request)
|
client_ip, is_routable = get_client_ip(request)
|
||||||
return HttpResponse(repr(client_ip), content_type="text/plain")
|
return HttpResponse(repr(client_ip), content_type="text/plain")
|
||||||
|
|
||||||
|
@ -26,6 +29,28 @@ def calc_etag(*args, **kwargs):
|
||||||
return get_file_hash()[:6]
|
return get_file_hash()[:6]
|
||||||
|
|
||||||
|
|
||||||
|
def save_draft(request: HttpRequest) -> HttpResponse:
|
||||||
|
body = json.loads(request.body)
|
||||||
|
draft_md = body.get("draft_md", None)
|
||||||
|
if not draft_md:
|
||||||
|
return HttpResponseBadRequest()
|
||||||
|
try:
|
||||||
|
last_draft = Draft.objects.filter(author=request.user).latest()
|
||||||
|
if last_draft.description_md == draft_md:
|
||||||
|
return JsonResponse({
|
||||||
|
"message": "saved (unchanged)"
|
||||||
|
})
|
||||||
|
except Draft.DoesNotExist:
|
||||||
|
pass
|
||||||
|
draft = Draft()
|
||||||
|
draft.description_md = draft_md
|
||||||
|
draft.author = request.user
|
||||||
|
draft.save()
|
||||||
|
return JsonResponse({
|
||||||
|
"message": "saved"
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
@condition(etag_func=calc_etag)
|
@condition(etag_func=calc_etag)
|
||||||
def debug_css(request):
|
def debug_css(request):
|
||||||
css, source_map = get_css(debug=True)
|
css, source_map = get_css(debug=True)
|
||||||
|
|
|
@ -19,6 +19,7 @@ urlpatterns = [
|
||||||
path('note/', include("notes.urls")),
|
path('note/', include("notes.urls")),
|
||||||
path('loot/', include("loot.urls")),
|
path('loot/', include("loot.urls")),
|
||||||
path('search/', include("search.urls")),
|
path('search/', include("search.urls")),
|
||||||
|
path('', include("common.urls")),
|
||||||
path('', include("campaigns.urls"))
|
path('', include("campaigns.urls"))
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
|
||||||
const ids = ["id_description_md"];
|
const ids = ["id_description_md"];
|
||||||
ids.forEach(function (id) {
|
ids.forEach(function (id) {
|
||||||
const element = document.getElementById(id);
|
const element = document.getElementById(id);
|
||||||
|
@ -33,7 +33,28 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||||
second: '2-digit',
|
second: '2-digit',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
});
|
inputStyle: "contenteditable",
|
||||||
|
status: ["lines", "words", "cursor", "saveStatus"],
|
||||||
|
});
|
||||||
|
window.editor = easyMDE
|
||||||
|
setInterval(function () {
|
||||||
|
const content = easyMDE.value();
|
||||||
|
fetch("/api/draft/save", {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
"draft_md": content
|
||||||
|
}),
|
||||||
|
headers: {'X-CSRFToken': csrftoken},
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
easyMDE.updateStatusBar("saveStatus", data.message)
|
||||||
|
setTimeout(e => easyMDE.updateStatusBar("saveStatus", ""), 5000)
|
||||||
|
}).catch(e => {
|
||||||
|
easyMDE.updateStatusBar("saveStatus", "error saving draft")
|
||||||
|
})
|
||||||
|
|
||||||
|
}, 1000 * 30)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue