Index: lams_tool_doku/build.xml =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/build.xml (.../build.xml) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/build.xml (.../build.xml) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -18,7 +18,7 @@ ${ant.project.name}: Copying additional Java classes to WAR Fisheye: Tag 1cef918442124e8d987a285095a7504e3bc00461 refers to a dead (removed) revision in file `lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/AdminAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1cef918442124e8d987a285095a7504e3bc00461 refers to a dead (removed) revision in file `lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/AuthoringAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1cef918442124e8d987a285095a7504e3bc00461 refers to a dead (removed) revision in file `lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/ClearSessionAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1cef918442124e8d987a285095a7504e3bc00461 refers to a dead (removed) revision in file `lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/LearningAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1cef918442124e8d987a285095a7504e3bc00461 refers to a dead (removed) revision in file `lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/LearningWebsocketServer.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1cef918442124e8d987a285095a7504e3bc00461 refers to a dead (removed) revision in file `lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/MonitoringAction.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/AdminController.java =================================================================== diff -u --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/AdminController.java (revision 0) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/AdminController.java (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -0,0 +1,64 @@ +package org.lamsfoundation.lams.tool.dokumaran.web.controller; + +import javax.servlet.http.HttpServletRequest; + +import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranConfigItem; +import org.lamsfoundation.lams.tool.dokumaran.service.IDokumaranService; +import org.lamsfoundation.lams.tool.dokumaran.web.form.AdminForm; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * @author Andrey Balan + */ +@Controller +@RequestMapping("/ladoku11admin") +public class AdminController { + + @Autowired + @Qualifier("dokumaranService") + private IDokumaranService dokumaranService; + + @RequestMapping("") + public String unspecified(@ModelAttribute("ladoku11adminForm") AdminForm ladoku11adminForm, + HttpServletRequest request) { + + DokumaranConfigItem etherpadUrl = dokumaranService.getConfigItem(DokumaranConfigItem.KEY_ETHERPAD_URL); + if (etherpadUrl != null) { + ladoku11adminForm.setEtherpadUrl(etherpadUrl.getConfigValue()); + } + + DokumaranConfigItem apiKey = dokumaranService.getConfigItem(DokumaranConfigItem.KEY_API_KEY); + if (apiKey != null) { + ladoku11adminForm.setApiKey(apiKey.getConfigValue()); + } + + request.setAttribute("error", false); + return "pages/admin/config"; + } + + @RequestMapping("/saveContent") + public String saveContent(@ModelAttribute("ladoku11adminForm") AdminForm ladoku11adminForm, + HttpServletRequest request) { + + if (ladoku11adminForm.getApiKey() != null && !ladoku11adminForm.getApiKey().equals("")) { + + DokumaranConfigItem etherpadUrl = dokumaranService.getConfigItem(DokumaranConfigItem.KEY_ETHERPAD_URL); + etherpadUrl.setConfigValue(ladoku11adminForm.getEtherpadUrl()); + dokumaranService.saveOrUpdateDokumaranConfigItem(etherpadUrl); + + DokumaranConfigItem apiKey = dokumaranService.getConfigItem(DokumaranConfigItem.KEY_API_KEY); + apiKey.setConfigValue(ladoku11adminForm.getApiKey()); + dokumaranService.saveOrUpdateDokumaranConfigItem(apiKey); + + request.setAttribute("savedSuccess", true); + return "pages/admin/config"; + } else { + request.setAttribute("error", true); + return "pages/admin/config"; + } + } +} Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/AuthoringController.java =================================================================== diff -u --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/AuthoringController.java (revision 0) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/AuthoringController.java (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -0,0 +1,244 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.dokumaran.web.controller; + +import java.sql.Timestamp; +import java.util.Date; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.authoring.web.AuthoringConstants; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.tool.dokumaran.DokumaranConstants; +import org.lamsfoundation.lams.tool.dokumaran.model.Dokumaran; +import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranUser; +import org.lamsfoundation.lams.tool.dokumaran.service.IDokumaranService; +import org.lamsfoundation.lams.tool.dokumaran.web.form.DokumaranForm; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.lamsfoundation.lams.web.util.SessionMap; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * @author Steve.Ni + */ +@Controller +@RequestMapping("/authoring") +public class AuthoringController { + + private static Logger log = Logger.getLogger(AuthoringController.class); + + @Autowired + @Qualifier("dokumaranService") + private IDokumaranService dokumaranService; + + /** + * Read dokumaran data from database and put them into HttpSession. It will + * redirect to init.do directly after this method run successfully. + * + * This method will avoid read database again and lost un-saved resouce item + * lost when user "refresh page", + * + * @throws ServletException + * + */ + @RequestMapping("/start") + private String start(@ModelAttribute("authoringForm") DokumaranForm authoringForm, HttpServletRequest request) + throws ServletException { + ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); + request.setAttribute(AttributeNames.ATTR_MODE, mode.toString()); + return starting(authoringForm, request); + } + + @RequestMapping("/definelater") + private String definelater(@ModelAttribute("authoringForm") DokumaranForm authoringForm, HttpServletRequest request) + throws ServletException { + Long contentId = new Long(WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID)); + Dokumaran dokumaran = dokumaranService.getDokumaranByContentId(contentId); + + dokumaran.setDefineLater(true); + dokumaranService.saveOrUpdateDokumaran(dokumaran); + + //audit log the teacher has started editing activity in monitor + dokumaranService.auditLogStartEditingActivityInMonitor(contentId); + + request.setAttribute(AttributeNames.ATTR_MODE, ToolAccessMode.TEACHER.toString()); + return starting(authoringForm, request); + } + + private String starting(@ModelAttribute("authoringForm") DokumaranForm authoringForm, HttpServletRequest request) + throws ServletException { + + // save toolContentID into HTTPSession + Long contentId = new Long(WebUtil.readLongParam(request, DokumaranConstants.PARAM_TOOL_CONTENT_ID)); + + // get back the dokumaran and item list and display them on page + + Dokumaran dokumaran = null; + + // Get contentFolderID and save to form. + String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); + authoringForm.setContentFolderID(contentFolderID); + + // initial Session Map + SessionMap sessionMap = new SessionMap<>(); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + authoringForm.setSessionMapID(sessionMap.getSessionID()); + + try { + dokumaran = dokumaranService.getDokumaranByContentId(contentId); + // if dokumaran does not exist, try to use default content instead. + if (dokumaran == null) { + dokumaran = dokumaranService.getDefaultContent(contentId); + } + + authoringForm.setDokumaran(dokumaran); + } catch (Exception e) { + AuthoringController.log.error(e); + throw new ServletException(e); + } + + sessionMap.put(DokumaranConstants.ATTR_RESOURCE_FORM, authoringForm); + request.getSession().setAttribute(AttributeNames.PARAM_NOTIFY_CLOSE_URL, + request.getParameter(AttributeNames.PARAM_NOTIFY_CLOSE_URL)); + return "pages/authoring/start"; + } + + /** + * Display same entire authoring page content from HttpSession variable. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws ServletException + */ + + @RequestMapping("/init") + private String initPage(@ModelAttribute("authoringForm") DokumaranForm authoringForm, HttpServletRequest request) + throws ServletException { + String sessionMapID = WebUtil.readStrParam(request, DokumaranConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapID); + DokumaranForm existForm = (DokumaranForm) sessionMap.get(DokumaranConstants.ATTR_RESOURCE_FORM); + + try { + PropertyUtils.copyProperties(authoringForm, existForm); + } catch (Exception e) { + throw new ServletException(e); + } + + ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); + request.setAttribute(AttributeNames.ATTR_MODE, mode.toString()); + authoringForm.setMode(mode.toString()); + + return "pages/authoring/authoring"; + } + + /** + * This method will persist all inforamtion in this authoring page, include + * all dokumaran item, information etc. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + * @throws ServletException + */ + + @RequestMapping("/update") + private String updateContent(@ModelAttribute("authoringForm") DokumaranForm authoringForm, + HttpServletRequest request) throws Exception { + + // get back sessionMAP + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(authoringForm.getSessionMapID()); + ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); + Dokumaran dokumaran = authoringForm.getDokumaran(); + + // **********************************Get Dokumaran PO********************* + Dokumaran dokumaranPO = dokumaranService.getDokumaranByContentId(dokumaran.getContentId()); + if (dokumaranPO == null) { + // new Dokumaran, create it + dokumaranPO = dokumaran; + dokumaranPO.setCreated(new Timestamp(new Date().getTime())); + dokumaranPO.setUpdated(new Timestamp(new Date().getTime())); + + } else { + Long uid = dokumaranPO.getUid(); + PropertyUtils.copyProperties(dokumaranPO, dokumaran); + + // copyProperties() above may result in "collection assigned to two objects in a session" exception + // Below we remove reference to one of Assessment objects, + // so maybe there will be just one object in session when save is done + // If this fails, we may have to evict the object from session using DAO + authoringForm.setDokumaran(null); + dokumaran = null; + // get back UID + dokumaranPO.setUid(uid); + + // if it's a teacher - change define later status + if (mode.isTeacher()) { + dokumaranPO.setDefineLater(false); + } + dokumaranPO.setUpdated(new Timestamp(new Date().getTime())); + } + + // *******************************Handle user******************* + // try to get form system session + HttpSession ss = SessionManager.getSession(); + // get back login user DTO + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + DokumaranUser dokumaranUser = dokumaranService.getUserByIDAndContent(new Long(user.getUserID().intValue()), + dokumaranPO.getContentId()); + if (dokumaranUser == null) { + dokumaranUser = new DokumaranUser(user, dokumaranPO); + } + + dokumaranPO.setCreatedBy(dokumaranUser); + + // ***************************** finally persist dokumaranPO again + dokumaranService.saveOrUpdateDokumaran(dokumaranPO); + + authoringForm.setDokumaran(dokumaranPO); + + request.setAttribute(AuthoringConstants.LAMS_AUTHORING_SUCCESS_FLAG, Boolean.TRUE); + request.setAttribute(AttributeNames.ATTR_MODE, mode.toString()); + + return "pages/authoring/authoring"; + } + +} Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/ClearSessionController.java =================================================================== diff -u --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/ClearSessionController.java (revision 0) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/ClearSessionController.java (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -0,0 +1,64 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.dokumaran.web.controller; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.lamsfoundation.lams.authoring.web.LamsAuthoringFinishController; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.context.WebApplicationContext; + +/** + * This class give a chance to clear HttpSession when user save/close authoring page. + * + * @author Steve.Ni + * + * @version $Revision$ + */ +@Controller +public class ClearSessionController extends LamsAuthoringFinishController { + + @Autowired + private WebApplicationContext applicationContext; + + @RequestMapping("/clearsession") + public void execute(HttpServletRequest request, HttpServletResponse response) throws IOException { + super.execute(request, response, applicationContext); + } + + @Override + public void clearSession(String customiseSessionID, HttpSession session, ToolAccessMode mode) { + if (mode.isAuthor()) { + session.removeAttribute(customiseSessionID); + } + } + +} Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/LearningController.java =================================================================== diff -u --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/LearningController.java (revision 0) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/LearningController.java (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -0,0 +1,379 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.tool.dokumaran.web.controller; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.learning.web.bean.ActivityPositionDTO; +import org.lamsfoundation.lams.learning.web.util.LearningWebUtil; +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.tool.dokumaran.DokumaranConstants; +import org.lamsfoundation.lams.tool.dokumaran.model.Dokumaran; +import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranConfigItem; +import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranSession; +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.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.WebUtil; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.lamsfoundation.lams.web.util.SessionMap; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.context.WebApplicationContext; + +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * @author Steve.Ni + */ +@Controller +@RequestMapping("/learning") +public class LearningController { + + private static Logger log = Logger.getLogger(LearningController.class); + + @Autowired + @Qualifier("dokumaranService") + private IDokumaranService dokumaranService; + + @Autowired + private WebApplicationContext applicationContext; + + /** + * Read dokumaran data from database and put them into HttpSession. It will redirect to init.do directly after this + * method run successfully. + * + * This method will avoid read database again and lost un-saved resouce item lost when user "refresh page", + * + * @throws DokumaranConfigurationException + * @throws URISyntaxException + * + */ + @RequestMapping("/start") + private String start(HttpServletRequest request, HttpServletResponse response) + throws DokumaranConfigurationException, DokumaranApplicationException, URISyntaxException { + + // initial Session Map + SessionMap sessionMap = new SessionMap<>(); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + request.setAttribute(DokumaranConstants.ATTR_SESSION_MAP_ID, sessionMap.getSessionID()); + + ToolAccessMode mode = WebUtil.readToolAccessModeParam(request, AttributeNames.PARAM_MODE, true); + Long toolSessionId = new Long(request.getParameter(DokumaranConstants.PARAM_TOOL_SESSION_ID)); + Dokumaran dokumaran = dokumaranService.getDokumaranBySessionId(toolSessionId); + request.setAttribute(DokumaranConstants.ATTR_TOOL_CONTENT_ID, dokumaran.getContentId()); + DokumaranSession session = dokumaranService.getDokumaranSessionBySessionId(toolSessionId); + + // get back the dokumaran and item list and display them on page + DokumaranUser user = null; + boolean isFirstTimeAccess = false; + if ((mode != null) && mode.isTeacher()) { + // monitoring mode - user is specified in URL + // dokumaranUser may be null if the user was force completed. + user = getSpecifiedUser(dokumaranService, toolSessionId, WebUtil.readIntParam(request, AttributeNames.PARAM_USER_ID, false)); + } else { + // get back login user DTO + HttpSession ss = SessionManager.getSession(); + UserDTO userDto = (UserDTO) ss.getAttribute(AttributeNames.USER); + user = dokumaranService.getUserByIDAndSession(new Long(userDto.getUserID().intValue()), toolSessionId); + if (user == null) { + user = new DokumaranUser(userDto, session); + dokumaranService.saveUser(user); + isFirstTimeAccess = true; + } + } + + // support for leader select feature + List leaders = dokumaran.isUseSelectLeaderToolOuput() + ? dokumaranService.checkLeaderSelectToolForSessionLeader(user, new Long(toolSessionId).longValue(), + isFirstTimeAccess) + : new ArrayList<>(); + // forwards to the leaderSelection page + if (dokumaran.isUseSelectLeaderToolOuput() && leaders.isEmpty() && !mode.isTeacher()) { + + // get group users and store it to request as DTO objects + List groupUsers = dokumaranService.getUsersBySession(toolSessionId); + List groupUserDtos = new ArrayList<>(); + for (DokumaranUser groupUser : groupUsers) { + User groupUserDto = new User(); + groupUserDto.setFirstName(groupUser.getFirstName()); + groupUserDto.setLastName(groupUser.getLastName()); + groupUserDtos.add(groupUserDto); + } + request.setAttribute(DokumaranConstants.ATTR_GROUP_USERS, groupUserDtos); + request.setAttribute(DokumaranConstants.ATTR_DOKUMARAN, dokumaran); + return "pages/learning/waitforleader"; + } + //time limit is set but hasn't yet launched by a teacher - show waitForTimeLimitLaunch page + if (dokumaran.getTimeLimit() > 0 && dokumaran.getTimeLimitLaunchedDate() == null) { + return "pages/learning/waitForTimeLimitLaunch"; + } + + boolean isUserLeader = (user != null) && dokumaranService.isUserLeader(leaders, user.getUserId()); + + // check whether finish lock is on/off + boolean finishedLock = dokumaran.getLockWhenFinished() && (user != null) && user.isSessionFinished(); + boolean hasEditRight = !dokumaran.isUseSelectLeaderToolOuput() + || dokumaran.isUseSelectLeaderToolOuput() && isUserLeader; + + // basic information + sessionMap.put(DokumaranConstants.ATTR_TITLE, dokumaran.getTitle()); + sessionMap.put(DokumaranConstants.ATTR_INSTRUCTIONS, dokumaran.getInstructions()); + sessionMap.put(DokumaranConstants.ATTR_FINISH_LOCK, finishedLock); + sessionMap.put(DokumaranConstants.ATTR_LOCK_ON_FINISH, dokumaran.getLockWhenFinished()); + sessionMap.put(DokumaranConstants.ATTR_USER_FINISHED, (user != null) && user.isSessionFinished()); + sessionMap.put(DokumaranConstants.ATTR_HAS_EDIT_RIGHT, hasEditRight); + sessionMap.put(DokumaranConstants.ATTR_IS_LEADER_RESPONSE_FINALIZED, + dokumaranService.isLeaderResponseFinalized(leaders)); + sessionMap.put(AttributeNames.PARAM_TOOL_SESSION_ID, toolSessionId); + sessionMap.put(AttributeNames.ATTR_MODE, mode); + + // reflection information + String entryText = new String(); + if (user != null) { + NotebookEntry notebookEntry = dokumaranService.getEntry(toolSessionId, CoreNotebookConstants.NOTEBOOK_TOOL, + DokumaranConstants.TOOL_SIGNATURE, user.getUserId().intValue()); + if (notebookEntry != null) { + entryText = notebookEntry.getEntry(); + } + } + sessionMap.put(DokumaranConstants.ATTR_REFLECTION_ON, dokumaran.isReflectOnActivity()); + sessionMap.put(DokumaranConstants.ATTR_REFLECTION_INSTRUCTION, dokumaran.getReflectInstructions()); + sessionMap.put(DokumaranConstants.ATTR_REFLECTION_ENTRY, entryText); + + // add define later support + if (dokumaran.isDefineLater()) { + return "pages/learning/definelater"; + } + + // set contentInUse flag to true! + dokumaran.setContentInUse(true); + dokumaran.setDefineLater(false); + dokumaranService.saveOrUpdateDokumaran(dokumaran); + + ActivityPositionDTO activityPosition = LearningWebUtil.putActivityPositionInRequestByToolSessionId( + toolSessionId, request, applicationContext.getServletContext()); + sessionMap.put(AttributeNames.ATTR_ACTIVITY_POSITION, activityPosition); + + sessionMap.put(DokumaranConstants.ATTR_DOKUMARAN, dokumaran); + + // get the API key from the config table and add it to the session + DokumaranConfigItem etherpadServerUrlConfig = dokumaranService + .getConfigItem(DokumaranConfigItem.KEY_ETHERPAD_URL); + DokumaranConfigItem apiKeyConfig = dokumaranService.getConfigItem(DokumaranConfigItem.KEY_API_KEY); + if (apiKeyConfig == null || apiKeyConfig.getConfigValue() == null || etherpadServerUrlConfig == null + || etherpadServerUrlConfig.getConfigValue() == null) { + return "pages/learning/notconfigured"; + } + String etherpadServerUrl = etherpadServerUrlConfig.getConfigValue(); + request.setAttribute(DokumaranConstants.KEY_ETHERPAD_SERVER_URL, etherpadServerUrl); + + //time limit + boolean isTimeLimitEnabled = hasEditRight && !finishedLock && dokumaran.getTimeLimit() != 0; + long secondsLeft = isTimeLimitEnabled ? dokumaranService.getSecondsLeft(dokumaran) : 0; + request.setAttribute(DokumaranConstants.ATTR_SECONDS_LEFT, secondsLeft); + + boolean isTimeLimitExceeded = dokumaranService.checkTimeLimitExceeded(dokumaran); + + String padId = session.getPadId(); + //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) { + return "pages/learning/notconfigured"; + } + } + request.setAttribute(DokumaranConstants.ATTR_PAD_ID, padId); + + //add new sessionID cookie in order to access pad + if (user != null) { + Cookie etherpadSessionCookie = dokumaranService.createEtherpadCookieForLearner(user, session); + response.addCookie(etherpadSessionCookie); + } + + return "pages/learning/learning"; + } + + /** + * Checks Leader Progress + */ + @RequestMapping("/checkLeaderProgress") + private String checkLeaderProgress(HttpServletRequest request, HttpServletResponse response) throws IOException { + + Long toolSessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + + boolean isLeaderResponseFinalized = dokumaranService.isLeaderResponseFinalized(toolSessionId); + + ObjectNode responseJSON = JsonNodeFactory.instance.objectNode(); + responseJSON.put(DokumaranConstants.ATTR_IS_LEADER_RESPONSE_FINALIZED, isLeaderResponseFinalized); + response.setContentType("application/x-json;charset=utf-8"); + response.getWriter().print(responseJSON); + return responseJSON.toString(); + } + + /** + * Finish learning session. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + @RequestMapping("/finish") + private String finish(@ModelAttribute("reflectionForm") ReflectionForm reflectionForm, HttpServletRequest request) { + + // get back SessionMap + String sessionMapID = request.getParameter(DokumaranConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapID); + + // get mode and ToolSessionID from sessionMAP + ToolAccessMode mode = (ToolAccessMode) sessionMap.get(AttributeNames.ATTR_MODE); + Long sessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); + + // get sessionId from HttpServletRequest + String nextActivityUrl = null; + try { + HttpSession ss = SessionManager.getSession(); + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + Long userID = new Long(user.getUserID().longValue()); + + nextActivityUrl = dokumaranService.finishToolSession(sessionId, userID); + request.setAttribute(DokumaranConstants.ATTR_NEXT_ACTIVITY_URL, nextActivityUrl); + } catch (DokumaranApplicationException e) { + LearningController.log.error("Failed get next activity url:" + e.getMessage()); + } + + return "pages/learning/finish"; + } + + /** + * Display empty reflection form. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + @RequestMapping("/newReflection") + private String newReflection(@ModelAttribute("reflectionForm") ReflectionForm reflectionForm, + HttpServletRequest request) { + + // get session value + String sessionMapID = WebUtil.readStrParam(request, DokumaranConstants.ATTR_SESSION_MAP_ID); + HttpSession ss = SessionManager.getSession(); + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + + reflectionForm.setUserID(user.getUserID()); + reflectionForm.setSessionMapID(sessionMapID); + + // get the existing reflection entry + + SessionMap map = (SessionMap) request.getSession().getAttribute(sessionMapID); + Long toolSessionID = (Long) map.get(AttributeNames.PARAM_TOOL_SESSION_ID); + NotebookEntry entry = dokumaranService.getEntry(toolSessionID, CoreNotebookConstants.NOTEBOOK_TOOL, + DokumaranConstants.TOOL_SIGNATURE, user.getUserID()); + + if (entry != null) { + reflectionForm.setEntryText(entry.getEntry()); + } + + return "pages/learning/notebook"; + } + + /** + * Submit reflection form input database. + * + * @param mapping + * @param form + * @param request + * @param response + * @return + */ + @RequestMapping("/submitReflection") + private String submitReflection(@ModelAttribute("reflectionForm") ReflectionForm reflectionForm, + HttpServletRequest request) { + Integer userId = reflectionForm.getUserID(); + + String sessionMapID = WebUtil.readStrParam(request, DokumaranConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapID); + Long sessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); + + // check for existing notebook entry + NotebookEntry entry = dokumaranService.getEntry(sessionId, CoreNotebookConstants.NOTEBOOK_TOOL, + DokumaranConstants.TOOL_SIGNATURE, userId); + + if (entry == null) { + // create new entry + dokumaranService.createNotebookEntry(sessionId, CoreNotebookConstants.NOTEBOOK_TOOL, + DokumaranConstants.TOOL_SIGNATURE, userId, reflectionForm.getEntryText()); + } else { + // update existing entry + entry.setEntry(reflectionForm.getEntryText()); + entry.setLastModified(new Date()); + dokumaranService.updateEntry(entry); + } + + return finish(reflectionForm, request); + } + + // ************************************************************************************* + // Private method + // ************************************************************************************* + + private DokumaranUser getSpecifiedUser(IDokumaranService service, Long sessionId, Integer userId) { + DokumaranUser dokumaranUser = service.getUserByIDAndSession(new Long(userId.intValue()), sessionId); + if (dokumaranUser == null) { + LearningController.log.error( + "Unable to find specified user for dokumaran activity. Screens are likely to fail. SessionId=" + + sessionId + " UserId=" + userId); + } + return dokumaranUser; + } +} Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/LearningWebsocketServer.java =================================================================== diff -u --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/LearningWebsocketServer.java (revision 0) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/LearningWebsocketServer.java (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -0,0 +1,203 @@ +package org.lamsfoundation.lams.tool.dokumaran.web.controller; + +import java.io.IOException; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +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.lamsfoundation.lams.tool.dokumaran.DokumaranConstants; +import org.lamsfoundation.lams.tool.dokumaran.model.Dokumaran; +import org.lamsfoundation.lams.tool.dokumaran.service.IDokumaranService; +import org.lamsfoundation.lams.util.hibernate.HibernateSessionManager; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Sends time limit start and +1min events to learners. + * + * @author Marcin Cieslak + * @author Andrey Balan + */ +@ServerEndpoint("/learningWebsocket") +public class LearningWebsocketServer { + + /** + * A singleton which updates Learners with Leader selection. + */ + private static class SendWorker extends Thread { + private boolean stopFlag = false; + // how ofter the thread runs + private static final long CHECK_INTERVAL = 3000; + + @Override + public void run() { + while (!stopFlag) { + try { + // websocket communication bypasses standard HTTP filters, so Hibernate session needs to be initialised manually + HibernateSessionManager.openSession(); + Iterator>> entryIterator = LearningWebsocketServer.websockets.entrySet() + .iterator(); + // go through activities and update registered learners with reports and vote count + while (entryIterator.hasNext()) { + Entry> entry = entryIterator.next(); + Long toolContentId = entry.getKey(); + // if all learners left the activity, remove the obsolete mapping + Set dokuWebsockets = entry.getValue(); + if (dokuWebsockets.isEmpty()) { + entryIterator.remove(); + timeLimitCache.remove(toolContentId); + continue; + } + + Dokumaran dokumaran = LearningWebsocketServer.getDokumaranService() + .getDokumaranByContentId(toolContentId); + int timeLimit = dokumaran.getTimeLimit(); + if (dokumaran.getTimeLimitLaunchedDate() != null && timeLimit != 0) { + Integer cachedTimeLimit = timeLimitCache.get(toolContentId); + if (cachedTimeLimit == null) { + timeLimitCache.put(toolContentId, timeLimit); + LearningWebsocketServer.sendPageRefreshRequest(toolContentId); + } else if (!cachedTimeLimit.equals(timeLimit)) { + timeLimitCache.put(toolContentId, timeLimit); + LearningWebsocketServer.sendAddTimeRequest(toolContentId, timeLimit - cachedTimeLimit); + } + } + } + } catch (Exception e) { + // error caught, but carry on + LearningWebsocketServer.log.error("Error in Dokumaran worker thread", e); + } finally { + HibernateSessionManager.closeSession(); + try { + Thread.sleep(SendWorker.CHECK_INTERVAL); + } catch (InterruptedException e) { + LearningWebsocketServer.log.warn("Stopping Dokumaran worker thread"); + stopFlag = true; + } + } + } + } + }; + + private static final Logger log = Logger.getLogger(LearningWebsocketServer.class); + + private static final SendWorker sendWorker = new SendWorker(); + private static final Map> websockets = new ConcurrentHashMap<>(); + private static final Map timeLimitCache = new ConcurrentHashMap<>(); + + private static IDokumaranService dokumaranService; + + static { + // run the singleton thread + LearningWebsocketServer.sendWorker.start(); + } + + /** + * Registeres the Learner for processing. + */ + @OnOpen + public void registerUser(Session websocket) throws IOException { + Long toolContentID = Long + .valueOf(websocket.getRequestParameterMap().get(AttributeNames.PARAM_TOOL_CONTENT_ID).get(0)); + Set toolContentWebsockets = websockets.get(toolContentID); + if (toolContentWebsockets == null) { + toolContentWebsockets = ConcurrentHashMap.newKeySet(); + 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. + */ + private static void sendAddTimeRequest(Long toolContentId, int timeLimit) throws IOException { + Set toolContentWebsockets = websockets.get(toolContentId); + if (toolContentWebsockets == null) { + return; + } + + ObjectNode responseJSON = JsonNodeFactory.instance.objectNode(); + responseJSON.put("addTime", timeLimit); + 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. + */ + private static void sendPageRefreshRequest(Long toolContentId) throws IOException { + Set toolContentWebsockets = websockets.get(toolContentId); + if (toolContentWebsockets == null) { + return; + } + + ObjectNode responseJSON = JsonNodeFactory.instance.objectNode(); + responseJSON.put("pageRefresh", true); + String response = responseJSON.toString(); + + for (Session websocket : toolContentWebsockets) { + if (websocket.isOpen()) { + websocket.getBasicRemote().sendText(response); + } + } + } + + private static IDokumaranService getDokumaranService() { + if (dokumaranService == null) { + WebApplicationContext wac = WebApplicationContextUtils + .getRequiredWebApplicationContext(SessionManager.getServletContext()); + dokumaranService = (IDokumaranService) wac.getBean(DokumaranConstants.RESOURCE_SERVICE); + } + return dokumaranService; + } +} \ No newline at end of file Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/MonitoringController.java =================================================================== diff -u --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/MonitoringController.java (revision 0) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/MonitoringController.java (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -0,0 +1,188 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.tool.dokumaran.web.controller; + +import java.io.IOException; +import java.io.PrintWriter; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; + +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.tool.dokumaran.DokumaranConstants; +import org.lamsfoundation.lams.tool.dokumaran.dto.ReflectDTO; +import org.lamsfoundation.lams.tool.dokumaran.dto.SessionDTO; +import org.lamsfoundation.lams.tool.dokumaran.model.Dokumaran; +import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranConfigItem; +import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranSession; +import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranUser; +import org.lamsfoundation.lams.tool.dokumaran.service.DokumaranConfigurationException; +import org.lamsfoundation.lams.tool.dokumaran.service.IDokumaranService; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.lamsfoundation.lams.web.util.SessionMap; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +@Controller +@RequestMapping("/monitoring") +public class MonitoringController{ + + public static Logger log = Logger.getLogger(MonitoringController.class); + + @Autowired + @Qualifier("dokumaranService") + private IDokumaranService dokumaranService; + + + @RequestMapping("/summary") + private String summary(HttpServletRequest request, + HttpServletResponse response) throws DokumaranConfigurationException, URISyntaxException { + // initial Session Map + SessionMap sessionMap = new SessionMap(); + request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); + request.setAttribute(DokumaranConstants.ATTR_SESSION_MAP_ID, sessionMap.getSessionID()); + // save contentFolderID into session + sessionMap.put(AttributeNames.PARAM_CONTENT_FOLDER_ID, + WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID)); + + Long contentId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); + List groupList = dokumaranService.getSummary(contentId); + boolean hasFaultySession = false; + for (SessionDTO group : groupList) { + hasFaultySession |= group.isSessionFaulty(); + } + + Dokumaran dokumaran = dokumaranService.getDokumaranByContentId(contentId); + + // Create reflectList if reflection is enabled. + if (dokumaran.isReflectOnActivity()) { + List relectList = dokumaranService.getReflectList(contentId); + sessionMap.put(DokumaranConstants.ATTR_REFLECT_LIST, relectList); + } + + //time limit + boolean isTimeLimitEnabled = dokumaran.getTimeLimit() != 0; + long secondsLeft = isTimeLimitEnabled ? dokumaranService.getSecondsLeft(dokumaran) : 0; + sessionMap.put(DokumaranConstants.ATTR_SECONDS_LEFT, secondsLeft); + + // cache into sessionMap + sessionMap.put(DokumaranConstants.ATTR_SUMMARY_LIST, groupList); + sessionMap.put(DokumaranConstants.ATTR_HAS_FAULTY_SESSION, hasFaultySession); + sessionMap.put(DokumaranConstants.PAGE_EDITABLE, dokumaran.isContentInUse()); + sessionMap.put(DokumaranConstants.ATTR_DOKUMARAN, dokumaran); + sessionMap.put(DokumaranConstants.ATTR_TOOL_CONTENT_ID, contentId); + sessionMap.put(DokumaranConstants.ATTR_IS_GROUPED_ACTIVITY, dokumaranService.isGroupedActivity(contentId)); + + // get the API key from the config table and add it to the session + DokumaranConfigItem etherpadServerUrlConfig = dokumaranService.getConfigItem(DokumaranConfigItem.KEY_ETHERPAD_URL); + if (etherpadServerUrlConfig == null || etherpadServerUrlConfig.getConfigValue() == null) { + return "pages/learning/notconfigured"; + } + String etherpadServerUrl = etherpadServerUrlConfig.getConfigValue(); + request.setAttribute(DokumaranConstants.KEY_ETHERPAD_SERVER_URL, etherpadServerUrl); + + HttpSession ss = SessionManager.getSession(); + // get back login user DTO + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + + //no need to store cookie if there are no sessions created yet + if (!groupList.isEmpty()) { + // add new sessionID cookie in order to access pad + Cookie etherpadSessionCookie = dokumaranService.createEtherpadCookieForMonitor(user, contentId); + response.addCookie(etherpadSessionCookie); + } + + return "pages/monitoring/monitoring"; + } + + @RequestMapping("/fixFaultySession") + private void fixFaultySession(HttpServletRequest request, + HttpServletResponse response) throws DokumaranConfigurationException, ServletException, IOException { + Long toolSessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); + DokumaranSession session = dokumaranService.getDokumaranSessionBySessionId(toolSessionId); + + try { + log.debug("Fixing faulty session (sessionId=" + toolSessionId + ")."); + dokumaranService.createPad(session.getDokumaran(), session); + + } catch (Exception e) { + // printing out error cause + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + response.setContentType("text/html"); + PrintWriter out = response.getWriter(); + out.write("Failed! " + e.getMessage()); + out.flush(); + out.close(); + log.error("Failed! " + e.getMessage()); + } + + } + + /** + * Stores date when user has started activity with time limit + * @throws IOException + * @throws JSONException + */ + @RequestMapping("/launchTimeLimit") + private void launchTimeLimit(HttpServletRequest request) throws IOException { + Long toolContentId = WebUtil.readLongParam(request, DokumaranConstants.ATTR_TOOL_CONTENT_ID, false); + + dokumaranService.launchTimeLimit(toolContentId); + } + + /** + * Stores date when user has started activity with time limit + * @throws IOException + * @throws JSONException + */ + @RequestMapping("/addOneMinute") + private void addOneMinute(HttpServletRequest request) throws IOException { + Long toolContentId = WebUtil.readLongParam(request, DokumaranConstants.ATTR_TOOL_CONTENT_ID, false); + + dokumaranService.addOneMinute(toolContentId); + + } + +} Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/form/AdminForm.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/form/AdminForm.java (.../AdminForm.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/form/AdminForm.java (.../AdminForm.java) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -9,18 +9,12 @@ /** * */ -public class AdminForm extends ActionForm { +public class AdminForm{ private static final long serialVersionUID = 414425664356226L; private String etherpadUrl; private String apiKey; - @Override - public ActionErrors validate(ActionMapping arg0, HttpServletRequest arg1) { - ActionErrors ac = new ActionErrors(); -// ac.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("this is an error")); - return ac; - } public String getEtherpadUrl() { return etherpadUrl; Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/form/DokumaranForm.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/form/DokumaranForm.java (.../DokumaranForm.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/form/DokumaranForm.java (.../DokumaranForm.java) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -48,6 +48,8 @@ private int currentTab; private FormFile offlineFile; private FormFile onlineFile; + + private String mode; private Dokumaran dokumaran; @@ -65,9 +67,8 @@ } } - @Override - public void reset(ActionMapping mapping, HttpServletRequest request) { - String param = mapping.getParameter(); + + public void reset(HttpServletRequest request, String param) { // 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")) { @@ -126,4 +127,12 @@ this.contentFolderID = contentFolderID; } + public String getMode() { + return mode; + } + + public void setMode(String mode) { + this.mode = mode; + } + } Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/form/ReflectionForm.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/form/ReflectionForm.java (.../ReflectionForm.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/form/ReflectionForm.java (.../ReflectionForm.java) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -33,7 +33,7 @@ * * */ -public class ReflectionForm extends ValidatorForm { +public class ReflectionForm{ private static final long serialVersionUID = -9054365604649146735L; private static Logger logger = Logger.getLogger(ReflectionForm.class.getName()); Index: lams_tool_doku/web/WEB-INF/spring-servlet.xml =================================================================== diff -u --- lams_tool_doku/web/WEB-INF/spring-servlet.xml (revision 0) +++ lams_tool_doku/web/WEB-INF/spring-servlet.xml (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -0,0 +1,17 @@ + + + + + + + + + + + \ No newline at end of file Index: lams_tool_doku/web/WEB-INF/tags/AuthoringButton.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/WEB-INF/tags/AuthoringButton.tag (.../AuthoringButton.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/WEB-INF/tags/AuthoringButton.tag (.../AuthoringButton.tag) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -32,7 +32,6 @@ <%@ tag body-content="scriptless" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> -<%@ taglib uri="tags-html" prefix="html" %> <%@ taglib uri="tags-lams" prefix="lams"%> <%@ attribute name="formID" required="true" rtexprvalue="true" %> @@ -123,11 +122,11 @@ } \ No newline at end of file Index: lams_tool_doku/web/WEB-INF/tags/AuthoringRatingAllStyleCriteria.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/WEB-INF/tags/AuthoringRatingAllStyleCriteria.tag (.../AuthoringRatingAllStyleCriteria.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/WEB-INF/tags/AuthoringRatingAllStyleCriteria.tag (.../AuthoringRatingAllStyleCriteria.tag) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -8,7 +8,6 @@ <%@ tag body-content="scriptless" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> -<%@ taglib uri="tags-html" prefix="html" %> <%@ taglib uri="tags-lams" prefix="lams"%> <%@ taglib uri="tags-function" prefix="fn" %> Index: lams_tool_doku/web/WEB-INF/tags/AuthoringRatingCriteria.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/WEB-INF/tags/AuthoringRatingCriteria.tag (.../AuthoringRatingCriteria.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/WEB-INF/tags/AuthoringRatingCriteria.tag (.../AuthoringRatingCriteria.tag) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -8,7 +8,6 @@ <%@ tag body-content="scriptless" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> -<%@ taglib uri="tags-html" prefix="html" %> <%@ taglib uri="tags-lams" prefix="lams"%> <%@ taglib uri="tags-function" prefix="fn" %> @@ -284,42 +283,42 @@ - - + + - - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + - - + + - - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + Index: lams_tool_doku/web/WEB-INF/tags/CommentsAuthor.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/WEB-INF/tags/CommentsAuthor.tag (.../CommentsAuthor.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/WEB-INF/tags/CommentsAuthor.tag (.../CommentsAuthor.tag) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -1,5 +1,4 @@ <%@ taglib uri="tags-core" prefix="c"%> -<%@ taglib uri="tags-html" prefix="html"%> <%@ taglib uri="tags-fmt" prefix="fmt"%> <%@ taglib uri="tags-lams" prefix="lams"%> @@ -42,23 +41,23 @@
-     -   +     +  
Index: lams_tool_doku/web/WEB-INF/tags/Page.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/WEB-INF/tags/Page.tag (.../Page.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/WEB-INF/tags/Page.tag (.../Page.tag) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -4,6 +4,7 @@ <%@ taglib uri="tags-lams" prefix="lams"%> <%@ attribute name="type" required="true" rtexprvalue="true"%> +<%@ attribute name="formID" required="false" rtexprvalue="true"%> <%@ attribute name="style" required="false" rtexprvalue="true"%> <%@ attribute name="title" required="false" rtexprvalue="true"%> <%@ attribute name="titleHelpURL" required="false" rtexprvalue="true"%> @@ -88,8 +89,8 @@ - - + + ${toolForm.toolSessionID} Index: lams_tool_doku/web/WEB-INF/tags/Rating.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/WEB-INF/tags/Rating.tag (.../Rating.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/WEB-INF/tags/Rating.tag (.../Rating.tag) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -8,7 +8,6 @@ <%@ tag body-content="scriptless" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> -<%@ taglib uri="tags-html" prefix="html" %> <%@ taglib uri="tags-lams" prefix="lams"%> <%@ taglib uri="tags-function" prefix="fn" %> Index: lams_tool_doku/web/WEB-INF/tags/StyledRating.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/WEB-INF/tags/StyledRating.tag (.../StyledRating.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/WEB-INF/tags/StyledRating.tag (.../StyledRating.tag) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -8,7 +8,6 @@ <%@ tag body-content="scriptless" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> -<%@ taglib uri="tags-html" prefix="html" %> <%@ taglib uri="tags-lams" prefix="lams"%> <%@ taglib uri="tags-function" prefix="fn" %> Index: lams_tool_doku/web/WEB-INF/tags/TabBody.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/WEB-INF/tags/TabBody.tag (.../TabBody.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/WEB-INF/tags/TabBody.tag (.../TabBody.tag) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -34,7 +34,6 @@ <%@ attribute name="titleKey" required="false" rtexprvalue="true"%> <%@ attribute name="page" required="false" rtexprvalue="true"%> <%@ taglib uri="tags-core" prefix="c"%> -<%@ taglib uri="tags-bean" prefix="bean"%> Index: lams_tool_doku/web/WEB-INF/tags/TabBodyArea.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/WEB-INF/tags/TabBodyArea.tag (.../TabBodyArea.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/WEB-INF/tags/TabBodyArea.tag (.../TabBodyArea.tag) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -30,7 +30,6 @@ %> <%@ taglib uri="tags-core" prefix="c"%> -<%@ taglib uri="tags-bean" prefix="bean"%>
Index: lams_tool_doku/web/WEB-INF/tags/TextSearch.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/WEB-INF/tags/TextSearch.tag (.../TextSearch.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/WEB-INF/tags/TextSearch.tag (.../TextSearch.tag) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -32,12 +32,11 @@ <%@ tag body-content="scriptless" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> -<%@ taglib uri="tags-html" prefix="html" %> +<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <%@ taglib uri="tags-lams" prefix="lams" %> <%-- Required attributes --%> <%@ attribute name="sessionMapID" required="true" rtexprvalue="true" %> -<%@ attribute name="wrapInFormTag" required="true" rtexprvalue="true" %> <%-- Optional attributes --%> <%@ attribute name="action" required="false" rtexprvalue="true" %> @@ -53,10 +52,10 @@ <%-- Default value for message key --%> - + - + @@ -85,52 +84,40 @@ - -
- - -

- - - - - - - - - - - - - - - - - -
- - - -
- - - -
- - - -
- - - -
- - - - - - - - - + +

+ + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
\ No newline at end of file Index: lams_tool_doku/web/WEB-INF/tlds/lams/lams.tld =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/WEB-INF/tlds/lams/lams.tld (.../lams.tld) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/WEB-INF/tlds/lams/lams.tld (.../lams.tld) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -212,192 +212,6 @@ - - STRUTS-textarea - org.lamsfoundation.lams.web.tag.MultiLinesTextareaTag - empty - - accesskey - false - true - - - alt - false - true - - - altKey - false - true - - - bundle - false - true - - - cols - false - true - - - disabled - false - true - - - errorKey - false - true - - - errorStyle - false - true - - - errorStyleClass - false - true - - - errorStyleId - false - true - - - index - false - true - - - indexed - false - true - - - name - false - true - - - onblur - false - true - - - onchange - false - true - - - onclick - false - true - - - ondblclick - false - true - - - onfocus - false - true - - - onkeydown - false - true - - - onkeypress - false - true - - - onkeyup - false - true - - - onmousedown - false - true - - - onmousemove - false - true - - - onmouseout - false - true - - - onmouseover - false - true - - - onmouseup - false - true - - - property - true - true - - - readonly - false - true - - - rows - false - true - - - style - false - true - - - styleClass - false - true - - - styleId - false - true - - - tabindex - false - true - - - title - false - true - - - titleKey - false - true - - - value - false - true - - - Small portrait of a user User Portrait Index: lams_tool_doku/web/WEB-INF/web.xml =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/WEB-INF/web.xml (.../web.xml) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/WEB-INF/web.xml (.../web.xml) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -73,25 +73,11 @@ - action - org.apache.struts.action.ActionServlet - - config - /WEB-INF/struts-config.xml - - - debug - 999 - - - detail - 1 - - - validate - true - - 2 + spring + + org.springframework.web.servlet.DispatcherServlet + + 1 @@ -122,7 +108,7 @@ - action + spring *.do Index: lams_tool_doku/web/common/messages.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/common/messages.jsp (.../messages.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/common/messages.jsp (.../messages.jsp) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -1,8 +1,9 @@ <%-- Error Messages --%> - - - -
-
-
-
+ + + + +
+
+
+
\ No newline at end of file Index: lams_tool_doku/web/common/taglibs.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/common/taglibs.jsp (.../taglibs.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/common/taglibs.jsp (.../taglibs.jsp) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -1,11 +1,7 @@ <%@ page language="java" errorPage="/error.jsp" pageEncoding="UTF-8" contentType="text/html;charset=utf-8" %> -<%@ taglib uri="tags-bean" prefix="bean" %> -<%@ taglib uri="tags-html" prefix="html" %> -<%@ taglib uri="tags-logic" prefix="logic" %> <%@ taglib uri="tags-function" prefix="fn" %> <%@ taglib uri="tags-core" prefix="c" %> <%@ taglib uri="tags-fmt" prefix="fmt" %> <%@ taglib uri="tags-xml" prefix="x" %> <%@ taglib uri="tags-lams" prefix="lams" %> - - +<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> \ No newline at end of file Index: lams_tool_doku/web/pages/admin/config.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/pages/admin/config.jsp (.../config.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/pages/admin/config.jsp (.../config.jsp) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -27,29 +27,27 @@
- + - -
- +
- +
- + -
+ Index: lams_tool_doku/web/pages/authoring/advance.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/pages/authoring/advance.jsp (.../advance.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/pages/authoring/advance.jsp (.../advance.jsp) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -1,20 +1,19 @@ <%@ include file="/common/taglibs.jsp"%> -
@@ -25,34 +24,34 @@
- +
@@ -61,20 +60,20 @@
- +
Index: lams_tool_doku/web/pages/authoring/authoring.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/pages/authoring/authoring.jsp (.../authoring.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/pages/authoring/authoring.jsp (.../authoring.jsp) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -28,13 +28,12 @@ - - - - - - - + + + + + + @@ -66,14 +65,14 @@ accessMode="author" --%> + toolSignature="<%=DokumaranConstants.TOOL_SIGNATURE%>" toolContentID="${authoringForm.dokumaran.contentId}" + customiseSessionID="${authoringForm.sessionMapID}" accessMode="${authoringForm.mode}" defineLater="${mode=='teacher'}" + contentFolderID="${authoringForm.contentFolderID}" /> - + Index: lams_tool_doku/web/pages/authoring/basic.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/pages/authoring/basic.jsp (.../basic.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/pages/authoring/basic.jsp (.../basic.jsp) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -1,17 +1,16 @@ <%@ include file="/common/taglibs.jsp"%> -
- +
- +
Index: lams_tool_doku/web/pages/authoring/start.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r1cef918442124e8d987a285095a7504e3bc00461 --- lams_tool_doku/web/pages/authoring/start.jsp (.../start.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/pages/authoring/start.jsp (.../start.jsp) (revision 1cef918442124e8d987a285095a7504e3bc00461) @@ -3,10 +3,10 @@ - - - - + + + + - + - +