Skip to content

Commit

Permalink
Merge pull request #95 from amir-zeldes/develop
Browse files Browse the repository at this point in the history
V4.0.0
amir-zeldes authored Jul 15, 2024
2 parents 81fe10c + e0dce4b commit 5341149
Showing 28 changed files with 898 additions and 185 deletions.
2 changes: 1 addition & 1 deletion _version.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

__version__ = "3.0.3"
__version__ = "4.0.0"
__author__ = "Amir Zeldes, Luke Gessler"
__copyright__ = "Copyright 2015-2021, Amir Zeldes"
__license__ = "MIT License"
26 changes: 26 additions & 0 deletions admin.py
Original file line number Diff line number Diff line change
@@ -136,6 +136,7 @@ def is_email(email):
<input type="hidden" name="switch_logging" id="switch_logging" value=""/>
<input type="hidden" name="switch_span_buttons" id="switch_span_buttons" value=""/>
<input type="hidden" name="switch_multinuc_buttons" id="switch_multinuc_buttons" value=""/>
<input type="hidden" name="switch_secedges" id="switch_secedges" value=""/>
<input type="hidden" name="update_schema" id="update_schema" value=""/>
<input type="hidden" name="imp_project" id="imp_project" value=""/>
<input type="hidden" name="import_file_type" id="import_file_type" value=""/>
@@ -719,6 +720,31 @@ def is_email(email):
cpout += '''<button onclick="admin('switch_span_buttons')">'''+ opposite_span +''' span buttons</button><br/><br/>'''
cpout += '''<button onclick="admin('switch_multinuc_buttons')">'''+ opposite_multinuc +''' multinuc buttons</button>'''

# spans/multinucs
cpout += '''<h2>Allow secondary edges</h2>
<p>Allow adding tree-breaking secondary edges using ctrl+drag.</p>'''

try:
secedge_state = get_setting("use_secedges")
except IndexError:
secedge_state="False"

if "switch_secedges" in theform:
if int(get_schema()) < 7:
update_schema()
if theform["switch_secedges"] == "switch_secedges":
if secedge_state == "True":
secedge_state = "False"
else:
secedge_state = "True"
save_setting("use_secedges",secedge_state)
if secedge_state == "True":
opposite_secedge = "Disable"
else:
opposite_secedge = "Enable"
cpout += '''<button onclick="admin('switch_secedges')">'''+ opposite_secedge +''' secondary edges</button><br/>'''


cpout += '''<h2>Update schema</h2>
<p>Update the schema without losing data between major schema upgrades.</p>'''

68 changes: 60 additions & 8 deletions css/rst.css
Original file line number Diff line number Diff line change
@@ -184,19 +184,44 @@ div.shield-of-justice {
}

.edu--clickable .tok:not(.tok--selected):hover {
background: rgba(255,255,0,0.3);
background-color: rgba(255,255,0,0.6);
}

.tok--highlighted {
background: rgba(255,255,0,0.3);
background-color: rgba(255,255,0,0.8) !important;
}
.tok--highlighted.signal-color {
background-color: rgba(var(--rgb), 0.8) !important;
}

.tok--highlighted-by-button {
background: rgba(255,255,0,0.2);
}
--rgb: 255,255,0;
background-color: rgba(var(--rgb),0.2);
}

.tok--highlighted-by-button.signal-type-1{--rgb: 255,0,0;background-color: rgba(var(--rgb),0.2);} /*red*/
.tok--highlighted-by-button.signal-type-2{--rgb: 247,231,51;background-color: rgba(var(--rgb),0.2);} /*yellow*/
.tok--highlighted-by-button.signal-type-3{--rgb: 251,183,52;background-color: rgba(var(--rgb),0.2);} /*orange*/
.tok--highlighted-by-button.signal-type-4{--rgb: 128,128,0;background-color: rgba(var(--rgb),0.2);} /*ochre*/
.tok--highlighted-by-button.signal-type-5{--rgb: 255,0,255;background-color: rgba(var(--rgb),0.2);} /*pink*/
.tok--highlighted-by-button.signal-type-6{--rgb: 0,0,255;background-color: rgba(var(--rgb),0.2);} /*blue*/
.tok--highlighted-by-button.signal-type-7{--rgb: 4,93,161;background-color: rgba(var(--rgb),0.2);} /*glas*/
.tok--highlighted-by-button.signal-type-8{--rgb: 0,255,0;background-color: rgba(var(--rgb),0.2);} /*green*/
.tok--highlighted-by-button.signal-type-9{--rgb: 0,255,255;background-color: rgba(var(--rgb),0.2);} /*cyan*/
.tok--highlighted-by-button.signal-type-10{--rgb: 105,3,117;background-color: rgba(var(--rgb),0.2);}/*violet*/
.tok--highlighted-by-button.signal-type-11{--rgb: 15,8,75;background-color: rgba(var(--rgb),0.2);} /* gray*/
.tok--highlighted-by-button.signal-type-12{--rgb: 199,214,109;background-color: rgba(var(--rgb),0.2);}
.tok--highlighted-by-button.signal-type-13{--rgb: 131,10,72;background-color: rgba(var(--rgb),0.2);}
.tok--highlighted-by-button.signal-type-14{--rgb: 174,132,126;background-color: rgba(var(--rgb),0.2);}
.tok--highlighted-by-button.signal-type-15{--rgb: 0,255,0;background-color: rgba(var(--rgb),0.2);}
.tok--highlighted-by-button.signal-type-16{--rgb: 255,255,0;background-color: rgba(var(--rgb),0.2);}
.tok--highlighted-by-button.signal-type-17{--rgb: 0,255,255;background-color: rgba(var(--rgb),0.2);}
.tok--highlighted-by-button.signal-type-18{--rgb: 255,0,255;background-color: rgba(var(--rgb),0.2);}
.tok--highlighted-by-button.signal-type-19{--rgb: 255,0,255;background-color: rgba(var(--rgb),0.2);}
.tok--highlighted-by-button.signal-type-20{--rgb: 255,0,255;background-color: rgba(var(--rgb),0.2);}

