Tomas 'Jethro' Pokorny
4 years ago
54 changed files with 91572 additions and 979 deletions
File diff suppressed because one or more lines are too long
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; |
|||
} |
After Width: | Height: | Size: 1.8 MiB |
After Width: | Height: | Size: 1.8 MiB |
After Width: | Height: | Size: 1.8 MiB |
@ -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,16 @@ |
|||
{% extends 'base.html' %} |
|||
|
|||
{% load humanize %} |
|||
{% load staticfiles %} |
|||
|
|||
|
|||
{% block content %} |
|||
|
|||
<div class=jakresit> |
|||
|
|||
<img class="jakresit_obrazek" alt="" src="{% static 'images/jakresit_1.svg' %}" /> |
|||
<img class="jakresit_obrazek" alt="" src="{% static 'images/jakresit_2.svg' %}" /> |
|||
<img class="jakresit_obrazek" alt="" src="{% static 'images/jakresit_3.svg' %}" /> |
|||
|
|||
</div> |
|||
{% 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,25 @@ |
|||
{% extends "base.html" %} |
|||
|
|||
|
|||
{% 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> |
|||
|
|||
<p style="text-align:justify"> </p> |
|||
|
|||
<h1>Aktuální témata</h1> |
|||
|
|||
{% for tematko in tematka %} |
|||
<h1>{{tematko.nazev}}</h1> |
|||
<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 %} |
|||
</div> |
|||
|
|||
<p>{{tematko.abstrakt}}</p> |
|||
<ul> |
|||
{% for cislo in tematko.cisla %} |
|||
<li><a href="/{{rocnik}}/t{{tematko.kod}}/#{{cislo.0.1}}">{{cislo.0.0}}</a></li> |
|||
<ul> |
|||
{% for odkaz in cislo.1 %} |
|||
<li><a href="/{{rocnik}}/t{{tematko.kod}}/#{{odkaz.1}}">{{odkaz.0}}</a></li> |
|||
{% endfor %} |
|||
</ul> |
|||
{% endfor %} |
|||
</ul> |
|||
{% endfor %} |
|||
{% endblock %} |
|||
|
@ -1,10 +1,12 @@ |
|||
{% extends "base.html" %} |
|||
{% load render_bundle from webpack_loader %} |
|||
|
|||
{% load comments %} |
|||
|
|||
{% 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 %} |
|||
|
@ -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 %} |
|||
{# <b>{{depth}}</b> #} |
|||
<div> |
|||
{% 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|isText %} |
|||
{{obj.node.text.na_web}} |
|||
{% else %} |
|||
Objekt jiného typu {{obj.node}} |
|||
<div class="borderized parent"> |
|||
<div class="node_type"> |
|||
{{obj.node}} |
|||
{{obj.node.id}} |
|||
{% if obj.node|deletable %} |
|||
<button type="submit" formaction="{%url 'treenode_smazat' obj.node.id%}">Smazat</button> |
|||
{% endif %} |
|||
{% if obj.parent and obj.parent|editableSiblings %} |
|||
<button type="submit" formaction="{%url 'treenode_odvesitpryc' obj.node.id%}">Odvěsit pryč ze stromu {{obj.parent.node}}</button> |
|||
{% endif %} |
|||
{% if obj|canPodvesitPred %} |
|||
<button type="submit" formaction="{%url 'treenode_podvesit' obj.node.id 'pred'%}">Podvěsit pod předchozí</button> - nejsou testovací data |
|||
{% endif %} |
|||
{% if obj|canPodvesitZa %} |
|||
<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 %} |
|||
{%if obj.children %} |
|||
<div> |
|||
{%for ch in obj.children %} |
|||
{%with obj=ch depth=depth|add:"1" template_name="seminar/treenode_recursive.html" %} |
|||
{%include template_name%} |
|||
{%endwith%} |
|||
{%endfor%} |
|||
{% include "seminar/treenode_name.html" %} |
|||
{%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 %} |
|||
|
|||
{# ----------- Vypisujeme podstrom ----------#} |
|||
{%with obj=ch depth=depth|add:"1" %} {%include "seminar/treenode_recursive.html" %} {%endwith%} |
|||
{# ----------- 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> |
|||
{% endfor %} |
|||
</div> |
|||
{%endif%} |
|||
{% else %} |
|||
{# ----------- Přidáváme prvního syna ----------#} |
|||
{% with kam="jako syna" kam_slug="syn" %} {% include "seminar/treenode_add_stub.html" %} {% endwith %} |
|||
{%endif%} |
|||
</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,49 +1,243 @@ |
|||
from django import template |
|||
from enum import Enum |
|||
import seminar.models as m |
|||
|
|||
register = template.Library() |
|||
|
|||
@register.filter |
|||
def nodeType(value): |
|||
if isinstance(value,RocnikNode): return "Ročník" |
|||
if isinstance(value,CisloNode): return "Číslo" |
|||
if isinstance(value,CastNode): return "Část" |
|||
if isinstance(value,TextNode): return "Text" |
|||
if isinstance(value,TemaVCisleNode): return "Téma v čísle" |
|||
if isinstance(value,KonferaNode): return "Konfera" |
|||
if isinstance(value,ClanekNode): return "Článek" |
|||
if isinstance(value,UlohaVzorakNode): return "Vzorák" |
|||
if isinstance(value,UlohaZadaniNode): return "Zadání úlohy" |
|||
if isinstance(value,PohadkaNode): return "Pohádka" |
|||
|
|||
### NASLEDUJICI FUNKCE SE POUZIVAJI VE views_all.py V SEKCI PRIPRAVJICI TNLData |
|||
### NEMAZAT, PRESUNOUT S TNLDaty NEKAM BOKEM |
|||
|
|||
@register.filter |
|||
def isRocnik(value): |
|||
return isinstance(value, m.RocnikNode) |
|||
return isinstance(value, m.RocnikNode) |
|||
|
|||
@register.filter |
|||
def isCislo(value): |
|||
return isinstance(value, m.CisloNode) |
|||
return isinstance(value, m.CisloNode) |
|||
|
|||
@register.filter |
|||
def isCast(value): |
|||
return isinstance(value, m.CastNode) |
|||
return isinstance(value, m.CastNode) |
|||
|
|||
@register.filter |
|||
def isText(value): |
|||
return isinstance(value, m.TextNode) |
|||
return isinstance(value, m.TextNode) |
|||
|
|||
@register.filter |
|||
def isTemaVCisle(value): |
|||
return isinstance(value, m.TemaVCisleNode) |
|||
return isinstance(value, m.TemaVCisleNode) |
|||
|
|||
@register.filter |
|||
def isKonfera(value): |
|||
return isinstance(value, m.KonferaNode) |
|||
return isinstance(value, m.KonferaNode) |
|||
|
|||
@register.filter |
|||
def isClanek(value): |
|||
return isinstance(value, m.ClanekNode) |
|||
return isinstance(value, m.ClanekNode) |
|||
|
|||
@register.filter |
|||
def isUlohaVzorak(value): |
|||
return isinstance(value, m.UlohaVzorakNode) |
|||
return isinstance(value, m.UlohaVzorakNode) |
|||
|
|||
@register.filter |
|||
def isUlohaZadani(value): |
|||
return isinstance(value, m.UlohaZadaniNode) |
|||
return isinstance(value, m.UlohaZadaniNode) |
|||
|
|||
@register.filter |
|||
def isPohadka(value): |
|||
return isinstance(value, m.PohadkaNode) |
|||
return isinstance(value, m.PohadkaNode) |
|||
|
|||
@register.filter |
|||
def isReseni(value): |
|||
return False |
|||
# return isinstance(value, m.OtisteneReseniNode) |
|||
|
|||
@register.filter |
|||
def isOrgText(value): |
|||
return False |
|||
# return isinstance(value, m.OrgTextNode) |
|||
|
|||
|
|||
### |
|||
|
|||
#@register.filter |
|||
#def podvesitelneNody(value): |
|||
# if isText() |
|||
|
|||
@register.filter |
|||
def deletable(value): |
|||
if isTemaVCisle(value): |
|||
return True |
|||
if isOrgText(value): |
|||
return True |
|||
if isReseni(value): |
|||
return True |
|||
if isUlohaZadani(value): |
|||
return True |
|||
if isUlohaVzorak(value): |
|||
return True |
|||
if isCast(value): |
|||
return True |
|||
if isText(value): |
|||
return True |
|||
return False |
|||
|
|||
@register.filter |
|||
def editableSiblings(value): |
|||
if isCast(value.node): |
|||
return True |
|||
if isText(value.node): |
|||
return True |
|||
if isReseni(value.node) and value.tema_in_path: |
|||
return True |
|||
if isUlohaZadani(value.node) and value.tema_in_path: |
|||
return True |
|||
if isUlohaVzorak(value.node) and value.tema_in_path: |
|||
return True |
|||
return False |
|||
|
|||
@register.filter |
|||
def editableChildren(value): |
|||
if isRocnik(value.node): |
|||
return False |
|||
if isCislo(value.node): |
|||
return False |
|||
if isText(value.node): |
|||
return False |
|||
return True |
|||
|
|||
@register.filter |
|||
def textOnlySubtree(value): |
|||
text_only = True |
|||
if isText(value.node): |
|||
return True |
|||
if not isCast(value.node): |
|||
return False |
|||
for ch in value.children: |
|||
if not textOnlySubtree(ch): |
|||
return False |
|||
return True |
|||
|
|||
def canPodvesit(obj,new_parent): |
|||
if isCast(new_parent.node): |
|||
# print("Lze",obj,new_parent) |
|||
return True |
|||
if textOnlySubtree(obj): |
|||
# print("Lze",obj,new_parent) |
|||
return True |
|||
return False |
|||
|
|||
@register.filter |
|||
def canPodvesitZa(value): |
|||
if not value.index or value.index+1 >= len(value.parent.children): |
|||
return False |
|||
new_parent = value.parent.children[value.index+1] |
|||
return canPodvesit(value,new_parent) |
|||
|
|||
@register.filter |
|||
def canPodvesitPred(value): |
|||
if not value.index or value.index <= 0: |
|||
return False |
|||
new_parent = value.parent.children[value.index-1] |
|||
return canPodvesit(value,new_parent) |
|||
|
|||
|
|||
class NodeTypes(Enum): |
|||
ROCNIK = ('rocnikNode','Ročník') |
|||
CISLO = ('cisloNode', 'Číslo') |
|||
MEZICISLO = ('mezicisloNode', 'Mezičíslo') |
|||
CAST = ('castNode', 'Část') |
|||
TEXT = ('textNode', 'Text') |
|||
TEMAVCISLE = ('temaVCisleNode', 'Téma v čísle') |
|||
RESENI = ('reseniNode','Řešení') |
|||
ULOHAZADANI = ('ulohaZadaniNode','Zadání') |
|||
ULOHAVZORAK = ('ulohaVzorakNode','Vzorák') |
|||
POHADKA = ('pohadkaNode','Pohádka') |
|||
ORGTEXT = ('orgText','Orgtext') |
|||
|
|||
|
|||
|
|||
|
|||
@register.simple_tag |
|||
def appendableChildren(value): |
|||
print(value) |
|||
print(value.node) |
|||
print(isUlohaZadani(value.node)) |
|||
if isTemaVCisle(value.node): |
|||
return (NodeTypes.RESENI.value[0], |
|||
NodeTypes.ULOHAZADANI.value[0], |
|||
NodeTypes.ULOHAVZORAK.value[0], |
|||
NodeTypes.CAST.value[0], |
|||
NodeTypes.TEXT.value[0], |
|||
) |
|||
if isOrgText(value.node) or isReseni(value.node) or isUlohaZadani(value.node) or isUlohaVzorak(value.node): |
|||
print("Text/Cast") |
|||
return (NodeTypes.CAST.value[0], |
|||
NodeTypes.TEXT.value[0], |
|||
) |
|||
if isCast(value.node): |
|||
return appendableChildren(value.parent) |
|||
return [] |
|||
|
|||
@register.simple_tag |
|||
def canAppendReseni(value): |
|||
if isTemaVCisle(value.node): |
|||
return True |
|||
if isCast(value.node): |
|||
return canAppendReseni(value.parent) |
|||
return False |
|||
|
|||
@register.simple_tag |
|||
def canAppendUlohaZadani(value): |
|||
if isTemaVCisle(value.node): |
|||
return True |
|||
if isCast(value.node): |
|||
return canAppendUlohaZadani(value.parent) |
|||
return False |
|||
|
|||
@register.simple_tag |
|||
def canAppendUlohaVzorak(value): |
|||
if isTemaVCisle(value.node): |
|||
return True |
|||
if isCast(value.node): |
|||
return canAppendUlohaVzorak(value.parent) |
|||
return False |
|||
|
|||
@register.simple_tag |
|||
def canAppendCast(value): |
|||
if isTemaVCisle(value.node) or isOrgText(value.node) or isReseni(value.node) or isUlohaZadani(value.node) or isUlohaVzorak(value.node): |
|||
return True |
|||
if isCast(value.node): |
|||
return canAppendCast(value.parent) |
|||
return False |
|||
|
|||
@register.simple_tag |
|||
def canAppendText(value): |
|||
if isTemaVCisle(value.node) or isOrgText(value.node) or isReseni(value.node) or isUlohaZadani(value.node) or isUlohaVzorak(value.node): |
|||
return True |
|||
if isCast(value.node): |
|||
return canAppendText(value.parent) |
|||
return False |
|||
|
|||
#@register.filter |
|||
#def is(value): |
|||
# return |
|||
# |
|||
# NodeTypes..value, |
|||
#@register.filter |
|||
#def isOtisteneReseniNode(value): |
|||
# return isinstance(value, m.OtisteneReseniNode) |
|||
#def is(value): |
|||
# return |
|||
|
|||
|
@ -1,2 +1,3 @@ |
|||
from .views_all import * |
|||
from .autocomplete import * |
|||
from .views_rest 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,77 @@ |
|||
from rest_framework import viewsets,filters |
|||
from . import models as m |
|||
from . import views |
|||
|
|||
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(viewsets.ModelViewSet): |
|||
queryset = m.UlohaVzorakNode.objects.all() |
|||
serializer_class = views.UlohaVzorakNodeSerializer |
|||
|
|||
class TextViewSet(viewsets.ModelViewSet): |
|||
queryset = m.Text.objects.all() |
|||
serializer_class = views.TextSerializer |
|||
|
|||
class TextNodeViewSet(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): |
|||
queryset = m.CastNode.objects.all() |
|||
read_serializer_class = views.CastNodeSerializer |
|||
write_serializer_class = views.CastNodeSerializer |
|||
create_serializer_class = views.CastNodeCreateSerializer |
|||
|
|||
class UlohaVzorakNodeViewSet(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) |
|||
return queryset |
@ -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,70 @@ |
|||
<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, |
|||
editorMode: Boolean, |
|||
debugMode: Boolean, |
|||
}, |
|||
mounted: function() { |
|||
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,74 @@ |
|||
<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, |
|||
}, |
|||
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,28 @@ |
|||
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 |
|||
}, |
|||
] |
|||
}) |
|||
|
@ -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