Index: lams_common/src/java/org/lamsfoundation/lams/flux/FluxRegistry.java =================================================================== diff -u -rc1e3ca12a9ccb265363e2330dd91ce7bedbcfa35 -rf61af352afa0ddbfb791477732cbfe80425af47d --- lams_common/src/java/org/lamsfoundation/lams/flux/FluxRegistry.java (.../FluxRegistry.java) (revision c1e3ca12a9ccb265363e2330dd91ce7bedbcfa35) +++ lams_common/src/java/org/lamsfoundation/lams/flux/FluxRegistry.java (.../FluxRegistry.java) (revision f61af352afa0ddbfb791477732cbfe80425af47d) @@ -1,6 +1,7 @@ package org.lamsfoundation.lams.flux; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; @@ -9,8 +10,9 @@ public class FluxRegistry { private static final Map fluxRegistry = new ConcurrentHashMap<>(); private static final Map sinkRegistry = new ConcurrentHashMap<>(); + private static final Map> boundSinks = new ConcurrentHashMap<>(); - public static SharedSink initSink(String sinkName) { + private static SharedSink getSink(String sinkName) { SharedSink sink = sinkRegistry.get(sinkName); if (sink != null) { return sink; @@ -20,14 +22,32 @@ return sink; } + /** + * Binds sinks so an emit for one sink is also an emit for another + */ + public static void bindSink(String sourceSinkName, String targetSinkName, Function emitTransformer) { + // make sure that sinks exist + FluxRegistry.getSink(sourceSinkName); + FluxRegistry.getSink(targetSinkName); + + Map sourceSinkBindings = boundSinks.get(sourceSinkName); + if (sourceSinkBindings == null) { + sourceSinkBindings = new ConcurrentHashMap<>(); + boundSinks.put(sourceSinkName, sourceSinkBindings); + } + if (!sourceSinkBindings.containsKey(targetSinkName)) { + sourceSinkBindings.put(targetSinkName, emitTransformer); + } + } + public static void initFluxMap(String fluxName, String sinkName, Function fetchFunction, Integer throttleSeconds, Integer timeoutSeconds) { if (fluxRegistry.containsKey(fluxName)) { throw new IllegalArgumentException("FluxMap for \"" + fluxName + "\" was already initialised"); } SharedSink sink = sinkRegistry.get(sinkName); if (sink == null) { - sink = FluxRegistry.initSink(sinkName); + sink = FluxRegistry.getSink(sinkName); } FluxMap fluxMap = new FluxMap<>(fluxName, sink.getFlux(), fetchFunction, throttleSeconds, timeoutSeconds); @@ -43,10 +63,21 @@ } public static void emit(String sinkName, T item) { - SharedSink sink = sinkRegistry.get(sinkName); - if (sink == null) { - throw new IllegalArgumentException("Sink for \"" + sinkName + "\" was not initialised"); + if (item == null) { + return; } + + SharedSink sink = sinkRegistry.get(sinkName); sink.emit(item); + + // check for bound sinks + Map sinkBindings = boundSinks.get(sinkName); + if (sinkBindings == null) { + return; + } + for (Entry binding : sinkBindings.entrySet()) { + FluxRegistry.emit(binding.getKey(), binding.getValue().apply(item)); + } + } } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/lesson/util/LearnerProgressFluxItem.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/lesson/util/LearnerProgressFluxItem.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/lesson/util/LearnerProgressFluxItem.java (revision f61af352afa0ddbfb791477732cbfe80425af47d) @@ -0,0 +1,28 @@ +package org.lamsfoundation.lams.lesson.util; + +/** + * Flux item emitted on learner moving from one activity to another by himself + */ +public class LearnerProgressFluxItem { + private long lessonId; + private long activityId; + private int userId; + + public LearnerProgressFluxItem(long lessonId, long activityId, int userId) { + this.lessonId = lessonId; + this.activityId = activityId; + this.userId = userId; + } + + public long getLessonId() { + return lessonId; + } + + public long getActivityId() { + return activityId; + } + + public int getUserId() { + return userId; + } +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/util/CommonConstants.java =================================================================== diff -u -rc1e3ca12a9ccb265363e2330dd91ce7bedbcfa35 -rf61af352afa0ddbfb791477732cbfe80425af47d --- lams_common/src/java/org/lamsfoundation/lams/util/CommonConstants.java (.../CommonConstants.java) (revision c1e3ca12a9ccb265363e2330dd91ce7bedbcfa35) +++ lams_common/src/java/org/lamsfoundation/lams/util/CommonConstants.java (.../CommonConstants.java) (revision f61af352afa0ddbfb791477732cbfe80425af47d) @@ -67,6 +67,10 @@ "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "ZA", "ZM", "ZW" }; - // flux management - public static final String ACTIVITY_COMPLETED_SINK_NAME = "activity completed"; + // FLUX sinks + + // updated when a learner completes an activity by himself + public static final String ACTIVITY_COMPLETED_SINK_NAME = "activity completed by learner"; + // updated when a there was a change to lesson progress + public static final String LESSON_PROGRESSED_SINK_NAME = "lesson progress changed"; } Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/CompleteActivityController.java =================================================================== diff -u -rc1e3ca12a9ccb265363e2330dd91ce7bedbcfa35 -rf61af352afa0ddbfb791477732cbfe80425af47d --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/CompleteActivityController.java (.../CompleteActivityController.java) (revision c1e3ca12a9ccb265363e2330dd91ce7bedbcfa35) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/CompleteActivityController.java (.../CompleteActivityController.java) (revision f61af352afa0ddbfb791477732cbfe80425af47d) @@ -39,6 +39,7 @@ import org.lamsfoundation.lams.learning.web.util.LearningWebUtil; import org.lamsfoundation.lams.learningdesign.Activity; import org.lamsfoundation.lams.lesson.LearnerProgress; +import org.lamsfoundation.lams.lesson.util.LearnerProgressFluxItem; import org.lamsfoundation.lams.util.CommonConstants; import org.lamsfoundation.lams.util.WebUtil; import org.lamsfoundation.lams.web.util.AttributeNames; @@ -121,7 +122,8 @@ } // notify all event subscribers that a learner finished an activity - FluxRegistry.emit(CommonConstants.ACTIVITY_COMPLETED_SINK_NAME, lessonId); + FluxRegistry.emit(CommonConstants.ACTIVITY_COMPLETED_SINK_NAME, + new LearnerProgressFluxItem(lessonId, activityId, learnerId)); return forward; Index: lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/MonitoringController.java =================================================================== diff -u -rc1e3ca12a9ccb265363e2330dd91ce7bedbcfa35 -rf61af352afa0ddbfb791477732cbfe80425af47d --- lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/MonitoringController.java (.../MonitoringController.java) (revision c1e3ca12a9ccb265363e2330dd91ce7bedbcfa35) +++ lams_monitoring/src/java/org/lamsfoundation/lams/monitoring/web/MonitoringController.java (.../MonitoringController.java) (revision f61af352afa0ddbfb791477732cbfe80425af47d) @@ -73,6 +73,7 @@ import org.lamsfoundation.lams.lesson.Lesson; import org.lamsfoundation.lams.lesson.dto.LessonDetailsDTO; import org.lamsfoundation.lams.lesson.service.ILessonService; +import org.lamsfoundation.lams.lesson.util.LearnerProgressFluxItem; import org.lamsfoundation.lams.logevent.LogEvent; import org.lamsfoundation.lams.logevent.service.ILogEventService; import org.lamsfoundation.lams.monitoring.MonitoringConstants; @@ -155,8 +156,12 @@ private IAuthoringService authoringService; public MonitoringController() { + // bind sinks so a learner finishing an activity also triggers an update in lesson progress + FluxRegistry.bindSink(CommonConstants.ACTIVITY_COMPLETED_SINK_NAME, CommonConstants.LESSON_PROGRESSED_SINK_NAME, + learnerProgressFluxItem -> ((LearnerProgressFluxItem) learnerProgressFluxItem).getLessonId()); + FluxRegistry.initFluxMap(MonitoringConstants.CANVAS_REFRESH_FLUX_NAME, - CommonConstants.ACTIVITY_COMPLETED_SINK_NAME, (Function) lessonId -> "doRefresh", + CommonConstants.LESSON_PROGRESSED_SINK_NAME, (Function) lessonId -> "doRefresh", CANVAS_REFRESH_FLUX_THROTTLE, FluxMap.STANDARD_TIMEOUT); }