Dynamické přidávání korektur a komentářů a úprava komentářů

This commit is contained in:
Jonas Havelka 2025-02-11 12:00:47 +01:00
parent 9ccacaecb5
commit 6eb4633af0
6 changed files with 106 additions and 61 deletions

View file

@ -58,8 +58,40 @@ class OpravaSerializer(serializers.ModelSerializer):
# komentar_set = serializers.ListField(child=KomentarSerializer()) # komentar_set = serializers.ListField(child=KomentarSerializer())
def opravy_a_komentare_view(request, pdf_id: int, **kwargs): def opravy_a_komentare_view(request, pdf_id: int, **kwargs):
if request.method == 'POST':
q = request.POST q = request.POST
x = int(q.get('x'))
y = int(q.get('y'))
img_id = int(q.get('img_id'))
oprava_id = int(q.get('oprava_id'))
komentar_id = int(q.get('komentar_id'))
text = q.get('text')
# prirazeni autora podle prihlaseni
autor_user = request.user
# pokud existuje ucet (user), ale neni to organizator = 403
autor = Organizator.objects.filter(osoba__user=autor_user).first()
if komentar_id != -1:
komentar = get_object_or_404(Komentar, id=komentar_id)
komentar.text = text
komentar.autor = autor
komentar.save()
else:
if oprava_id != -1:
oprava = get_object_or_404(Oprava, id=oprava_id)
else:
pdf = get_object_or_404(KorekturovanePDF, id=pdf_id)
oprava = Oprava.objects.create(
pdf=pdf,
strana=img_id,
x=x,
y=y,
)
Komentar.objects.create(oprava=oprava, autor=autor, text=text)
opravy = Oprava.objects.filter(pdf=pdf_id).all() opravy = Oprava.objects.filter(pdf=pdf_id).all()
# Serializovat list je prý security vulnerability, tedy je přidán slovník pro bezpečnost # Serializovat list je prý security vulnerability, tedy je přidán slovník pro bezpečnost
return JsonResponse({"context": [OpravaSerializer(oprava).data for oprava in opravy]}) return JsonResponse({"context": [OpravaSerializer(oprava).data for oprava in opravy]})

View file

@ -1,64 +1,75 @@
<div id="commform-div" style="display: none"> <div id="commform-div" style="display: none">
<form action='' id="commform" method="POST">
{% csrf_token %}
<input size="24" name="au" value="{{user.first_name}} {{user.last_name}}" readonly/> <input size="24" name="au" value="{{user.first_name}} {{user.last_name}}" readonly/>
<input type=submit value="Oprav!"/> <button id="commform-submit">Oprav!</button>
<button type="button" onclick="close_commform()">Zavřít</button> <button id="commform-close">Zavřít</button>
<br/> <br/>
<textarea id="commform-text" cols=40 rows=10 name="txt"></textarea> <textarea id="commform-text" cols=40 rows=10 name="txt"></textarea>
<br/> <br/>
<input type="hidden" size="3" id="commform-x" name="x"/>
<input type="hidden" size="3" id="commform-y" name="y"/>
<input type="hidden" size="3" id="commform-img-id" name="img-id"/>
<input type="hidden" size="3" id="commform-id" name="id"/>
<input type="hidden" size="3" id="commform-action" name="action"/>
</form>
</div> </div>
<script> <script>
const commform = document.getElementById('commform'); class _CommForm {
commform._div = document.getElementById('commform-div'); constructor() {
commform._text = document.getElementById('commform-text'); this.div = document.getElementById('commform-div');
commform._x = document.getElementById('commform-x'); this.text = document.getElementById('commform-text');
commform._y = document.getElementById('commform-y'); const submit_button = document.getElementById('commform-submit');
commform._imgID = document.getElementById('commform-img-id'); const close_button = document.getElementById('commform-close');
commform._id = document.getElementById('commform-id');
commform._action = document.getElementById('commform-action');
// ctrl-enter submits form // ctrl-enter submits form
commform._text.addEventListener("keydown", ev => { this.text.addEventListener("keydown", ev => {
if (ev.code === "Enter" && ev.ctrlKey) commform.submit(); if (ev.code === "Enter" && ev.ctrlKey) this.submit();
}); });
//hide comment form close_button.addEventListener("click", _ => { this.close(); });
function close_commform() { submit_button.addEventListener("click", _ => { this.submit(); });
commform._div.style.display = 'none';
return false;
} }
//fill up comment form and show him
function show_form(img_id, dx, dy, id, text, action) {
const img = document.getElementById("img-" + img_id);
if (commform._div.style.display !== 'none' && commform._text.value !== "" && !confirm("Zavřít předchozí okénko přidávání korektury / editace komentáře?")) return 1; // schová commform
close() { this.div.style.display = 'none'; }
// zobrazí commform (bez vyplňování)
_show(img_id, x, y) {
this.div.style.display = 'block';
this.div.style.left = x;
this.div.style.top = y;
const img = document.getElementById("img-" + img_id);
img.parentNode.appendChild(commform.div);
this.text.focus();
}
// fill up comment form and show him
show(img_id, x, y, text, oprava_id=-1, komentar_id=-1) {
if (this.div.style.display !== 'none' && this.text.value !== "" && !confirm("Zavřít předchozí okénko přidávání korektury / editace komentáře?")) return;
// set hidden values // set hidden values
commform._x.value = dx; this.x = x;
commform._y.value = dy; this.y = y;
commform._imgID.value = img_id; this.imgID = img_id;
commform._id.value = id; this.oprava_id = oprava_id;
commform._action.value = action; this.komentar_id = komentar_id;
commform._text.value = text; this.text.value = text;
// show form // show form
commform._div.style.display = 'block'; this._show(img_id, x, y);
commform._div.style.left = dx;
commform._div.style.top = dy;
img.parentNode.appendChild(commform._div);
commform._text.focus();
return true;
} }
submit() {
const data = new FormData(CSRF_FORM);
data.append('x', this.x);
data.append('y', this.y);
data.append('img_id', this.imgID);
data.append('oprava_id', this.oprava_id);
data.append('komentar_id', this.komentar_id);
data.append('text', this.text.value);
update_all({method: 'POST', body: data}, true, () => {this.close()});
}
}
const commform = new _CommForm();
</script> </script>

