From 242e23c085385a8c674b3435020dbc75d81d3f0a Mon Sep 17 00:00:00 2001 From: David Huynh Date: Wed, 10 Feb 2010 01:15:25 +0000 Subject: [PATCH] The schema alignment dialog is starting to work. The protograph gets rendered and is interactive. No saving yet. git-svn-id: http://google-refine.googlecode.com/svn/trunk@83 7d457c2a-affb-35e4-300a-418c747d4874 --- .../gridworks/protograph/CellNode.java | 24 +- .../gridworks/protograph/CellTopicNode.java | 35 +++ .../gridworks/protograph/CellValueNode.java | 36 +++ .../protograph/ExistingTopicNode.java | 22 -- .../protograph/FreebaseTopicNode.java | 25 ++ .../metaweb/gridworks/protograph/Link.java | 19 +- .../gridworks/protograph/ValueNode.java | 31 ++ src/main/webapp/images/arrow-end.png | Bin 0 -> 142 bytes src/main/webapp/images/arrow-start.png | Bin 0 -> 139 bytes src/main/webapp/images/collapsed.png | Bin 0 -> 176 bytes src/main/webapp/images/expanded.png | Bin 0 -> 115 bytes .../scripts/project/schema-alignment.js | 284 ++++++++++++++++-- src/main/webapp/styles/common.css | 4 + src/main/webapp/styles/process.css | 3 - .../webapp/styles/schema-alignment-dialog.css | 47 ++- 15 files changed, 450 insertions(+), 80 deletions(-) create mode 100644 src/main/java/com/metaweb/gridworks/protograph/CellTopicNode.java create mode 100644 src/main/java/com/metaweb/gridworks/protograph/CellValueNode.java delete mode 100644 src/main/java/com/metaweb/gridworks/protograph/ExistingTopicNode.java create mode 100644 src/main/java/com/metaweb/gridworks/protograph/FreebaseTopicNode.java create mode 100644 src/main/java/com/metaweb/gridworks/protograph/ValueNode.java create mode 100644 src/main/webapp/images/arrow-end.png create mode 100644 src/main/webapp/images/arrow-start.png create mode 100644 src/main/webapp/images/collapsed.png create mode 100644 src/main/webapp/images/expanded.png diff --git a/src/main/java/com/metaweb/gridworks/protograph/CellNode.java b/src/main/java/com/metaweb/gridworks/protograph/CellNode.java index 9213e1910..24b56f796 100644 --- a/src/main/java/com/metaweb/gridworks/protograph/CellNode.java +++ b/src/main/java/com/metaweb/gridworks/protograph/CellNode.java @@ -1,31 +1,13 @@ package com.metaweb.gridworks.protograph; -import java.util.Properties; - -import org.json.JSONException; -import org.json.JSONWriter; - -public class CellNode extends Node { +abstract public class CellNode extends Node { private static final long serialVersionUID = 5820786756175547307L; - final public int cellIndex; - final public boolean createUnlessRecon; - final public FreebaseType type; + final public int cellIndex; public CellNode( - int cellIndex, - boolean createUnlessRecon, - FreebaseType type + int cellIndex ) { this.cellIndex = cellIndex; - this.createUnlessRecon = createUnlessRecon; - this.type = type; } - - public void write(JSONWriter writer, Properties options) - throws JSONException { - // TODO Auto-generated method stub - - } - } diff --git a/src/main/java/com/metaweb/gridworks/protograph/CellTopicNode.java b/src/main/java/com/metaweb/gridworks/protograph/CellTopicNode.java new file mode 100644 index 000000000..41564c4f9 --- /dev/null +++ b/src/main/java/com/metaweb/gridworks/protograph/CellTopicNode.java @@ -0,0 +1,35 @@ +package com.metaweb.gridworks.protograph; + +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONWriter; + +public class CellTopicNode extends CellNode { + private static final long serialVersionUID = 1684854896739592911L; + + final public boolean createForNoReconMatch; + final public FreebaseType type; + + public CellTopicNode( + int cellIndex, + boolean createForNoReconMatch, + FreebaseType type + ) { + super(cellIndex); + + this.createForNoReconMatch = createForNoReconMatch; + this.type = type; + } + + public void write(JSONWriter writer, Properties options) + throws JSONException { + + writer.object(); + writer.key("nodeType"); writer.value("cell-as-topic"); + writer.key("cellIndex"); writer.value(cellIndex); + writer.key("type"); type.write(writer, options); + writer.key("createUnlessRecon"); writer.value(createForNoReconMatch); + writer.endObject(); + } +} diff --git a/src/main/java/com/metaweb/gridworks/protograph/CellValueNode.java b/src/main/java/com/metaweb/gridworks/protograph/CellValueNode.java new file mode 100644 index 000000000..3b056cb2c --- /dev/null +++ b/src/main/java/com/metaweb/gridworks/protograph/CellValueNode.java @@ -0,0 +1,36 @@ +package com.metaweb.gridworks.protograph; + +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONWriter; + +public class CellValueNode extends CellNode { + private static final long serialVersionUID = 7311884925532708576L; + + final public String valueType; + final public String lang; + + public CellValueNode( + int cellIndex, + String valueType, + String lang + ) { + super(cellIndex); + + this.valueType = valueType; + this.lang = lang; + } + + public void write(JSONWriter writer, Properties options) + throws JSONException { + + writer.object(); + writer.key("nodeType"); writer.value("cell-as-value"); + writer.key("cellIndex"); writer.value(cellIndex); + writer.key("valueType"); writer.value(valueType); + writer.key("lang"); writer.value(lang); + writer.endObject(); + } + +} diff --git a/src/main/java/com/metaweb/gridworks/protograph/ExistingTopicNode.java b/src/main/java/com/metaweb/gridworks/protograph/ExistingTopicNode.java deleted file mode 100644 index 140fd9e5f..000000000 --- a/src/main/java/com/metaweb/gridworks/protograph/ExistingTopicNode.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.metaweb.gridworks.protograph; - -import java.util.Properties; - -import org.json.JSONException; -import org.json.JSONWriter; - -public class ExistingTopicNode extends Node { - private static final long serialVersionUID = 8418548867745587387L; - - final protected FreebaseTopic _topic; - - public ExistingTopicNode(FreebaseTopic topic) { - _topic = topic; - } - - public void write(JSONWriter writer, Properties options) - throws JSONException { - // TODO Auto-generated method stub - - } -} diff --git a/src/main/java/com/metaweb/gridworks/protograph/FreebaseTopicNode.java b/src/main/java/com/metaweb/gridworks/protograph/FreebaseTopicNode.java new file mode 100644 index 000000000..1c632a9e8 --- /dev/null +++ b/src/main/java/com/metaweb/gridworks/protograph/FreebaseTopicNode.java @@ -0,0 +1,25 @@ +package com.metaweb.gridworks.protograph; + +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONWriter; + +public class FreebaseTopicNode extends Node { + private static final long serialVersionUID = 8418548867745587387L; + + final public FreebaseTopic topic; + + public FreebaseTopicNode(FreebaseTopic topic) { + this.topic = topic; + } + + public void write(JSONWriter writer, Properties options) + throws JSONException { + + writer.object(); + writer.key("nodeType"); writer.value("topic"); + writer.key("topic"); topic.write(writer, options); + writer.endObject(); + } +} diff --git a/src/main/java/com/metaweb/gridworks/protograph/Link.java b/src/main/java/com/metaweb/gridworks/protograph/Link.java index 0c14eab11..3c17600b3 100644 --- a/src/main/java/com/metaweb/gridworks/protograph/Link.java +++ b/src/main/java/com/metaweb/gridworks/protograph/Link.java @@ -11,26 +11,29 @@ import com.metaweb.gridworks.Jsonizable; public class Link implements Serializable, Jsonizable { private static final long serialVersionUID = 2908086768260322876L; - final protected FreebaseProperty _property; - final protected Node _target; + final public FreebaseProperty property; + final public Node target; public Link(FreebaseProperty property, Node target) { - _property = property; - _target = target; + this.property = property; + this.target = target; } public FreebaseProperty getProperty() { - return _property; + return property; } public Node getTarget() { - return _target; + return target; } public void write(JSONWriter writer, Properties options) throws JSONException { - // TODO Auto-generated method stub - + + writer.object(); + writer.key("property"); property.write(writer, options); + writer.key("target"); target.write(writer, options); + writer.endObject(); } } diff --git a/src/main/java/com/metaweb/gridworks/protograph/ValueNode.java b/src/main/java/com/metaweb/gridworks/protograph/ValueNode.java new file mode 100644 index 000000000..167c1b2ee --- /dev/null +++ b/src/main/java/com/metaweb/gridworks/protograph/ValueNode.java @@ -0,0 +1,31 @@ +package com.metaweb.gridworks.protograph; + +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONWriter; + +public class ValueNode extends Node { + private static final long serialVersionUID = -5626883493437735688L; + + final public Object value; + final public String valueType; + final public String lang; + + public ValueNode(Object value, String valueType, String lang) { + this.value = value; + this.valueType = valueType; + this.lang = lang; + } + + public void write(JSONWriter writer, Properties options) + throws JSONException { + + writer.object(); + writer.key("nodeType"); writer.value("value"); + writer.key("value"); writer.value(value); + writer.key("valueType"); writer.value(valueType); + writer.key("lang"); writer.value(lang); + writer.endObject(); + } +} diff --git a/src/main/webapp/images/arrow-end.png b/src/main/webapp/images/arrow-end.png new file mode 100644 index 0000000000000000000000000000000000000000..5df656c2cc779eac8e785b6cd35d6510ef9b5853 GIT binary patch literal 142 zcmeAS@N?(olHy`uVBq!ia0vp^{6Ngj!2~4rRUNp26id3JuOkD)#(wTUiL5}rtEY=& zh(>Vopa1{unLjeDkP^?x$Z(jPbYQ)dFLUD66H*;Pyw@3mc%KL`J3Mr}a95yN;S^BF neBy?zl+&Cm)D-s^?qy*xRhp!KOgNDjXdr{9tDnm{r-UW|uPG?N literal 0 HcmV?d00001 diff --git a/src/main/webapp/images/arrow-start.png b/src/main/webapp/images/arrow-start.png new file mode 100644 index 0000000000000000000000000000000000000000..df70be001010a6d5855932045b973deb4fa352f3 GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^{6Ngj!2~4rRUNp26id3JuOkD)#(wTUiL5}rlc$Sg zh(>Vopa1{unLjeDm{oCrA@EiM%ZH4%Rcb-ZPNs%Z0U?Vs9m?b;@N)5|gbS6}M!r+a l&^p5T;@vU%Z%bCPG33sgq(AA3m@UvW22WQ%mvv4FO#ngTDBu79 literal 0 HcmV?d00001 diff --git a/src/main/webapp/images/collapsed.png b/src/main/webapp/images/collapsed.png new file mode 100644 index 0000000000000000000000000000000000000000..1a171be45eaa0210832d97bfff9298e908ce1ad6 GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1SHkYJtzcHjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijSl0AZa85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP(shs z#W6%9I5{UHBjEslgVw*tYzlufv!lvI6;9o-U3d z8o|jq85s!&_#3qTJ!Vt*`z3^N3%4-CT=)F)2V8v1qRGKp-yS^Vb*P#1%z LtDnm{r-UW|_c|Y+ literal 0 HcmV?d00001 diff --git a/src/main/webapp/scripts/project/schema-alignment.js b/src/main/webapp/scripts/project/schema-alignment.js index db19719d2..a0f1b7845 100644 --- a/src/main/webapp/scripts/project/schema-alignment.js +++ b/src/main/webapp/scripts/project/schema-alignment.js @@ -91,16 +91,18 @@ SchemaAlignment._cleanName = function(s) { } function SchemaAlignmentDialog(protograph) { - this._originalProtograph = { + protograph = { rootNodes: [ { nodeType: "cell-as-topic", - column: "name", - linkages: [ + links: [ ] } ] }; + + this._originalProtograph = protograph; + this._protograph = cloneDeep(protograph); this._createDialog(); }; @@ -138,22 +140,29 @@ SchemaAlignmentDialog.prototype._renderBody = function(body) { var self = this; this._canvas = $('
').addClass("schema-alignment-dialog-canvas").appendTo(body); - this._nodeTable = $('
').appendTo(this._canvas)[0]; + this._nodeTable = $('
').addClass("schema-alignment-table-layout").appendTo(this._canvas)[0]; for (var i = 0; i < this._originalProtograph.rootNodes.length; i++) { new SchemaAlignmentDialog.UINode( - this._originalProtograph.rootNodes[i], + this._protograph.rootNodes[i], this._nodeTable, - true + { + expanded: true, + mustBeCellTopic: true + } ); } }; -SchemaAlignmentDialog.UINode = function(node, table, expanded) { - this._originalNode = node; - this._newNode = { - nodeType: node.nodeType - }; +/*---------------------------------------------------------------------- + * UINode + *---------------------------------------------------------------------- + */ +SchemaAlignmentDialog.UINode = function(node, table, options) { + this._node = node; + this._options = options; + + this._linkUIs = []; this._detailsRendered = false; this._tr = table.insertRow(table.rows.length); @@ -161,24 +170,74 @@ SchemaAlignmentDialog.UINode = function(node, table, expanded) { this._tdToggle = this._tr.insertCell(1); this._tdDetails = this._tr.insertCell(2); - $(this._tdMain).addClass("schema-alignment-node-main").attr("width", "250"); - $(this._tdToggle).addClass("schema-alignment-node-toggle").attr("width", "1%").hide(); + $(this._tdMain).addClass("schema-alignment-node-main").attr("width", "250").addClass("padded"); + $(this._tdToggle).addClass("schema-alignment-node-toggle").attr("width", "1%").addClass("padded").hide(); $(this._tdDetails).addClass("schema-alignment-node-details").attr("width", "90%").hide(); this._renderMain(); - this._expanded = expanded; + this._expanded = options.expanded; if (this._isExpandable()) { this._showExpandable(); } }; SchemaAlignmentDialog.UINode.prototype._isExpandable = function() { - return this._newNode.nodeType != "existing-content" && this._newNode.nodeType != "cell-as-content"; + return this._node.nodeType == "cell-as-topic"; +}; + +SchemaAlignmentDialog._findColumn = function(cellIndex) { + var columns = theProject.columnModel.columns; + for (var i = 0; i < columns.length; i++) { + var column = columns[i]; + if (column.cellIndex == cellIndex) { + return column; + } + } + return null; }; SchemaAlignmentDialog.UINode.prototype._renderMain = function() { - $(this._tdMain).empty().html(this._newNode.nodeType); + $(this._tdMain).empty(); + + var self = this; + var a = $('') + .addClass("schema-alignment-node-tag") + .appendTo(this._tdMain) + .click(function(evt) { + self._showTagMenu(this); + }); + + if (this._node.nodeType == "cell-as-topic" || this._node.nodeType == "cell-as-value") { + if ("cellIndex" in this._node) { + a.html(" cell"); + + $('') + .text(SchemaAlignmentDialog._findColumn(this._node.cellIndex).headerLabel) + .addClass("schema-alignment-node-column") + .prependTo(a); + } else { + a.html("Which column?"); + } + } else if (this._node.nodeType == "topic") { + if ("topic" in this._node) { + a.html(this._node.topic.name); + } else if ("id" in this._node) { + a.html(this._node.topic.id); + } else { + a.html("Which topic?"); + } + } else if (this._node.nodeType == "value") { + if ("value" in this._node) { + a.html(this._node.value); + } else { + a.html("What value?"); + } + } else if (this._node.nodeType == "anonymous") { + a.html("(anonymous)"); + } + + $('').attr("src", "images/down-arrow.png").appendTo(a); }; SchemaAlignmentDialog.UINode.prototype._showExpandable = function() { @@ -190,8 +249,8 @@ SchemaAlignmentDialog.UINode.prototype._showExpandable = function() { } this._detailsRendered = true; - this._collapsedDetailDiv = $('
').appendTo(this._tdDetails).html("..."); - this._expandedDetailDiv = $('
').appendTo(this._tdDetails).html("details"); + this._collapsedDetailDiv = $('
').appendTo(this._tdDetails).addClass("padded").html("..."); + this._expandedDetailDiv = $('
').appendTo(this._tdDetails).addClass("schema-alignment-detail-container"); this._renderDetails(); @@ -208,14 +267,13 @@ SchemaAlignmentDialog.UINode.prototype._showExpandable = function() { show(); $(this._tdToggle).html(" "); - $('') - .attr("src", this._expanded ? "images/down-arrow.png" : "images/right-arrow.png") + .attr("src", this._expanded ? "images/expanded.png" : "images/collapsed.png") .appendTo(this._tdToggle) .click(function() { self._expanded = !self._expanded; - $(this).attr("src", self._expanded ? "images/down-arrow.png" : "images/right-arrow.png"); + $(this).attr("src", self._expanded ? "images/expanded.png" : "images/collapsed.png"); show(); }); @@ -227,5 +285,187 @@ SchemaAlignmentDialog.UINode.prototype._hideExpandable = function() { }; SchemaAlignmentDialog.UINode.prototype._renderDetails = function() { - var tableDetails = $('
').appendTo(this._tdDetails)[0]; + var self = this; + + this._tableLinks = $('
').addClass("schema-alignment-table-layout").appendTo(this._expandedDetailDiv)[0]; + + if ("links" in this._node && this._node.links != null) { + for (var i = 0; i < this._node.links.length; i++) { + this._linkUIs.push(new SchemaAlignmentDialog.UILink(this._node.links[i], this._tableLinks, true)); + } + } + + var divFooter = $('
').addClass("padded").appendTo(this._expandedDetailDiv); + + $('') + .addClass("action") + .text("add property") + .appendTo(divFooter) + .click(function() { + var newLink = { + property: null, + target: { + nodeType: "cell-as-value" + } + }; + self._linkUIs.push(new SchemaAlignmentDialog.UILink( + newLink, + self._tableLinks, + { + expanded: true, + mustBeCellTopic: false + } + )); + }); }; + +SchemaAlignmentDialog.UINode.prototype._showTagMenu = function(elmt) { + self = this; + + var menu = []; + + if (!this._options.mustBeCellTopic) { + menu.push({ + label: "Anonymous Node", + click: function() { + self._node.nodeType = "anonymous"; + self._showExpandable(); + self._renderMain(); + } + }); + menu.push({ + label: "Freebase Topic", + click: function() { + self._node.nodeType = "topic"; + self._hideExpandable(); + self._renderMain(); + } + }); + menu.push({ + label: "Value", + click: function() { + self._node.nodeType = "value"; + self._hideExpandable(); + self._renderMain(); + } + }); + menu.push({}); // separator + } + + var columns = theProject.columnModel.columns; + var createColumnMenuItem = function(index) { + menu.push({ + label: columns[index].headerLabel, + click: function() { + self._node.nodeType = "cell-as-topic"; + self._node.cellIndex = columns[index].cellIndex; + self._showExpandable(); + self._renderMain(); + } + }); + }; + for (var i = 0; i < columns.length; i++) { + createColumnMenuItem(i); + } + + MenuSystem.createAndShowStandardMenu(menu, elmt); +}; + +/*---------------------------------------------------------------------- + * UILink + *---------------------------------------------------------------------- + */ +SchemaAlignmentDialog.UILink = function(link, table, expanded) { + this._link = link; + this._expanded = expanded; + + this._tr = table.insertRow(table.rows.length); + this._tdMain = this._tr.insertCell(0); + this._tdToggle = this._tr.insertCell(1); + this._tdDetails = this._tr.insertCell(2); + + $(this._tdMain).addClass("schema-alignment-link-main").attr("width", "250").addClass("padded"); + $(this._tdToggle).addClass("schema-alignment-link-toggle").attr("width", "1%").addClass("padded"); + $(this._tdDetails).addClass("schema-alignment-link-details").attr("width", "90%"); + + this._collapsedDetailDiv = $('
').appendTo(this._tdDetails).addClass("padded").html("..."); + this._expandedDetailDiv = $('
').appendTo(this._tdDetails).addClass("schema-alignment-detail-container"); + var self = this; + var show = function() { + if (self._expanded) { + self._collapsedDetailDiv.hide(); + self._expandedDetailDiv.show(); + } else { + self._collapsedDetailDiv.show(); + self._expandedDetailDiv.hide(); + } + }; + show(); + + $(this._tdToggle).html(" "); + $('') + .attr("src", this._expanded ? "images/expanded.png" : "images/collapsed.png") + .appendTo(this._tdToggle) + .click(function() { + self._expanded = !self._expanded; + + $(this).attr("src", self._expanded ? "images/expanded.png" : "images/collapsed.png"); + + show(); + }); + + this._renderMain(); + this._renderDetails(); +}; + +SchemaAlignmentDialog.UILink.prototype._renderMain = function() { + $(this._tdMain).empty() + + var label = this._link.property != null ? this._link.property.id : "property?"; + + var self = this; + + var a = $('') + .addClass("schema-alignment-link-tag") + .html(label) + .appendTo(this._tdMain) + .click(function(evt) { + self._showTagSuggest(this); + }); + + $('').attr("src", "images/arrow-start.png").prependTo(a); + $('').attr("src", "images/arrow-end.png").appendTo(a); +}; + +SchemaAlignmentDialog.UILink.prototype._renderDetails = function() { + var tableDetails = $('
').addClass("schema-alignment-table-layout").appendTo(this._expandedDetailDiv)[0]; + this._targetUI = new SchemaAlignmentDialog.UINode(this._link.target, tableDetails, true); +}; + +SchemaAlignmentDialog.UILink.prototype._showTagSuggest = function(elmt) { + self = this; + + var fakeMenu = MenuSystem.createMenu() + .width(300) + .height(100) + .css("background", "none") + .css("border", "none"); + + var input = $('').appendTo(fakeMenu); + + var level = MenuSystem.showMenu(fakeMenu, function(){}); + MenuSystem.positionMenuAboveBelow(fakeMenu, $(elmt)); + + input.suggest({ type : '/type/property' }).bind("fb-select", function(e, data) { + self._link.property = { + id: data.id, + name: data.name + }; + + window.setTimeout(function() { + MenuSystem.dismissAll(); + self._renderMain(); + }, 100); + }); + input[0].focus(); +}; \ No newline at end of file diff --git a/src/main/webapp/styles/common.css b/src/main/webapp/styles/common.css index c2003678e..09c935cf6 100644 --- a/src/main/webapp/styles/common.css +++ b/src/main/webapp/styles/common.css @@ -62,4 +62,8 @@ a img { img { vertical-align: middle; +} + +.fbs-pane, .fbs-flyout-pane { + z-index: 2000; } \ No newline at end of file diff --git a/src/main/webapp/styles/process.css b/src/main/webapp/styles/process.css index 7c89b2f51..3e8952988 100644 --- a/src/main/webapp/styles/process.css +++ b/src/main/webapp/styles/process.css @@ -14,6 +14,3 @@ text-align: left; } -.fbs-pane, .fbs-flyout-pane { - z-index: 200; -} \ No newline at end of file diff --git a/src/main/webapp/styles/schema-alignment-dialog.css b/src/main/webapp/styles/schema-alignment-dialog.css index e94db0a41..2a165970c 100644 --- a/src/main/webapp/styles/schema-alignment-dialog.css +++ b/src/main/webapp/styles/schema-alignment-dialog.css @@ -2,25 +2,64 @@ height: 500px; overflow: auto; border: 1px solid #aaa; + padding: 10px; } -td.schema-alignment-node-main { +table.schema-alignment-table-layout { + border-collapse: collapse; + margin: 0px; + padding: 0px; + margin-bottom: 1em; +} + +table.schema-alignment-table-layout .padded { + padding: 3px 6px; +} + +div.schema-alignment-detail-container { + border-left: 3px solid #eee; +} + +td.schema-alignment-node-main, td.schema-alignment-link-main { white-space: pre; width: 300px; } -td.schema-alignment-node-toggle { +td.schema-alignment-node-toggle, td.schema-alignment-link-toggle { white-space: pre; width: 1%; } -td.schema-alignment-node-toggle img { +td.schema-alignment-node-toggle img, td.schema-alignment-link-toggle img { cursor: pointer; vertical-align: middle; padding: 2px; } -td.schema-alignment-node-details { +td.schema-alignment-node-details, td.schema-alignment-link-details { width: 90%; } +a.schema-alignment-node-tag { + padding: 3px 6px; + background: #ddd; + text-decoration: none; + color: black; + -moz-border-radius: 10px; +} +a.schema-alignment-node-tag:hover { + background: #888; + color: white; +} +.schema-alignment-node-column { + font-weight: bold; +} + +a.schema-alignment-link-tag { + padding: 3px 6px; + text-decoration: none; + color: black; +} +a.schema-alignment-link-tag:hover { + color: #88f; +}