first commit
This commit is contained in:
commit
1699990c02
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
node_modules
|
||||||
|
package-lock.json
|
||||||
|
__pycache__
|
||||||
|
|
||||||
|
build/*
|
||||||
|
!build/Makefile
|
||||||
|
!build/browserify.js
|
||||||
|
|
||||||
|
|
41
build/Makefile
Normal file
41
build/Makefile
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
SRC_FOLDER=$(CURDIR)/../src
|
||||||
|
RES_FOLDER=$(CURDIR)/../res
|
||||||
|
|
||||||
|
TS_BUILD=tsbuild
|
||||||
|
TS_FLAGS=-da -n -m -od ../build/$(TS_BUILD) # has to be relative for some reason
|
||||||
|
|
||||||
|
LESS_FILE=$(RES_FOLDER)/main.less
|
||||||
|
PY_FILE=$(SRC_FOLDER)/main.py
|
||||||
|
HTML_FILE=$(RES_FOLDER)/main.html
|
||||||
|
|
||||||
|
.PHONY: all transcrypt $(LESS_FILE) $(PY_FILE) $(HTML_FILE)
|
||||||
|
|
||||||
|
|
||||||
|
# mypy:
|
||||||
|
# mypy src/main.py
|
||||||
|
|
||||||
|
all: main.css bundle.js main.html
|
||||||
|
|
||||||
|
transcrypt: $(PY_FILE) $(TS_BUILD)
|
||||||
|
# ln -s $(TS_BUILD) $(SRC_FOLDER)/__target__
|
||||||
|
transcrypt $(TS_FLAGS) $<
|
||||||
|
# rm $(SRC_FOLDER)/__target__
|
||||||
|
|
||||||
|
bundle.js: transcrypt
|
||||||
|
node browserify.js $(TS_BUILD)/main.js > bundle.js
|
||||||
|
|
||||||
|
main.css: $(LESS_FILE)
|
||||||
|
lessc $< > $@
|
||||||
|
|
||||||
|
$(TS_BUILD):
|
||||||
|
mkdir -p $(TS_BUILD)
|
||||||
|
|
||||||
|
main.html: $(HTML_FILE)
|
||||||
|
cp $(RES_FOLDER)/main.html ./
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -r $(TS_BUILD)
|
||||||
|
rm bundle.js main.html main.css
|
||||||
|
|
||||||
|
|
||||||
|
|
11
build/browserify.js
Normal file
11
build/browserify.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
var browserify = require('browserify');
|
||||||
|
var esmify = require('esmify');
|
||||||
|
|
||||||
|
var bundler = browserify({
|
||||||
|
debug: true,
|
||||||
|
paths: ["../node_modules/snabbdom/"],
|
||||||
|
plugin: [esmify]
|
||||||
|
});
|
||||||
|
|
||||||
|
bundler.add(process.argv[2]);
|
||||||
|
bundler.bundle().pipe(process.stdout);
|
20
package.json
Normal file
20
package.json
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"name": "vsms-py",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Trying out using transcrypt!",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "Ozbolt Menegatti",
|
||||||
|
"license": "MPL2",
|
||||||
|
"devDependencies": {
|
||||||
|
"sorcery": "^0.10.0",
|
||||||
|
"sourceify": "^1.0.0",
|
||||||
|
"tinyify": "^2.5.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"browserify": "^16.5.0",
|
||||||
|
"esmify": "^2.1.1",
|
||||||
|
"snabbdom": "^0.7.3"
|
||||||
|
}
|
||||||
|
}
|
BIN
res/line.png
Normal file
BIN
res/line.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 81 B |
13
res/main.html
Normal file
13
res/main.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>PYVsms</title>
|
||||||
|
<link rel="stylesheet" href="main.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>My First App</h1>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script src="bundle.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
192
res/main.less
Normal file
192
res/main.less
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
@title-color: #cc3366;
|
||||||
|
@line-image: "./line.png";
|
||||||
|
|
||||||
|
.translation-element-margin {
|
||||||
|
margin: 0 0.3em;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.translation-button {
|
||||||
|
width: 1.5em;
|
||||||
|
height: 1.5em;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.elm-div {
|
||||||
|
clear: both;
|
||||||
|
overflow: auto;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#entry {
|
||||||
|
#entry-header {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
|
||||||
|
#headword {
|
||||||
|
font-size: 1.2em;
|
||||||
|
color: @title-color;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#grammar {
|
||||||
|
color: #666666;
|
||||||
|
font-style: italic;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#comment {
|
||||||
|
background-color: #e9d76d;
|
||||||
|
padding: 0.5em;
|
||||||
|
float: right;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: "Opomba: "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#sense-container {
|
||||||
|
border-top: 1px dotted #999999;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
|
||||||
|
.sense-num {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sense {
|
||||||
|
margin-left: 2em;
|
||||||
|
|
||||||
|
.sense-definition {
|
||||||
|
display: inline;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0 0.2em;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #CCCCCC;
|
||||||
|
}
|
||||||
|
&:after {
|
||||||
|
content: ")";
|
||||||
|
}
|
||||||
|
&:before {
|
||||||
|
content: "(";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.sense-label {
|
||||||
|
display: inline;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0 0.2em;
|
||||||
|
color: lightgreen;
|
||||||
|
font-size: 0.8em;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #CCCCCC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.translation-div {
|
||||||
|
display: inline;
|
||||||
|
|
||||||
|
.translation-tags {
|
||||||
|
display: inline;
|
||||||
|
color: green;
|
||||||
|
font-size: 0.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.translation-text {
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline;
|
||||||
|
color: blue;
|
||||||
|
.translation-element-margin();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
.translation-element-margin();
|
||||||
|
.translation-button();
|
||||||
|
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
|
||||||
|
background-size: 100%;
|
||||||
|
background-repeat: repeat-y;
|
||||||
|
color: rgba(0,0,0,0);
|
||||||
|
background-image: data-uri(@line-image); //url(line.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #CCCCCC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.translation-add {
|
||||||
|
.translation-element-margin();
|
||||||
|
.translation-button();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.example {
|
||||||
|
.example-dot, .example-rest {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-arrow, .example-dot {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#xml-status {
|
||||||
|
margin-left: 3em;
|
||||||
|
height: 1em;
|
||||||
|
margin-bottom: -1em;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xml-status-bad { color: red; }
|
||||||
|
.xml-status-good { color: green; }
|
||||||
|
.xml-status-wait { color: yellow; }
|
||||||
|
|
||||||
|
|
||||||
|
#log {
|
||||||
|
overflow: scroll;
|
||||||
|
border: 2px solid red;
|
||||||
|
height: 10em;
|
||||||
|
|
||||||
|
:nth-last-child(odd) {
|
||||||
|
background-color: lightgray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sweet modal edit entry
|
||||||
|
|
||||||
|
.tag-div {
|
||||||
|
.tag-key {
|
||||||
|
width: 10em;
|
||||||
|
display: inline-block
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-input {
|
||||||
|
margin-left: 1em;
|
||||||
|
width: 9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
width: 9em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#cluster-group-div {
|
||||||
|
margin-top: 1em;
|
||||||
|
span {
|
||||||
|
width: 10em;
|
||||||
|
display: inline-block
|
||||||
|
}
|
||||||
|
}
|
4
src/browser/__init__.py
Normal file
4
src/browser/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
from browser.internal import Document, Window # type: ignore
|
||||||
|
|
||||||
|
document = Document()
|
||||||
|
window = Window()
|
15
src/browser/internal.py
Normal file
15
src/browser/internal.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
class Document:
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
return lambda x: document[attr](x)
|
||||||
|
|
||||||
|
|
||||||
|
class Window:
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
return lambda x: window[attr](x)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
76
src/main.py
Normal file
76
src/main.py
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
from snabbdom import h, patch
|
||||||
|
|
||||||
|
|
||||||
|
from browser import document
|
||||||
|
from model import Model
|
||||||
|
from view import View
|
||||||
|
from update import update
|
||||||
|
|
||||||
|
|
||||||
|
model = Model()
|
||||||
|
|
||||||
|
|
||||||
|
def main(xml_str):
|
||||||
|
model.import_xml(xml_str)
|
||||||
|
update.set_view(View(document.getElementById("app")))
|
||||||
|
update.set_model(model)
|
||||||
|
update.update_model()
|
||||||
|
|
||||||
|
|
||||||
|
main("""<entry>
|
||||||
|
<head>
|
||||||
|
<status>A</status>
|
||||||
|
<headword>
|
||||||
|
<lemma>adolescenca</lemma>
|
||||||
|
</headword>
|
||||||
|
<grammar>
|
||||||
|
<category>samostalnik</category>
|
||||||
|
</grammar>
|
||||||
|
<comment></comment>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<senseList>
|
||||||
|
<sense>
|
||||||
|
<labelList>
|
||||||
|
<label>tehnika</label>
|
||||||
|
</labelList>
|
||||||
|
<definitionList>
|
||||||
|
<definition type="indicator">obdobje</definition>
|
||||||
|
</definitionList>
|
||||||
|
<translationContainerList>
|
||||||
|
<translationContainer cluster="1">
|
||||||
|
<translation>preizkus</translation>
|
||||||
|
<explanation>explainme!</explanation>
|
||||||
|
<tagsContainer>
|
||||||
|
<tag><type>podrocje</type><value>biologija</value></tag>
|
||||||
|
</tagsContainer>
|
||||||
|
</translationContainer>
|
||||||
|
<translationContainer cluster="1">
|
||||||
|
<translation>fsd</translation>
|
||||||
|
</translationContainer>
|
||||||
|
<translationContainer cluster="2">
|
||||||
|
<translation>preskus</translation>
|
||||||
|
</translationContainer>
|
||||||
|
<translationContainer cluster="2">
|
||||||
|
<translation>sdfsd</translation>
|
||||||
|
<tagsContainer>
|
||||||
|
<tag><type>podrocje</type><value>ozboltologija</value></tag>
|
||||||
|
</tagsContainer>
|
||||||
|
</translationContainer>
|
||||||
|
<translationContainer cluster="3">
|
||||||
|
<translation>fsd</translation>
|
||||||
|
</translationContainer>
|
||||||
|
</translationContainerList>
|
||||||
|
<exampleContainerList>
|
||||||
|
<exampleContainer>
|
||||||
|
<example>The test was interesting.</example>
|
||||||
|
<translationContainer>
|
||||||
|
<translation>Preizkus je bil zanimiv.</translation>
|
||||||
|
</translationContainer>
|
||||||
|
</exampleContainer>
|
||||||
|
</exampleContainerList>
|
||||||
|
</sense>
|
||||||
|
</senseList>
|
||||||
|
</body>
|
||||||
|
</entry>""")
|
||||||
|
|
9
src/message/__init__.py
Normal file
9
src/message/__init__.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
from message.simple_messages import ListItemClick
|
||||||
|
|
||||||
|
|
||||||
|
def msg(message_class):
|
||||||
|
from update import update
|
||||||
|
def callback(arg):
|
||||||
|
message_instance = message_class(arg)
|
||||||
|
update.schedule(message_instance)
|
||||||
|
return callback
|
3
src/message/message.py
Normal file
3
src/message/message.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
class Message:
|
||||||
|
def update_model(self, model):
|
||||||
|
raise NotImplementedError("This message does not implement update_model method")
|
10
src/message/simple_messages.py
Normal file
10
src/message/simple_messages.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from message.message import Message
|
||||||
|
|
||||||
|
|
||||||
|
class ListItemClick(Message):
|
||||||
|
def __init__(self, num):
|
||||||
|
self.num = num
|
||||||
|
|
||||||
|
def update_model(self, model):
|
||||||
|
print(self.num)
|
||||||
|
model.names.splice(self.num, 1)
|
1
src/model/__init__.py
Normal file
1
src/model/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from model.model import Model
|
17
src/model/entry.py
Normal file
17
src/model/entry.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
from model.sense import Sense
|
||||||
|
|
||||||
|
class Entry:
|
||||||
|
def __init__(self, entry_xml):
|
||||||
|
status = entry_xml.querySelector("head status")
|
||||||
|
headword = entry_xml.querySelector("head headword lemma")
|
||||||
|
grammar = entry_xml.querySelector("head grammar category")
|
||||||
|
comment = entry_xml.querySelector("head comment")
|
||||||
|
|
||||||
|
self.status = status.textContent if status else ""
|
||||||
|
self.headword = headword.textContent if headword else ""
|
||||||
|
self.grammar = grammar.textContent if grammar else ""
|
||||||
|
self.comment = comment.textContent if comment else ""
|
||||||
|
|
||||||
|
self.senses = [Sense(sense_xml) for sense_xml in
|
||||||
|
entry_xml.querySelectorAll("body senseList sense")]
|
||||||
|
|
8
src/model/example.py
Normal file
8
src/model/example.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
class Example:
|
||||||
|
def __init__(self, example_xml):
|
||||||
|
example = example_xml.querySelector("example")
|
||||||
|
translation = example_xml.querySelector("translationContainer translation")
|
||||||
|
|
||||||
|
self.example = example.textContent if example else ""
|
||||||
|
self.translation = translation.textContent if translation else ""
|
||||||
|
|
25
src/model/model.py
Normal file
25
src/model/model.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
from model.entry import Entry
|
||||||
|
|
||||||
|
|
||||||
|
class Model:
|
||||||
|
def __init__(self, names):
|
||||||
|
self.entry = None
|
||||||
|
self.log = []
|
||||||
|
self.names = ["Ozbolt", "Katarina"]
|
||||||
|
|
||||||
|
|
||||||
|
def import_xml(self, xml_text):
|
||||||
|
parser = __new__(DOMParser())
|
||||||
|
xmlDoc = parser.parseFromString(xml_text, "text/xml")
|
||||||
|
self.entry = Entry(xmlDoc.querySelector("entry"))
|
||||||
|
|
||||||
|
|
||||||
|
# type alias Model =
|
||||||
|
# { shown: Bool
|
||||||
|
# , editable: Bool
|
||||||
|
# , entry: Maybe Entry
|
||||||
|
# , newXml: Bool
|
||||||
|
# , xml: Maybe String
|
||||||
|
# , xmlObject: Maybe Xml2.Value
|
||||||
|
# , log: List LogEntry
|
||||||
|
# }
|
27
src/model/sense.py
Normal file
27
src/model/sense.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
from model.example import Example
|
||||||
|
from model.translation import Translation
|
||||||
|
|
||||||
|
class Sense:
|
||||||
|
def __init__(self, sense_xml):
|
||||||
|
label = sense_xml.querySelector("labelList label")
|
||||||
|
definition = sense_xml.querySelector("definitionList definition")
|
||||||
|
|
||||||
|
self.label = label.textContent if label else ""
|
||||||
|
self.definition = definition.textContent if definition else ""
|
||||||
|
|
||||||
|
self.examples = [Example(example_xml) for example_xml in
|
||||||
|
sense_xml.querySelectorAll("exampleContainerList exampleContainer")]
|
||||||
|
|
||||||
|
translations = []
|
||||||
|
max_num_cluster = 0
|
||||||
|
|
||||||
|
for translation_xml in sense_xml.querySelectorAll("translationContainerList translationContainer"):
|
||||||
|
num_cluster = int(translation_xml.getAttribute("cluster"))
|
||||||
|
max_num_cluster = max(max_num_cluster, num_cluster)
|
||||||
|
translations.append((num_cluster, Translation(translation_xml)))
|
||||||
|
|
||||||
|
self.translations = [[] for _ in range(max_num_cluster)]
|
||||||
|
for clusterNum, translation in translations:
|
||||||
|
self.translations[clusterNum - 1].append(translation)
|
||||||
|
|
||||||
|
|
10
src/model/translation.py
Normal file
10
src/model/translation.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
class Translation:
|
||||||
|
def __init__(self, translation_xml):
|
||||||
|
translation = translation_xml.querySelector("translation")
|
||||||
|
self.translation = translation.textContent if translation else ""
|
||||||
|
|
||||||
|
self.tags = {}
|
||||||
|
for tag_xml in translation_xml.querySelectorAll("tagsContainer tag"):
|
||||||
|
t_type = tag_xml.querySelector("type").textContent
|
||||||
|
t_value = tag_xml.querySelector("value").textContent
|
||||||
|
self.tags[t_type] = t_value
|
17
src/snabbdom.py
Normal file
17
src/snabbdom.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
__pragma__ ('noanno')
|
||||||
|
__pragma__ ('js', """
|
||||||
|
var snabbdom = require('snabbdom.js');
|
||||||
|
|
||||||
|
var s_patch = snabbdom.init([ // Init patch function with chosen modules
|
||||||
|
require('snabbdom/modules/class').default, // makes it easy to toggle classes
|
||||||
|
require('snabbdom/modules/props').default, // for setting properties on DOM elements
|
||||||
|
require('snabbdom/modules/style').default, // handles styling on elements with support for animations
|
||||||
|
require('snabbdom/modules/eventlisteners').default, // attaches event listeners
|
||||||
|
]);
|
||||||
|
var s_h = require('snabbdom/h').default; // helper function for creating vnodes
|
||||||
|
""", None)
|
||||||
|
|
||||||
|
# export the symbols
|
||||||
|
|
||||||
|
h = s_h
|
||||||
|
patch = s_patch
|
27
src/update.py
Normal file
27
src/update.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
class Update:
|
||||||
|
def __init__(self):
|
||||||
|
self.message_queue = []
|
||||||
|
self.model = None
|
||||||
|
self.view = None
|
||||||
|
|
||||||
|
def update_model(self):
|
||||||
|
for msg in self.message_queue:
|
||||||
|
msg.update_model(self.model)
|
||||||
|
|
||||||
|
self.message_queue = []
|
||||||
|
self.view.view(self.model)
|
||||||
|
|
||||||
|
def schedule(self, msg):
|
||||||
|
self.message_queue.append(msg)
|
||||||
|
# for now, directly clearing message queue
|
||||||
|
self.update_model()
|
||||||
|
|
||||||
|
def set_model(self, model):
|
||||||
|
self.model = model
|
||||||
|
|
||||||
|
def set_view(self, view):
|
||||||
|
self.view = view
|
||||||
|
|
||||||
|
|
||||||
|
update = Update()
|
||||||
|
|
98
src/view.py
Normal file
98
src/view.py
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
from snabbdom import h, patch
|
||||||
|
from message import ListItemClick, msg
|
||||||
|
|
||||||
|
|
||||||
|
class View:
|
||||||
|
def __init__(self, container):
|
||||||
|
self.vdom = h('div', {}, "Loading...")
|
||||||
|
self.model = None
|
||||||
|
patch(container, self.vdom)
|
||||||
|
|
||||||
|
def view(self, model):
|
||||||
|
self.model = model
|
||||||
|
new_vdom = self._view()
|
||||||
|
patch(self.vdom, new_vdom)
|
||||||
|
self.vdom = new_vdom
|
||||||
|
|
||||||
|
def _view(self):
|
||||||
|
return View.view_entry(self.model.entry)
|
||||||
|
|
||||||
|
def view_list_elements(self):
|
||||||
|
def callback(num):
|
||||||
|
return msg(lambda: ListItemClick(num))
|
||||||
|
|
||||||
|
list_elements = [
|
||||||
|
h('li', {"on": {"click": callback(idx)}}, name)
|
||||||
|
for idx, name in enumerate(self.model.names)
|
||||||
|
]
|
||||||
|
return h('ol', {}, list_elements)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def view_entry(entry):
|
||||||
|
view_sense_list = [View.view_sense(sense, idx) for idx, sense in enumerate(entry.senses)]
|
||||||
|
|
||||||
|
return h("div#entry", {}, [
|
||||||
|
h("div#entry-status", {}, entry.status),
|
||||||
|
h("div#entry-header", {}, [
|
||||||
|
h("span#headword", {}, entry.headWord),
|
||||||
|
h("span#grammar", {}, entry.grammar),
|
||||||
|
h("span#comment", {}, entry.comment)]),
|
||||||
|
h("div#sense-container", {}, view_sense_list)])
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def view_sense(sense, senseNum):
|
||||||
|
examples = [View.view_example(example) for example in sense.examples]
|
||||||
|
|
||||||
|
return h("div.elm-div", {}, [
|
||||||
|
h("div.sense-num", {}, str(senseNum + 1)),
|
||||||
|
h("div.sense", {}, [
|
||||||
|
h("span.sense-label", {}, sense.label),
|
||||||
|
h("span.sense-definition", {}, sense.definition),
|
||||||
|
h("div", {}, View.view_translations(sense.translations)),
|
||||||
|
h("div", {}, examples),
|
||||||
|
h("input#translation-add",
|
||||||
|
{"attr": {"type": "button", "value": "+", "title": "Dodaj prevedek / HUN"}},
|
||||||
|
[])])])
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def view_example(example):
|
||||||
|
return h("div.example", {}, [
|
||||||
|
h("div.example-dot", {}, "▣"),
|
||||||
|
h("div.example-rest", {}, [
|
||||||
|
h("span.example-text", {}, example.example),
|
||||||
|
h("div.example-translation", {}, [
|
||||||
|
h("span.example-arrow", {}, "↪"),
|
||||||
|
h("span", {}, example.translation)])])])
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def view_translations(translations):
|
||||||
|
joiner = lambda: h("span.translation-semicolon", {}, ";")
|
||||||
|
result = []
|
||||||
|
|
||||||
|
for cluster in translations:
|
||||||
|
result.extend([View.view_one_translation(t) for t in cluster])
|
||||||
|
result.append(joiner())
|
||||||
|
|
||||||
|
result.pop()
|
||||||
|
return result
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def view_one_translation(translation):
|
||||||
|
elements = []
|
||||||
|
|
||||||
|
if translation.tags:
|
||||||
|
tags = h("div.translation-tags", {}, [
|
||||||
|
h("span", {"attr": {"title": key}}, value)
|
||||||
|
for key, value in translation.tags.items()])
|
||||||
|
elements.append(tags)
|
||||||
|
|
||||||
|
elements.append(h("span.translation-text", {}, translation.translation))
|
||||||
|
#elements.append(h("select.translation-select", {}, [
|
||||||
|
# h("option", {"style": {"color": "black"}, {"attr": {"value": "edit", "title": "Spremeni"}}}, "✎"),
|
||||||
|
# h("option", {"style": {"color": "black"}, {"attr": {"value": "right", "title": "Desno"}}}, "→"),
|
||||||
|
# h("option", {"style": {"color": "black"}, {"attr": {"value": "left", "title": "Levo"}}}, "←"),
|
||||||
|
# h("option", {"style": {"color": "black"}, {"attr": {"value": "bin", "title": "Odstrani"}}}, "🗑")]))
|
||||||
|
|
||||||
|
return h("div.translation-div", {}, elements)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user