Skip to content

Commit

Permalink
Remote workspaces implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
gertvv committed Dec 13, 2013
1 parent 851ca4f commit 89b5d1b
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 95 deletions.
5 changes: 3 additions & 2 deletions app/js/controllers/chooseProblem.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ define(['angular', 'underscore'], function(angular, _) {
DecisionProblem.populateWithUrl(choice);
}
DecisionProblem.problem.then(function(problem) {
var workspace = Workspaces.create(problem);
workspace.redirectToDefaultView();
Workspaces
.create(problem)
.then(function(workspace) { workspace.redirectToDefaultView(); });
});
};

Expand Down
12 changes: 8 additions & 4 deletions app/js/controllers/workspace.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,19 @@ define(['angular', 'underscore', 'config'], function(angular, _, Config) {
$scope.scenarios = currentWorkspace.query();
$scope.resultsAccessible = resultsAccessible();
});

function redirect(scenarioId) { currentWorkspace.redirectToDefaultView(scenarioId); };

$scope.forkScenario = function() {
var scenarioId = currentWorkspace.newScenario(currentScenario.state);
currentWorkspace.redirectToDefaultView(scenarioId);
currentWorkspace
.newScenario(currentScenario.state)
.then(redirect);
};

$scope.newScenario = function() {
var scenarioId = currentWorkspace.newScenario({ "problem" : currentWorkspace.problem });
currentWorkspace.redirectToDefaultView(scenarioId);
currentWorkspace
.newScenario({ "problem" : currentWorkspace.problem })
.then(redirect);
};
};
});
9 changes: 7 additions & 2 deletions app/js/services/localWorkspaces.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ define(['config', 'angular', 'underscore', 'services/partialValueFunction'], fun

save(workspace.id, workspace);

return id;
var deferred = $q.defer();
deferred.resolve(id);
return deferred.promise;
};

workspace.query = function() {
Expand Down Expand Up @@ -95,7 +97,10 @@ define(['config', 'angular', 'underscore', 'services/partialValueFunction'], fun
"problem": problem,
"id" : workspaceId };
localStorage.setItem(workspaceId, angular.toJson(workspace));
return decorate(workspace);

var deferred = $q.defer();
deferred.resolve(decorate(workspace));
return deferred.promise;
};

