refactoring view, now combining modals and view into one module.

Also common modal components can now be nicely separated and reused
This commit is contained in:
2019-11-16 14:41:29 +01:00
parent 5301b2a5fa
commit d8291a15cf
7 changed files with 37 additions and 30 deletions

2
src/view/__init__.py Normal file
View File

@@ -0,0 +1,2 @@
import view.modals
from view.view import View

View File

@@ -0,0 +1,30 @@
import message
from lib.snabbdom import h
def modal_template(content, title, msg, prop):
reset = message.msg(message.ModalNotOkClose)
return [
h("header", {}, [
h("h3", {}, title),
h("label.close", {"on": {"click": reset}}, "×")]),
h("section.content", {}, content ),
h("footer", {}, [
h("a.button", {"on": {"click": message.msg(msg, prop)}}, "OK"),
h("label.button.dangerous", {"on": {"click": reset}}, "Cancel")])]
def one_question_modal(title, msg, question, current_value, prop):
content = [
h("span", {}, question),
h("label", {}, [
h("input#modal-input", {"props": {"type": "text", "value": current_value}}, "")])]
return modal_template(content, title, msg, prop)
def list_adder(title, element_list_getter, add_click_message):
content = [h("span", {}, title)]
for slabel in element_list_getter():
content.append(h("label", {}, [
h("input.list-adder-input", {"props": {"type": "text", "value": slabel}}, "")]))
content.append(h("button", {"on": {"click": add_click_message}}, "+"))
return content

83
src/view/modals.py Normal file
View File

@@ -0,0 +1,83 @@
from lib.snabbdom import h
import message
from model.translation import TAGS
from view.modal_templates import *
def edit_translation(translation, cluster_idx, num_clusters, cls, prop):
def split_line2(left, right):
return h("div.flex.two", {}, [
h("span.third.span-left-of-input", {}, left), h("span.two-third", {}, right)])
def split_line3(left, center, right):
return h("div.flex.three", {}, [
h("span.third.span-left-of-input", {}, left), h("span.third", {}, center), h("span.third", {}, right)])
def dropdown_right(tag_name):
left = tag_name + ":"
values = TAGS[tag_name]
selected_value = translation.tags[tag_name] if tag_name in translation.tags else None
options = [h("option", {}, [])]
for value in values:
options.append(h("option", {"props": {"selected": selected_value == value}}, value))
center = h("select#{}-s".format(tag_name), {}, options)
right_value = selected_value if selected_value not in values and selected_value is not None else ""
right = h("input#{}-o".format(tag_name),
{"props": {"type": "text", "value": right_value, "placeholder": "drugo"}},
[])
return split_line3(left, center, right)
# first line: transalation itself
content = [split_line2("Prevedek:",
h("input#etv", {"props": {"type": "text", "value": translation.translation}}, "")),
split_line2("Razlaga:",
h("input#ete", {"props": {"type": "text", "value": translation.explanation}}, ""))]
# 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)))
# tags
content.append(h("h4", {}, "Tags"))
for tag in TAGS.keys():
content.append(dropdown_right(tag))
return modal_template(content, "Translation", cls, prop)
def edit_sense_label(sense):
content = [h("span", {}, "Edit sense labels")]
for slabel in sense.copy().labels:
content.append(h("label", {}, [
h("input.sense-edit-input", {"props": {"type": "text", "value": slabel}}, "")]))
content.append(h("button", {"on": {"click": message.msg(message.AddSenseLabel, sense)}}, "+"))
return modal_template(content, "Sense", message.EditSenseLabel, sense)
def edit_example_translation(example):
etl_getter = lambda: example.copy().translations
content = list_adder("Edit example translations", etl_getter, message.msg(message.AddExampleTranslation, example))
return modal_template(content, "Example Translations", message.EditExampleTranslation, example)
def add_sense(sense):
return one_question_modal("Add sense", message.AddSense, "Add sense with a label", "", sense)
def edit_sense_definition(sense):
return one_question_modal("Sense definition", message.EditSenseDefinition, "Edit sense definition", sense.definition, sense)
def edit_comment(comment):
return one_question_modal("Comment", message.EditComment, "Edit comment", comment, None)
def edit_example(example):
return one_question_modal("Example", message.EditExample, "Edit example", example.example, example)

117
src/view/view.py Normal file
View File

