Index: lams_tool_doku/.classpath =================================================================== diff -u -rd6fa07234d396367e63b1b59db70e70d0e7ccb60 -r47200ab94fd2651b62702c9e4f2eb6eb989a08c1 --- lams_tool_doku/.classpath (.../.classpath) (revision d6fa07234d396367e63b1b59db70e70d0e7ccb60) +++ lams_tool_doku/.classpath (.../.classpath) (revision 47200ab94fd2651b62702c9e4f2eb6eb989a08c1) @@ -26,5 +26,6 @@ + Index: lams_tool_doku/build.xml =================================================================== diff -u -rd6fa07234d396367e63b1b59db70e70d0e7ccb60 -r47200ab94fd2651b62702c9e4f2eb6eb989a08c1 --- lams_tool_doku/build.xml (.../build.xml) (revision d6fa07234d396367e63b1b59db70e70d0e7ccb60) +++ lams_tool_doku/build.xml (.../build.xml) (revision 47200ab94fd2651b62702c9e4f2eb6eb989a08c1) @@ -3,5 +3,24 @@ + + + + + + ${ant.project.name}: Copying additional Java classes to WAR + + Index: lams_tool_doku/conf/hibernate/mappings/org/lamsfoundation/lams/tool/dokumaran/model/Dokumaran.hbm.xml =================================================================== diff -u -r98c10a5949c04e6f923cb9ea1aaaefd845e4de41 -r47200ab94fd2651b62702c9e4f2eb6eb989a08c1 --- lams_tool_doku/conf/hibernate/mappings/org/lamsfoundation/lams/tool/dokumaran/model/Dokumaran.hbm.xml (.../Dokumaran.hbm.xml) (revision 98c10a5949c04e6f923cb9ea1aaaefd845e4de41) +++ lams_tool_doku/conf/hibernate/mappings/org/lamsfoundation/lams/tool/dokumaran/model/Dokumaran.hbm.xml (.../Dokumaran.hbm.xml) (revision 47200ab94fd2651b62702c9e4f2eb6eb989a08c1) @@ -100,6 +100,22 @@ column="content_id" unique="true" /> + + + + PROPAGATION_REQUIRED,-java.lang.Exception PROPAGATION_REQUIRED,-java.lang.Exception PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception + PROPAGATION_REQUIRED,-java.lang.Exception PROPAGATION_REQUIRED,-java.lang.Exception PROPAGATION_REQUIRED,-java.lang.Exception PROPAGATION_REQUIRED,-java.lang.Exception Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/model/Dokumaran.java =================================================================== diff -u -r98c10a5949c04e6f923cb9ea1aaaefd845e4de41 -r47200ab94fd2651b62702c9e4f2eb6eb989a08c1 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/model/Dokumaran.java (.../Dokumaran.java) (revision 98c10a5949c04e6f923cb9ea1aaaefd845e4de41) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/model/Dokumaran.java (.../Dokumaran.java) (revision 47200ab94fd2651b62702c9e4f2eb6eb989a08c1) @@ -54,6 +54,11 @@ private boolean useSelectLeaderToolOuput; private boolean allowMultipleLeaders; + + private int timeLimit; + + //date when teacher has started time counter (pressed start button) + private Date timeLimitLaunchedDate; private boolean showChat; @@ -299,8 +304,35 @@ public void setContentId(Long contentId) { this.contentId = contentId; } + + /** + * @return Returns the time limitation, that students have to complete an attempt. + */ + public int getTimeLimit() { + return timeLimit; + } /** + * @param timeLimit + * the time limitation, that students have to complete an attempt. + */ + public void setTimeLimit(int timeLimit) { + this.timeLimit = timeLimit; + } + + /** + * + * @return date when teacher has started time counter (pressed start button) + */ + public Date getTimeLimitLaunchedDate() { + return timeLimitLaunchedDate; + } + + public void setTimeLimitLaunchedDate(Date timeLimitLaunchedDate) { + this.timeLimitLaunchedDate = timeLimitLaunchedDate; + } + + /** * * @return */ Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/DokumaranService.java =================================================================== diff -u -r40a1c8bbca353fc6db4a252242d61a8448c82ef9 -r47200ab94fd2651b62702c9e4f2eb6eb989a08c1 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/DokumaranService.java (.../DokumaranService.java) (revision 40a1c8bbca353fc6db4a252242d61a8448c82ef9) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/DokumaranService.java (.../DokumaranService.java) (revision 47200ab94fd2651b62702c9e4f2eb6eb989a08c1) @@ -23,6 +23,7 @@ package org.lamsfoundation.lams.tool.dokumaran.service; +import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; @@ -69,6 +70,7 @@ import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranSession; import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranUser; import org.lamsfoundation.lams.tool.dokumaran.util.DokumaranToolContentHandler; +import org.lamsfoundation.lams.tool.dokumaran.web.action.LearningWebsocketServer; import org.lamsfoundation.lams.tool.exception.DataMissingException; import org.lamsfoundation.lams.tool.exception.ToolException; import org.lamsfoundation.lams.tool.service.ILamsToolService; @@ -268,8 +270,70 @@ return isLeaderResponseFinalized; } + + @Override + public void launchTimeLimit(Long toolContentId) throws JSONException, IOException { + Dokumaran dokumaran = getDokumaranByContentId(toolContentId); + dokumaran.setTimeLimitLaunchedDate(new Date()); + dokumaranDao.saveObject(dokumaran); + + LearningWebsocketServer.sendPageRefreshRequest(dokumaran.getContentId()); + } + + @Override + public void addOneMinute(Long toolContentId) throws JSONException, IOException { + Dokumaran dokumaran = getDokumaranByContentId(toolContentId); + + int timeLimit = dokumaran.getTimeLimit(); + if (timeLimit == 0) { + return; + } + + int newTimeLimit = 0; + if (checkTimeLimitExceeded(dokumaran)) { + int minutesPassedSinceStart = (int) ((System.currentTimeMillis() - dokumaran.getTimeLimitLaunchedDate().getTime()) / 1000/60); + newTimeLimit = minutesPassedSinceStart + 1; + // change negative to 0 + newTimeLimit = Math.max(0, newTimeLimit); + } else { + newTimeLimit = timeLimit + 1; + } + dokumaran.setTimeLimit(newTimeLimit); + dokumaranDao.saveObject(dokumaran); + + LearningWebsocketServer.sendAddOneMinuteRequest(dokumaran.getContentId()); + } @Override + public long getSecondsLeft(Dokumaran dokumaran) { + + long secondsLeft = 0; + if (dokumaran.getTimeLimit() != 0) { + // if teacher has started the time limit already - calculate remaining time, and full time otherwise + secondsLeft = dokumaran.getTimeLimitLaunchedDate() == null ? dokumaran.getTimeLimit() * 60 + : dokumaran.getTimeLimit() * 60 + - (System.currentTimeMillis() - dokumaran.getTimeLimitLaunchedDate().getTime()) / 1000; + // change negative to 0 + secondsLeft = Math.max(0, secondsLeft); + } + + return secondsLeft; + } + + @Override + public boolean checkTimeLimitExceeded(Dokumaran dokumaran) { + int timeLimit = dokumaran.getTimeLimit(); + if (timeLimit == 0) { + return false; + } + + // check if the time limit is exceeded + Date timeLimitLaunchedDate = dokumaran.getTimeLimitLaunchedDate(); + return (timeLimitLaunchedDate != null) + && timeLimitLaunchedDate.getTime() + timeLimit * 60000 < System.currentTimeMillis(); + } + + @Override public void saveUser(DokumaranUser dokumaranUser) { dokumaranUserDao.saveObject(dokumaranUser); } @@ -1070,6 +1134,7 @@ dokumaran.setInstructions(toolContentJSON.getString(RestTags.INSTRUCTIONS)); dokumaran.setCreated(updateDate); + dokumaran.setTimeLimit(JsonUtil.opt(toolContentJSON, "timeLimit", 0)); dokumaran.setShowChat(JsonUtil.opt(toolContentJSON, "showChat", Boolean.FALSE)); dokumaran.setShowLineNumbers(JsonUtil.opt(toolContentJSON, "showLineNumbers", Boolean.FALSE)); dokumaran.setSharedPadId(JsonUtil.opt(toolContentJSON, "sharedPadId", (String) null)); Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/IDokumaranService.java =================================================================== diff -u -r16c98c95fc32882d9f80529722d7b62c5486e7fb -r47200ab94fd2651b62702c9e4f2eb6eb989a08c1 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/IDokumaranService.java (.../IDokumaranService.java) (revision 16c98c95fc32882d9f80529722d7b62c5486e7fb) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/IDokumaranService.java (.../IDokumaranService.java) (revision 47200ab94fd2651b62702c9e4f2eb6eb989a08c1) @@ -23,11 +23,13 @@ package org.lamsfoundation.lams.tool.dokumaran.service; +import java.io.IOException; import java.net.URISyntaxException; import java.util.List; import javax.servlet.http.Cookie; +import org.apache.tomcat.util.json.JSONException; import org.lamsfoundation.lams.notebook.model.NotebookEntry; import org.lamsfoundation.lams.tool.dokumaran.dto.ReflectDTO; import org.lamsfoundation.lams.tool.dokumaran.dto.SessionDTO; @@ -103,6 +105,31 @@ */ boolean isLeaderResponseFinalized(Long toolSessionId); + /** + * Stores date when user has started activity with time limit. + * + * @param toolContentId + * @throws IOException + * @throws JSONException + */ + void launchTimeLimit(Long toolContentId) throws JSONException, IOException; + + void addOneMinute(Long toolContentId) throws JSONException, IOException; + + /** + * Calculates how many seconds left till the time limit will expire. + * + * @param assessment + * @return + */ + long getSecondsLeft(Dokumaran dokumaran); + + /** + * @param assessment + * @return whether the time limit is exceeded already + */ + boolean checkTimeLimitExceeded(Dokumaran dokumaran); + Cookie createEtherpadCookieForLearner(DokumaranUser user, DokumaranSession session) throws DokumaranConfigurationException, URISyntaxException, DokumaranApplicationException; Cookie createEtherpadCookieForMonitor(UserDTO user, Long contentId) throws DokumaranConfigurationException, URISyntaxException; Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/LearningAction.java =================================================================== diff -u -r16c98c95fc32882d9f80529722d7b62c5486e7fb -r47200ab94fd2651b62702c9e4f2eb6eb989a08c1 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/LearningAction.java (.../LearningAction.java) (revision 16c98c95fc32882d9f80529722d7b62c5486e7fb) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/LearningAction.java (.../LearningAction.java) (revision 47200ab94fd2651b62702c9e4f2eb6eb989a08c1) @@ -54,12 +54,10 @@ import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranUser; import org.lamsfoundation.lams.tool.dokumaran.service.DokumaranApplicationException; import org.lamsfoundation.lams.tool.dokumaran.service.DokumaranConfigurationException; -import org.lamsfoundation.lams.tool.dokumaran.service.DokumaranService; import org.lamsfoundation.lams.tool.dokumaran.service.IDokumaranService; import org.lamsfoundation.lams.tool.dokumaran.web.form.ReflectionForm; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; -import org.lamsfoundation.lams.util.HashUtil; import org.lamsfoundation.lams.util.WebUtil; import org.lamsfoundation.lams.web.session.SessionManager; import org.lamsfoundation.lams.web.util.AttributeNames; @@ -124,6 +122,7 @@ Long toolSessionId = new Long(request.getParameter(DokumaranConstants.PARAM_TOOL_SESSION_ID)); IDokumaranService service = getDokumaranService(); Dokumaran dokumaran = service.getDokumaranBySessionId(toolSessionId); + request.setAttribute(DokumaranConstants.ATTR_TOOL_CONTENT_ID, dokumaran.getContentId()); DokumaranSession session = service.getDokumaranSessionBySessionId(toolSessionId); // get back the dokumaran and item list and display them on page @@ -166,6 +165,11 @@ request.setAttribute(DokumaranConstants.ATTR_DOKUMARAN, dokumaran); return mapping.findForward("waitforleader"); } + //time limit is set but hasn't yet launched by a teacher - show waitForTimeLimitLaunch page + if (dokumaran.getTimeLimit() > 0 && dokumaran.getTimeLimitLaunchedDate() == null) { + return mapping.findForward("waitForTimeLimitLaunch"); + } + boolean isUserLeader = (user != null) && service.isUserLeader(leaders, user.getUserId()); // check whether finish lock is on/off @@ -222,9 +226,16 @@ String etherpadServerUrl = etherpadServerUrlConfig.getConfigValue(); request.setAttribute(DokumaranConstants.KEY_ETHERPAD_SERVER_URL, etherpadServerUrl); + //time limit + boolean isTimeLimitEnabled = hasEditRight && !finishedLock && dokumaran.getTimeLimit() != 0; + long secondsLeft = isTimeLimitEnabled ? service.getSecondsLeft(dokumaran) : 0; + request.setAttribute(DokumaranConstants.ATTR_SECONDS_LEFT, secondsLeft); + + boolean isTimeLimitExceeded = service.checkTimeLimitExceeded(dokumaran); + String padId = session.getPadId(); - //in case of non-leader or finished lock - show Etherpad in readonly mode - if (dokumaran.isUseSelectLeaderToolOuput() && !isUserLeader || finishedLock) { + //in case of non-leader or finished lock or isTimeLimitExceeded - show Etherpad in readonly mode + if (dokumaran.isUseSelectLeaderToolOuput() && !isUserLeader || finishedLock || isTimeLimitExceeded) { padId = session.getEtherpadReadOnlyId(); //in case Etherpad didn't have enough time to initialize - show notconfigured.jsp if (padId == null) { Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/LearningWebsocketServer.java =================================================================== diff -u --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/LearningWebsocketServer.java (revision 0) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/LearningWebsocketServer.java (revision 47200ab94fd2651b62702c9e4f2eb6eb989a08c1) @@ -0,0 +1,123 @@ +package org.lamsfoundation.lams.tool.dokumaran.web.action; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import javax.websocket.CloseReason; +import javax.websocket.CloseReason.CloseCodes; +import javax.websocket.OnClose; +import javax.websocket.OnOpen; +import javax.websocket.Session; +import javax.websocket.server.ServerEndpoint; + +import org.apache.log4j.Logger; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; +import org.lamsfoundation.lams.web.util.AttributeNames; + +/** + * Sends time limit start and +1min events to learners. + * + * @author Marcin Cieslak + * @author Andrey Balan + */ +@ServerEndpoint("/learningWebsocket") +public class LearningWebsocketServer { + + private static Logger log = Logger.getLogger(LearningWebsocketServer.class); + + private static final Map> websockets = Collections + .synchronizedMap(new TreeMap>()); + + /** + * Registeres the Learner for processing by SendWorker. + */ + @OnOpen + public void registerUser(Session websocket) throws JSONException, IOException { + Long toolContentID = Long + .valueOf(websocket.getRequestParameterMap().get(AttributeNames.PARAM_TOOL_CONTENT_ID).get(0)); + Set toolContentWebsockets = websockets.get(toolContentID); + if (toolContentWebsockets == null) { + toolContentWebsockets = Collections.synchronizedSet(new HashSet()); + websockets.put(toolContentID, toolContentWebsockets); + } + toolContentWebsockets.add(websocket); + + if (log.isDebugEnabled()) { + log.debug("User " + websocket.getUserPrincipal().getName() + " entered Dokumaran with toolContentId: " + + toolContentID); + } + } + + /** + * When user leaves the activity. + */ + @OnClose + public void unregisterUser(Session websocket, CloseReason reason) { + Long toolContentID = Long + .valueOf(websocket.getRequestParameterMap().get(AttributeNames.PARAM_TOOL_CONTENT_ID).get(0)); + websockets.get(toolContentID).remove(websocket); + + if (log.isDebugEnabled()) { + // If there was something wrong with the connection, put it into logs. + log.debug("User " + websocket.getUserPrincipal().getName() + " left Dokumaran with Tool Content ID: " + + toolContentID + + (!(reason.getCloseCode().equals(CloseCodes.GOING_AWAY) + || reason.getCloseCode().equals(CloseCodes.NORMAL_CLOSURE)) + ? ". Abnormal close. Code: " + reason.getCloseCode() + ". Reason: " + + reason.getReasonPhrase() + : "")); + } + } + + /** + * Monitor has added one more minute to the time limit. All learners will need + * to add +1 minute to their countdown counters. + */ + public static void sendAddOneMinuteRequest(Long toolContentID) throws JSONException, IOException { + Set toolContentWebsockets = websockets.get(toolContentID); + if (toolContentWebsockets == null) { + return; + } + // make a copy of the websocket collection so it does not get blocked while sending messages + toolContentWebsockets = new HashSet(toolContentWebsockets); + + JSONObject responseJSON = new JSONObject(); + responseJSON.put("addOneMinute", true); + String response = responseJSON.toString(); + + for (Session websocket : toolContentWebsockets) { + if (websocket.isOpen()) { + websocket.getBasicRemote().sendText(response); + } + } + } + + /** + * Monitor has launched time limit. All learners will need to refresh the page in order to stop showing them + * waitForTimeLimitLaunch page. + */ + public static void sendPageRefreshRequest(Long toolContentID) throws JSONException, IOException { + Set toolContentWebsockets = websockets.get(toolContentID); + if (toolContentWebsockets == null) { + return; + } + // make a copy of the websocket collection so it does not get blocked while sending messages + toolContentWebsockets = new HashSet(toolContentWebsockets); + + JSONObject responseJSON = new JSONObject(); + responseJSON.put("pageRefresh", true); + String response = responseJSON.toString(); + + for (Session websocket : toolContentWebsockets) { + if (websocket.isOpen()) { + websocket.getBasicRemote().sendText(response); + } + } + } + +} \ No newline at end of file Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/MonitoringAction.java =================================================================== diff -u -r5aed68d35341e5fe14c078eb76377c0aae9e51d8 -r47200ab94fd2651b62702c9e4f2eb6eb989a08c1 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/MonitoringAction.java (.../MonitoringAction.java) (revision 5aed68d35341e5fe14c078eb76377c0aae9e51d8) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/MonitoringAction.java (.../MonitoringAction.java) (revision 47200ab94fd2651b62702c9e4f2eb6eb989a08c1) @@ -75,6 +75,10 @@ return summary(mapping, form, request, response); } else if (param.equals("fixFaultySession")) { return fixFaultySession(mapping, form, request, response); + } else if (param.equals("launchTimeLimit")) { + return launchTimeLimit(mapping, form, request, response); + } else if (param.equals("addOneMinute")) { + return addOneMinute(mapping, form, request, response); } return mapping.findForward(DokumaranConstants.ERROR); @@ -105,6 +109,11 @@ List relectList = service.getReflectList(contentId); sessionMap.put(DokumaranConstants.ATTR_REFLECT_LIST, relectList); } + + //time limit + boolean isTimeLimitEnabled = dokumaran.getTimeLimit() != 0; + long secondsLeft = isTimeLimitEnabled ? service.getSecondsLeft(dokumaran) : 0; + sessionMap.put(DokumaranConstants.ATTR_SECONDS_LEFT, secondsLeft); // cache into sessionMap sessionMap.put(DokumaranConstants.ATTR_SUMMARY_LIST, groupList); @@ -141,7 +150,6 @@ IDokumaranService service = getDokumaranService(); Long toolSessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); DokumaranSession session = service.getDokumaranSessionBySessionId(toolSessionId); - try { log.debug("Fixing faulty session (sessionId=" + toolSessionId + ")."); @@ -161,7 +169,37 @@ return null; } + + /** + * Stores date when user has started activity with time limit + * @throws IOException + * @throws JSONException + */ + private ActionForward launchTimeLimit(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException, IOException { + IDokumaranService service = getDokumaranService(); + Long toolContentId = WebUtil.readLongParam(request, DokumaranConstants.ATTR_TOOL_CONTENT_ID, false); + + service.launchTimeLimit(toolContentId); + return null; + } + + /** + * Stores date when user has started activity with time limit + * @throws IOException + * @throws JSONException + */ + private ActionForward addOneMinute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException, IOException { + IDokumaranService service = getDokumaranService(); + Long toolContentId = WebUtil.readLongParam(request, DokumaranConstants.ATTR_TOOL_CONTENT_ID, false); + + service.addOneMinute(toolContentId); + + return null; + } + // ************************************************************************************* // Private method // ************************************************************************************* Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/form/DokumaranForm.java =================================================================== diff -u -r98c10a5949c04e6f923cb9ea1aaaefd845e4de41 -r47200ab94fd2651b62702c9e4f2eb6eb989a08c1 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/form/DokumaranForm.java (.../DokumaranForm.java) (revision 98c10a5949c04e6f923cb9ea1aaaefd845e4de41) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/form/DokumaranForm.java (.../DokumaranForm.java) (revision 47200ab94fd2651b62702c9e4f2eb6eb989a08c1) @@ -71,6 +71,7 @@ // if it is start page, all data read out from database or current session // so need not reset checkbox to refresh value! if (!StringUtils.equals(param, "start") && !StringUtils.equals(param, "initPage")) { + dokumaran.setTimeLimit(0); dokumaran.setShowChat(false); dokumaran.setShowLineNumbers(false); dokumaran.setLockWhenFinished(false); Index: lams_tool_doku/web/WEB-INF/struts-config.xml =================================================================== diff -u -r10ab0e7b6a09e2d42c72915ba4d44192bb040892 -r47200ab94fd2651b62702c9e4f2eb6eb989a08c1 --- lams_tool_doku/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision 10ab0e7b6a09e2d42c72915ba4d44192bb040892) +++ lams_tool_doku/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision 47200ab94fd2651b62702c9e4f2eb6eb989a08c1) @@ -90,6 +90,7 @@ parameter="start" > + @@ -121,7 +122,6 @@ parameter="submitReflection" scope="request"> - + + + + + + +
+ +
- +
Index: lams_tool_doku/web/pages/monitoring/summary.jsp =================================================================== diff -u -rb6788b7cd8583f3f0903e08dd640ccfe1d9c7e44 -r47200ab94fd2651b62702c9e4f2eb6eb989a08c1 --- lams_tool_doku/web/pages/monitoring/summary.jsp (.../summary.jsp) (revision b6788b7cd8583f3f0903e08dd640ccfe1d9c7e44) +++ lams_tool_doku/web/pages/monitoring/summary.jsp (.../summary.jsp) (revision 47200ab94fd2651b62702c9e4f2eb6eb989a08c1) @@ -4,11 +4,57 @@ <%@ page import="org.lamsfoundation.lams.tool.dokumaran.DokumaranConstants"%> + + + - + + + +