View file

@ -74,7 +74,7 @@
// show comment form when 'update-comment' button pressed // show comment form when 'update-comment' button pressed
#update_comment() { #update_comment() {
return show_form(this.oprava.img_id, this.oprava.x, this.oprava.y, this.id, this.#text.textContent, 'update-comment'); return commform.show(this.oprava.img_id, this.oprava.x, this.oprava.y, this.#text.textContent, -1, this.id);
} }
#delete_comment() { #delete_comment() {

View file

@ -121,7 +121,7 @@
} }
// show comment form, when 'comment' button pressed // show comment form, when 'comment' button pressed
#comment() { return show_form(this.img_id, this.x, this.y, this.id, "", "comment"); } #comment() { commform.show(this.img_id, this.x, this.y, "", this.id); }
#zmenStavKorektury(event) { #zmenStavKorektury(event) {
const data = new FormData(CSRF_FORM); const data = new FormData(CSRF_FORM);

View file

@ -43,8 +43,8 @@
dx = ev.offsetX; dx = ev.offsetX;
dy = ev.offsetY; dy = ev.offsetY;
} }
const img_id = image.id; const img_id = image.id.substring(4);
return show_form(img_id, dx, dy, '', '', ''); commform.show(img_id, dx, dy, '');
}); });
} }
</script> </script>

View file

@ -11,12 +11,14 @@
* *
* @param {RequestInit} data * @param {RequestInit} data
* @param {Boolean} catchError * @param {Boolean} catchError
* @param pri_uspechu Akce, která se má provést při úspěchu (speciálně zavřít formulář)
*/ */
function update_all(data={}, catchError=true) { // FIXME není mi jasné, zda v {} nemá být `cache: "no-store"`, aby prohlížeč necachoval GET. function update_all(data={}, catchError=true, pri_uspechu=null) { // FIXME není mi jasné, zda v {} nemá být `cache: "no-store"`, aby prohlížeč necachoval GET.
fetch('{% url "korektury_api_opravy_a_komentare" pdf.id %}', data) fetch('{% url "korektury_api_opravy_a_komentare" pdf.id %}', data)
.then(response => { .then(response => {
if (!response.ok && catchError) {alert('Něco se nepovedlo:' + response.statusText);} if (!response.ok && catchError) {alert('Něco se nepovedlo:' + response.statusText);}
else response.json().then(data => { else response.json().then(data => {
if (pri_uspechu) pri_uspechu();
for (const oprava_data of data["context"]) { for (const oprava_data of data["context"]) {
const oprava = Oprava.update_or_create(oprava_data); const oprava = Oprava.update_or_create(oprava_data);
for (const komentar_data of oprava_data["komentare"]) { for (const komentar_data of oprava_data["komentare"]) {