@@ -0,0 +1,117 @@
from lib.snabbdom import h, patch
from message import *
import random
from export import export_to_xml
class View:
def __init__(self, container):
self.vdom = h('div', {}, "Loading...")
self.model = None
patch(container, self.vdom)
def view(self, model):
self.model = model
new_vdom = self._view()
patch(self.vdom, new_vdom)
self.vdom = new_vdom
def _view(self):
return h("div", {"on": { "click": msg(Reset) }}, [
View.view_entry(self.model.entry),
# h("button.blk", {"on": { "click": lambda _: console.log(export_to_xml(self.model)) } }, "XML2Console"),
View.view_menu(self.model.menu_location, self.model.menu_shown, self.model.translation),
View.view_modal(self.model.modal_shown, self.model.modal)])
@staticmethod
def view_entry(entry):
view_sense_list = [View.view_sense(sense, idx) for idx, sense in enumerate(entry.senses)]
return h("div#entry", {}, [
h("div#entry-status", {}, entry.status),
h("div#entry-header", {}, [
h("span#headword", {}, entry.headword),
h("span#grammar", {}, entry.grammar),
h("button#comment.warning", {"on": {"click": msg(ShowCommentEdit)}}, entry.comment)]),
h("div#sense-container", {}, view_sense_list),
h("button.add-button", {"on": {"click": msg(ShowSenseAdd)}}, "+")])
@staticmethod
def view_sense(sense, senseNum):
examples = [View.view_example(example) for example in sense.examples]
return h("div.elm-div", {}, [
h("div.sense-num", {}, str(senseNum + 1)),
h("div.sense", {}, [
h("span.sense-label-list", { "on": { "click": msg(ShowSenseLabelEdit, sense) }}, [
h("span.sense-label", {}, slabel) for slabel in sense.labels ]),
h("span.sense-definition", { "on": { "click": msg(ShowSenseDefinitionEdit, sense) }}, sense.definition),
h("div", {}, View.view_translations(sense.translations, sense)),
h("div", {}, examples)])])
@staticmethod
def view_example(example):
return h("div.example", {}, [
h("div.example-dot", {}, ""),
h("div.example-rest", {}, [
h("span.example-text", {"on": {"click": msg(ShowExampleEdit, example)} }, example.example),
h("div.example-translation-list", { "on": {"click": msg(ShowExampleTranslationEdit, example)} }, [
h("div.example-translation", {}, [
h("span.example-arrow", {}, ""),
h("span", {}, t)])
for t in example.translations])])])
@staticmethod
def view_translations(translations, sense):
result = []
for cluster in translations:
result.append(h("div.translation-div-cluster", {}, [View.view_one_translation(t) for t in cluster]))
result.append(h("button.add-button", {"on": {"click": msg(ShowAddTranslation, sense)}}, "+"))
return result
@staticmethod
def view_one_translation(translation):
elements = []
if translation.tags:
tags = h("div.translation-tags", {}, [
h("span", {"attr": {"title": key}}, value)
for key, value in translation.tags.items()])
elements.append(tags)
elements.append(h("span.translation-text", {}, translation.translation))
if translation.source:
elements.append(h("span.translation-source", {}, translation.source))
explanation_class = ".translation-explanation" if translation.translation else ""
elements.append(h("span{}".format(explanation_class), {}, translation.explanation))
return h("div.translation-div", {"on": {"click": msg(ShowMenu, translation) }}, elements)
@staticmethod
def view_menu(location, menu_shown, translation):
style = {
"left": "{}px".format(location[0]),
"top": "{}px".format(location[1])
}
if menu_shown:
style["opacity"] = "1"
style["visibility"] = "visible"
return h("span.popup-menu", { "style": style }, [
h("button.shyButton", { "on": {"click": msg(ShowEditTranslation, translation)}}, ""),
h("button.shyButton", { "on": {"click": msg(MoveRight, translation)}}, ""),
h("button.shyButton", { "on": {"click": msg(MoveLeft, translation)}}, ""),
h("button.shyButton", { "on": {"click": msg(BinTranslation, translation)}}, "🗑")])
@staticmethod
def view_modal(modal_shown, modal):
return h("div.modal", {}, [
h("input", { "props": {"type": "checkbox", "checked": modal_shown} }, ""),
h("label.overlay", {}, ""),
h("article", {"on": { "click": msg(NoReset) }}, modal())])