Added row flagging support. Fixed bug in row star change: starring or unstarring one row wasn't undo-able previously.

git-svn-id: http://google-refine.googlecode.com/svn/trunk@547 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
David Huynh 2010-04-26 01:08:56 +00:00
parent 1b16ef0c5c
commit fed3c87fa6
12 changed files with 289 additions and 13 deletions

View File

@ -106,3 +106,9 @@ licenses/icu4j.LICENSE.txt
licenses/json.LICENSE.txt
json
Others
------
Flag icon
http://pixel-mixer.com/category/free-icons/

Binary file not shown.

View File

@ -38,9 +38,27 @@ public class AnnotateOneRowCommand extends Command {
);
performProcessAndRespond(request, response, project, process);
} else {
respond(response, "{ \"code\" : \"error\", \"message\" : \"invalid command parameters\" }");
return;
}
String flaggedString = request.getParameter("flagged");
if (flaggedString != null) {
boolean flagged = "true".endsWith(flaggedString);
String description = (flagged ? "Flag row " : "Unflag row ") + (rowIndex + 1);
FlagOneRowProcess process = new FlagOneRowProcess(
project,
description,
rowIndex,
flagged
);
performProcessAndRespond(request, response, project, process);
return;
}
respond(response, "{ \"code\" : \"error\", \"message\" : \"invalid command parameters\" }");
} catch (Exception e) {
respondException(response, e);
}
@ -71,4 +89,29 @@ public class AnnotateOneRowCommand extends Command {
);
}
}
protected static class FlagOneRowProcess extends QuickHistoryEntryProcess {
final int rowIndex;
final boolean flagged;
FlagOneRowProcess(
Project project,
String briefDescription,
int rowIndex,
boolean flagged
) {
super(project, briefDescription);
this.rowIndex = rowIndex;
this.flagged = flagged;
}
protected HistoryEntry createHistoryEntry() throws Exception {
return new HistoryEntry(
_project,
(flagged ? "Flag row " : "Unflag row ") + (rowIndex + 1),
null,
new RowStarChange(rowIndex, flagged)
);
}
}
}

View File

@ -7,6 +7,7 @@ import org.json.JSONObject;
import com.metaweb.gridworks.commands.EngineDependentCommand;
import com.metaweb.gridworks.model.AbstractOperation;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.operations.RowFlagOperation;
import com.metaweb.gridworks.operations.RowStarOperation;
public class AnnotateRowsCommand extends EngineDependentCommand {
@ -21,6 +22,13 @@ public class AnnotateRowsCommand extends EngineDependentCommand {
return new RowStarOperation(engineConfig, starred);
}
String flaggedString = request.getParameter("flagged");
if (flaggedString != null) {
boolean flagged = "true".endsWith(flaggedString);
return new RowFlagOperation(engineConfig, flagged);
}
return null;
}
}

View File

@ -0,0 +1,69 @@
package com.metaweb.gridworks.model.changes;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.Writer;
import java.util.Properties;
import com.metaweb.gridworks.history.Change;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Row;
import com.metaweb.gridworks.util.Pool;
public class RowFlagChange implements Change {
final int rowIndex;
final boolean newFlagged;
Boolean oldFlagged = null;
public RowFlagChange(int rowIndex, boolean newFlagged) {
this.rowIndex = rowIndex;
this.newFlagged = newFlagged;
}
public void apply(Project project) {
Row row = project.rows.get(rowIndex);
if (oldFlagged == null) {
oldFlagged = row.flagged;
}
row.flagged = newFlagged;
}
public void revert(Project project) {
Row row = project.rows.get(rowIndex);
row.flagged = oldFlagged;
}
public void save(Writer writer, Properties options) throws IOException {
writer.write("row="); writer.write(Integer.toString(rowIndex)); writer.write('\n');
writer.write("newFlagged="); writer.write(Boolean.toString(newFlagged)); writer.write('\n');
writer.write("oldFlagged="); writer.write(Boolean.toString(oldFlagged)); writer.write('\n');
writer.write("/ec/\n"); // end of change marker
}
static public RowFlagChange load(LineNumberReader reader, Pool pool) throws Exception {
int row = -1;
boolean oldStarred = false;
boolean newStarred = false;
String line;
while ((line = reader.readLine()) != null && !"/ec/".equals(line)) {
int equal = line.indexOf('=');
CharSequence field = line.subSequence(0, equal);
String value = line.substring(equal + 1);
if ("row".equals(field)) {
row = Integer.parseInt(value);
} else if ("oldFlagged".equals(field)) {
oldStarred = Boolean.parseBoolean(value);
} else if ("newFlagged".equals(field)) {
oldStarred = Boolean.parseBoolean(value);
}
}
RowFlagChange change = new RowFlagChange(row, newStarred);
change.oldFlagged = oldStarred;
return change;
}
}

