summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/com/p4square/grow/frontend/TrainingPageResource.java88
-rw-r--r--src/templates/templates/training.ftl15
-rw-r--r--web/scripts/growth.js6
-rw-r--r--web/style.css21
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 f71f784..3ad3297 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%;