diff --git a/mamweb/static/css/mamweb.css b/mamweb/static/css/mamweb.css index 7e7adbfd..09b870f4 100644 --- a/mamweb/static/css/mamweb.css +++ b/mamweb/static/css/mamweb.css @@ -51,7 +51,10 @@ a:focus, a:hover, a:active { color: #e84e10; text-decoration: none; } -a:focus a:hover + +img { + filter: drop-shadow(0px 3px 3px rgba(0, 0, 0, 0.4)); +} h1 { /*todo: odlišit 1 a 2 */ font-size: 200%; @@ -594,6 +597,14 @@ div.org_pole, div.rocnik_pole { text-align: center; } +div.cislo_pole { + display: inline-block; + width: 15%; + min-width: 165px; + text-align: center; + padding: 10px; +} + div.seznam_orgu h3 { text-align: center; margin-top: 10px; @@ -623,6 +634,11 @@ div.org_email { height: 298px; } +#archiv-rocnik.flip-card { + width: 144px; + height: 205px; +} + /* This container is needed to position the front and back side */ .flip-card-inner { position: relative; @@ -654,16 +670,13 @@ div.org_email { div.flip-card-foto img { width: 100%; height: 100%; - filter: drop-shadow(0px 3px 3px rgba(0, 0, 0, 0.4)); /* FIXME: obecně k obrázkům */ + } /* Style the back side */ .flip-card-back { - /*background-color: #e84e10; - color: #fffbf6; - background-color: #fdedd5;*/ background-color: #f9d59e; - color: black;/**/ + color: black; transform: rotateY(180deg); padding: 10px; padding-top: 20px; @@ -678,26 +691,35 @@ div.popis_rocniku { } -div.popis_rocniku a{ +div.popis_rocniku a, div.cislo_odkazy a { + font-weight: bold; color: black; } -div.popis_rocniku a:hover{ +div.popis_rocniku a:hover, +div.cislo_odkazy a:hover { color: #6f2509; } -/* graf na úvodní stránce */ - -a span.popup { - position: absolute; - visibility: hidden; +div.cislo_odkazy ul { + margin: 0px; + padding: 0px; } -a span.popup:hover { - visibility:visible; - top:37px; left:37px; +/* archiv ročník +div.cisla-v-rocniku { + font-weight: bold; + color: #6f2509; } +div.cislo-v-rocniku-blok { + display: inline-block; + width: 150px; + height: 220px; + text-align: center; +}*/ + + /* galerie */ /* velká fotka */ diff --git a/seminar/admin.py b/seminar/admin.py index 6a9dd815..edfbb595 100644 --- a/seminar/admin.py +++ b/seminar/admin.py @@ -35,6 +35,7 @@ class ProblemAdmin(PolymorphicParentModelAdmin): m.Tema, m.Clanek, m.Uloha, + m.Konfera, ] @admin.register(m.Tema) @@ -52,6 +53,11 @@ class UlohaAdmin(PolymorphicChildModelAdmin): base_model = m.Uloha show_in_index = True +@admin.register(m.Konfera) +class KonferaAdmin(PolymorphicChildModelAdmin): + base_model = m.Konfera + show_in_index = True + class TextAdminInline(admin.TabularInline): model = m.Text exclude = ['text_zkraceny_set','text_zkraceny'] @@ -82,7 +88,6 @@ class ReseniAdmin(ReverseModelAdmin): admin.site.register(m.Hodnoceni) admin.site.register(m.Pohadka) -admin.site.register(m.Konfera) admin.site.register(m.Obrazek) @@ -97,8 +102,6 @@ class TreeNodeAdmin(PolymorphicParentModelAdmin): m.CisloNode, m.MezicisloNode, m.TemaVCisleNode, - m.KonferaNode, - m.ClanekNode, m.UlohaZadaniNode, m.PohadkaNode, m.UlohaVzorakNode, @@ -136,16 +139,6 @@ class TemaVCisleNodeAdmin(PolymorphicChildModelAdmin): base_model = m.TemaVCisleNode show_in_index = True -@admin.register(m.KonferaNode) -class KonferaNodeAdmin(PolymorphicChildModelAdmin): - base_model = m.KonferaNode - show_in_index = True - -@admin.register(m.ClanekNode) -class ClanekNodeAdmin(PolymorphicChildModelAdmin): - base_model = m.ClanekNode - show_in_index = True - @admin.register(m.UlohaZadaniNode) class UlohaZadaniNodeAdmin(PolymorphicChildModelAdmin): base_model = m.UlohaZadaniNode diff --git a/seminar/migrations/0080_zruseni_claneknode_a_konferanode.py b/seminar/migrations/0080_zruseni_claneknode_a_konferanode.py new file mode 100644 index 00000000..13d083f9 --- /dev/null +++ b/seminar/migrations/0080_zruseni_claneknode_a_konferanode.py @@ -0,0 +1,121 @@ +# Generated by Django 2.2.12 on 2020-04-01 20:54 +# Fixed by Pavel, 2020-01-04 20:56 UTC +# This is quite possibly a bug in Django. + +from django.db import migrations, models +import django.db.models.deletion + +def vyrob_dummy_problemy(apps, schema_editor): + Problem = apps.get_model('seminar', 'Problem') + Konfera = apps.get_model('seminar', 'Konfera') + for k in Konfera.objects.all(): + pr = Problem.objects.create(nazev=k.nazev, + garant=k.organizator) + pr.save() + k.problem_ptr = pr + k.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('seminar', '0079_clanek_resitelsky'), + ] + + operations = [ + migrations.DeleteModel( + name='Konfery_Ucastnici', + ), + migrations.RemoveField( + model_name='konfera', + name='ucastnici', + ), + migrations.CreateModel( + name='OrgTextNode', + fields=[ + ('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='seminar.TreeNode')), + ('org_verejny', models.BooleanField(default=True, help_text='Pokud ano, bude org pod článkem podepsaný', verbose_name='Org je veřejný?')), + ('organizator', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='seminar.Organizator', verbose_name='Organizátor')), + ], + options={ + 'verbose_name': 'Organizátorský článek (Node)', + 'verbose_name_plural': 'Organizátorské články (Node)', + 'db_table': 'seminar_nodes_orgtextnode', + }, + bases=('seminar.treenode',), + ), + migrations.RemoveField( + model_name='konfera', + name='id', + ), + migrations.RenameModel( + old_name='OtisteneReseniNode', + new_name='ReseniNode', + ), + migrations.RemoveField( + model_name='clanek', + name='cislo', + ), + migrations.RemoveField( + model_name='clanek', + name='resitelsky', + ), + migrations.RemoveField( + model_name='reseni', + name='text_zkraceny', + ), + migrations.AddField( + model_name='konfera', + name='problem_ptr', + field=models.OneToOneField(auto_created=True, null=False, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='seminar.Problem'), + preserve_default=False, + ), + migrations.RemoveField( + model_name='konfera', + name='nazev', + ), + migrations.RemoveField( + model_name='konfera', + name='organizator', + ), + migrations.RemoveField( + model_name='konfera', + name='poznamka', + ), + migrations.RemoveField( + model_name='konfera', + name='reseni', + ), + migrations.AlterField( + model_name='reseni', + name='text_cely', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='reseni_cely_set', to='seminar.ReseniNode', verbose_name='Plná verze textu řešení'), + ), + migrations.DeleteModel( + name='ClanekNode', + ), + migrations.DeleteModel( + name='KonferaNode', + ), + migrations.CreateModel( + name='Konfery_Ucastnici', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k účasti (plain text)', verbose_name='neveřejná poznámka')), + ('konfera', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='seminar.Konfera', verbose_name='konfera')), + ('resitel', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='seminar.Resitel', verbose_name='řešitel')), + ], + options={ + 'verbose_name': 'Účast na konfeře', + 'verbose_name_plural': 'Účasti na konfeře', + 'db_table': 'seminar_konfery_ucastnici', + 'ordering': ['konfera', 'resitel'], + }, + ), + migrations.AddField( + model_name='konfera', + name='ucastnici', + field=models.ManyToManyField(help_text='Seznam účastníků konfery', through='seminar.Konfery_Ucastnici', to='seminar.Resitel', verbose_name='účastníci konfery'), + ), + ] diff --git a/seminar/migrations/0080_auto_20200408_2221.py b/seminar/migrations/0081_auto_20200408_2221.py similarity index 92% rename from seminar/migrations/0080_auto_20200408_2221.py rename to seminar/migrations/0081_auto_20200408_2221.py index f095ee06..6cf908bb 100644 --- a/seminar/migrations/0080_auto_20200408_2221.py +++ b/seminar/migrations/0081_auto_20200408_2221.py @@ -7,7 +7,7 @@ import seminar.models class Migration(migrations.Migration): dependencies = [ - ('seminar', '0079_clanek_resitelsky'), + ('seminar', '0080_zruseni_claneknode_a_konferanode'), ] operations = [ diff --git a/seminar/models.py b/seminar/models.py index 6419e73d..226fec78 100644 --- a/seminar/models.py +++ b/seminar/models.py @@ -792,14 +792,6 @@ class Clanek(Problem): verbose_name = 'Článek' verbose_name_plural = 'Články' - cislo = models.ForeignKey(Cislo, verbose_name='číslo', blank=True, null=True, - on_delete=models.PROTECT) - - resitelsky = models.BooleanField('Jde o řešitelský článek?', default=True) - - # má OneToOneField s: - # ClanekNode - def kod_v_rocniku(self): if self.stav == 'zadany': # Nemělo by být potřeba @@ -808,15 +800,6 @@ class Clanek(Problem): return "c{}".format(self.kod) return '' - def save(self, *args, **kwargs): - super().save(*args, **kwargs) - # *Node.save() aktualizuje název *Nodu. - try: - self.claneknode.save() - except ObjectDoesNotExist: - # Neexistující *Node nemá smysl aktualizovat. - pass - class Text(SeminarModelBase): class Meta: db_table = 'seminar_texty' @@ -926,13 +909,10 @@ class Reseni(SeminarModelBase): forma = models.CharField('forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False, default=FORMA_EMAIL) - text_cely = models.OneToOneField(Text, verbose_name='Plná verze textu řešení', + text_cely = models.OneToOneField('ReseniNode', verbose_name='Plná verze textu řešení', blank=True, null=True, related_name="reseni_cely_set", - on_delete=models.SET_NULL) + on_delete=models.PROTECT) - text_zkraceny = models.ManyToManyField(Text, verbose_name='zkrácené verze řešení', - help_text='Seznam úryvků z řešení',related_name="reseni_zkraceny_set") - poznamka = models.TextField('neveřejná poznámka', blank=True, help_text='Neveřejná poznámka k řešení (plain text)') @@ -1141,25 +1121,18 @@ class Soustredeni_Organizatori(SeminarModelBase): @reversion.register(ignore_duplicates=True) -class Konfera(models.Model): +class Konfera(Problem): class Meta: db_table = 'seminar_konfera' verbose_name = 'Konfera' verbose_name_plural = 'Konfery' - # Interní ID - id = models.AutoField(primary_key = True) - nazev = models.CharField('název konfery', max_length=100, help_text = 'Název konfery') - anotace = models.TextField('anotace', blank=True, help_text='Popis, o čem bude konfera.') abstrakt = models.TextField('abstrakt', blank=True, help_text='Abstrakt konfery tak, jak byl uveden ve sborníku') - organizator = models.ForeignKey(Organizator, verbose_name='organizátor', related_name='konfery', - on_delete = models.SET_NULL, null=True) - # FIXME: Umíme omezit jen na účastníky daného soustřeďka? ucastnici = models.ManyToManyField(Resitel, verbose_name='účastníci konfery', help_text='Seznam účastníků konfery', through='Konfery_Ucastnici') @@ -1167,13 +1140,6 @@ class Konfera(models.Model): soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění', related_name='konfery', on_delete = models.SET_NULL, null=True) - poznamka = models.TextField('neveřejná poznámka', blank=True, - help_text='Neveřejná poznámka ke konfeře(plain text)') - # Jedno reseni se vztahuje nejvyse k jedne konfere - reseni = models.OneToOneField(Reseni, verbose_name='článek ke konfeře', related_name='konfery', - help_text='Účastnický přípěvek o konfeře', on_delete = models.SET_NULL, - null=True, blank=True) - TYP_VELETRH = 'veletrh' TYP_PREZENTACE = 'prezentace' TYP_CHOICES = [ @@ -1190,21 +1156,9 @@ class Konfera(models.Model): help_text = 'Další materiály ke konfeře zabalené do jednoho souboru', upload_to = generate_filename_konfera, blank=True) - # má OneToOneField s: - # KonferaNode - def __str__(self): return "{}: ({})".format(self.nazev, self.soustredeni) - def save(self, *args, **kwargs): - super().save(*args, **kwargs) - # *Node.save() aktualizuje název *Nodu. - try: - self.konferanode.save() - except ObjectDoesNotExist: - # Neexistující *Node nemá smysl aktualizovat. - pass - # Vazebna tabulka. Mozna se generuje automaticky. @reversion.register(ignore_duplicates=True) @@ -1417,36 +1371,30 @@ class TemaVCisleNode(TreeNode): def getOdkazStr(self): return str(self.tema) -class KonferaNode(TreeNode): +class OrgTextNode(TreeNode): class Meta: - db_table = 'seminar_nodes_konfera' - verbose_name = 'Konfera (Node)' - verbose_name_plural = 'Konfery (Node)' - konfera = models.OneToOneField(Konfera, - on_delete=models.PROTECT, # Pokud chci mazat téma, musím si Node pořešit ručně - verbose_name = "konfera", - null=True, - blank=False) - - def aktualizuj_nazev(self): - self.nazev = "KonferaNode: "+str(self.konfera) - -class ClanekNode(TreeNode): - class Meta: - db_table = 'seminar_nodes_clanek' - verbose_name = 'Článek (Node)' - verbose_name_plural = 'Články (Node)' - clanek = models.OneToOneField(Clanek, - on_delete=models.PROTECT, # Pokud chci mazat téma, musím si Node pořešit ručně - verbose_name = "článek", - null=True, - blank=False) + db_table = 'seminar_nodes_orgtextnode' + verbose_name = 'Organizátorský článek (Node)' + verbose_name_plural = 'Organizátorské články (Node)' + + organizator = models.ForeignKey(Organizator, + null=False, + blank=False, + on_delete=models.DO_NOTHING, + verbose_name="Organizátor", + ) + org_verejny = models.BooleanField(default = True, + verbose_name = "Org je veřejný?", + help_text = "Pokud ano, bude org pod článkem podepsaný", + null=False, + ) def aktualizuj_nazev(self): - self.nazev = "ClanekNode: "+str(self.clanek) + return f"OrgTextNode začínající následujícim: {self.first_child.nazev}" - def getOdkazStr(self): - return str(self.clanek) + # FIXME!!! + #def getOdkazStr(self): + # return str(self.clanek) class UlohaZadaniNode(TreeNode): @@ -1527,7 +1475,7 @@ class CastNode(TreeNode): def getOdkazStr(self): return str(self.nadpis) -class OtisteneReseniNode(TreeNode): +class ReseniNode(TreeNode): class Meta: db_table = 'seminar_nodes_otistene_reseni' verbose_name = 'Otištěné řešení (Node)' diff --git a/seminar/templates/seminar/archiv/cisla.html b/seminar/templates/seminar/archiv/cisla.html index 3c4a38b4..f931ee49 100644 --- a/seminar/templates/seminar/archiv/cisla.html +++ b/seminar/templates/seminar/archiv/cisla.html @@ -40,7 +40,7 @@ {% for cislo in rocnik.cisla.all reversed %}
  • {{ cislo.poradi }}. číslo {% if cislo.pdf %}(pdf) {% endif %} {% empty %} - --- + Žádná čísla k zobrazení {% endfor %} Výsledková listina diff --git a/seminar/templates/seminar/archiv/rocnik.html b/seminar/templates/seminar/archiv/rocnik.html index 2dd99ab4..0f48b30c 100644 --- a/seminar/templates/seminar/archiv/rocnik.html +++ b/seminar/templates/seminar/archiv/rocnik.html @@ -17,14 +17,49 @@ {% endif %} - + {% if vysledkovka %} {% if user.is_staff %} diff --git a/seminar/testutils.py b/seminar/testutils.py index c8d02316..65ffbfcd 100644 --- a/seminar/testutils.py +++ b/seminar/testutils.py @@ -9,7 +9,7 @@ from django.db import transaction import unidecode import logging -from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Osoba, Organizator, Prijemce, Tema, Uloha, Konfera, KonferaNode, TextNode, UlohaVzorakNode, RocnikNode, CisloNode, TemaVCisleNode, Text, Hodnoceni, UlohaZadaniNode, Novinky, TreeNode +from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Osoba, Organizator, Prijemce, Tema, Uloha, Konfera, TextNode, UlohaVzorakNode, RocnikNode, CisloNode, TemaVCisleNode, Text, Hodnoceni, UlohaZadaniNode, Novinky, TreeNode from django.contrib.flatpages.models import FlatPage from django.contrib.sites.models import Site @@ -339,7 +339,7 @@ def gen_konfery(size, rnd, organizatori, resitele, soustredeni): nazev=rnd.choice(['Pozorování', 'Zkoumání', 'Modelování', 'Počítání', 'Zkoušení']) + rnd.choice([' vlastností', ' jevů', ' charakteristik']) + rnd.choice([' vektorových prostorů', ' kinetické terorie látek', ' molekulární biologie', ' syntentických stromů']), anotace=lorem.paragraph(), abstrakt=lorem.paragraph(), - organizator=rnd.choice(organizatori), + garant=rnd.choice(organizatori), soustredeni=rnd.choice(soustredeni), typ_prezentace=rnd.choice(['veletrh', 'prezentace'])) ucastnici_sous = list(konfera.soustredeni.ucastnici.all()) @@ -349,9 +349,6 @@ def gen_konfery(size, rnd, organizatori, resitele, soustredeni): # Konfery_Ucastnici.objects.create(resitel=res, konfera=konfera) konfera.save() konfery.append(konfera) - - konferanode = KonferaNode.objects.create(konfera=konfera) - konferanode.save() return konfery def gen_cisla(rnd, rocniky): diff --git a/seminar/views/views_all.py b/seminar/views/views_all.py index bb078614..1ac106d5 100644 --- a/seminar/views/views_all.py +++ b/seminar/views/views_all.py @@ -309,136 +309,16 @@ class ArchivView(generic.ListView): def get_context_data(self, **kwargs): context = super(ArchivView, self).get_context_data(**kwargs) - vyska = 594 # px - sirka = 420 # px - - # první číslo z každého ročníku - cisla = Cislo.objects.filter(poradi=1) - - # op == os.path, udělá z argumentů cestu - png_dir = op.join(settings.MEDIA_ROOT, "cislo", "png") - - # slovník {(ročník, url obrázku)} + cisla = Cislo.objects.filter(poradi=1) urls ={} - # for j, rocnik in enumerate(Rocnik.objects.all()): - # urls_rocnik = {} - # for i,c in enumerate(rocnik.cisla.all()): - # if not c.pdf: - # urls_rocnik[c.poradi] = op.join(settings.MEDIA_URL, "cislo", "png", "default.png") - # else: - # filename = os.path.split(c.pdf.file.name)[1].split(".")[0] - # png_filename = "{}.png".format(filename) - - # # Pokud obrázek neexistuje nebo není aktuální, vytvoř jej - # png_path = op.join(png_dir, png_filename) - # if not op.exists(png_path) or \ - # op.getmtime(png_path) < op.getmtime(c.pdf.path): - - # subprocess.call([ - # "convert", - # "-density", "300x300", - # "-geometry", "{}x{}".format(vyska, sirka), - # "-background", "white", - # "-flatten", - # "{}[0]".format(c.pdf.path), # titulní strana - # png_path - # ]) - - # urls_rocnik[c.poradi] = op.join(settings.MEDIA_URL, "cislo", "png", png_filename) - # urls[rocnik] = urls_rocnik - - for i,c in enumerate(cisla): - if not c.pdf: - urls[c.rocnik] = op.join(settings.MEDIA_URL, "cislo", "png", "default.png") - else: - filename = os.path.split(c.pdf.file.name)[1].split(".")[0] - png_filename = "{}.png".format(filename) - - # Pokud obrázek neexistuje nebo není aktuální, vytvoř jej - png_path = op.join(png_dir, png_filename) - if not op.exists(png_path) or \ - op.getmtime(png_path) < op.getmtime(c.pdf.path): - - subprocess.call([ - "convert", - "-density", "300x300", - "-geometry", "{}x{}".format(vyska, sirka), - "-background", "white", - "-flatten", - "{}[0]".format(c.pdf.path), # titulní strana - png_path - ]) - - urls[c.rocnik] = op.join(settings.MEDIA_URL, "cislo", "png", png_filename) + for i, c in enumerate(cisla): + if c.titulka_nahled: + urls[c.rocnik] = c.titulka_nahled.url + else: + urls[c.rocnik] = op.join(settings.MEDIA_URL, "cislo", "png", "default.png") context["object_list"] = urls - - print(context) - - # for i, c in enumerate(cisla): - # if not c.pdf: - # continue - # filename = os.path.split(c.pdf.file.name)[1].split(".")[0] - # png_filename = "{}-{}px.png".format(filename, vyska) - - # # Pokud obrázek neexistuje nebo není aktuální, vytvoř jej - # png_path = op.join(png_dir, png_filename) - # if not op.exists(png_path) or \ - # op.getmtime(png_path) < op.getmtime(c.pdf.path): - - # subprocess.call([ - # "convert", - # "-density", "300x300", - # "-geometry", "{}x{}".format(vyska, sirka), - # "-background", "white", - # "-flatten", - # "-rotate", str(90 * i), - # "{}[0]".format(c.pdf.path), # titulní strana - # png_path - # ]) - - # urls.append( - # (op.join(settings.MEDIA_URL, "cislo", "png", png_filename), c) - # ) - # vyska, sirka = sirka, vyska / 2 - - # tags = [] - - # def spirala(urls, tags, idx): - # """Rekurzivně prochází urls a generuje strom elementů do tags""" - # if idx >= len(urls): - # return - - # img_url, cislo = urls[idx] - # tags.append( - # "
    " - # .format( - # 50 if idx % 4 == 2 else 0, - # 50 if idx % 4 == 1 else 0, - # 50 if idx % 2 == 1 else 100, - # 50 if idx > 0 and idx % 2 == 0 else 100 - # ) - # ) - # tags.append("".format( - # cislo.verejne_url(), cislo.kod() - # )) - # tags.append( - # "" - # .format( - # img_url, - # 50 if idx % 4 == 3 else 0, - # 50 if idx % 4 == 2 else 0, - # 50 if idx % 2 == 0 else 100, - # 50 if idx % 2 == 1 else 100 - # ) - # ) - # tags.append("") - # spirala(urls, tags, idx + 1) - # tags.append("
    ") - # spirala(urls, tags, 0) - - # context["nahledy"] = "\n".join(tags) return context