View File

@ -13,7 +13,7 @@ import com.metaweb.gridworks.util.Pool;
public class RowStarChange implements Change {
final int rowIndex;
final boolean newStarred;
boolean oldStarred;
Boolean oldStarred = null;
public RowStarChange(int rowIndex, boolean newStarred) {
this.rowIndex = rowIndex;
@ -22,8 +22,9 @@ public class RowStarChange implements Change {
public void apply(Project project) {
Row row = project.rows.get(rowIndex);
oldStarred = row.starred;
if (oldStarred == null) {
oldStarred = row.starred;
}
row.starred = newStarred;
}

View File

@ -38,6 +38,7 @@ public abstract class OperationRegistry {
register("row-removal", RowRemovalOperation.class);
register("row-star", RowStarOperation.class);
register("row-flag", RowFlagOperation.class);
register("save-protograph", SaveProtographOperation.class);
register("text-transform", TextTransformOperation.class);

View File

@ -0,0 +1,90 @@
package com.metaweb.gridworks.operations;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.browsing.Engine;
import com.metaweb.gridworks.browsing.FilteredRows;
import com.metaweb.gridworks.browsing.RowVisitor;
import com.metaweb.gridworks.history.Change;
import com.metaweb.gridworks.history.HistoryEntry;
import com.metaweb.gridworks.model.AbstractOperation;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Row;
import com.metaweb.gridworks.model.changes.MassChange;
import com.metaweb.gridworks.model.changes.RowFlagChange;
public class RowFlagOperation extends EngineDependentOperation {
final protected boolean _flagged;
static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception {
JSONObject engineConfig = obj.getJSONObject("engineConfig");
boolean flagged = obj.getBoolean("flagged");
return new RowFlagOperation(
engineConfig,
flagged
);
}
public RowFlagOperation(JSONObject engineConfig, boolean flagged) {
super(engineConfig);
_flagged = flagged;
}
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass()));
writer.key("description"); writer.value(getBriefDescription(null));
writer.key("engineConfig"); writer.value(getEngineConfig());
writer.key("flagged"); writer.value(_flagged);
writer.endObject();
}
protected String getBriefDescription(Project project) {
return (_flagged ? "Flag rows" : "Unflag rows");
}
protected HistoryEntry createHistoryEntry(Project project) throws Exception {
Engine engine = createEngine(project);
List<Change> changes = new ArrayList<Change>(project.rows.size());
FilteredRows filteredRows = engine.getAllFilteredRows(false);
filteredRows.accept(project, createRowVisitor(project, changes));
return new HistoryEntry(
project,
(_flagged ? "Flag" : "Unflag") + " " + changes.size() + " rows",
this,
new MassChange(changes, false)
);
}
protected RowVisitor createRowVisitor(Project project, List<Change> changes) throws Exception {
return new RowVisitor() {
List<Change> changes;
public RowVisitor init(List<Change> changes) {
this.changes = changes;
return this;
}
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
if (row.starred != _flagged) {
RowFlagChange change = new RowFlagChange(rowIndex, _flagged);
changes.add(change);
}
return false;
}
}.init(changes);
}
}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 778 B

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -122,7 +122,8 @@ DataTableView.prototype._renderDataTable = function(table) {
if (keys.length > 0) {
var tr = table.insertRow(table.rows.length);
tr.insertCell(0); // star
tr.insertCell(1); // row index
tr.insertCell(1); // flag
tr.insertCell(2); // row index
for (var c = 0; c < columns.length; c++) {
var td = tr.insertCell(tr.cells.length);
@ -143,7 +144,8 @@ DataTableView.prototype._renderDataTable = function(table) {
if (groups.length > 0) {
var tr = table.insertRow(table.rows.length);
tr.insertCell(0); // star
tr.insertCell(1); // row index
tr.insertCell(1); // flag
tr.insertCell(2); // row index
for (var c = 0; c < columns.length; c++) {
var foundGroup = false;
@ -197,7 +199,7 @@ DataTableView.prototype._renderDataTable = function(table) {
var trHead = table.insertRow(table.rows.length);
DOM.bind(
$(trHead.insertCell(trHead.cells.length))
.attr("colspan", "2")
.attr("colspan", "3")
.addClass("column-header")
.html(
'<table class="column-header-layout"><tr>' +
@ -261,6 +263,27 @@ DataTableView.prototype._renderDataTable = function(table) {
);
});
var tdFlag = tr.insertCell(tr.cells.length);
var flag = $('<a href="javascript:{}">&nbsp;</a>')
.addClass(row.flagged ? "data-table-flag-on" : "data-table-flag-off")
.appendTo(tdFlag)
.click(function() {
var newFlagged = !row.flagged;
Gridworks.postProcess(
"annotate-one-row",
{ row: row.i, flagged: newFlagged },
null,
{},
{ onDone: function(o) {
row.flagged = newFlagged;
renderRow(tr, r, row, even);
}
},
"json"
);
});
var tdIndex = tr.insertCell(tr.cells.length);
if ("j" in row) {
$(tr).addClass("record");
@ -345,6 +368,22 @@ DataTableView.prototype._createMenuForAllColumns = function(elmt) {
}
);
}
},
{
label: "Facet by Flag",
click: function() {
ui.browsingEngine.addFacet(
"list",
{
"name" : "Flagged Rows",
"columnName" : "",
"expression" : "row.flagged"
},
{
"scroll" : false
}
);
}
}
]
},
@ -364,7 +403,20 @@ DataTableView.prototype._createMenuForAllColumns = function(elmt) {
},
{},
{
label: "Remove Matching Rows",
label: "Flag Rows",
click: function() {
Gridworks.postProcess("annotate-rows", { "flagged" : "true" }, null, { rowMetadataChanged: true });
}
},
{
label: "Unflag Rows",
click: function() {
Gridworks.postProcess("annotate-rows", { "flagged" : "false" }, null, { rowMetadataChanged: true });
}
},
{},
{
label: "Remove All Matching Rows",
click: function() {
Gridworks.postProcess("remove-rows", {}, null, { rowMetadataChanged: true });
}

View File

@ -200,7 +200,7 @@ a.data-table-recon-match-similar:hover {
background-position: 0px -17px;
}
a.data-table-star-on, a.data-table-star-off {
a.data-table-star-on, a.data-table-star-off, a.data-table-flag-on, a.data-table-flag-off {
display: block;
width: 16px;
height: 16px;
@ -208,12 +208,18 @@ a.data-table-star-on, a.data-table-star-off {
background-repeat: no-repeat;
text-decoration: none;
}
a.data-table-star-on {
a.data-table-star-on, a.data-table-star-off:hover {
background-position: 0px 0px;
}
a.data-table-star-off {
a.data-table-star-off, a.data-table-star-on:hover {
background-position: -17px 0px;
}
a.data-table-flag-on, a.data-table-flag-off:hover {
background-position: 0px -17px;
}
a.data-table-flag-off, a.data-table-flag-on:hover {
background-position: -17px -17px;
}
.data-table-cell-editor {
border: 1px solid #ccc;