51 Commits

Author SHA1 Message Date
matic_t
596a0a372a fixed id=null and moving collocations between senses 2020-12-05 06:08:53 -08:00
matic_t
920ce87cfc fix definitions 2020-10-30 05:55:11 -07:00
matic_t
b2e277d8eb Merge pull request 'mt-definition-list-ui' (#11) from mt-definition-list-ui into master
Reviewed-on: #11
2020-10-30 12:42:18 +00:00
matic_t
6816f8c33a definitionList UI support 2020-10-30 05:40:06 -07:00
matic_t
30cad4ab23 definitionList UI support 2020-10-30 05:39:54 -07:00
matic_t
cc1a1b34d4 Merge pull request 'definitionList UI support - v 4.1' (#10) from mt-definition-list-ui into master
Reviewed-on: #10
2020-10-30 12:31:39 +00:00
matic_t
30d0709781 definitionList UI support 2020-10-30 05:01:58 -07:00
a571a9ceb1 updated sense label 2020-10-16 16:50:50 +02:00
matic_t
a8b84c4b37 Merge pull request 'mt-export-example-as-entry - v4.1' (#9) from mt-export-example-as-entry into master
Reviewed-on: #9
2020-10-12 08:35:01 +00:00
matic_t
bc897dbe06 Should be finished v4 2020-10-12 01:28:06 -07:00
matic_t
fe3b3dfb0c Should be finished v3 2020-10-12 01:28:06 -07:00
matic_t
5f26dd6034 Should be finished v2 2020-10-12 01:28:06 -07:00
matic_t
5e741343c3 finished 2020-10-12 01:28:06 -07:00
matic_t
bd4e64f818 lexicalUnit from single lexeme to multiple lexeme support 2020-10-12 01:28:06 -07:00
matic_t
eea25b9968 export multiword example as new entry 2020-10-12 01:28:06 -07:00
matic_t
a0758f5c11 sense id support 2020-10-12 01:27:36 -07:00
300f90822c cql query option 2020-09-15 08:38:44 +02:00
Luka Kavčič
37980d56e5 Merge pull request 'lk-collocations-feature' (#8) from lk-collocations-feature into master
Reviewed-on: #8
2020-09-15 06:20:55 +00:00
Luka Kavčič
0b2bf53a6f Merge branch 'master' into lk-collocations-feature 2020-09-15 06:19:50 +00:00
c7a405fc46 lock <comp> in collocations 2020-09-03 13:46:14 +02:00
4812c18a1d structure id fix 2020-09-03 11:28:57 +02:00
197cc6199c show structure at example edit 2020-09-03 10:51:32 +02:00
19d3e38dcb better collocation export 2020-09-03 10:29:24 +02:00
matic_t
76c80baa09 remove saving original from grammar 2020-08-27 00:20:58 -07:00
8802a09c9c sort and filter collocations 2020-08-25 16:24:11 +02:00
matic_t
04c8bc1471 Merge pull request 'add support for lexeme_id on comp' (#7) from mt-additional-xml-shema-support into master
Reviewed-on: #7
2020-08-20 15:32:36 +00:00
matic_t
d513ec8eaa add support for lexeme_id on comp 2020-08-20 08:29:50 -07:00
Luka Kavčič
5fe2bb62bb Merge pull request 'mt-additional-xml-shema-support' (#6) from mt-additional-xml-shema-support into master
Reviewed-on: #6
2020-08-14 09:32:33 +00:00
matic_t
85bf0473e5 logs + comment for upcoming work 2020-08-12 06:22:39 -07:00
matic_t
8049f5ed95 translationContainerList implementation 2020-08-12 06:18:00 -07:00
matic_t
48c51c38de handling new entries 2020-08-12 06:17:29 -07:00
matic_t
094cc7afcf Merge branch 'master' of https://gitea.cjvt.si/lexonomy/lexonomy_custom_editor into mt-additional-xml-shema-support 2020-08-11 23:14:33 -07:00
matic_t
410054cdd6 grammar example with saved entry_xml 2020-08-11 07:41:47 -07:00
matic_t
ec811028ab explanationList 2020-08-10 08:38:08 -07:00
matic_t
752ec44d43 fixing double_list_getter 2020-08-07 01:34:47 -07:00
matic_t
83396ef8a0 ups 2020-08-06 05:40:26 -07:00
matic_t
efe4d07464 required audio support #1351 2020-08-06 05:39:24 -07:00
matic_t
1770932a14 language on explanation support + explanation as new model + homonymy refactored as a double list 2020-08-06 03:47:52 -07:00
matic_t
2b2a2c4bd9 Merge pull request 'mt-additional-xml-shema-support' (#5) from mt-additional-xml-shema-support into master
Reviewed-on: #5
2020-08-05 10:04:53 +00:00
matic_t
a07b35c6a8 Merge branch 'master' of https://gitea.cjvt.si/lexonomy/lexonomy_custom_editor into mt-additional-xml-shema-support 2020-08-04 07:07:58 -07:00
matic_t
ad83665b0d explanationList 2020-08-04 07:00:53 -07:00
Luka Kavčič
0c62cbe4d8 Merge pull request 'lk-collocation-structure-fix' (#4) from lk-collocation-structure-fix into master
Reviewed-on: #4
2020-08-04 10:17:28 +00:00
matic_t
964dc3f788 Explanation list support 2020-07-23 05:40:39 -07:00
matic_t
8b7c282fdf sloleks supported in components 2020-07-23 01:38:51 -07:00
matic_t
6f157eeea1 update build_and_upload.sh.template with unlink 2020-07-16 04:21:38 -07:00
matic_t
ed8bb37b15 Merge branch 'master' of https://gitea.cjvt.si/lexonomy/lexonomy_custom_editor into mt-homonymy-support 2020-07-16 03:50:04 -07:00
matic_t
9c007f6dd6 upsy daisys 2020-07-16 03:46:48 -07:00
matic_t
b010414bfe support homonymy inside modal 2020-07-16 03:22:54 -07:00
matic_t
fb9a809c02 modal supports editing name and value 2020-07-16 01:43:26 -07:00
matic_t
6f9142b046 Added support for name attribute 2020-07-16 01:31:16 -07:00
matic_t
a22490c0fc homonymy basic implementation 2020-07-15 04:17:58 -07:00
26 changed files with 960 additions and 397 deletions

View File

@@ -4,10 +4,10 @@
#############################################################################
# Alter these variables
#USERNAME= vps_sign_in(probably name@lexonomy.cjvt.si
#VPS_PASSWORD= vps password
#VPS_USERNAME= user name inside vps(probably name from @lexonomy)
#API_KEY= $(cat path/to/api/token/file)
#USERNAME=vps_sign_in(probably name@lexonomy.cjvt.si
#VPS_PASSWORD=vps password
#VPS_USERNAME=user name inside vps(probably name from @lexonomy)
#API_KEY=$(cat path/to/api/token/file)
# Exit if no argument is passed on run
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/
# Routes must be absolute or it doesn't work.
ssh -t $USERNAME -p $VPS_PASSWORD "sudo ln -s /home/$VPS_USERNAME/plugins/$PLUGIN_NAME /home/ozbolt/plugins/$PLUGIN_NAME"
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"

View File

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

View File

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

View File

@@ -1,17 +1,16 @@
from browser import document
from model.tags import export_tag
from model.translation import Translation
def export_to_xml(model):
xml_document = export_entry(model.entry)
serializer = __new__(XMLSerializer())
return serializer.serializeToString(xml_document);
return serializer.serializeToString(xml_document)
def export_entry(entry):
parser = __new__(DOMParser())
doc = parser.parseFromString("<entry />", "text/xml")
entry_xml = doc.firstChild
# create head
@@ -21,139 +20,321 @@ def export_entry(entry):
status = doc.createElement("status")
status.textContent = entry.status
head.appendChild(status)
headword = doc.createElement("headword")
headword_lemma = doc.createElement("lemma")
# headword_lemma = entry.original_xml.querySelector("head headword lemma")
headword_lemma.textContent = entry.headword
if entry.headword_type is not None:
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)
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 len(entry.lexical_unit) > 0:
if len(entry.lexical_unit) > 0 and len(entry.lexical_unit['lexemes']) > 0:
lexunit = doc.createElement("lexicalUnit")
lexunit.setAttribute("id", entry.lexical_unit["id"])
lexunit.setAttribute("type", "single")
lexeme = doc.createElement("lexeme")
lexeme.setAttribute("lexical_unit_lexeme_id", entry.lexical_unit["id"])
lexeme.textContent = entry.lexical_unit["text"]
lexunit.appendChild(lexeme)
if(entry.lexical_unit["id"]):
lexunit.setAttribute("id", entry.lexical_unit["id"])
lexunit.setAttribute("type", entry.lexical_unit['type'])
for lexeme in entry.lexical_unit["lexemes"]:
lexeme_xml = doc.createElement("lexeme")
if(lexeme["id"]):
lexeme_xml.setAttribute("lexical_unit_lexeme_id", lexeme["id"])
lexeme_xml.textContent = lexeme["text"]
if len(entry.lexical_unit["lexemes"]) > 1:
component = doc.createElement('component')
component.appendChild(lexeme_xml)
lexunit.appendChild(component)
else:
lexunit.appendChild(lexeme_xml)
head.appendChild(lexunit)
grammar = doc.createElement("grammar")
grammar_category = doc.createElement("category")
grammar_category.textContent = entry.grammar
grammar.appendChild(grammar_category)
head.appendChild(grammar)
if len(entry.measure) > 0:
measure_list = doc.createElement("measureList")
measure = doc.createElement("measure")
measure.setAttribute("source", entry.measure["source"])
measure.setAttribute("type", entry.measure["type"])
measure.textContent = entry.measure["text"]
measure_list.appendChild(measure)
head.appendChild(measure_list)
variants = doc.createElement("variantList")
head.appendChild(variants)
for v in entry.variants:
variant = doc.createElement("variant")
variant.textContent = v
variants.appendChild(variant)
relist = doc.createElement("relatedEntryList")
head.appendChild(relist)
for re in entry.related_entries:
relateEntry = doc.createElement("relatedEntry")
relateEntry.textContent = re
relist.appendChild(relateEntry)
head.appendChild(_export_label_list(doc, entry.labels))
comment = doc.createElement("comment")
comment.textContent = entry.comment
head.appendChild(comment)
# now lets do body
body = doc.createElement("body")
entry_xml.appendChild(body)
sense_list = doc.createElement("senseList")
body.appendChild(sense_list)
for sense in entry.senses:
sense_list.appendChild(export_sense(doc, sense))
return doc
def export_sense(doc, sense):
sense_xml = doc.createElement("sense")
sense_xml.appendChild(_export_label_list(doc, sense.labels))
if sense.id is not None:
sense_xml.setAttribute("id", sense.id)
definition_list = doc.createElement("definitionList")
sense_xml.appendChild(definition_list)
for typ, text in sense.definition.items():
definition = doc.createElement("definition")
definition.textContent = text
definition.setAttribute("type", typ)
definition_list.appendChild(definition)
for definition in sense.definitions:
definition_xml = doc.createElement("definition")
definition_xml.textContent = definition["value"]
definition_xml.setAttribute("type", definition["type"])
definition_list.appendChild(definition_xml)
translation_container_list = doc.createElement("translationContainerList")
export_translation_list(doc, sense, translation_container_list)
sense_xml.appendChild(translation_container_list)
example_container_list = doc.createElement("exampleContainerList")
sense_xml.appendChild(example_container_list)
for example in sense.examples:
example_container = example.export(doc)
export_translation_list(doc, example, example_container)
translation_container_list = doc.createElement("translationContainerList")
export_translation_list(doc, example, translation_container_list)
example_container.appendChild(translation_container_list)
example_container_list.appendChild(example_container)
return sense_xml
def export_translation_list(doc, py_parent, xml_parent):
for cidx, cluster in enumerate(py_parent.translations):
for translation in cluster:
translation_container = export_translation(doc, translation)
translation_container.setAttribute("cluster", str(cidx + 1))
xml_parent.appendChild(translation_container)
if len(cluster) > 0:
for translation in cluster:
translation_container = export_translation(doc, translation)
translation_container.setAttribute("cluster", str(cidx + 1))
xml_parent.appendChild(translation_container)
def export_translation(doc, translation):
translation_xml = doc.createElement("translationContainer")
translation_xml.appendChild(_export_label_list(doc, translation.tags))
actual_t = doc.createElement("translation")
actual_t.textContent = translation.translation
actual_t.setAttribute("targetLang", translation.targetLang)
if translation.audio:
actual_t.setAttribute("audio", translation.audio)
if translation.source:
actual_t.setAttribute("source", translation.source)
translation_xml.appendChild(actual_t)
explanation = doc.createElement("explanation")
explanation.textContent = translation.explanation
translation_xml.appendChild(explanation)
if len(translation.explanationList) > 0 :
explanationList = _export_explanation_list(doc, translation.explanationList)
translation_xml.appendChild(explanationList)
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):
result = doc.createElement("labelList")
for key, value in lst:
key, value = export_tag(key, value)
label_el = doc.createElement("label")
label_el.textContent = value
label_el.setAttribute('type', key)
result.appendChild(label_el)
return result
def _original_xml_query_selector(selector, entry, doc, parent_selector = selector.rsplit(' ', 1)[0]):
query = entry.original_xml.querySelector(selector)
if query is None:
query = doc.createElement(selector.rsplit(' ', 1)[1])
entry.original_xml.querySelector(parent_selector).appendChild(query)
return query
def export_example_to_entry_xml(example, other_examples = None):
parser = __new__(DOMParser())
doc = parser.parseFromString("<entry />", "text/xml")
entry_xml = doc.firstChild
head = doc.createElement("head")
entry_xml.appendChild(head)
status = doc.createElement("status")
head.appendChild(status)
headword = doc.createElement("headword")
head.appendChild(headword)
lemma = doc.createElement("lemma")
lemma.textContent = " ".join(comp.text for comp in example.components)
lemma.setAttribute("type", "compound")
if example.inner.other_attributes['audio'] is not None:
lemma.setAttribute('audio', example.inner.other_attributes['audio'])
headword.appendChild(lemma)
homonymy = doc.createElement("homonymy")
headword.appendChild(homonymy)
lexical_unit = doc.createElement("lexicalUnit")
lexical_unit.setAttribute("type", "MWE")
head.appendChild(lexical_unit)
if example.inner.other_attributes['structure_id'] != None and len(example.components) <= 3:
lexical_unit.setAttribute("id", example.inner.other_attributes['structure_id'])
for comp in example.components:
lexeme = doc.createElement("lexeme")
lexeme.textContent = comp.text
comp_xml = doc.createElement("component")
lexical_unit.appendChild(comp_xml)
comp_xml.appendChild(lexeme)
grammar = doc.createElement("grammar")
category = doc.createElement("category")
grammar.appendChild(category)
head.appendChild(grammar)
variant_list = doc.createElement("variantList")
head.appendChild(variant_list)
related_entry_list = doc.createElement("relatedEntryList")
head.appendChild(related_entry_list)
label_list = doc.createElement("labelList")
head.appendChild(label_list)
comment = doc.createElement("comment")
head.appendChild(comment)
body = doc.createElement("body")
entry_xml.appendChild(body)
sense_list = doc.createElement("senseList")
body.appendChild(sense_list)
sense = doc.createElement("sense")
sense_list.appendChild(sense)
sense_label_list = doc.createElement("labelList")
sense.appendChild(sense_label_list)
first_translation = example.translations[0][0] if len(example.translations) > 0 and len(example.translations[0]) > 0 else Translation()
first_translation_is_valid = False
translation_label_list = doc.createElement("labelList")
# Add labels to sense if label value isn't kontrastivno or približek else keep them in translation
for key, value in first_translation.tags:
key, value = export_tag(key, value)
label_el = doc.createElement("label")
label_list = translation_label_list if value == "kontrastivno" or value == "približek" else sense_label_list
label_el.textContent = value
label_el.setAttribute('type', key)
label_list.appendChild(label_el)
# Set definition as explanation if explanation in slo
definition_list = doc.createElement("definitionList")
sense.appendChild(definition_list)
for explanation in first_translation.explanationList:
if explanation.language == "slo":
definition = doc.createElement("definition")
definition.setAttribute("type", "indicator")
definition.textContent = explanation.value
definition_list.appendChild(definition)
first_translation.explanationList.remove(explanation)
translation_container_list = doc.createElement("translationContainerList")
sense.appendChild(translation_container_list)
translation_container = doc.createElement("translationContainer")
if len(translation_label_list) > 0:
translation_container.appendChild(translation_label_list)
if first_translation.translation is not "":
translation = doc.createElement("translation")
translation_container.appendChild(translation)
translation.textContent = first_translation.translation
translation.setAttribute("targetLang", first_translation.targetLang)
if first_translation.audio:
translation.setAttribute("audio", first_translation.audio)
if first_translation.source:
translation.setAttribute("source", first_translation.source)
first_translation_is_valid = True
if len(first_translation.explanationList) > 0 :
explanation_list = _export_explanation_list(doc, first_translation.explanationList)
translation_container.appendChild(explanation_list)
first_translation_is_valid = True
if first_translation_is_valid:
translation_container_list.appendChild(translation_container)
example.translations[0] = example.translations[0][1:] if len(example.translations) > 0 and len(example.translations[0]) > 0 else example.translations[0]
export_translation_list(doc, example, translation_container_list)
if other_examples is not None:
example_container_list = doc.createElement("exampleContainerList")
sense.appendChild(example_container_list)
for example in other_examples:
example_container = example.export(doc)
translation_container_list = doc.createElement("translationContainerList")
export_translation_list(doc, example, translation_container_list)
example_container.appendChild(translation_container_list)
example_container_list.appendChild(example_container)
return doc

View File

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

View File

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

View File

@@ -8,28 +8,51 @@ def generic_list_getter():
if result_candidate != "":
result.append(result_candidate)
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 definitions_getter():
result = {}
result["indicator"] = document.getElementById("indicator-input").value
result["explanation"] = document.getElementById("explanation-input").value
return result
def label_list_getter():
result = []
for row in document.getElementsByClassName("label-list-row"):
ltype = row.querySelector(".label-type")
lvalue = row.querySelector(".label-value")
lother = row.querySelector(".label-value-other")
if lother is None:
continue
value = lother.value
if not value:
value = lvalue.options[lvalue.selectedIndex].text
value = lvalue.options[lvalue.selectedIndex].text
if not value:
continue
result.append((ltype.textContent, value))
kontrastivno = document.getElementById("kontrastivno-input").checked;
if kontrastivno:
result.append(("razmerje", "kontrastivno"))
return result

View File

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

View File

@@ -3,6 +3,10 @@ from message.simple_messages import DataChgClickMessage, ClickMessage, NoReset
from message.message import Message
from model.example import Example, ComponentLexeme
from model.sense import Sense
from model.entry import Entry
from model.model import Model
import lib.screenful as screenful
from export import export_to_xml, export_example_to_entry_xml
@@ -13,6 +17,17 @@ def _get_example_idx(example, model):
return (sense, eidx)
class ExampleAsNewEntry(ClickMessage):
def update_model(self, model):
example = self.get_arg(0, Example)
entry_xml = export_example_to_entry_xml(example)
new_entry = Entry()
new_entry.import_xml(entry_xml)
new_model = Model()
new_model.entry = new_entry
screenful.screenful().Editor['new'](None, export_to_xml(new_model))
class ExampleMoveUp(DataChgClickMessage):
def update_model(self, model):
example = self.get_arg(0, Example)
@@ -60,7 +75,7 @@ class EditExampleText(Message):
if example.newly_created:
example.newly_created = False
sense.examples.append(example)
idx = 0
for txt in document.getElementsByClassName("example-component-text"):
example.components[idx].text = txt.value

View File

@@ -57,11 +57,21 @@ class ShowSenseMenu(ShowMenu):
class ShowExampleMenu(KeyPlusClickMessage):
def update_model_default(self, model):
example = self.get_arg(0, Example)
# if some are chosen, then show modal for choosing senses
# if some are chosen, then show modal for choosing actions
if len(model.chosen_examples) > 0 and example in model.chosen_examples:
chosen_examples = model.chosen_examples
model.modal_set(lambda: modals.do_chosen_examples(chosen_examples, model.entry))
multiword_example = False
for chosen_example in chosen_examples:
if chosen_example.is_multiword():
if multiword_example is False:
multiword_example = chosen_example
else:
multiword_example = False
break
model.modal_set(lambda: modals.do_chosen_examples(chosen_examples, model, multiword_example))
else:
model.menu_location = self.menu_location
model.menu_target = example

View File

@@ -3,54 +3,61 @@ from message.simple_messages import ClickMessage
from model import Example, Sense, Translation
from view import modals
class ShowSenseLabelEdit(ClickMessage):
def update_model(self, model):
model.sense = self.get_arg(0, Sense)
model.sense.make_copy()
model.modal_set(lambda: modals.edit_sense_label(model.sense))
class ShowSenseDefinitionEdit(ClickMessage):
def update_model(self, model):
model.sense = self.get_arg(0, Sense)
model.sense.make_copy()
model.modal_set(lambda: modals.edit_sense_definition(model.sense))
class ShowCommentEdit(ClickMessage):
def update_model(self, model):
model.modal_set(lambda: modals.edit_comment(model.entry.comment))
class ShowVariantsEdit(ClickMessage):
def update_model(self, model):
model.entry.make_copy()
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):
def update_model(self, model):
model.entry.make_copy()
model.modal_set(lambda: modals.edit_related_entries(model.entry))
class ShowExampleEdit(ClickMessage):
def update_model(self, model):
example = self.get_arg(0, Example)
sense = self.get_arg(1, Sense)
example.make_copy()
model.modal_set(lambda: modals.edit_example(example, sense))
class ShowEditTranslation(ClickMessage):
def update_model(self, model):
translation = self.get_arg(0, Translation)
# Get translation location
(cidx, idx), (parent, cluster) = EditTranslation.get_translation_location(model.entry, translation)
translation.make_copy()
num_clusters = len(parent.translations)
model.modal_set(lambda: modals.edit_translation(
@@ -61,10 +68,10 @@ class ShowAddTranslation(ClickMessage):
def update_model(self, model):
chosen_sense_or_example = self.get_arg(0)
translation = Translation()
translation.make_copy()
model.modal_set(lambda: modals.edit_translation(
translation,
translation,
chosen_sense_or_example,
-1,
len(chosen_sense_or_example.translations),
@@ -75,4 +82,4 @@ class ShowEntryLabelsEdit(ClickMessage):
def update_model(self, model):
model.entry.make_copy()
model.modal_set(lambda: modals.edit_entry_labels(model.entry))

View File

@@ -22,20 +22,20 @@ class AddToGenericList(NoReset):
def update_model(self, model):
list_getter = self.get_arg(0)
list_getter().append("")
def data_change(self):
return False
class AddToLabelList(NoReset):
def update_model(self, model):
list_to_add_to = self.get_arg(0, list)
thing_to_add_getter = self.get_arg(1)
thing_to_add = thing_to_add_getter()
# just adding to the copy to show in the modal
list_to_add_to.append(thing_to_add)
def data_change(self):
return False
@@ -43,42 +43,69 @@ class AddToLabelList(NoReset):
class AddSense(Message):
def update_model(self, model):
sense = Sense()
sense.definition = {"indicator": "New Sense"}
sense.definitions = [{"type": "indicator", "value": "Nov pomen"}]
model.entry.senses.append(sense)
class EditSenseDefinition(QuestionMessage):
class EditSenseDefinition(Message):
def update_model(self, model):
sense = self.get_arg(0, Sense)
sense.definition["indicator"] = self.new_text
definitions_values = common_accessors.definitions_getter()
indicator = None
explanation = None
for x in sense.definitions:
if indicator is None and x["type"] == "indicator":
indicator = x
if explanation is not None:
break
if explanation is None and x["type"] == "explanation":
explanation = x
if indicator is not None:
break
if definitions_values["indicator"] != "":
if indicator is None:
indicator = {"type": "indicator"}
sense.definitions.append(indicator)
indicator["value"] = definitions_values["indicator"]
elif indicator is not None:
sense.definitions.remove(indicator)
if definitions_values["explanation"] != "":
if explanation is None:
explanation = {"type": "explanation"}
sense.definitions.append(explanation)
explanation["value"] = definitions_values["explanation"]
elif explanation is not None:
sense.definitions.remove(explanation)
class EditComment(QuestionMessage):
def update_model(self, model):
model.entry.comment = self.new_text
class DoChosenExamples(Message):
class MoveExamplesToSense(Message):
def update_model(self, model):
chosen_examples = self.get_arg(0, list)
inputs = document.getElementsByClassName("checkable-input")
selected = None
for idx, el in enumerate(inputs):
if el.checked:
selected = idx
break
# none was selected
if selected is None:
return
# first, remove the selected examples from wherever they were
for sense in model.entry.senses:
for example in chosen_examples:
if example in sense.examples:
sense.examples.remove(example)
# now, append selected examples to chosen sense
model.entry.senses[selected].examples.extend(chosen_examples)
@@ -87,8 +114,13 @@ class EditVariants(Message):
def update_model(self, model):
variants = common_accessors.generic_list_getter()
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):
def update_model(self, model):
related_entries = common_accessors.generic_list_getter()
@@ -99,17 +131,17 @@ class EditEntryLabels(Message):
def update_model(self, model):
labels = common_accessors.label_list_getter()
model.entry.labels = labels
class ExampleClusterEdit(DataChgClickMessage):
def update_model(self, model):
example = self.get_arg(0, Example)
cluster = self.get_arg(1, int)
example.set_cluster(cluster)
class ExampleClusterAdd(DataChgClickMessage):
def update_model(self, model):
example = self.get_arg(0, Example)
example.set_cluster(ExampleClusters.first_empty_cluster())

View File

@@ -59,7 +59,8 @@ class SkeCollocation:
def __init__(self, data):
self.word = data.word
self.frequency = data.count
self.structure_name, self.structure_id = convert_structure(data.gramrel, data.lempos)
self.gramrel = data.gramrel
self.structure_name, self.structure, self.structure_id = convert_structure(data.gramrel, data.lempos)
self.other = {"score": data.score, "cm": data.cm}
@@ -102,13 +103,28 @@ def match_gf2_examples(data, *args):
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):
def on_event(self, event):
# event could be data if this is the return from external library
if type(event) in [list, int]:
self.add_arg(event)
else:
if len(self._args) < 4:
if len(self._args) < 5:
self.add_arg(None)
super().on_event(event)
@@ -116,18 +132,20 @@ class SkeModal(ClickMessage):
page_num = self.get_arg(0, int)
search_term = self.get_arg(1, str)
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)
next_message = msg(SkeModal, page_num, search_term, ske_index)
next_message = msg(SkeModal, page_num, search_term, ske_index, ske_pos_query)
# could be none if empty
data = self.get_arg(3)
data = self.get_arg(4)
if data is None:
params = {"additional_refs": "s.id,p.id",
"page_num": page_num,
"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")
if gdex:
@@ -136,15 +154,36 @@ class SkeModal(ClickMessage):
return
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)
search_term = search_term_old
elif type(data) is list:
window.console.log(data)
# check if gf2 examples are loaded or not
if not data[0].gf2_check and type(data[0]) is SkeExample:
# 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)
match_gf2_examples(data, page_num, search_term, ske_index, ske_pos_query)
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(
search_term, data, page_num, model.entry.senses, model.ske.request_kinds))
@@ -155,7 +194,7 @@ class SkeModal(ClickMessage):
class SkeModalGf2Update(SkeModal):
def on_event(self, event):
response_data = window.JSON.parse(event.target.response)
data = self.get_arg(3)
data = self.get_arg(4)
data_dict = {}
for example in data:
@@ -191,6 +230,7 @@ class SearchInSkeModal(SkeModal):
self.add_arg(int(document.getElementById("ske-page-num").value))
self.add_arg(document.getElementById("ske-search").value)
self.add_arg(document.getElementById("ske-select").selectedIndex)
self.add_arg(document.getElementById("ske-pos-query").value)
super().on_event(event)
@@ -238,7 +278,7 @@ class SkeInsert(DataChgClickMessage):
lex_mid = ComponentLexeme()
lex_mid.text = example["mid"]
lex_mid.role = "collocation"
lex_mid.role = "headword"
lex_right = ComponentLexeme()
lex_right.text = example["right"]
@@ -257,17 +297,45 @@ class SkeInsert(DataChgClickMessage):
new_collocation.inner.other_attributes["frequency"] = example.frequency
new_collocation.inner.type = "collocation"
lex_left = ComponentLexeme()
lex_left.text = ""
lex_left.role = None
lex_mid = ComponentLexeme()
lex_mid.text = example.word
lex_mid.role = "collocation"
lex_right = ComponentLexeme()
lex_right.text = ""
lex_right.role = None
new_collocation.components.extend([lex_left, lex_mid, lex_right])
headword = document.getElementById("ske-search").value
lexemes = []
structure_name = example.structure_name.split("-")
gramrel = example.gramrel.split("_")
structure = example.structure.split(" ")
structure.append("") # Bad fix: we have to add something for structure l-gg-ggn
for i in range(len(structure_name)):
lex = ComponentLexeme()
structure[i] = structure[i].replace("Inf-", "")
# take care of negations "ne"
if "Neg-" in structure[i]:
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

View File

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

View File

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

View File

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

View File

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

View File

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

21
src/model/explanation.py Normal file
View File

@@ -0,0 +1,21 @@
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

@@ -11,41 +11,45 @@ from view.utils import clean_label
class Sense(Data):
def __init__(self):
self.original_idx = -1
self.definition = {}
self.id = None
self.definitions = []
self.labels = []
self.translations = []
self.examples = []
def import_xml(self, sense_xml, idx):
self.original_idx = idx
for definition in sense_xml.querySelectorAll("definitionList definition"):
key = definition.getAttribute("type")
self.definition[key] = definition.textContent
self.id = sense_xml.getAttribute("id") if sense_xml.hasAttribute("id") else None
self.definitions = [{"value": v.textContent, "type": v.getAttribute("type")} for v in sense_xml.querySelectorAll("definitionList definition")]
self.labels = import_label_list("sense > labelList label", sense_xml)
self.translations = from_container_list(
sense_xml.querySelectorAll("translationContainerList translationContainer"))
sense_xml.querySelectorAll('sense > translationContainerList translationContainer'))
for example_xml in sense_xml.querySelectorAll("exampleContainerList exampleContainer"):
example = Example()
example.import_xml(example_xml)
self.examples.append(example)
def merge_labels(self):
return ", ".join(val for _, val in self.labels)
def view(self, model, sense_num):
examples = [example.view(model, self) for example in self.examples]
definition = ""
for x in self.definitions:
if x["type"] == "indicator":
definition = x.value
break
result = h("div.elm-div", {}, [
h("div.sense-num", {"on": {"click": M.msg(M.ShowSenseMenu, self)}}, str(sense_num + 1)),
h("div.sense", {}, [
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-definition", { "on": { "click": M.msg(M.ShowSenseDefinitionEdit, self) }}, self.definition["indicator"]),
h("span.sense-label", {}, clean_label(slabel)) for _, slabel in self.labels ]),
h("span.sense-definition", { "on": { "click": M.msg(M.ShowSenseDefinitionEdit, self) }}, definition),
h("div", {}, View.view_translations(self.translations, self, model)),
h("div", {}, examples)])])
return result

View File

@@ -8,7 +8,8 @@ TAGS = {
"latinsko": [],
"razmerje": ["približek", "sinonim", "antonim"],
"semantično": [],
"English-full": []
"Polno angleško": [],
"Blagovna znamka": []
}
SLO2ENG_TAGS = {
@@ -22,7 +23,8 @@ SLO2ENG_TAGS = {
"latinsko": "latin",
"razmerje": "relation",
"semantično": "semantic",
"English-full": "Polno angleško"
"Polno angleško": "English-full",
"Blagovna znamka": "trademark"
}
ENG2SLO_TAGS = { value: key for key, value in SLO2ENG_TAGS.items() }

View File

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

View File

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

View File

@@ -5,37 +5,37 @@ from browser import document
def modal_template(content, title, msg, delete_msg=None):
reset = message.msg(message.ModalNotOkClose)
footer = []
if msg is not None:
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}}, "Prekliči"))
if delete_msg is not None:
footer.append(h("label.button.warning.modal-delete", {"on": {"click": message.msg(*delete_msg)}}, "🗑"))
return [
h("header", {}, [
h("h3", {}, title),
h("label.close", {"on": {"click": reset}}, "×")]),
h("section.content", {}, content ),
h("footer", {}, footer)]
def _question(question, current_value, input_element):
props = {"value": current_value}
if input_element == "input":
props["type"] = "text"
return [
h("span", {}, question),
h("label", {}, [
h("{}#modal-question".format(input_element), {"props": props}, "")])]
def big_question(question, current_value):
return _question(question, current_value, "textarea")
def question(question, current_value):
return _question(question, current_value, "input")
@@ -47,28 +47,98 @@ def generic_list_editor(title, element_list_getter):
content.append(h("button", {"on": {"click": message.msg(message.AddToGenericList, element_list_getter)}}, "+"))
return content
def generic_key_value_editor(title, element_list_getter, key, value = "value"):
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, element in enumerate(element_list_getter()):
keys = []
values = []
keys.append(h("label", {"attrs": {"for": i}}, key.capitalize() + ":"))
keys.append(h("input." + key + "-input", {"props": {"type": "text", "value": element[key], "id": i}}, ""))
values.append(h("label", {"attrs": {"for": i + "-value"}}, "Value:"))
values.append(
h("input.value-input", {"props": {"type": "text", "value": element[value], "id": i + "-value"}}, ""))
content.append(split_line2(keys, values))
content.append(h("button", {"on": {"click": message.msg(message.AddToGenericList, element_list_getter)}}, "+"))
return content
def sense_definitions_editor(type_value, explanation_value):
type_props = {"value": type_value, "type": "text"}
explanation_props = {"value": explanation_value, "type": "text"}
return [
h("span", {}, "Indikator:"),
h("label", {}, [h("input#indicator-input", {"props": type_props}, "")]),
h("span", {}, "Razlaga:"),
h("label", {}, [h("input#explanation-input", {"props": explanation_props}, "")])
]
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 split_line3(left, center, right, is_llr=True):
cls = "flex.three{}".format(".label-list-row" if is_llr else "")
return h("div.{}".format(cls), {}, [
h("span.third", {}, left), h("span.third", {}, center), h("span.third", {}, right)])
def dropdown_right(label_type, label):
left = h("span.label-type", {}, label_type)
options = [h("option", {}, [])]
for value in TAGS[label_type]:
options.append(h("option", {"props": {"selected": label == value}}, value))
center = h("select.label-value", {}, options)
right_value = label if label not in TAGS[label_type] else ""
right = h("input.label-value-other",
{"props": {"type": "text", "value": right_value, "placeholder": "drugo"}},
right_value = "blagovna znamka" if label_type == 'Blagovna znamka' else right_value
right = h("input.label-value-other",
{"props": {"type": "text", "value": right_value, "placeholder": "drugo"}},
[])
return split_line3(left, center, right)
content = []
kontrastivno = False
for key, value in current_labels:
@@ -76,27 +146,27 @@ def label_list_editor(current_labels, add_label_message_class):
if value == "kontrastivno":
kontrastivno = True
continue
content.append(dropdown_right(key, value))
# add a way to get new element to add to tag list
def get_new_label_type():
select = document.getElementById("new-tag-select")
return (select.options[select.selectedIndex].text, "")
add_label_message_class.append(get_new_label_type)
content.append(split_line3(
h("", {}, []),
h("label", {}, [
h("input#kontrastivno-input", {"props": {"type": "checkbox", "checked": kontrastivno}}, []),
h("span.checkable", {}, "kontrastivno")]),
h("", {}, [])))
left = h("span", {}, "Add more!")
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)}}, "+")
content.append(split_line3(left, center, right, False))
content.append(h("hr", {}, []))
return content

