Tagy u korektur

This commit is contained in:
Jonas Havelka 2025-02-11 18:54:15 +01:00
parent 326be3eaa0
commit 773cd7d419
10 changed files with 101 additions and 5 deletions

View file

@ -1,6 +1,6 @@
from django.contrib import admin
from reversion.admin import VersionAdmin
from korektury.models import KorekturovanePDF, Oprava
from korektury.models import KorekturovanePDF, Oprava, KorekturaTag
from django.core.mail import EmailMessage
from django.urls import reverse
@ -66,6 +66,7 @@ admin.site.register(KorekturovanePDF, KorekturovanePDFAdmin)
class OpravaAdmin(admin.ModelAdmin):
model = Oprava
filter_horizontal = ("informovani_orgove", )
filter_horizontal = ("informovani_orgove", "tagy",)
admin.site.register(Oprava, OpravaAdmin)
admin.site.register(KorekturaTag)

View file

@ -6,7 +6,7 @@ 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
from korektury.models import Oprava, KorekturovanePDF, Komentar, KorekturaTag
from personalni.models import Organizator, Osoba
@ -45,6 +45,12 @@ class KomentarSerializer(serializers.ModelSerializer):
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
@ -53,6 +59,7 @@ class OpravaSerializer(serializers.ModelSerializer):
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())
@ -82,6 +89,7 @@ def opravy_a_komentare_view(request, pdf_id: int, **kwargs):
if oprava_id != -1:
oprava = get_object_or_404(Oprava, id=oprava_id)
else:
tagy = list(map(int, q.get('tagy').split(",")))
pdf = get_object_or_404(KorekturovanePDF, id=pdf_id)
oprava = Oprava.objects.create(
pdf=pdf,
@ -89,6 +97,7 @@ def opravy_a_komentare_view(request, pdf_id: int, **kwargs):
x=x,
y=y,
)
oprava.tagy.add(*KorekturaTag.objects.filter(id__in=tagy))
Komentar.objects.create(oprava=oprava, autor=autor, text=text)

View file

@ -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'),
),
]

View file

@ -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
@ -131,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:
@ -164,6 +175,8 @@ class Oprava(models.Model):
related_name='informovan_o_opravach',
)
tagy = models.ManyToManyField(KorekturaTag, blank=True, default=None,)
@reversion.register(ignore_duplicates=True)
class Komentar(models.Model):

View file

@ -137,6 +137,14 @@ form {
opacity: 80%;
}
.korektury-tag {
border-radius: 5px;
margin: 2px;
padding: 2px;
&[data-selected="false"] { opacity: 0.5; }
}
/**** ROZLIŠENÍ MEZI LOKÁLNÍM, TESTOVACÍM A PRODUKČNÍM WEBEM ****/
body.localweb, body.testweb, body.suprodweb {

View file

@ -5,6 +5,11 @@
<br/>
<textarea id="commform-text" cols=40 rows=10 name="txt"></textarea>
<br/>
<span id="commform-tagy">
{% for tag in tagy %}
<button type="button" class="korektury-tag" value="{{tag.id}}" data-selected="false" style="background: {{ tag.barva }};">{{tag.nazev}}</button>
{% endfor %}
</span>
</div>
<script>
@ -14,6 +19,7 @@
this.text = document.getElementById('commform-text');
this.submit_button = document.getElementById('commform-submit');
const close_button = document.getElementById('commform-close');
this.tagy = document.getElementById('commform-tagy');
// ctrl-enter submits form
@ -23,6 +29,12 @@
close_button.addEventListener("click", _ => { this.close(); });
this.submit_button.addEventListener("click", _ => { this.submit(); });
for (const tag of this.tagy.getElementsByTagName("button")) tag.addEventListener("click", event => { this.toggle_tag(event); });
}
toggle_tag(event) {
const button = event.target;
button.dataset.selected = String(button.dataset.selected === "false");
}
@ -54,6 +66,7 @@
this.text.value = text;
// show form
if (oprava_id === -1 && komentar_id === -1) this.tagy.style.display = 'unset'; else this.tagy.style.display = 'none';
this._show(img_id, x, y);
}
@ -65,6 +78,13 @@
data.append('img_id', this.imgID);
data.append('oprava_id', this.oprava_id);
data.append('komentar_id', this.komentar_id);
if (this.oprava_id === -1 && this.komentar_id === -1) {
const tagy = [];
for (const tag of this.tagy.getElementsByTagName("button")) {
if (tag.dataset.selected !== "false") tagy.push(tag.value);
}
data.append('tagy', String(tagy));
}
data.append('text', this.text.value);

View file

@ -11,6 +11,10 @@
{# data-opravastatus='{{o.status}}' #}
data-opravazobrazit='true'
>
<div class='corr-tagy'>
{# {% for tag in o.tagy %} <span style="background:{{ tag.barva }}>{{ tag.text }}<span/> #}
</div>
<div class='corr-body'>
{# {% for k in o.komentare %} {% include "korektury/korekturovatko/__komentar.html" %} <hr> {% endfor %} #}
</div>
@ -65,7 +69,7 @@
else return new Oprava(oprava_data);
}
#komentare;
#komentare; #tagy;
htmlElement; pointer;
id; x; y; img_id; zobrazit = true; {# oprava_data; #}
@ -73,6 +77,7 @@
this.htmlElement = preoprava.cloneNode(true);
this.pointer = prepointer.cloneNode(true);
this.#komentare = this.htmlElement.getElementsByClassName('corr-body')[0];
this.#tagy = this.htmlElement.getElementsByClassName('corr-tagy')[0];
this.id = oprava_data['id'];
this.htmlElement.id = 'op' + this.id;
@ -103,6 +108,14 @@
update(oprava_data) {
{# this.oprava_data = oprava_data; #}
this.set_status(oprava_data['status']);
this.#tagy.innerHTML = "";
for (const tag of oprava_data["tagy"]) {
const span = document.createElement("span");
span.innerHTML = tag["nazev"];
span.classList.add("korektury-tag");
span.style.backgroundColor = tag["barva"];
this.#tagy.appendChild(span);
}
return this;
};

View file

@ -5,7 +5,7 @@ from django.http import HttpResponseForbidden
from django.db.models import Count,Q
from .utils import send_email_notification_komentar
from .models import Oprava,Komentar,KorekturovanePDF, Organizator
from .models import Oprava, Komentar, KorekturovanePDF, Organizator, KorekturaTag
class KorekturyListView(generic.ListView):
model = KorekturovanePDF
@ -150,5 +150,7 @@ class KorekturyView(generic.TemplateView):
context['opravy'] = opravy
context['zasluhy'] = zasluhy
context['tagy'] = KorekturaTag.objects.all()
return context

View file

@ -129,6 +129,8 @@ INSTALLED_APPS = (
'rest_framework',
'rest_framework.authtoken',
'colorfield',
# MaMweb
'mamweb',
'seminar',

View file

@ -25,6 +25,7 @@ django_reverse_admin # Lepší handlování OneToOne fieldů v adminu
django-rest-framework
django-webpack-loader
django-rest-polymorphic
django-colorfield # Field pro ukládání barvy (např. tagy v korekturovátku)
# debug tools/extensions