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:
parent
1b16ef0c5c
commit
fed3c87fa6
@ -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.
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 |
@ -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>' +
|
||||
@ -260,6 +262,27 @@ DataTableView.prototype._renderDataTable = function(table) {
|
||||
"json"
|
||||
);
|
||||
});
|
||||
|
||||
var tdFlag = tr.insertCell(tr.cells.length);
|
||||
var flag = $('<a href="javascript:{}"> </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) {
|
||||
@ -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 });
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user