diff options
author | Jesse Morgan <jesse@jesterpm.net> | 2013-08-04 16:09:29 -0700 |
---|---|---|
committer | Jesse Morgan <jesse@jesterpm.net> | 2013-08-04 16:09:29 -0700 |
commit | 52539d7aaba96b7997a3c5a07e4a1ad234af7d04 (patch) | |
tree | 2686f56bc37656c0824a05e28472f7334ed39028 /src/com/p4square/grow/frontend | |
parent | 69e2512750dd75fce43a21226979996c3cd7da1d (diff) |
Committing everything since its long overdue.
Diffstat (limited to 'src/com/p4square/grow/frontend')
-rw-r--r-- | src/com/p4square/grow/frontend/GrowFrontend.java | 32 | ||||
-rw-r--r-- | src/com/p4square/grow/frontend/SurveyPageResource.java | 22 | ||||
-rw-r--r-- | src/com/p4square/grow/frontend/TrainingPageResource.java | 228 |
3 files changed, 280 insertions, 2 deletions
diff --git a/src/com/p4square/grow/frontend/GrowFrontend.java b/src/com/p4square/grow/frontend/GrowFrontend.java index 226929d..74cd704 100644 --- a/src/com/p4square/grow/frontend/GrowFrontend.java +++ b/src/com/p4square/grow/frontend/GrowFrontend.java @@ -4,8 +4,14 @@ package com.p4square.grow.frontend; +import java.io.File; +import java.io.IOException; + +import org.restlet.Application; import org.restlet.Component; +import org.restlet.Restlet; import org.restlet.data.Protocol; +import org.restlet.resource.Directory; import org.restlet.routing.Router; import org.apache.log4j.Logger; @@ -71,6 +77,8 @@ public class GrowFrontend extends FMFacade { final Router accountRouter = new Router(getContext()); accountRouter.attach("/assessment/question/{questionId}", SurveyPageResource.class); accountRouter.attach("/assessment", SurveyPageResource.class); + accountRouter.attach("/training/{chapter}", TrainingPageResource.class); + accountRouter.attach("/training", TrainingPageResource.class); final LoginAuthenticator accountGuard = new LoginAuthenticator(getContext(), false, loginPage); @@ -88,6 +96,17 @@ public class GrowFrontend extends FMFacade { final Component component = new Component(); component.getServers().add(Protocol.HTTP, 8085); component.getClients().add(Protocol.HTTP); + component.getClients().add(Protocol.FILE); + + // Static content + try { + component.getDefaultHost().attach("/images/", new FileServingApp("./build/images/")); + component.getDefaultHost().attach("/scripts", new FileServingApp("./build/scripts")); + component.getDefaultHost().attach("/style.css", new FileServingApp("./build/style.css")); + } catch (IOException e) { + cLog.error("Could not create directory for static resources: " + + e.getMessage(), e); + } // Setup App GrowFrontend app = new GrowFrontend(); @@ -119,4 +138,17 @@ public class GrowFrontend extends FMFacade { cLog.fatal("Could not start: " + e.getMessage(), e); } } + + private static class FileServingApp extends Application { + private final String mPath; + + public FileServingApp(String path) throws IOException { + mPath = new File(path).getAbsolutePath(); + } + + @Override + public Restlet createInboundRoot() { + return new Directory(getContext(), "file://" + mPath); + } + } } diff --git a/src/com/p4square/grow/frontend/SurveyPageResource.java b/src/com/p4square/grow/frontend/SurveyPageResource.java index 280184b..8145c0d 100644 --- a/src/com/p4square/grow/frontend/SurveyPageResource.java +++ b/src/com/p4square/grow/frontend/SurveyPageResource.java @@ -115,6 +115,7 @@ public class SurveyPageResource extends FreeMarkerPageResource { protected Representation post(Representation entity) { final Form form = new Form(entity); final String answerId = form.getFirstValue("answer"); + final String direction = form.getFirstValue("direction"); if (mQuestionId == null || answerId == null || answerId.length() == 0) { // Something is wrong. @@ -154,9 +155,26 @@ public class SurveyPageResource extends FreeMarkerPageResource { // Find the next question or finish the assessment. String nextPage = mConfig.getString("dynamicRoot", ""); { - String nextQuestionId = (String) questionData.get("nextQuestion"); + String nextQuestionId = null; + if ("previous".equals(direction)) { + nextQuestionId = (String) questionData.get("previousQuestion"); + } else { + nextQuestionId = (String) questionData.get("nextQuestion"); + } + if (nextQuestionId == null) { - nextPage += "/account/assessment/results"; + //nextPage += "/account/assessment/results"; + // TODO: Remove this hack: + JsonResponse response = backendGet("/accounts/" + mUserId + "/assessment"); + if (!response.getStatus().isSuccess()) { + nextPage += "/account/assessment/results"; + } else { + final String score = (String) response.getMap().get("result"); + if (score != null) { + nextPage += "/account/training/" + score; + } + } + } else { nextPage += "/account/assessment/question/" + nextQuestionId; } diff --git a/src/com/p4square/grow/frontend/TrainingPageResource.java b/src/com/p4square/grow/frontend/TrainingPageResource.java new file mode 100644 index 0000000..6493638 --- /dev/null +++ b/src/com/p4square/grow/frontend/TrainingPageResource.java @@ -0,0 +1,228 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package com.p4square.grow.frontend; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.HashMap; + +import freemarker.template.Template; + +import org.restlet.data.Form; +import org.restlet.data.MediaType; +import org.restlet.data.Status; +import org.restlet.ext.freemarker.TemplateRepresentation; +import org.restlet.representation.Representation; +import org.restlet.resource.ServerResource; + +import org.apache.log4j.Logger; + +import net.jesterpm.fmfacade.json.JsonRequestClient; +import net.jesterpm.fmfacade.json.JsonResponse; + +import net.jesterpm.fmfacade.FreeMarkerPageResource; + +import com.p4square.grow.config.Config; + +/** + * SurveyPageResource handles rendering the survey and processing user's answers. + * + * This resource expects the user to be authenticated and the ClientInfo User object + * to be populated. Each question is requested from the backend along with the + * user's previous answer. Each answer is sent to the backend and the user is redirected + * to the next question. After the last question the user is sent to his results. + * + * @author Jesse Morgan <jesse@jesterpm.net> + */ +public class TrainingPageResource extends FreeMarkerPageResource { + private static Logger cLog = Logger.getLogger(TrainingPageResource.class); + + private Config mConfig; + private Template mTrainingTemplate; + private JsonRequestClient mJsonClient; + + // Fields pertaining to this request. + private String mChapter; + private String mUserId; + + @Override + public void doInit() { + super.doInit(); + + GrowFrontend growFrontend = (GrowFrontend) getApplication(); + mConfig = growFrontend.getConfig(); + mTrainingTemplate = growFrontend.getTemplate("templates/training.ftl"); + if (mTrainingTemplate == null) { + cLog.fatal("Could not find training template."); + setStatus(Status.SERVER_ERROR_INTERNAL); + } + + mJsonClient = new JsonRequestClient(getContext().getClientDispatcher()); + + mChapter = getAttribute("chapter"); + mUserId = getRequest().getClientInfo().getUser().getIdentifier(); + } + + /** + * Return a page with a survey question. + */ + @Override + protected Representation get() { + try { + // Get the current chapter. + if (mChapter == null) { + // TODO: Get user's current question + mChapter = "seeker"; + } + + // Get videos for the chapter. + List<Map<String, Object>> videos = null; + { + JsonResponse response = backendGet("/training/" + mChapter); + if (!response.getStatus().isSuccess()) { + setStatus(Status.CLIENT_ERROR_NOT_FOUND); + return null; + } + videos = (List<Map<String, Object>>) response.getMap().get("videos"); + } + + // Get list of completed videos + Map<String, Object> trainingRecord = null; + Map<String, Object> completedVideos = new HashMap<String, Object>(); + { + JsonResponse response = backendGet("/accounts/" + mUserId + "/training"); + if (response.getStatus().isSuccess()) { + trainingRecord = response.getMap(); + completedVideos = (Map<String, Object>) trainingRecord.get("videos"); + } + } + + // Mark the completed videos as completed + int chapterProgress = 0; + for (Map<String, Object> video : videos) { + boolean completed = (null != completedVideos.get(video.get("id"))); + video.put("completed", completed); + + if (completed) { + chapterProgress++; + } + } + chapterProgress = chapterProgress * 100 / videos.size(); + + Map root = getRootObject(); + root.put("chapter", mChapter); + root.put("chapterProgress", chapterProgress); + root.put("videos", videos); + root.put("completedVideos", completedVideos); + + return new TemplateRepresentation(mTrainingTemplate, root, MediaType.TEXT_HTML); + + } catch (Exception e) { + cLog.fatal("Could not render page: " + e.getMessage(), e); + setStatus(Status.SERVER_ERROR_INTERNAL); + return null; + } + } + + /** + * Record a survey answer and redirect to the next question. + */ + @Override + protected Representation post(Representation entity) { + return null; + /*final Form form = new Form(entity); + final String answerId = form.getFirstValue("answer"); + + if (mQuestionId == null || answerId == null || answerId.length() == 0) { + // Something is wrong. + setStatus(Status.CLIENT_ERROR_BAD_REQUEST); + return null; + } + + try { + // Find the question + Map questionData = null; + { + JsonResponse response = backendGet("/assessment/question/" + mQuestionId); + if (!response.getStatus().isSuccess()) { + // User is answering a question which doesn't exist + setStatus(Status.CLIENT_ERROR_NOT_FOUND); + return null; + } + + questionData = response.getMap(); + } + + // Store answer + { + Map<String, String> answer = new HashMap<String, String>(); + answer.put("answerId", answerId); + JsonResponse response = backendPut("/accounts/" + mUserId + + "/assessment/answers/" + mQuestionId, answer); + + if (!response.getStatus().isSuccess()) { + // Something went wrong talking to the backend, error out. + cLog.fatal("Error recording survey answer " + response.getStatus()); + setStatus(Status.SERVER_ERROR_INTERNAL); + return null; + } + } + + // Find the next question or finish the assessment. + String nextPage = mConfig.getString("dynamicRoot", ""); + { + String nextQuestionId = (String) questionData.get("nextQuestion"); + if (nextQuestionId == null) { + nextPage += "/account/assessment/results"; + } else { + nextPage += "/account/assessment/question/" + nextQuestionId; + } + } + + getResponse().redirectSeeOther(nextPage); + return null; + + } catch (Exception e) { + cLog.fatal("Could not render page: " + e.getMessage(), e); + setStatus(Status.SERVER_ERROR_INTERNAL); + return null; + }*/ + } + + /** + * @return The backend endpoint URI + */ + private String getBackendEndpoint() { + return mConfig.getString("backendUri", "riap://component/backend"); + } + + /** + * Helper method to send a GET to the backend. + */ + private JsonResponse backendGet(final String uri) { + cLog.debug("Sending backend GET " + uri); + + final JsonResponse response = mJsonClient.get(getBackendEndpoint() + uri); + final Status status = response.getStatus(); + if (!status.isSuccess() && !Status.CLIENT_ERROR_NOT_FOUND.equals(status)) { + cLog.warn("Error making backend request for '" + uri + "'. status = " + response.getStatus().toString()); + } + + return response; + } + + private JsonResponse backendPut(final String uri, final Map data) { + cLog.debug("Sending backend PUT " + uri); + + final JsonResponse response = mJsonClient.put(getBackendEndpoint() + uri, data); + final Status status = response.getStatus(); + if (!status.isSuccess() && !Status.CLIENT_ERROR_NOT_FOUND.equals(status)) { + cLog.warn("Error making backend request for '" + uri + "'. status = " + response.getStatus().toString()); + } + + return response; + } +} |