View File

@@ -2,6 +2,11 @@ from lib.snabbdom import h
import message
from view.modal_templates import *
from view.utils import show_toggle_cluster_buttons
from export import export_to_xml, export_example_to_entry_xml
from update import update
from model.entry import Entry
import lib.screenful as screenful
from model.model import Model
import model
@@ -9,53 +14,52 @@ def edit_translation(translation, parent, cluster_idx, num_clusters, cls):
def split_line2(left, right):
return h("div.flex.two", {}, [
h("span.third.span-left-of-input", {}, left), h("span.two-third", {}, right)])
content = []
if type(parent) is model.Example:
content.extend([
h("span.translation-original-title", {}, "Primer: "),
h("span.translation-original", {}, parent.simple_view()),
h("hr", {}, None)])
# first line: transalation itself
content.extend([
split_line2("Prevedek:",
h("textarea#etv", {"props": {"value": translation.translation}}, "")),
split_line2("Razlaga:",
h("textarea#ete", {"props": {"value": translation.explanation}}, ""))])
split_line2("Prevedek:", h("textarea#etv", {"props": {"value": translation.translation}}, ""))])
content.extend(explanation_editor("Razlage:", lambda: translation.explanationList))
# cluster number
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(h("h4", {}, "Tags"))
content.extend(label_list_editor(translation.copy().tags, [message.AddToLabelList, translation.copy().tags]))
return modal_template(content, "Translation", cls)
def edit_sense_label(sense):
content = label_list_editor(sense.copy().labels, [message.AddToLabelList, sense.copy().labels])
return modal_template(content, "Translation", (message.EditSenseLabel, sense))
def edit_example(example, sense):
example_original = example
example = example_original.copy()
def role_msg(idx, role):
return message.msg(message.ExampleRoleChange, example_original, idx, role)
divs = []
def list_of_right_buttons(idx, component):
result = [
h("span.example-component-button.example-component-headword",
h("span.example-component-button.example-component-headword",
{"on": {"click": role_msg(idx, "headword")}}, "H"),
h("span.example-component-button.example-component-collocate",
{"on": {"click": role_msg(idx, "collocate")}}, "C"),
h("span.example-component-button.example-component-other",
{"on": {"click": role_msg(idx, "other")}}, "O")]
if example.is_multiword():
additional_class = ".example-component-no-space" if component.no_space else ""
click_message = message.msg(message.ExampleComponentSpace, example_original, idx)
@@ -64,32 +68,36 @@ def edit_example(example, sense):
else:
result.append(h("span.example-component-button.example-component-none",
{"on": {"click": role_msg(idx, "none")}}, "N"))
result.extend([
h("span.example-component-button",
{"on": {"click": message.msg(message.ExampleComponentAdd, example_original, idx)}}, "+"),
h("span.example-component-button",
{"on": {"click": message.msg(message.ExampleComponentRemove, example_original, idx)}}, "-")])
if "-" not in example.inner.other_attributes["structureName"]:
result.extend([
h("span.example-component-button",
{"on": {"click": message.msg(message.ExampleComponentAdd, example_original, idx)}}, "+"),
h("span.example-component-button",
{"on": {"click": message.msg(message.ExampleComponentRemove, example_original, idx)}}, "-")])
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):
role_txt = component.role if component.role is not None else "none"
color_class = ".example-component-" + role_txt
left = [h("span" + color_class, {}, role_txt)]
if component.role is None:
middle = [h("textarea.example-component-text", {"props": {"value": component.text}}, "")]
else:
middle = [h("input.example-component-text", {"props": {"type": "text", "value": component.text}}, "")]
divs.append(h("div.flex.five.example-component", {}, [
h("div.one-fifth", {}, left),
h("div.three-fifth", {}, middle),
h("div.one-fifth", {}, left),
h("div.three-fifth", {}, middle),
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))
@@ -99,6 +107,11 @@ def edit_variants(entry):
return modal_template(content, "Add or remove variants", (message.EditVariants,), (message.DeleteVariants,))
def edit_homonymy(entry):
hget = lambda: entry.copy().homonymy
content = generic_key_value_editor("Homonymy", hget, "name")
return modal_template(content, "Add or remove homonymy features", (message.EditHomonymy,), (message.DeleteHomonymy,))
def edit_related_entries(entry):
reget = lambda: entry.copy().related_entries
content = generic_list_editor("Related entries", reget)
@@ -111,43 +124,92 @@ def edit_entry_labels(entry):
def edit_sense_definition(sense):
return modal_template(question("Edit sense definition", sense.definition["indicator"]), "Sense definition", (message.EditSenseDefinition, sense))
indicator = ""
explanation = ""
for x in sense.copy().definitions:
if indicator == "" and x["type"] == "indicator":
indicator = x.value
if explanation is not "":
break
if explanation == "" and x["type"] == "explanation":
explanation = x.value
if indicator is not "":
break
content = sense_definitions_editor(indicator, explanation)
return modal_template(content, "Definicije pomena", (message.EditSenseDefinition, sense))
def edit_comment(comment):
return modal_template(big_question("Edit comment", comment), "Comment", (message.EditComment,), (message.DeleteComment,))
def do_chosen_examples(example_list, entry):
def do_chosen_examples(example_list, model, multiword_example):
if multiword_example is False:
return move_examples_to_sense(example_list, model.entry)
else:
return modal_template([
h("button.shyButton", {"on": {"click": (lambda: move_to_view(example_list, model))}}, "Premakni v pomen"),
h("button.shyButton", {"on": {"click": (lambda: export_to_new_entry(multiword_example, example_list))}},
"Izvozi v novo geslo")], "Izberite željeno akcijo", None)
def move_to_view(example_list, model):
model.modal_reset()
model.modal_set(lambda: move_examples_to_sense(example_list, model.entry))
update.view.view(model, True)
def export_to_new_entry(multiword_example, example_list):
other_examples = []
for example in example_list:
if example.is_multiword() is False:
other_examples.append(example)
entry_xml = export_example_to_entry_xml(multiword_example, other_examples if len(example_list) > 0 else None)
new_entry = Entry()
new_entry.import_xml(entry_xml)
new_model = Model()
new_model.entry = new_entry
screenful.screenful().Editor['new'](None, export_to_xml(new_model))
def move_examples_to_sense(example_list, entry):
example_senses = []
for idx, sense in enumerate(entry.senses):
for ex in sense.examples:
if ex in example_list:
example_senses.append(idx)
break
sense_of_first_example = example_senses[0]
options = [h("p", {}, "Choose sense for examples")]
for idx, sense in enumerate(entry.senses):
text = "{}: {}".format(idx + 1, sense.definition["indicator"])
definition = sense.definitions[0].value
for x in sense.definitions:
if x["type"] == "indicator":
definition = x.value
break
text = "{}: {}".format(idx + 1, definition)
id_ = "choose-example-{}".format(idx)
props = {"type": "radio", "name": "choose-example"}
if idx == sense_of_first_example:
if idx == sense_of_first_example:
props["checked"] = True
options.append(h("input#{}.checkable-input".format(id_), {"props": props}, []))
options.append(h("label.checkable", {"attrs": {"for": id_}}, text))
options.append(h("br", {}, []))
return modal_template(options, "Examples picker", (message.DoChosenExamples, example_list))
return modal_template(options, "Examples picker", (message.MoveExamplesToSense, example_list))
def ske_list(search_term, data, page_num, senses, ske_kinds):
list_contents = []
ske_list_hidden = False
if data is None:
list_contents.append(h("div.loadingspinner", {}, ""))
elif type(data) is list:
@@ -159,7 +221,12 @@ def ske_list(search_term, data, page_num, senses, ske_kinds):
ske_list_hidden = True
else:
list_contents.append(h("span.error", {}, "Something went wrong in SKE: {}".format(data)))
definitions = []
for sense in senses:
for x in sense.definitions:
if x["type"] == "indicator":
definitions.append(x.value)
break
contents = [
h("div.flex.four", {}, [
h("select#ske-select.fourth", {}, [
@@ -168,18 +235,22 @@ def ske_list(search_term, data, page_num, senses, ske_kinds):
h("input#ske-search", {"props": {"value": search_term, "type": "text"}}, "")]),
h("label.fourth.ske-mid-input", {}, [
h("input#ske-page-num", {"attrs": {
"value": str(page_num),
"value": str(page_num),
"type": "number",
"min": 1,
"step": 1}}, "")]),
h("span.fourth.button.ske-right-button",
h("label.fourth.ske-mid-input", {}, [
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")]),
h("div.ske-list",
{"style": {"visibility": "hidden" if ske_list_hidden else "visible"}},
h("div.ske-list",
{"style": {"visibility": "hidden" if ske_list_hidden else "visible"}},
list_contents),
h("div.flex.three", {}, [
h("span.third", {}, "Vstavi v:"),
h("select#ske-sense-select.two-third", {}, [ h("option", {}, "{} {}".format(
idx + 1, sense.definition["indicator"])) for idx, sense in enumerate(senses)])])]
idx + 1, definition)) for idx, definition in enumerate(definitions)])])]
return modal_template(contents, "SKE", (message.SkeInsert, data))

