Compare commits

..

No commits in common. "c41281378bf45eb69cc0d97af193e16a6908be61" and "c75697b221a5c39e1bca6d7d17dceab5f4349fcb" have entirely different histories.

9 changed files with 126 additions and 74 deletions

View file

@ -35,6 +35,7 @@
for (let [_, opravy] of Object.entries(comments)) { for (let [_, opravy] of Object.entries(comments)) {
for (const oprava of opravy) { for (const oprava of opravy) {
if (stav == null || oprava.status === stav) { if (stav == null || oprava.status === stav) {
console.log(oprava, oprava.htmlElement.getBoundingClientRect().y);
const y = oprava.htmlElement.getBoundingClientRect().y; const y = oprava.htmlElement.getBoundingClientRect().y;
if (y >= -1) { if (y >= -1) {
if (dalsi) { if (dalsi) {
@ -43,6 +44,7 @@
return; return;
} }
} else { } else {
console.log(predchozi);
if (predchozi !== null) predchozi.htmlElement.scrollIntoView(); else alert("Výše už není žádná taková korektura."); if (predchozi !== null) predchozi.htmlElement.scrollIntoView(); else alert("Výše už není žádná taková korektura.");
return; return;
} }

View file

@ -35,7 +35,6 @@
#autor; #text; #autor; #text;
htmlElement; htmlElement;
id; oprava; {# komentar_data; #} id; oprava; {# komentar_data; #}
autor;
/** /**
* *
@ -67,11 +66,7 @@
this.set_text(komentar_data['text']); this.set_text(komentar_data['text']);
}; };
set_autor(autor) { set_autor(autor) {this.#autor.textContent=autor;};
this.#autor.textContent=autor;
this.autor = autor;
};
set_text(text) { set_text(text) {
this.#text.innerHTML=text; this.#text.innerHTML=text;
}; };

View file

@ -151,10 +151,7 @@
fetch('{% url "korektury_api_oprava_stav" %}', {method: 'POST', body: data}) fetch('{% url "korektury_api_oprava_stav" %}', {method: 'POST', body: data})
.then(response => { .then(response => {
if (!response.ok) {alert('Něco se nepovedlo:' + response.statusText);} if (!response.ok) {alert('Něco se nepovedlo:' + response.statusText);}
else response.json().then(data => { else response.json().then(data => this.set_status(data['status']));
this.set_status(data['status']);
updatuj_pocty_stavu();
});
}) })
.catch(error => {alert('Něco se nepovedlo:' + error);}); .catch(error => {alert('Něco se nepovedlo:' + error);});
} }

View file

@ -3,7 +3,7 @@
<img <img
id='img-{{i}}' id='img-{{i}}'
width='1021' height='1448' width='1021' height='1448'
src='/media/korektury/img/{{korekturovanepdf.get_prefix}}-{{i}}.png' src='/media/korektury/img/{{img_prefix}}-{{i}}.png'
alt='Strana {{ i|add:1 }}' alt='Strana {{ i|add:1 }}'
class="strana" class="strana"
/> />
@ -14,9 +14,6 @@
<script> <script>
// Mapování stránka -> korektury // Mapování stránka -> korektury
/**
* @type {Object.<number, Array<Oprava>>}
*/
const comments = { const comments = {
{% for s in img_indexes %} {% for s in img_indexes %}
{{s}}: []{% if not forloop.last %},{% endif %} {{s}}: []{% if not forloop.last %},{% endif %}

View file

@ -18,7 +18,7 @@
* @param pri_uspechu Akce, která se má provést při úspěchu (speciálně zavřít formulář) * @param pri_uspechu Akce, která se má provést při úspěchu (speciálně zavřít formulář)
*/ */
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. 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" korekturovanepdf.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 => {
@ -30,8 +30,6 @@
} }
} }
updatuj_pocty_stavu();
updatuj_pocty_zasluh();
place_comments(); place_comments();
}); });
}) })

View file

