Compare commits

..

No commits in common. "master" and "mt-initial-setup" have entirely different histories.

26 changed files with 356 additions and 628 deletions

2
.gitignore vendored
View File

@ -10,5 +10,5 @@ build/*
# using kdev4, works fairly nicely! # using kdev4, works fairly nicely!
.kdev4 .kdev4
**/*.kdev4 **/*.kdev4
remote

View File

@ -1,3 +1,5 @@
.PHONY: all release build transcrypt copy $(RES_LESS_FILE) $(RES_PY_FILE) $(RES_HTML_FILE) $(RES_XML_FILE)
SRC_FOLDER=$(CURDIR)/../src SRC_FOLDER=$(CURDIR)/../src
RES_FOLDER=$(CURDIR)/../res RES_FOLDER=$(CURDIR)/../res
@ -18,7 +20,6 @@ RES_PY_FILE=$(SRC_FOLDER)/$(PY_FILE)
RES_HTML_FILE=$(RES_FOLDER)/$(HTML_FILE) RES_HTML_FILE=$(RES_FOLDER)/$(HTML_FILE)
RES_XML_FILE=$(RES_FOLDER)/$(XML_FILE) RES_XML_FILE=$(RES_FOLDER)/$(XML_FILE)
.PHONY: all release build transcrypt copy $(RES_LESS_FILE) $(RES_PY_FILE) $(RES_HTML_FILE) $(RES_XML_FILE) $(CONV_FILE)
.DEFAULT_GOAL := all .DEFAULT_GOAL := all
all: BR_FLAGS := $(BR_FLAGS) --debug all: BR_FLAGS := $(BR_FLAGS) --debug

View File

@ -4,10 +4,10 @@
############################################################################# #############################################################################
# Alter these variables # Alter these variables
#USERNAME=vps_sign_in(probably name@lexonomy.cjvt.si #USERNAME= vps_sign_in(probably name@lexonomy.cjvt.si
#VPS_PASSWORD=vps password #VPS_PASSWORD= vps password
#VPS_USERNAME=user name inside vps(probably name from @lexonomy) #VPS_USERNAME= user name inside vps(probably name from @lexonomy)
#API_KEY=$(cat path/to/api/token/file) #API_KEY= $(cat path/to/api/token/file)
# Exit if no argument is passed on run # Exit if no argument is passed on run
if [[ -z "$1" ]]; then if [[ -z "$1" ]]; then
@ -24,4 +24,4 @@ tar czf - ./config.json ./bundle.js ./local.js ./main.css ./main.html | ssh $USE
# Create a simlink on VPS that will enable specific plugin on https://lexonomy.cjvt.si/ # Create a simlink on VPS that will enable specific plugin on https://lexonomy.cjvt.si/
# Routes must be absolute or it doesn't work. # Routes must be absolute or it doesn't work.
ssh -t $USERNAME -p $VPS_PASSWORD "sudo -s unlink /home/ozbolt/plugins/$PLUGIN_NAME || true && sudo ln -s /home/$VPS_USERNAME/plugins/$PLUGIN_NAME /home/ozbolt/plugins/$PLUGIN_NAME" ssh -t $USERNAME -p $VPS_PASSWORD "sudo ln -s /home/$VPS_USERNAME/plugins/$PLUGIN_NAME /home/ozbolt/plugins/$PLUGIN_NAME"

View File

@ -3,20 +3,16 @@
# fail if any command fails # fail if any command fails
set -e set -e
OUT_FILE=conversions.csv
if [[ -z "${API_KEY}" ]]; then if [[ -z "${API_KEY}" ]]; then
echo "API_KEY not defined, should be api key to CJVT's gitea" echo "API_KEY not defined, should be api key to CJVT's gitea"
exit 1 exit 1
fi fi
if [ -f $OUT_FILE ]; then OUT_FILE=conversions.csv
echo "file for conversion of SKE collocations: '$OUT_FILE' already exists, skipping."
exit 0
fi
TEMP_FILE=$(mktemp) TEMP_FILE=$(mktemp)
rm -r $OUT_FILE
curl -s "https://gitea.cjvt.si/api/v1/repos/generic/data_admin/contents/resources/structure_conversions.csv?token=$API_KEY" -o $TEMP_FILE curl -s "https://gitea.cjvt.si/api/v1/repos/generic/data_admin/contents/resources/structure_conversions.csv?token=$API_KEY" -o $TEMP_FILE
echo "wc: $(wc $TEMP_FILE)" echo "wc: $(wc $TEMP_FILE)"
cat $TEMP_FILE | python3 -c "import sys, json; print(json.load(sys.stdin)['content'])" | base64 -d > $OUT_FILE cat $TEMP_FILE | python3 -c "import sys, json; print(json.load(sys.stdin)['content'])" | base64 -d > $OUT_FILE

View File

@ -64,13 +64,13 @@
margin-bottom: 1em; margin-bottom: 1em;
#headword { #headword {
font-size: 1.2em; font-size: 1.2em;
color: @darkred; color: @darkred;
font-weight: bold; font-weight: bold;
} }
#grammar { #grammar {
color: @gray; color: @gray;
font-style: italic; font-style: italic;
margin-left: 1em; margin-left: 1em;
} }
@ -90,8 +90,8 @@
} }
#sense-container { #sense-container {
border-top: 1px dotted #999999; border-top: 1px dotted #999999;
padding-top: 0.5em; padding-top: 0.5em;
margin-top: 0.5em; margin-top: 0.5em;
.sense-num { .sense-num {
@ -156,7 +156,16 @@
vertical-align: super; vertical-align: super;
font-size: 0.7em; font-size: 0.7em;
} }
.translation-explanation:not(:empty) {
font-style: italic;
&:before {
content: '[';
}
&:after {
content: ']';
}
}
} }
.translation-add { .translation-add {
@ -166,24 +175,10 @@
} }
} }
.explanations:not(:empty) {
font-style: italic;
&:not(.solo) {
&:before {
content: '[';
}
&:after {
content: ']';
}
}
}
.example { .example {
clear: left; clear: left;
margin-left: 1em; margin-left: 1em;
.example-dot, .example-rest { .example-dot, .example-rest {
float: left; float: left;
max-width: 90%; max-width: 90%;
@ -247,7 +242,7 @@
// if span left of input it is just too high, this is a fix // if span left of input it is just too high, this is a fix
.span-left-of-input { .span-left-of-input {
margin-top: 0.3em; margin-top: 0.3em;
} }
@ -262,7 +257,7 @@
.example-cluster { .example-cluster {
color: @blue; color: @blue;
} }
.example-logdice { .example-logdice {
color: @gray; color: @gray;
} }
.example-frequency { .example-frequency {
@ -294,7 +289,7 @@
.example-component-none { .example-component-none {
color: @gray; color: @gray;
} }
.example-component-no-space { .example-component-no-space {
color: @silver; color: @silver;
} }
@ -318,7 +313,7 @@
background-color: rgba(0,0, 0, 0.01); background-color: rgba(0,0, 0, 0.01);
padding: 0.5em; padding: 0.5em;
border: 2px solid gray; border: 2px solid gray;
margin: 1em; margin: 1em;
.ske-line { .ske-line {
display: block; display: block;
@ -330,13 +325,13 @@
.grey1 { .grey1 {
margin-left: 0.3em; margin-left: 0.3em;
background-color: @silver; background-color: @silver;
color: @black; color: @black;
} }
.grey2 { .grey2 {
margin-left: 0.3em; margin-left: 0.3em;
background-color: @black; background-color: @black;
color: @silver; color: @silver;
} }
.no-gf2-info { .no-gf2-info {
@ -379,7 +374,7 @@
// overflow: scroll; // overflow: scroll;
// border: 2px solid red; // border: 2px solid red;
// height: 10em; // height: 10em;
// //
// :nth-last-child(odd) { // :nth-last-child(odd) {
// background-color: lightgray; // background-color: lightgray;
// } // }

View File

@ -4,12 +4,7 @@
<head> <head>
<status>LBS</status> <status>LBS</status>
<headword> <headword>
<lemma>aplikativen3</lemma> <lemma>aplikativen</lemma>
<homonymy>
<homonymyFeature name="pronunciation">bolníšnica</homonymyFeature>
<homonymyFeature name="blahblah">xyz</homonymyFeature>
<homonymyFeature name="bluhbluh">abc</homonymyFeature>
</homonymy>
</headword> </headword>
<grammar> <grammar>
<category>pridevnik</category> <category>pridevnik</category>

View File

@ -5,12 +5,13 @@ from model.tags import export_tag
def export_to_xml(model): def export_to_xml(model):
xml_document = export_entry(model.entry) xml_document = export_entry(model.entry)
serializer = __new__(XMLSerializer()) serializer = __new__(XMLSerializer())
return serializer.serializeToString(xml_document) return serializer.serializeToString(xml_document);
def export_entry(entry): def export_entry(entry):
parser = __new__(DOMParser()) parser = __new__(DOMParser())
doc = parser.parseFromString("<entry />", "text/xml") doc = parser.parseFromString("<entry />", "text/xml")
entry_xml = doc.firstChild entry_xml = doc.firstChild
# create head # create head
@ -20,31 +21,15 @@ def export_entry(entry):
status = doc.createElement("status") status = doc.createElement("status")
status.textContent = entry.status status.textContent = entry.status
head.appendChild(status) head.appendChild(status)
headword = doc.createElement("headword") headword = doc.createElement("headword")
headword_lemma = doc.createElement("lemma") headword_lemma = doc.createElement("lemma")
# headword_lemma = entry.original_xml.querySelector("head headword lemma")
headword_lemma.textContent = entry.headword headword_lemma.textContent = entry.headword
if entry.headword_type is not None: if entry.headword_type is not None:
headword_lemma.setAttribute("type", entry.headword_type) headword_lemma.setAttribute("type", entry.headword_type)
if entry.headword_audio is not None:
headword_lemma.setAttribute("audio", entry.headword_audio)
headword.appendChild(headword_lemma) headword.appendChild(headword_lemma)
head.appendChild(headword) head.appendChild(headword)
homonymy = doc.createElement("homonymy")
headword.appendChild(homonymy)
for hFeature in entry.homonymy:
feature = doc.createElement("homonymyFeature")
feature.textContent = hFeature.value
# Can't use hFeature.name, because Python has name reserver and so it becomes py_name in JS
feature.setAttribute("name", hFeature["name"])
homonymy.appendChild(feature)
# if({}) works uncorrectly in transcrypt # if({}) works uncorrectly in transcrypt
if len(entry.lexical_unit) > 0: if len(entry.lexical_unit) > 0:
lexunit = doc.createElement("lexicalUnit") lexunit = doc.createElement("lexicalUnit")
@ -53,90 +38,86 @@ def export_entry(entry):
lexeme = doc.createElement("lexeme") lexeme = doc.createElement("lexeme")
lexeme.setAttribute("lexical_unit_lexeme_id", entry.lexical_unit["id"]) lexeme.setAttribute("lexical_unit_lexeme_id", entry.lexical_unit["id"])
lexeme.textContent = entry.lexical_unit["text"] lexeme.textContent = entry.lexical_unit["text"]
lexunit.appendChild(lexeme) lexunit.appendChild(lexeme)
head.appendChild(lexunit) head.appendChild(lexunit)
grammar = doc.createElement("grammar") grammar = doc.createElement("grammar")
grammar_category = doc.createElement("category") grammar_category = doc.createElement("category")
grammar_category.textContent = entry.grammar grammar_category.textContent = entry.grammar
grammar.appendChild(grammar_category) grammar.appendChild(grammar_category)
head.appendChild(grammar) head.appendChild(grammar)
if len(entry.measure) > 0: if len(entry.measure) > 0:
measure_list = doc.createElement("measureList") measure_list = doc.createElement("measureList")
measure = doc.createElement("measure") measure = doc.createElement("measure")
measure.setAttribute("source", entry.measure["source"]) measure.setAttribute("source", entry.measure["source"])
measure.setAttribute("type", entry.measure["type"]) measure.setAttribute("type", entry.measure["type"])
measure.textContent = entry.measure["text"] measure.textContent = entry.measure["text"]
measure_list.appendChild(measure) measure_list.appendChild(measure)
head.appendChild(measure_list) head.appendChild(measure_list)
variants = doc.createElement("variantList") variants = doc.createElement("variantList")
head.appendChild(variants) head.appendChild(variants)
for v in entry.variants: for v in entry.variants:
variant = doc.createElement("variant") variant = doc.createElement("variant")
variant.textContent = v variant.textContent = v
variants.appendChild(variant) variants.appendChild(variant)
relist = doc.createElement("relatedEntryList") relist = doc.createElement("relatedEntryList")
head.appendChild(relist) head.appendChild(relist)
for re in entry.related_entries: for re in entry.related_entries:
relateEntry = doc.createElement("relatedEntry") relateEntry = doc.createElement("relatedEntry")
relateEntry.textContent = re relateEntry.textContent = re
relist.appendChild(relateEntry) relist.appendChild(relateEntry)
head.appendChild(_export_label_list(doc, entry.labels)) head.appendChild(_export_label_list(doc, entry.labels))
comment = doc.createElement("comment") comment = doc.createElement("comment")
comment.textContent = entry.comment comment.textContent = entry.comment
head.appendChild(comment) head.appendChild(comment)
# now lets do body # now lets do body
body = doc.createElement("body") body = doc.createElement("body")
entry_xml.appendChild(body) entry_xml.appendChild(body)
sense_list = doc.createElement("senseList") sense_list = doc.createElement("senseList")
body.appendChild(sense_list) body.appendChild(sense_list)
for sense in entry.senses: for sense in entry.senses:
sense_list.appendChild(export_sense(doc, sense)) sense_list.appendChild(export_sense(doc, sense))
return doc return doc
def export_sense(doc, sense): def export_sense(doc, sense):
sense_xml = doc.createElement("sense") sense_xml = doc.createElement("sense")
sense_xml.appendChild(_export_label_list(doc, sense.labels)) sense_xml.appendChild(_export_label_list(doc, sense.labels))
definition_list = doc.createElement("definitionList") definition_list = doc.createElement("definitionList")
sense_xml.appendChild(definition_list) sense_xml.appendChild(definition_list)
for typ, text in sense.definition.items(): for typ, text in sense.definition.items():
definition = doc.createElement("definition") definition = doc.createElement("definition")
definition.textContent = text definition.textContent = text
definition.setAttribute("type", typ) definition.setAttribute("type", typ)
definition_list.appendChild(definition) definition_list.appendChild(definition)
translation_container_list = doc.createElement("translationContainerList") translation_container_list = doc.createElement("translationContainerList")
export_translation_list(doc, sense, translation_container_list) export_translation_list(doc, sense, translation_container_list)
sense_xml.appendChild(translation_container_list) sense_xml.appendChild(translation_container_list)
example_container_list = doc.createElement("exampleContainerList") example_container_list = doc.createElement("exampleContainerList")
sense_xml.appendChild(example_container_list) sense_xml.appendChild(example_container_list)
for example in sense.examples: for example in sense.examples:
example_container = example.export(doc) example_container = example.export(doc)
translation_container_list = doc.createElement("translationContainerList") export_translation_list(doc, example, example_container)
export_translation_list(doc, example, translation_container_list)
example_container.appendChild(translation_container_list)
example_container_list.appendChild(example_container) example_container_list.appendChild(example_container)
return sense_xml return sense_xml
def export_translation_list(doc, py_parent, xml_parent): def export_translation_list(doc, py_parent, xml_parent):
@ -145,43 +126,32 @@ def export_translation_list(doc, py_parent, xml_parent):
translation_container = export_translation(doc, translation) translation_container = export_translation(doc, translation)
translation_container.setAttribute("cluster", str(cidx + 1)) translation_container.setAttribute("cluster", str(cidx + 1))
xml_parent.appendChild(translation_container) xml_parent.appendChild(translation_container)
def export_translation(doc, translation): def export_translation(doc, translation):
translation_xml = doc.createElement("translationContainer") translation_xml = doc.createElement("translationContainer")
translation_xml.appendChild(_export_label_list(doc, translation.tags)) translation_xml.appendChild(_export_label_list(doc, translation.tags))
actual_t = doc.createElement("translation") actual_t = doc.createElement("translation")
actual_t.textContent = translation.translation actual_t.textContent = translation.translation
actual_t.setAttribute("targetLang", translation.targetLang) actual_t.setAttribute("targetLang", translation.targetLang)
if translation.audio:
actual_t.setAttribute("audio", translation.audio)
if translation.source: if translation.source:
actual_t.setAttribute("source", translation.source) actual_t.setAttribute("source", translation.source)
translation_xml.appendChild(actual_t) translation_xml.appendChild(actual_t)
if len(translation.explanationList) > 0 : explanation = doc.createElement("explanation")
explanationList = _export_explanation_list(doc, translation.explanationList) explanation.textContent = translation.explanation
translation_xml.appendChild(explanationList) translation_xml.appendChild(explanation)
return translation_xml return translation_xml
def _export_explanation_list(doc, lst):
result = doc.createElement('explanationList')
for explanation in lst:
result.appendChild(explanation.export(doc))
return result
def _export_label_list(doc, lst): def _export_label_list(doc, lst):
result = doc.createElement("labelList") result = doc.createElement("labelList")
for key, value in lst: for key, value in lst:
key, value = export_tag(key, value) key, value = export_tag(key, value)
label_el = doc.createElement("label") label_el = doc.createElement("label")
label_el.textContent = value label_el.textContent = value
label_el.setAttribute('type', key) label_el.setAttribute('type', key)

View File

@ -24,41 +24,29 @@ def build_structure_conversions():
if line[1] == "struktura": if line[1] == "struktura":
continue continue
vto_structure = line[1].strip().split(">")[1].split("<")[0]
vto_name = line[2].strip() vto_name = line[2].strip()
vto_id = line[6].strip() vto_id = line[4].strip()
if 0 in (len(vto_name), len(vto_id)): if 0 in (len(vto_name), len(vto_id)):
continue continue
vfrom = "^" + line[0].replace("?", "\?").replace("%s", "([a-zA-Z螚ȎŠ-]+)") + "$" vfrom = "^" + line[0].replace("?", "\?").replace("%s", "([a-zA-Z螚ȎŠ-]+)") + "$"
structure_conversions.append((__new__(RegExp(vfrom, 'u')), vto_name, vto_structure, vto_id)) structure_conversions.append((__new__(RegExp(vfrom, 'u')), vto_name, vto_id))
def convert_structure(structure, type): def convert_structure(structure):
if structure_conversions is None: if structure_conversions is None:
build_structure_conversions() build_structure_conversions()
for vfrom, vto_name, vto_structure, vto_id in structure_conversions: for vfrom, vto_name, vto_id in structure_conversions:
match = structure.match(vfrom) match = structure.match(vfrom)
# fix for ids 106, 107, 44 which instead matched with 30
if match and vto_id == '30' and '-s' in type:
vto_name = 's0-vp-s0'
vto_id = '106'
elif match and vto_id == '30' and '-g' in type:
vto_name = 'gg-vp-gg'
vto_id = '107'
elif match and vto_id == '30' and '-r' in type:
vto_name = 'r-vp-r'
vto_id = '44'
if match: if match:
# we need to remove replace alias here as we want to use javascript's one # we need to remove replace alias here as we want to use javascript's one
__pragma__('noalias', 'replace') __pragma__('noalias', 'replace')
result = structure.replace(vfrom, vto_name).strip() result = structure.replace(vfrom, vto_name).strip()
__pragma__('alias', 'replace', "py_replace") __pragma__('alias', 'replace', "py_replace")
return result, vto_structure, vto_id return result, vto_id
window.console.log("Unknown structure: ", structure) window.console.log("Unknown structure: ", structure)
return 'N/A', '/' return None

View File

@ -1,13 +1,13 @@
from message.simple_messages import NoReset, Reset, ModalNotOkClose, ClickMessage, DataChgClickMessage, KeyboardPress, NoAction from message.simple_messages import NoReset, Reset, ModalNotOkClose, ClickMessage, DataChgClickMessage, KeyboardPress, NoAction
from message.translation_edit import EditTranslation, MoveRight, MoveLeft, BinTranslation from message.translation_edit import EditTranslation, MoveRight, MoveLeft, BinTranslation
from message.show_messages import ShowEntryLabelsEdit, ShowEditTranslation, ShowSenseLabelEdit, ShowSenseDefinitionEdit, ShowCommentEdit, ShowAddTranslation, ShowExampleEdit, ShowVariantsEdit, ShowHomonymyEdit, ShowRelatedEntriesEdit from message.show_messages import ShowEntryLabelsEdit, ShowEditTranslation, ShowSenseLabelEdit, ShowSenseDefinitionEdit, ShowCommentEdit, ShowAddTranslation, ShowExampleEdit, ShowVariantsEdit, ShowRelatedEntriesEdit
from message.simple_edits import EditSenseLabel, EditSenseDefinition, EditComment, AddSenseLabel, AddSense, AddExampleTranslation, DoChosenExamples, AddToLabelList, AddToGenericList, EditVariants, EditHomonymy, EditRelatedEntries, EditEntryLabels, ExampleClusterEdit, ExampleClusterAdd from message.simple_edits import EditSenseLabel, EditSenseDefinition, EditComment, AddSenseLabel, AddSense, AddExampleTranslation, DoChosenExamples, AddToLabelList, AddToGenericList, EditVariants, EditRelatedEntries, EditEntryLabels, ExampleClusterEdit, ExampleClusterAdd
from message.show_menu import ShowTranslationMenu, ShowSenseMenu, ShowExampleMenu from message.show_menu import ShowTranslationMenu, ShowSenseMenu, ShowExampleMenu
from message.sense_edit import SenseMoveUp, SenseMoveDown, SenseBin, AddMultiwordExample from message.sense_edit import SenseMoveUp, SenseMoveDown, SenseBin, AddMultiwordExample
from message.example_edit import ExampleMoveUp, ExampleMoveDown, ExampleBin, ExampleRoleChange, ExampleComponentSpace, ExampleComponentAdd, ExampleComponentRemove, EditExampleText, ToggleExamples, ToggleClusters from message.example_edit import ExampleMoveUp, ExampleMoveDown, ExampleBin, ExampleRoleChange, ExampleComponentSpace, ExampleComponentAdd, ExampleComponentRemove, EditExampleText, ToggleExamples, ToggleClusters
from message.delete_messages import DeleteComment, DeleteVariants, DeleteHomonymy, DeleteRelatedEntries, DeleteEntryLabels from message.delete_messages import DeleteComment, DeleteVariants, DeleteRelatedEntries, DeleteEntryLabels
from message.ske_messages import ShowSkeModal, SearchInSkeModal, SkeInsert from message.ske_messages import ShowSkeModal, SearchInSkeModal, SkeInsert
from message.message import msg, delayed_msg from message.message import msg, delayed_msg

View File

@ -8,46 +8,28 @@ def generic_list_getter():
if result_candidate != "": if result_candidate != "":
result.append(result_candidate) result.append(result_candidate)
return result return result
# Formats data from inputs to name-value objects
def double_list_getter(firstParameter, secondParameter, allowEmptyField = False):
result = []
for row in document.getElementsByClassName("double-list-row"):
firstValue = row.querySelector("." + firstParameter + "-input").value
secondValue = row.querySelector("." + secondParameter + "-input").value
if (allowEmptyField is False and '' in [firstValue, secondValue]):
continue
if (allowEmptyField is True and all('' == value or value.isspace() for value in [firstValue, secondValue])):
continue
result.append({firstParameter: firstValue, secondParameter: secondValue})
return result
def label_list_getter(): def label_list_getter():
result = [] result = []
for row in document.getElementsByClassName("label-list-row"): for row in document.getElementsByClassName("label-list-row"):
ltype = row.querySelector(".label-type") ltype = row.querySelector(".label-type")
lvalue = row.querySelector(".label-value") lvalue = row.querySelector(".label-value")
lother = row.querySelector(".label-value-other") lother = row.querySelector(".label-value-other")
if lother is None: if lother is None:
continue continue
value = lother.value value = lother.value
if not value: if not value:
value = lvalue.options[lvalue.selectedIndex].text value = lvalue.options[lvalue.selectedIndex].text
if not value: if not value:
continue continue
result.append((ltype.textContent, value)) result.append((ltype.textContent, value))
kontrastivno = document.getElementById("kontrastivno-input").checked; kontrastivno = document.getElementById("kontrastivno-input").checked;
if kontrastivno: if kontrastivno:
result.append(("razmerje", "kontrastivno")) result.append(("razmerje", "kontrastivno"))
return result return result

View File

@ -6,26 +6,18 @@ from message.simple_messages import NoReset
class DeleteComment(NoReset): class DeleteComment(NoReset):
def update_model(self, model): def update_model(self, model):
document.getElementById("modal-question").value = "" document.getElementById("modal-question").value = ""
class DeleteVariants(NoReset): class DeleteVariants(NoReset):
def update_model(self, model): def update_model(self, model):
for el in document.getElementsByClassName("list-adder-input"): for el in document.getElementsByClassName("list-adder-input"):
el.value = "" el.value = ""
class DeleteRelatedEntries(DeleteVariants): class DeleteRelatedEntries(DeleteVariants):
pass pass
class DeleteHomonymy(NoReset):
def update_model(self, model):
for el in document.getElementsByClassName("list-adder-input"):
el.value = ""
class DeleteEntryLabels(NoReset): class DeleteEntryLabels(NoReset):
def update_model(self, model): def update_model(self, model):
for sel in document.getElementsByClassName("label-value"): for sel in document.getElementsByClassName("label-value"):

View File

@ -3,16 +3,16 @@ from message.simple_messages import ClickMessage
from model import Example, Sense, Translation from model import Example, Sense, Translation
from view import modals from view import modals
class ShowSenseLabelEdit(ClickMessage): class ShowSenseLabelEdit(ClickMessage):
def update_model(self, model): def update_model(self, model):
model.sense = self.get_arg(0, Sense) model.sense = self.get_arg(0, Sense)
model.sense.make_copy() model.sense.make_copy()
model.modal_set(lambda: modals.edit_sense_label(model.sense)) model.modal_set(lambda: modals.edit_sense_label(model.sense))
class ShowSenseDefinitionEdit(ClickMessage): class ShowSenseDefinitionEdit(ClickMessage):
def update_model(self, model): def update_model(self, model):
model.sense = self.get_arg(0, Sense) model.sense = self.get_arg(0, Sense)
@ -22,41 +22,35 @@ class ShowSenseDefinitionEdit(ClickMessage):
class ShowCommentEdit(ClickMessage): class ShowCommentEdit(ClickMessage):
def update_model(self, model): def update_model(self, model):
model.modal_set(lambda: modals.edit_comment(model.entry.comment)) model.modal_set(lambda: modals.edit_comment(model.entry.comment))
class ShowVariantsEdit(ClickMessage): class ShowVariantsEdit(ClickMessage):
def update_model(self, model): def update_model(self, model):
model.entry.make_copy() model.entry.make_copy()
model.modal_set(lambda: modals.edit_variants(model.entry)) model.modal_set(lambda: modals.edit_variants(model.entry))
class ShowHomonymyEdit(ClickMessage):
def update_model(self, model):
model.entry.make_copy()
model.modal_set(lambda: modals.edit_homonymy(model.entry))
class ShowRelatedEntriesEdit(ClickMessage): class ShowRelatedEntriesEdit(ClickMessage):
def update_model(self, model): def update_model(self, model):
model.entry.make_copy() model.entry.make_copy()
model.modal_set(lambda: modals.edit_related_entries(model.entry)) model.modal_set(lambda: modals.edit_related_entries(model.entry))
class ShowExampleEdit(ClickMessage): class ShowExampleEdit(ClickMessage):
def update_model(self, model): def update_model(self, model):
example = self.get_arg(0, Example) example = self.get_arg(0, Example)
sense = self.get_arg(1, Sense) sense = self.get_arg(1, Sense)
example.make_copy() example.make_copy()
model.modal_set(lambda: modals.edit_example(example, sense)) model.modal_set(lambda: modals.edit_example(example, sense))
class ShowEditTranslation(ClickMessage): class ShowEditTranslation(ClickMessage):
def update_model(self, model): def update_model(self, model):
translation = self.get_arg(0, Translation) translation = self.get_arg(0, Translation)
# Get translation location # Get translation location
(cidx, idx), (parent, cluster) = EditTranslation.get_translation_location(model.entry, translation) (cidx, idx), (parent, cluster) = EditTranslation.get_translation_location(model.entry, translation)
translation.make_copy() translation.make_copy()
num_clusters = len(parent.translations) num_clusters = len(parent.translations)
model.modal_set(lambda: modals.edit_translation( model.modal_set(lambda: modals.edit_translation(
@ -67,10 +61,10 @@ class ShowAddTranslation(ClickMessage):
def update_model(self, model): def update_model(self, model):
chosen_sense_or_example = self.get_arg(0) chosen_sense_or_example = self.get_arg(0)
translation = Translation() translation = Translation()
translation.make_copy() translation.make_copy()
model.modal_set(lambda: modals.edit_translation( model.modal_set(lambda: modals.edit_translation(
translation, translation,
chosen_sense_or_example, chosen_sense_or_example,
-1, -1,
len(chosen_sense_or_example.translations), len(chosen_sense_or_example.translations),
@ -81,4 +75,4 @@ class ShowEntryLabelsEdit(ClickMessage):
def update_model(self, model): def update_model(self, model):
model.entry.make_copy() model.entry.make_copy()
model.modal_set(lambda: modals.edit_entry_labels(model.entry)) model.modal_set(lambda: modals.edit_entry_labels(model.entry))

View File

@ -22,20 +22,20 @@ class AddToGenericList(NoReset):
def update_model(self, model): def update_model(self, model):
list_getter = self.get_arg(0) list_getter = self.get_arg(0)
list_getter().append("") list_getter().append("")
def data_change(self): def data_change(self):
return False return False
class AddToLabelList(NoReset): class AddToLabelList(NoReset):
def update_model(self, model): def update_model(self, model):
list_to_add_to = self.get_arg(0, list) list_to_add_to = self.get_arg(0, list)
thing_to_add_getter = self.get_arg(1) thing_to_add_getter = self.get_arg(1)
thing_to_add = thing_to_add_getter() thing_to_add = thing_to_add_getter()
# just adding to the copy to show in the modal # just adding to the copy to show in the modal
list_to_add_to.append(thing_to_add) list_to_add_to.append(thing_to_add)
def data_change(self): def data_change(self):
return False return False
@ -45,14 +45,14 @@ class AddSense(Message):
sense = Sense() sense = Sense()
sense.definition = {"indicator": "New Sense"} sense.definition = {"indicator": "New Sense"}
model.entry.senses.append(sense) model.entry.senses.append(sense)
class EditSenseDefinition(QuestionMessage): class EditSenseDefinition(QuestionMessage):
def update_model(self, model): def update_model(self, model):
sense = self.get_arg(0, Sense) sense = self.get_arg(0, Sense)
sense.definition["indicator"] = self.new_text sense.definition["indicator"] = self.new_text
class EditComment(QuestionMessage): class EditComment(QuestionMessage):
def update_model(self, model): def update_model(self, model):
model.entry.comment = self.new_text model.entry.comment = self.new_text
@ -61,24 +61,24 @@ class EditComment(QuestionMessage):
class DoChosenExamples(Message): class DoChosenExamples(Message):
def update_model(self, model): def update_model(self, model):
chosen_examples = self.get_arg(0, list) chosen_examples = self.get_arg(0, list)
inputs = document.getElementsByClassName("checkable-input") inputs = document.getElementsByClassName("checkable-input")
selected = None selected = None
for idx, el in enumerate(inputs): for idx, el in enumerate(inputs):
if el.checked: if el.checked:
selected = idx selected = idx
break break
# none was selected # none was selected
if selected is None: if selected is None:
return return
# first, remove the selected examples from wherever they were # first, remove the selected examples from wherever they were
for sense in model.entry.senses: for sense in model.entry.senses:
for example in chosen_examples: for example in chosen_examples:
if example in sense.examples: if example in sense.examples:
sense.examples.remove(example) sense.examples.remove(example)
# now, append selected examples to chosen sense # now, append selected examples to chosen sense
model.entry.senses[selected].examples.extend(chosen_examples) model.entry.senses[selected].examples.extend(chosen_examples)
@ -87,13 +87,8 @@ class EditVariants(Message):
def update_model(self, model): def update_model(self, model):
variants = common_accessors.generic_list_getter() variants = common_accessors.generic_list_getter()
model.entry.variants = variants model.entry.variants = variants
class EditHomonymy(Message):
def update_model(self, model):
homonymy = common_accessors.double_list_getter("value", "name")
model.entry.homonymy = homonymy
class EditRelatedEntries(Message): class EditRelatedEntries(Message):
def update_model(self, model): def update_model(self, model):
related_entries = common_accessors.generic_list_getter() related_entries = common_accessors.generic_list_getter()
@ -104,17 +99,17 @@ class EditEntryLabels(Message):
def update_model(self, model): def update_model(self, model):
labels = common_accessors.label_list_getter() labels = common_accessors.label_list_getter()
model.entry.labels = labels model.entry.labels = labels
class ExampleClusterEdit(DataChgClickMessage): class ExampleClusterEdit(DataChgClickMessage):
def update_model(self, model): def update_model(self, model):
example = self.get_arg(0, Example) example = self.get_arg(0, Example)
cluster = self.get_arg(1, int) cluster = self.get_arg(1, int)
example.set_cluster(cluster) example.set_cluster(cluster)
class ExampleClusterAdd(DataChgClickMessage): class ExampleClusterAdd(DataChgClickMessage):
def update_model(self, model): def update_model(self, model):
example = self.get_arg(0, Example) example = self.get_arg(0, Example)
example.set_cluster(ExampleClusters.first_empty_cluster()) example.set_cluster(ExampleClusters.first_empty_cluster())

View File

@ -26,7 +26,6 @@ class SkeExample:
self.mid = "" self.mid = ""
self.s_id = "" self.s_id = ""
self.gf2_good = None self.gf2_good = None
self.gf2_check = False
@staticmethod @staticmethod
def fromLine(line): def fromLine(line):
@ -59,8 +58,7 @@ class SkeCollocation:
def __init__(self, data): def __init__(self, data):
self.word = data.word self.word = data.word
self.frequency = data.count self.frequency = data.count
self.gramrel = data.gramrel self.structure_name, self.structure_id = convert_structure(data.gramrel)
self.structure_name, self.structure, self.structure_id = convert_structure(data.gramrel, data.lempos)
self.other = {"score": data.score, "cm": data.cm} self.other = {"score": data.score, "cm": data.cm}
@ -73,7 +71,7 @@ class SkeCollocation:
h("span.grey1", {}, self.other["cm"]), h("span.grey1", {}, self.other["cm"]),
h("span", {}, ","), h("span", {}, ","),
h("span.grey2", {}, self.structure_name)])] h("span.grey2", {}, self.structure_name)])]
def get_parser(ske_index_type): def get_parser(ske_index_type):
if ske_index_type == 0: if ske_index_type == 0:
@ -103,28 +101,13 @@ def match_gf2_examples(data, *args):
xhr.send(to_send) xhr.send(to_send)
def make_cql_query(ske_index, search_term, pos):
cql_pos= {
"samostalnik": ("S.*", "-s"),
"glagol": ("G.*", "-g"),
"pridevnik": ("P.*", "-p"),
"prislov": ("R.*", "-r"),
"zaimek": ("Z.*", "-z")
}
if ske_index == 0:
return "[ lemma=\"{0}\" & tag=\"{1}\" ]".format(search_term, cql_pos[pos][0])
else:
return search_term + cql_pos[pos][1]
class SkeModal(ClickMessage): class SkeModal(ClickMessage):
def on_event(self, event): def on_event(self, event):
# event could be data if this is the return from external library # event could be data if this is the return from external library
if type(event) in [list, int]: if type(event) in [list, int]:
self.add_arg(event) self.add_arg(event)
else: else:
if len(self._args) < 5: if len(self._args) < 4:
self.add_arg(None) self.add_arg(None)
super().on_event(event) super().on_event(event)
@ -132,20 +115,18 @@ class SkeModal(ClickMessage):
page_num = self.get_arg(0, int) page_num = self.get_arg(0, int)
search_term = self.get_arg(1, str) search_term = self.get_arg(1, str)
ske_index = self.get_arg(2, int) ske_index = self.get_arg(2, int)
ske_pos_query = self.get_arg(3, str)
ske_lookup = model.ske.url_for_kind_index(ske_index) ske_lookup = model.ske.url_for_kind_index(ske_index)
next_message = msg(SkeModal, page_num, search_term, ske_index, ske_pos_query) next_message = msg(SkeModal, page_num, search_term, ske_index)
# could be none if empty # could be none if empty
data = self.get_arg(4) data = self.get_arg(3)
if data is None: if data is None:
params = {"additional_refs": "s.id,p.id", params = {"additional_refs": "s.id,p.id",
"page_num": page_num, "page_num": page_num,
"error_callback": next_message, "error_callback": next_message,
"data_parser": get_parser(ske_index), "data_parser": get_parser(ske_index)}
"querytype": ske_pos_query}
gdex = get_preference("ske_gdex") gdex = get_preference("ske_gdex")
if gdex: if gdex:
@ -154,36 +135,15 @@ class SkeModal(ClickMessage):
return return
params["gdex"] = gdex params["gdex"] = gdex
# enable CQL query
if ske_pos_query is not "simple":
search_term_old = search_term
search_term = make_cql_query(ske_index, search_term, ske_pos_query)
model.ske.request(search_term, next_message, ske_lookup, params) model.ske.request(search_term, next_message, ske_lookup, params)
search_term = search_term_old
elif type(data) is list: elif type(data) is list:
window.console.log(data) window.console.log(data)
# check if gf2 examples are loaded or not # check if gf2 examples are loaded or not
if not data[0].gf2_check and type(data[0]) is SkeExample: if data[0].gf2_good is None:
# we get the data, we have to match it with available data on our gf2 examples API # we get the data, we have to match it with available data on our gf2 examples API
match_gf2_examples(data, page_num, search_term, ske_index, ske_pos_query) match_gf2_examples(data, page_num, search_term, ske_index)
elif type(data[0]) is SkeCollocation:
# filtering, grouping and sorting data
data.sort(key= lambda x: float(x.other["score"]), reverse=True)
_data = []
while len(data) > 0:
max_item = data.pop(0) # max(data, key= lambda x: x.other["score"])
_data.append(max_item)
for item in data:
if "N/A" in item.structure_name:
data.remove(item)
elif item.structure_name.strip() == max_item.structure_name.strip():
_data.append(item)
for delete_item in _data:
if delete_item in data:
data.remove(delete_item)
data = _data
model.modal_set(lambda: modals.ske_list( model.modal_set(lambda: modals.ske_list(
search_term, data, page_num, model.entry.senses, model.ske.request_kinds)) search_term, data, page_num, model.entry.senses, model.ske.request_kinds))
@ -194,25 +154,19 @@ class SkeModal(ClickMessage):
class SkeModalGf2Update(SkeModal): class SkeModalGf2Update(SkeModal):
def on_event(self, event): def on_event(self, event):
response_data = window.JSON.parse(event.target.response) response_data = window.JSON.parse(event.target.response)
data = self.get_arg(4) data = self.get_arg(3)
data_dict = {} data_dict = {}
for example in data: for example in data:
example.gf_good = False example.gf_good = False
data_dict[example.s_id] = example data_dict[example.s_id] = example
bad_response = dict(response_data["bad"])
for gf_sid, gf_data in bad_response.items():
data_dict[gf_sid].gf2_good = None
data_dict[gf_sid].gf2_check = True
good_response = dict(response_data["good"]) good_response = dict(response_data["good"])
for gf_sid, gf_data in good_response.items(): for gf_sid, gf_data in good_response.items():
data_dict[gf_sid].left = gf_data.left data_dict[gf_sid].left = gf_data.left
data_dict[gf_sid].mid = gf_data.mid data_dict[gf_sid].mid = gf_data.mid
data_dict[gf_sid].right = gf_data.right data_dict[gf_sid].right = gf_data.right
data_dict[gf_sid].gf2_good = True data_dict[gf_sid].gf2_good = True
data_dict[gf_sid].gf2_check = True
# changed data_dict, now we can redraw! # changed data_dict, now we can redraw!
# just let it do its thing in update_model # just let it do its thing in update_model
@ -230,7 +184,6 @@ class SearchInSkeModal(SkeModal):
self.add_arg(int(document.getElementById("ske-page-num").value)) self.add_arg(int(document.getElementById("ske-page-num").value))
self.add_arg(document.getElementById("ske-search").value) self.add_arg(document.getElementById("ske-search").value)
self.add_arg(document.getElementById("ske-select").selectedIndex) self.add_arg(document.getElementById("ske-select").selectedIndex)
self.add_arg(document.getElementById("ske-pos-query").value)
super().on_event(event) super().on_event(event)
@ -263,13 +216,11 @@ class SkeInsert(DataChgClickMessage):
else: else:
console.log("You really should not be here, my lady") console.log("You really should not be here, my lady")
continue continue
model.reset()
def _as_corpus_example(self, example): def _as_corpus_example(self, example):
new_example = Example() new_example = Example()
new_example.inner = CorpusExample() new_example.inner = CorpusExample()
new_example.inner.other_attributes["example_id"] = example.s_id new_example.inner.other_attributes["exampleId"] = example.s_id
new_example.inner.cluster = ExampleClusters.first_empty_cluster() new_example.inner.cluster = ExampleClusters.first_empty_cluster()
lex_left = ComponentLexeme() lex_left = ComponentLexeme()
@ -292,50 +243,21 @@ class SkeInsert(DataChgClickMessage):
new_collocation.inner = MultiwordExample() new_collocation.inner = MultiwordExample()
new_collocation.inner.other_attributes["structure_id"] = example.structure_id new_collocation.inner.other_attributes["structure_id"] = example.structure_id
new_collocation.inner.other_attributes["structureName"] = example.structure_name
new_collocation.inner.other_attributes["logDice"] = example.other["score"] new_collocation.inner.other_attributes["logDice"] = example.other["score"]
new_collocation.inner.other_attributes["frequency"] = example.frequency new_collocation.inner.other_attributes["frequency"] = example.frequency
new_collocation.inner.type = "collocation" new_collocation.inner.type = "collocation"
headword = document.getElementById("ske-search").value lex_left = ComponentLexeme()
lexemes = [] lex_left.text = ""
structure_name = example.structure_name.split("-") lex_left.role = None
gramrel = example.gramrel.split("_")
structure = example.structure.split(" ") lex_mid = ComponentLexeme()
structure.append("") # Bad fix: we have to add something for structure l-gg-ggn lex_mid.text = example.word
lex_mid.role = "headword"
for i in range(len(structure_name)):
lex = ComponentLexeme() lex_right = ComponentLexeme()
structure[i] = structure[i].replace("Inf-", "") lex_right.text = ""
lex_right.role = None
# take care of negations "ne"
if "Neg-" in structure[i]: new_collocation.components.extend([lex_left, lex_mid, lex_right])
structure[i] = structure[i].replace("Neg-", "")
negation_flag = True
n_lex = ComponentLexeme()
n_lex.text = "ne"
n_lex.role = "other"
lexemes.append(n_lex)
if structure[i] is "":
continue # skipping bcs of fix
elif "Vez-gbz" in structure[i]:
lex.text = "je"
lex.role = "other"
elif structure_name[i] in ["d", "vd", "zp"]:
lex.text = gramrel[i]
lex.text = lex.text.replace("-d", "").replace("%", "")
lex.role = "other"
elif structure_name[i] is "vp":
lex.text = structure[i]
lex.role = "other"
elif structure[i][0] in ["S", "G", "P", "R"]:
lex.text = headword
lex.role = "headword"
else:
lex.text = example.word
lex.role = "collocate"
lexemes.append(lex)
new_collocation.components.extend(lexemes)
return new_collocation return new_collocation

View File

@ -4,35 +4,28 @@ import message.common_accessors as common_accessors
from browser import document, window from browser import document, window
from model.translation import Translation from model.translation import Translation
from model.sense import Sense from model.sense import Sense
from model.explanation import Explanation
class EditTranslation(DataChgClickMessage): class EditTranslation(DataChgClickMessage):
def update_model(self, model): def update_model(self, model):
self.translation = self.get_arg(0, Translation) self.translation = self.get_arg(0, Translation)
self.old_cluster_idx = self.get_arg(1, int) self.old_cluster_idx = self.get_arg(1, int)
self.translation.translation = document.getElementById("etv").value self.translation.translation = document.getElementById("etv").value
# This could be dangerous if double_list_getter is getting data from any other list as well. self.translation.explanation = document.getElementById("ete").value
explanations = common_accessors.double_list_getter('value', 'language', True)
self.translation.explanationList = []
for entry in explanations:
explanation = Explanation()
explanation.value = entry.value
explanation.language = entry.language
self.translation.explanationList.append(explanation)
# common_accessors.label_list_getter() # common_accessors.label_list_getter()
self.translation.tags = common_accessors.label_list_getter() self.translation.tags = common_accessors.label_list_getter()
# check if empty, remove! # check if empty, remove!
if self.translation.is_empty(): if self.translation.is_empty():
model.entry.remove_translation(self.translation) model.entry.remove_translation(self.translation)
return return
new_cluster_idx = int(document.getElementById("cluster-num").value) - 1 new_cluster_idx = int(document.getElementById("cluster-num").value) - 1
self.handle_cluster_change(new_cluster_idx, model) self.handle_cluster_change(new_cluster_idx, model)
@staticmethod @staticmethod
def get_translation_location(entry, translation): def get_translation_location(entry, translation):
def find_in_clusters(parent): def find_in_clusters(parent):
@ -41,7 +34,7 @@ class EditTranslation(DataChgClickMessage):
if search_translation == translation: if search_translation == translation:
return (ci, ti), (parent, cluster) return (ci, ti), (parent, cluster)
return None return None
for sense in entry.senses: for sense in entry.senses:
res = find_in_clusters(sense) res = find_in_clusters(sense)
if res is not None: if res is not None:
@ -50,21 +43,21 @@ class EditTranslation(DataChgClickMessage):
res = find_in_clusters(example) res = find_in_clusters(example)
if res is not None: if res is not None:
return res return res
window.console.log("should not be here...") window.console.log("should not be here...")
def handle_cluster_change(self, new_cluster_idx, model): def handle_cluster_change(self, new_cluster_idx, model):
if self.old_cluster_idx == new_cluster_idx: if self.old_cluster_idx == new_cluster_idx:
return return
(cidx, tidx), (parent, cluster) = EditTranslation.get_translation_location(model.entry, self.translation) (cidx, tidx), (parent, cluster) = EditTranslation.get_translation_location(model.entry, self.translation)
self.do_cluster_change(parent, cluster, cidx, tidx, new_cluster_idx) self.do_cluster_change(parent, cluster, cidx, tidx, new_cluster_idx)
def do_cluster_change(self, sense_or_example, cluster, cidx, tidx, new_cluster_idx): def do_cluster_change(self, sense_or_example, cluster, cidx, tidx, new_cluster_idx):
# remove the translation from the old cluster # remove the translation from the old cluster
cluster.splice(tidx, 1) cluster.splice(tidx, 1)
# we maybe are creating a new cluster, handle that # we maybe are creating a new cluster, handle that
if len(sense_or_example.translations) == new_cluster_idx: if len(sense_or_example.translations) == new_cluster_idx:
sense_or_example.translations.append([self.translation]) sense_or_example.translations.append([self.translation])
@ -73,12 +66,12 @@ class EditTranslation(DataChgClickMessage):
sense_or_example.translations[new_cluster_idx].append(self.translation) sense_or_example.translations[new_cluster_idx].append(self.translation)
else: else:
raise ValueError("Bad new cluster idx :(") raise ValueError("Bad new cluster idx :(")
# we still hold cluster reference, check if empty and remove if necessary # we still hold cluster reference, check if empty and remove if necessary
# we cant do this earlier since indexes change and yeah, fun stuff # we cant do this earlier since indexes change and yeah, fun stuff
if len(cluster) == 0: if len(cluster) == 0:
sense_or_example.translations.splice(cidx, 1) sense_or_example.translations.splice(cidx, 1)
class MoveRight(DataChgClickMessage): class MoveRight(DataChgClickMessage):
def update_model(self, model): def update_model(self, model):
@ -87,8 +80,8 @@ class MoveRight(DataChgClickMessage):
if idx != len(cluster) - 1: if idx != len(cluster) - 1:
cluster[idx], cluster[idx + 1] = cluster[idx + 1], cluster[idx] cluster[idx], cluster[idx + 1] = cluster[idx + 1], cluster[idx]
model.translation = None model.translation = None
class MoveLeft(DataChgClickMessage): class MoveLeft(DataChgClickMessage):
def update_model(self, model): def update_model(self, model):
translation = self.get_arg(0, Translation) translation = self.get_arg(0, Translation)
@ -96,8 +89,8 @@ class MoveLeft(DataChgClickMessage):
if idx != 0 and len(cluster) > 1: if idx != 0 and len(cluster) > 1:
cluster[idx], cluster[idx - 1] = cluster[idx - 1], cluster[idx] cluster[idx], cluster[idx - 1] = cluster[idx - 1], cluster[idx]
model.translation = None model.translation = None
class BinTranslation(DataChgClickMessage): class BinTranslation(DataChgClickMessage):
def update_model(self, model): def update_model(self, model):
translation = self.get_arg(0, Translation) translation = self.get_arg(0, Translation)
@ -108,7 +101,7 @@ class BinTranslation(DataChgClickMessage):
else: else:
cluster.splice(tidx, 1) cluster.splice(tidx, 1)
model.translation = None model.translation = None
class AddTranslation(EditTranslation): class AddTranslation(EditTranslation):
def handle_cluster_change(self, new_cluster_idx, _): def handle_cluster_change(self, new_cluster_idx, _):
@ -117,4 +110,4 @@ class AddTranslation(EditTranslation):
# we make a dummy cluster, cluster_idx and translation_idx # we make a dummy cluster, cluster_idx and translation_idx
# we give a correct new_cluster_idx # we give a correct new_cluster_idx
self.do_cluster_change(self.get_arg(2), [None, None], None, None, new_cluster_idx) self.do_cluster_change(self.get_arg(2), [None, None], None, None, new_cluster_idx)

View File

@ -2,4 +2,3 @@ from model.model import Model
from model.sense import Sense from model.sense import Sense
from model.translation import Translation from model.translation import Translation
from model.example import Example from model.example import Example
from model.explanation import Explanation

View File

@ -12,9 +12,7 @@ class Entry(Data):
def __init__(self): def __init__(self):
self.status = "" self.status = ""
self.headword = "" self.headword = ""
self.homonymy = []
self.headword_type = None self.headword_type = None
self.headword_audio = None
self.grammar = "" self.grammar = ""
self.comment = "" self.comment = ""
self.variants = [] self.variants = []
@ -23,31 +21,26 @@ class Entry(Data):
self.measure = {} self.measure = {}
self.labels = [] self.labels = []
self.senses = [] self.senses = []
self.original_xml = None
def import_xml(self, entry_xml): def import_xml(self, entry_xml):
self.original_xml = entry_xml.cloneNode(True)
status = entry_xml.querySelector("head status") status = entry_xml.querySelector("head status")
headword = entry_xml.querySelector("head headword lemma") headword = entry_xml.querySelector("head headword lemma")
grammar = entry_xml.querySelector("head grammar category") grammar = entry_xml.querySelector("head grammar category")
comment = entry_xml.querySelector("head comment") comment = entry_xml.querySelector("head comment")
self.status = status.textContent if status else "" self.status = status.textContent if status else ""
self.headword = headword.textContent if headword else "" self.headword = headword.textContent if headword else ""
self.headword_type = headword.getAttribute("type") if headword and headword.hasAttribute("type") else None self.headword_type = headword.getAttribute("type") if headword else None
self.headword_audio = headword.getAttribute("audio") if headword and headword.hasAttribute("audio") else None
self.grammar = grammar.textContent if grammar else "" self.grammar = grammar.textContent if grammar else ""
self.comment = comment.textContent if comment else "" self.comment = comment.textContent if comment else ""
self.variants = [v.textContent for v in entry_xml.querySelectorAll("head variantList variant")] self.variants = [v.textContent for v in entry_xml.querySelectorAll("head variantList variant")]
self.homonymy = [{"value": v.textContent, "name": v.getAttribute("name")} for v in entry_xml.querySelectorAll("head headword homonymy homonymyFeature ")]
self.related_entries = [re.textContent for re in entry_xml.querySelectorAll("head relatedEntryList relatedEntry")] self.related_entries = [re.textContent for re in entry_xml.querySelectorAll("head relatedEntryList relatedEntry")]
lex_unit = entry_xml.querySelector("lexical_unit lexeme,lexicalUnit lexeme") lex_unit = entry_xml.querySelector("lexical_unit lexeme,lexicalUnit lexeme")
if lex_unit: if lex_unit:
self.lexical_unit['id'] = lex_unit.getAttribute("lexical_unit_lexeme_id") self.lexical_unit['id'] = lex_unit.getAttribute("lexical_unit_lexeme_id")
self.lexical_unit['text'] = lex_unit.textContent self.lexical_unit['text'] = lex_unit.textContent
measure = entry_xml.querySelector("measureList measure") measure = entry_xml.querySelector("measureList measure")
if measure: if measure:
self.measure["source"] = measure.getAttribute("source") self.measure["source"] = measure.getAttribute("source")
@ -55,19 +48,19 @@ class Entry(Data):
self.measure["text"] = measure.textContent self.measure["text"] = measure.textContent
self.labels = import_label_list("head labelList label", entry_xml) self.labels = import_label_list("head labelList label", entry_xml)
for i, sense_xml in enumerate(entry_xml.querySelectorAll("body senseList sense")): for i, sense_xml in enumerate(entry_xml.querySelectorAll("body senseList sense")):
sense = Sense() sense = Sense()
sense.import_xml(sense_xml, i) sense.import_xml(sense_xml, i)
self.senses.append(sense) self.senses.append(sense)
def view(self, model): def view(self, model):
view_sense_list = [sense.view(model, idx) for idx, sense in enumerate(self.senses)] view_sense_list = [sense.view(model, idx) for idx, sense in enumerate(self.senses)]
buttons_left = self._view_button_section(model) buttons_left = self._view_button_section(model)
buttons_right = View.view_toggle_buttons(model) buttons_right = View.view_toggle_buttons(model)
return h("div#entry", {}, [ return h("div#entry", {}, [
h("div#entry-status", {}, self.status), h("div#entry-status", {}, self.status),
h("div#entry-header", {}, [ h("div#entry-header", {}, [
@ -79,57 +72,51 @@ class Entry(Data):
h("div.one-fifth", {}, buttons_right)]), h("div.one-fifth", {}, buttons_right)]),
h("div#sense-container", {}, view_sense_list), h("div#sense-container", {}, view_sense_list),
h("button.add-button", {"on": {"click": M.msg(M.AddSense)}}, "+")]) h("button.add-button", {"on": {"click": M.msg(M.AddSense)}}, "+")])
def _view_button_section(self, model): def _view_button_section(self, model):
clk = lambda cls: {"on": {"click": M.msg(cls)}} clk = lambda cls: {"on": {"click": M.msg(cls)}}
buttons = [ buttons = [
h("button.normal", clk(M.ShowVariantsEdit), "Variante"), h("button.normal", clk(M.ShowVariantsEdit), "Variante"),
h("button.success", clk(M.ShowRelatedEntriesEdit), "Povezano"), h("button.success", clk(M.ShowRelatedEntriesEdit), "Povezano"),
h("button.success", clk(M.ShowEntryLabelsEdit), "Oznake"), h("button.success", clk(M.ShowEntryLabelsEdit), "Oznake"),
h("button.normal", clk(M.ShowCommentEdit), "Opombe"), h("button.normal", clk(M.ShowCommentEdit), "Opombe")]
h("button.normal", clk(M.ShowHomonymyEdit), "Homonomije"),]
view_buttons = [] view_buttons = []
view_table = [] view_table = []
if len(self.variants) == 0: if len(self.variants) == 0:
view_buttons.append(buttons[0]) view_buttons.append(buttons[0])
else: else:
view_table.append((buttons[0], ", ".join(self.variants))) view_table.append((buttons[0], ", ".join(self.variants)))
if len(self.homonymy) == 0:
view_buttons.append(buttons[4])
else:
view_table.append((buttons[4], ", ".join((h["name"] + ": " + h.value) for h in self.homonymy)))
if len(self.related_entries) == 0: if len(self.related_entries) == 0:
view_buttons.append(buttons[1]) view_buttons.append(buttons[1])
else: else:
view_table.append((buttons[1], ", ".join(self.related_entries))) view_table.append((buttons[1], ", ".join(self.related_entries)))
if len(self.labels) == 0: if len(self.labels) == 0:
view_buttons.append(buttons[2]) view_buttons.append(buttons[2])
else: else:
labels = ", ".join([clean_label(val) for _, val in self.labels]) labels = ", ".join([clean_label(val) for _, val in self.labels])
view_table.append((buttons[2], labels)) view_table.append((buttons[2], labels))
if self.comment == "": if self.comment == "":
view_buttons.append(buttons[3]) view_buttons.append(buttons[3])
else: else:
view_table.append((buttons[3], self.comment)) view_table.append((buttons[3], self.comment))
table_rows = [ table_rows = [
h("tr", {}, [ h("td", {}, btn), h("td", {}, content)]) h("tr", {}, [ h("td", {}, btn), h("td", {}, content)])
for btn, content in view_table] for btn, content in view_table]
view_buttons.append(h("table", {}, table_rows)) view_buttons.append(h("table", {}, table_rows))
return h("div", {}, view_buttons) return h("div", {}, view_buttons)
def get_measure_text(self): def get_measure_text(self):
return self.measure["text"] if "text" in self.measure else "" return self.measure["text"] if "text" in self.measure else ""
def remove_translation(self, translation): def remove_translation(self, translation):
for sense in self.senses: for sense in self.senses:
for cluster in sense.translations: for cluster in sense.translations:
@ -141,4 +128,4 @@ class Entry(Data):
if translation in cluster: if translation in cluster:
cluster.remove(translation) cluster.remove(translation)
return return

View File

@ -11,7 +11,7 @@ class ComponentLexeme(Data):
self.text = "" self.text = ""
self.role = "" self.role = ""
self.no_space = False self.no_space = False
def import_xml(self, xml): def import_xml(self, xml):
if xml.nodeName == "#text": if xml.nodeName == "#text":
self.text = xml.data self.text = xml.data
@ -19,31 +19,33 @@ class ComponentLexeme(Data):
else: else:
self.text = xml.textContent self.text = xml.textContent
self.role = xml.getAttribute("role") self.role = xml.getAttribute("role")
if xml.hasAttribute("space"): if xml.hasAttribute("space"):
self.no_space = xml.getAttribute("space") == "false" self.no_space = xml.getAttribute("space") == "false"
for oth_attr in ["lexeme_id", "lexical_unit_lexeme_id", "slolex", "kol", "sloleks"]: for oth_attr in ["lexical_unit_lexeme_id", "slolex", "kol"]:
if xml.hasAttribute(oth_attr): if xml.hasAttribute(oth_attr):
self.other_attributes[oth_attr] = xml.getAttribute(oth_attr) self.other_attributes[oth_attr] = xml.getAttribute(oth_attr)
def isValid(self): def isValid(self):
return len(self.text) > 0 return len(self.text) > 0
def export(self, doc): def export(self, doc):
if self.role is None: if self.role is None:
return doc.createTextNode(self.text) return doc.createTextNode(self.text)
result = doc.createElement("comp") result = doc.createElement("comp")
result.setAttribute("role", self.role) result.setAttribute("role", self.role)
result.textContent = self.text result.textContent = self.text
if self.no_space and self.no_space != self.LAST_COMPONENT_SPACE: if self.no_space and self.no_space != self.LAST_COMPONENT_SPACE:
result.setAttribute("space", "false") result.setAttribute("space", "false")
for key, value in self.other_attributes.items(): for key, value in self.other_attributes.items():
result.setAttribute(key, value) result.setAttribute(key, value)
return result return result
def view_style(self): def view_style(self):
# no-space is handled in multiword-example directly # no-space is handled in multiword-example directly
result = ".comp-text" result = ".comp-text"
@ -51,8 +53,8 @@ class ComponentLexeme(Data):
result += ".comp-role" result += ".comp-role"
if self.role == "headword": if self.role == "headword":
result += ".comp-role-headword" result += ".comp-role-headword"
return result return result

View File

@ -18,12 +18,12 @@ class Example(Data):
self.components = [] self.components = []
self.edited = False self.edited = False
self.newly_created = False self.newly_created = False
# removes space from last component if multiword example # removes space from last component if multiword example
def check_multiword_components(self): def check_multiword_components(self):
if self.is_multiword(): if self.is_multiword():
self.components[len(self.components) - 1].no_space = ComponentLexeme.LAST_COMPONENT_SPACE self.components[len(self.components) - 1].no_space = ComponentLexeme.LAST_COMPONENT_SPACE
@staticmethod @staticmethod
def new_multiword(): def new_multiword():
example = Example() example = Example()
@ -32,105 +32,105 @@ class Example(Data):
example.inner = MultiwordExample() example.inner = MultiwordExample()
example.inner.cluster = ExampleClusters.first_empty_cluster() example.inner.cluster = ExampleClusters.first_empty_cluster()
example.inner.type = "grammaticalCombination" example.inner.type = "grammaticalCombination"
empty_component = ComponentLexeme() empty_component = ComponentLexeme()
empty_component.role = "headword" empty_component.role = "headword"
example.components.append(empty_component) example.components.append(empty_component)
return example return example
def import_xml(self, example_xml): def import_xml(self, example_xml):
self.translations = from_container_list(example_xml.querySelectorAll("translationContainerList translationContainer")) self.translations = from_container_list(example_xml.querySelectorAll("translationContainer"))
if example_xml.hasAttribute("modified"): if example_xml.hasAttribute("modified"):
self.edited = example_xml.getAttribute("modified") == "true" self.edited = example_xml.getAttribute("modified") == "true"
inner_xml = example_xml.querySelector("corpusExample") inner_xml = example_xml.querySelector("corpusExample")
if inner_xml is not None: if inner_xml is not None:
self.inner = CorpusExample() self.inner = CorpusExample()
else: else:
inner_xml = example_xml.querySelector("multiwordExample") inner_xml = example_xml.querySelector("multiwordExample")
self.inner = MultiwordExample() self.inner = MultiwordExample()
self.inner.import_xml(inner_xml) self.inner.import_xml(inner_xml)
for idx, comp_xml in enumerate(inner_xml.childNodes): for idx, comp_xml in enumerate(inner_xml.childNodes):
comp = ComponentLexeme() comp = ComponentLexeme()
comp.import_xml(comp_xml) comp.import_xml(comp_xml)
if comp.isValid(): if comp.isValid():
self.components.append(comp) self.components.append(comp)
self.check_multiword_components() self.check_multiword_components()
def export(self, doc): def export(self, doc):
self.check_multiword_components() self.check_multiword_components()
result = doc.createElement("exampleContainer") result = doc.createElement("exampleContainer")
inner = self.inner.export(doc, self.edited) inner = self.inner.export(doc, self.edited)
# TODO: bad quick fix # TODO: bad quick fix
for comp in self.components: for comp in self.components:
inner.appendChild(comp.export(doc)) inner.appendChild(comp.export(doc))
result.appendChild(inner) result.appendChild(inner)
return result return result
def view(self, model, sense): def view(self, model, sense):
example_tag = "div.example-rest" example_tag = "div.example-rest"
if self in model.chosen_examples: if self in model.chosen_examples:
example_tag += ".example-chosen" example_tag += ".example-chosen"
cluster = self.get_cluster() cluster = self.get_cluster()
dot_attr = {"style": { "visibility": "visible" if cluster is None else "hidden"}} dot_attr = {"style": { "visibility": "visible" if cluster is None else "hidden"}}
example_content = [] example_content = []
if cluster is not None: if cluster is not None:
example_content.append(h("span.example-cluster", {}, str(cluster + 1))) example_content.append(h("span.example-cluster", {}, str(cluster + 1)))
example_text_inner_tag = "span.example-text-{}".format(self.get_view_type()) example_text_inner_tag = "span.example-text-{}".format(self.get_view_type())
example_content.append(h(example_text_inner_tag, {}, self.inner.view(self.components))) example_content.append(h(example_text_inner_tag, {}, self.inner.view(self.components)))
other_attributes = self.get_other_attributes() other_attributes = self.get_other_attributes()
if "frequency" in other_attributes: if "frequency" in other_attributes:
example_content.append(h("span.example-frequency", {}, other_attributes["frequency"])) example_content.append(h("span.example-frequency", {}, other_attributes["frequency"]))
if "logDice" in other_attributes: if "logDice" in other_attributes:
example_content.append(h("span.example-logdice", {}, other_attributes["logDice"])) example_content.append(h("span.example-logdice", {}, other_attributes["logDice"]))
parent_display = "none" parent_display = "none"
if model.examples_shown or self.is_multiword() or len(self.translations) > 0: if model.examples_shown or self.is_multiword() or len(self.translations) > 0:
parent_display = "inherit" parent_display = "inherit"
clusters_display = "inherit" clusters_display = "inherit"
if not model.clusters_shown: if not model.clusters_shown:
clusters_display = "none" clusters_display = "none"
return h("div.example", {"style": {"display": parent_display}}, [ return h("div.example", {"style": {"display": parent_display}}, [
h("div.example-dot", dot_attr, ""), h("div.example-dot", dot_attr, ""),
h(example_tag, {}, [ h(example_tag, {}, [
h("span.example-text", {"on": {"click": M.msg(M.ShowExampleMenu, self)} }, example_content), h("span.example-text", {"on": {"click": M.msg(M.ShowExampleMenu, self)} }, example_content),
h("div.example-translation-list", {}, [ h("div.example-translation-list", {}, [
h("div.example-translation", {}, View.view_translations(self.translations, self, model))]), h("div.example-translation", {}, View.view_translations(self.translations, self, model))]),
h("div.example-clusters", h("div.example-clusters",
{"style": {"display": clusters_display }}, show_toggle_cluster_buttons(sense, self))])]) {"style": {"display": clusters_display }}, show_toggle_cluster_buttons(sense, self))])])
def simple_view(self): def simple_view(self):
return self.inner.view(self.components) return self.inner.view(self.components)
def get_cluster(self): def get_cluster(self):
return self.inner.get_cluster() return self.inner.get_cluster()
def set_cluster(self, cluster): def set_cluster(self, cluster):
self.inner.cluster = cluster self.inner.cluster = cluster
def get_structure(self): def get_structure(self):
return self.inner.get_structure() return self.inner.get_structure()
def is_collocation(self): def is_collocation(self):
return self.get_view_type() == 2 return self.get_view_type() == 2
def is_multiword(self): def is_multiword(self):
return self.get_view_type() != 1 return self.get_view_type() != 1
def get_view_type(self): def get_view_type(self):
# as per the bosses, these are the rules for different colors # as per the bosses, these are the rules for different colors
if type(self.inner) is CorpusExample: if type(self.inner) is CorpusExample:
@ -139,8 +139,8 @@ class Example(Data):
return 2 return 2
else: else:
return 3 return 3
def get_other_attributes(self): def get_other_attributes(self):
return self.inner.other_attributes return self.inner.other_attributes

View File

@ -1,21 +0,0 @@
from model.data import Data
from lib.snabbdom import h
class Explanation(Data):
def __init__(self):
self.value = ""
self.language = ""
def import_dom(self, explanation_dom):
self.value = explanation_dom.textContent if explanation_dom else ""
self.language = explanation_dom.getAttribute("language") if explanation_dom.hasAttribute("language") else ""
def export(self, doc):
result = doc.createElement("explanation")
result.textContent = self.value
if self.language != "": result.setAttribute('language', self.language)
return result

View File

@ -15,37 +15,37 @@ class Sense(Data):
self.labels = [] self.labels = []
self.translations = [] self.translations = []
self.examples = [] self.examples = []
def import_xml(self, sense_xml, idx): def import_xml(self, sense_xml, idx):
self.original_idx = idx self.original_idx = idx
for definition in sense_xml.querySelectorAll("definitionList definition"): for definition in sense_xml.querySelectorAll("definitionList definition"):
key = definition.getAttribute("type") key = definition.getAttribute("type")
self.definition[key] = definition.textContent self.definition[key] = definition.textContent
self.labels = import_label_list("sense > labelList label", sense_xml) self.labels = import_label_list("sense > labelList label", sense_xml)
self.translations = from_container_list( self.translations = from_container_list(
sense_xml.querySelectorAll('sense > translationContainerList translationContainer')) sense_xml.querySelectorAll("translationContainerList translationContainer"))
for example_xml in sense_xml.querySelectorAll("exampleContainerList exampleContainer"): for example_xml in sense_xml.querySelectorAll("exampleContainerList exampleContainer"):
example = Example() example = Example()
example.import_xml(example_xml) example.import_xml(example_xml)
self.examples.append(example) self.examples.append(example)
def merge_labels(self): def merge_labels(self):
return ", ".join(val for _, val in self.labels) return ", ".join(val for _, val in self.labels)
def view(self, model, sense_num): def view(self, model, sense_num):
examples = [example.view(model, self) for example in self.examples] examples = [example.view(model, self) for example in self.examples]
result = h("div.elm-div", {}, [ result = h("div.elm-div", {}, [
h("div.sense-num", {"on": {"click": M.msg(M.ShowSenseMenu, self)}}, str(sense_num + 1)), h("div.sense-num", {"on": {"click": M.msg(M.ShowSenseMenu, self)}}, str(sense_num + 1)),
h("div.sense", {}, [ h("div.sense", {}, [
h("span.sense-label-list", { "on": { "click": M.msg(M.ShowSenseLabelEdit, self) }}, [ h("span.sense-label-list", { "on": { "click": M.msg(M.ShowSenseLabelEdit, self) }}, [
h("span.sense-label", {}, clean_label(slabel)) for _, slabel in self.labels ]), h("span.sense-label", {}, clean_label(slabel)) for _, slabel in self.labels ]),
h("span.sense-definition", { "on": { "click": M.msg(M.ShowSenseDefinitionEdit, self) }}, self.definition["indicator"]), h("span.sense-definition", { "on": { "click": M.msg(M.ShowSenseDefinitionEdit, self) }}, self.definition["indicator"]),
h("div", {}, View.view_translations(self.translations, self, model)), h("div", {}, View.view_translations(self.translations, self, model)),
h("div", {}, examples)])]) h("div", {}, examples)])])
return result return result

View File

@ -1,5 +1,4 @@
from model.tags import import_label_list from model.tags import import_label_list
from model.explanation import Explanation
from model.data import Data from model.data import Data
from lib.snabbdom import h from lib.snabbdom import h
@ -10,21 +9,21 @@ import message as M
def from_container_list(translation_list_container_xml): def from_container_list(translation_list_container_xml):
translations = [] translations = []
max_num_cluster = 0 max_num_cluster = 0
for translation_xml in translation_list_container_xml: for translation_xml in translation_list_container_xml:
num_cluster = 1 # default cluster num_cluster = 1 # default cluster
if translation_xml.hasAttribute("cluster"): if translation_xml.hasAttribute("cluster"):
num_cluster = int(translation_xml.getAttribute("cluster")) num_cluster = int(translation_xml.getAttribute("cluster"))
max_num_cluster = max(max_num_cluster, num_cluster) max_num_cluster = max(max_num_cluster, num_cluster)
t = Translation() t = Translation()
t.import_xml(translation_xml) t.import_xml(translation_xml)
translations.append((num_cluster, t)) translations.append((num_cluster, t))
result = [[] for _ in range(max_num_cluster)] result = [[] for _ in range(max_num_cluster)]
for clusterNum, translation in translations: for clusterNum, translation in translations:
result[clusterNum - 1].append(translation) result[clusterNum - 1].append(translation)
return result return result
@ -33,54 +32,47 @@ class Translation(Data):
self.translation = "" self.translation = ""
self.source = "" self.source = ""
self.targetLang = "" self.targetLang = ""
self.audio = "" self.explanation = ""
self.explanationList = set()
self.tags = [] self.tags = []
def import_xml(self, translation_xml): def import_xml(self, translation_xml):
translation = translation_xml.querySelector("translation") translation = translation_xml.querySelector("translation")
if translation: if translation:
self.translation = translation.textContent self.translation = translation.textContent
self.source = translation.getAttribute("source") if translation.hasAttribute("source") else "" self.source = translation.getAttribute("source") if translation.hasAttribute("source") else ""
self.targetLang = translation.getAttribute("targetLang") if translation.hasAttribute("targetLang") else "" self.targetLang = translation.getAttribute("targetLang") if translation.hasAttribute("targetLang") else ""
self.audio = translation.getAttribute("audio") if translation.hasAttribute("audio") else ""
explanation = translation_xml.querySelector("explanation")
explanationList = translation_xml.querySelectorAll("explanationList explanation") self.explanation = explanation.textContent if explanation else ""
for explanation_dom in explanationList:
explanation = Explanation()
explanation.import_dom(explanation_dom)
self.explanationList.append(explanation)
self.tags = import_label_list("labelList label", translation_xml) self.tags = import_label_list("labelList label", translation_xml)
def view(self, model): def view(self, model):
elements = [] elements = []
if self.tags: if self.tags:
tags = h("div.translation-tags", {}, [ tags = h("div.translation-tags", {}, [
h("span", {"attr": {"title": key}}, clean_label(value)) h("span", {"attr": {"title": key}}, clean_label(value))
for key, value in self.tags]) for key, value in self.tags])
elements.append(tags) elements.append(tags)
elements.append(h("span.translation-text", {}, self.translation)) elements.append(h("span.translation-text", {}, self.translation))
if self.source: if self.source:
elements.append(h("span.translation-source", {}, self.source)) elements.append(h("span.translation-source", {}, self.source))
if (self.explanationList): explanation_class = ".translation-explanation" if self.translation else ""
explanation_class = ".explanations" if self.translation else ".explanations.solo" elements.append(h("span{}".format(explanation_class), {}, self.explanation))
explanations = [explanation.value for explanation in self.explanationList]
elements.append(h("span{}".format(explanation_class), {}, ", ".join(explanations)))
return h("div.translation-div", {"on": {"click": M.msg(M.ShowTranslationMenu, self) }}, elements) return h("div.translation-div", {"on": {"click": M.msg(M.ShowTranslationMenu, self) }}, elements)
def is_empty(self): def is_empty(self):
result = True result = True
result = result and self.translation == "" result = result and self.translation == ""
# next two are not checked as the also can not be deleted via gui # next two are not checked as the also can not be deleted via gui
# result = result and self.source == "" # result = result and self.source == ""
# result = result and self.targetLang == "" # result = result and self.targetLang == ""
result = result and len(self.explanationList) == 0 result = result and self.explanation == ""
result = result and len(self.tags) == 0 result = result and len(self.tags) == 0
return result return result

View File

@ -9,34 +9,34 @@ class Update:
# check if completely no action needed # check if completely no action needed
if msg.no_action(): if msg.no_action():
return return
# by default, no need to redraw entry # by default, no need to redraw entry
entry_redraw = False entry_redraw = False
# check if we need to signal the data change # check if we need to signal the data change
if msg.data_change(): if msg.data_change():
screenful.changed() screenful.changed()
entry_redraw = True entry_redraw = True
# redraw of view can happen even if no data changed # redraw of view can happen even if no data changed
entry_redraw |= msg.entry_redraw() entry_redraw |= msg.entry_redraw()
# check if we need to reset the model # check if we need to reset the model
reset = msg.reset() reset = msg.reset()
if reset: if reset:
self.model.pre_reset() self.model.pre_reset()
# actually run the update_model # actually run the update_model
msg.update_model(self.model) msg.update_model(self.model)
msg.clear_args() msg.clear_args()
# post reset comes now # post reset comes now
if reset: if reset:
self.model.post_reset() self.model.post_reset()
self.view.view(self.model, entry_redraw) self.view.view(self.model, entry_redraw)
def set_model(self, model): def set_model(self, model):
self.model = model self.model = model

View File

@ -5,37 +5,37 @@ from browser import document
def modal_template(content, title, msg, delete_msg=None): def modal_template(content, title, msg, delete_msg=None):
reset = message.msg(message.ModalNotOkClose) reset = message.msg(message.ModalNotOkClose)
footer = [] footer = []
if msg is not None: if msg is not None:
footer.append(h("a#modal-ok.button", {"on": {"click": message.msg(*msg)}}, "OK")) footer.append(h("a#modal-ok.button", {"on": {"click": message.msg(*msg)}}, "OK"))
footer.append(h("label.button.dangerous", {"on": {"click": reset}}, "Cancel")) footer.append(h("label.button.dangerous", {"on": {"click": reset}}, "Cancel"))
if delete_msg is not None: if delete_msg is not None:
footer.append(h("label.button.warning.modal-delete", {"on": {"click": message.msg(*delete_msg)}}, "🗑")) footer.append(h("label.button.warning.modal-delete", {"on": {"click": message.msg(*delete_msg)}}, "🗑"))
return [ return [
h("header", {}, [ h("header", {}, [
h("h3", {}, title), h("h3", {}, title),
h("label.close", {"on": {"click": reset}}, "×")]), h("label.close", {"on": {"click": reset}}, "×")]),
h("section.content", {}, content ), h("section.content", {}, content ),
h("footer", {}, footer)] h("footer", {}, footer)]
def _question(question, current_value, input_element): def _question(question, current_value, input_element):
props = {"value": current_value} props = {"value": current_value}
if input_element == "input": if input_element == "input":
props["type"] = "text" props["type"] = "text"
return [ return [
h("span", {}, question), h("span", {}, question),
h("label", {}, [ h("label", {}, [
h("{}#modal-question".format(input_element), {"props": props}, "")])] h("{}#modal-question".format(input_element), {"props": props}, "")])]
def big_question(question, current_value): def big_question(question, current_value):
return _question(question, current_value, "textarea") return _question(question, current_value, "textarea")
def question(question, current_value): def question(question, current_value):
return _question(question, current_value, "input") return _question(question, current_value, "input")
@ -47,69 +47,28 @@ def generic_list_editor(title, element_list_getter):
content.append(h("button", {"on": {"click": message.msg(message.AddToGenericList, element_list_getter)}}, "+")) content.append(h("button", {"on": {"click": message.msg(message.AddToGenericList, element_list_getter)}}, "+"))
return content return content
def homonymy_editor(title, current_labels):
def split_line2(left, right):
cls = "flex.two{}".format(".double-list-row")
return h("div.{}".format(cls), {}, [
h("div.half", {}, left), h("div.half", {}, right)])
content = [h("p", {}, title)]
for i, feature in enumerate(current_labels()):
name = []
value = []
name.append(h("label", {"attrs": {"for": i}}, "Name:"))
name.append(h("input.name-input", {"props": {"type": "text", "value": feature["name"], "id": i}}, ""))
value.append(h("label", {"attrs": {"for": i + "-value"}}, "Value:"))
value.append(h("input.value-input", {"props": {"type": "text", "value": feature["value"], "id": i + "-value"}}, ""))
content.append(split_line2(name, value))
content.append(h("button", {"on": {"click": message.msg(message.AddToGenericList, current_labels)}}, "+"))
return content
def explanation_editor(title, current_labels):
def split_line2(left, right):
cls = "flex.two{}".format(".double-list-row")
return h("div.{}".format(cls), {}, [
h("div.four-fifth", {}, left), h("div.fifth", {}, right)])
content = [h("p", {}, title)]
for i, explanation in enumerate(current_labels()):
language = []
value = []
language.append(h("label", {"attrs": {"for": i}}, "Language:"))
language.append(h("input.language-input", {"props": {"type": "text", "value": explanation["language"], "id": i}}, ""))
value.append(h("label", {"attrs": {"for": i + "-value"}}, "Value:"))
value.append(h("input.value-input", {"props": {"type": "text", "value": explanation["value"], "id": i + "-value"}}, ""))
content.append(split_line2(value, language))
content.append(h("button", {"on": {"click": message.msg(message.AddToGenericList, current_labels)}}, "+"))
return content
def label_list_editor(current_labels, add_label_message_class): def label_list_editor(current_labels, add_label_message_class):
def split_line3(left, center, right, is_llr=True): def split_line3(left, center, right, is_llr=True):
cls = "flex.three{}".format(".label-list-row" if is_llr else "") cls = "flex.three{}".format(".label-list-row" if is_llr else "")
return h("div.{}".format(cls), {}, [ return h("div.{}".format(cls), {}, [
h("span.third", {}, left), h("span.third", {}, center), h("span.third", {}, right)]) h("span.third", {}, left), h("span.third", {}, center), h("span.third", {}, right)])
def dropdown_right(label_type, label): def dropdown_right(label_type, label):
left = h("span.label-type", {}, label_type) left = h("span.label-type", {}, label_type)
options = [h("option", {}, [])] options = [h("option", {}, [])]
for value in TAGS[label_type]: for value in TAGS[label_type]:
options.append(h("option", {"props": {"selected": label == value}}, value)) options.append(h("option", {"props": {"selected": label == value}}, value))
center = h("select.label-value", {}, options) center = h("select.label-value", {}, options)
right_value = label if label not in TAGS[label_type] else "" right_value = label if label not in TAGS[label_type] else ""
right = h("input.label-value-other", right = h("input.label-value-other",
{"props": {"type": "text", "value": right_value, "placeholder": "drugo"}}, {"props": {"type": "text", "value": right_value, "placeholder": "drugo"}},
[]) [])
return split_line3(left, center, right) return split_line3(left, center, right)
content = [] content = []
kontrastivno = False kontrastivno = False
for key, value in current_labels: for key, value in current_labels:
@ -117,27 +76,27 @@ def label_list_editor(current_labels, add_label_message_class):
if value == "kontrastivno": if value == "kontrastivno":
kontrastivno = True kontrastivno = True
continue continue
content.append(dropdown_right(key, value)) content.append(dropdown_right(key, value))
# add a way to get new element to add to tag list # add a way to get new element to add to tag list
def get_new_label_type(): def get_new_label_type():
select = document.getElementById("new-tag-select") select = document.getElementById("new-tag-select")
return (select.options[select.selectedIndex].text, "") return (select.options[select.selectedIndex].text, "")
add_label_message_class.append(get_new_label_type) add_label_message_class.append(get_new_label_type)
content.append(split_line3( content.append(split_line3(
h("", {}, []), h("", {}, []),
h("label", {}, [ h("label", {}, [
h("input#kontrastivno-input", {"props": {"type": "checkbox", "checked": kontrastivno}}, []), h("input#kontrastivno-input", {"props": {"type": "checkbox", "checked": kontrastivno}}, []),
h("span.checkable", {}, "kontrastivno")]), h("span.checkable", {}, "kontrastivno")]),
h("", {}, []))) h("", {}, [])))
left = h("span", {}, "Add more!") left = h("span", {}, "Add more!")
center = h("select#new-tag-select", {}, [h("option", {}, ltype) for ltype in TAGS.keys()]) center = h("select#new-tag-select", {}, [h("option", {}, ltype) for ltype in TAGS.keys()])
right = h("button", {"style": {"float": "right"}, "on": {"click": message.msg(*add_label_message_class)}}, "+") right = h("button", {"style": {"float": "right"}, "on": {"click": message.msg(*add_label_message_class)}}, "+")
content.append(split_line3(left, center, right, False)) content.append(split_line3(left, center, right, False))
content.append(h("hr", {}, [])) content.append(h("hr", {}, []))
return content return content

View File

@ -9,52 +9,53 @@ def edit_translation(translation, parent, cluster_idx, num_clusters, cls):
def split_line2(left, right): def split_line2(left, right):
return h("div.flex.two", {}, [ return h("div.flex.two", {}, [
h("span.third.span-left-of-input", {}, left), h("span.two-third", {}, right)]) h("span.third.span-left-of-input", {}, left), h("span.two-third", {}, right)])
content = [] content = []
if type(parent) is model.Example: if type(parent) is model.Example:
content.extend([ content.extend([
h("span.translation-original-title", {}, "Primer: "), h("span.translation-original-title", {}, "Primer: "),
h("span.translation-original", {}, parent.simple_view()), h("span.translation-original", {}, parent.simple_view()),
h("hr", {}, None)]) h("hr", {}, None)])
# first line: transalation itself # first line: transalation itself
content.extend([ content.extend([
split_line2("Prevedek:", h("textarea#etv", {"props": {"value": translation.translation}}, ""))]) split_line2("Prevedek:",
h("textarea#etv", {"props": {"value": translation.translation}}, "")),
content.extend(explanation_editor("Razlage:", lambda: translation.explanationList)) split_line2("Razlaga:",
h("textarea#ete", {"props": {"value": translation.explanation}}, ""))])
# cluster number # cluster number
options = [h("option", {"props": {"selected": idx == cluster_idx}}, str(idx + 1)) for idx in range(num_clusters + 1)] options = [h("option", {"props": {"selected": idx == cluster_idx}}, str(idx + 1)) for idx in range(num_clusters + 1)]
content.append(split_line2("Stevilka gruce:", h("select#cluster-num", {}, options))) content.append(split_line2("Stevilka gruce:", h("select#cluster-num", {}, options)))
content.append(h("h4", {}, "Tags")) content.append(h("h4", {}, "Tags"))
content.extend(label_list_editor(translation.copy().tags, [message.AddToLabelList, translation.copy().tags])) content.extend(label_list_editor(translation.copy().tags, [message.AddToLabelList, translation.copy().tags]))
return modal_template(content, "Translation", cls) return modal_template(content, "Translation", cls)
def edit_sense_label(sense): def edit_sense_label(sense):
content = label_list_editor(sense.copy().labels, [message.AddToLabelList, sense.copy().labels]) content = label_list_editor(sense.copy().labels, [message.AddToLabelList, sense.copy().labels])
return modal_template(content, "Translation", (message.EditSenseLabel, sense)) return modal_template(content, "Translation", (message.EditSenseLabel, sense))
def edit_example(example, sense): def edit_example(example, sense):
example_original = example example_original = example
example = example_original.copy() example = example_original.copy()
def role_msg(idx, role): def role_msg(idx, role):
return message.msg(message.ExampleRoleChange, example_original, idx, role) return message.msg(message.ExampleRoleChange, example_original, idx, role)
divs = [] divs = []
def list_of_right_buttons(idx, component): def list_of_right_buttons(idx, component):
result = [ result = [
h("span.example-component-button.example-component-headword", h("span.example-component-button.example-component-headword",
{"on": {"click": role_msg(idx, "headword")}}, "H"), {"on": {"click": role_msg(idx, "headword")}}, "H"),
h("span.example-component-button.example-component-collocate", h("span.example-component-button.example-component-collocate",
{"on": {"click": role_msg(idx, "collocate")}}, "C"), {"on": {"click": role_msg(idx, "collocate")}}, "C"),
h("span.example-component-button.example-component-other", h("span.example-component-button.example-component-other",
{"on": {"click": role_msg(idx, "other")}}, "O")] {"on": {"click": role_msg(idx, "other")}}, "O")]
if example.is_multiword(): if example.is_multiword():
additional_class = ".example-component-no-space" if component.no_space else "" additional_class = ".example-component-no-space" if component.no_space else ""
click_message = message.msg(message.ExampleComponentSpace, example_original, idx) click_message = message.msg(message.ExampleComponentSpace, example_original, idx)
@ -63,36 +64,32 @@ def edit_example(example, sense):
else: else:
result.append(h("span.example-component-button.example-component-none", result.append(h("span.example-component-button.example-component-none",
{"on": {"click": role_msg(idx, "none")}}, "N")) {"on": {"click": role_msg(idx, "none")}}, "N"))
if "-" not in example.inner.other_attributes["structureName"]: result.extend([
result.extend([ h("span.example-component-button",
h("span.example-component-button", {"on": {"click": message.msg(message.ExampleComponentAdd, example_original, idx)}}, "+"),
{"on": {"click": message.msg(message.ExampleComponentAdd, example_original, idx)}}, "+"), h("span.example-component-button",
h("span.example-component-button", {"on": {"click": message.msg(message.ExampleComponentRemove, example_original, idx)}}, "-")])
{"on": {"click": message.msg(message.ExampleComponentRemove, example_original, idx)}}, "-")])
return result return result
divs.append(h("div.flex.five.example-component", {}, [h("div.one-fifth", {}, "Struktura:"),
h("div.three-fifth", {}, example.inner.other_attributes["structureName"])]))
for idx, component in enumerate(example.components): for idx, component in enumerate(example.components):
role_txt = component.role if component.role is not None else "none" role_txt = component.role if component.role is not None else "none"
color_class = ".example-component-" + role_txt color_class = ".example-component-" + role_txt
left = [h("span" + color_class, {}, role_txt)] left = [h("span" + color_class, {}, role_txt)]
if component.role is None: if component.role is None:
middle = [h("textarea.example-component-text", {"props": {"value": component.text}}, "")] middle = [h("textarea.example-component-text", {"props": {"value": component.text}}, "")]
else: else:
middle = [h("input.example-component-text", {"props": {"type": "text", "value": component.text}}, "")] middle = [h("input.example-component-text", {"props": {"type": "text", "value": component.text}}, "")]
divs.append(h("div.flex.five.example-component", {}, [ divs.append(h("div.flex.five.example-component", {}, [
h("div.one-fifth", {}, left), h("div.one-fifth", {}, left),
h("div.three-fifth", {}, middle), h("div.three-fifth", {}, middle),
h("div.one-fifth", {}, list_of_right_buttons(idx, component))])) h("div.one-fifth", {}, list_of_right_buttons(idx, component))]))
return modal_template(divs, "Edit Example", return modal_template(divs, "Edit Example",
(message.EditExampleText, example_original, sense)) (message.EditExampleText, example_original, sense))
@ -102,12 +99,6 @@ def edit_variants(entry):
return modal_template(content, "Add or remove variants", (message.EditVariants,), (message.DeleteVariants,)) return modal_template(content, "Add or remove variants", (message.EditVariants,), (message.DeleteVariants,))
def edit_homonymy(entry):
hget = lambda: entry.copy().homonymy
content = homonymy_editor("Homonymy", hget)
return modal_template(content, "Add or remove homonymy features", (message.EditHomonymy,), (message.DeleteHomonymy,))
def edit_related_entries(entry): def edit_related_entries(entry):
reget = lambda: entry.copy().related_entries reget = lambda: entry.copy().related_entries
content = generic_list_editor("Related entries", reget) content = generic_list_editor("Related entries", reget)
@ -134,29 +125,29 @@ def do_chosen_examples(example_list, entry):
if ex in example_list: if ex in example_list:
example_senses.append(idx) example_senses.append(idx)
break break
sense_of_first_example = example_senses[0] sense_of_first_example = example_senses[0]
options = [h("p", {}, "Choose sense for examples")] options = [h("p", {}, "Choose sense for examples")]
for idx, sense in enumerate(entry.senses): for idx, sense in enumerate(entry.senses):
text = "{}: {}".format(idx + 1, sense.definition["indicator"]) text = "{}: {}".format(idx + 1, sense.definition["indicator"])
id_ = "choose-example-{}".format(idx) id_ = "choose-example-{}".format(idx)
props = {"type": "radio", "name": "choose-example"} props = {"type": "radio", "name": "choose-example"}
if idx == sense_of_first_example: if idx == sense_of_first_example:
props["checked"] = True props["checked"] = True
options.append(h("input#{}.checkable-input".format(id_), {"props": props}, [])) options.append(h("input#{}.checkable-input".format(id_), {"props": props}, []))
options.append(h("label.checkable", {"attrs": {"for": id_}}, text)) options.append(h("label.checkable", {"attrs": {"for": id_}}, text))
options.append(h("br", {}, [])) options.append(h("br", {}, []))
return modal_template(options, "Examples picker", (message.DoChosenExamples, example_list)) return modal_template(options, "Examples picker", (message.DoChosenExamples, example_list))
def ske_list(search_term, data, page_num, senses, ske_kinds): def ske_list(search_term, data, page_num, senses, ske_kinds):
list_contents = [] list_contents = []
ske_list_hidden = False ske_list_hidden = False
if data is None: if data is None:
list_contents.append(h("div.loadingspinner", {}, "")) list_contents.append(h("div.loadingspinner", {}, ""))
elif type(data) is list: elif type(data) is list:
@ -168,7 +159,7 @@ def ske_list(search_term, data, page_num, senses, ske_kinds):
ske_list_hidden = True ske_list_hidden = True
else: else:
list_contents.append(h("span.error", {}, "Something went wrong in SKE: {}".format(data))) list_contents.append(h("span.error", {}, "Something went wrong in SKE: {}".format(data)))
contents = [ contents = [
h("div.flex.four", {}, [ h("div.flex.four", {}, [
h("select#ske-select.fourth", {}, [ h("select#ske-select.fourth", {}, [
@ -177,22 +168,18 @@ def ske_list(search_term, data, page_num, senses, ske_kinds):
h("input#ske-search", {"props": {"value": search_term, "type": "text"}}, "")]), h("input#ske-search", {"props": {"value": search_term, "type": "text"}}, "")]),
h("label.fourth.ske-mid-input", {}, [ h("label.fourth.ske-mid-input", {}, [
h("input#ske-page-num", {"attrs": { h("input#ske-page-num", {"attrs": {
"value": str(page_num), "value": str(page_num),
"type": "number", "type": "number",
"min": 1, "min": 1,
"step": 1}}, "")]), "step": 1}}, "")]),
h("label.fourth.ske-mid-input", {}, [ h("span.fourth.button.ske-right-button",
h("select#ske-pos-query", {}, [h("option", {}, "{}".format(pos)) for pos in ["simple", "samostalnik", "glagol", "pridevnik", "prislov", "zaimek"]])
]),
h("span.fourth.button.ske-right-button",
{"on": {"click": message.msg(message.SearchInSkeModal)}}, "Isci")]), {"on": {"click": message.msg(message.SearchInSkeModal)}}, "Isci")]),
h("div.ske-list", h("div.ske-list",
{"style": {"visibility": "hidden" if ske_list_hidden else "visible"}}, {"style": {"visibility": "hidden" if ske_list_hidden else "visible"}},
list_contents), list_contents),
h("div.flex.three", {}, [ h("div.flex.three", {}, [
h("span.third", {}, "Vstavi v:"), h("span.third", {}, "Vstavi v:"),
h("select#ske-sense-select.two-third", {}, [ h("option", {}, "{} {}".format( h("select#ske-sense-select.two-third", {}, [ h("option", {}, "{} {}".format(
idx + 1, sense.definition["indicator"])) for idx, sense in enumerate(senses)])])] idx + 1, sense.definition["indicator"])) for idx, sense in enumerate(senses)])])]
return modal_template(contents, "SKE", (message.SkeInsert, data)) return modal_template(contents, "SKE", (message.SkeInsert, data))

View File

@ -58,7 +58,7 @@ class View:
def view_ske_button(model): def view_ske_button(model):
return h( return h(
"span#ske-button.button.toggle", "span#ske-button.button.toggle",
{ "on": {"click": msg(ShowSkeModal, 1, model.entry.headword, 0, "simple")} }, { "on": {"click": msg(ShowSkeModal, 1, model.entry.headword, 0)} },
h("svg#ske-img", { h("svg#ske-img", {
"attrs": { "attrs": {
"xmlns": "http://www.w3.org/2000/svg", "xmlns": "http://www.w3.org/2000/svg",