diff --git a/korektury/admin.py b/korektury/admin.py index 3888dc4c..aad8fd20 100644 --- a/korektury/admin.py +++ b/korektury/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin from reversion.admin import VersionAdmin -from korektury.models import KorekturovanePDF +from korektury.models import KorekturovanePDF, Oprava, KorekturaTag from django.core.mail import EmailMessage from django.urls import reverse @@ -62,3 +62,11 @@ Korekturovátko ).send() admin.site.register(KorekturovanePDF, KorekturovanePDFAdmin) + + +class OpravaAdmin(admin.ModelAdmin): + model = Oprava + filter_horizontal = ("informovani_orgove", "tagy",) + +admin.site.register(Oprava, OpravaAdmin) +admin.site.register(KorekturaTag) diff --git a/korektury/api/__init__.py b/korektury/api/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/korektury/api/apps.py b/korektury/api/apps.py new file mode 100644 index 00000000..be74e478 --- /dev/null +++ b/korektury/api/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + + +class ApiConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'korektury.api' + label = 'korektury_api' # Protože jedno api už máme. diff --git a/korektury/api/migrations/__init__.py b/korektury/api/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/korektury/api/urls.py b/korektury/api/urls.py new file mode 100644 index 00000000..eb74d90f --- /dev/null +++ b/korektury/api/urls.py @@ -0,0 +1,9 @@ +from django.urls import path +from personalni.utils import org_required +from . import views + +urlpatterns = [ + path('/stav', org_required(views.korektury_stav_view), name='korektury_api_pdf_stav'), + path('oprava/stav', org_required(views.oprava_stav_view), name='korektury_api_oprava_stav'), + path('/opravy_a_komentare', org_required(views.opravy_a_komentare_view), name='korektury_api_opravy_a_komentare'), +] diff --git a/korektury/api/views.py b/korektury/api/views.py new file mode 100644 index 00000000..560abfad --- /dev/null +++ b/korektury/api/views.py @@ -0,0 +1,109 @@ +from django.http import HttpResponseForbidden, JsonResponse +from django.shortcuts import get_object_or_404 +from django.utils.html import linebreaks +from django.views.decorators.csrf import csrf_exempt + +from rest_framework import serializers + +from korektury.utils import send_email_notification_komentar +from korektury.models import Oprava, KorekturovanePDF, Komentar, KorekturaTag +from personalni.models import Organizator, Osoba + + +def korektury_stav_view(request, pdf_id: int, **kwargs): + q = request.POST + pdf = get_object_or_404(KorekturovanePDF, id=pdf_id) + status = q.get('state') + if status is not None: + assert status in KorekturovanePDF.STATUS.values + pdf.status = status + pdf.save() + return JsonResponse({'status': pdf.status}) + + +def oprava_stav_view(request, **kwargs): + q = request.POST + op_id_str = q.get('id') + assert op_id_str is not None + op_id = int(op_id_str) + op = get_object_or_404(Oprava, id=op_id) + status = q.get('action') + if status is not None: + assert status in Oprava.STATUS.values + op.status = status + op.save() + return JsonResponse({'status': op.status}) + +class KomentarSerializer(serializers.ModelSerializer): + class Meta: + model = Komentar + fields = '__all__' + + def to_representation(self, instance): + ret = super().to_representation(instance) + ret["autor"] = str(instance.autor) + ret["text"] = linebreaks(ret["text"], autoescape=True) # Autora není třeba escapovat, ten se vkládá jako text. + return ret + +class KorekturaTagSerializer(serializers.ModelSerializer): + class Meta: + model = KorekturaTag + fields = '__all__' + + +class OpravaSerializer(serializers.ModelSerializer): + class Meta: + model = Oprava + fields = '__all__' + + def to_representation(self, instance): + ret = super().to_representation(instance) + ret["komentare"] = [KomentarSerializer(komentar).data for komentar in instance.komentar_set.all()] + ret["tagy"] = [KorekturaTagSerializer(tag).data for tag in instance.tagy.all()] + return ret + + # komentar_set = serializers.ListField(child=KomentarSerializer()) + +def opravy_a_komentare_view(request, pdf_id: int, **kwargs): + if request.method == '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, + ) + + tagy_raw = q.get('tagy') + if tagy_raw != "": + tagy = list(map(int, tagy_raw.split(","))) + oprava.tagy.add(*KorekturaTag.objects.filter(id__in=tagy)) + Komentar.objects.create(oprava=oprava, autor=autor, text=text) + + + opravy = Oprava.objects.filter(pdf=pdf_id).all() + # 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]}) diff --git a/korektury/forms.py b/korektury/forms.py deleted file mode 100644 index 22c82818..00000000 --- a/korektury/forms.py +++ /dev/null @@ -1,14 +0,0 @@ -from django import forms - -class OpravaForm(forms.Form): - """ formulář k přidání opravy (:class:`korektury.models.Oprava`) """ - text = forms.CharField(max_length=256) - autor = forms.CharField(max_length=20) - x = forms.IntegerField() - y = forms.IntegerField() - scroll = forms.CharField(max_length=256) - pdf = forms.CharField(max_length=256) - img_id = forms.CharField(max_length=256) - id = forms.CharField(max_length=256) - action = forms.CharField(max_length=256) - diff --git a/korektury/migrations/0025_remove_oprava_autor_remove_oprava_text.py b/korektury/migrations/0025_remove_oprava_autor_remove_oprava_text.py new file mode 100644 index 00000000..82f23ba2 --- /dev/null +++ b/korektury/migrations/0025_remove_oprava_autor_remove_oprava_text.py @@ -0,0 +1,45 @@ +# Generated by Django 4.2.16 on 2024-12-12 10:25 + +from django.db import migrations + +import datetime +from django.utils import timezone + + +def oprava2komentar(apps, schema_editor): + Oprava = apps.get_model('korektury', 'Oprava') + Komentar = apps.get_model('korektury', 'Komentar') + + for o in Oprava.objects.all(): + Komentar.objects.create(oprava=o, text=o.text, autor=o.autor, cas=timezone.make_aware(datetime.datetime.fromtimestamp(0))) + +def komentar2oprava(apps, schema_editor): + Oprava = apps.get_model('korektury', 'Oprava') + Komentar = apps.get_model('korektury', 'Komentar') + + for o in Oprava.objects.all(): + k = Komentar.objects.filter(oprava=o).first() + o.text = k.text + o.autor = k.autor + o.save() + k.delete() + + + +class Migration(migrations.Migration): + + dependencies = [ + ('korektury', '0024_vic_orgu_k_pdf'), + ] + + operations = [ + migrations.RunPython(oprava2komentar, komentar2oprava), + migrations.RemoveField( + model_name='oprava', + name='autor', + ), + migrations.RemoveField( + model_name='oprava', + name='text', + ), + ] diff --git a/korektury/migrations/0026_oprava_informovani_orgove.py b/korektury/migrations/0026_oprava_informovani_orgove.py new file mode 100644 index 00000000..23da722f --- /dev/null +++ b/korektury/migrations/0026_oprava_informovani_orgove.py @@ -0,0 +1,29 @@ +# Generated by Django 4.2.16 on 2025-02-11 14:28 + +from django.db import migrations, models + +def pridani_orgu(apps, _schema_editor): + Komentar = apps.get_model('korektury','Komentar') + for komentar in Komentar.objects.all(): + org = komentar.autor + if org is not None: + # Tohle jde asi udělat lépe než .all(…). Ale nejhorší na tom je, že .add(…) funguje jinak tady v migracích. + if org not in komentar.oprava.informovani_orgove.all(): + komentar.oprava.informovani_orgove.add(org) + + +class Migration(migrations.Migration): + + dependencies = [ + ('personalni', '0019_rename_upozorneni_resitel_upozornovat_na_opravy_reseni'), + ('korektury', '0025_remove_oprava_autor_remove_oprava_text'), + ] + + operations = [ + migrations.AddField( + model_name='oprava', + name='informovani_orgove', + field=models.ManyToManyField(blank=True, default=None, help_text='Orgové informovaní při přidání komentáře ke korektuře', related_name='informovan_o_opravach', to='personalni.organizator', verbose_name='Informovaní organizátoři'), + ), + migrations.RunPython(pridani_orgu, migrations.RunPython.noop), + ] diff --git a/korektury/migrations/0027_korekturatag_oprava_tagy.py b/korektury/migrations/0027_korekturatag_oprava_tagy.py new file mode 100644 index 00000000..c5445957 --- /dev/null +++ b/korektury/migrations/0027_korekturatag_oprava_tagy.py @@ -0,0 +1,27 @@ +# Generated by Django 4.2.16 on 2025-02-11 16:07 + +import colorfield.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('korektury', '0026_oprava_informovani_orgove'), + ] + + operations = [ + migrations.CreateModel( + name='KorekturaTag', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nazev', models.CharField(help_text='Název daného tagu, <20 znaků', max_length=20, verbose_name='název tagu')), + ('barva', colorfield.fields.ColorField(default='#FFFFFF', image_field=None, max_length=25, samples=None, verbose_name='barva daného tagu')), + ], + ), + migrations.AddField( + model_name='oprava', + name='tagy', + field=models.ManyToManyField(blank=True, default=None, to='korektury.korekturatag'), + ), + ] diff --git a/korektury/models.py b/korektury/models.py index 9ca40ba1..6da05b64 100644 --- a/korektury/models.py +++ b/korektury/models.py @@ -1,4 +1,7 @@ import os + +from colorfield.fields import ColorField + from django.db import models from django.urls import reverse from django.utils import timezone @@ -52,16 +55,13 @@ class KorekturovanePDF(models.Model): stran = models.IntegerField(u'počet stran', help_text='Počet stran PDF', default=0) - STATUS_PRIDAVANI = 'pridavani' - STATUS_ZANASENI = 'zanaseni' - STATUS_ZASTARALE = 'zastarale' - STATUS_CHOICES = ( - (STATUS_PRIDAVANI, u'Přidávání korektur'), - (STATUS_ZANASENI, u'Korektury jsou zanášeny'), - (STATUS_ZASTARALE, u'Stará verze, nekorigovat'), - ) - status = models.CharField(u'stav PDF',max_length=16, choices=STATUS_CHOICES, blank=False, - default = STATUS_PRIDAVANI) + + class STATUS(models.TextChoices): + PRIDAVANI = 'pridavani', 'Přidávání korektur' + ZANASENI = 'zanaseni', 'Korektury jsou zanášeny' + ZASTARALE = 'zastarale', 'Stará verze, nekorigovat' + + status = models.CharField(u'stav PDF',max_length=16, choices=STATUS.choices, blank=False, default = STATUS.PRIDAVANI) poslat_mail = models.BooleanField('Poslat mail o novém PDF', default=True, help_text='Určuje, zda se má o nově nahraném PDF poslat e-mail do mam-org. Při upravování existujícího souboru už nemá žádný vliv.', @@ -134,6 +134,14 @@ class KorekturovanePDF(models.Model): return reverse('korektury', kwargs={'pdf': self.id}) +class KorekturaTag(models.Model): + nazev = models.CharField("název tagu", blank = False, max_length=20, help_text="Název daného tagu, <20 znaků") + barva = ColorField("barva daného tagu", default="#FFFFFF") + + def __str__(self): + return self.nazev + + @reversion.register(ignore_duplicates=True) class Oprava(models.Model): class Meta: @@ -152,32 +160,22 @@ class Oprava(models.Model): x = models.IntegerField(u'x-ová souřadnice bugu') y = models.IntegerField(u'y-ová souřadnice bugu') - STATUS_K_OPRAVE = 'k_oprave' - STATUS_OPRAVENO = 'opraveno' - STATUS_NENI_CHYBA = 'neni_chyba' - STATUS_K_ZANESENI = 'k_zaneseni' - STATUS_CHOICES = ( - (STATUS_K_OPRAVE, u'K opravě'), - (STATUS_OPRAVENO, u'Opraveno'), - (STATUS_NENI_CHYBA, u'Není chyba'), - (STATUS_K_ZANESENI, u'K zanesení do TeXu'), - ) - status = models.CharField(u'stav opravy',max_length=16, choices=STATUS_CHOICES, blank=False, - default = STATUS_K_OPRAVE) + class STATUS(models.TextChoices): + K_OPRAVE = 'k_oprave', 'K opravě' + OPRAVENO = 'opraveno', 'Opraveno' + NENI_CHYBA = 'neni_chyba', 'Není chyba' + K_ZANESENI = 'k_zaneseni', 'K zanesení do TeXu' - autor = models.ForeignKey(Organizator, blank = True, - help_text='Autor opravy', - null = True, on_delete=models.SET_NULL) - - text = models.TextField(u'text opravy',blank = True, help_text='Text opravy') + status = models.CharField(u'stav opravy',max_length=16, choices=STATUS.choices, blank=False, default = STATUS.K_OPRAVE) -# def __init__(self,dictionary): -# for k,v in dictionary.items(): -# setattr(self,k,v) - - def __str__(self): - return '{} od {}: {}'.format(self.status,self.autor,self.text) + informovani_orgove = models.ManyToManyField( + Organizator, blank=True, default=None, + verbose_name='Informovaní organizátoři', + help_text="Orgové informovaní při přidání komentáře ke korektuře", + related_name='informovan_o_opravach', + ) + tagy = models.ManyToManyField(KorekturaTag, blank=True, default=None,) @reversion.register(ignore_duplicates=True) @@ -203,5 +201,7 @@ class Komentar(models.Model): def __str__(self): return '{} od {}: {}'.format(self.cas,self.autor,self.text) - - + def save(self, *args, **kwargs): + super().save(*args, **kwargs) + if self.autor is not None: + self.oprava.informovani_orgove.add(self.autor) diff --git a/korektury/static/korektury/imgs/hide.png b/korektury/static/korektury/imgs/hide.png index bcaeec04..e58ddb03 100644 Binary files a/korektury/static/korektury/imgs/hide.png and b/korektury/static/korektury/imgs/hide.png differ diff --git a/korektury/static/korektury/opraf.css b/korektury/static/korektury/opraf.css index d5b21da2..7a2896e2 100644 --- a/korektury/static/korektury/opraf.css +++ b/korektury/static/korektury/opraf.css @@ -1,136 +1,227 @@ -body, -.adding{ - background: #f3f3f3; - color: black; -} -.comitting -{ - background: yellow; -} -.deprecated { - background: red; +.textzanaseni { display:none; } +.textzastarale { display:none; } +#prekomentar, #preoprava, #prepointer { display: none; } + +body { + &[data-status="pridavani"] { + background: #f3f3f3; + } + + &[data-status="zanaseni"] { + background: yellow; + + .textzanaseni { display: unset; } + } + + &[data-status="zastarale"] { + background: red; + + .textzastarale { display: unset; } + } } img{background:white;} /* Barvy korektur */ -.k_oprave { +[data-opravastatus="k_oprave"] { --rgb: 255, 0, 0; + + [value="k_oprave"] { display: none } + .komentovat_disabled { display: none } } -.opraveno { +[data-opravastatus="opraveno"] { --rgb: 0, 0, 255; + + [value="opraveno"] { display: none } + .komentovat { display: none } } -.neni_chyba { +[data-opravastatus="neni_chyba"] { --rgb: 128, 128, 128; + + [value="neni_chyba"] { display: none } + .komentovat { display: none } } -.k_zaneseni { +[data-opravastatus="k_zaneseni"] { --rgb: 0, 255, 0; + + [value="k_zaneseni"] { display: none } + .komentovat { display: none } } -.pointer-hi, +/* Skrývání korektur */ +[data-opravazobrazit="false"] { + .corr-body { display: none; } + .corr-buttons { display: none; } + .toggle-button { transform: rotate(180deg); } +} + +/* Tlačítko na aktualizaci */ + +#korektury-aktualizace { + position: absolute; + right: 10px; + top: 10px; + + border-radius: 10px; + + + /* copy-paste .button */ + margin: 10px 0 10px 0; + padding: 4px 0; /*vertikální centování textu*/ + text-align: center; + background-color: #e84e10; + color: #fffbf6; + font-size: 150%; + font-weight: bold; + font-variant: small-caps; + filter: drop-shadow(0px 5px 5px rgba(0, 0, 0, 0.4)); + + &:hover { + background-color: #df490e; + } +} + +/* Čára od textu k místu korektury */ .pointer{ position:absolute; - /*border-bottom-left-radius: 10px; */ - border-left: 2px solid yellow; - border-bottom: 2px solid yellow; - border-color: rgb(var(--rgb),var(--alpha)); + border-bottom-left-radius: 10px; + border-left: 1px solid rgb(var(--rgb),var(--alpha)); + border-bottom: 1px solid rgb(var(--rgb),var(--alpha)); + pointer-events: none; + + --alpha: 0.35; + + /* Zvýraznění čáry při najetí na korekturu */ + &[data-highlight="true"] { + border-width: 3px; + --alpha: 1; + } } -.pointer { - border-width: 1px; - --alpha: 0.35; -} - -.pointer-hi { - border-width: 3px; - --alpha: 1; -} - - - -.box:hover{ - border-width:3px; - margin: 0px; -} -.box { +/* Korektura samotná */ +.oprava { margin: 1px; background-color: white; - width:300px; - /*position:absolute;*/ + width: 300px; padding: 3px; - border: 2px solid black; + border: 2px solid rgb(var(--rgb)); border-radius: 10px; - border-color: rgb(var(--rgb)); + position: absolute; + + &:hover { + border-width:3px; + margin: 0; + } + + button, img { + border: 1px solid white; + background-color:transparent; + margin:0; + padding: 1px; + + &:hover { + border: 1px solid black; + } + } + + button img { pointer-events: none; } + + .corr-header { + overflow: auto; + } + + .author { + font-weight: bold; + float: left; + margin-top: 3px; + } + + .float-right{ + float:right; + } } + form { display:inline; } -.float-right{ - float:right; -} - +/* Zobrazované PDF */ .imgdiv { position:relative; - left:0px; - top:0px; + left:0; + top:0; } + +/* Přidávání korektury / úprava komentáře */ #commform-div { - display: none; position: absolute; background-color: white; - border: 1px solid; padding: 3px; - /* - width: 310; - height: 220; - */ z-index: 10; border: 4px solid red; border-radius: 10px; - background-color: white; opacity: 80%; } -.close-button{ - background-color: yellow; + +.korektury-tag { + border-radius: 5px; + margin: 2px; + padding: 2px; + + &[data-selected="false"] { opacity: 0.7; } +} + +/* Šipky na posouvání korektur */ +#korektury-sipky { + position: fixed; + bottom: 5px; + left: 5px; + + button, img { + border: 1px solid white; + background-color:transparent; + margin:0; + padding: 1px; + + border-radius: 5px; + + &:hover { + border: 1px solid black; + } + } + + button img { pointer-events: none; } + + #predchozi-korektura, #dalsi-korektura { + background-color: #EEEEEE; + } + + #predchozi-korektura-k-oprave, #dalsi-korektura-k-oprave { + background-color: #FF0000; + } + + #predchozi-korektura-k-zaneseni, #dalsi-korektura-k-zaneseni { + background-color: #00FF00; + } } -.box button, -.box img, -.box-done button, -.box-done img, -.box-ready button, -.box-ready img, -.box-wontfix button, -.box-wontfix img{ - border: 1px solid white; - background-color:transparent; - margin:0; - padding: 1px; -} -.box button:hover, -.box img:hover, -.box-done img:hover, -.box-done button:hover, -.box-ready img:hover, -.box-ready button:hover, -.box-wontfix img:hover, -.box-wontfix button:hover{ - border: 1px solid black; -} - -.comment hr { - height: 0px; -} - -.corr-header { - overflow: auto; -} - -.author { - font-weight: bold; - float: left; - margin-top: 3px; +/**** ROZLIŠENÍ MEZI LOKÁLNÍM, TESTOVACÍM A PRODUKČNÍM WEBEM ****/ +body.localweb, body.testweb, body.suprodweb { + &:before, &:after { + content: ""; + position: fixed; + width: 20px; + height: 100%; + top: 0; + z-index: -1000; + } + + &:before { left: 0; } + &:after { right: 0; } } +body.localweb { &:before, &:after { background: greenyellow; } } +body.testweb { &:before, &:after { background: darkorange; } } +body.suprodweb { &:before, &:after { background: red; } } +/****************************************************************/ diff --git a/korektury/static/korektury/opraf.js b/korektury/static/korektury/opraf.js index 61eb5ce9..3963c49c 100644 --- a/korektury/static/korektury/opraf.js +++ b/korektury/static/korektury/opraf.js @@ -1,283 +1,46 @@ +const W_SKIP = 10; +const H_SKIP = 5; +const POINTER_MIN_H = 30; + function place_comments_one_div(img_id, comments) { - var img = document.getElementById(img_id); - if( img == null ) { - return; + const img = document.getElementById("img-"+img_id); + if( img == null ) return; + const comments_sorted = comments.sort((a, b) => a.y - b.y); + + const par = img.parentNode; + const w = img.clientWidth; + + let bott_max = 0; + for (const oprava of comments_sorted) { + const x = oprava.x; + const y = oprava.y; + const htmlElement = oprava.htmlElement; + const pointer = oprava.pointer; + + par.appendChild(pointer); + par.appendChild(htmlElement); + + const delta_y = (y > bott_max) ? 0: bott_max - y + H_SKIP; + + pointer.style.left = x; + pointer.style.top = y; + pointer.style.width = w - x + W_SKIP; + pointer.style.height = POINTER_MIN_H + delta_y; + + htmlElement.style.left = w + W_SKIP; + htmlElement.style.top = y + delta_y; + + bott_max = Math.max(bott_max, htmlElement.offsetTop + htmlElement.offsetHeight + H_SKIP); // FIXME nemám páru, proč +H_SKIP funguje, ale opravuje to bug, že nově vytvořené korektury za sebou neměly mezeru } - var par = img.parentNode; - var w = img.clientWidth; - var h = img.clientHeight; - var w_skip = 10; - var h_skip = 5; - var pointer_min_h = 30; - var bott_max = 0; - var comments_sorted = comments.sort(function (a,b) { - return a[2] - b[2]; - //pokus o hezci kladeni poiteru, ale nic moc - if( a[3] < b[3] ) { - return (a[2] + pointer_min_h)- b[2]; - } else { - return (a[2] - pointer_min_h)- b[2]; - } - - }); - //console.log("w:" + w); - for (c in comments_sorted) { - var id = comments_sorted[c][0]; - var x = comments_sorted[c][1]; - var y = comments_sorted[c][2]; - - var el = document.getElementById(id); - var elp = document.getElementById(id + "-pointer"); - - if( el == null || elp == null ) { - continue; - } - - par.appendChild(elp); - par.appendChild(el); - - var delta_y = (y > bott_max) ? 0: bott_max - y + h_skip; - - elp.style.left = x; - elp.style.top = y ; - elp.style.width = w - x + w_skip; - elp.style.height = pointer_min_h + delta_y; - elp.img_id = img_id; - el.img_id = img_id; - - el.style.position = 'absolute'; - el.style.left = w + w_skip; - el.style.top = y + delta_y; - - var bott = el.offsetTop + el.offsetHeight; - bott_max = ( bott_max > bott ) ? bott_max : bott; - - //console.log( "par.w:" + par.style.width); - - } - if( par.offsetHeight < bott_max ) { - //par.style.height = bott_max; - //alert("preteklo to:"+ par.offsetHeight +",mx:" + bott_max ); - par.style.height = bott_max; - - } + if (par.offsetHeight < bott_max) par.style.height = bott_max; } function place_comments() { - for (var i=0; i < comments.length-1; i++) { - place_comments_one_div(comments[i][0], comments[i][1]) + for (let [img_id, opravy] of Object.entries(comments)) { + place_comments_one_div(img_id, opravy) } } -// ctrl-enter submits form -function textarea_onkey(ev) -{ - //console.log("ev:" + ev.keyCode + "," + ev.ctrlKey); - if( (ev.keyCode == 13 || ev.keyCode == 10 ) && ev.ctrlKey ) { - var form = document.getElementById('commform'); - if( form ) { - save_scroll(form); - //form.action =''; - form.submit(); - } - return true; - } - return false; -} - -//hide comment form -function close_commform() { - var formdiv = document.getElementById('commform-div'); - if( formdiv == null ) { - alert("form null"); - return true; - } - formdiv.style.display = 'none'; - return false; -} - -// show comment form, when clicked to image -function img_click(element, ev) { - var body_class = document.body.className; - switch(body_class){ - case "comitting": - if (!confirm("Právě jsou zanášeny korektury, opravdu chcete přidat novou?")) - return; - break; - case "deprecated": - if (!confirm("Toto PDF je již zastaralé, opravdu chcete vytvořit korekturu?")) - return; - break; - } - - var dx, dy; - var par = element.parentNode; - if( ev.pageX != null ) { - dx = ev.pageX - par.offsetLeft; - dy = ev.pageY - par.offsetTop; - } else { //IE - dx = ev.offsetX; - dy = ev.offsetY; - } - var img_id = element.id; - if( element.img_id != null ) { - // click was to '-pointer' - img_id = element.img_id; - } - return show_form(img_id, dx, dy, '', '', '', ''); -} -// hide or show text of correction -function toggle_visibility(oid){ - var buttondiv = document.getElementById(oid+'-buttons') - var text = document.getElementById(oid+'-body'); - if (text.style.display == 'none'){ - text.style.display = 'block'; - buttondiv.style.display = 'inline-block'; - }else { - text.style.display = 'none'; - buttondiv.style.display = 'none'; - } - for (var i=0;i