View File

@@ -58,7 +58,7 @@ class View:
def view_ske_button(model):
return h(
"span#ske-button.button.toggle",
{ "on": {"click": msg(ShowSkeModal, 1, model.entry.headword, 0)} },
{ "on": {"click": msg(ShowSkeModal, 1, model.entry.headword, 0, "simple")} },
h("svg#ske-img", {
"attrs": {
"xmlns": "http://www.w3.org/2000/svg",
@@ -98,11 +98,16 @@ class View:
elif type(menu_target) is Example:
example = menu_target
sense = example_sense(example, entry)
return h("span.popup-menu", { "style": style }, [
dom_children = [
h("button.shyButton", { "on": {"click": msg(ShowExampleEdit, example, sense)}}, ""),
h("button.shyButton", { "on": {"click": msg(ExampleMoveUp, example)}}, ""),
h("button.shyButton", { "on": {"click": msg(ExampleMoveDown, example)}}, ""),
h("button.shyButton", { "on": {"click": msg(ExampleBin, example)}}, "🗑")])
h("button.shyButton", { "on": {"click": msg(ExampleBin, example)}}, "🗑")]
if example.is_multiword():
dom_children.insert(1, h("button.shyButton", { "on": {"click": msg(ExampleAsNewEntry, example, sense)}}, "Izvozi v novo geslo"))
return h("span.popup-menu", { "style": style }, dom_children)
else:
console.log("Should not be heree!!")