Split css files.

Allow expressions to be evaluated on null cells too.
Various minor UI polishing touches and minor bug fixes.

git-svn-id: http://google-refine.googlecode.com/svn/trunk@58 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
David Huynh 2010-02-07 03:36:40 +00:00
parent 51de415809
commit 2ceaa53390
26 changed files with 531 additions and 447 deletions

View File

@ -25,23 +25,20 @@ public class ExpressionNominalRowGrouper implements RowVisitor {
@Override @Override
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) { public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
if (_cellIndex < row.cells.size()) { Cell cell = row.getCell(_cellIndex);
Cell cell = row.cells.get(_cellIndex);
if (cell != null) { Properties bindings = ExpressionUtils.createBindings(project);
Properties bindings = ExpressionUtils.createBindings(project); ExpressionUtils.bind(bindings, row, cell);
ExpressionUtils.bind(bindings, row, cell);
Object value = _evaluable.evaluate(bindings);
Object value = _evaluable.evaluate(bindings); if (value != null) {
if (value != null) { if (value.getClass().isArray()) {
if (value.getClass().isArray()) { Object[] a = (Object[]) value;
Object[] a = (Object[]) value; for (Object v : a) {
for (Object v : a) { processValue(v);
processValue(v);
}
} else {
processValue(value);
}
} }
} else {
processValue(value);
} }
} }
return false; return false;

View File

@ -25,23 +25,20 @@ public class ExpressionNumericRowBinner implements RowVisitor {
@Override @Override
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) { public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
if (_cellIndex < row.cells.size()) { Cell cell = row.getCell(_cellIndex);
Cell cell = row.cells.get(_cellIndex);
if (cell != null) { Properties bindings = ExpressionUtils.createBindings(project);
Properties bindings = ExpressionUtils.createBindings(project); ExpressionUtils.bind(bindings, row, cell);
ExpressionUtils.bind(bindings, row, cell);
Object value = _evaluable.evaluate(bindings);
Object value = _evaluable.evaluate(bindings); if (value != null) {
if (value != null) { if (value.getClass().isArray()) {
if (value.getClass().isArray()) { Object[] a = (Object[]) value;
Object[] a = (Object[]) value; for (Object v : a) {
for (Object v : a) { processValue(v);
processValue(v);
}
} else {
processValue(value);
}
} }
} else {
processValue(value);
} }
} }
return false; return false;

View File

@ -25,25 +25,21 @@ public class NumericBinIndex {
List<Double> allValues = new ArrayList<Double>(); List<Double> allValues = new ArrayList<Double>();
for (int i = 0; i < project.rows.size(); i++) { for (int i = 0; i < project.rows.size(); i++) {
Row row = project.rows.get(i); Row row = project.rows.get(i);
Cell cell = row.getCell(cellIndex);
ExpressionUtils.bind(bindings, row, cell);
if (cellIndex < row.cells.size()) { Object value = eval.evaluate(bindings);
Cell cell = row.cells.get(cellIndex); if (value != null) {
if (cell != null) { if (value.getClass().isArray()) {
ExpressionUtils.bind(bindings, row, cell); Object[] a = (Object[]) value;
for (Object v : a) {
Object value = eval.evaluate(bindings); if (v instanceof Number) {
if (value != null) { processValue(((Number) v).doubleValue(), allValues);
if (value.getClass().isArray()) {
Object[] a = (Object[]) value;
for (Object v : a) {
if (v instanceof Number) {
processValue(((Number) v).doubleValue(), allValues);
}
}
} else if (value instanceof Number) {
processValue(((Number) value).doubleValue(), allValues);
} }
} }
} else if (value instanceof Number) {
processValue(((Number) value).doubleValue(), allValues);
} }
} }
} }

View File

@ -21,31 +21,27 @@ public class ExpressionEqualRowFilter implements RowFilter {
@Override @Override
public boolean filterRow(Project project, int rowIndex, Row row) { public boolean filterRow(Project project, int rowIndex, Row row) {
if (_cellIndex < row.cells.size()) { Cell cell = row.getCell(_cellIndex);
Cell cell = row.cells.get(_cellIndex); Properties bindings = ExpressionUtils.createBindings(project);
if (cell != null) { ExpressionUtils.bind(bindings, row, cell);
Properties bindings = ExpressionUtils.createBindings(project);
ExpressionUtils.bind(bindings, row, cell); Object value = _evaluable.evaluate(bindings);
if (value != null) {
Object value = _evaluable.evaluate(bindings); if (value.getClass().isArray()) {
if (value != null) { Object[] a = (Object[]) value;
if (value.getClass().isArray()) { for (Object v : a) {
Object[] a = (Object[]) value; for (Object match : _matches) {
for (Object v : a) { if (match.equals(v)) {
for (Object match : _matches) { return true;
if (match.equals(v)) {
return true;
}
}
}
} else {
for (Object match : _matches) {
if (match.equals(value)) {
return true;
}
} }
} }
} }
} else {
for (Object match : _matches) {
if (match.equals(value)) {
return true;
}
}
} }
} }
return false; return false;

View File

@ -19,27 +19,24 @@ abstract public class ExpressionNumberComparisonRowFilter implements RowFilter {
@Override @Override
public boolean filterRow(Project project, int rowIndex, Row row) { public boolean filterRow(Project project, int rowIndex, Row row) {
if (_cellIndex < row.cells.size()) { Cell cell = row.getCell(_cellIndex);
Cell cell = row.cells.get(_cellIndex);
if (cell != null) { Properties bindings = ExpressionUtils.createBindings(project);
Properties bindings = ExpressionUtils.createBindings(project); ExpressionUtils.bind(bindings, row, cell);
ExpressionUtils.bind(bindings, row, cell);
Object value = _evaluable.evaluate(bindings);
Object value = _evaluable.evaluate(bindings); if (value != null) {
if (value != null) { if (value.getClass().isArray()) {
if (value.getClass().isArray()) { Object[] a = (Object[]) value;
Object[] a = (Object[]) value; for (Object v : a) {
for (Object v : a) { if (v instanceof Number && checkValue(((Number) v).doubleValue())) {
if (v instanceof Number && checkValue(((Number) v).doubleValue())) { return true;
return true;
}
}
} else {
if (value instanceof Number && checkValue(((Number) value).doubleValue())) {
return true;
}
} }
} }
} else {
if (value instanceof Number && checkValue(((Number) value).doubleValue())) {
return true;
}
} }
} }
return false; return false;

View File

@ -19,27 +19,23 @@ abstract public class ExpressionStringComparisonRowFilter implements RowFilter {
@Override @Override
public boolean filterRow(Project project, int rowIndex, Row row) { public boolean filterRow(Project project, int rowIndex, Row row) {
if (_cellIndex < row.cells.size()) { Cell cell = row.getCell(_cellIndex);
Cell cell = row.cells.get(_cellIndex); Properties bindings = ExpressionUtils.createBindings(project);
if (cell != null) { ExpressionUtils.bind(bindings, row, cell);
Properties bindings = ExpressionUtils.createBindings(project);
ExpressionUtils.bind(bindings, row, cell); Object value = _evaluable.evaluate(bindings);
if (value != null) {
Object value = _evaluable.evaluate(bindings); if (value.getClass().isArray()) {
if (value != null) { Object[] a = (Object[]) value;
if (value.getClass().isArray()) { for (Object v : a) {
Object[] a = (Object[]) value; if (checkValue(v instanceof String ? ((String) v) : v.toString())) {
for (Object v : a) { return true;
if (checkValue(v instanceof String ? ((String) v) : v.toString())) {
return true;
}
}
} else {
if (checkValue(value instanceof String ? ((String) value) : value.toString())) {
return true;
}
} }
} }
} else {
if (checkValue(value instanceof String ? ((String) value) : value.toString())) {
return true;
}
} }
} }
return false; return false;

View File

@ -87,6 +87,7 @@ public abstract class Command {
} }
protected void respondException(HttpServletResponse response, Exception e) throws IOException { protected void respondException(HttpServletResponse response, Exception e) throws IOException {
e.printStackTrace();
try { try {
JSONObject o = new JSONObject(); JSONObject o = new JSONObject();
o.put("code", "error"); o.put("code", "error");

View File

@ -57,17 +57,14 @@ public class PreviewExpressionCommand extends Command {
int rowIndex = rowIndices.getInt(i); int rowIndex = rowIndices.getInt(i);
if (rowIndex >= 0 && rowIndex < project.rows.size()) { if (rowIndex >= 0 && rowIndex < project.rows.size()) {
Row row = project.rows.get(rowIndex); Row row = project.rows.get(rowIndex);
if (cellIndex < row.cells.size()) { Cell cell = row.getCell(cellIndex);
Cell cell = row.cells.get(cellIndex);
if (cell != null && cell.value != null) { ExpressionUtils.bind(bindings, row, cell);
ExpressionUtils.bind(bindings, row, cell);
try {
try { result = eval.evaluate(bindings);
result = eval.evaluate(bindings); } catch (Exception e) {
} catch (Exception e) { // ignore
// ignore
}
}
} }
} }

View File

@ -22,8 +22,13 @@ public class ExpressionUtils {
bindings.put("row", row); bindings.put("row", row);
bindings.put("cells", row.getField("cells", bindings)); bindings.put("cells", row.getField("cells", bindings));
bindings.put("cell", cell); if (cell == null) {
bindings.put("value", cell.value); bindings.remove("cell");
bindings.remove("value");
} else {
bindings.put("cell", cell);
bindings.put("value", cell.value);
}
} }
static public boolean isBlank(Object o) { static public boolean isBlank(Object o) {

View File

@ -109,16 +109,17 @@ public class ColumnAdditionOperation extends EngineDependentOperation {
@Override @Override
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) { public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
if (cellIndex < row.cells.size()) { Cell cell = row.getCell(cellIndex);
Cell cell = row.cells.get(cellIndex);
if (cell.value != null) { ExpressionUtils.bind(bindings, row, cell);
ExpressionUtils.bind(bindings, row, cell);
Object v = eval.evaluate(bindings);
Cell newCell = new Cell(eval.evaluate(bindings), null); if (v != null) {
Cell newCell = new Cell(v, null);
cellsAtRows.add(new CellAtRow(rowIndex, newCell));
} cellsAtRows.add(new CellAtRow(rowIndex, newCell));
} }
return false; return false;
} }
}.init(_baseCellIndex, bindings, cellsAtRows, eval); }.init(_baseCellIndex, bindings, cellsAtRows, eval);

View File

@ -7,6 +7,7 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.history.Change; import com.metaweb.gridworks.history.Change;
import com.metaweb.gridworks.history.HistoryEntry; import com.metaweb.gridworks.history.HistoryEntry;
import com.metaweb.gridworks.model.AbstractOperation; import com.metaweb.gridworks.model.AbstractOperation;
@ -68,7 +69,7 @@ public class MultiValueCellJoinOperation implements AbstractOperation {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
for (int r3 = r; r3 < r2; r3++) { for (int r3 = r; r3 < r2; r3++) {
Object value = project.rows.get(r3).getCellValue(_cellIndex); Object value = project.rows.get(r3).getCellValue(_cellIndex);
if (value != null) { if (!ExpressionUtils.isBlank(value)) {
if (sb.length() > 0) { if (sb.length() > 0) {
sb.append(_separator); sb.append(_separator);
} }

View File

@ -63,17 +63,18 @@ public class TextTransformOperation extends EngineDependentMassCellOperation {
@Override @Override
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) { public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
if (cellIndex < row.cells.size()) { Cell cell = row.getCell(cellIndex);
Cell cell = row.cells.get(cellIndex);
if (cell.value != null) { ExpressionUtils.bind(bindings, row, cell);
ExpressionUtils.bind(bindings, row, cell);
Object v = eval.evaluate(bindings);
Cell newCell = new Cell(eval.evaluate(bindings), cell.recon); if ((cell != null && cell.value != null) || v != null) {
Cell newCell = new Cell(v, cell.recon);
CellChange cellChange = new CellChange(rowIndex, cellIndex, cell, newCell);
cellChanges.add(cellChange); CellChange cellChange = new CellChange(rowIndex, cellIndex, cell, newCell);
} cellChanges.add(cellChange);
} }
return false; return false;
} }
}.init(_cellIndex, bindings, cellChanges, eval); }.init(_cellIndex, bindings, cellChanges, eval);

View File

@ -1 +1 @@
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Gridlock</title> <link type="text/css" rel="stylesheet" href="http://freebaselibs.com/static/suggest/1.0.3/suggest.min.css" /> <link type="text/css" rel="stylesheet" href="externals/jquery-ui/css/ui-lightness/jquery-ui-1.7.2.custom.css" /> <link rel="stylesheet" href="/styles/common.css" /> <link rel="stylesheet" href="/styles/project.css" /> <link rel="stylesheet" href="/styles/history.css" /> <link rel="stylesheet" href="/styles/browsing.css" /> <link rel="stylesheet" href="/styles/process.css" /> <link rel="stylesheet" href="/styles/expression-preview-dialog.css" /> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script> <script type="text/javascript" src="http://freebaselibs.com/static/suggest/1.0.3/suggest.min.js"></script> <script type="text/javascript" src="externals/jquery-ui/jquery-ui-1.7.2.custom.min.js"></script> <script type="text/javascript" src="scripts/util/misc.js"></script> <script type="text/javascript" src="scripts/util/url.js"></script> <script type="text/javascript" src="scripts/util/string.js"></script> <script type="text/javascript" src="scripts/util/ajax.js"></script> <script type="text/javascript" src="scripts/util/menu.js"></script> <script type="text/javascript" src="scripts/util/dialog.js"></script> <script type="text/javascript" src="scripts/project.js"></script> <script type="text/javascript" src="scripts/project/list-facet.js"></script> <script type="text/javascript" src="scripts/project/range-facet.js"></script> <script type="text/javascript" src="scripts/project/text-search-facet.js"></script> <script type="text/javascript" src="scripts/project/browsing-engine.js"></script> <script type="text/javascript" src="scripts/project/data-table-view.js"></script> <script type="text/javascript" src="scripts/project/history-widget.js"></script> <script type="text/javascript" src="scripts/project/process-widget.js"></script> <script type="text/javascript" src="scripts/project/recon-dialog.js"></script> <script type="text/javascript" src="scripts/project/expression-preview-dialog.js"></script> </head> <body> <div id="header"> <h1 id="title"><a href="./index.html">Gridworks</a> &raquo; </h1> </div> <div id="body"> Loading ... </div> </body> </html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Gridlock</title> <link type="text/css" rel="stylesheet" href="http://freebaselibs.com/static/suggest/1.0.3/suggest.min.css" /> <link type="text/css" rel="stylesheet" href="externals/jquery-ui/css/ui-lightness/jquery-ui-1.7.2.custom.css" /> <link rel="stylesheet" href="/styles/common.css" /> <link rel="stylesheet" href="/styles/menu.css" /> <link rel="stylesheet" href="/styles/dialog.css" /> <link rel="stylesheet" href="/styles/project.css" /> <link rel="stylesheet" href="/styles/data-table-view.css" /> <link rel="stylesheet" href="/styles/history.css" /> <link rel="stylesheet" href="/styles/browsing.css" /> <link rel="stylesheet" href="/styles/process.css" /> <link rel="stylesheet" href="/styles/expression-preview-dialog.css" /> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script> <script type="text/javascript" src="http://freebaselibs.com/static/suggest/1.0.3/suggest.min.js"></script> <script type="text/javascript" src="externals/jquery-ui/jquery-ui-1.7.2.custom.min.js"></script> <script type="text/javascript" src="scripts/util/misc.js"></script> <script type="text/javascript" src="scripts/util/url.js"></script> <script type="text/javascript" src="scripts/util/string.js"></script> <script type="text/javascript" src="scripts/util/ajax.js"></script> <script type="text/javascript" src="scripts/util/menu.js"></script> <script type="text/javascript" src="scripts/util/dialog.js"></script> <script type="text/javascript" src="scripts/project.js"></script> <script type="text/javascript" src="scripts/project/list-facet.js"></script> <script type="text/javascript" src="scripts/project/range-facet.js"></script> <script type="text/javascript" src="scripts/project/text-search-facet.js"></script> <script type="text/javascript" src="scripts/project/browsing-engine.js"></script> <script type="text/javascript" src="scripts/project/data-table-view.js"></script> <script type="text/javascript" src="scripts/project/history-widget.js"></script> <script type="text/javascript" src="scripts/project/process-widget.js"></script> <script type="text/javascript" src="scripts/project/recon-dialog.js"></script> <script type="text/javascript" src="scripts/project/expression-preview-dialog.js"></script> <script type="text/javascript" src="scripts/project/schema-alignment.js"></script> </head> <body> <div id="header"> <div id="path"><a class="app-path-section" href="./index.html">Gridworks</a> &raquo; </div> </div> <div id="body"> <div id="loading-message"><img src="images/large-spinner.gif" /> starting up ...</div> </div> </body> </html>

View File

@ -15,7 +15,8 @@ $(onLoad);
function initializeUI() { function initializeUI() {
document.title = theProject.metadata.name + " - Gridworks"; document.title = theProject.metadata.name + " - Gridworks";
$('<span></span>').text(theProject.metadata.name).appendTo($("#title")); $('<span></span>').text(theProject.metadata.name).addClass("app-path-section").appendTo($("#path"));
$('<span></span>').text(" project").appendTo($("#path"));
var body = $("#body").empty(); var body = $("#body").empty();

View File

@ -326,6 +326,15 @@ DataTableView.prototype._createMenuForAllColumns = function(elmt) {
} }
}, },
{}, {},
{
label: "Automatically Align Schemas with Freebase ...",
click: function() { self._doAutoSchemaAlignment(); }
},
{
label: "Edit Schema Alignment ...",
click: function() { }
},
{},
{ {
label: "Export Filtered Rows", label: "Export Filtered Rows",
click: function() { self._doExportRows(); } click: function() { self._doExportRows(); }
@ -336,11 +345,51 @@ DataTableView.prototype._createMenuForAllColumns = function(elmt) {
DataTableView.prototype._createMenuForColumnHeader = function(column, index, elmt) { DataTableView.prototype._createMenuForColumnHeader = function(column, index, elmt) {
self = this; self = this;
MenuSystem.createAndShowStandardMenu([ MenuSystem.createAndShowStandardMenu([
{
label: "Edit",
submenu: [
{ "heading" : "Cell Content Transformations" },
{
label: "To Titlecase",
click: function() { self._doTextTransform(column, "toTitlecase(value)"); }
},
{
label: "To Uppercase",
click: function() { self._doTextTransform(column, "toUppercase(value)"); }
},
{
label: "To Lowercase",
click: function() { self._doTextTransform(column, "toLowercase(value)"); }
},
{},
{
label: "Custom Expression ...",
click: function() { self._doTextTransformPrompt(column); }
},
{ "heading" : "Column Operations" },
{
label: "Add Column Based on This Column ...",
click: function() { self._doAddColumn(column, index, "value"); }
},
{
label: "Remove This Column",
click: function() { self._doRemoveColumn(column, index); }
},
{ "heading" : "Advanced Transformations" },
{
label: "Split Multi-Value Cells ...",
click: function() { self._doSplitMultiValueCells(column); }
},
{
label: "Join Multi-Value Cells ...",
click: function() { self._doJoinMultiValueCells(column); }
}
]
},
{ {
label: "Filter", label: "Filter",
tooltip: "Filter rows by this column's cell content or characteristics", tooltip: "Filter rows by this column's cell content or characteristics",
submenu: [ submenu: [
{ "heading" : "On Cell Content" },
{ {
label: "Text Facet", label: "Text Facet",
click: function() { click: function() {
@ -354,6 +403,11 @@ DataTableView.prototype._createMenuForColumnHeader = function(column, index, elm
); );
} }
}, },
{
label: "Custom Text Facet ...",
click: function() { self._doFilterByExpressionPrompt(column, "value", "list"); }
},
{},
{ {
label: "Numeric Facet", label: "Numeric Facet",
click: function() { click: function() {
@ -372,10 +426,6 @@ DataTableView.prototype._createMenuForColumnHeader = function(column, index, elm
); );
} }
}, },
{
label: "Custom Text Facet ...",
click: function() { self._doFilterByExpressionPrompt(column, "value", "list"); }
},
{ {
label: "Custom Numeric Facet ...", label: "Custom Numeric Facet ...",
click: function() { self._doFilterByExpressionPrompt(column, "value", "range"); } click: function() { self._doFilterByExpressionPrompt(column, "value", "range"); }
@ -408,8 +458,82 @@ DataTableView.prototype._createMenuForColumnHeader = function(column, index, elm
} }
); );
} }
}
]
},
{
label: "View",
tooltip: "Collapse/expand columns to make viewing the data more convenient",
submenu: [
{
label: "Collapse This Column",
click: function() {
theProject.columnModel.columns[index].collapsed = true;
self.render();
}
}, },
{ "heading" : "By Reconciliation Features" }, {
label: "Collapse All Other Columns",
click: function() {
for (var i = 0; i < theProject.columnModel.columns.length; i++) {
if (i != index) {
theProject.columnModel.columns[i].collapsed = true;
}
}
self.render();
}
},
{
label: "Collapse All Columns To Right",
click: function() {
for (var i = index + 1; i < theProject.columnModel.columns.length; i++) {
theProject.columnModel.columns[i].collapsed = true;
}
self.render();
}
}
]
},
{},
{
label: "Reconcile",
tooltip: "Match this column's cells to topics on Freebase",
submenu: [
{
label: "Start Reconciling ...",
tooltip: "Reconcile text in this column with topics on Freebase",
click: function() {
new ReconDialog(index);
}
},
{},
{
label: "Approve Best Candidates",
tooltip: "Approve best reconciliaton candidate per cell in this column for all current filtered rows",
click: function() {
self._doApproveBestCandidates(column);
}
},
{
label: "Approve As New Topics",
tooltip: "Set to create new topics for cells in this column for all current filtered rows",
click: function() {
self._doApproveNewTopics(column);
}
},
{
label: "Discard Reconciliation Results",
tooltip: "Discard reconciliaton results in this column for all current filtered rows",
click: function() {
self._doDiscardReconResults(column);
}
}
]
},
{
label: "Reconcile Filter",
tooltip: "Match this column's cells to topics on Freebase",
submenu: [
{ {
label: "By Judgment", label: "By Judgment",
click: function() { click: function() {
@ -531,116 +655,6 @@ DataTableView.prototype._createMenuForColumnHeader = function(column, index, elm
} }
} }
] ]
},
{
label: "View",
tooltip: "Collapse/expand columns to make viewing the data more convenient",
submenu: [
{
label: "Collapse This Column",
click: function() {
theProject.columnModel.columns[index].collapsed = true;
self.render();
}
},
{
label: "Collapse All Other Columns",
click: function() {
for (var i = 0; i < theProject.columnModel.columns.length; i++) {
if (i != index) {
theProject.columnModel.columns[i].collapsed = true;
}
}
self.render();
}
},
{
label: "Collapse All Columns To Right",
click: function() {
for (var i = index + 1; i < theProject.columnModel.columns.length; i++) {
theProject.columnModel.columns[i].collapsed = true;
}
self.render();
}
}
]
},
{},
{
label: "Edit",
submenu: [
{ "heading" : "Column Operations" },
{
label: "Add Column Based on This Column",
click: function() { self._doAddColumn(column, index, "value"); }
},
{
label: "Remove This Column",
click: function() { self._doRemoveColumn(column, index); }
},
{ "heading" : "Cell Content Transformations" },
{
label: "To Titlecase",
click: function() { self._doTextTransform(column, "toTitlecase(value)"); }
},
{
label: "To Uppercase",
click: function() { self._doTextTransform(column, "toUppercase(value)"); }
},
{
label: "To Lowercase",
click: function() { self._doTextTransform(column, "toLowercase(value)"); }
},
{},
{
label: "Custom Expression ...",
click: function() { self._doTextTransformPrompt(column); }
},
{ "heading" : "Advanced Transformations" },
{
label: "Join Multi-Value Cells ...",
click: function() { self._doJoinMultiValueCells(column); }
},
{
label: "Split Multi-Value Cells ...",
click: function() { self._doSplitMultiValueCells(column); }
}
]
},
{
label: "Reconcile",
tooltip: "Match this column's cells to topics on Freebase",
submenu: [
{
label: "Start Reconciling ...",
tooltip: "Reconcile text in this column with topics on Freebase",
click: function() {
new ReconDialog(index);
}
},
{},
{
label: "Approve Best Candidates",
tooltip: "Approve best reconciliaton candidate per cell in this column for all current filtered rows",
click: function() {
self._doApproveBestCandidates(column);
}
},
{
label: "Approve As New Topics",
tooltip: "Set to create new topics for cells in this column for all current filtered rows",
click: function() {
self._doApproveNewTopics(column);
}
},
{
label: "Discard Reconciliation Results",
tooltip: "Discard reconciliaton results in this column for all current filtered rows",
click: function() {
self._doDiscardReconResults(column);
}
}
]
} }
], elmt, { width: "120px", horizontal: false }); ], elmt, { width: "120px", horizontal: false });
}; };
@ -850,3 +864,7 @@ DataTableView.prototype._doExportRows = function() {
document.body.removeChild(form); document.body.removeChild(form);
}; };
DataTableView.prototype._doAutoSchemaAlignment = function() {
SchemaAlignment.autoAlign();
};

View File

@ -20,11 +20,12 @@ ExpressionPreviewDialog.prototype._createDialog = function(title) {
var body = $('<div></div>').addClass("dialog-body").appendTo(frame); var body = $('<div></div>').addClass("dialog-body").appendTo(frame);
var footer = $('<div></div>').addClass("dialog-footer").appendTo(frame); var footer = $('<div></div>').addClass("dialog-footer").appendTo(frame);
$('<p></p>').text("Expression:").appendTo(body); var p = $('<p></p>').text("Expression: ").appendTo(body);
this._input = $('<input />').width("400px").keypress(function(){ this._input = $('<input />').width("400px").keypress(function(){
self._scheduleUpdate(); self._scheduleUpdate();
}).appendTo($('<p></p>').appendTo(body)); }).appendTo(p);
this._preview = $('<div></div>').addClass("expression-preview-container").appendTo(body); this._preview = $('<div></div>').addClass("expression-preview-container").appendTo(body);
$('<button></button>').html("&nbsp;&nbsp;OK&nbsp;&nbsp;").click(function() { $('<button></button>').html("&nbsp;&nbsp;OK&nbsp;&nbsp;").click(function() {
@ -40,7 +41,7 @@ ExpressionPreviewDialog.prototype._createDialog = function(title) {
this._input[0].value = this._expression; this._input[0].value = this._expression;
this._input[0].focus(); this._input[0].focus();
this._renderPreview(this._expression); this._update();
}; };
ExpressionPreviewDialog.prototype._scheduleUpdate = function() { ExpressionPreviewDialog.prototype._scheduleUpdate = function() {
@ -75,23 +76,34 @@ ExpressionPreviewDialog.prototype._update = function() {
ExpressionPreviewDialog.prototype._renderPreview = function(expression) { ExpressionPreviewDialog.prototype._renderPreview = function(expression) {
var container = this._preview.empty(); var container = this._preview.empty();
var table = $('<table></table>').appendTo(container)[0]; var table = $('<table width="100%"></table>').appendTo(container)[0];
var tr = table.insertRow(0); var tr = table.insertRow(0);
$(tr.insertCell(0)).addClass("expression-preview-heading").text("value"); $(tr.insertCell(0)).addClass("expression-preview-heading").text("row");
$(tr.insertCell(1)).addClass("expression-preview-heading").text(expression); $(tr.insertCell(1)).addClass("expression-preview-heading").text("value");
$(tr.insertCell(2)).addClass("expression-preview-heading").text(expression);
var renderValue = function(td, v) {
if (v != null) {
td.html($.isArray(v) ? JSON.stringify(v) : v);
} else {
$('<span>(null)</span>').addClass("expression-preview-empty").appendTo(td);
}
};
for (var i = 0; i < this._values.length; i++) { for (var i = 0; i < this._values.length; i++) {
var tr = table.insertRow(table.rows.length); var tr = table.insertRow(table.rows.length);
$(tr.insertCell(0)).html(this._values[i]); $(tr.insertCell(0)).attr("width", "1%").html((this._rowIndices[i] + 1) + ".");
renderValue($(tr.insertCell(1)), this._values[i]);
var tdValue = $(tr.insertCell(2));
if (this._results != null) { if (this._results != null) {
var v = this._results[i]; var v = this._results[i];
if (v != null) { renderValue(tdValue, v);
if ($.isArray(v)) { } else {
v = JSON.stringify(v); $('<span>(error)</span>').addClass("expression-preview-empty").appendTo(tdValue);
}
$(tr.insertCell(1)).html(v);
}
} }
} }
}; };

View File

@ -19,16 +19,16 @@ HistoryWidget.prototype._render = function() {
this._div.empty(); this._div.empty();
$('<h3>History for Undo/Redo</h3>').appendTo(this._div); $('<h3>Undo/Redo History</h3>').appendTo(this._div);
var bodyDiv = $('<div></div>').addClass("history-panel-body").appendTo(this._div); var bodyDiv = $('<div></div>').addClass("history-panel-body").appendTo(this._div);
bodyDiv.mouseover(function() { bodyDiv.mouseenter(function(evt) {
this.style.height = "300px"; $(this).addClass("history-panel-body-expanded");
}).mouseout(function() { }).mouseleave(function(evt) {
this.style.height = "50px"; $(this).removeClass("history-panel-body-expanded");
autoscroll();
}); });
var lastPast = null;
var renderEntry = function(container, entry, lastDoneID, title) { var renderEntry = function(container, entry, lastDoneID, title) {
var a = $('<a href="javascript:{}"></a>').appendTo(container); var a = $('<a href="javascript:{}"></a>').appendTo(container);
a.addClass("history-entry").html(entry.description).attr("title", title).click(function(evt) { a.addClass("history-entry").html(entry.description).attr("title", title).click(function(evt) {
@ -43,11 +43,11 @@ HistoryWidget.prototype._render = function() {
} else { } else {
for (var i = 0; i < this._data.past.length; i++) { for (var i = 0; i < this._data.past.length; i++) {
var entry = this._data.past[i]; var entry = this._data.past[i];
lastPast = renderEntry(divPast, entry, i == 0 ? 0 : this._data.past[i - 1].id, "Undo to here"); renderEntry(divPast, entry, i == 0 ? 0 : this._data.past[i - 1].id, "Undo to here");
} }
} }
$('<div></div>').text("done upto here").addClass("history-now").appendTo(bodyDiv); var divNow = $('<div></div>').text("done upto here").addClass("history-now").appendTo(bodyDiv);
var divFuture = $('<div></div>').addClass("history-future").appendTo(bodyDiv); var divFuture = $('<div></div>').addClass("history-future").appendTo(bodyDiv);
if (this._data.future.length == 0) { if (this._data.future.length == 0) {
@ -59,9 +59,10 @@ HistoryWidget.prototype._render = function() {
} }
} }
if (lastPast != null) { var autoscroll = function() {
bodyDiv[0].scrollTop = lastPast[0].offsetTop; bodyDiv[0].scrollTop = divNow[0].offsetTop + divNow[0].offsetHeight - bodyDiv[0].offsetHeight;
} };
autoscroll();
}; };
HistoryWidget.prototype._onClickHistoryEntry = function(evt, entry, lastDoneID) { HistoryWidget.prototype._onClickHistoryEntry = function(evt, entry, lastDoneID) {

View File

@ -0,0 +1,24 @@
var SchemaAlignment = {};
SchemaAlignment.autoAlign = function() {
var protograph = {};
var columns = theProject.columnModel.columns;
var typedColumns = [];
var candidates = [];
for (var c = 0; c < columns.length; c++) {
var column = columns[c];
if ("reconConfig" in column && column.reconConfig != null) {
typedColumns.push(column);
}
candidates.push({
status: "unbound",
index: c,
column: column
})
}
};

View File

@ -78,8 +78,13 @@ MenuSystem.createAndShowStandardMenu = function(items, elmt, options) {
if ("label" in item) { if ("label" in item) {
var menuItem = MenuSystem.createMenuItem().appendTo(menu); var menuItem = MenuSystem.createMenuItem().appendTo(menu);
if ("submenu" in item) { if ("submenu" in item) {
menuItem.html('<table width="100%" cellspacing="0" cellpadding="0"><tr><td>' + item.label + '</td><td width="1%"><img src="/images/right-arrow.png" /></td></tr></table>'); menuItem.html(
menuItem.mouseover(function() { '<table width="100%" cellspacing="0" cellpadding="0" class="menu-item-layout"><tr>' +
'<td>' + item.label + '</td>' +
'<td width="1%"><img src="/images/right-arrow.png" /></td>' +
'</tr></table>'
);
menuItem.mouseenter(function() {
MenuSystem.dismissUntil(level); MenuSystem.dismissUntil(level);
menuItem.addClass("menu-expanded"); menuItem.addClass("menu-expanded");
@ -100,7 +105,7 @@ MenuSystem.createAndShowStandardMenu = function(items, elmt, options) {
if ("tooltip" in item) { if ("tooltip" in item) {
menuItem.attr("title", item.tooltip); menuItem.attr("title", item.tooltip);
} }
menuItem.mouseover(function() { menuItem.mouseenter(function() {
MenuSystem.dismissUntil(level); MenuSystem.dismissUntil(level);
}); });
} }

View File

@ -18,8 +18,19 @@ tr, td {
} }
#header { #header {
padding: 10px 20px; padding: 5px 20px;
background: #eee; background: #666;
color: #eee;
}
#header .app-path-section {
font-weight: bold;
}
#header a.app-path-section {
text-decoration: none;
color: #eee;
}
#header a.app-path-section:hover {
text-decoration: underline;
} }
#header h1 { #header h1 {
@ -45,119 +56,10 @@ a.inaction {
color: #ccc; color: #ccc;
} }
.menu-overlay { a img {
background: black;
opacity: 0.3;
position: fixed;
padding: 0px;
margin: 0px;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
}
.menu-container {
position: absolute;
width: 250px;
background: white;
padding: 1px;
border: 1px solid #ddd;
}
.menu-container hr {
height: 1px;
border: none;
border-top: 1px solid #ccc;
padding: 0px;
margin: 2px 0px;
}
a.menu-item {
display: block;
padding: 5px 7px;
text-decoration: none;
color: black;
white-space: pre;
}
a.menu-item:hover {
color: #44a;
background: #eee;
}
a.menu-item.menu-expanded {
background: #ddd;
}
a.menu-item img {
border: none; border: none;
} }
.menu-section { img {
padding: 2px 7px; vertical-align: middle;
background: #aaa;
color: white;
font-weight: bold;
}
.dialog-overlay {
background: black;
opacity: 0.3;
position: fixed;
padding: 0px;
margin: 0px;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
}
.dialog-overlay2 {
position: fixed;
padding: 0px;
margin: 0px;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
background: black;
opacity: 0.01;
}
.dialog-container {
position: fixed;
padding: 0px;
margin: 0px;
left: 0px;
width: 100%;
text-align: center;
}
.dialog-frame {
margin: 0 auto;
text-align: left;
background: white;
border: 1px solid #aaa;
padding: 2px;
}
.dialog-header {
background: #ccc;
padding: 5px 10px;
font-weight: bold;
}
.dialog-body {
padding: 10px;
}
.dialog-footer {
background: #ddd;
padding: 5px 10px;
text-align: right;
}
.dialog-footer button {
margin-left: 5px;
} }

View File

@ -0,0 +1,43 @@
.data-table-container {
border: 1px solid #ccc;
overflow-x: auto;
}
table.data-table td {
padding: 2px 5px;
}
table.data-table tr.odd {
}
table.data-table tr.even {
background: #eee;
}
table.data-table tr.contextual {
opacity: 0.2;
}
table.data-table td.column-header {
background: #ddd;
cursor: pointer;
padding: 5px 5px;
border-bottom: 2px solid #aaa;
white-space: pre;
font-weight: bold;
}
table.column-header-layout td {
padding: 0px;
font-weight: bold;
}
img.column-header-menu {
}
.viewPanel-summary {
}
.viewPanel-pagingControls {
text-align: center;
margin: 1em 0;
}

View File

@ -0,0 +1,60 @@
.dialog-overlay {
background: black;
opacity: 0.3;
position: fixed;
padding: 0px;
margin: 0px;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
}
.dialog-overlay2 {
position: fixed;
padding: 0px;
margin: 0px;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
background: black;
opacity: 0.01;
}
.dialog-container {
position: fixed;
padding: 0px;
margin: 0px;
left: 0px;
width: 100%;
text-align: center;
}
.dialog-frame {
margin: 0 auto;
text-align: left;
background: white;
border: 1px solid #aaa;
padding: 2px;
}
.dialog-header {
background: #ccc;
padding: 5px 10px;
font-weight: bold;
}
.dialog-body {
padding: 10px;
}
.dialog-footer {
background: #ddd;
padding: 5px 10px;
text-align: right;
}
.dialog-footer button {
margin-left: 5px;
}

View File

@ -15,3 +15,6 @@ td.expression-preview-heading {
font-weight: bold; font-weight: bold;
} }
.expression-preview-empty {
color: #aaa;
}

View File

@ -2,21 +2,28 @@
position: absolute; position: absolute;
top: -1px; top: -1px;
right: 20px; right: 20px;
width: 200px; width: 250px;
background: #fffee0; background: #fffee0;
border: 1px solid #ccc; border: 1px solid #666;
z-index: 10; z-index: 10;
-moz-border-radius-bottomleft: 20px;
padding-bottom: 10px;
} }
.history-panel h3 { .history-panel h3 {
margin: 0; margin: 0;
padding: 3px; padding: 3px;
background: #888; background: #aaa;
color: #eee; color: #eee;
font-size: 100%; font-size: 100%;
text-align: center;
} }
.history-panel-body { .history-panel-body {
padding: 2px; padding: 2px;
height: 50px; height: 50px;
overflow: hidden;
}
.history-panel-body.history-panel-body-expanded {
height: 300px;
overflow: auto; overflow: auto;
} }
.history-panel-message { .history-panel-message {

View File

@ -0,0 +1,59 @@
.menu-overlay {
background: black;
opacity: 0.15;
position: fixed;
padding: 0px;
margin: 0px;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
}
.menu-container {
position: absolute;
width: 250px;
background: white;
padding: 1px;
border: 1px solid #ddd;
}
.menu-container hr {
height: 1px;
border: none;
border-top: 1px solid #ccc;
padding: 0px;
margin: 2px 0px;
}
a.menu-item {
display: block;
padding: 5px 7px;
text-decoration: none;
color: black;
white-space: pre;
}
a.menu-item:hover {
color: #44a;
background: #eee;
}
a.menu-item.menu-expanded {
background: #ddd;
}
a.menu-item img {
border: none;
}
table.menu-item-layout td {
vertical-align: middle;
}
.menu-section {
padding: 2px 7px;
background: #aaa;
color: white;
font-weight: bold;
}

View File

@ -1,44 +1,8 @@
.data-table-container { #loading-message {
border: 1px solid #ccc;
overflow-x: auto;
}
table.data-table td {
padding: 2px 5px;
}
table.data-table tr.odd {
}
table.data-table tr.even {
background: #eee;
}
table.data-table tr.contextual {
opacity: 0.2;
}
table.data-table td.column-header {
background: #ddd;
cursor: pointer;
padding: 5px 5px;
border-bottom: 2px solid #aaa;
white-space: pre;
font-weight: bold;
}
table.column-header-layout td {
padding: 0px;
vertical-align: middle;
font-weight: bold;
}
img.column-header-menu {
}
.viewPanel-summary {
}
.viewPanel-pagingControls {
text-align: center; text-align: center;
margin: 1em 0; font-size: 300%;
color: #faa;
margin: 1in;
font-style: italic;
} }