.edu--clickable .tok--selected {
background: rgba(255,255,0,0.7);
background-color: rgba(255,255,0,0.7);
}


@@ -341,7 +366,7 @@ select.rst_rel {
.seg_end:before{content:"\a0\a0"}
.seg_end:hover:before{content:"x"}

.tab{position: absolute;left: 0px; top:86px; background-color:white;height: 700px; width: 500px;padding-left:5px}
.tab{position: absolute;left: 0px; top:86px; background-color:white;height: 800px; width: 500px;padding-left:5px}
.tab_btn{width:82px;top:85px;position:absolute;z-index:2;border-width:1px;border-color: black black black black; border-style: solid; text-align:center; border-top-left-radius: 6px; border-top-right-radius: 6px; cursor: pointer; background-color: buttonface; border-bottom-color: black}
.tab_btn:after{content: "\a0"; width:8px; border-bottom-style: solid; border-bottom-width:1px;border-bottom-color: black; left: 82px;position:absolute;top:0px}
button:hover:enabled, .nav_button:hover:enabled{ color: red; background: #f5f5f5; }
@@ -542,6 +567,33 @@ input:checked + .slider:before {
height: 80%;
}

.ui-dialog { z-index: 1000 !important ;}
.ui-dialog { z-index: 10000 !important ;}

#quick_container{padding-top:5px}

.custom-menu {
display: none;
z-index: 10000;
position: absolute;
overflow: hidden;
border: 1px solid #CCC;
white-space: nowrap;
font-family: sans-serif;
background: #FFF;
color: #333;
border-radius: 5px;
padding: 0;
}

/* Each of the items in the list */
.custom-menu li {
padding: 8px 12px;
cursor: pointer;
list-style-type: none;
transition: all .3s ease;
user-select: none;
}

#quick_container{padding-top:5px}
.custom-menu li:hover {
background-color: #DEF;
}
9 changes: 7 additions & 2 deletions get_structure.py
Original file line number Diff line number Diff line change
@@ -23,16 +23,21 @@ def get_structure_main(**kwargs):
current_project = "quick"

rels = {}
nodes, signals = read_rst(rs3,rels,as_string=True)
nodes, signals, signal_type_dict = read_rst(rs3,rels,as_string=True)
secedges = []
for nid in nodes:
node = nodes[nid]
node.relkind = "rst"
if node.relname.endswith("_m"):
node.relkind = "multinuc"
elif node.relname == "span":
node.relkind = "span"
if node.secedges != "":
secedges += node.secedges.split(";")
secedge_data = ";".join(secedges)
rels = sorted([(k,v) for k,v in iteritems(rels)])
output = build_canvas(current_doc, current_project, rels, nodes, signal_data=signals, show_signals=False, validations="validate_empty;validate_flat;validate_mononuc")
output = build_canvas(current_doc, current_project, rels, nodes, secedge_data=secedge_data, signal_data=signals,
validations="validate_empty;validate_flat;validate_mononuc", signal_type_dict=signal_type_dict)
return output

def get_structure_main_server():
77 changes: 74 additions & 3 deletions modules/formats/db2rst.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,54 @@
import re
import re, sys


def db2rst(rels, nodes, signals):
def db2rst(rels, nodes, secedges, signals, signal_types, doc, project, user):
def sequential_ids(rst_xml):
# Ensure no gaps in node IDs and corresponding adjustments to signals and secedges.
# Assume input xml IDs are already sorted, but with possible gaps
output = []
temp = []
current_id = 1
id_map = {}
for line in rst_xml.split("\n"):
if ' id="' in line:
xml_id = re.search(r' id="([^"]+)"', line).group(1)
if ('<segment ' in line or '<group ' in line):
id_map[xml_id] = str(current_id)
line = line.replace(' id="'+xml_id+'"',' id="'+str(current_id)+'"')
current_id += 1
temp.append(line)

for line in temp:
if ' id="' in line:
if ' parent=' in line and ('<segment ' in line or '<group ' in line):
parent_id = re.search(r' parent="([^"]+)"', line).group(1)
new_parent = id_map[parent_id]
line = line.replace(' parent="'+parent_id+'"',' parent="'+str(new_parent)+'"')
elif "<secedge " in line:
xml_id = re.search(r' id="([^"]+)"', line).group(1)
src, trg = xml_id.split("-")
line = line.replace(' source="'+src+'"', ' source="'+id_map[src]+'"')
line = line.replace(' target="' + trg + '"', ' target="' + id_map[trg] + '"')
line = line.replace(' id="' + xml_id + '"', ' id="' + id_map[src] + '-' + id_map[trg] + '"')
elif "<signal " in line:
source = re.search(r' source="([^"]+)"', line).group(1)
if "-" in source:
src, trg = source.split("-")
line = line.replace(' source="' + source + '"', ' source="' + id_map[src] + '-' + id_map[trg] + '"')
else:
if source in id_map:
line = line.replace(' source="' + source + '"', ' source="' + id_map[source] + '"')
else: # Zombie signal pointing to no longer existing node
from ..rstweb_sql import generic_query
# Repair the database
generic_query("DELETE from rst_signals WHERE source like ? and doc=? and project=? and user=?",
(source, doc, project, user))
sys.stderr.write("Removed signal with non-existant source " + source + ":\n"+line+"\n")
continue
output.append(line)

return "\n".join(output)

rst_out = [
"<rst>",
"\t<header>",
@@ -13,6 +60,15 @@ def db2rst(rels, nodes, signals):
rst_out.append('\t\t\t<rel name="' + relname_string + '" type="' + rel[1] + '"/>')

rst_out.append("\t\t</relations>")

if len(signal_types) > 0:
rst_out.append("\t\t<sigtypes>")
for major_type in signal_types:
minor_types = signal_types[major_type]
minor_types = ";".join(sorted(minor_types))
rst_out.append('\t\t\t<sig type="'+major_type+'" subtypes="'+minor_types+'"/>')
rst_out.append("\t\t</sigtypes>")

rst_out.append("\t</header>")
rst_out.append("\t<body>")

@@ -53,6 +109,18 @@ def db2rst(rels, nodes, signals):
rst_out.append('\t\t<group id="' + node[0] + '" type="' + node[
5] + '" ' + parent_string + relname_string + '/>')

if len(secedges) > 0:
rst_out.append("\t\t<secedges>")
for s in secedges.split(";"):
if ":" not in s:
continue
src_trg, relname = s.split(":",1)
src, trg = src_trg.split("-")
if relname.endswith("_r") or relname.endswith("_m"):
relname = relname[:-2]
rst_out.append('\t\t\t<secedge id="'+src+"-"+trg+'" source="' + src + '" target="' + trg + '" relname="' + relname + '"/>')
rst_out.append("\t\t</secedges>")

if len(signals) > 0:
rst_out.append("\t\t<signals>")
for signal in signals:
@@ -61,4 +129,7 @@ def db2rst(rels, nodes, signals):
rst_out.append("\t\t</signals>")
rst_out.append("\t</body>")
rst_out.append("</rst>")
return '\n'.join(rst_out) + '\n'
rst_out = '\n'.join(rst_out) + '\n'
rst_out = sequential_ids(rst_out)

return rst_out
7 changes: 4 additions & 3 deletions modules/logintools/login.py
Original file line number Diff line number Diff line change
@@ -97,7 +97,7 @@
# login is the function most frequently imported
# and called directly by external scripts

def login(theform, userdir, thisscript=None, action=None):
def login(theform, userdir, thisscript=None, action=None, print_cookie=True):
"""From the form decide which function to call."""
# FIXME: this function got a bit more complicated than intended
# it also handles checking logins when editaccount or admin
@@ -185,8 +185,9 @@ def login(theform, userdir, thisscript=None, action=None):

else:
displaylogin(userdir, thisscript, action) # we haven't understood - just display the login screen XXXX error message instead ?

print(newcookie) # XXXX ought to be a way of returning the cookie object instead...

if print_cookie:
print(newcookie) # XXXX ought to be a way of returning the cookie object instead...
if action == 'EMPTY_VAL_MJF': # the programmer ought never to 'see' this value, although it might get passed to his script by the login code a few times....
action = None
userconfig['lastused'] = str(time())
3 changes: 2 additions & 1 deletion modules/rstweb_classes.py
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
"""

class NODE:
def __init__(self, id, left, right, parent, depth, kind, text, relname, relkind):
def __init__(self, id, left, right, parent, depth, kind, text, relname, relkind, secedges):

"""Basic class to hold all nodes (EDU, span and multinuc) in structure.py and while importing"""

@@ -21,6 +21,7 @@ def __init__(self, id, left, right, parent, depth, kind, text, relname, relkind)
self.relname = relname
self.relkind = relkind #rst (a.k.a. satellite), multinuc or span relation
self.sortdepth = depth
self.secedges = secedges


class SEGMENT:
54 changes: 46 additions & 8 deletions modules/rstweb_reader.py
Original file line number Diff line number Diff line change
@@ -23,11 +23,13 @@ def read_rst(filename, rel_hash, do_tokenize=False, as_string=False):
else:
f = codecs.open(filename, "r", "utf-8")
in_rs3 = f.read()
# Remove processing instruction
in_rs3 = re.sub(r'<\?xml[^<>]*?\?>','',in_rs3)
try:
xmldoc = minidom.parseString(codecs.encode(in_rs3, "utf-8"))
except ExpatError:
message = "Invalid .rs3 file"
return message
return message, None

nodes = []
ordered_id = {}
@@ -184,10 +186,19 @@ def read_rst(filename, rel_hash, do_tokenize=False, as_string=False):
signals = []
for signal in item_list:
source = signal.attributes["source"].value
# This will crash if signal source refers to a non-existing node:
source = ordered_id[source]
if source not in all_node_ids:
raise IOError("Invalid source node ID for signal: " + str(source) + " (from XML file source="+signal.attributes["source"].value+"(\n")
if "-" in source: # Secedge signal
src, trg = source.split("-")
# We assume .rs4 format files are properly ordered, so directly look up IDs from secedge
if int(src) not in all_node_ids or int(trg) not in all_node_ids:
raise IOError("Invalid secedge ID for signal: " + str(source) + " (from XML file source="+signal.attributes["source"].value+")\n")
src = str(ordered_id[src])
trg = str(ordered_id[trg])
source = src + "-" + trg
else:
# This will crash if signal source refers to a non-existing node:
source = ordered_id[source]
if source not in all_node_ids:
raise IOError("Invalid source node ID for signal: " + str(source) + " (from XML file source="+signal.attributes["source"].value+")\n")
type = signal.attributes["type"].value
subtype = signal.attributes["subtype"].value
tokens = signal.attributes["tokens"].value
@@ -199,15 +210,42 @@ def read_rst(filename, rel_hash, do_tokenize=False, as_string=False):
raise IOError("Signal refers to non-existent token: " + str(max_tok))
signals.append([str(source),type,subtype,tokens])

# Collect signal type inventory declaration if available
item_list = xmldoc.getElementsByTagName("sig")
signal_type_dict = {}
for sig in item_list:
sigtype = sig.attributes["type"].value
subtypes = sig.attributes["subtypes"].value.split(";")
signal_type_dict[sigtype] = subtypes
if len(signal_type_dict) == 0:
signal_type_dict = None

# Collect secondary edges if any are available
item_list = xmldoc.getElementsByTagName("secedge")
secedge_dict = collections.defaultdict(set)
for secedge in item_list:
source = secedge.attributes["source"].value
target = secedge.attributes["target"].value
relname = secedge.attributes["relname"].value
# This will crash if signal source or target refers to a non-existing node:
source = ordered_id[source]
target = ordered_id[target]
if source not in all_node_ids:
raise IOError("Invalid source node ID for secedge: " + str(source) + " (from XML file source="+secedge.attributes["source"].value+"(\n")
if target not in all_node_ids:
raise IOError("Invalid target node ID for secedge: " + str(target) + " (from XML file source="+secedge.attributes["target"].value+"(\n")
secedge_dict[str(source)].add(str(source) + "-" + str(target) + ":" + relname + "_r")

elements = {}
for row in nodes:
elements[row[0]] = NODE(row[0],row[1],row[2],row[3],row[4],row[5],row[6],row[7],"")
secedges = ";".join(secedge_dict[row[0]]) if row[0] in secedge_dict else ""
elements[row[0]] = NODE(row[0],row[1],row[2],row[3],row[4],row[5],row[6],row[7],"",secedges)

for element in elements:
if elements[element].kind == "edu":
get_left_right(element, elements,0,0,rel_hash)

return elements, signals
return elements, signals, signal_type_dict


def read_text(filename,rel_hash,do_tokenize=False):
@@ -238,7 +276,7 @@ def read_text(filename,rel_hash,do_tokenize=False):
contents = tokenize(contents)
contents = " ".join(contents)

nodes[str(id_counter)] = NODE(str(id_counter),id_counter,id_counter,"0",0,"edu",contents,list(rels.keys())[0],list(rels.values())[0])
nodes[str(id_counter)] = NODE(str(id_counter),id_counter,id_counter,"0",0,"edu",contents,list(rels.keys())[0],list(rels.values())[0],"")

return nodes

188 changes: 159 additions & 29 deletions modules/rstweb_sql.py

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions quick_export.py
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
import codecs
import sys
import cgi
import os
import os, re
from modules.configobj import ConfigObj
from modules.logintools import login
from modules.rstweb_sql import get_export_string
@@ -64,14 +64,16 @@ def quickexp_main_server():
theform = cgi.FieldStorage()
scriptpath = os.path.dirname(os.path.realpath(__file__)) + os.sep
userdir = scriptpath + "users" + os.sep
action, userconfig = login(theform, userdir, thisscript, action)
action, userconfig = login(theform, userdir, thisscript, action, print_cookie=False)
user = userconfig["username"]
admin = userconfig["admin"]
kwargs={}
for key in theform:
kwargs[key] = theform[key].value

output = quickexp_main(user, admin, 'server', **kwargs)
output = re.sub(r'Set-Cookie[^\n]+','',output) # Remove any cookies
sys.stdout.buffer.flush()
if sys.version_info[0] < 3:
print(output)
else:
Binary file modified rstWeb_user_guide.pdf
Binary file not shown.
Binary file modified rstweb.db
Binary file not shown.
4 changes: 4 additions & 0 deletions script/admin.js
Original file line number Diff line number Diff line change
@@ -254,6 +254,10 @@ function admin(action){
document.getElementById("switch_multinuc_buttons").value = "switch_multinuc_buttons";
document.getElementById("sel_tab").value = "database";
break;
case "switch_secedges":
document.getElementById("switch_secedges").value = "switch_secedges";
document.getElementById("sel_tab").value = "database";
break;
case "update_schema":
document.getElementById("update_schema").value = "update_schema";
document.getElementById("sel_tab").value = "database";
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added script/images/ui-bg_glass_100_f6f6f6_1x400.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added script/images/ui-bg_glass_100_fdf5ce_1x400.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added script/images/ui-icons_222222_256x240.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added script/images/ui-icons_ef8c08_256x240.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 62 additions & 12 deletions script/quick.js
Original file line number Diff line number Diff line change
@@ -42,23 +42,72 @@ function get_rs3(){
groups.push('\t\t<group id="'+nid.replace("n","")+'" type="'+node.kind+'" ' + parent_string + relname_string+'/>');
}
}
for (rel of reltypes.sort()){
if (rel=="span" || rel=="none"){continue;}
relname_string = rel.replace(/_[rm]/,'');
if (rel.endsWith("_m")){
reltype = "multinuc";
}
else{
reltype = "rst";
}
rels.push('\t\t\t<rel name="' + relname_string + '" type="' + reltype + '"/>');
}
for (rel of reltypes.sort()){
if (rel=="span" || rel=="none"){continue;}
relname_string = rel.replace(/_[rm]/,'');
if (rel.endsWith("_m")){
reltype = "multinuc";
}
else{
reltype = "rst";
}
rels.push('\t\t\t<rel name="' + relname_string + '" type="' + reltype + '"/>');
}

rst_out = '<rst>\n\t<header>\n\t\t<relations>\n';
rst_out += rels.join("\n") + "\n";
rst_out += "\t\t</relations>\n\t</header>\n\t<body>\n";
rst_out += "\t\t</relations>\n";

signal_types = window.rstWebSignalTypes;
if (Object.keys(signal_types).length > 0){
rst_out += "\t\t<sigtypes>\n";
for (major_type in signal_types){
minor_types = signal_types[major_type];
minor_types = minor_types.join(";");
rst_out += '\t\t\t<sig type="'+major_type+'" subtypes="'+minor_types+'"/>\n';
}
rst_out += "\t\t</sigtypes>\n";
}

rst_out += "\t</header>\n\t<body>\n";
rst_out += edus.join("\n") + "\n";
rst_out += groups.join("\n") + "\n";

secedges = document.getElementById("secedges").value;
if (secedges.length > 0){
rst_out += "\t\t<secedges>\n"
for (s of secedges.split(";")){
if (!s.includes(":")){continue;}
parts = s.split(":");
src_trg = parts[0];
relname = parts[1];
parts = src_trg.split("-");
src = parts[0];
trg = parts[1];
if (relname.endsWith("_r") || relname.endsWith("_m")){
relname = relname.slice(0,-2);
}
rst_out += '\t\t\t<secedge id="'+src+"-"+trg+'" source="' + src + '" target="' + trg + '" relname="' + relname + '"/>\n';
}
rst_out += "\t\t</secedges>\n";
}

signals = window.rstWebSignals;

if (Object.keys(signals).length > 0){
rst_out += "\t\t<signals>\n";
for (source in signals){
for (signal of signals[source]){
signal_type = signal["type"];
signal_subtype = signal["subtype"];
tokens = signal["tokens"];
tokens = tokens.join(",");
rst_out += '\t\t\t<signal source="' + source + '" type="' + signal_type + '" subtype="' + signal_subtype + '" tokens="' + tokens + '"/>\n';
}
}
rst_out += "\t\t</signals>\n";
}

rst_out += "\t</body>\n</rst>\n";
return rst_out;
}
@@ -91,6 +140,7 @@ $(document).ready(function() {
data: rs3},
function(newData){
$("#quick_structure").html(newData);
$("#show-all-signals").click();
}
);
}
341 changes: 311 additions & 30 deletions script/structure.js

Large diffs are not rendered by default.

90 changes: 38 additions & 52 deletions signals/default.json
Original file line number Diff line number Diff line change
@@ -1,52 +1,38 @@
{"DM": ["DM"],
"Reference": ["Personal reference",
"Demonstrative reference",
"Comparative reference",
"Propositional reference"],
"Lexical": ["Indicative word",
"Alternate expression"],
"Semantic": ["Synonymy",
"Antonymy",
"Meronymy",
"Repetition",
"Indicative word pair",
"Lexical chain",
"General word"],
"Morphological": ["Tense"],
"Syntactic": ["Relative clause",
"Infinitival clause",
"Present participial clause",
"Past participial clause",
"Imperative clause",
"Interrupted matrix clause",
"Parallel syntactic construction",
"Reported speech",
"Subject auxiliary inversion",
"Nominal modifier",
"Adjectival modifier"],
"Graphical": ["Colon",
"Semicolon",
"Dash",
"Parentheses",
"Items in sequence"],
"Genre": ["Inverted pyramid scheme",
"Newspaper layout",
"Newspaper style attribution",
"Newspaper style definition"],
"Numerical": ["Same count"],
"Reference + syntactic": ["Personal reference + subject NP",
"Demonstrative reference + subject NP",
"Comparative reference + subject NP",
"Propositional reference + subject NP"],
"Semantic + syntactic": ["Repetition + subject NP",
"Lexical chain + subject NP",
"Synonymy + subject NP",
"Meronymy + subject NP",
"General word + subject NP"],
"Lexical + syntactic": ["Indicative word + present participial clause"],
"Syntactic + positional": ["Past participial clause + beginning",
"Present participial clause + beginning"],
"Syntactic + semantic": ["parallel syntactic construction + lexical chain"],
"Graphical + syntactic": ["Comma + present participial clause",
"Comma + past participial clause"],
"Unsure": ["Unsure"]}
{"dm": ["dm"],
"reference": ["personal_reference",
"demonstrative_reference",
"comparative_reference",
"propositional_reference"],
"lexical": ["indicative_word",
"indicative_phrase",
"alternate_expression"],
"semantic": ["attribution_source",
"synonymy",
"antonymy",
"meronymy",
"repetition",
"lexical_chain",
"negation"],
"morphological": ["mood",
"tense"],
"syntactic": ["relative_clause",
"infinitival_clause",
"present_participial_clause",
"past_participial_clause",
"modified_head",
"interrupted_matrix_clause",
"parallel_syntactic_construction",
"reported_speech",
"subject_auxiliary_inversion",
"nominal_modifier"],
"graphical": ["colon",
"semicolon",
"dash",
"layout",
"parentheses",
"question_mark",
"quotation_marks",
"items_in_sequence"],
"numerical": ["same_count"],
"unsure": ["unsure"],
"orphan": ["orphan"]}
76 changes: 65 additions & 11 deletions structure.py
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@
from modules.logintools import login


def build_canvas(current_doc, current_project, rels, nodes, def_rstrel="", def_multirel="", signal_data=None, user=None, show_signals=True, validations=None):
def build_canvas(current_doc, current_project, rels, nodes, secedge_data="", def_rstrel="", def_multirel="", signal_data=None, user=None, show_signals=True, validations=None, signal_type_dict=None):
###GRAPHICAL PARAMETERS###
top_spacing = 20
layer_spacing = 60
@@ -40,6 +40,9 @@ def build_canvas(current_doc, current_project, rels, nodes, def_rstrel="", def_m
cpout += ''' <button id="show-all-signals">
Show All Signal Tokens
</button>\n'''
cpout += '''<ul class='custom-menu' data-action="">
<li data-action="quick_delete_signals">Delete signals</li>
</ul>\n''' # Signal context menu on right click token

cpout += ''' <div class="signal-drawer">
<div id="signal-list"> </div>
@@ -76,11 +79,13 @@ def build_canvas(current_doc, current_project, rels, nodes, def_rstrel="", def_m
if def_rstrel == "":
def_rstrel = sorted([rel[0] for rel in rels if rel[1] != "multinuc"])[0] # Take alphabetically first rel
if def_rstrel == "":
def_rstrel = "elaboration_r"
def_rstrel = "elaboration-additional_r"
if def_multirel == "":
def_multirel = sorted([rel[0] for rel in rels if rel[1] == "multinuc"])[0] # Take alphabetically first rel
multirels = sorted([rel[0] for rel in rels if rel[1] == "multinuc"])
if len(multirels) > 0:
def_multirel = multirels[0] # Take alphabetically first rel
if def_multirel == "":
def_multirel = "joint_m"
def_multirel = "joint-other_m"
for rel in rels:
rel_list.append(rel[0])
if rel[1] == "multinuc":
@@ -113,9 +118,13 @@ def build_canvas(current_doc, current_project, rels, nodes, def_rstrel="", def_m
signals[s_id].append({'type': s_type,
'subtype': subtype,
'tokens': tokens})

if signal_type_dict is None:
signal_type_dict = get_signal_types_dict(current_doc, current_project)

cpout += '<script>'
cpout += 'window.rstWebSignals = ' + json.dumps(signals) + ';'
cpout += 'window.rstWebSignalTypes = ' + json.dumps(get_signal_types_dict(current_doc, current_project),
cpout += 'window.rstWebSignalTypes = ' + json.dumps(signal_type_dict,
sort_keys=True) + ';'
cpout += 'window.rstWebDefaultSignalType = Object.keys(window.rstWebSignalTypes)[0];'
cpout += 'if (window.rstWebDefaultSignalType != null) {window.rstWebDefaultSignalSubtype = window.rstWebSignalTypes[window.rstWebDefaultSignalType][0];}'
@@ -209,6 +218,12 @@ def build_canvas(current_doc, current_project, rels, nodes, def_rstrel="", def_m
use_span_buttons = True
use_multinuc_buttons = True

# Check whether secondary edges should be allowed
if int(get_schema()) > 6:
use_secedges = True if get_setting("use_secedges") == "True" else False
else:
use_secedges = False

if sys.version_info[0] == 2:
lambda_button = "Λ".decode("utf-8")
else:
@@ -276,6 +291,11 @@ def build_canvas(current_doc, current_project, rels, nodes, def_rstrel="", def_m
hidden_val = hidden_val[0:len(hidden_val) - 1]
cpout += 'value="' + hidden_val + '"/>'

# secondary edges, if any
cpout += '<input id="secedges" name="secedges" type="hidden" '
hidden_val = secedge_data
cpout += 'value="' + hidden_val + '"/>'

cpout += '<input id="def_multi_rel" type="hidden" value="' + def_multirel + '"/>\n'
cpout += '<input id="def_rst_rel" type="hidden" value="' + def_rstrel + '"/>\n'
cpout += '<input id="undo_log" type="hidden" value=""/>\n'
@@ -285,6 +305,7 @@ def build_canvas(current_doc, current_project, rels, nodes, def_rstrel="", def_m
cpout += '<input id="validations" type="hidden" value="' + validations + '"/>\n'
cpout += '<input id="use_span_buttons" type="hidden" value="' + str(use_span_buttons) + '"/>\n'
cpout += '<input id="use_multinuc_buttons" type="hidden" value="' + str(use_multinuc_buttons) + '"/>\n'
cpout += '<input id="use_secedges" type="hidden" value="' + str(use_secedges) + '"/>\n'

cpout += ''' <script src="./script/jquery.jsPlumb-1.7.5-min.js"></script>
@@ -296,8 +317,15 @@ def build_canvas(current_doc, current_project, rels, nodes, def_rstrel="", def_m
cpout += 'function select_my_rel(options,my_rel){'
cpout += 'var multi_options = `' + multi_options + '`;\n'
cpout += 'var rst_options = `' + rst_options + '`;\n'
cpout += 'if (options =="multi"){options = multi_options;} else {options=rst_options;}'
cpout += ' return options.replace("<option value=' + "'" + '"' + '+my_rel+' + '"' + "'" + '","<option selected=' + "'" + 'selected' + "'" + ' value=' + "'" + '"' + '+my_rel+' + '"' + "'" + '");'
cpout += 'var relname_mapping = {"adversative-antithesis":"antithesis","adversative-concession":"concession","adversative-contrast":"contrast","attribution-negative":"attrib.-negative","attribution-positive":"attrib.-positive","causal-cause":"cause","causal-result":"result","context-background":"background","context-circumstance":"circumstance","contingency-condition":"condition","elaboration-additional":"elab.-additional","elaboration-attribute":"elab.-attribute","evaluation-comment":"eval.-comment","explanation-evidence":"evidence","explanation-justify":"justify","explanation-motivation":"motivation","joint-disjunction":"disjunction","joint-list":"list","joint-other":"other","joint-sequence":"sequence","mode-manner":"manner","mode-means":"means","organization-heading":"heading","organization-phatic":"phatic","organization-preparation":"preparation","purpose-attribute":"purp.-attribute","purpose-goal":"purp.-goal","restatement-partial":"restat.-partial","restatement-repetition":"restat.-repetition","same-unit":"same-unit","topic-question":"question","topic-solutionhood":"solutionhood"}\n'
cpout += '''if (options =="both"){options = multi_options.replace(/<option value=[^<>]+?>.?(satellite|same-unit)[^<>]*<.option>/g,"").replace(/\\n+/g,"\\n").replace(/_m'/g,"_r'") + rst_options;}\n'''
cpout += 'else if (options =="multi"){options = multi_options;} else {options=rst_options;}\n'
cpout += ' replaced = options.replace("<option value=' + "'" + '"' + '+my_rel+' + '"' + "'" + '","<option selected=' + "'" + 'selected' + "'" + ' value=' + "'" + '"' + '+my_rel+' + '"' + "'" + '");\n'
cpout += ' const longrel = /([a-z]{4})[a-z]+-([a-z]+<.option)/gi;\n'
cpout += ' for (f in relname_mapping) {replaced = replaced.replace(">" + f + "<",">" + relname_mapping[f] + "<");}\n'
#cpout += ' replaced = replaced.replace(longrel,"$1-$2"); //shorten long names\n'
cpout += ' replaced = replaced.trim().split("\\n").sort( (a,b) => a.match(/>([^<>]+)</)[1] > b.match(/>([^<>]+)</)[1] ).join("\\n"); \n'
cpout += ' return replaced + "\\n";\n'
cpout += ' }\n'
cpout += '''function make_relchooser(id,option_type,rel){
var s = "<div id='seldiv"+id.replace("n","")+"' style='white-space:nowrap;'>";
@@ -331,8 +359,11 @@ def build_canvas(current_doc, current_project, rels, nodes, def_rstrel="", def_m
Anchor:"Top",
Connector : [ "Bezier", { curviness:50 } ]
})
var loading_done = false;
jsPlumb.ready(function() {
if (loading_done){return;}
loading_done = true;
jsPlumb.setContainer(document.getElementById("inner_canvas"));
'''

@@ -387,6 +418,12 @@ def build_canvas(current_doc, current_project, rels, nodes, def_rstrel="", def_m
var node_id = "n"+info.sourceId.replace(/edu|g|lg/,"");
var new_parent_id = "n"+info.targetId.replace(/edu|g|lg/,"");
if (ctrlPressed.value && $('#use_secedges').val().toLowerCase() == "true"){
defrel = get_def_rstrel();
act("sc:"+node_id.replace(/n/,'') + "-"+new_parent_id.replace(/n/,'')+"," + defrel);
return;
}
nodes = parse_data();
new_parent = nodes[new_parent_id];
relname = nodes[node_id].relname;
@@ -419,6 +456,9 @@ def build_canvas(current_doc, current_project, rels, nodes, def_rstrel="", def_m
$(".minibtn").prop("disabled",false);
});
loading_done = true;
nodes = parse_data();
render_all_secedges(nodes);
});
nodes = parse_data();
@@ -556,6 +596,10 @@ def structure_main(user, admin, mode, **kwargs):
update_rel(params[0], params[1], current_doc, current_project, user)
elif action_type == "sg":
update_signals(action.split(":")[1:], current_doc, current_project, user)
elif action_type == "sc": # Add secedge
update_secedge(params[0].split("-")[0], params[0].split("-")[1], params[1], current_doc, current_project, user)
elif action_type == "xs": # Delete secedge
update_secedge(params[0].split("-")[0], params[0].split("-")[1], "-ERASE-", current_doc, current_project, user)
else:
cpout += '<script>alert("the action was: " + theform["action"]);</script>\n'

@@ -573,18 +617,28 @@ def structure_main(user, admin, mode, **kwargs):
rows = get_rst_doc(current_doc, current_project, user)
signal_data = get_signals(current_doc, current_project, user)
nodes = {}
secedge_data = []
for row in rows:
relkind = "span"
if row[7].endswith("_m"):
relkind = "multinuc"
elif row[7].endswith("_r"):
relkind = "rst"
if row[5] == "edu":
nodes[row[0]] = NODE(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], relkind)
nodes[row[0]] = NODE(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], relkind, row[8])
else:
nodes[row[0]] = NODE(row[0], 0, 0, row[3], row[4], row[5], row[6], row[7], relkind)

cpout += build_canvas(current_doc, current_project, rels, nodes, def_rstrel=def_rstrel, def_multirel=def_multirel, signal_data=signal_data)
nodes[row[0]] = NODE(row[0], 0, 0, row[3], row[4], row[5], row[6], row[7], relkind, row[8])
if row[8] is not None:
sec = row[8]
if sec.startswith(";"):
sec = sec[1:]
if row[8].endswith(";"):
sec = sec[:-1]
if len(sec) > 0:
secedge_data += sec.split(";")
secedge_data = ";".join(sorted(list(set(secedge_data))))

cpout += build_canvas(current_doc, current_project, rels, nodes, secedge_data=secedge_data, user=user, def_rstrel=def_rstrel, def_multirel=def_multirel, signal_data=signal_data)
cpout += ''' </body>
</html>
'''
2 changes: 1 addition & 1 deletion templates/control/main_header.html
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

<title>rstWeb - **page_title**</title>
<link rel="stylesheet" href="css/rst.css" type="text/css" charset="utf-8"/>
<link rel="stylesheet" href="css/rst.css?v=2" type="text/css" charset="utf-8"/>
<link rel="stylesheet" href="css/font-awesome-4.2.0/css/font-awesome.min.css"/>
<script src="./script/jquery-1.11.3.min.js"></script>
<script src="./script/jquery-ui.min.js"></script>
2 changes: 1 addition & 1 deletion templates/control/quick.html
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

<title>rstWeb - **page_title**</title>
<link rel="stylesheet" href="css/rst.css" type="text/css" charset="utf-8"/>
<link rel="stylesheet" href="css/rst.css?v=2" type="text/css" charset="utf-8"/>
<link rel="stylesheet" href="css/font-awesome-4.2.0/css/font-awesome.min.css"/>
<link rel="stylesheet" href="./script/jquery-ui.min.css">
<script src="./script/jquery-1.11.3.min.js"></script>
2 changes: 1 addition & 1 deletion templates/login/login_page.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<title>rstWeb - Login</title>
<link rel="stylesheet" href="css/rst.css" type="text/css" charset="utf-8"/>

52 changes: 32 additions & 20 deletions users/default_rels.tab
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
antithesis rst
background rst
cause rst
circumstance rst
concession rst
condition rst
contrast multinuc
elaboration rst
evaluation rst
evidence rst
joint multinuc
justify rst
motivation rst
preparation rst
purpose rst
restatement multinuc
restatement rst
result rst
sequence multinuc
solutionhood rst
adversative-antithesis rst
adversative-concession rst
adversative-contrast multinuc
attribution-negative rst
attribution-positive rst
causal-cause rst
causal-result rst
context-background rst
context-circumstance rst
contingency-condition rst
elaboration-additional rst
elaboration-attribute rst
evaluation-comment rst
explanation-evidence rst
explanation-justify rst
explanation-motivation rst
joint-disjunction multinuc
joint-list multinuc
joint-other multinuc
joint-sequence multinuc
mode-manner rst
mode-means rst
organization-heading rst
organization-phatic rst
organization-preparation rst
purpose-attribute rst
purpose-goal rst
restatement-partial rst
restatement-repetition multinuc
same-unit multinuc
topic-question rst
topic-solutionhood rst

0 comments on commit 5341149

Please sign in to comment.