Merge branch 'data_migrations' into test
This commit is contained in:
		
						commit
						6aa4a5e797
					
				
					 14 changed files with 274 additions and 29 deletions
				
			
		
							
								
								
									
										6
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								Makefile
									
									
									
									
									
								
							|  | @ -153,3 +153,9 @@ sync_local_db: | |||
| 
 | ||||
| # Sync database and media. See above lines
 | ||||
| sync_local: sync_local_media sync_local_db | ||||
| 
 | ||||
| # Push local compiled Vue to gimli test site
 | ||||
| push_compiled_vue_to_test: | ||||
| 	scp vue_frontend/webpack-stats.json mam-web@gimli:/akce/mam/www/mamweb-test/vue_frontend/ | ||||
| 	rsync -ave ssh seminar/static/seminar/vue mam-web@gimli:/akce/mam/www/mamweb-test/seminar/static/seminar/ | ||||
| 	ssh mam-web@gimli.ms.mff.cuni.cz 'cd /akce/mam/www/mamweb-test/ && . env/bin/activate && ./manage.py collectstatic --noinput' | ||||
|  |  | |||
|  | @ -123,6 +123,7 @@ INSTALLED_APPS = ( | |||
|      | ||||
|     'webpack_loader', | ||||
|     'rest_framework', | ||||
|     'rest_framework.authtoken', | ||||
| 
 | ||||
|     # MaMweb | ||||
|     'mamweb', | ||||
|  |  | |||
|  | @ -759,17 +759,26 @@ div.odpocet { | |||
| 
 | ||||
| /*stránka organizátorů*/ | ||||
| 
 | ||||
| div.seznam_orgu { | ||||
| div.seznam_orgu, div.rozcestnik_temat { | ||||
| 	text-align: center; | ||||
| 	padding-bottom: 10px; | ||||
| } | ||||
| 
 | ||||
| div.org_pole, div.rocnik_pole { | ||||
| div.org_pole, div.rocnik_pole, div.tema_pole { | ||||
| 	display: inline-block; | ||||
| 	width: 30%; | ||||
| 	min-width: 300px; | ||||
| 	text-align: center; | ||||
| } | ||||
| 
 | ||||
| div.tema_pole { | ||||
| 	display: inline-block; | ||||
| 	width: 40%; | ||||
| 	min-width: 350px; | ||||
| 	padding-bottom: 20px; | ||||
| 	text-align: center; | ||||
| } | ||||
| 
 | ||||
| div.cislo_pole { | ||||
| 	display: inline-block; | ||||
| 	width: 15%; | ||||
|  | @ -812,6 +821,11 @@ div.org_email { | |||
| 	height: 205px; | ||||
| } | ||||
| 
 | ||||
| #tema-rozcestnik.flip-card { | ||||
| 	width: 300px; | ||||
| 	height: 300px; | ||||
| } | ||||
| 
 | ||||
| /* This container is needed to position the front and back side */ | ||||
| .flip-card-inner { | ||||
|  position: relative; | ||||
|  | @ -835,7 +849,8 @@ div.org_email { | |||
|  backface-visibility: hidden; | ||||
| } | ||||
| 
 | ||||
| div.flip-card-foto img { | ||||
| 
 | ||||
| div.flip-card-foto, div.flip-card-foto img { | ||||
| 	width: 100%; | ||||
| 	height: 100%; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										1
									
								
								seminar/.~lock.profile_vysledkovka.txt#
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								seminar/.~lock.profile_vysledkovka.txt#
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| ,anet,erebus,25.03.2020 22:21,file:///home/anet/.config/libreoffice/4; | ||||
|  | @ -743,12 +743,17 @@ class Problem(SeminarModelBase,PolymorphicModel): | |||
| 		return '<Není zadaný>' | ||||
| 
 | ||||
| 	def verejne(self): | ||||
| 		# FIXME: Tohle se liší podle typu problému, má se udělat polymorfně. | ||||
| 		# Zatím je tu jen dummy fail-safe default: nic není veřejné. | ||||
| 		# Doporučené řešení: dělat tohle podle stavu problému a veřejnosti čísla, ve kterém je | ||||
| 		return False | ||||
| 		# FIXME: Tohle je blbost | ||||
| 		return (self.cislo_zadani and self.cislo_zadani.verejne()) | ||||
| 		# aktuálně podle stavu problému | ||||
| 		# FIXME pro některé problémy možná chceme override | ||||
| 		stav_verejny = False | ||||
| 		if self.stav == 'zadany' or self.stav == 'vyreseny': | ||||
| 			stav_verejny = True | ||||
| 		 | ||||
| 		cislo_verejne = False | ||||
| 		if (self.cislo_zadani and self.cislo_zadani.verejne()): | ||||
| 			cislo_verejne = True | ||||
| 		 | ||||
| 		return (stav_verejny and cislo_verejne) | ||||
| 	verejne.boolean = True | ||||
| 
 | ||||
| 	def verejne_url(self): | ||||
|  |  | |||
							
								
								
									
										7
									
								
								seminar/permissions.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								seminar/permissions.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| from rest_framework.permissions import BasePermission | ||||
| 
 | ||||
| class AllowWrite(BasePermission): | ||||
| 
 | ||||
|          def has_permission(self, request, view): | ||||
|                   return request.user.has_perm('auth.org') | ||||
| 
 | ||||
							
								
								
									
										
											BIN
										
									
								
								seminar/static/images/tema-bez-obrazku.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								seminar/static/images/tema-bez-obrazku.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 300 KiB | 
							
								
								
									
										97
									
								
								seminar/templates/seminar/archiv/cislo-normal.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								seminar/templates/seminar/archiv/cislo-normal.html
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,97 @@ | |||
| {% extends "seminar/archiv/base_cisla.html" %} | ||||
| 
 | ||||
| {# {% block content %} | ||||
|  <div> | ||||
| 
 | ||||
|   <h1> | ||||
|     {% block nadpis1a %}{% block nadpis1b %} | ||||
|       Číslo {{ cislo }} | ||||
|     {% endblock %}{% endblock %} | ||||
|   </h1> | ||||
| 
 | ||||
|   {% if cislo.pdf %} | ||||
|     <p><a href='{{ cislo.pdf.url }}'>Číslo v pdf</a> | ||||
|   {% endif %} | ||||
|   <p><a href='{{ cislo.rocnik.verejne_url }}'>Ročník {{ cislo.rocnik }}</a> | ||||
| 
 | ||||
|   {% if v_cisle_zadane %} | ||||
|     <h2>Zadané problémy</h2> | ||||
|     <ul> | ||||
|     {% for p in v_cisle_zadane %} | ||||
|       <li{% if user.is_staff and not cislo.verejne %} class='mam-org-only'{% endif %}> | ||||
|         {% if user.is_staff or cislo.verejne %} | ||||
|           <a href='{{ p.verejne_url }}'>{% endif %}{{ p.kod_v_rocniku }} {{ p.nazev }} {{ p.body_v_zavorce }}{% if user.is_staff or cislo.verejne %}</a>{% endif %} | ||||
|     {% endfor %} | ||||
|     </ul> | ||||
|   {% endif %} | ||||
| 
 | ||||
|   {% if resene_problemy %} | ||||
|     <h2>Řešené problémy</h2> | ||||
|     <ul> | ||||
|     {% for p in resene_problemy %} | ||||
|       <li{% if user.is_staff and not cislo.verejne %} class='mam-org-only'{% endif %}> | ||||
|         {% if user.is_staff or cislo.verejne %} | ||||
|           <a href='{{ p.verejne_url }}'>{% endif %}{{ p.kod_v_rocniku }} {{ p.nazev }} {{ p.body_v_zavorce }}{% if user.is_staff or cislo.verejne %}</a>{% endif %} | ||||
|     {% endfor %} | ||||
|     </ul> | ||||
|   {% endif %} | ||||
| 
 | ||||
|   {% if user.is_staff %} | ||||
|       <div class="mam-org-only"> | ||||
|         <h2> Orgovské odkazy </h2> | ||||
|         <ul> | ||||
|           <li><a href="obalky.pdf">Obálky (PDF)</a></li> | ||||
|           <li><a href="tituly.tex">Tituly (TeX)</a></li> | ||||
|           <li><a href="vysledkovka.tex">Výsledkovka (TeX)</a></li> | ||||
|           <li><a href="obalkovani">Obálkování</a></li> | ||||
|         </ul> | ||||
|       </div> | ||||
|   {% endif %}  | ||||
| 
 | ||||
|   {% if cislo.verejna_vysledkovka %} | ||||
|   <h2>Výsledkovka</h2> | ||||
|   {% else %} | ||||
|     {% if user.is_staff %} | ||||
|       <div class='mam-org-only'> | ||||
|       <h2>Výsledkovka (neveřejná)</h2> | ||||
|     {% endif %} | ||||
|   {% endif %} | ||||
| 
 | ||||
|   {% if cislo.verejna_vysledkovka or user.is_staff %} | ||||
|     <table class='vysledkovka'> | ||||
|       <tr class='border-b'> | ||||
|         <th class='border-r'># | ||||
|         <th class='border-r'>Jméno #} | ||||
|         {# problémy by měly být veřejné, když je veřejná výsledkovka #} | ||||
| {#        {% for p in problemy %} | ||||
|         <th class='border-r'><a href="{{ p.verejne_url }}">{{ p.kod_v_rocniku }}</a> | ||||
|         {% endfor %} | ||||
|         <th class='border-r'>Za číslo</sup> | ||||
|         <th class='border-r'>Za ročník | ||||
|         <th class='border-r'>Odjakživa | ||||
|     {% for rv in radky_vysledkovky %} | ||||
|       <tr> | ||||
|         <td class='border-r'>{% autoescape off %}{{ rv.poradi }}{% endautoescape %} | ||||
|             <th class='border-r'> | ||||
|             {% if rv.resitel.titul != "" %} | ||||
|               {{ rv.resitel.titul }}<sup>MM</sup> | ||||
|             {% endif %} | ||||
|             {{ rv.resitel.osoba.plne_jmeno }} | ||||
|         {% for b in rv.hlavni_problemy_body %} | ||||
|         <td class='border-r'>{{ b }} | ||||
|         {% endfor %} | ||||
|         <td class='border-r'>{{ rv.body_cislo }} | ||||
|         <td class='border-r'><b>{{ rv.body_rocnik }}</b> | ||||
|         <td class='border-r'>{{ rv.body_celkem_odjakziva }} | ||||
|       </tr> | ||||
|     {% endfor %} | ||||
|     </table> | ||||
|   {% endif %} | ||||
| 
 | ||||
|   {% if not cislo.verejna_vysledkovka and user.is_staff %} | ||||
|       </div> | ||||
|   {% endif %} | ||||
| 
 | ||||
| </div>  | ||||
| {% endblock content %} #} | ||||
| 
 | ||||
							
								
								
									
										19
									
								
								seminar/templates/seminar/archiv/problem_tema.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								seminar/templates/seminar/archiv/problem_tema.html
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| {% extends "seminar/archiv/problem.html" %} | ||||
| 
 | ||||
| {% block problem %} | ||||
|     <h1> | ||||
|       {% block nadpis1a %}{% block nadpis1b %} | ||||
|         {{ problem.nazev_typu }} {{ problem.kod_v_rocniku }}: {{ problem.nazev }} | ||||
|       {% endblock %}{% endblock %} | ||||
|     </h1> | ||||
| 
 | ||||
|   <h2>Zadání</h2> | ||||
|   {{ problem.text_zadani |safe }} | ||||
|   {% if problem.text_reseni %} | ||||
|     <h2>Řešení</h2> | ||||
|     {{ problem.text_reseni |safe }} | ||||
|   {% endif %} | ||||
| 
 | ||||
|   {# TODO vysledkovka tematu #} | ||||
| 
 | ||||
| {% endblock %} | ||||
							
								
								
									
										23
									
								
								seminar/templates/seminar/archiv/problem_uloha.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								seminar/templates/seminar/archiv/problem_uloha.html
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| {% extends "seminar/archiv/problem.html" %} | ||||
| 
 | ||||
| {% block problem %} | ||||
|     <h1> | ||||
|       {% block nadpis1a %}{% block nadpis1b %} | ||||
|         {{ problem.nazev_typu }} {{ problem.kod_v_rocniku }}: {{ problem.nazev }} {{ problem.body_v_zavorce }} | ||||
|       {% endblock %}{% endblock %} | ||||
|     </h1> | ||||
|   {% if problem.cislo_zadani %} | ||||
|     <p>Zadáno v čísle <a href='{{ problem.cislo_zadani.verejne_url }}'>{{ problem.cislo_zadani.kod }}</a>. | ||||
|   {% endif %} | ||||
|   {% if problem.cislo_reseni %} | ||||
|     <p>Řešeno v čísle <a href='{{ problem.cislo_reseni.verejne_url }}'>{{ problem.cislo_reseni.kod }}</a>. | ||||
|   {% endif %} | ||||
| 
 | ||||
|   <h2>Zadání</h2> | ||||
|   {{ problem.text_zadani |safe }} | ||||
|   {% if problem.text_reseni %} | ||||
|     <h2>Řešení</h2> | ||||
|     {{ problem.text_reseni |safe }} | ||||
|   {% endif %} | ||||
| 
 | ||||
| {% endblock %} | ||||
|  | @ -2,24 +2,53 @@ | |||
| 
 | ||||
| 
 | ||||
| {% block content %} | ||||
| <p style="text-align:justify">Témata jsou texty nejen z oblasti matematiky, fyziky a informatiky, které popisují nějaký problém a jsou doprovázeny návodnými úlohami. Vaším úkolem je zamyslet se nad daným problémem a sepsat vaše úvahy ve formě krátkého textu.</p> | ||||
| 
 | ||||
| <p style="text-align:justify"><a href="/co-je-MaM/jak-resit/">Jak řešit téma?</a></p> | ||||
| <h2> | ||||
|   {% block nadpis1a %}{% block nadpis1b %} | ||||
|   Aktuální témata | ||||
|   {% endblock %}{% endblock %} | ||||
| </h2> | ||||
| 
 | ||||
| <p style="text-align:justify"> </p> | ||||
| <p>Témata jsou texty nejen z oblasti matematiky, fyziky a informatiky, které popisují nějaký | ||||
|   problém a jsou doprovázeny návodnými úlohami. Vaším úkolem je zamyslet se nad daným | ||||
|   problémem a sepsat vaše úvahy ve formě krátkého textu.</p> | ||||
| 
 | ||||
| <h1>Aktuální témata</h1> | ||||
| <p><a href="/co-je-MaM/jak-resit/">Jak řešit téma?</a></p> | ||||
| 
 | ||||
| 
 | ||||
| <div class="rozcestnik_temat"> | ||||
| 
 | ||||
| {% for tematko in tematka %} | ||||
| <h2>{{tematko.nazev}}</h2> | ||||
| <div class="tematko-obrazek"> | ||||
|     {% if tematko.obrazek %} | ||||
|       <a href="{{tematko.obrazek.url}}" class="ref-tema-obr"><img src="{{tematko.obrazek.url}}" height="{{tematko.obrazek.height}}" alt="{{tematko.nazev}}"></a> | ||||
|     {% else %} {# pokud témátko nemá fotku, zobrazuje se defaultní obrázek #} | ||||
|       {% load static %} <img src="{% static 'images/no-photo.png' %}" height=200px alt="{{tematko.nazev}}"> | ||||
|     {% endif %} | ||||
| 
 | ||||
| {# karta témátka - zepředu ilustrační, zezadu abstrakt #} | ||||
| <div class="tema_pole"> | ||||
| 
 | ||||
|   <h3> | ||||
|     <a href='{{ rocnik.verejne_url }}'>Téma {{ tematko.nazev }}</a> | ||||
|   </h3> | ||||
| 
 | ||||
|   <div class="flip-card" id="tema-rozcestnik"> | ||||
| 
 | ||||
|     <div class="flip-card-inner"> | ||||
|       <div class="flip-card-front"> | ||||
|         <div class="flip-card-foto"> | ||||
|           {% if tematko.obrazek %} | ||||
|             <img src="{{ tematko.obrazek.url }}" alt="{{ tematko.nazev }}"> | ||||
|           {% else %} {# pokud témátko nemá fotku, zobrazuje se defaultní obrázek #} | ||||
|             {% load static %} <img src="{% static 'images/tema-bez-obrazku.png' %}" alt="{{ tematko.nazev }}"> | ||||
|           {% endif %} | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="flip-card-back"> | ||||
|           <p>{{ tematko.abstrakt }}</p> | ||||
|       </div> | ||||
|     </div> | ||||
| 
 | ||||
|   </div> | ||||
| </div> | ||||
| {# konec karty témátka #} | ||||
| {% endfor %} | ||||
| 
 | ||||
| </div> | ||||
| 
 | ||||
| <p>{{tematko.abstrakt}}</p> | ||||
| {% endfor %} | ||||
| {% endblock %} | ||||
|  |  | |||
|  | @ -140,7 +140,7 @@ def gen_resitele(rnd, osoby, skoly): | |||
| 				x += 1 | ||||
| 				os.user = user | ||||
| 				os.save() | ||||
| 			os.user.user_permissions.add(resitel_perm) | ||||
| 				os.user.user_permissions.add(resitel_perm) | ||||
| 			resitele.append(Resitel.objects.create(osoba=os, skola=rnd.choice(skoly), | ||||
| 				rok_maturity=rnd.randint(2019, 2029), | ||||
| 				zasilat=rnd.choice(Resitel.ZASILAT_CHOICES)[0])) | ||||
|  | @ -199,7 +199,7 @@ def gen_organizatori(rnd, osoby, last_rocnik): | |||
| 				x += 1 | ||||
| 				os.user = user | ||||
| 				os.save() | ||||
| 			os.user.user_permissions.add(org_perm) | ||||
| 				os.user.user_permissions.add(org_perm) | ||||
| 			organizatori.append(Organizator.objects.create(osoba=os, | ||||
| 				organizuje_od=od, organizuje_do=do, strucny_popis_organizatora = popis_orga)) | ||||
| 	return organizatori | ||||
|  |  | |||
|  | @ -127,6 +127,7 @@ class TNLData(object): | |||
| 	def from_treenode(cls,anode,parent=None,index=None): | ||||
| 		out = cls(anode,parent,index) | ||||
| 		for (idx,ch) in enumerate(treelib.all_children(anode)): | ||||
| 			# FIXME přidat filtrování na veřejnost | ||||
| 			outitem = cls.from_treenode(ch,out,idx) | ||||
| 			out.children.append(outitem) | ||||
| 		out.add_edit_options() | ||||
|  |  | |||
|  | @ -1,7 +1,48 @@ | |||
| from rest_framework import viewsets,filters | ||||
| from rest_framework.permissions import BasePermission, AllowAny | ||||
| from . import models as m | ||||
| from . import views | ||||
| 
 | ||||
| from seminar.permissions import AllowWrite  | ||||
| 
 | ||||
| class PermissionMixin(object): | ||||
| 	""" Redefines get_permissions so that only organizers can make changes. """ | ||||
| 
 | ||||
| 	def get_permissions(self): | ||||
| 		permission_classes = [] | ||||
| 		print("get_permissions have been called.") | ||||
| 		if self.action in ["create", "update", "partial_update", "destroy"]: | ||||
| 			permission_classes = [AllowWrite] # speciální permission na zápis - orgové | ||||
| 		else: | ||||
| 			permission_classes = [AllowAny]  | ||||
| 		# návštěvník nemusí být zalogován, aby si prohlížel obsah | ||||
| 		return [permission() for permission in permission_classes] | ||||
| 
 | ||||
| 	def verejne_nad(self, node): | ||||
| 		""" Returns output of verejne for closest Rocnik, Cislo or Problem above. | ||||
| 		(All of them have method verejne.)""" | ||||
| 		parent = get_parent(node) | ||||
| 		while True: | ||||
| 			rocnik = isinstance(parent, RocnikNode) | ||||
| 			cislo = isinstance(parent, CisloNode) | ||||
| 			problem = isinstance(parent, ProblemNode) | ||||
| 
 | ||||
| 			if (rocnik or cislo or problem): | ||||
| 				break | ||||
| 			else: | ||||
| 				parent = get_parent(parent) | ||||
| 		if rocnik: | ||||
| 			return parent.rocnik.verejne() | ||||
| 		elif cislo: | ||||
| 			return parent.cislo.verejne() | ||||
| 		elif problem: | ||||
| 			return parent.problem.verjne() | ||||
| 
 | ||||
| 	def has_object_permission(self, request, view, obj): | ||||
| 		# test that obj is Node | ||||
| 		assert isinstance(obj, Node) | ||||
| 		return verejne_nad(node) | ||||
| 
 | ||||
| class ReadWriteSerializerMixin(object): | ||||
| 	""" | ||||
| 	Overrides get_serializer_class to choose the read serializer | ||||
|  | @ -46,27 +87,27 @@ class ReadWriteSerializerMixin(object): | |||
| 		) | ||||
| 		return self.create_serializer_class | ||||
| 
 | ||||
| class UlohaVzorakNodeViewSet(viewsets.ModelViewSet): | ||||
| class UlohaVzorakNodeViewSet(PermissionMixin, viewsets.ModelViewSet): | ||||
| 	queryset = m.UlohaVzorakNode.objects.all() | ||||
| 	serializer_class = views.UlohaVzorakNodeSerializer | ||||
| 
 | ||||
| class TextViewSet(viewsets.ModelViewSet): | ||||
| class TextViewSet(PermissionMixin, viewsets.ModelViewSet): | ||||
| 	queryset = m.Text.objects.all() | ||||
| 	serializer_class = views.TextSerializer | ||||
| 
 | ||||
| class TextNodeViewSet(ReadWriteSerializerMixin,viewsets.ModelViewSet): | ||||
| class TextNodeViewSet(PermissionMixin, ReadWriteSerializerMixin,viewsets.ModelViewSet): | ||||
| 	queryset = m.TextNode.objects.all() | ||||
| 	read_serializer_class = views.TextNodeSerializer | ||||
| 	write_serializer_class = views.TextNodeWriteSerializer | ||||
| 	create_serializer_class = views.TextNodeCreateSerializer | ||||
| 
 | ||||
| class CastNodeViewSet(ReadWriteSerializerMixin,viewsets.ModelViewSet): | ||||
| class CastNodeViewSet(PermissionMixin, ReadWriteSerializerMixin,viewsets.ModelViewSet): | ||||
| 	queryset = m.CastNode.objects.all() | ||||
| 	read_serializer_class = views.CastNodeSerializer | ||||
| 	write_serializer_class = views.CastNodeSerializer | ||||
| 	create_serializer_class = views.CastNodeCreateSerializer | ||||
| 
 | ||||
| class UlohaVzorakNodeViewSet(viewsets.ModelViewSet): | ||||
| class UlohaVzorakNodeViewSet(PermissionMixin, viewsets.ModelViewSet): | ||||
| 	serializer_class = views.UlohaVzorakNodeSerializer | ||||
| 
 | ||||
| 	def get_queryset(self): | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Pavel "LEdoian" Turinsky
						Pavel "LEdoian" Turinsky