Started to hook up sorting. You can sort on one column right now but there's no indicator after you've done sorting.
git-svn-id: http://google-refine.googlecode.com/svn/trunk@835 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
parent
496823e564
commit
80a199b4a9
@ -8,6 +8,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONWriter;
|
||||
|
||||
import com.metaweb.gridworks.browsing.Engine;
|
||||
@ -20,10 +21,13 @@ import com.metaweb.gridworks.commands.Command;
|
||||
import com.metaweb.gridworks.model.Project;
|
||||
import com.metaweb.gridworks.model.Record;
|
||||
import com.metaweb.gridworks.model.Row;
|
||||
import com.metaweb.gridworks.sorting.SortingRecordVisitor;
|
||||
import com.metaweb.gridworks.sorting.SortingRowVisitor;
|
||||
import com.metaweb.gridworks.util.ParsingUtilities;
|
||||
import com.metaweb.gridworks.util.Pool;
|
||||
|
||||
public class GetRowsCommand extends Command {
|
||||
|
||||
|
||||
public void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
|
||||
@ -46,25 +50,49 @@ public class GetRowsCommand extends Command {
|
||||
JSONWriter writer = new JSONWriter(response.getWriter());
|
||||
writer.object();
|
||||
|
||||
RowWritingVisitor acc = new RowWritingVisitor(start, limit, writer, options);
|
||||
RowWritingVisitor rwv = new RowWritingVisitor(start, limit, writer, options);
|
||||
|
||||
JSONObject sortingJson = null;
|
||||
try{
|
||||
String json = request.getParameter("sorting");
|
||||
sortingJson = (json == null) ? null :
|
||||
ParsingUtilities.evaluateJsonStringToObject(json);
|
||||
} catch (JSONException e) {
|
||||
}
|
||||
|
||||
if (engine.getMode() == Mode.RowBased) {
|
||||
FilteredRows filteredRows = engine.getAllFilteredRows();
|
||||
RowVisitor visitor = rwv;
|
||||
|
||||
if (sortingJson != null) {
|
||||
SortingRowVisitor srv = new SortingRowVisitor(visitor);
|
||||
|
||||
srv.initializeFromJSON(project, sortingJson);
|
||||
visitor = srv;
|
||||
}
|
||||
|
||||
writer.key("mode"); writer.value("row-based");
|
||||
writer.key("rows"); writer.array();
|
||||
filteredRows.accept(project, acc);
|
||||
filteredRows.accept(project, visitor);
|
||||
writer.endArray();
|
||||
writer.key("filtered"); writer.value(acc.total);
|
||||
writer.key("filtered"); writer.value(rwv.total);
|
||||
writer.key("total"); writer.value(project.rows.size());
|
||||
} else {
|
||||
FilteredRecords filteredRecords = engine.getFilteredRecords();
|
||||
RecordVisitor visitor = rwv;
|
||||
|
||||
if (sortingJson != null) {
|
||||
SortingRecordVisitor srv = new SortingRecordVisitor(visitor);
|
||||
|
||||
srv.initializeFromJSON(project, sortingJson);
|
||||
visitor = srv;
|
||||
}
|
||||
|
||||
writer.key("mode"); writer.value("record-based");
|
||||
writer.key("rows"); writer.array();
|
||||
filteredRecords.accept(project, acc);
|
||||
filteredRecords.accept(project, visitor);
|
||||
writer.endArray();
|
||||
writer.key("filtered"); writer.value(acc.total);
|
||||
writer.key("filtered"); writer.value(rwv.total);
|
||||
writer.key("total"); writer.value(project.recordModel.getRecordCount());
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,10 @@ abstract public class BaseSorter {
|
||||
}
|
||||
|
||||
public Object getKey(Project project, Object o, int index) {
|
||||
while (index >= _keys.size()) {
|
||||
_keys.add(null);
|
||||
}
|
||||
|
||||
Object[] keys = _keys.get(index);
|
||||
if (keys == null) {
|
||||
keys = makeKeys(project, o, index);
|
||||
|
@ -6,22 +6,23 @@ import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import com.metaweb.gridworks.browsing.RecordVisitor;
|
||||
import com.metaweb.gridworks.browsing.RowVisitor;
|
||||
import com.metaweb.gridworks.model.Project;
|
||||
import com.metaweb.gridworks.model.Record;
|
||||
import com.metaweb.gridworks.sorting.Criterion.KeyMaker;
|
||||
|
||||
public class SortingRecordVisitor extends BaseSorter implements RecordVisitor {
|
||||
final protected RowVisitor _visitor;
|
||||
protected List<Record> _records;
|
||||
final protected RecordVisitor _visitor;
|
||||
protected List<Record> _records;
|
||||
|
||||
public SortingRecordVisitor(RowVisitor visitor) {
|
||||
public SortingRecordVisitor(RecordVisitor visitor) {
|
||||
_visitor = visitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Project project) {
|
||||
_records = new ArrayList<Record>(project.recordModel.getRecordCount());
|
||||
int count = project.recordModel.getRecordCount();
|
||||
_records = new ArrayList<Record>(count);
|
||||
_keys = new ArrayList<Object[]>(count);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -42,6 +43,10 @@ public class SortingRecordVisitor extends BaseSorter implements RecordVisitor {
|
||||
}
|
||||
}.init(project));
|
||||
|
||||
for (Record record : _records) {
|
||||
_visitor.visit(project, record);
|
||||
}
|
||||
|
||||
_visitor.end(project);
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,9 @@ public class SortingRowVisitor extends BaseSorter implements RowVisitor {
|
||||
|
||||
@Override
|
||||
public void start(Project project) {
|
||||
_indexedRows = new ArrayList<IndexedRow>(project.rows.size());
|
||||
int count = project.rows.size();
|
||||
_indexedRows = new ArrayList<IndexedRow>(count);
|
||||
_keys = new ArrayList<Object[]>(count);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -51,6 +53,10 @@ public class SortingRowVisitor extends BaseSorter implements RowVisitor {
|
||||
}
|
||||
}.init(project));
|
||||
|
||||
for (IndexedRow indexedRow : _indexedRows) {
|
||||
_visitor.visit(project, indexedRow.index, indexedRow.row);
|
||||
}
|
||||
|
||||
_visitor.end(project);
|
||||
}
|
||||
|
||||
|
@ -337,10 +337,17 @@ Gridworks.preparePool = function(pool) {
|
||||
}
|
||||
};
|
||||
|
||||
Gridworks.fetchRows = function(start, limit, onDone) {
|
||||
Gridworks.fetchRows = function(start, limit, onDone, sorting) {
|
||||
var body = {
|
||||
engine: JSON.stringify(ui.browsingEngine.getJSON())
|
||||
};
|
||||
if (sorting) {
|
||||
body.sorting = JSON.stringify(sorting)
|
||||
}
|
||||
|
||||
$.post(
|
||||
"/command/get-rows?" + $.param({ project: theProject.id, start: start, limit: limit }),
|
||||
{ engine: JSON.stringify(ui.browsingEngine.getJSON()) },
|
||||
body,
|
||||
function(data) {
|
||||
theProject.rowModel = data;
|
||||
|
||||
|
@ -313,6 +313,10 @@ DataTableColumnHeaderUI.prototype._createMenuForColumnHeader = function(elmt) {
|
||||
]
|
||||
},
|
||||
{},
|
||||
{
|
||||
label: "Sort",
|
||||
submenu: this.createSortingMenu()
|
||||
},
|
||||
{
|
||||
label: "View",
|
||||
tooltip: "Collapse/expand columns to make viewing the data more convenient",
|
||||
@ -538,6 +542,40 @@ DataTableColumnHeaderUI.prototype._createMenuForColumnHeader = function(elmt) {
|
||||
], elmt, { width: "120px", horizontal: false });
|
||||
};
|
||||
|
||||
DataTableColumnHeaderUI.prototype.createSortingMenu = function() {
|
||||
var self = this;
|
||||
var criterion = this._dataTableView._getSortingCriterionForColumn(this._column.name);
|
||||
var criteriaCount = this._dataTableView._getSortingCriteriaCount();
|
||||
var hasOtherCriteria = criterion == null ? (criteriaCount > 0) : criteriaCount > 1;
|
||||
|
||||
var items = [
|
||||
{
|
||||
"label": "Sort ...",
|
||||
"click": function() {
|
||||
self._showSortingCriterion(criterion, hasOtherCriteria)
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
if (criterion != null) {
|
||||
items.push({
|
||||
"label": "Reverse",
|
||||
"click": function() {
|
||||
criterion.reverse = !criterion.reverse;
|
||||
self._dataTableView._addSortingCriterion(criterion);
|
||||
}
|
||||
});
|
||||
items.push({
|
||||
"label": "Un-sort",
|
||||
"click": function() {
|
||||
self._dataTableView._removeSortingCriterionOfColumn(criterion.column);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
DataTableColumnHeaderUI.prototype._doFilterByExpressionPrompt = function(expression, type) {
|
||||
var self = this;
|
||||
DataTableView.promptExpressionOnVisibleRows(
|
||||
@ -1080,3 +1118,111 @@ DataTableColumnHeaderUI.prototype._doSplitColumn = function() {
|
||||
|
||||
footerElmts.cancelButton.click(dismiss);
|
||||
};
|
||||
|
||||
DataTableColumnHeaderUI.prototype._showSortingCriterion = function(criterion, hasOtherCriteria) {
|
||||
var self = this;
|
||||
|
||||
criterion = criterion || {
|
||||
column: this._column.name,
|
||||
valueType: "string",
|
||||
caseSensitive: false,
|
||||
errorPosition: 1,
|
||||
blankPosition: 2
|
||||
};
|
||||
|
||||
var frame = DialogSystem.createDialog();
|
||||
frame.width("400px");
|
||||
|
||||
var header = $('<div></div>').addClass("dialog-header").text("Sort by " + this._column.name).appendTo(frame);
|
||||
var body = $('<div></div>').addClass("dialog-body").appendTo(frame);
|
||||
var footer = $('<div></div>').addClass("dialog-footer").appendTo(frame);
|
||||
|
||||
body.html(
|
||||
'<div class="grid-layout layout-normal layout-full "><table>' +
|
||||
'<tr>' +
|
||||
'<td>Sort cell values as</td>' +
|
||||
'<td>Position blanks and errors</td>' +
|
||||
'</tr>' +
|
||||
'<tr>' +
|
||||
'<td>' +
|
||||
'<div class="grid-layout layout-tightest grid-layout-for-text" bind="valueTypeOptions"><table>' +
|
||||
'<tr>' +
|
||||
'<td width="1"><input type="radio" name="sorting-dialog-value-type" value="string" /></td>' +
|
||||
'<td>text <input type="checkbox" class="inline" bind="caseSensitiveCheckbox" /> case-sensitive</td>' +
|
||||
'</tr>' +
|
||||
'<tr>' +
|
||||
'<td width="1"><input type="radio" name="sorting-dialog-value-type" value="number" /></td>' +
|
||||
'<td>numbers</td>' +
|
||||
'</tr>' +
|
||||
'<tr>' +
|
||||
'<td width="1"><input type="radio" name="sorting-dialog-value-type" value="date" /></td>' +
|
||||
'<td>dates</td>' +
|
||||
'</tr>' +
|
||||
'<tr>' +
|
||||
'<td width="1"><input type="radio" name="sorting-dialog-value-type" value="boolean" /></td>' +
|
||||
'<td>booleans</td>' +
|
||||
'</tr>' +
|
||||
'</table></div>' +
|
||||
'</td>' +
|
||||
'<td>' +
|
||||
'<ul>' +
|
||||
'<li>Valid Values</li>' +
|
||||
'<li>Blanks</li>' +
|
||||
'<li>Errors</li>' +
|
||||
'</ul>' +
|
||||
'<p>Drag and drop to re-order</p>' +
|
||||
'</td>' +
|
||||
'</tr>' +
|
||||
'<tr><td colspan="2" bind="directionOptions">' +
|
||||
'<input type="radio" class="inline" name="sorting-dialog-direction" value="forward" /><label>forward</label> ' +
|
||||
'<input type="radio" class="inline" name="sorting-dialog-direction" value="reverse" /><label>reverse</label> ' +
|
||||
'<span bind="sortAloneContainer" style="display:none;"><input type="checkbox" class="inline" /><label>sort by this column alone</label></span>' +
|
||||
'</td></tr>' +
|
||||
'</table></div>'
|
||||
);
|
||||
|
||||
var bodyElmts = DOM.bind(body);
|
||||
|
||||
bodyElmts.valueTypeOptions.find("input[type='radio'][value='" + criterion.valueType + "']")
|
||||
.attr("checked", "checked");
|
||||
|
||||
if (criterion.valueType == "string" && criterion.caseSensitive) {
|
||||
bodyElmts.caseSensitiveCheckbox.attr("checked", "checked");
|
||||
}
|
||||
|
||||
bodyElmts.directionOptions.find("input[type='radio'][value='" + (criterion.reverse ? "reverse" : "forward") + "']")
|
||||
.attr("checked", "checked");
|
||||
|
||||
if (hasOtherCriteria) {
|
||||
bodyElmts.sortAloneContainer.show();
|
||||
}
|
||||
|
||||
footer.html(
|
||||
'<button bind="okButton"> OK </button>' +
|
||||
'<button bind="cancelButton">Cancel</button>'
|
||||
);
|
||||
var footerElmts = DOM.bind(footer);
|
||||
|
||||
var level = DialogSystem.showDialog(frame);
|
||||
var dismiss = function() {
|
||||
DialogSystem.dismissUntil(level - 1);
|
||||
};
|
||||
|
||||
footerElmts.cancelButton.click(dismiss);
|
||||
footerElmts.okButton.click(function() {
|
||||
var criterion2 = {
|
||||
column: self._column.name,
|
||||
valueType: bodyElmts.valueTypeOptions.find("input[type='radio']:checked")[0].value,
|
||||
reverse: bodyElmts.directionOptions.find("input[type='radio']:checked")[0].value == "reverse"
|
||||
};
|
||||
|
||||
if (criterion2.valueType == "string") {
|
||||
criterion2.caseSensitive = bodyElmts.caseSensitiveCheckbox[0].checked;
|
||||
}
|
||||
|
||||
self._dataTableView._addSortingCriterion(
|
||||
criterion2, bodyElmts.sortAloneContainer.find("input")[0].checked);
|
||||
|
||||
dismiss();
|
||||
});
|
||||
};
|
@ -3,6 +3,7 @@ function DataTableView(div) {
|
||||
this._pageSize = 20;
|
||||
this._showRecon = true;
|
||||
this._collapsedColumnNames = {};
|
||||
this._sorting = { criteria: [] };
|
||||
|
||||
this._showRows(0);
|
||||
}
|
||||
@ -333,7 +334,7 @@ DataTableView.prototype._showRows = function(start, onDone) {
|
||||
if (onDone) {
|
||||
onDone();
|
||||
}
|
||||
});
|
||||
}, this._sorting);
|
||||
};
|
||||
|
||||
DataTableView.prototype._onClickPreviousPage = function(elmt, evt) {
|
||||
@ -352,6 +353,54 @@ DataTableView.prototype._onClickLastPage = function(elmt, evt) {
|
||||
this._showRows(Math.floor(theProject.rowModel.filtered / this._pageSize) * this._pageSize);
|
||||
};
|
||||
|
||||
DataTableView.prototype._getSortingCriteriaCount = function() {
|
||||
return this._sorting.criteria.length;
|
||||
};
|
||||
|
||||
DataTableView.prototype._sortedByColumn = function(columnName) {
|
||||
for (var i = 0; i < this._sorting.criteria.length; i++) {
|
||||
if (this._sorting.criteria[i].column == columnName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
DataTableView.prototype._getSortingCriterionForColumn = function(columnName) {
|
||||
for (var i = 0; i < this._sorting.criteria.length; i++) {
|
||||
if (this._sorting.criteria[i].column == columnName) {
|
||||
return this._sorting.criteria[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
DataTableView.prototype._removeSortingCriterionOfColumn = function(columnName) {
|
||||
for (var i = 0; i < this._sorting.criteria.length; i++) {
|
||||
if (this._sorting.criteria[i].column == columnName) {
|
||||
this._sorting.criteria.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.update();
|
||||
};
|
||||
|
||||
DataTableView.prototype._addSortingCriterion = function(criterion, alone) {
|
||||
if (alone) {
|
||||
this._sorting.criteria = [];
|
||||
} else {
|
||||
for (var i = 0; i < this._sorting.criteria.length; i++) {
|
||||
if (this._sorting.criteria[i].column == criterion.column) {
|
||||
this._sorting.criteria[i] = criterion;
|
||||
this.update();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
this._sorting.criteria.push(criterion);
|
||||
this.update();
|
||||
};
|
||||
|
||||
DataTableView.prototype._createMenuForAllColumns = function(elmt) {
|
||||
self = this;
|
||||
MenuSystem.createAndShowStandardMenu([
|
||||
|
@ -29,6 +29,9 @@ div.grid-layout > table > tbody > tr > th, div.grid-layout > table > tbody > tr
|
||||
text-align: left;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
div.grid-layout.grid-layout-for-text > table > tbody > tr > th, div.grid-layout.grid-layout-for-text > table > tbody > tr > td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
div.grid-layout.layout-normal {
|
||||
margin: -10px;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user