@ -3,33 +3,26 @@ Zobrazit:
id="k_oprave_checkbox" id="k_oprave_checkbox"
name="k_oprave_checkbox" name="k_oprave_checkbox"
onchange="toggle_corrections('k_oprave')" checked> onchange="toggle_corrections('k_oprave')" checked>
<label for="k_oprave_checkbox">K opravě (<span id="k_oprave_pocet"></span>)</label> <label for="k_oprave_checkbox">K opravě ({{k_oprave_cnt}})</label>
<input type="checkbox" <input type="checkbox"
id="opraveno_checkbox" id="opraveno_checkbox"
name="opraveno_checkbox" name="opraveno_checkbox"
onchange="toggle_corrections('opraveno')" checked> onchange="toggle_corrections('opraveno')" checked>
<label for="opraveno_checkbox">Opraveno (<span id="opraveno_pocet"></span>)</label> <label for="opraveno_checkbox">Opraveno ({{opraveno_cnt}})</label>
<input type="checkbox" <input type="checkbox"
id="neni_chyba_checkbox" id="neni_chyba_checkbox"
name="neni_chyba_checkbox" name="neni_chyba_checkbox"
onchange="toggle_corrections('neni_chyba')" checked> onchange="toggle_corrections('neni_chyba')" checked>
<label for="neni_chyba_checkbox">Není chyba (<span id="neni_chyba_pocet"></span>)</label> <label for="neni_chyba_checkbox">Není chyba ({{neni_chyba_cnt}})</label>
<input type="checkbox" <input type="checkbox"
id="k_zaneseni_checkbox" id="k_zaneseni_checkbox"
name="k_zaneseni_checkbox" name="k_zaneseni_checkbox"
onchange="toggle_corrections('k_zaneseni')" checked> onchange="toggle_corrections('k_zaneseni')" checked>
<label for="k_zaneseni_checkbox">K zanesení (<span id="k_zaneseni_pocet"></span>)</label> <label for="k_zaneseni_checkbox">K zanesení ({{k_zaneseni_cnt}})</label>
<hr/> <hr/>
<script> <script>
const spany_s_pocty_stavu = {
'k_oprave': document.getElementById('k_oprave_pocet'),
'opraveno': document.getElementById('opraveno_pocet'),
'neni_chyba': document.getElementById('neni_chyba_pocet'),
'k_zaneseni': document.getElementById('k_zaneseni_pocet'),
}
function toggle_corrections(aclass) function toggle_corrections(aclass)
{ {
const stylesheets = document.styleSheets; const stylesheets = document.styleSheets;
@ -55,14 +48,4 @@ Zobrazit:
} }
place_comments(); place_comments();
} }
function updatuj_pocty_stavu() {
const pocty_stavu = {};
for (const stav of Object.keys(spany_s_pocty_stavu)) pocty_stavu[stav] = 0;
for (const oprava of Object.values(opravy)) {
if (!(oprava.status in pocty_stavu)) pocty_stavu[oprava.status] = 0;
pocty_stavu[oprava.status] += 1;
}
for (let [stav, pocet] of Object.entries(pocty_stavu)) spany_s_pocty_stavu[stav].innerText = pocet;
}
</script> </script>

View file

