diff options
author | Jesse Morgan <jesse@jesterpm.net> | 2013-11-09 21:21:44 -0800 |
---|---|---|
committer | Jesse Morgan <jesse@jesterpm.net> | 2013-11-09 21:21:44 -0800 |
commit | 41eeace2b82271c8b5ea569ffe286a8a2f25216f (patch) | |
tree | 798e85491ac63454f4756a6fc292aaeed55602ff | |
parent | 0d90da39f77ac3cfa607a68bc59336bf0bdff240 (diff) |
Enforcing the viewing order of videos.
Also made the Outline links more noticeable.
-rw-r--r-- | src/com/p4square/grow/frontend/TrainingPageResource.java | 88 | ||||
-rw-r--r-- | src/templates/templates/training.ftl | 15 | ||||
-rw-r--r-- | web/scripts/growth.js | 6 | ||||
-rw-r--r-- | web/style.css | 21 |
4 files changed, 95 insertions, 35 deletions
diff --git a/src/com/p4square/grow/frontend/TrainingPageResource.java b/src/com/p4square/grow/frontend/TrainingPageResource.java index bf08a1a..311bc2c 100644 --- a/src/com/p4square/grow/frontend/TrainingPageResource.java +++ b/src/com/p4square/grow/frontend/TrainingPageResource.java @@ -5,9 +5,12 @@ package com.p4square.grow.frontend; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.HashMap; import freemarker.template.Template; @@ -44,6 +47,24 @@ import com.p4square.grow.provider.Provider; public class TrainingPageResource extends FreeMarkerPageResource { private static Logger cLog = Logger.getLogger(TrainingPageResource.class); + private static final String[] CHAPTERS = { "introduction", "seeker", "believer", "disciple", "teacher" }; + private static final Comparator<Map<String, Object>> VIDEO_COMPARATOR = new Comparator<Map<String, Object>>() { + @Override + public int compare(Map<String, Object> left, Map<String, Object> right) { + String leftNumberStr = (String) left.get("number"); + String rightNumberStr = (String) right.get("number"); + + if (leftNumberStr == null || rightNumberStr == null) { + return -1; + } + + int leftNumber = Integer.valueOf(leftNumberStr); + int rightNumber = Integer.valueOf(rightNumberStr); + + return leftNumber - rightNumber; + } + }; + private Config mConfig; private Template mTrainingTemplate; private JsonRequestClient mJsonClient; @@ -93,29 +114,51 @@ public class TrainingPageResource extends FreeMarkerPageResource { Playlist playlist = trainingRecord.getPlaylist(); Map<String, Boolean> chapters = playlist.getChapterStatuses(); - - // Get the current chapter (the lowest, incomplete chapter) - if (mChapter == null) { - int min = Integer.MAX_VALUE; - for (Map.Entry<String, Boolean> chapter : chapters.entrySet()) { - int index = chapterIndex(chapter.getKey()); - if (!chapter.getValue() && index < min) { - min = index; - mChapter = chapter.getKey(); + Map<String, Boolean> allowedChapters = new LinkedHashMap<String, Boolean>(); + + // The user is not allowed to view chapters after his highest completed chapter. + // In this loop we find which chapters are allowed and check if the user tried + // to skip ahead. + String defaultChapter = null; + boolean userTriedToSkip = false; + + boolean foundRequired = false; + for (String chapterId : CHAPTERS) { + boolean allowed = true; + + if (!foundRequired) { + if (!chapters.get(chapterId)) { + // The first incomplete chapter is the highest allowed chapter. + foundRequired = true; + defaultChapter = chapterId; + } + + } else { + allowed = false; + + if (chapterId.equals(mChapter)) { + userTriedToSkip = true; } } - if (mChapter == null) { - // Everything is completed... send them back to introduction. - mChapter = "introduction"; - } + allowedChapters.put(chapterId, allowed); + } + + if (defaultChapter == null) { + // Everything is completed... send them back to introduction. + defaultChapter = "introduction"; + } + if (mChapter == null || userTriedToSkip) { + // No chapter was specified or the user tried to skip ahead. + // Either case, redirect. String nextPage = mConfig.getString("dynamicRoot", ""); - nextPage += "/account/training/" + mChapter; + nextPage += "/account/training/" + defaultChapter; getResponse().redirectSeeOther(nextPage); return new StringRepresentation("Redirecting to " + nextPage); } + // Get videos for the chapter. List<Map<String, Object>> videos = null; { @@ -125,6 +168,7 @@ public class TrainingPageResource extends FreeMarkerPageResource { return null; } videos = (List<Map<String, Object>>) response.getMap().get("videos"); + Collections.sort(videos, VIDEO_COMPARATOR); } // Mark the completed videos as completed @@ -147,6 +191,7 @@ public class TrainingPageResource extends FreeMarkerPageResource { Map root = getRootObject(); root.put("chapter", mChapter); + root.put("isChapterAllowed", allowedChapters); root.put("chapterProgress", chapterProgress); root.put("videos", videos); @@ -181,17 +226,4 @@ public class TrainingPageResource extends FreeMarkerPageResource { return response; } - int chapterIndex(String chapter) { - if ("teacher".equals(chapter)) { - return 4; - } else if ("disciple".equals(chapter)) { - return 3; - } else if ("believer".equals(chapter)) { - return 2; - } else if ("seeker".equals(chapter)) { - return 1; - } else { - return 0; - } - } } diff --git a/src/templates/templates/training.ftl b/src/templates/templates/training.ftl index c560622..80c5ca4 100644 --- a/src/templates/templates/training.ftl +++ b/src/templates/templates/training.ftl @@ -24,7 +24,12 @@ <nav> <#assign chapters = ["introduction", "seeker", "believer", "disciple", "teacher"]> <#list chapters as x> - <a href="${dynamicRoot}/account/training/${x}" <#if x == chapter>class="current"</#if>>${x?capitalize}</a> + <#if isChapterAllowed[x]> + <a href="${dynamicRoot}/account/training/${x}" <#if x == chapter>class="current"</#if>>${x?capitalize}</a> + <#else> + <span class="disabled">${x?capitalize}</span> + </#if> + <#if x_has_next> - </#if> </#list> </nav> @@ -36,14 +41,18 @@ </div> <div id="videos"> + <#assign allowed = true> <#list videos as video> <article> - <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> + <div class="image <#if video.completed>completed</#if> <#if allowed>allowed</#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.number}. ${video.title}</h2> <span class="duration"><@hms seconds=video.length /></span> <#if (video.pdf!"") != ""> <span class="pdf"><a href="${video.pdf}" target="_blank">Outline</a></span> </#if> + <#if allowed && !video.completed> + <#assign allowed = false> + </#if> </article> </#list> </div> diff --git a/web/scripts/growth.js b/web/scripts/growth.js index 5f5b273..fa5e3a9 100644 --- a/web/scripts/growth.js +++ b/web/scripts/growth.js @@ -143,6 +143,11 @@ function sendAnswer(required) function playVideo(videoId) { + if (!$('#' + videoId).hasClass('allowed')) { + notice("You must watch the videos in order."); + return; + } + $.ajax({ type: "GET", url: location.href + "/videos/" + videoId + ".json", @@ -197,6 +202,7 @@ function reportVideoComplete(data) var completedBefore = $('#videos article .completed').length; $('#' + data.id).addClass('completed'); + $('#' + data.id).parent().next().children('div.image').addClass('allowed'); var completed = $('#videos article .completed').length; var total = $('#videos article').length; diff --git a/web/style.css b/web/style.css index ecad037..3e96a5d 100644 --- a/web/style.css +++ b/web/style.css @@ -7,7 +7,7 @@ html, body { a { color: #BDBDBD; - text-decoration: none; + text-decoration: underline; font-weight: bold; } @@ -75,6 +75,7 @@ header h1 { header h1 a { color: #7bc043; + text-decoration: none; } header h1 img { @@ -266,7 +267,7 @@ footer a:hover { #content nav a { text-decoration: none; - color: #eaeaea; + color: #BDBDBD; letter-spacing: 2px; font-weight: normal; } @@ -275,6 +276,10 @@ footer a:hover { color: #fd6000; } +#content nav .disabled { + color: #eaeaea; +} + #chapterprogress { margin: 2em auto 2em auto; width: 75%; @@ -306,14 +311,22 @@ footer a:hover { border-radius: 10px; } -#videos .image.completed a:before { +#videos .image.completed.allowed a:before { content: url('/images/complete.png'); position: absolute; top: 0; left: 0; } -#videos .image a:hover:before { +#videos .image.allowed a { + cursor: pointer; +} + +#videos .image a { + cursor: default; +} + +#videos .image.allowed a:hover:before { content: url('/images/play.png'); position: absolute; top: 50%; |