Pavel "LEdoian" Turinsky
4 years ago
54 changed files with 10992 additions and 178 deletions
File diff suppressed because one or more lines are too long
@ -0,0 +1,10 @@ |
|||||
|
from rest_framework import routers |
||||
|
from seminar import viewsets as vs |
||||
|
|
||||
|
router = routers.DefaultRouter() |
||||
|
|
||||
|
router.register(r'ulohavzoraknode', vs.UlohaVzorakNodeViewSet,basename='ulohavzoraknode') |
||||
|
router.register(r'text', vs.TextViewSet) |
||||
|
router.register(r'textnode', vs.TextNodeViewSet) |
||||
|
router.register(r'castnode', vs.CastNodeViewSet) |
||||
|
|
@ -0,0 +1,38 @@ |
|||||
|
/* |
||||
|
.pink { |
||||
|
background-color: #ffc0cb; |
||||
|
} |
||||
|
|
||||
|
div.borderized { |
||||
|
border-style: solid; |
||||
|
border-radius: 5px; |
||||
|
padding: 5px; |
||||
|
padding-right: 20px; |
||||
|
} |
||||
|
|
||||
|
div.tnmenu { |
||||
|
float: right; |
||||
|
margin-right: 0px; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
div.parent { |
||||
|
border-width: 2px; |
||||
|
} |
||||
|
|
||||
|
div.children { |
||||
|
border-width: 1px; |
||||
|
} |
||||
|
|
||||
|
div.node_type { |
||||
|
background-color: #d4d4d4; |
||||
|
} |
||||
|
|
||||
|
.hidden-tn { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
/*test*/ |
||||
|
h1 { |
||||
|
color: chartreuse; |
||||
|
} |
@ -0,0 +1 @@ |
|||||
|
,anet,erebus,25.03.2020 22:21,file:///home/anet/.config/libreoffice/4; |
@ -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') |
||||
|
|
After Width: | Height: | Size: 300 KiB |
@ -0,0 +1,18 @@ |
|||||
|
function showSelectedItemForm(sel,id){ |
||||
|
var option; |
||||
|
var name; |
||||
|
var div; |
||||
|
Array.from(sel.options).forEach(function(option){ |
||||
|
console.log(option); |
||||
|
name = 'pridat-'+option.value+'-'+id; |
||||
|
div = document.getElementById(name); |
||||
|
console.log(div); |
||||
|
div.style.display = 'none'; |
||||
|
}); |
||||
|
name = sel.options[sel.selectedIndex].value; |
||||
|
name = 'pridat-'+name+'-'+id; |
||||
|
div = document.getElementById(name); |
||||
|
console.log(div); |
||||
|
div.style.display = 'block'; |
||||
|
|
||||
|
} |
@ -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 %} #} |
||||
|
|
@ -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 %} |
@ -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 %} |
@ -0,0 +1,23 @@ |
|||||
|
{% extends "seminar/archiv/base.html" %} |
||||
|
{% load staticfiles %} |
||||
|
{% load sekizai_tags %} |
||||
|
|
||||
|
{# toto z nejakeho duvodu nefunguje #} |
||||
|
{% addtoblock css %} |
||||
|
dfsdfs |
||||
|
<link rel="stylesheet" type="text/css" href="{% static 'css/mamweb-dev.css' %}" /> |
||||
|
{% endaddtoblock "css" %} |
||||
|
|
||||
|
{% block custom_css %} |
||||
|
<link rel="stylesheet" type="text/css" href="{% static 'css/mamweb-dev.css' %}" /> |
||||
|
{% endblock custom_css %} |
||||
|
|
||||
|
{% load comments %} |
||||
|
|
||||
|
{% block content %} |
||||
|
<ul> |
||||
|
{% for obj in object_list %} |
||||
|
<li>{{obj}} (id {{obj.id}})</li> |
||||
|
{% endfor %} |
||||
|
</ul> |
||||
|
{% endblock content %} |
@ -1,14 +1,54 @@ |
|||||
|
{% extends "base.html" %} |
||||
|
|
||||
|
|
||||
|
{% block content %} |
||||
|
|
||||
|
<h2> |
||||
|
{% block nadpis1a %}{% block nadpis1b %} |
||||
|
Aktuální témata |
||||
|
{% endblock %}{% endblock %} |
||||
|
</h2> |
||||
|
|
||||
|
<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> |
||||
|
|
||||
|
<p><a href="/co-je-MaM/jak-resit/">Jak řešit téma?</a></p> |
||||
|
|
||||
|
|
||||
|
<div class="rozcestnik_temat"> |
||||
|
|
||||
{% for tematko in tematka %} |
{% for tematko in tematka %} |
||||
<h1>{{tematko.nazev}}</h1> |
|
||||
<p>{{tematko.abstrakt}}</p> |
{# karta témátka - zepředu ilustrační, zezadu abstrakt #} |
||||
<ul> |
<div class="tema_pole"> |
||||
{% for cislo in tematko.cisla %} |
|
||||
<li><a href="/{{rocnik}}/t{{tematko.kod}}/#{{cislo.0.1}}">{{cislo.0.0}}</a></li> |
<h3> |
||||
<ul> |
<a href='{{ rocnik.verejne_url }}'>Téma {{ tematko.nazev }}</a> |
||||
{% for odkaz in cislo.1 %} |
</h3> |
||||
<li><a href="/{{rocnik}}/t{{tematko.kod}}/#{{odkaz.1}}">{{odkaz.0}}</a></li> |
|
||||
{% endfor %} |
<div class="flip-card" id="tema-rozcestnik"> |
||||
</ul> |
|
||||
{% endfor %} |
<div class="flip-card-inner"> |
||||
</ul> |
<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 %} |
{% endfor %} |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
{% endblock %} |
||||
|
@ -1,10 +1,12 @@ |
|||||
{% extends "base.html" %} |
{% extends "base.html" %} |
||||
|
{% load render_bundle from webpack_loader %} |
||||
|
|
||||
{% load comments %} |
|
||||
|
|
||||
{% block content %} |
{% block content %} |
||||
|
<div id="app"> |
||||
|
<app></app> |
||||
|
</div> |
||||
|
{% render_bundle 'chunk-vendors' %} |
||||
|
{% render_bundle 'vue_app_01' %} |
||||
|
|
||||
{%with obj=tnldata depth=1 template_name="seminar/treenode_recursive.html" %} |
|
||||
{%include template_name%} |
|
||||
{%endwith%} |
|
||||
{% endblock content %} |
{% endblock content %} |
||||
|
@ -0,0 +1,27 @@ |
|||||
|
{% load treenodes %} |
||||
|
{% if kam_slug == "syn" %} |
||||
|
{% appendableChildren obj as dostupne_typy %} |
||||
|
{% else %} |
||||
|
{% appendableChildren obj.parent as dostupne_typy %} |
||||
|
{% endif %} |
||||
|
|
||||
|
{# ulohaZadani ulohaVzorak Reseni Cast Text #} |
||||
|
{% if dostupne_typy %} |
||||
|
<div class="pink">Přidat {{kam}} |
||||
|
<select name="pridat-typ-{{obj.node.id}}-{{kam_slug}}" onchange="showSelectedItemForm(this,'{{obj.node.id}}-{{kam_slug}}')"> |
||||
|
{% for typ in dostupne_typy %} |
||||
|
<option value="{{typ.0}}">{{typ.1}}</option> |
||||
|
{% endfor %} |
||||
|
</select> |
||||
|
<div class="hidden-tn" id="pridat-castNode-{{obj.node.id}}-{{kam_slug}}"> |
||||
|
Nadpis: <input name="pridat-cast-{{obj.node.id}}-{{kam_slug}}" type="text"> |
||||
|
<button action="submit" formaction="{%url 'treenode_pridat' obj.node.id kam_slug%}">Přidat</button> |
||||
|
</div> |
||||
|
<div class="hidden-tn" id="pridat-textNode-{{obj.node.id}}-{{kam_slug}}"> Vytvořit</div> |
||||
|
<div class="hidden-tn" id="pridat-reseniNode-{{obj.node.id}}-{{kam_slug}}">Vytvořit, Tady bude autocomplete na reseniNode</div> |
||||
|
<div class="hidden-tn" id="pridat-ulohaZadaniNode-{{obj.node.id}}-{{kam_slug}}">Vytvořit zadání</div> |
||||
|
<div class="hidden-tn" id="pridat-ulohaVzorakNode-{{obj.node.id}}-{{kam_slug}}">Vytvořit vzorák k: Tady bude autocomplete na problémy k aktuálnímu kontextu</div> |
||||
|
|
||||
|
|
||||
|
</div> |
||||
|
{% endif %}{# appendablebleChildren #} |
@ -0,0 +1,18 @@ |
|||||
|
{% load treenodes %} |
||||
|
{% if obj.node|isRocnik %} |
||||
|
<h{{depth}}> Ročník {{obj.node.rocnik}} </h{{depth}}> |
||||
|
{% elif obj.node|isCislo %} |
||||
|
<h{{depth}}> Číslo {{obj.node.cislo}} </h{{depth}}> |
||||
|
{% elif obj.node|isTemaVCisle %} |
||||
|
<h{{depth}}> Téma {{obj.node.tema.nazev}} </h{{depth}}> |
||||
|
{% elif obj.node|isUlohaZadani %} |
||||
|
<h{{depth}}>Úloha {{obj.node.uloha.kod_v_rocniku}} ({{obj.node.uloha.max_body}} b)</h{{depth}}> |
||||
|
{% elif obj.node|isUlohaVzorak %} |
||||
|
<h{{depth}}>Řešení: {{obj.node.uloha.kod_v_rocniku}}</h{{depth}}> |
||||
|
{% elif obj.node|isCast %} |
||||
|
<h{{depth}}> {{obj.node.nadpis}} </h{{depth}}> |
||||
|
{% elif obj.node|isText %} |
||||
|
{{obj.node.text.na_web}} |
||||
|
{% else %} |
||||
|
Objekt jiného typu {{obj.node}} |
||||
|
{% endif %} |
@ -1,28 +1,55 @@ |
|||||
{% load treenodes %} |
{% load treenodes %} |
||||
{# <b>{{depth}}</b> #} |
{# <b>{{depth}}</b> #} |
||||
<div> |
<div class="borderized parent"> |
||||
{% if obj.node|isRocnik %} |
<div class="node_type"> |
||||
<h{{depth}}> Ročník {{obj.node.rocnik}} </h{{depth}}> |
{{obj.node}} |
||||
{% elif obj.node|isCislo %} |
{{obj.node.id}} |
||||
<h{{depth}}> Číslo {{obj.node.cislo}} </h{{depth}}> |
{% if obj.node|deletable %} |
||||
{% elif obj.node|isTemaVCisle %} |
<button type="submit" formaction="{%url 'treenode_smazat' obj.node.id%}">Smazat</button> |
||||
<h{{depth}}> Téma {{obj.node.tema.nazev}} </h{{depth}}> |
{% endif %} |
||||
{% elif obj.node|isUlohaZadani %} |
{% if obj.parent and obj.parent|editableSiblings %} |
||||
<h{{depth}}>Úloha {{obj.node.uloha.kod_v_rocniku}} ({{obj.node.uloha.max_body}} b)</h{{depth}}> |
<button type="submit" formaction="{%url 'treenode_odvesitpryc' obj.node.id%}">Odvěsit pryč ze stromu {{obj.parent.node}}</button> |
||||
{% elif obj.node|isUlohaVzorak %} |
{% endif %} |
||||
<h{{depth}}>Řešení: {{obj.node.uloha.kod_v_rocniku}}</h{{depth}}> |
{% if obj|canPodvesitPred %} |
||||
{% elif obj.node|isText %} |
<button type="submit" formaction="{%url 'treenode_podvesit' obj.node.id 'pred'%}">Podvěsit pod předchozí</button> - nejsou testovací data |
||||
{{obj.node.text.na_web}} |
{% endif %} |
||||
{% else %} |
{% if obj|canPodvesitZa %} |
||||
Objekt jiného typu {{obj.node}} |
<button type="submit" formaction="{%url 'treenode_podvesit' obj.node.id 'za'%}">Podvěsit pod následující</button> - nejsou testovací data |
||||
|
{% endif %} |
||||
|
|
||||
|
|
||||
|
</div> |
||||
|
{% if False %} |
||||
|
<div class="node_move"> |
||||
|
FIXME: není zatím implementováno |
||||
|
<button>Zvyš úroveň nadpisu</button> - nejsou testovací data |
||||
|
</div> |
||||
{% endif %} |
{% endif %} |
||||
{%if obj.children %} |
{% include "seminar/treenode_name.html" %} |
||||
<div> |
{%if obj.children %} |
||||
|
<div class="borderized children"> |
||||
|
|
||||
|
{% with kam="před" kam_slug="syn" %} {% include "seminar/treenode_add_stub.html" %} {% endwith %} |
||||
{%for ch in obj.children %} |
{%for ch in obj.children %} |
||||
{%with obj=ch depth=depth|add:"1" template_name="seminar/treenode_recursive.html" %} |
|
||||
{%include template_name%} |
{# ----------- Vypisujeme podstrom ----------#} |
||||
{%endwith%} |
{%with obj=ch depth=depth|add:"1" %} {%include "seminar/treenode_recursive.html" %} {%endwith%} |
||||
{%endfor%} |
{# ----------- Přidáváme mezi syny / za posledního -------- #} |
||||
|
{% if forloop.last %} |
||||
|
{% with kam="za" kam_slug="za" obj=ch %} {% include "seminar/treenode_add_stub.html" %} {% endwith %} |
||||
|
{% else %} |
||||
|
{% with kam="mezi" obj=ch kam_slug="za" %} {% include "seminar/treenode_add_stub.html" %} {% endwith %} |
||||
|
{% endif %} |
||||
|
{# ----------- Prohazujeme sousedy ----------#} |
||||
|
<div class="pink"> |
||||
|
{% if not forloop.last and ch|editableSiblings %} |
||||
|
<button type="submit" formaction="{%url 'treenode_prohodit' ch.node.id%}">Prohodit ^ a v</button> |
||||
|
{% endif %} |
||||
</div> |
</div> |
||||
{%endif%} |
{% endfor %} |
||||
|
</div> |
||||
|
{% else %} |
||||
|
{# ----------- Přidáváme prvního syna ----------#} |
||||
|
{% with kam="jako syna" kam_slug="syn" %} {% include "seminar/treenode_add_stub.html" %} {% endwith %} |
||||
|
{%endif%} |
||||
</div> |
</div> |
||||
|
@ -0,0 +1,7 @@ |
|||||
|
{% load render_bundle from webpack_loader %} |
||||
|
|
||||
|
<div id="app"> |
||||
|
<app></app> |
||||
|
</div> |
||||
|
{% render_bundle 'chunk-vendors' %} |
||||
|
{% render_bundle 'vue_app_01' %} |
@ -1,3 +1,4 @@ |
|||||
from .views_all import * |
from .views_all import * |
||||
from .autocomplete import * |
from .autocomplete import * |
||||
|
from .views_rest import * |
||||
from .odevzdavatko import * |
from .odevzdavatko import * |
||||
|
@ -0,0 +1,162 @@ |
|||||
|
from rest_framework import serializers |
||||
|
from rest_polymorphic.serializers import PolymorphicSerializer |
||||
|
|
||||
|
import seminar.models as m |
||||
|
from seminar import treelib |
||||
|
|
||||
|
DEFAULT_NODE_DEPTH = 2 |
||||
|
|
||||
|
class TextSerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = m.Text |
||||
|
fields = '__all__' |
||||
|
|
||||
|
|
||||
|
|
||||
|
class UlohaVzorakNodeSerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = m.UlohaVzorakNode |
||||
|
fields = '__all__' |
||||
|
depth = DEFAULT_NODE_DEPTH |
||||
|
|
||||
|
class UlohaZadaniNodeSerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = m.UlohaZadaniNode |
||||
|
fields = '__all__' |
||||
|
depth = DEFAULT_NODE_DEPTH |
||||
|
|
||||
|
class RocnikNodeSerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = m.RocnikNode |
||||
|
fields = '__all__' |
||||
|
depth = DEFAULT_NODE_DEPTH |
||||
|
|
||||
|
class CisloNodeSerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = m.CisloNode |
||||
|
fields = '__all__' |
||||
|
depth = DEFAULT_NODE_DEPTH |
||||
|
|
||||
|
class MezicisloNodeSerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = m.MezicisloNode |
||||
|
fields = '__all__' |
||||
|
depth = DEFAULT_NODE_DEPTH |
||||
|
|
||||
|
class TemaVCisleNodeSerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = m.TemaVCisleNode |
||||
|
fields = '__all__' |
||||
|
depth = DEFAULT_NODE_DEPTH |
||||
|
|
||||
|
class OrgTextNodeSerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = m.OrgTextNode |
||||
|
fields = '__all__' |
||||
|
depth = DEFAULT_NODE_DEPTH |
||||
|
|
||||
|
class PohadkaNodeSerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = m.PohadkaNode |
||||
|
fields = '__all__' |
||||
|
depth = DEFAULT_NODE_DEPTH |
||||
|
|
||||
|
class TextNodeSerializer(serializers.ModelSerializer): |
||||
|
text = TextSerializer() |
||||
|
|
||||
|
class Meta: |
||||
|
model = m.TextNode |
||||
|
fields = ('id','text','polymorphic_ctype') |
||||
|
depth = DEFAULT_NODE_DEPTH |
||||
|
|
||||
|
class TextNodeWriteSerializer(serializers.ModelSerializer): |
||||
|
text = TextSerializer() |
||||
|
|
||||
|
def update(self,node,validated_data): |
||||
|
node.text.na_web = validated_data.get('text').get('na_web') |
||||
|
node.text.save() |
||||
|
return node |
||||
|
|
||||
|
class Meta: |
||||
|
model = m.TextNode |
||||
|
fields = ('id','text') |
||||
|
depth = DEFAULT_NODE_DEPTH |
||||
|
|
||||
|
class TextNodeCreateSerializer(serializers.ModelSerializer): |
||||
|
text = TextSerializer() |
||||
|
refnode = serializers.CharField() |
||||
|
where = serializers.CharField() |
||||
|
|
||||
|
def create(self,validated_data): |
||||
|
temp_text = validated_data.pop('text') |
||||
|
where = validated_data.pop('where') |
||||
|
refnode_id = validated_data.pop('refnode') |
||||
|
refnode = m.TreeNode.objects.get(pk=refnode_id) |
||||
|
text = m.Text.objects.create(**temp_text) |
||||
|
if where == 'syn': |
||||
|
node = treelib.create_child(refnode,m.TextNode,text=text) |
||||
|
elif where == 'za': |
||||
|
node = treelib.create_node_after(refnode,m.TextNode,text=text) |
||||
|
elif where == 'pred': |
||||
|
node = treelib.create_node_before(refnode,m.TextNode,text=text) |
||||
|
node.where = None |
||||
|
node.refnode = None |
||||
|
return node |
||||
|
|
||||
|
class Meta: |
||||
|
model = m.TextNode |
||||
|
fields = ('text','where','refnode') |
||||
|
depth = DEFAULT_NODE_DEPTH |
||||
|
|
||||
|
class CastNodeSerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = m.CastNode |
||||
|
fields = '__all__' |
||||
|
depth = DEFAULT_NODE_DEPTH |
||||
|
|
||||
|
class CastNodeCreateSerializer(serializers.ModelSerializer): |
||||
|
refnode = serializers.CharField() |
||||
|
where = serializers.CharField() |
||||
|
|
||||
|
def create(self,validated_data): |
||||
|
temp_nadpis = validated_data.pop('nadpis') |
||||
|
where = validated_data.pop('where') |
||||
|
refnode_id = validated_data.pop('refnode') |
||||
|
refnode = m.TreeNode.objects.get(pk=refnode_id) |
||||
|
if where == 'syn': |
||||
|
node = treelib.create_child(refnode,m.CastNode,nadpis=temp_nadpis) |
||||
|
elif where == 'za': |
||||
|
node = treelib.create_node_after(refnode,m.CastNode,nadpis=temp_nadpis) |
||||
|
elif where == 'pred': |
||||
|
node = treelib.create_node_before(refnode,m.CastNode,nadpis=temp_nadpis) |
||||
|
node.where = None |
||||
|
node.refnode = None |
||||
|
return node |
||||
|
|
||||
|
class Meta: |
||||
|
model = m.CastNode |
||||
|
fields = ('nadpis','where','refnode') |
||||
|
depth = DEFAULT_NODE_DEPTH |
||||
|
|
||||
|
class ReseniNodeSerializer(serializers.ModelSerializer): |
||||
|
class Meta: |
||||
|
model = m.ReseniNode |
||||
|
fields = '__all__' |
||||
|
depth = DEFAULT_NODE_DEPTH |
||||
|
|
||||
|
|
||||
|
class TreeNodeSerializer(PolymorphicSerializer): |
||||
|
model_serializer_mapping = { |
||||
|
m.RocnikNode: RocnikNodeSerializer, |
||||
|
m.CisloNode: CisloNodeSerializer, |
||||
|
m.MezicisloNode: MezicisloNodeSerializer, |
||||
|
m.TemaVCisleNode: TemaVCisleNodeSerializer, |
||||
|
m.OrgTextNode: OrgTextNodeSerializer, |
||||
|
m.UlohaZadaniNode: UlohaZadaniNodeSerializer, |
||||
|
m.UlohaVzorakNode: UlohaVzorakNodeSerializer, |
||||
|
m.PohadkaNode: PohadkaNodeSerializer, |
||||
|
m.TextNode: TextNodeSerializer, |
||||
|
m.CastNode: CastNodeSerializer, |
||||
|
m.ReseniNode: ReseniNodeSerializer, |
||||
|
} |
||||
|
|
@ -0,0 +1,96 @@ |
|||||
|
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] |
||||
|
|
||||
|
class ReadWriteSerializerMixin(object): |
||||
|
""" |
||||
|
Overrides get_serializer_class to choose the read serializer |
||||
|
for GET requests and the write serializer for POST requests. |
||||
|
|
||||
|
Set read_serializer_class and write_serializer_class attributes on a |
||||
|
viewset. |
||||
|
""" |
||||
|
|
||||
|
read_serializer_class = None |
||||
|
create_serializer_class = None |
||||
|
write_serializer_class = None |
||||
|
|
||||
|
def get_serializer_class(self): |
||||
|
if self.action == "create": |
||||
|
return self.get_create_serializer_class() |
||||
|
if self.action in ["update", "partial_update", "destroy"]: |
||||
|
return self.get_write_serializer_class() |
||||
|
return self.get_read_serializer_class() |
||||
|
|
||||
|
def get_read_serializer_class(self): |
||||
|
assert self.read_serializer_class is not None, ( |
||||
|
"'%s' should either include a `read_serializer_class` attribute," |
||||
|
"or override the `get_read_serializer_class()` method." |
||||
|
% self.__class__.__name__ |
||||
|
) |
||||
|
return self.read_serializer_class |
||||
|
|
||||
|
def get_write_serializer_class(self): |
||||
|
assert self.write_serializer_class is not None, ( |
||||
|
"'%s' should either include a `write_serializer_class` attribute," |
||||
|
"or override the `get_write_serializer_class()` method." |
||||
|
% self.__class__.__name__ |
||||
|
) |
||||
|
return self.write_serializer_class |
||||
|
|
||||
|
def get_create_serializer_class(self): |
||||
|
assert self.create_serializer_class is not None, ( |
||||
|
"'%s' should either include a `create_serializer_class` attribute," |
||||
|
"or override the `get_create_serializer_class()` method." |
||||
|
% self.__class__.__name__ |
||||
|
) |
||||
|
return self.create_serializer_class |
||||
|
|
||||
|
class UlohaVzorakNodeViewSet(PermissionMixin, viewsets.ModelViewSet): |
||||
|
queryset = m.UlohaVzorakNode.objects.all() |
||||
|
serializer_class = views.UlohaVzorakNodeSerializer |
||||
|
|
||||
|
class TextViewSet(PermissionMixin, viewsets.ModelViewSet): |
||||
|
queryset = m.Text.objects.all() |
||||
|
serializer_class = views.TextSerializer |
||||
|
|
||||
|
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(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(PermissionMixin, viewsets.ModelViewSet): |
||||
|
serializer_class = views.UlohaVzorakNodeSerializer |
||||
|
|
||||
|
def get_queryset(self): |
||||
|
queryset = m.UlohaVzorakNode.objects.all() |
||||
|
nazev = self.request.query_params.get('nazev',None) |
||||
|
if nazev is not None: |
||||
|
queryset = queryset.filter(nazev__contains=nazev) |
||||
|
if self.request.user.has_perm('auth.org'): |
||||
|
return queryset |
||||
|
else: # pro neorgy jen zveřejněné vzoráky |
||||
|
return queryset.filter(uloha__cislo_reseni__verejne_db=True) |
@ -0,0 +1,22 @@ |
|||||
|
.DS_Store |
||||
|
node_modules |
||||
|
/dist |
||||
|
|
||||
|
# local env files |
||||
|
.env.local |
||||
|
.env.*.local |
||||
|
|
||||
|
# Log files |
||||
|
npm-debug.log* |
||||
|
yarn-debug.log* |
||||
|
yarn-error.log* |
||||
|
pnpm-debug.log* |
||||
|
|
||||
|
# Editor directories and files |
||||
|
.idea |
||||
|
.vscode |
||||
|
*.suo |
||||
|
*.ntvs* |
||||
|
*.njsproj |
||||
|
*.sln |
||||
|
*.sw? |
@ -0,0 +1,5 @@ |
|||||
|
module.exports = { |
||||
|
presets: [ |
||||
|
'@vue/cli-plugin-babel/preset' |
||||
|
] |
||||
|
} |
@ -0,0 +1,48 @@ |
|||||
|
{ |
||||
|
"name": "vue_frontend", |
||||
|
"version": "0.1.0", |
||||
|
"private": true, |
||||
|
"scripts": { |
||||
|
"serve": "vue-cli-service serve", |
||||
|
"build": "vue-cli-service build", |
||||
|
"lint": "vue-cli-service lint" |
||||
|
}, |
||||
|
"dependencies": { |
||||
|
"@ckeditor/ckeditor5-upload": "^23.0.0", |
||||
|
"@ckeditor/ckeditor5-vue": "^1.0.1", |
||||
|
"axios": "^0.19.2", |
||||
|
"ckeditor5-build-classic-simple-upload-adapter-image-resize": "^1.0.4", |
||||
|
"core-js": "^3.6.5", |
||||
|
"vue": "^2.6.11", |
||||
|
"vue-router": "^3.4.3" |
||||
|
}, |
||||
|
"devDependencies": { |
||||
|
"@vue/cli-plugin-babel": "~4.4.0", |
||||
|
"@vue/cli-plugin-eslint": "~4.4.0", |
||||
|
"@vue/cli-service": "^4.5.6", |
||||
|
"babel-eslint": "^10.1.0", |
||||
|
"eslint": "^6.7.2", |
||||
|
"eslint-plugin-vue": "^6.2.2", |
||||
|
"vue-template-compiler": "^2.6.11", |
||||
|
"webpack-bundle-tracker": "0.4.3" |
||||
|
}, |
||||
|
"eslintConfig": { |
||||
|
"root": true, |
||||
|
"env": { |
||||
|
"node": true |
||||
|
}, |
||||
|
"extends": [ |
||||
|
"plugin:vue/essential", |
||||
|
"eslint:recommended" |
||||
|
], |
||||
|
"parserOptions": { |
||||
|
"parser": "babel-eslint" |
||||
|
}, |
||||
|
"rules": {} |
||||
|
}, |
||||
|
"browserslist": [ |
||||
|
"> 1%", |
||||
|
"last 2 versions", |
||||
|
"not dead" |
||||
|
] |
||||
|
} |
@ -0,0 +1,7 @@ |
|||||
|
<template> |
||||
|
<router-view id="app"/> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { name: 'app' } |
||||
|
</script> |
@ -0,0 +1,50 @@ |
|||||
|
<template> |
||||
|
<div class="addnewnode"> |
||||
|
<button v-if="types.includes('castNode')" v-on:click="selected='castNode'" :disabled="selected && selected !== 'castNode'">Část</button> |
||||
|
<button v-if="types.includes('textNode')" v-on:click="selected='textNode'" :disabled="selected && selected !== 'textNode'">Text</button> |
||||
|
<button v-if="types.includes('reseniNode')" v-on:click="selected='reseniNode'" :disabled="selected && selected !== 'reseniNode'">Řešení</button> |
||||
|
<button v-if="types.includes('ulohaZadaniNode')" v-on:click="selected='ulohaZadaniNode'" :disabled="selected && selected !== 'ulohaZadaniNode'">Zadání úlohy</button> |
||||
|
<button v-if="types.includes('ulohaVzorakNode')" v-on:click="selected='ulohaVzorakNode'" :disabled="selected && selected !== 'ulohaVzorakNode'">Vzorák</button> |
||||
|
<div v-if="selected"> |
||||
|
<component :is='selected' :item='null' :where="where" :refnode="refnode" create></component> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import castNode from './CastNode.vue' |
||||
|
import textNode from './TextNode.vue' |
||||
|
import ulohaZadaniNode from './UlohaZadaniNode.vue' |
||||
|
import ulohaVzorakNode from './UlohaVzorakNode.vue' |
||||
|
//import reseniNode from './UlohaVzorakNode.vue' |
||||
|
|
||||
|
export default { |
||||
|
name: 'AddNewNode', |
||||
|
props: { |
||||
|
types: Array, |
||||
|
where: String, |
||||
|
refnode: Object, |
||||
|
}, |
||||
|
data: () => ({ |
||||
|
selected: null, |
||||
|
}), |
||||
|
components: { |
||||
|
castNode, |
||||
|
textNode, |
||||
|
ulohaZadaniNode, |
||||
|
ulohaVzorakNode, |
||||
|
}, |
||||
|
mounted: function() { |
||||
|
this.$root.$on('dataUpdated',(arg) => { |
||||
|
this.selected = null; |
||||
|
console.log('dataUpdated'+arg); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.addnewnode { |
||||
|
display: inline; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,86 @@ |
|||||
|
<template> |
||||
|
<div class="castnode"> |
||||
|
<!--pre>CastNode {{item}} {{typeof(item)}}</pre--> |
||||
|
<div v-if="editorShow"> |
||||
|
<input type="text" v-model="currentText" /> |
||||
|
<button v-on:click="saveText">Uložit</button> |
||||
|
<button v-on:click="currentText = originalText;editorShow=!editorShow;">Zahodit úpravy</button> |
||||
|
</div> |
||||
|
<div v-else> |
||||
|
<h4>{{ currentText }} </h4> <button v-if="editorMode" v-on:click="editorShow=!editorShow">Upravit</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import axios from 'axios' |
||||
|
|
||||
|
export default { |
||||
|
name: 'CastNode', |
||||
|
data: () => ({ |
||||
|
editorShow: false, |
||||
|
currentText: "", |
||||
|
originalText: "", |
||||
|
}), |
||||
|
props: { |
||||
|
item: Object, |
||||
|
editorShow: Boolean, |
||||
|
create: Boolean, |
||||
|
where: String, |
||||
|
refnode: Object |
||||
|
}, |
||||
|
mounted: function() { |
||||
|
if (this.create){ |
||||
|
this.currentText = ""; |
||||
|
this.originalText = ""; |
||||
|
this.editorShow = true; |
||||
|
} |
||||
|
else { |
||||
|
this.currentText = this.item.node.nadpis; |
||||
|
this.originalText = this.item.node.nadpis; |
||||
|
} |
||||
|
|
||||
|
//this.getText(); |
||||
|
}, |
||||
|
methods: { |
||||
|
saveText: function() { |
||||
|
console.log("Saving cast"); |
||||
|
console.log(this.currentText); |
||||
|
if (this.create){ |
||||
|
console.log(this.refnode); |
||||
|
console.log(this.where); |
||||
|
axios.post('/api/castnode/',{ |
||||
|
'nadpis': this.currentText, |
||||
|
'refnode': this.refnode.id, |
||||
|
'where': this.where |
||||
|
}).then(response => { |
||||
|
this.originalText = response.data.nadpis; |
||||
|
this.$root.$emit('updateData',"castNode create update"); |
||||
|
}) |
||||
|
.catch(e => { |
||||
|
console.log(e); |
||||
|
this.errors.push(e); |
||||
|
}); |
||||
|
} else { |
||||
|
axios.put('/api/castnode/'+this.item.node.id+'/',{ |
||||
|
'nadpis': this.currentText, |
||||
|
'id': this.item.node.id |
||||
|
}).then(response => { |
||||
|
this.originalText = response.data.nadpis; |
||||
|
}) |
||||
|
.catch(e => { |
||||
|
console.log(e); |
||||
|
this.errors.push(e) |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
this.editorShow = false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<!-- Add "scoped" attribute to limit CSS to this component only --> |
||||
|
<style scoped> |
||||
|
</style> |
@ -0,0 +1,19 @@ |
|||||
|
<template> |
||||
|
<div class="cislonode"> |
||||
|
<!--pre>CisloNode {{item}} {{typeof(item)}}</pre--> |
||||
|
<h1>{{ item.node.cislo.poradi }}. číslo</h1> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
name: 'CisloNode', |
||||
|
props: { |
||||
|
item: Object |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<!-- Add "scoped" attribute to limit CSS to this component only --> |
||||
|
<style scoped> |
||||
|
</style> |
@ -0,0 +1,21 @@ |
|||||
|
<template> |
||||
|
|
||||
|
<div class="rocniknode"> |
||||
|
<!--pre>RocnikNode {{item}} {{typeof(item)}}</pre--> |
||||
|
<h1>Ročník {{ item.node.rocnik.rocnik }} ({{ item.node.rocnik.prvni_rok }}/{{item.node.rocnik.prvni_rok+1 }})</h1> |
||||
|
</div> |
||||
|
|
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
name: 'RocnikNode', |
||||
|
props: { |
||||
|
item: Object |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<!-- Add "scoped" attribute to limit CSS to this component only --> |
||||
|
<style scoped> |
||||
|
</style> |
@ -0,0 +1,19 @@ |
|||||
|
<template> |
||||
|
<div class="temavcislenode"> |
||||
|
<!--pre>TemaVCisleNode {{item}} {{typeof(item)}}</pre--> |
||||
|
<h2>Téma {{ item.node.tema.kod }}: {{ item.node.tema.nazev }}</h2> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
name: 'TemaVCisleNode', |
||||
|
props: { |
||||
|
item: Object |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<!-- Add "scoped" attribute to limit CSS to this component only --> |
||||
|
<style scoped> |
||||
|
</style> |
@ -0,0 +1,174 @@ |
|||||
|
<template> |
||||
|
<div v-if="loading" class="loading"> |
||||
|
<p>Loading...</p> |
||||
|
</div> |
||||
|
<div v-else class="textnode"> |
||||
|
<!--pre>TextNode {{item}} {{typeof(item)}}</pre--> |
||||
|
<template v-if="editorShow"> |
||||
|
|
||||
|
<div v-if="plainEditShow"> |
||||
|
<textarea id="textarea" v-model="currentText" rows="8" cols="50"></textarea> |
||||
|
<br> |
||||
|
<button v-on:click="plainEditShow=!plainEditShow">Editovat v editoru</button> |
||||
|
</div> |
||||
|
|
||||
|
<div v-else> |
||||
|
<component v-bind:is="editorComponent" :editor="editor" v-model="currentText" :config="editorConfig"></component> |
||||
|
<button v-on:click="plainEditShow=!plainEditShow">Editovat HTML</button> |
||||
|
</div> |
||||
|
<button v-on:click="saveText">Uložit</button> |
||||
|
<button v-on:click="currentText = originalText;editorShow=!editorShow;">Zahodit úpravy</button> |
||||
|
|
||||
|
</template> |
||||
|
|
||||
|
<template v-else v-bind:class="changedObject"> |
||||
|
<p v-html="currentText"></p> |
||||
|
<button v-if="editorMode" v-on:click="editorShow=!editorShow">Upravit</button> |
||||
|
</template> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import axios from 'axios' |
||||
|
|
||||
|
//import ClassicEditor from '@ckeditor/ckeditor5-build-classic' |
||||
|
import ClassicEditor from 'ckeditor5-build-classic-simple-upload-adapter-image-resize'; |
||||
|
import CKEditor from '@ckeditor/ckeditor5-vue'; |
||||
|
|
||||
|
export default { |
||||
|
name: 'TextNode', |
||||
|
data: () => ({ |
||||
|
loading: false, |
||||
|
editor: ClassicEditor, |
||||
|
editorData: '<p>Content of the editor.</p>', |
||||
|
editorConfig: { |
||||
|
extraPlugins: ['SimpleUploadAdapter'], |
||||
|
simpleUpload: { |
||||
|
uploadUrl: "/temp/image_upload/", |
||||
|
headers: {}, |
||||
|
withCredentials: true |
||||
|
} |
||||
|
// The configuration of the editor. |
||||
|
}, |
||||
|
editorShow: false, |
||||
|
plainEditShow: false, |
||||
|
editorComponent: CKEditor.component, |
||||
|
currentText: "",// this.item.node.text.na_web, |
||||
|
originalText: "",// this.item.node.text.na_web, |
||||
|
}), |
||||
|
computed: { |
||||
|
changedObject: function () { |
||||
|
//console.log(this.currentText); |
||||
|
//console.log(this.originalText); |
||||
|
return { |
||||
|
changed: this.currentText !== this.originalText, |
||||
|
} |
||||
|
}, |
||||
|
textId: function () { |
||||
|
console.log(this.create); |
||||
|
console.log(this.node.text.id); |
||||
|
if (this.create){ |
||||
|
return null; |
||||
|
} |
||||
|
return this.node.text.id; |
||||
|
|
||||
|
} |
||||
|
}, |
||||
|
props: { |
||||
|
item: Object, |
||||
|
editorShow: Boolean, |
||||
|
editorMode: Boolean, |
||||
|
create: Boolean, |
||||
|
where: String, |
||||
|
refnode: Object |
||||
|
}, |
||||
|
mounted: function() { |
||||
|
//console.log("mounted"); |
||||
|
this.editorConfig.simpleUpload.headers['X-CSRFToken'] = this.getCookie('csrftoken'); |
||||
|
axios.defaults.headers.common['X-CSRFToken'] = this.getCookie('csrftoken'); |
||||
|
if (this.create){ |
||||
|
this.currentText = ""; |
||||
|
this.originalText = ""; |
||||
|
this.editorShow = true; |
||||
|
} else { |
||||
|
this.currentText = this.item.node.text.na_web; |
||||
|
this.originalText = this.item.node.text.na_web; |
||||
|
this.editorConfig.simpleUpload.headers.textId = this.item.node.text.id; |
||||
|
|
||||
|
} |
||||
|
//this.getText(); |
||||
|
}, |
||||
|
methods: { |
||||
|
getCookie: function (name){ |
||||
|
var cookieValue = null; |
||||
|
if (document.cookie && document.cookie != '') { |
||||
|
var cookies = document.cookie.split(';'); |
||||
|
for (var i = 0; i < cookies.length; i++) { |
||||
|
var cookie = cookies[i].trim(); |
||||
|
// Does this cookie string begin with the name we want? |
||||
|
|
||||
|
if (cookie.substring(0, name.length + 1) == (name + '=')) { |
||||
|
cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return cookieValue; |
||||
|
}, |
||||
|
getText: function() { |
||||
|
this.loading = true; |
||||
|
console.log(this.item); |
||||
|
console.log(this.item.node.text); |
||||
|
axios.get('/treenode/text/'+this.item.node.text) |
||||
|
.then((response) => { |
||||
|
this.text = response.data.na_web; |
||||
|
this.loading = false; |
||||
|
}) |
||||
|
.catch((err) => { |
||||
|
this.loading = false; |
||||
|
console.log(err); |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
saveText: function() { |
||||
|
console.log("Saving text"); |
||||
|
console.log(this.currentText); |
||||
|
if (this.create){ |
||||
|
console.log(this.refnode); |
||||
|
console.log(this.where); |
||||
|
axios.post('/api/textnode/',{ |
||||
|
'text': { 'na_web': this.currentText}, |
||||
|
'refnode': this.refnode.id, |
||||
|
'where': this.where |
||||
|
}).then(response => { |
||||
|
this.originalText = response.data.text.na_web; |
||||
|
this.loading = false; |
||||
|
this.$root.$emit('updateData',"textNode create update"); |
||||
|
}) |
||||
|
.catch(e => { |
||||
|
this.errors.push(e) |
||||
|
}); |
||||
|
} else { |
||||
|
axios.put('/api/textnode/'+this.item.node.id+'/',{ |
||||
|
'text': { 'na_web': this.currentText}, |
||||
|
'id': this.item.node.id |
||||
|
}).then(response => { |
||||
|
this.originalText = response.data.text.na_web; |
||||
|
}) |
||||
|
.catch(e => { |
||||
|
this.errors.push(e) |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
this.editorShow = false; |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<!-- Add "scoped" attribute to limit CSS to this component only --> |
||||
|
<style scoped> |
||||
|
.changed { |
||||
|
background-color: 'yellow'; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,161 @@ |
|||||
|
<template> |
||||
|
|
||||
|
<div :class="editorMode ? 'treenode-org' : 'treenode'"> |
||||
|
<!--b v-if="v_tematu">v tematu</b> |
||||
|
<b v-if="visible">visible</b> |
||||
|
Force visible: {{String(force_visible)}}--> |
||||
|
<component :is='item.node.polymorphic_ctype.model' :item='item' :key='item.node.id' |
||||
|
:editorMode="editorMode" |
||||
|
:debugMode="debugMode"></component> |
||||
|
|
||||
|
|
||||
|
<button v-if="debugMode" v-on:click="debugShow = !debugShow" class="nodebug">Ladící data</button> <!-- bude tu nějaký if na class="nodebug", v debug módu bude tlačítko vidět, jinak ne --> |
||||
|
<div v-if="debugShow"> |
||||
|
<pre>{{ item.node.polymorphic_ctype.model }}</pre> |
||||
|
<pre>{{ item }}</pre> |
||||
|
</div> |
||||
|
|
||||
|
<div v-if="item.children.length === 0"> |
||||
|
<div v-if="item.appendable_children.length > 0 && editorMode"> |
||||
|
<b>Vložit jako syna: </b> |
||||
|
<addnewnode :types="item.appendable_children" :refnode="item.node" where="syn" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div v-else :class="editorMode ? 'children-org' : 'children'"> <!-- bude tu nějaký if na class="children" --> |
||||
|
<div v-if="item.children.length > 0 && item.children[0].appendable_siblings.length > 0 && editorMode"> |
||||
|
<b>Vložit před: </b> |
||||
|
<addnewnode :types="item.children[0].appendable_siblings" :refnode="item.children[0].node" where="pred" /> |
||||
|
</div> |
||||
|
<div v-if="item.node.polymorphic_ctype.model==='temavcislenode'"> |
||||
|
<!--Children: {{String(showChildren)}}--> |
||||
|
<div v-for="(chld, index) in item.children" v-bind:key="chld.nazev" > |
||||
|
<!--Hide: {{hideNode(chld)}}, v tematu: {{v_tematu}}, force_visible: {{force_visible}}--> |
||||
|
<div v-if="!hideNode(chld)"> |
||||
|
<div v-if="chld.node.polymorphic_ctype.model==='ulohazadaninode'"> |
||||
|
<button v-if="showChildren" v-on:click="showChildren=!showChildren"> Schovat </button> |
||||
|
<button v-else v-on:click="showChildren=!showChildren"> Rozbalit </button> |
||||
|
<TreeNode :item="chld" :v_tematu="true" |
||||
|
:force_visible="showChildren" |
||||
|
:editorMode="editorMode" |
||||
|
:debugMode="debugMode"> |
||||
|
</TreeNode> |
||||
|
</div> |
||||
|
<div v-else> |
||||
|
<TreeNode :item="chld" :v_tematu="true" |
||||
|
:force_visible="showChildren" |
||||
|
:editorMode="editorMode" |
||||
|
:debugMode="debugMode"> |
||||
|
</TreeNode> |
||||
|
</div> |
||||
|
<div v-if="chld.appendable_siblings.length > 0 && editorMode" > |
||||
|
<b v-if="index < (item.children.length - 1)">Vložit mezi: </b> |
||||
|
<b v-else>Vložit za: </b> |
||||
|
<addnewnode :types="chld.appendable_siblings" :refnode="chld.node" where="za" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<button v-if="showChildren" v-on:click="showChildren=!showChildren"> Schovat </button> |
||||
|
<button v-else v-on:click="showChildren=!showChildren"> Rozbalit </button> |
||||
|
</div> |
||||
|
<div v-else> |
||||
|
<div v-for="(chld, index) in item.children" v-bind:key="chld.nazev" > |
||||
|
<div v-if="v_tematu && chld.node.polymorphic_ctype.model==='ulohazadaninode'"> |
||||
|
<div> Tady možná něco je </div> |
||||
|
<TreeNode :item="chld" :v_tematu="v_tematu" |
||||
|
:force_visible="force_visible" |
||||
|
:editorMode="editorMode" |
||||
|
:debugMode="debugMode"> |
||||
|
</TreeNode> |
||||
|
</div> |
||||
|
<div v-else> |
||||
|
<TreeNode :item="chld" :v_tematu="v_tematu" |
||||
|
:force_visible="force_visible" |
||||
|
:editorMode="editorMode" |
||||
|
:debugMode="debugMode"> |
||||
|
</TreeNode> |
||||
|
</div> |
||||
|
<div v-if="chld.appendable_siblings.length > 0 && editorMode" > |
||||
|
<b v-if="index < (item.children.length - 1)">Vložit mezi: </b> |
||||
|
<b v-else>Vložit za: </b> |
||||
|
<addnewnode :types="chld.appendable_siblings" :refnode="chld.node" where="za" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
import rocniknode from './RocnikNode.vue' |
||||
|
import cislonode from './CisloNode.vue' |
||||
|
import temavcislenode from './TemaVCisleNode.vue' |
||||
|
import castnode from './CastNode.vue' |
||||
|
import textnode from './TextNode.vue' |
||||
|
import ulohazadaninode from './UlohaZadaniNode.vue' |
||||
|
import ulohavzoraknode from './UlohaVzorakNode.vue' |
||||
|
import addnewnode from './AddNewNode.vue' |
||||
|
|
||||
|
export default { |
||||
|
name: 'TreeNode', |
||||
|
components: { |
||||
|
rocniknode, |
||||
|
cislonode, |
||||
|
temavcislenode, |
||||
|
castnode, |
||||
|
textnode, |
||||
|
ulohazadaninode, |
||||
|
ulohavzoraknode, |
||||
|
addnewnode |
||||
|
}, |
||||
|
data: () => ({ |
||||
|
debugShow: false, |
||||
|
showChildren: false |
||||
|
}), |
||||
|
computed: { |
||||
|
}, |
||||
|
props: { |
||||
|
item: Object, |
||||
|
force_visible: Boolean, |
||||
|
v_tematu: Boolean, |
||||
|
editorMode: Boolean, |
||||
|
debugMode: Boolean, |
||||
|
}, |
||||
|
methods: { |
||||
|
hideNode: function(chld){ |
||||
|
if (this.showChildren || this.force_visible){ |
||||
|
return false; |
||||
|
} |
||||
|
if (chld.node.polymorphic_ctype.model === 'ulohazadaninode'){ |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<!-- Add "scoped" attribute to limit CSS to this component only --> |
||||
|
<style scoped> |
||||
|
|
||||
|
|
||||
|
.treenode-org { |
||||
|
padding: 5px; |
||||
|
margin: 5px; |
||||
|
border: #6a0043 2px solid; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.children-org { |
||||
|
padding: 10px; |
||||
|
margin: 5px; |
||||
|
border: #6a0043 2px dashed; |
||||
|
} |
||||
|
|
||||
|
.nodebug { |
||||
|
/* display: none; */ |
||||
|
} |
||||
|
|
||||
|
</style> |
@ -0,0 +1,75 @@ |
|||||
|
<template> |
||||
|
<div id="app"> |
||||
|
<div id="loading" v-if="loading"> |
||||
|
Loading... |
||||
|
</div> |
||||
|
<!--pre> |
||||
|
{{item}} |
||||
|
</pre--> |
||||
|
<button v-show="editorMode" v-on:click="editorMode = false">Vypnout editační mód</button> |
||||
|
<button v-show="!editorMode" v-on:click="editorMode = true">Zapnout editační mód</button> |
||||
|
<button v-show="debugMode" v-on:click="debugMode = false">Vypnout ladicí mód</button> |
||||
|
<button v-show="!debugMode" v-on:click="debugMode = true">Zapnout ladicí mód</button> |
||||
|
<TreeNode :item="item" :editorMode="editorMode" :debugMode="debugMode"/> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import TreeNode from './TreeNode.vue' |
||||
|
import axios from 'axios' |
||||
|
export default { |
||||
|
name: 'App', |
||||
|
components: { |
||||
|
TreeNode, |
||||
|
}, |
||||
|
data: () => ({ |
||||
|
loading: true, |
||||
|
item: null, |
||||
|
tnid: 1, |
||||
|
editorMode: false, |
||||
|
debugMode: false, |
||||
|
}), |
||||
|
props:{ |
||||
|
tnid: Number, |
||||
|
tnsource: String, |
||||
|
editorMode: Boolean, |
||||
|
debugMode: Boolean, |
||||
|
}, |
||||
|
mounted: function() { |
||||
|
if (this.tnsource && this.tnsource=='inline'){ |
||||
|
let data = JSON.parse(document.getElementById('vuedata').textContent); |
||||
|
this.tnid = data.treenode; |
||||
|
} |
||||
|
this.getArticles(); |
||||
|
this.$root.$on('updateData',(arg) => { |
||||
|
console.log(arg); |
||||
|
this.getArticles(); |
||||
|
}); |
||||
|
}, |
||||
|
methods: { |
||||
|
getArticles: function() { |
||||
|
this.loading = true; |
||||
|
axios.get('/treenode/'+this.tnid+'/json/') |
||||
|
.then((response) => { |
||||
|
this.item = response.data; |
||||
|
this.loading = false; |
||||
|
console.log('Data updated'); |
||||
|
this.$root.$emit('dataUpdated',"dataUpdated"); |
||||
|
}) |
||||
|
.catch((err) => { |
||||
|
this.loading = false; |
||||
|
console.log(err); |
||||
|
}) |
||||
|
} |
||||
|
}, |
||||
|
events: { |
||||
|
updateData: function(){ |
||||
|
this.getArticles() |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
@import '../../../mamweb/static/css/mamweb.css'; |
||||
|
</style> |
@ -0,0 +1,75 @@ |
|||||
|
<template> |
||||
|
<div class="ulohavzoraknode"> |
||||
|
<!--pre>UlohaVzorakNode {{item}} {{typeof(item)}}</pre--> |
||||
|
<h5>Řešení {{item.node.uloha.cislo_zadani.poradi}}.{{ item.node.uloha.kod }}: {{ item.node.uloha.nazev }}</h5> |
||||
|
<button v-if="editorMode" v-on:click="showSelect=!showSelect" class="upravit">Upravit</button> |
||||
|
<div v-if="showSelect"> |
||||
|
<form class="searchForm" v-on:submit.prevent="submitSearch"> |
||||
|
<input type="text" v-model="searchQuery" placeholder="Napište název" @keyup="submitSearch"> |
||||
|
</form> |
||||
|
<div class="searchResult" v-show="isResult"> |
||||
|
<ul> |
||||
|
<li v-for="res in searchResults" :key="res.id" v-on:click="setSelected(res)">{{res.nazev}}</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import axios from 'axios' |
||||
|
|
||||
|
export default { |
||||
|
name: 'UlohaVzorakNode', |
||||
|
data: () => { |
||||
|
return { |
||||
|
isResult: false, |
||||
|
searchQuery: '', |
||||
|
searchResults: [], |
||||
|
showSelect: false, |
||||
|
selected: null, |
||||
|
selected_id: null |
||||
|
} |
||||
|
}, |
||||
|
props: { |
||||
|
item: Object, |
||||
|
create: Boolean, |
||||
|
showSelect: Boolean, |
||||
|
editorMode: Boolean, |
||||
|
}, |
||||
|
mounted: function(){ |
||||
|
if (this.item.node.uloha === null){ |
||||
|
console.log("Uloha je null!"); |
||||
|
console.log(this.item); |
||||
|
} |
||||
|
if (this.create){ |
||||
|
this.showSelect = true; |
||||
|
console.log('Creating'); |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
submitSearch: function(){ |
||||
|
if (this.searchQuery.length < 3) { return;} |
||||
|
var reqURL = "/api/ulohavzoraknode/?nazev="+this.searchQuery; |
||||
|
axios.get(reqURL).then( (response) => { |
||||
|
this.searchResults = response.data.results; |
||||
|
this.isResult = true; |
||||
|
console.log("Got:"); |
||||
|
console.log(this.searchResults); |
||||
|
}).catch( (err) => { /* fail response msg */ |
||||
|
console.log(err); |
||||
|
}); |
||||
|
}, |
||||
|
setSelected: function(res){ |
||||
|
this.searchQuery = res.nazev |
||||
|
this.selected_id = res.id |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.upravit { |
||||
|
margin-top:-40px; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,23 @@ |
|||||
|
<template> |
||||
|
<div class="ulohazadaninode"> |
||||
|
<!--pre>UlohaZadaniNode {{item.node.uloha}} {{typeof(item)}}</pre--> |
||||
|
<h5>Zadání {{item.node.uloha.cislo_zadani.poradi}}.{{ item.node.uloha.kod }}: {{ item.node.uloha.nazev }}</h5> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
name: 'UlohaZadaniNode', |
||||
|
props: { |
||||
|
item: Object, |
||||
|
created: Boolean |
||||
|
, |
||||
|
mounted: function(){ |
||||
|
if (this.item.node.uloha === null){ |
||||
|
console.log("Uloha je null!"); |
||||
|
console.log(this.item); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
@ -0,0 +1,12 @@ |
|||||
|
import Vue from 'vue' |
||||
|
import App from './App.vue' |
||||
|
import router from './router' |
||||
|
import CKEditor from '@ckeditor/ckeditor5-vue' |
||||
|
|
||||
|
Vue.config.productionTip = false |
||||
|
Vue.use(CKEditor); |
||||
|
|
||||
|
new Vue({ |
||||
|
router, |
||||
|
render: h => h(App), |
||||
|
}).$mount('#app') |
@ -0,0 +1,33 @@ |
|||||
|
import Vue from 'vue' |
||||
|
import Router from 'vue-router' |
||||
|
import TreeNodeRoot from '../components/TreeNodeRoot.vue' |
||||
|
|
||||
|
Vue.use(Router) |
||||
|
|
||||
|
export default new Router({ |
||||
|
mode: 'history', |
||||
|
linkActiveClass: 'active', |
||||
|
routes: [{ |
||||
|
path: '/temp/vue', |
||||
|
name: 'treenodedefault', |
||||
|
props: {'tnid': 23}, |
||||
|
component: TreeNodeRoot |
||||
|
}, { |
||||
|
path: '/temp/vue/:tnid', |
||||
|
name: 'treenode', |
||||
|
props: true, |
||||
|
component: TreeNodeRoot |
||||
|
}, { |
||||
|
path: '/zadani/aktualni', |
||||
|
name: 'treenode_zadani', |
||||
|
props: {'tnid': 23}, |
||||
|
component: TreeNodeRoot |
||||
|
}, { |
||||
|
path: '/cislo/:cislo', |
||||
|
name: 'treenode_cislo', |
||||
|
props: {'tnsource':'inline'}, |
||||
|
component: TreeNodeRoot |
||||
|
} |
||||
|
] |
||||
|
}) |
||||
|
|
@ -0,0 +1,61 @@ |
|||||
|
const BundleTracker = require("webpack-bundle-tracker"); |
||||
|
|
||||
|
const pages = { |
||||
|
'vue_app_01': { |
||||
|
entry: './src/main.js', |
||||
|
chunks: ['chunk-vendors'] |
||||
|
}, |
||||
|
/* 'vue_app_02': { |
||||
|
entry: './src/newhampshir.js', |
||||
|
chunks: ['chunk-vendors'] |
||||
|
}, |
||||
|
*/ |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
pages: pages, |
||||
|
filenameHashing: false, |
||||
|
productionSourceMap: false, |
||||
|
publicPath: process.env.NODE_ENV === 'production' |
||||
|
? '/static/seminar/vue/' |
||||
|
: 'http://localhost:8080/', |
||||
|
outputDir: '../seminar/static/seminar/vue/', |
||||
|
|
||||
|
chainWebpack: config => { |
||||
|
|
||||
|
config.optimization |
||||
|
.splitChunks({ |
||||
|
cacheGroups: { |
||||
|
vendor: { |
||||
|
test: /[\\/]node_modules[\\/]/, |
||||
|
name: "chunk-vendors", |
||||
|
chunks: "all", |
||||
|
priority: 1 |
||||
|
}, |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
Object.keys(pages).forEach(page => { |
||||
|
config.plugins.delete(`html-${page}`); |
||||
|
config.plugins.delete(`preload-${page}`); |
||||
|
config.plugins.delete(`prefetch-${page}`); |
||||
|
}) |
||||
|
|
||||
|
config |
||||
|
.plugin('BundleTracker') |
||||
|
.use(BundleTracker, [{filename: '../vue_frontend/webpack-stats.json'}]); |
||||
|
|
||||
|
config.resolve.alias |
||||
|
.set('__STATIC__', 'static') |
||||
|
|
||||
|
config.devServer |
||||
|
.public('http://localhost:8080') |
||||
|
.host('localhost') |
||||
|
.port(8080) |
||||
|
.hotOnly(true) |
||||
|
.watchOptions({poll: 1000}) |
||||
|
.https(false) |
||||
|
.headers({"Access-Control-Allow-Origin": ["*"]}) |
||||
|
|
||||
|
} |
||||
|
}; |
File diff suppressed because it is too large
Loading…
Reference in new issue