@ -1,13 +1,13 @@
<h4>Změnit stav PDF:</h4> <h4>Změnit stav PDF:</h4>
<i>Aktuální: {{korekturovanepdf.status}}</i> <i>Aktuální: {{pdf.status}}</i>
<br> <br>
<form method="post" id="PDFSTAV_FORM"> <form method="post" id="PDFSTAV_FORM">
{% csrf_token %} {% csrf_token %}
<input type="radio" name="state" value="{{ korekturovanepdf.STATUS.PRIDAVANI }}" {% if korekturovanepdf.status == korekturovanepdf.STATUS.PRIDAVANI %} checked {% endif %}>Přidávání korektur <input type="radio" name="state" value="{{ pdf.STATUS.PRIDAVANI }}" {% if pdf.status == pdf.STATUS.PRIDAVANI %} checked {% endif %}>Přidávání korektur
<br> <br>
<input type="radio" name="state" value="{{ korekturovanepdf.STATUS.ZANASENI }}" {% if korekturovanepdf.status == korekturovanepdf.STATUS.ZANASENI %} checked {% endif %}>Zanášení korektur <input type="radio" name="state" value="{{ pdf.STATUS.ZANASENI }}" {% if pdf.status == pdf.STATUS.ZANASENI %} checked {% endif %}>Zanášení korektur
<br> <br>
<input type="radio" name="state" value="{{ korekturovanepdf.STATUS.ZASTARALE }}" {% if korekturovanepdf.status == korekturovanepdf.STATUS.ZASTARALE %} checked {% endif %}>Zastaralé, nekorigovat <input type="radio" name="state" value="{{ pdf.STATUS.ZASTARALE }}" {% if pdf.status == pdf.STATUS.ZASTARALE %} checked {% endif %}>Zastaralé, nekorigovat
<br> <br>
<input type='submit' value='Změnit stav PDF'/> <input type='submit' value='Změnit stav PDF'/>
</form> </form>
@ -21,7 +21,7 @@
* @param {Boolean} catchError * @param {Boolean} catchError
*/ */
function fetchStav(data, catchError=true) { function fetchStav(data, catchError=true) {
fetch("{% url 'korektury_api_pdf_stav' korekturovanepdf.id %}", data fetch("{% url 'korektury_api_pdf_stav' pdf.id %}", data
) )
.then(response => { .then(response => {
if (!response.ok) { if (catchError) alert("Něco se nepovedlo:" + response.statusText);} if (!response.ok) { if (catchError) alert("Něco se nepovedlo:" + response.statusText);}

View file

@ -6,19 +6,19 @@
<link rel="stylesheet" title="opraf-css" type="text/css" media="screen, projection" href="{% static "korektury/opraf.css"%}?version=1" /> <link rel="stylesheet" title="opraf-css" type="text/css" media="screen, projection" href="{% static "korektury/opraf.css"%}?version=1" />
<link href="{% static 'css/rozliseni.css' %}?version=1" rel="stylesheet"> <link href="{% static 'css/rozliseni.css' %}?version=1" rel="stylesheet">
<script src="{% static "korektury/opraf.js"%}?version=1"></script> <script src="{% static "korektury/opraf.js"%}?version=1"></script>
<title>Korektury {{korekturovanepdf.nazev}}</title> <title>Korektury {{pdf.nazev}}</title>
</head> </head>
<body class="{{ LOCAL_TEST_PROD }}web" data-status="{{ korekturovanepdf.status }}"> <body class="{{ LOCAL_TEST_PROD }}web" data-status="{{ pdf.status }}" onload='place_comments()'>
<h1>Korektury {{korekturovanepdf.nazev}}</h1> <h1>Korektury {{pdf.nazev}}</h1>
<h2 class="textzanaseni"> Probíhá zanášení korektur, zvažte, zda chcete přidávat nové </h2> <h2 class="textzanaseni"> Probíhá zanášení korektur, zvažte, zda chcete přidávat nové </h2>
<h2 class="textzastarale"> Toto PDF je již zastaralé, nepřidávejte nové korektury </h2> <h2 class="textzastarale"> Toto PDF je již zastaralé, nepřidávejte nové korektury </h2>
<i>{{korekturovanepdf.komentar}}</i> <i>{{pdf.komentar}}</i>
<br> <br>
<i>Klikni na chybu, napiš komentář</i> | <i>Klikni na chybu, napiš komentář</i> |
<a href="{{korekturovanepdf.pdf.url}}">stáhnout PDF (bez korektur)</a> | <a href="{{pdf.pdf.url}}">stáhnout PDF (bez korektur)</a> |
<a href="../">seznam souborů</a> | <a href="../">seznam souborů</a> |
<a href="/admin/korektury/korekturovanepdf/">Spravovat PDF</a> | <a href="/admin/korektury/korekturovanepdf/">Spravovat PDF</a> |
<a href="../help">nápověda</a> | <a href="../help">nápověda</a> |
@ -35,27 +35,10 @@
<hr/> <hr/>
<p> <p>
Děkujeme opravovatelům: <span id="pocty_autoru"></span></p> Děkujeme opravovatelům:
{% for z in zasluhy %}
{{z.autor}} ({{z.pocet}}){% if not forloop.last %},{% endif %}
{% endfor %}</p>
<hr> <hr>
<script>
const span_s_pocty_autoru = document.getElementById("pocty_autoru")
function updatuj_pocty_zasluh() {
const pocty_autoru = {};
for (let komentar of Object.values(komentare)) {
if (!(komentar.autor in pocty_autoru)) pocty_autoru[komentar.autor] = 0;
pocty_autoru[komentar.autor] += 1;
}
const setrizene = [];
for (const keyval of Object.entries(pocty_autoru)) setrizene.push(keyval);
setrizene.sort(function(a, b) {return a[1] - b[1];});
let ans = "";
for (let [autor, pocet] of setrizene) ans += `, ${autor} (${pocet})`;
span_s_pocty_autoru.innerHTML = ans.substring(2);
}
</script>
</body> </body>
</html> </html>

View file

@ -1,7 +1,11 @@
from django.shortcuts import get_object_or_404, render
from django.views import generic from django.views import generic
from django.conf import settings
from django.http import HttpResponseForbidden
from django.db.models import Count,Q from django.db.models import Count,Q
from .models import Oprava, KorekturovanePDF, KorekturaTag from .utils import send_email_notification_komentar
from .models import Oprava, Komentar, KorekturovanePDF, Organizator, KorekturaTag
class KorekturyListView(generic.ListView): class KorekturyListView(generic.ListView):
model = KorekturovanePDF model = KorekturovanePDF
@ -46,14 +50,107 @@ class KorekturySeskupeneListView(KorekturyAktualniListView):
return reversed(sorted(qs, key=lambda it: it.cislo_a_tema)) return reversed(sorted(qs, key=lambda it: it.cislo_a_tema))
### Korektury ### Korektury
class KorekturyView(generic.DetailView): class KorekturyView(generic.TemplateView):
model = KorekturovanePDF model = Oprava
pk_url_kwarg = "pdf"
template_name = 'korektury/korekturovatko/htmlstrana.html' template_name = 'korektury/korekturovatko/htmlstrana.html'
def setup(self, request, *args, **kwargs):
super().setup(request, *args, **kwargs)
self.pdf_id = self.kwargs["pdf"]
self.pdf = get_object_or_404(KorekturovanePDF, id=self.pdf_id)
def post(self, request, *args, **kwargs):
q = request.POST
# 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 not autor:
return HttpResponseForbidden()
action = q.get('action')
if (action == ''): # Přidej
x = int(q.get('x'))
y = int(q.get('y'))
text = q.get('txt')
strana = int(q.get('img-id')[4:])
op = Oprava(x=x,y=y, strana=strana, pdf=self.pdf)
op.save()
kom = Komentar(oprava=op,autor=autor,text=text)
kom.save()
send_email_notification_komentar(op, autor, request)
elif (action == 'del'):
id = int(q.get('id'))
op = Oprava.objects.get(id=id)
for k in Komentar.objects.filter(oprava=op):
k.delete()
op.delete()
elif action in Oprava.STATUS.values:
id = int(q.get('id'))
op = Oprava.objects.get(id=id)
op.status = action
op.save()
elif (action == 'comment'):
id = int(q.get('id'))
op = Oprava.objects.get(id=id)
text = q.get('txt')
kom = Komentar(oprava=op,autor=autor,text=text)
kom.save()
send_email_notification_komentar(op, autor, request)
elif (action == 'update-comment'):
id = int(q.get('id'))
kom = Komentar.objects.get(id=id)
text = q.get('txt')
kom.text = text
kom.autor = autor
kom.save()
elif (action == 'del-comment'):
id = int(q.get('id'))
kom = Komentar.objects.get(id=id)
kom.delete()
elif (action == 'set-state'):
status = q.get('state')
assert status in KorekturovanePDF.STATUS.values
self.pdf.status = status
self.pdf.save()
context = self.get_context_data()
context['autor'] = autor
return render(request, 'korektury/korekturovatko/htmlstrana.html', context)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context['img_indexes'] = range(self.object.stran) context['pdf'] = self.pdf
context['img_prefix'] = self.pdf.get_prefix()
context['img_path'] = settings.KOREKTURY_IMG_DIR
context['img_indexes'] = range(self.pdf.stran)
opravy = Oprava.objects.filter(pdf=self.pdf_id)
zasluhy = {}
for o in opravy:
o.komentare = o.komentar_set.all()
for k in o.komentare:
if k.autor in zasluhy:
zasluhy[k.autor] += 1
else:
zasluhy[k.autor] = 1
zasluhy = [
{'autor': jmeno, 'pocet': pocet}
for (jmeno, pocet) in zasluhy.items()
]
zasluhy.sort(key=lambda z: z['pocet'], reverse=True)
strany = set(o.strana for o in opravy)
opravy_na_stranu = [{'strana': s, 'op_id': opravy.filter(strana=s)} for s in strany]
context['opravy_strany'] = opravy_na_stranu
context['k_oprave_cnt'] = opravy.filter(status='k_oprave').count()
context['opraveno_cnt'] = opravy.filter(status='opraveno').count()
context['neni_chyba_cnt'] = opravy.filter(status='neni_chyba').count()
context['k_zaneseni_cnt'] = opravy.filter(status='k_zaneseni').count()
context['opravy'] = opravy
context['zasluhy'] = zasluhy
context['tagy'] = KorekturaTag.objects.all() context['tagy'] = KorekturaTag.objects.all()
return context return context