Viewing example clusters in main view
This commit is contained in:
parent
dc03f84e8b
commit
cab655497b
|
@ -12,6 +12,28 @@
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cluster-list-button {
|
||||||
|
padding: 0.2em;
|
||||||
|
margin-left: .2em;
|
||||||
|
background-color: #ddd;
|
||||||
|
color: @black;
|
||||||
|
background-color: @silver;
|
||||||
|
height: 1em;
|
||||||
|
width: 1em;
|
||||||
|
vertical-align: middle;
|
||||||
|
line-height: 0;
|
||||||
|
font-family: "Lucida Console", Monaco, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cluster-button-checked {
|
||||||
|
color: @silver;
|
||||||
|
background-color: @black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-clusters {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
._hoverable {
|
._hoverable {
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: @silver;
|
background-color: @silver;
|
||||||
|
@ -208,6 +230,7 @@
|
||||||
|
|
||||||
.example-rest {
|
.example-rest {
|
||||||
border: 1px transparent solid;
|
border: 1px transparent solid;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.example-chosen {
|
.example-chosen {
|
||||||
|
|
|
@ -3,30 +3,7 @@ from model.translation import from_container_list
|
||||||
|
|
||||||
|
|
||||||
class Example(Editable):
|
class Example(Editable):
|
||||||
@staticmethod
|
def __init__(self, example_xml, cluster_info):
|
||||||
def add_clusters(entry):
|
|
||||||
nocluster_examples = []
|
|
||||||
taken_clusters = []
|
|
||||||
|
|
||||||
# gahter all taken cluster numbers and all examples without clusters
|
|
||||||
for sense in entry.senses:
|
|
||||||
for example in sense.examples:
|
|
||||||
cluster = example.get_cluster()
|
|
||||||
if cluster == -1:
|
|
||||||
nocluster_examples.append(example)
|
|
||||||
elif cluster is not None:
|
|
||||||
taken_clusters.append(cluster)
|
|
||||||
|
|
||||||
cnum = 1
|
|
||||||
for example in nocluster_examples:
|
|
||||||
while cnum in taken_clusters:
|
|
||||||
cnum += 1
|
|
||||||
taken_clusters.append(cnum)
|
|
||||||
|
|
||||||
example.set_cluster(cnum)
|
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, example_xml):
|
|
||||||
self.translations = from_container_list(example_xml.querySelectorAll("translationContainer"))
|
self.translations = from_container_list(example_xml.querySelectorAll("translationContainer"))
|
||||||
|
|
||||||
inner_xml = example_xml.querySelector("corpusExample")
|
inner_xml = example_xml.querySelector("corpusExample")
|
||||||
|
@ -34,7 +11,7 @@ class Example(Editable):
|
||||||
self.inner = CorpusExample(inner_xml)
|
self.inner = CorpusExample(inner_xml)
|
||||||
else:
|
else:
|
||||||
inner_xml = example_xml.querySelector("multiwordExample")
|
inner_xml = example_xml.querySelector("multiwordExample")
|
||||||
self.inner = MultiwordExample(inner_xml)
|
self.inner = MultiwordExample(inner_xml, cluster_info)
|
||||||
|
|
||||||
all_components = [ComponentLexeme(el) for el in inner_xml.childNodes]
|
all_components = [ComponentLexeme(el) for el in inner_xml.childNodes]
|
||||||
self.components = [comp for comp in all_components if comp.isValid()]
|
self.components = [comp for comp in all_components if comp.isValid()]
|
||||||
|
@ -57,14 +34,11 @@ class Example(Editable):
|
||||||
def get_cluster(self):
|
def get_cluster(self):
|
||||||
return self.inner.get_cluster()
|
return self.inner.get_cluster()
|
||||||
|
|
||||||
def get_valid_cluster(self):
|
|
||||||
return self.inner.get_valid_cluster()
|
|
||||||
|
|
||||||
def set_cluster(self, cluster):
|
def set_cluster(self, cluster):
|
||||||
self.inner.cluster = cluster
|
self.inner.cluster = cluster
|
||||||
|
|
||||||
def is_collocation(self):
|
def is_collocation(self):
|
||||||
return type(self.inner) is CorpusExample
|
return self.get_view_type() == 2
|
||||||
|
|
||||||
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
|
||||||
|
@ -92,28 +66,40 @@ class CorpusExample:
|
||||||
def get_cluster(self):
|
def get_cluster(self):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_valid_cluster(self):
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
class MultiwordExample:
|
class MultiwordExample:
|
||||||
def __init__(self, example_xml):
|
def __init__(self, example_xml, cluster_info):
|
||||||
self.other_attributes = {}
|
self.other_attributes = {}
|
||||||
for oth_attr in ["lexical_unit_id", "structure_id", "structureName", "audio", "frequency", "logDice"]:
|
for oth_attr in ["lexical_unit_id", "structure_id", "structureName", "audio", "frequency", "logDice"]:
|
||||||
if example_xml.hasAttribute(oth_attr):
|
if example_xml.hasAttribute(oth_attr):
|
||||||
self.other_attributes[oth_attr] = example_xml.getAttribute(oth_attr)
|
self.other_attributes[oth_attr] = example_xml.getAttribute(oth_attr)
|
||||||
|
|
||||||
self.cluster_valid = False
|
self.cluster = self._determine_cluster_number(example_xml, cluster_info)
|
||||||
self.cluster = -1
|
|
||||||
if example_xml.hasAttribute("cluster"):
|
|
||||||
self.cluster_valid = True
|
|
||||||
self.cluster = int(example_xml.getAttribute("cluster"))
|
|
||||||
|
|
||||||
if example_xml.hasAttribute("type"):
|
if example_xml.hasAttribute("type"):
|
||||||
self.type = example_xml.getAttribute(oth_attr)
|
self.type = example_xml.getAttribute("type")
|
||||||
else:
|
else:
|
||||||
self.type = None
|
self.type = None
|
||||||
|
|
||||||
|
def _determine_cluster_number(self, example_xml, cluster_info):
|
||||||
|
# since cluster numbers can be fairly fragmented, this is defragmentation
|
||||||
|
# we do need to get info about sense examples to do this, that is why we have cluster_info
|
||||||
|
if cluster_info is None:
|
||||||
|
cluster_mappings, cluster_begin = {}, 0
|
||||||
|
else:
|
||||||
|
cluster_mappings, cluster_begin = cluster_info
|
||||||
|
|
||||||
|
|
||||||
|
if not example_xml.hasAttribute("cluster"):
|
||||||
|
cluster = len(cluster_mappings) + cluster_begin
|
||||||
|
cluster_mappings[cluster] = cluster
|
||||||
|
else:
|
||||||
|
cluster = int(example_xml.getAttribute("cluster"))
|
||||||
|
if cluster not in cluster_mappings:
|
||||||
|
cluster_mappings[cluster] = len(cluster_mappings) + cluster_begin
|
||||||
|
|
||||||
|
return cluster_mappings[cluster]
|
||||||
|
|
||||||
def export(self, doc):
|
def export(self, doc):
|
||||||
result = doc.createElement("multiwordExample")
|
result = doc.createElement("multiwordExample")
|
||||||
|
|
||||||
|
@ -131,9 +117,6 @@ class MultiwordExample:
|
||||||
def get_cluster(self):
|
def get_cluster(self):
|
||||||
return self.cluster
|
return self.cluster
|
||||||
|
|
||||||
def get_valid_cluster(self):
|
|
||||||
return self.cluster if self.cluster_valid else None
|
|
||||||
|
|
||||||
|
|
||||||
class ComponentLexeme(Editable):
|
class ComponentLexeme(Editable):
|
||||||
def __init__(self, xml):
|
def __init__(self, xml):
|
||||||
|
|
|
@ -26,9 +26,6 @@ class Model:
|
||||||
self.chosen_examples = []
|
self.chosen_examples = []
|
||||||
self.examples_shown = True
|
self.examples_shown = True
|
||||||
|
|
||||||
self.reset()
|
|
||||||
self.modal_reset()
|
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
# do both resets at once
|
# do both resets at once
|
||||||
self.pre_reset()
|
self.pre_reset()
|
||||||
|
@ -56,7 +53,5 @@ class Model:
|
||||||
parser = __new__(DOMParser())
|
parser = __new__(DOMParser())
|
||||||
xmlDoc = parser.parseFromString(xml_text, "text/xml")
|
xmlDoc = parser.parseFromString(xml_text, "text/xml")
|
||||||
self.entry = Entry(xmlDoc.querySelector("entry"))
|
self.entry = Entry(xmlDoc.querySelector("entry"))
|
||||||
|
self.reset()
|
||||||
# we need to fix the example clusters
|
|
||||||
Example.add_clusters(self.entry)
|
|
||||||
|
|
||||||
|
|
|
@ -4,19 +4,42 @@ from model.editable import Editable
|
||||||
from model.tags import import_label_list
|
from model.tags import import_label_list
|
||||||
|
|
||||||
|
|
||||||
|
cluster_min = 0
|
||||||
|
|
||||||
|
|
||||||
class Sense(Editable):
|
class Sense(Editable):
|
||||||
def __init__(self, sense_xml):
|
def __init__(self, sense_xml):
|
||||||
|
global cluster_min
|
||||||
|
|
||||||
self.definition = {}
|
self.definition = {}
|
||||||
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.examples = [Example(example_xml) for example_xml in
|
|
||||||
sense_xml.querySelectorAll("exampleContainerList exampleContainer")]
|
|
||||||
|
|
||||||
self.translations = from_container_list(
|
self.translations = from_container_list(
|
||||||
sense_xml.querySelectorAll("translationContainerList translationContainer"))
|
sense_xml.querySelectorAll("translationContainerList translationContainer"))
|
||||||
|
|
||||||
|
cluster_mappings = {}
|
||||||
|
cluster_info = (cluster_mappings, cluster_min)
|
||||||
|
|
||||||
|
self.examples = [Example(example_xml, cluster_info) for example_xml in
|
||||||
|
sense_xml.querySelectorAll("exampleContainerList exampleContainer")]
|
||||||
|
|
||||||
|
# set limit for example cluster
|
||||||
|
self.reserved_example = max(cluster_mappings.values()) + 1
|
||||||
|
cluster_min = self.reserved_example + 1
|
||||||
|
|
||||||
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 example_clusters(self):
|
||||||
|
result = set()
|
||||||
|
for ex in self.examples:
|
||||||
|
cluster = ex.get_cluster()
|
||||||
|
if cluster is not None:
|
||||||
|
result.add(cluster)
|
||||||
|
result.add(self.reserved_example)
|
||||||
|
|
||||||
|
return sorted(result)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from lib.snabbdom import h
|
from lib.snabbdom import h
|
||||||
import message
|
import message
|
||||||
from view.modal_templates import *
|
from view.modal_templates import *
|
||||||
|
from view.utils import show_toggle_cluster_buttons
|
||||||
|
|
||||||
|
|
||||||
def edit_translation(translation, cluster_idx, num_clusters, cls):
|
def edit_translation(translation, cluster_idx, num_clusters, cls):
|
||||||
|
@ -63,6 +64,13 @@ def edit_example(example):
|
||||||
h("div.three-fifth", {}, middle),
|
h("div.three-fifth", {}, middle),
|
||||||
h("div.one-fifth", {}, buttons_right(idx))]))
|
h("div.one-fifth", {}, buttons_right(idx))]))
|
||||||
|
|
||||||
|
cluster = example.get_cluster()
|
||||||
|
if cluster is not None:
|
||||||
|
divs.append(h("hr", {}, []))
|
||||||
|
divs.append(h("div.flex.five.example-component", {}, [
|
||||||
|
h("div.one-fifth", {}, "Cluster"),
|
||||||
|
h("div.four-fifth", {}, show_toggle_cluster_buttons(list(range(10))))]))
|
||||||
|
|
||||||
return modal_template(divs, "Edit Example", message.EditExampleText(example_original))
|
return modal_template(divs, "Edit Example", message.EditExampleText(example_original))
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,15 +100,24 @@ def edit_comment(comment):
|
||||||
|
|
||||||
|
|
||||||
def do_chosen_examples(example_list, entry):
|
def do_chosen_examples(example_list, entry):
|
||||||
# assert len(example_list) > 0
|
example_senses = []
|
||||||
|
|
||||||
sense_of_first_example = None
|
|
||||||
for idx, sense in enumerate(entry.senses):
|
for idx, sense in enumerate(entry.senses):
|
||||||
for ex in sense.examples:
|
for ex in sense.examples:
|
||||||
if ex == example_list[0]:
|
if ex in example_list:
|
||||||
sense_of_first_example = idx
|
example_senses.append(idx)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
sense_of_first_example = example_senses[0]
|
||||||
|
|
||||||
|
# determine if one can choose clusters
|
||||||
|
# this can happen ef every example from same sense and every example a collocation
|
||||||
|
can_choose_cluster = len(set(example_senses)) == 1
|
||||||
|
idx = 0
|
||||||
|
while can_choose_cluster and idx < len(example_list):
|
||||||
|
can_choose_cluster = example_list[idx].is_collocation()
|
||||||
|
idx += 1
|
||||||
|
console.log(can_choose_cluster)
|
||||||
|
|
||||||
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"])
|
||||||
|
|
|
@ -1,5 +1,19 @@
|
||||||
from export import export_to_xml
|
from export import export_to_xml
|
||||||
from browser import window
|
from browser import window
|
||||||
|
from lib.snabbdom import h
|
||||||
|
|
||||||
|
|
||||||
|
NUM2STR = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
def show_toggle_cluster_buttons(sense, example):
|
||||||
|
result = []
|
||||||
|
for opt in sense.example_clusters():
|
||||||
|
tag = "input.cluster-list-button"
|
||||||
|
if opt == example.get_cluster():
|
||||||
|
tag += ".cluster-button-checked"
|
||||||
|
|
||||||
|
result.append(h(tag, {"attrs": {"value": NUM2STR[opt], "type": "button"}}, []))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def clean_label(label):
|
def clean_label(label):
|
||||||
|
|
|
@ -98,7 +98,7 @@ class View:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def view_sense(sense, senseNum, model):
|
def view_sense(sense, senseNum, model):
|
||||||
examples = [View.view_example(example, model) for example in sense.examples]
|
examples = [View.view_example(example, sense, model) for example in sense.examples]
|
||||||
|
|
||||||
result = h("div.elm-div", {}, [
|
result = h("div.elm-div", {}, [
|
||||||
h("div.sense-num", {"on": {"click": msg(ShowSenseMenu(sense))}}, str(senseNum + 1)),
|
h("div.sense-num", {"on": {"click": msg(ShowSenseMenu(sense))}}, str(senseNum + 1)),
|
||||||
|
@ -111,7 +111,7 @@ class View:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def view_example(example, model):
|
def view_example(example, sense, model):
|
||||||
example_tag = "div.example-rest"
|
example_tag = "div.example-rest"
|
||||||
if example in model.chosen_examples:
|
if example in model.chosen_examples:
|
||||||
example_tag += ".example-chosen"
|
example_tag += ".example-chosen"
|
||||||
|
@ -140,6 +140,7 @@ class View:
|
||||||
h("div.example-dot", dot_attr, "▣"),
|
h("div.example-dot", dot_attr, "▣"),
|
||||||
h(example_tag, {}, [
|
h(example_tag, {}, [
|
||||||
h("span.example-text", {"on": {"click": msg(ShowExampleMenu(example))} }, example_content),
|
h("span.example-text", {"on": {"click": msg(ShowExampleMenu(example))} }, example_content),
|
||||||
|
h("div.example-clusters", {}, show_toggle_cluster_buttons(sense, example)),
|
||||||
h("div.example-translation-list", {}, [
|
h("div.example-translation-list", {}, [
|
||||||
h("div.example-translation", {}, View.view_translations(example.translations, example, model))])])])
|
h("div.example-translation", {}, View.view_translations(example.translations, example, model))])])])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user