More scaffolding.
git-svn-id: http://google-refine.googlecode.com/svn/trunk@4 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
parent
e1fa9279eb
commit
9f436ad717
@ -17,6 +17,7 @@ import org.json.JSONTokener;
|
||||
import com.metaweb.gridlock.commands.Command;
|
||||
import com.metaweb.gridlock.commands.CreateProjectFromUploadCommand;
|
||||
import com.metaweb.gridlock.commands.GetColumnModelCommand;
|
||||
import com.metaweb.gridlock.commands.GetProjectMetadataCommand;
|
||||
import com.metaweb.gridlock.commands.GetRowsCommand;
|
||||
|
||||
public class GridlockServlet extends HttpServlet {
|
||||
@ -26,6 +27,7 @@ public class GridlockServlet extends HttpServlet {
|
||||
|
||||
static {
|
||||
_commands.put("create-project-from-upload", new CreateProjectFromUploadCommand());
|
||||
_commands.put("get-project-metadata", new GetProjectMetadataCommand());
|
||||
_commands.put("get-column-model", new GetColumnModelCommand());
|
||||
_commands.put("get-rows", new GetRowsCommand());
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ public class ProjectManager implements Serializable {
|
||||
private static final long serialVersionUID = -2967415873336723962L;
|
||||
|
||||
protected File _dir;
|
||||
protected Map<Long, ProjectMetadata> _projectsMetadata = new HashMap<Long, ProjectMetadata>();
|
||||
protected Map<Long, ProjectMetadata> _projectsMetadata;
|
||||
|
||||
transient protected Map<Long, Project> _projects;
|
||||
|
||||
@ -67,6 +67,9 @@ public class ProjectManager implements Serializable {
|
||||
private ProjectManager(File dir) {
|
||||
_dir = dir;
|
||||
_dir.mkdirs();
|
||||
|
||||
_projectsMetadata = new HashMap<Long, ProjectMetadata>();
|
||||
|
||||
internalInitialize();
|
||||
}
|
||||
|
||||
@ -88,6 +91,10 @@ public class ProjectManager implements Serializable {
|
||||
return project;
|
||||
}
|
||||
|
||||
public ProjectMetadata getProjectMetadata(long id) {
|
||||
return _projectsMetadata.get(id);
|
||||
}
|
||||
|
||||
public Project getProject(long id) {
|
||||
if (_projects.containsKey(id)) {
|
||||
return _projects.get(id);
|
||||
|
@ -2,9 +2,20 @@ package com.metaweb.gridlock;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class ProjectMetadata implements Serializable {
|
||||
private static final long serialVersionUID = 7959027046468240844L;
|
||||
|
||||
public String name;
|
||||
public String password;
|
||||
|
||||
public JSONObject getJSON() throws JSONException {
|
||||
JSONObject o = new JSONObject();
|
||||
|
||||
o.put("name", name);
|
||||
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ public class CreateProjectFromUploadCommand extends Command {
|
||||
String content = readFileUpload(request, properties);
|
||||
|
||||
ProjectMetadata pm = new ProjectMetadata();
|
||||
pm.name = properties.getProperty("name");
|
||||
pm.password = properties.getProperty("password");
|
||||
pm.name = properties.getProperty("project-name");
|
||||
pm.password = properties.getProperty("project-password");
|
||||
|
||||
Project project = ProjectManager.singleton.createProject(pm);
|
||||
|
||||
@ -49,14 +49,14 @@ public class CreateProjectFromUploadCommand extends Command {
|
||||
if (tab >= 0) {
|
||||
sep = "\t";
|
||||
} else {
|
||||
sep = "\\,";
|
||||
sep = ",";
|
||||
}
|
||||
}
|
||||
|
||||
String[] cells = line.split(sep);
|
||||
if (first) {
|
||||
first = false;
|
||||
String[] cells = line.split(sep);
|
||||
|
||||
first = false;
|
||||
for (int c = 0; c < cells.length; c++) {
|
||||
String cell = cells[c];
|
||||
if (cell.startsWith("\"") && cell.endsWith("\"")) {
|
||||
@ -74,13 +74,10 @@ public class CreateProjectFromUploadCommand extends Command {
|
||||
} else {
|
||||
Row row = new Row(cellCount);
|
||||
|
||||
for (int c = 0; c < cells.length; c++) {
|
||||
String text = cells[c];
|
||||
|
||||
Cell cell = new Cell();
|
||||
cell.value = parseCellValue(text);
|
||||
|
||||
row.cells.add(cell);
|
||||
if (sep.charAt(0) == ',') {
|
||||
parseCSVIntoRow(row, line);
|
||||
} else {
|
||||
parseTSVIntoRow(row, line);
|
||||
}
|
||||
|
||||
project.rows.add(row);
|
||||
@ -90,21 +87,66 @@ public class CreateProjectFromUploadCommand extends Command {
|
||||
redirect(response, "/project.html?project=" + project.id);
|
||||
}
|
||||
|
||||
static public Object parseCellValue(String text) {
|
||||
if (text.startsWith("\"") && text.endsWith("\"")) {
|
||||
return text.substring(1, text.length() - 1);
|
||||
}
|
||||
|
||||
try {
|
||||
return Long.parseLong(text);
|
||||
} catch (NumberFormatException e) {
|
||||
static protected void parseTSVIntoRow(Row row, String line) {
|
||||
String[] cells = line.split("\t");
|
||||
for (int c = 0; c < cells.length; c++) {
|
||||
String text = cells[c];
|
||||
|
||||
Cell cell = new Cell();
|
||||
cell.value = parseCellValue(text);
|
||||
|
||||
row.cells.add(cell);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return Double.parseDouble(text);
|
||||
} catch (NumberFormatException e) {
|
||||
static protected void parseCSVIntoRow(Row row, String line) {
|
||||
int start = 0;
|
||||
while (start < line.length()) {
|
||||
String text = null;
|
||||
|
||||
if (line.charAt(start) == '"') {
|
||||
int next = line.indexOf('"', start + 1);
|
||||
if (next < 0) {
|
||||
text = line.substring(start);
|
||||
start = line.length();
|
||||
} else {
|
||||
text = line.substring(start, next + 1);
|
||||
start = next + 2;
|
||||
}
|
||||
} else {
|
||||
int next = line.indexOf(',', start);
|
||||
if (next < 0) {
|
||||
text = line.substring(start);
|
||||
start = line.length();
|
||||
} else {
|
||||
text = line.substring(start, next);
|
||||
start = next + 1;
|
||||
}
|
||||
}
|
||||
|
||||
Cell cell = new Cell();
|
||||
cell.value = parseCellValue(text);
|
||||
|
||||
row.cells.add(cell);
|
||||
}
|
||||
}
|
||||
|
||||
static public Object parseCellValue(String text) {
|
||||
if (text.length() > 0) {
|
||||
if (text.length() > 1 && text.startsWith("\"") && text.endsWith("\"")) {
|
||||
return text.substring(1, text.length() - 1);
|
||||
}
|
||||
|
||||
try {
|
||||
return Long.parseLong(text);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
return Double.parseDouble(text);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
package com.metaweb.gridlock.commands;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import com.metaweb.gridlock.ProjectManager;
|
||||
import com.metaweb.gridlock.model.Project;
|
||||
|
||||
public class GetProjectMetadataCommand extends Command {
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
|
||||
Project project = getProject(request);
|
||||
|
||||
try {
|
||||
respondJSON(response, ProjectManager.singleton.getProjectMetadata(project.id).getJSON());
|
||||
} catch (JSONException e) {
|
||||
respondException(response, e);
|
||||
}
|
||||
}
|
||||
}
|
@ -40,6 +40,7 @@ public class GetRowsCommand extends Command {
|
||||
o.put("start", start);
|
||||
o.put("limit", limit);
|
||||
o.put("rows", a);
|
||||
o.put("total", project.rows.size());
|
||||
|
||||
respondJSON(response, o);
|
||||
} catch (JSONException e) {
|
||||
|
@ -1 +1 @@
|
||||
<html>
<head>
<title>Gridlock</title>
<link rel="stylesheet" href="/styles/common.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="scripts/util/string.js"></script>
<script type="text/javascript" src="scripts/index.js"></script>
</head>
<body>
<div id="header">
<h1>Gridlock</h1>
</div>
<div id="body">
<h2>New Project</h2>
<p>Create a new project by uploading a tab-separated value or comma-separated value file.</p>
<form id="file-upload-form" method="post" enctype="multipart/form-data" action="/command/create-project-from-upload">
<table cellspacing="10">
<tr><td>Project Name:</td><td><input type="text" size="30" id="project-name-input" name="project-name" /></td></tr>
<tr><td>Project Password:</td><td><input type="password" size="30" id="project-password-input" name="project-password" /><br/>optional, not protected, so use some password you don't care to reveal</td></tr>
<tr><td>Upload File:</td><td>
<input type="file" id="project-file-input" name="project-file" size="50" />
</td></tr>
<tr><td></td><td>
<input type="submit" value="Create Project" id="upload-file-button" />
</td></tr>
</table>
</form>
</div>
</body>
</html>
|
||||
<html>
<head>
<title>Gridlock</title>
<link rel="stylesheet" href="/styles/common.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript" src="scripts/util/string.js"></script>
<script type="text/javascript" src="scripts/index.js"></script>
</head>
<body>
<div id="header">
<h1>Gridlock</h1>
</div>
<div id="body">
<h2>New Project</h2>
<p>Create a new project by uploading a tab-separated value or comma-separated value file.</p>
<form id="file-upload-form" method="post" enctype="multipart/form-data" action="/command/create-project-from-upload">
<table cellspacing="10">
<tr><td>Project Name:</td><td><input type="text" size="30" id="project-name-input" name="project-name" /></td></tr>
<tr><td>Project Password:</td><td><input type="password" size="30" id="project-password-input" name="project-password" /><br/>optional, not protected, so use some password you don't care to reveal</td></tr>
<tr><td>Upload File:</td><td>
<input type="file" id="project-file-input" name="project-file" size="50" />
</td></tr>
<tr><td></td><td>
<input type="submit" value="Create Project" id="upload-file-button" />
</td></tr>
</table>
</form>
</div>
</body>
</html>
|
@ -1 +1 @@
|
||||
<html>
<head>
<title>Gridlock</title>
<link rel="stylesheet" href="/styles/common.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="scripts/util/string.js"></script>
<script type="text/javascript" src="scripts/project.js"></script>
</head>
<body>
<div id="header">
<h1 id="title">Gridlock</h1>
</div>
<div id="body">
Loading ...
</div>
</body>
</html>
|
||||
<html>
<head>
<title>Gridlock</title>
<link rel="stylesheet" href="/styles/common.css" />
<link rel="stylesheet" href="/styles/project.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.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/project.js"></script>
</head>
<body>
<div id="header">
<h1 id="title">Gridlock</h1>
</div>
<div id="body">
Loading ...
</div>
</body>
</html>
|
@ -1,4 +1,153 @@
|
||||
var theProject;
|
||||
var ui = {};
|
||||
|
||||
function onLoad() {
|
||||
|
||||
var params = URL.getParameters();
|
||||
if ("project" in params) {
|
||||
theProject = {
|
||||
id: parseInt(params.project),
|
||||
view: {
|
||||
pageSize: 25
|
||||
}
|
||||
};
|
||||
|
||||
Ajax.chainGetJSON(
|
||||
"/command/get-project-metadata?" + $.param({ project: theProject.id }), null,
|
||||
function(data) {
|
||||
theProject.metadata = data;
|
||||
},
|
||||
"/command/get-column-model?" + $.param({ project: theProject.id }), null,
|
||||
function(data) {
|
||||
theProject.columnModel = data;
|
||||
},
|
||||
"/command/get-rows?" + $.param({ project: theProject.id, start: 0, limit: 25 }), null,
|
||||
function(data) {
|
||||
theProject.rowModel = data;
|
||||
},
|
||||
function() {
|
||||
initializeUI();
|
||||
renderView();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
$(onLoad);
|
||||
|
||||
function initializeUI() {
|
||||
document.title = theProject.metadata.name + " - Gridlock";
|
||||
$("#title").html(document.title);
|
||||
|
||||
var body = $("#body").empty();
|
||||
|
||||
var table = document.createElement("table");
|
||||
$(table).attr("cellspacing", 20).css("width", "100%");
|
||||
body.append(table);
|
||||
|
||||
var tr = table.insertRow(0);
|
||||
|
||||
var tdLeft = tr.insertCell(0);
|
||||
var tdRight = tr.insertCell(1);
|
||||
tdLeft.setAttribute("width", "75%");
|
||||
tdRight.setAttribute("width", "25%");
|
||||
|
||||
ui.viewPanel = $('<div></div>').appendTo(tdLeft).css("width", tdLeft.offsetWidth + "px").css("overflow-x", "auto");
|
||||
ui.facetPanel = $('<div></div>').appendTo(tdRight);
|
||||
}
|
||||
|
||||
function renderView() {
|
||||
ui.viewPanel.empty();
|
||||
|
||||
var divSummary = $('<div></div>').addClass("viewPanel-summary").appendTo(ui.viewPanel);
|
||||
$('<span>' +
|
||||
(theProject.rowModel.start + 1) + " to " +
|
||||
(theProject.rowModel.start + theProject.rowModel.limit) + " of " +
|
||||
(theProject.rowModel.total) +
|
||||
" rows total" +
|
||||
'</span>'
|
||||
).appendTo(divSummary);
|
||||
|
||||
var pagingControls = $('<div></div>').addClass("viewPanel-pagingControls").appendTo(ui.viewPanel);
|
||||
var firstPage = $('<a href="javascript:{}">« first</a>').appendTo(pagingControls);
|
||||
var previousPage = $('<a href="javascript:{}">« previous</a>').appendTo(pagingControls);
|
||||
if (theProject.rowModel.start > 0) {
|
||||
firstPage.addClass("action").click(onClickFirstPage);
|
||||
previousPage.addClass("action").click(onClickPreviousPage);
|
||||
} else {
|
||||
firstPage.addClass("inaction");
|
||||
previousPage.addClass("inaction");
|
||||
}
|
||||
$('<span> • </span>').appendTo(pagingControls);
|
||||
var nextPage = $('<a href="javascript:{}">next page »</a>').appendTo(pagingControls);
|
||||
var lastPage = $('<a href="javascript:{}">last »</a>').appendTo(pagingControls);
|
||||
if (theProject.rowModel.start + theProject.rowModel.limit < theProject.rowModel.total) {
|
||||
nextPage.addClass("action").click(onClickNextPage);
|
||||
lastPage.addClass("action").click(onClickLastPage);
|
||||
} else {
|
||||
nextPage.addClass("inaction");
|
||||
lastPage.addClass("inaction");
|
||||
}
|
||||
|
||||
var table = document.createElement("table");
|
||||
table.className = "data-table";
|
||||
ui.viewPanel.append(table);
|
||||
|
||||
var trHead = table.insertRow(0);
|
||||
var td = trHead.insertCell(trHead.cells.length);
|
||||
|
||||
var columns = theProject.columnModel.columns;
|
||||
for (var i = 0; i < columns.length; i++) {
|
||||
var column = columns[i];
|
||||
var td = trHead.insertCell(trHead.cells.length);
|
||||
$(td).html(column.headerLabel);
|
||||
}
|
||||
|
||||
var rows = theProject.rowModel.rows;
|
||||
for (var r = 0; r < rows.length; r++) {
|
||||
var row = rows[r];
|
||||
var cells = row.cells;
|
||||
|
||||
var tr = table.insertRow(table.rows.length);
|
||||
tr.className = (r % 2) == 1 ? "odd" : "even";
|
||||
|
||||
var td = tr.insertCell(tr.cells.length);
|
||||
$(td).html((theProject.rowModel.start + r + 1) + ".");
|
||||
|
||||
for (var i = 0; i < columns.length; i++) {
|
||||
var column = columns[i];
|
||||
var td = tr.insertCell(tr.cells.length);
|
||||
|
||||
if (column.cellIndex < cells.length) {
|
||||
var cell = cells[column.cellIndex];
|
||||
if (cell.v != null) {
|
||||
$(td).html(cell.v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showRows(start, onDone) {
|
||||
Ajax.chainGetJSON(
|
||||
"/command/get-rows?" + $.param({ project: theProject.id, start: start, limit: theProject.view.pageSize }), null,
|
||||
function(data) {
|
||||
theProject.rowModel = data;
|
||||
renderView();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function onClickPreviousPage() {
|
||||
showRows(theProject.rowModel.start - theProject.view.pageSize);
|
||||
}
|
||||
|
||||
function onClickNextPage() {
|
||||
showRows(theProject.rowModel.start + theProject.view.pageSize);
|
||||
}
|
||||
|
||||
function onClickFirstPage() {
|
||||
showRows(0, theProject.view.pageSize);
|
||||
}
|
||||
|
||||
function onClickLastPage() {
|
||||
showRows(Math.floor(theProject.rowModel.total / theProject.view.pageSize) * theProject.view.pageSize);
|
||||
}
|
||||
|
22
src/main/webapp/scripts/util/ajax.js
Normal file
22
src/main/webapp/scripts/util/ajax.js
Normal file
@ -0,0 +1,22 @@
|
||||
Ajax = {};
|
||||
|
||||
Ajax.chainGetJSON = function() {
|
||||
var a = arguments;
|
||||
var i = 0;
|
||||
var next = function() {
|
||||
if (i <= a.length - 3) {
|
||||
var url = a[i++];
|
||||
var data = a[i++];
|
||||
var callback = a[i++];
|
||||
|
||||
$.getJSON(url, data, function(o) {
|
||||
callback(o);
|
||||
next();
|
||||
}, "json");
|
||||
} else if (i < a.length) {
|
||||
var finalCallback = a[i++];
|
||||
finalCallback();
|
||||
}
|
||||
};
|
||||
next();
|
||||
};
|
16
src/main/webapp/scripts/util/url.js
Normal file
16
src/main/webapp/scripts/util/url.js
Normal file
@ -0,0 +1,16 @@
|
||||
URL = {};
|
||||
|
||||
URL.getParameters = function() {
|
||||
var r = {};
|
||||
|
||||
var params = window.location.search;
|
||||
if (params.length > 1) {
|
||||
params = params.substr(1).split("&");
|
||||
$.each(params, function() {
|
||||
pair = this.split("=");
|
||||
r[pair[0]] = unescape(pair[1]);
|
||||
});
|
||||
}
|
||||
|
||||
return r;
|
||||
};
|
@ -30,3 +30,17 @@ tr, td {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
a.action {
|
||||
margin: 0 3px;
|
||||
text-decoration: none;
|
||||
color: #448;
|
||||
}
|
||||
a.action:hover {
|
||||
color: #88f;
|
||||
}
|
||||
|
||||
a.inaction {
|
||||
margin: 0 3px;
|
||||
text-decoration: none;
|
||||
color: #ccc;
|
||||
}
|
||||
|
17
src/main/webapp/styles/project.css
Normal file
17
src/main/webapp/styles/project.css
Normal file
@ -0,0 +1,17 @@
|
||||
table.data-table td {
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
table.data-table tr.odd {
|
||||
}
|
||||
|
||||
table.data-table tr.even {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.viewPanel-summary {
|
||||
}
|
||||
.viewPanel-pagingControls {
|
||||
text-align: center;
|
||||
margin: 1em 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user