return { "create" : create,
Expand Down
147 changes: 71 additions & 76 deletions app/js/services/remoteWorkspaces.js
Original file line number Diff line number Diff line change
@@ -1,122 +1,117 @@
'use strict';
define(['config', 'angular', 'angular-resource', 'underscore', 'services/partialValueFunction'], function(Config, angular, angularResource, _) {
var dependencies = ['elicit.pvfService', 'ngResource'];

function randomId(size, prefix) {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

for(var i = 0; i < size; i++ ) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return prefix ? prefix + text : text;
}

var Workspaces = function(PartialValueFunction, $resource, $rootScope, $q, $location) {
var csrfToken = config.workspacesRepository._csrf_token;
var csrfHeader = config.workspacesRepository._csrf_header;
var headers = {};
headers[csrfHeader] = csrfToken;
var repositoryUrl = config.workspacesRepository.url;

function randomId(size, prefix) {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

for(var i = 0; i < size; i++ ) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return prefix ? prefix + text : text;
}

var save = function(id, workspace) {
console.info("saving", workspace);
localStorage.setItem(id, angular.toJson(workspace));
$rootScope.$broadcast("elicit.scenariosChanged");
return workspace;
};

var WorkspaceResource = $resource(repositoryUrl + ":workspaceId", {},
{save: {method: "POST", headers: headers}});

var redirectToDefaultView = function(workspaceId, scenarioId) {
console.info("redirecting to", workspaceId, scenarioId);
var nextUrl = "/workspaces/" + workspaceId + "/scenarios/" + scenarioId + "/" + Config.defaultView;
$location.path(nextUrl);
};

var scope = $rootScope.$new(true);

var decorate = function(workspace) {
var ScenarioResource = $resource(repositoryUrl + ":workspaceId/scenarios/:scenarioId",
{ workspaceId: workspace.id, scenarioId: '@id' },
{save: {method: "POST", headers: headers}});

workspace.redirectToDefaultView = function(scenarioId) {
redirectToDefaultView(workspace.id, scenarioId ? scenarioId : _.keys(workspace.scenarios)[0]);
};

workspace.getScenario = function(id) {
var deferred = $q.defer();
var scenario = workspace.scenarios[id];
PartialValueFunction.attach(scenario.state);
scenario.redirectToDefaultView = function() {
redirectToDefaultView(workspace.id, id);
};

scenario.save = function() {
save(workspace.id, workspace);
};

scenario.update = function(state) {
var fields = ['problem', 'prefs'];
scenario.state = _.pick(state, fields);
scenario.save();
};

scenario.createPath = _.partial(Config.createPath, workspace.id, scenario.id);

deferred.resolve(scenario);
ScenarioResource.get({ scenarioId: id }, function(scenario) {
PartialValueFunction.attach(scenario.state);
scenario.redirectToDefaultView = function() {
redirectToDefaultView(workspace.id, id);
};

scenario.save = function() {
return scenario.$save(function() { $rootScope.$broadcast("elicit.scenariosChanged"); });
};

scenario.update = function(state) {
var fields = ['problem', 'prefs'];
scenario.state = _.pick(state, fields);
scenario.$save();
};

scenario.createPath = _.partial(Config.createPath, workspace.id, scenario.id);

console.log(scenario);

deferred.resolve(scenario);
});
return deferred.promise;
};

workspace.newScenario = function(state) {
var id = randomId(5);

var n = _.size(workspace.scenarios) + 1;
var scenario = { "id" : id, "title": "Scenario " + n, "state": state };
workspace.scenarios[id] = scenario;

save(workspace.id, workspace);

return id;
var deferred = $q.defer();

var scenario = new ScenarioResource({"title" : randomId(3, "Scenario "), "state": state});
scenario.$save(function(scenario) {
deferred.resolve(scenario.id);
});

return deferred.promise;
};

workspace.query = function() {
return _.values(workspace.scenarios).sort(function(a, b) { return a.title.localeCompare(b.title); });
return ScenarioResource.query();
};

return workspace;
};

var get = _.memoize(function(id) {
var deferred = $q.defer();
var workspace = angular.fromJson(localStorage.getItem(id));
deferred.resolve(decorate(workspace));
console.log("Getting " + id);
WorkspaceResource.get({workspaceId: id}, function(workspace) {
deferred.resolve(decorate(workspace));
});
return deferred.promise;
});

var testResource = function(problem) {
console.log("Going to the server ...");
var headers = {};
headers[csrfHeader] = csrfToken;
var Workspace = $resource(repositoryUrl + ":id", {},
{save: {method: "POST", headers: headers}});
var workspace = new Workspace({title: problem.title, problem: problem});
workspace.$save(function(data) { console.log("RETURNED: ", data); });
};

var create = function(problem) {
testResource(problem);

var workspaceId = randomId(5);
var scenarioId = randomId(5);

var scenarios = {};
scenarios[scenarioId] = { "id" : scenarioId, "title": "Default", "state": { problem: problem }};

var workspace = { "scenarios": scenarios,
"title": problem.title,
"problem": problem,
"id" : workspaceId };
localStorage.setItem(workspaceId, angular.toJson(workspace));
return decorate(workspace);
var deferred = $q.defer();

var workspace = new WorkspaceResource({title: problem.title, problem: problem});
workspace.$save(function(workspace) {
var Scenario = $resource(repositoryUrl + ":workspaceId/scenarios/:scenarioId",
{ workspaceId: workspace.id },
{save: {method: "POST", headers: headers}});
var scenario = new Scenario({"title" : "Default", "state": { problem: problem }});
scenario.$save(function(scenario) {
workspace.scenarios = {};
workspace.scenarios[scenario.id] = scenario;
deferred.resolve(decorate(workspace));
});
});

return deferred.promise;
};

return { "create" : create,
"get" : get,
"save": save };
"get" : get };
};

return angular.module('elicit.remoteWorkspaces', dependencies).factory('RemoteWorkspaces', Workspaces);
Expand Down
2 changes: 1 addition & 1 deletion app/views/workspace.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ <h2>Preference elicitation <small ng-bind="workspace.title"></small></h2>

<div class="tabs">
<ul class="tabsNavigation">
<li ng-repeat="s in scenarios" ng-class="{current: s.id == scenario.id}">
<li ng-repeat="s in scenarios | orderBy:'title'" ng-class="{current: s.id == scenario.id}">
<a href="{{createPath(s.id)}}" ng-bind="s.title"></a>
</li>
<li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@

import org.drugis.mcdaweb.standalone.account.Account;
import org.drugis.mcdaweb.standalone.account.AccountRepository;
import org.drugis.mcdaweb.standalone.workspace.Scenario;
import org.drugis.mcdaweb.standalone.workspace.ScenarioRepository;
import org.drugis.mcdaweb.standalone.workspace.Workspace;
import org.drugis.mcdaweb.standalone.workspace.WorkspaceRepository;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -23,6 +24,11 @@
public class WorkspacesController {
@Inject private AccountRepository accountRepository;
@Inject private WorkspaceRepository workspaceRepository;
@Inject private ScenarioRepository scenarioRepository;

/*
* Workspaces
*/

@RequestMapping(value="/workspaces", method=RequestMethod.GET)
@ResponseBody
Expand All @@ -32,17 +38,54 @@ public Collection<Workspace> query(Principal currentUser) {
}

@RequestMapping(value="/workspaces", method=RequestMethod.POST)
public void create(HttpServletRequest request, HttpServletResponse response, Principal currentUser, @RequestBody Workspace body) {
@ResponseBody
public Workspace create(HttpServletRequest request, HttpServletResponse response, Principal currentUser, @RequestBody Workspace body) {
Account user = accountRepository.findAccountByUsername(currentUser.getName());
Workspace workspace = workspaceRepository.create(user.getId(), body.getTitle(), body.getProblem());
response.setStatus(HttpServletResponse.SC_CREATED);
response.setHeader("Location", request.getRequestURI() + "/" + workspace.getId());
response.setHeader("Location", request.getRequestURL() + "/" + workspace.getId());
return workspace;
}

@RequestMapping(value="/workspaces/{workspaceId}", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
@RequestMapping(value="/workspaces/{workspaceId}", method=RequestMethod.GET)
@ResponseBody
public Workspace get(Principal currentUser, @PathVariable int workspaceId) {
return workspaceRepository.findById(workspaceId); // FIXME: check user
}

}
/*
* Scenarios
*/

@RequestMapping(value="/workspaces/{workspaceId}/scenarios", method=RequestMethod.GET)
@ResponseBody
public Collection<Scenario> queryScenarios(Principal currentUser, @PathVariable int workspaceId) {
Collection<Scenario> scenarios = scenarioRepository.findByWorkspace(workspaceId);
for (Scenario scenario : scenarios) {
scenario.setState(null);
}
return scenarios;
}

@RequestMapping(value="/workspaces/{workspaceId}/scenarios", method=RequestMethod.POST)
@ResponseBody
public Scenario createScenario(HttpServletRequest request, HttpServletResponse response, Principal currentUser, @PathVariable int workspaceId, @RequestBody Scenario body) {
Scenario scenario = scenarioRepository.create(workspaceId, body.getTitle(), body.getState()); // FIXME: check user
response.setStatus(HttpServletResponse.SC_CREATED);
response.setHeader("Location", request.getRequestURL() + "/" + scenario.getId());
return scenario;
}

@RequestMapping(value="/workspaces/{workspaceId}/scenarios/{scenarioId}", method=RequestMethod.GET)
@ResponseBody
public Scenario getScenario(Principal currentUser, @PathVariable int workspaceId, @PathVariable int scenarioId) {
return scenarioRepository.findById(scenarioId); // FIXME: check user
}

@RequestMapping(value="/workspaces/{workspaceId}/scenarios/{scenarioId}", method=RequestMethod.POST)
@ResponseBody
public Scenario updateScenario(Principal currentUser, @PathVariable int workspaceId, @PathVariable int scenarioId, @RequestBody Scenario body) {
Scenario scenario = scenarioRepository.update(scenarioId, body.getTitle(), body.getState()); // FIXME: check user
return scenario;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Collection;

import javax.inject.Inject;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreatorFactory;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
Expand All @@ -29,6 +31,10 @@ public Scenario mapRow(ResultSet rs, int rowNum) throws SQLException {
public Scenario create(int workspaceId, String title, String state) {
PreparedStatementCreatorFactory pscf =
new PreparedStatementCreatorFactory("insert into Scenario (workspace, title, state) values (?, ?, ?)");
pscf.addParameter(new SqlParameter(Types.INTEGER));
pscf.addParameter(new SqlParameter(Types.VARCHAR));
pscf.addParameter(new SqlParameter(Types.VARCHAR));

KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(
pscf.newPreparedStatementCreator(new Object[] {workspaceId, title, state}), keyHolder);
Expand All @@ -40,6 +46,10 @@ public Scenario create(int workspaceId, String title, String state) {
public Scenario update(int scenarioId, String title, String state) {
PreparedStatementCreatorFactory pscf =
new PreparedStatementCreatorFactory("UPDATE Scenario SET title = ?, state = ? WHERE id = ?");
pscf.addParameter(new SqlParameter(Types.VARCHAR));
pscf.addParameter(new SqlParameter(Types.VARCHAR));
pscf.addParameter(new SqlParameter(Types.INTEGER));

jdbcTemplate.update(
pscf.newPreparedStatementCreator(new Object[] {title, state, scenarioId}));
return findById(scenarioId);
Expand All @@ -48,7 +58,9 @@ public Scenario update(int scenarioId, String title, String state) {
@Override
public Collection<Scenario> findByWorkspace(int workspaceId) {
PreparedStatementCreatorFactory pscf =
new PreparedStatementCreatorFactory("select id, workspace, title, problem from Scenario where workspace = ?");
new PreparedStatementCreatorFactory("select id, workspace, title, state from Scenario where workspace = ?");
pscf.addParameter(new SqlParameter(Types.INTEGER));

return jdbcTemplate.query(
pscf.newPreparedStatementCreator(new Object[] { workspaceId }), rowMapper);
}
Expand Down
Loading

0 comments on commit 89b5d1b

Please sign in to comment.