diff options
-rw-r--r-- | src/com/p4square/grow/frontend/GrowFrontend.java | 1 | ||||
-rw-r--r-- | src/com/p4square/grow/frontend/TrainingPageResource.java | 8 | ||||
-rw-r--r-- | src/com/p4square/grow/frontend/VideosResource.java | 120 | ||||
-rw-r--r-- | src/templates/templates/training.ftl | 13 | ||||
-rw-r--r-- | web/scripts/growth.js | 11 | ||||
-rw-r--r-- | web/style.css | 1 |
6 files changed, 146 insertions, 8 deletions
diff --git a/src/com/p4square/grow/frontend/GrowFrontend.java b/src/com/p4square/grow/frontend/GrowFrontend.java index 74cd704..5c49fe2 100644 --- a/src/com/p4square/grow/frontend/GrowFrontend.java +++ b/src/com/p4square/grow/frontend/GrowFrontend.java @@ -77,6 +77,7 @@ 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}/videos/{videoId}.json", VideosResource.class); accountRouter.attach("/training/{chapter}", TrainingPageResource.class); accountRouter.attach("/training", TrainingPageResource.class); diff --git a/src/com/p4square/grow/frontend/TrainingPageResource.java b/src/com/p4square/grow/frontend/TrainingPageResource.java index 6493638..6c89ac9 100644 --- a/src/com/p4square/grow/frontend/TrainingPageResource.java +++ b/src/com/p4square/grow/frontend/TrainingPageResource.java @@ -28,13 +28,11 @@ import net.jesterpm.fmfacade.FreeMarkerPageResource; import com.p4square.grow.config.Config; /** - * SurveyPageResource handles rendering the survey and processing user's answers. + * TrainingPageResource handles rendering the training page. * * 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. - * + * to be populated. + * * @author Jesse Morgan <jesse@jesterpm.net> */ public class TrainingPageResource extends FreeMarkerPageResource { diff --git a/src/com/p4square/grow/frontend/VideosResource.java b/src/com/p4square/grow/frontend/VideosResource.java new file mode 100644 index 0000000..fed315b --- /dev/null +++ b/src/com/p4square/grow/frontend/VideosResource.java @@ -0,0 +1,120 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package com.p4square.grow.frontend; + +import java.util.Map; + +import freemarker.template.Template; + +import org.restlet.data.Form; +import org.restlet.data.MediaType; +import org.restlet.data.Status; +import org.restlet.ext.jackson.JacksonRepresentation; +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 com.p4square.grow.config.Config; + +/** + * VideosResource returns JSON blobs with video information and records watched + * videos. + * + * @author Jesse Morgan <jesse@jesterpm.net> + */ +public class VideosResource extends ServerResource { + private static Logger cLog = Logger.getLogger(VideosResource.class); + + private Config mConfig; + private JsonRequestClient mJsonClient; + + // Fields pertaining to this request. + private String mChapter; + private String mVideoId; + private String mUserId; + + @Override + public void doInit() { + super.doInit(); + + GrowFrontend growFrontend = (GrowFrontend) getApplication(); + mConfig = growFrontend.getConfig(); + + mJsonClient = new JsonRequestClient(getContext().getClientDispatcher()); + + mChapter = getAttribute("chapter"); + mVideoId = getAttribute("videoId"); + mUserId = getRequest().getClientInfo().getUser().getIdentifier(); + } + + /** + * Fetch a video record from the backend. + */ + @Override + protected Representation get() { + try { + JsonResponse response = backendGet("/training/" + mChapter + "/videos/" + mVideoId); + + if (response.getStatus().isSuccess()) { + return new JacksonRepresentation<Map>(response.getMap()); + + } else { + setStatus(response.getStatus()); + return null; + } + + } catch (Exception e) { + cLog.fatal("Could not render page: " + e.getMessage(), e); + setStatus(Status.SERVER_ERROR_INTERNAL); + return null; + } + } + + /** + * Mark a video as completed. + */ + @Override + protected Representation post(Representation entity) { + 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; + } +} diff --git a/src/templates/templates/training.ftl b/src/templates/templates/training.ftl index 3207c33..0490a9a 100644 --- a/src/templates/templates/training.ftl +++ b/src/templates/templates/training.ftl @@ -36,7 +36,7 @@ <div id="videos"> <#list videos as video> <article> - <div class="image <#if video.completed>completed</#if>"><a href="#"><img src="${video.image!staticRoot+"/images/videoimage.jpg"}" alt="${video.title}" /></a></div> + <div class="image <#if video.completed>completed</#if>" id="${video.id}"><a href="#" onclick="playVideo('${video.id}'); return false"><img src="${video.image!staticRoot+"/images/videoimage.jpg"}" alt="${video.title}" /></a></div> <h2>${video.title}</h2> <span class="duration">${video.length}</span> </article> </#list> @@ -66,6 +66,17 @@ </article> </div> </div> + + <div id="videoplayer"> + <div class="close"><a href="#" onclick="closeVideo(); return false"><img src="${staticRoot}/images/close.png" alt="Close Video" /></a></div> + <div class="video"> + <video width="720" height="405" controls="controls"> + This video is not playable in your browser. + <a href="http://google.com/chrome">Try Chrome?</a> + </video> + </div> + </div> + </@commonpage> diff --git a/web/scripts/growth.js b/web/scripts/growth.js index b9a36b0..5bc30d4 100644 --- a/web/scripts/growth.js +++ b/web/scripts/growth.js @@ -126,7 +126,7 @@ function playVideo(videoId) { $.ajax({ type: "GET", - url: "videos/" + videoId + ".json", + url: location.href + "/videos/" + videoId + ".json", dataType: "json" }).done(function(data) { if (data == null) { @@ -175,6 +175,15 @@ function reportVideoComplete(data) $('#chapterprogress .progresslabel').html(percent); closeVideo(); + + $.ajax({ + type: "POST", + url: location.href + "/videos/" + videoId + ".json", + dataType: "json", + data: {'completed':'true'} + }).error(function(jqXHR, error) { + notice('Could not record video completiton due to ' + error + '. If the problem persists, please contact us.'); + }); if (completed == total) { chapterComplete(); diff --git a/web/style.css b/web/style.css index ac13249..026ca7c 100644 --- a/web/style.css +++ b/web/style.css @@ -177,7 +177,6 @@ footer a:hover { } .progressbar, .progress { - margin-top: 0.5em; margin-bottom: 0.5em; height: 10px; background: #eaeaea; |