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
|
licenses/json.LICENSE.txt
|
||||||
json
|
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);
|
performProcessAndRespond(request, response, project, process);
|
||||||
} else {
|
return;
|
||||||
respond(response, "{ \"code\" : \"error\", \"message\" : \"invalid command parameters\" }");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
} catch (Exception e) {
|
||||||
respondException(response, 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.commands.EngineDependentCommand;
|
||||||
import com.metaweb.gridworks.model.AbstractOperation;
|
import com.metaweb.gridworks.model.AbstractOperation;
|
||||||
import com.metaweb.gridworks.model.Project;
|
import com.metaweb.gridworks.model.Project;
|
||||||
|
import com.metaweb.gridworks.operations.RowFlagOperation;
|
||||||
import com.metaweb.gridworks.operations.RowStarOperation;
|
import com.metaweb.gridworks.operations.RowStarOperation;
|
||||||
|
|
||||||
public class AnnotateRowsCommand extends EngineDependentCommand {
|
public class AnnotateRowsCommand extends EngineDependentCommand {
|
||||||
@ -21,6 +22,13 @@ public class AnnotateRowsCommand extends EngineDependentCommand {
|
|||||||
|
|
||||||
return new RowStarOperation(engineConfig, starred);
|
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;
|
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 {
|
public class RowStarChange implements Change {
|
||||||
final int rowIndex;
|
final int rowIndex;
|
||||||
final boolean newStarred;
|
final boolean newStarred;
|
||||||
boolean oldStarred;
|
Boolean oldStarred = null;
|
||||||
|
|
||||||
public RowStarChange(int rowIndex, boolean newStarred) {
|
public RowStarChange(int rowIndex, boolean newStarred) {
|
||||||
this.rowIndex = rowIndex;
|
this.rowIndex = rowIndex;
|
||||||
@ -22,8 +22,9 @@ public class RowStarChange implements Change {
|
|||||||
|
|
||||||
public void apply(Project project) {
|
public void apply(Project project) {
|
||||||
Row row = project.rows.get(rowIndex);
|
Row row = project.rows.get(rowIndex);
|
||||||
|
if (oldStarred == null) {
|
||||||
oldStarred = row.starred;
|
oldStarred = row.starred;
|
||||||
|
}
|
||||||
row.starred = newStarred;
|
row.starred = newStarred;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ public abstract class OperationRegistry {
|
|||||||
|
|
||||||
register("row-removal", RowRemovalOperation.class);
|
register("row-removal", RowRemovalOperation.class);
|
||||||
register("row-star", RowStarOperation.class);
|
register("row-star", RowStarOperation.class);
|
||||||
|
register("row-flag", RowFlagOperation.class);
|
||||||
|
|
||||||
register("save-protograph", SaveProtographOperation.class);
|
register("save-protograph", SaveProtographOperation.class);
|
||||||
register("text-transform", TextTransformOperation.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) {
|
if (keys.length > 0) {
|
||||||
var tr = table.insertRow(table.rows.length);
|
var tr = table.insertRow(table.rows.length);
|
||||||
tr.insertCell(0); // star
|
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++) {
|
for (var c = 0; c < columns.length; c++) {
|
||||||
var td = tr.insertCell(tr.cells.length);
|
var td = tr.insertCell(tr.cells.length);
|
||||||
@ -143,7 +144,8 @@ DataTableView.prototype._renderDataTable = function(table) {
|
|||||||
if (groups.length > 0) {
|
if (groups.length > 0) {
|
||||||
var tr = table.insertRow(table.rows.length);
|
var tr = table.insertRow(table.rows.length);
|
||||||
tr.insertCell(0); // star
|
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++) {
|
for (var c = 0; c < columns.length; c++) {
|
||||||
var foundGroup = false;
|
var foundGroup = false;
|
||||||
@ -197,7 +199,7 @@ DataTableView.prototype._renderDataTable = function(table) {
|
|||||||
var trHead = table.insertRow(table.rows.length);
|
var trHead = table.insertRow(table.rows.length);
|
||||||
DOM.bind(
|
DOM.bind(
|
||||||
$(trHead.insertCell(trHead.cells.length))
|
$(trHead.insertCell(trHead.cells.length))
|
||||||
.attr("colspan", "2")
|
.attr("colspan", "3")
|
||||||
.addClass("column-header")
|
.addClass("column-header")
|
||||||
.html(
|
.html(
|
||||||
'<table class="column-header-layout"><tr>' +
|
'<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:{}"> </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);
|
var tdIndex = tr.insertCell(tr.cells.length);
|
||||||
if ("j" in row) {
|
if ("j" in row) {
|
||||||
$(tr).addClass("record");
|
$(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() {
|
click: function() {
|
||||||
Gridworks.postProcess("remove-rows", {}, null, { rowMetadataChanged: true });
|
Gridworks.postProcess("remove-rows", {}, null, { rowMetadataChanged: true });
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ a.data-table-recon-match-similar:hover {
|
|||||||
background-position: 0px -17px;
|
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;
|
display: block;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
@ -208,12 +208,18 @@ a.data-table-star-on, a.data-table-star-off {
|
|||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
a.data-table-star-on {
|
a.data-table-star-on, a.data-table-star-off:hover {
|
||||||
background-position: 0px 0px;
|
background-position: 0px 0px;
|
||||||
}
|
}
|
||||||
a.data-table-star-off {
|
a.data-table-star-off, a.data-table-star-on:hover {
|
||||||
background-position: -17px 0px;
|
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 {
|
.data-table-cell-editor {
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
|
Loading…
Reference in New Issue
Block a user