Index: lams_tool_doku/conf/etherpad-lite/src/static/js/pad.js =================================================================== diff -u --- lams_tool_doku/conf/etherpad-lite/src/static/js/pad.js (revision 0) +++ lams_tool_doku/conf/etherpad-lite/src/static/js/pad.js (revision 10a1136c72ffe94801498ff7fb718dc9b582c521) @@ -0,0 +1,947 @@ +/** + * This code is mostly from the old Etherpad. Please help us to comment this code. + * This helps other people to understand this code better and helps them to improve it. + * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED + */ + +/** + * Copyright 2009 Google Inc., 2011 Peter 'Pita' Martischka (Primary Technology Ltd) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS-IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* global $, window */ + +var socket; + +// These jQuery things should create local references, but for now `require()` +// assigns to the global `$` and augments it with plugins. +require('./jquery'); +require('./farbtastic'); +require('./excanvas'); +JSON = require('./json2'); + +var chat = require('./chat').chat; +var getCollabClient = require('./collab_client').getCollabClient; +var padconnectionstatus = require('./pad_connectionstatus').padconnectionstatus; +var padcookie = require('./pad_cookie').padcookie; +var padeditbar = require('./pad_editbar').padeditbar; +var padeditor = require('./pad_editor').padeditor; +var padimpexp = require('./pad_impexp').padimpexp; +var padmodals = require('./pad_modals').padmodals; +var padsavedrevs = require('./pad_savedrevs'); +var paduserlist = require('./pad_userlist').paduserlist; +var padutils = require('./pad_utils').padutils; +var colorutils = require('./colorutils').colorutils; +var createCookie = require('./pad_utils').createCookie; +var readCookie = require('./pad_utils').readCookie; +var randomString = require('./pad_utils').randomString; +var gritter = require('./gritter').gritter; + +var hooks = require('./pluginfw/hooks'); + +var receivedClientVars = false; + +function randomString() +{ + var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + var string_length = 20; + var randomstring = ''; + for (var i = 0; i < string_length; i++) + { + var rnum = Math.floor(Math.random() * chars.length); + randomstring += chars.substring(rnum, rnum + 1); + } + return "t." + randomstring; +} + +// This array represents all GET-parameters which can be used to change a setting. +// name: the parameter-name, eg `?noColors=true` => `noColors` +// checkVal: the callback is only executed when +// * the parameter was supplied and matches checkVal +// * the parameter was supplied and checkVal is null +// callback: the function to call when all above succeeds, `val` is the value supplied by the user +var getParameters = [ + { name: "noColors", checkVal: "true", callback: function(val) { settings.noColors = true; $('#clearAuthorship').hide(); } }, + { name: "showControls", checkVal: "false", callback: function(val) { $('#editbar').addClass('hideControlsEditbar'); $('#editorcontainer').addClass('hideControlsEditor'); } }, + { name: "showChat", checkVal: "false", callback: function(val) { $('#chaticon').hide(); } }, + { name: "showLineNumbers", checkVal: "false", callback: function(val) { settings.LineNumbersDisabled = true; } }, + { name: "useMonospaceFont", checkVal: "true", callback: function(val) { settings.useMonospaceFontGlobal = true; } }, + // If the username is set as a parameter we should set a global value that we can call once we have initiated the pad. + { name: "userName", checkVal: null, callback: function(val) { settings.globalUserName = decodeURIComponent(val); clientVars.userName = decodeURIComponent(val); } }, + // If the userColor is set as a parameter, set a global value to use once we have initiated the pad. + { name: "userColor", checkVal: null, callback: function(val) { settings.globalUserColor = decodeURIComponent(val); clientVars.userColor = decodeURIComponent(val); } }, + { name: "rtl", checkVal: "true", callback: function(val) { settings.rtlIsTrue = true } }, + { name: "alwaysShowChat", checkVal: "true", callback: function(val) { chat.stickToScreen(); } }, + { name: "chatAndUsers", checkVal: "true", callback: function(val) { chat.chatAndUsers(); } }, + { name: "lang", checkVal: null, callback: function(val) { window.html10n.localize([val, 'en']); createCookie('language', val); } } +]; + +function getParams() +{ + // Tries server enforced options first.. + for(var i = 0; i < getParameters.length; i++) + { + var setting = getParameters[i]; + var value = clientVars.padOptions[setting.name]; + if(value.toString() === setting.checkVal) + { + setting.callback(value); + } + } + + // Then URL applied stuff + var params = getUrlVars() + + for(var i = 0; i < getParameters.length; i++) + { + var setting = getParameters[i]; + var value = params[setting.name]; + + if(value && (value == setting.checkVal || setting.checkVal == null)) + { + setting.callback(value); + } + } +} + +function getUrlVars() +{ + var vars = [], hash; + var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); + for(var i = 0; i < hashes.length; i++) + { + hash = hashes[i].split('='); + vars.push(hash[0]); + vars[hash[0]] = hash[1]; + } + return vars; +} + +function savePassword() +{ + //set the password cookie + createCookie("password",$("#passwordinput").val(),null,document.location.pathname); + //reload + document.location=document.location; + return false; +} + +function sendClientReady(isReconnect, messageType) +{ + messageType = typeof messageType !== 'undefined' ? messageType : 'CLIENT_READY'; + var padId = document.location.pathname.substring(document.location.pathname.lastIndexOf("/") + 1); + padId = decodeURIComponent(padId); // unescape neccesary due to Safari and Opera interpretation of spaces + + if(!isReconnect) + { + var titleArray = document.title.split('|'); + var title = titleArray[titleArray.length - 1]; + document.title = padId.replace(/_+/g, ' ') + " | " + title; + } + + var token = readCookie("token"); + if (token == null) + { + token = "t." + randomString(); + createCookie("token", token, 60); + } + + var sessionID = decodeURIComponent(readCookie("sessionID")); + var password = readCookie("password"); + + var msg = { + "component": "pad", + "type": messageType, + "padId": padId, + "sessionID": sessionID, + "password": password, + "token": token, + "protocolVersion": 2 + }; + + //this is a reconnect, lets tell the server our revisionnumber + if(isReconnect == true) + { + msg.client_rev=pad.collabClient.getCurrentRevisionNumber(); + msg.reconnect=true; + } + + socket.json.send(msg); +} + +function handshake() +{ + var loc = document.location; + //get the correct port + var port = loc.port == "" ? (loc.protocol == "https:" ? 443 : 80) : loc.port; + //create the url + var url = loc.protocol + "//" + loc.hostname + ":" + port + "/"; + //find out in which subfolder we are + var resource = exports.baseURL.substring(1) + "socket.io"; + //connect + socket = pad.socket = io.connect(url, { + // Allow deployers to host Etherpad on a non-root path + 'path': exports.baseURL + "socket.io", + 'resource': resource, + 'reconnectionAttempts': 5, + 'reconnection' : true, + 'reconnectionDelay' : 1000, + 'reconnectionDelayMax' : 5000 + }); + + socket.once('connect', function () { + sendClientReady(false); + }); + + socket.on('reconnect', function () { + pad.collabClient.setChannelState("CONNECTED"); + pad.sendClientReady(true); + }); + + socket.on('reconnecting', function() { + pad.collabClient.setChannelState("RECONNECTING"); + }); + + socket.on('reconnect_failed', function(error) { + pad.collabClient.setChannelState("DISCONNECTED", "reconnect_timeout"); + }); + + var initalized = false; + + socket.on('message', function(obj) + { + //the access was not granted, give the user a message + if(obj.accessStatus) + { + if(!receivedClientVars){ + $('.passForm').submit(require(module.id).savePassword); + } + + if(obj.accessStatus == "deny") + { + $('#loading').hide(); + $("#permissionDenied").show(); + + if(receivedClientVars) + { + // got kicked + $("#editorcontainer").hide(); + $("#editorloadingbox").show(); + } + } + else if(obj.accessStatus == "needPassword") + { + $('#loading').hide(); + $('#passwordRequired').show(); + $("#passwordinput").focus(); + } + else if(obj.accessStatus == "wrongPassword") + { + $('#loading').hide(); + $('#wrongPassword').show(); + $('#passwordRequired').show(); + $("#passwordinput").focus(); + } + } + + //if we haven't recieved the clientVars yet, then this message should it be + else if (!receivedClientVars && obj.type == "CLIENT_VARS") + { + //log the message + if (window.console) console.log(obj); + + receivedClientVars = true; + + //set some client vars + clientVars = obj.data; + clientVars.userAgent = "Anonymous"; + clientVars.collab_client_vars.clientAgent = "Anonymous"; + + //initalize the pad + pad._afterHandshake(); + initalized = true; + + if(clientVars.readonly){ + chat.hide(); + $('#myusernameedit').attr("disabled", true); + $('#chatinput').attr("disabled", true); + $('#chaticon').hide(); + $('#options-chatandusers').parent().hide(); + $('#options-stickychat').parent().hide(); + } + + $("body").addClass(clientVars.readonly ? "readonly" : "readwrite") + + padeditor.ace.callWithAce(function (ace) { + ace.ace_setEditable(!clientVars.readonly); + }); + + // If the LineNumbersDisabled value is set to true then we need to hide the Line Numbers + if (settings.LineNumbersDisabled == true) + { + pad.changeViewOption('showLineNumbers', false); + } + + // If the noColors value is set to true then we need to hide the background colors on the ace spans + if (settings.noColors == true) + { + pad.changeViewOption('noColors', true); + } + + if (settings.rtlIsTrue == true) + { + pad.changeViewOption('rtlIsTrue', true); + } + + // If the Monospacefont value is set to true then change it to monospace. + if (settings.useMonospaceFontGlobal == true) + { + pad.changeViewOption('useMonospaceFont', true); + } + // if the globalUserName value is set we need to tell the server and the client about the new authorname + if (settings.globalUserName !== false) + { + pad.notifyChangeName(settings.globalUserName); // Notifies the server + pad.myUserInfo.name = settings.globalUserName; + $('#myusernameedit').val(settings.globalUserName); // Updates the current users UI + } + if (settings.globalUserColor !== false && colorutils.isCssHex(settings.globalUserColor)) + { + + // Add a 'globalUserColor' property to myUserInfo, so collabClient knows we have a query parameter. + pad.myUserInfo.globalUserColor = settings.globalUserColor; + pad.notifyChangeColor(settings.globalUserColor); // Updates pad.myUserInfo.colorId + paduserlist.setMyUserInfo(pad.myUserInfo); + } + } + //This handles every Message after the clientVars + else + { + //this message advices the client to disconnect + if (obj.disconnect) + { + console.warn("FORCED TO DISCONNECT"); + console.warn(obj); + padconnectionstatus.disconnected(obj.disconnect); + socket.disconnect(); + return; + } + else + { + pad.collabClient.handleMessageFromServer(obj); + } + } + }); + // Bind the colorpicker + var fb = $('#colorpicker').farbtastic({ callback: '#mycolorpickerpreview', width: 220}); + // Bind the read only button + $('#readonlyinput').on('click',function(){ + padeditbar.setEmbedLinks(); + }); +} + +$.extend($.gritter.options, { + position: 'bottom-right', // defaults to 'top-right' but can be 'bottom-left', 'bottom-right', 'top-left', 'top-right' (added in 1.7.1) + fade: false, // dont fade, too jerky on mobile + time: 6000 // hang on the screen for... +}); + +var pad = { + // don't access these directly from outside this file, except + // for debugging + collabClient: null, + myUserInfo: null, + diagnosticInfo: {}, + initTime: 0, + clientTimeOffset: null, + padOptions: {}, + + // these don't require init; clientVars should all go through here + getPadId: function() + { + return clientVars.padId; + }, + getClientIp: function() + { + return clientVars.clientIp; + }, + getColorPalette: function() + { + return clientVars.colorPalette; + }, + getDisplayUserAgent: function() + { + return padutils.uaDisplay(clientVars.userAgent); + }, + getIsDebugEnabled: function() + { + return clientVars.debugEnabled; + }, + getPrivilege: function(name) + { + return clientVars.accountPrivs[name]; + }, + getUserIsGuest: function() + { + return clientVars.userIsGuest; + }, + getUserId: function() + { + return pad.myUserInfo.userId; + }, + getUserName: function() + { + return pad.myUserInfo.name; + }, + userList: function() + { + return paduserlist.users(); + }, + sendClientReady: function(isReconnect, messageType) + { + messageType = typeof messageType !== 'undefined' ? messageType : 'CLIENT_READY'; + sendClientReady(isReconnect, messageType); + }, + switchToPad: function(padId) + { + var options = document.location.href.split('?')[1]; + var newHref = padId; + if (typeof options != "undefined" && options != null){ + newHref = newHref + '?' + options; + } + + if(window.history && window.history.pushState) + { + $('#chattext p').remove(); //clear the chat messages + window.history.pushState("", "", newHref); + receivedClientVars = false; + sendClientReady(false, 'SWITCH_TO_PAD'); + } + else // fallback + { + window.location.href = newHref; + } + }, + sendClientMessage: function(msg) + { + pad.collabClient.sendClientMessage(msg); + }, + createCookie: createCookie, + + init: function() + { + padutils.setupGlobalExceptionHandler(); + + $(document).ready(function() + { + // start the custom js + if (typeof customStart == "function") customStart(); + handshake(); + + // To use etherpad you have to allow cookies. + // This will check if the prefs-cookie is set. + // Otherwise it shows up a message to the user. + padcookie.init(); + if (!readCookie("prefs")) + { + $('#loading').hide(); + $('#noCookie').show(); + } + }); + }, + _afterHandshake: function() + { + pad.clientTimeOffset = new Date().getTime() - clientVars.serverTimestamp; + //initialize the chat + chat.init(this); + getParams(); + + padcookie.init(); // initialize the cookies + pad.initTime = +(new Date()); + pad.padOptions = clientVars.initialOptions; + + // for IE + if (browser.msie) + { + try + { + document.execCommand("BackgroundImageCache", false, true); + } + catch (e) + {} + } + + // order of inits is important here: + pad.myUserInfo = { + userId: clientVars.userId, + name: clientVars.userName, + ip: pad.getClientIp(), + colorId: clientVars.userColor, + userAgent: pad.getDisplayUserAgent() + }; + + padimpexp.init(this); + padsavedrevs.init(this); + + padeditor.init(postAceInit, pad.padOptions.view || {}, this); + + paduserlist.init(pad.myUserInfo, this); + padconnectionstatus.init(); + padmodals.init(this); + + pad.collabClient = getCollabClient(padeditor.ace, clientVars.collab_client_vars, pad.myUserInfo, { + colorPalette: pad.getColorPalette() + }, pad); + pad.collabClient.setOnUserJoin(pad.handleUserJoin); + pad.collabClient.setOnUpdateUserInfo(pad.handleUserUpdate); + pad.collabClient.setOnUserLeave(pad.handleUserLeave); + pad.collabClient.setOnClientMessage(pad.handleClientMessage); + pad.collabClient.setOnServerMessage(pad.handleServerMessage); + pad.collabClient.setOnChannelStateChange(pad.handleChannelStateChange); + pad.collabClient.setOnInternalAction(pad.handleCollabAction); + + // load initial chat-messages + if(clientVars.chatHead != -1) + { + var chatHead = clientVars.chatHead; + var start = Math.max(chatHead - 100, 0); + pad.collabClient.sendMessage({"type": "GET_CHAT_MESSAGES", "start": start, "end": chatHead}); + } + else // there are no messages + { + $("#chatloadmessagesbutton").css("display", "none"); + } + + function postAceInit() + { + padeditbar.init(); + setTimeout(function() + { + padeditor.ace.focus(); + }, 0); + if(padcookie.getPref("chatAlwaysVisible")){ // if we have a cookie for always showing chat then show it + chat.stickToScreen(true); // stick it to the screen + $('#options-stickychat').prop("checked", true); // set the checkbox to on + } + if(padcookie.getPref("chatAndUsers")){ // if we have a cookie for always showing chat then show it + chat.chatAndUsers(true); // stick it to the screen + $('#options-chatandusers').prop("checked", true); // set the checkbox to on + } + if(padcookie.getPref("showAuthorshipColors") == false){ + pad.changeViewOption('showAuthorColors', false); + } + if(padcookie.getPref("showLineNumbers") == false){ + //*LAMS* commented out the following line. As otherwise once stored cookie will affect all other pads ignoring showLineNumbers URL parameter + //pad.changeViewOption('showLineNumbers', false); + } + if(padcookie.getPref("rtlIsTrue") == true){ + pad.changeViewOption('rtlIsTrue', true); + } + + var fonts = ['useMonospaceFont', 'useOpenDyslexicFont', 'useComicSansFont', 'useCourierNewFont', 'useGeorgiaFont', 'useImpactFont', + 'useLucidaFont', 'useLucidaSansFont', 'usePalatinoFont', 'useTahomaFont', 'useTimesNewRomanFont', + 'useTrebuchetFont', 'useVerdanaFont', 'useSymbolFont', 'useWebdingsFont', 'useWingDingsFont', 'useSansSerifFont', + 'useSerifFont']; + + $.each(fonts, function(i, font){ + if(padcookie.getPref(font) == true){ + pad.changeViewOption(font, true); + } + }) + + hooks.aCallAll("postAceInit", {ace: padeditor.ace, pad: pad}); + } + }, + dispose: function() + { + padeditor.dispose(); + }, + notifyChangeName: function(newName) + { + pad.myUserInfo.name = newName; + pad.collabClient.updateUserInfo(pad.myUserInfo); + }, + notifyChangeColor: function(newColorId) + { + pad.myUserInfo.colorId = newColorId; + pad.collabClient.updateUserInfo(pad.myUserInfo); + }, + changePadOption: function(key, value) + { + var options = {}; + options[key] = value; + pad.handleOptionsChange(options); + pad.collabClient.sendClientMessage( + { + type: 'padoptions', + options: options, + changedBy: pad.myUserInfo.name || "unnamed" + }); + }, + changeViewOption: function(key, value) + { + var options = { + view: {} + }; + options.view[key] = value; + pad.handleOptionsChange(options); + }, + handleOptionsChange: function(opts) + { + // opts object is a full set of options or just + // some options to change + if (opts.view) + { + if (!pad.padOptions.view) + { + pad.padOptions.view = {}; + } + for (var k in opts.view) + { + pad.padOptions.view[k] = opts.view[k]; + padcookie.setPref(k, opts.view[k]); + } + padeditor.setViewOptions(pad.padOptions.view); + } + if (opts.guestPolicy) + { + // order important here + pad.padOptions.guestPolicy = opts.guestPolicy; + } + }, + getPadOptions: function() + { + // caller shouldn't mutate the object + return pad.padOptions; + }, + isPadPublic: function() + { + return pad.getPadOptions().guestPolicy == 'allow'; + }, + suggestUserName: function(userId, name) + { + pad.collabClient.sendClientMessage( + { + type: 'suggestUserName', + unnamedId: userId, + newName: name + }); + }, + handleUserJoin: function(userInfo) + { + paduserlist.userJoinOrUpdate(userInfo); + }, + handleUserUpdate: function(userInfo) + { + paduserlist.userJoinOrUpdate(userInfo); + }, + handleUserLeave: function(userInfo) + { + paduserlist.userLeave(userInfo); + }, + handleClientMessage: function(msg) + { + if (msg.type == 'suggestUserName') + { + if (msg.unnamedId == pad.myUserInfo.userId && msg.newName && !pad.myUserInfo.name) + { + pad.notifyChangeName(msg.newName); + paduserlist.setMyUserInfo(pad.myUserInfo); + } + } + else if (msg.type == 'newRevisionList') + { + padsavedrevs.newRevisionList(msg.revisionList); + } + else if (msg.type == 'revisionLabel') + { + padsavedrevs.newRevisionList(msg.revisionList); + } + else if (msg.type == 'padoptions') + { + var opts = msg.options; + pad.handleOptionsChange(opts); + } + else if (msg.type == 'guestanswer') + { + // someone answered a prompt, remove it + paduserlist.removeGuestPrompt(msg.guestId); + } + }, + dmesg: function(m) + { + if (pad.getIsDebugEnabled()) + { + var djs = $('#djs').get(0); + var wasAtBottom = (djs.scrollTop - (djs.scrollHeight - $(djs).height()) >= -20); + $('#djs').append('

' + m + '

'); + if (wasAtBottom) + { + djs.scrollTop = djs.scrollHeight; + } + } + }, + handleServerMessage: function(m) + { + if (m.type == 'NOTICE') + { + if (m.text) + { + alertBar.displayMessage(function(abar) + { + abar.find("#servermsgdate").text(" (" + padutils.simpleDateTime(new Date) + ")"); + abar.find("#servermsgtext").text(m.text); + }); + } + if (m.js) + { + window['ev' + 'al'](m.js); + } + } + else if (m.type == 'GUEST_PROMPT') + { + paduserlist.showGuestPrompt(m.userId, m.displayName); + } + }, + handleChannelStateChange: function(newState, message) + { + var oldFullyConnected = !! padconnectionstatus.isFullyConnected(); + var wasConnecting = (padconnectionstatus.getStatus().what == 'connecting'); + if (newState == "CONNECTED") + { + padeditor.enable(); + padconnectionstatus.connected(); + } + else if (newState == "RECONNECTING") + { + padconnectionstatus.reconnecting(); + } + else if (newState == "DISCONNECTED") + { + pad.diagnosticInfo.disconnectedMessage = message; + pad.diagnosticInfo.padId = pad.getPadId(); + pad.diagnosticInfo.socket = {}; + + //we filter non objects from the socket object and put them in the diagnosticInfo + //this ensures we have no cyclic data - this allows us to stringify the data + for(var i in socket.socket) + { + var value = socket.socket[i]; + var type = typeof value; + + if(type == "string" || type == "number") + { + pad.diagnosticInfo.socket[i] = value; + } + } + + pad.asyncSendDiagnosticInfo(); + if (typeof window.ajlog == "string") + { + window.ajlog += ("Disconnected: " + message + '\n'); + } + padeditor.disable(); + padeditbar.disable(); + padimpexp.disable(); + + padconnectionstatus.disconnected(message); + } + var newFullyConnected = !! padconnectionstatus.isFullyConnected(); + if (newFullyConnected != oldFullyConnected) + { + pad.handleIsFullyConnected(newFullyConnected, wasConnecting); + } + }, + handleIsFullyConnected: function(isConnected, isInitialConnect) + { + pad.determineChatVisibility(isConnected && !isInitialConnect); + pad.determineChatAndUsersVisibility(isConnected && !isInitialConnect); + pad.determineAuthorshipColorsVisibility(); + setTimeout(function(){ + padeditbar.toggleDropDown("none"); + }, 1000); + }, + determineChatVisibility: function(asNowConnectedFeedback){ + var chatVisCookie = padcookie.getPref('chatAlwaysVisible'); + if(chatVisCookie){ // if the cookie is set for chat always visible + chat.stickToScreen(true); // stick it to the screen + $('#options-stickychat').prop("checked", true); // set the checkbox to on + } + else{ + $('#options-stickychat').prop("checked", false); // set the checkbox for off + } + }, + determineChatAndUsersVisibility: function(asNowConnectedFeedback){ + var chatAUVisCookie = padcookie.getPref('chatAndUsersVisible'); + if(chatAUVisCookie){ // if the cookie is set for chat always visible + chat.chatAndUsers(true); // stick it to the screen + $('#options-chatandusers').prop("checked", true); // set the checkbox to on + } + else{ + $('#options-chatandusers').prop("checked", false); // set the checkbox for off + } + }, + determineAuthorshipColorsVisibility: function(){ + var authColCookie = padcookie.getPref('showAuthorshipColors'); + if (authColCookie){ + pad.changeViewOption('showAuthorColors', true); + $('#options-colorscheck').prop("checked", true); + } + else { + $('#options-colorscheck').prop("checked", false); + } + }, + handleCollabAction: function(action) + { + if (action == "commitPerformed") + { + padeditbar.setSyncStatus("syncing"); + } + else if (action == "newlyIdle") + { + padeditbar.setSyncStatus("done"); + } + }, + hideServerMessage: function() + { + alertBar.hideMessage(); + }, + asyncSendDiagnosticInfo: function() + { + window.setTimeout(function() + { + $.ajax( + { + type: 'post', + url: '/ep/pad/connection-diagnostic-info', + data: { + diagnosticInfo: JSON.stringify(pad.diagnosticInfo) + }, + success: function() + {}, + error: function() + {} + }); + }, 0); + }, + forceReconnect: function() + { + $('form#reconnectform input.padId').val(pad.getPadId()); + pad.diagnosticInfo.collabDiagnosticInfo = pad.collabClient.getDiagnosticInfo(); + $('form#reconnectform input.diagnosticInfo').val(JSON.stringify(pad.diagnosticInfo)); + $('form#reconnectform input.missedChanges').val(JSON.stringify(pad.collabClient.getMissedChanges())); + $('form#reconnectform').submit(); + }, + // this is called from code put into a frame from the server: + handleImportExportFrameCall: function(callName, varargs) + { + padimpexp.handleFrameCall.call(padimpexp, callName, Array.prototype.slice.call(arguments, 1)); + }, + callWhenNotCommitting: function(f) + { + pad.collabClient.callWhenNotCommitting(f); + }, + getCollabRevisionNumber: function() + { + return pad.collabClient.getCurrentRevisionNumber(); + }, + isFullyConnected: function() + { + return padconnectionstatus.isFullyConnected(); + }, + addHistoricalAuthors: function(data) + { + if (!pad.collabClient) + { + window.setTimeout(function() + { + pad.addHistoricalAuthors(data); + }, 1000); + } + else + { + pad.collabClient.addHistoricalAuthors(data); + } + } +}; + +var alertBar = (function() +{ + + var animator = padutils.makeShowHideAnimator(arriveAtAnimationState, false, 25, 400); + + function arriveAtAnimationState(state) + { + if (state == -1) + { + $("#alertbar").css('opacity', 0).css('display', 'block'); + } + else if (state == 0) + { + $("#alertbar").css('opacity', 1); + } + else if (state == 1) + { + $("#alertbar").css('opacity', 0).css('display', 'none'); + } + else if (state < 0) + { + $("#alertbar").css('opacity', state + 1); + } + else if (state > 0) + { + $("#alertbar").css('opacity', 1 - state); + } + } + + var self = { + displayMessage: function(setupFunc) + { + animator.show(); + setupFunc($("#alertbar")); + }, + hideMessage: function() + { + animator.hide(); + } + }; + return self; +}()); + +function init() { + return pad.init(); +} + +var settings = { + LineNumbersDisabled: false +, noColors: false +, useMonospaceFontGlobal: false +, globalUserName: false +, globalUserColor: false +, rtlIsTrue: false +}; + +pad.settings = settings; +exports.baseURL = ''; +exports.settings = settings; +exports.createCookie = createCookie; +exports.readCookie = readCookie; +exports.randomString = randomString; +exports.getParams = getParams; +exports.getUrlVars = getUrlVars; +exports.savePassword = savePassword; +exports.handshake = handshake; +exports.pad = pad; +exports.init = init; +exports.alertBar = alertBar; Index: lams_tool_doku/conf/language/lams/ApplicationResources_en_AU.properties =================================================================== diff -u -reeb7734f1d37604e1b9e14b4df3214d5cdd0338b -r10a1136c72ffe94801498ff7fb718dc9b582c521 --- lams_tool_doku/conf/language/lams/ApplicationResources_en_AU.properties (.../ApplicationResources_en_AU.properties) (revision eeb7734f1d37604e1b9e14b4df3214d5cdd0338b) +++ lams_tool_doku/conf/language/lams/ApplicationResources_en_AU.properties (.../ApplicationResources_en_AU.properties) (revision 10a1136c72ffe94801498ff7fb718dc9b582c521) @@ -74,7 +74,10 @@ label.shared.pad.id =Shared pad id that allows using the same pad between several doKumaran activities label.allow.multiple.leaders =All leaders participate together (applicable only for non-grouped doKumaran activities) label.timeslider =Timeslider -label.export.pad.html =Export current pad as HTML -label.manage.faulty.pads =Pads with issues +label.export.pad.html =Export as HTML +label.recreate.faulty.pad =Recreate pad +label.cant.display.faulty.pad =This session has had problems with initialization. You can fix this by pressing the Recreate pad button. +label.pad.started.fixing =Please wait. Pad is getting recreated now. +label.pad.fixed =Pad has been successfully created. Please refresh the page to see its content. #======= End labels: Exported 164 labels for en AU ===== Index: lams_tool_doku/readme.txt =================================================================== diff -u -reeb7734f1d37604e1b9e14b4df3214d5cdd0338b -r10a1136c72ffe94801498ff7fb718dc9b582c521 --- lams_tool_doku/readme.txt (.../readme.txt) (revision eeb7734f1d37604e1b9e14b4df3214d5cdd0338b) +++ lams_tool_doku/readme.txt (.../readme.txt) (revision 10a1136c72ffe94801498ff7fb718dc9b582c521) @@ -1,3 +1,3 @@ -Modifications required to be done for Etherpad server. Copy two files: -1. /lams_tool_doku/conf/etherpad-lite/src/node/utils/Settings.js to /${etherpad-lite-server-folder}/src/node/utils/Settings.js -2. /lams_tool_doku/conf/etherpad-lite/src/static/js/pad_userlist.js to /${etherpad-lite-server-folder}/src/static/js/pad_userlist.js \ No newline at end of file +Modifications required to be done for Etherpad server (version #1.6.1): +Copy the folder /lams_tool_doku/conf/etherpad-lite/src/ over to /${etherpad-lite-server-folder}/src/ +(it will copy three files /src/node/utils/Settings.js, /src/static/js/pad.js and /src/static/js/pad_userlist.js). \ No newline at end of file Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/DokumaranConstants.java =================================================================== diff -u -r3135ffa870d30b00e33204b2ab83954665ce8d61 -r10a1136c72ffe94801498ff7fb718dc9b582c521 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/DokumaranConstants.java (.../DokumaranConstants.java) (revision 3135ffa870d30b00e33204b2ab83954665ce8d61) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/DokumaranConstants.java (.../DokumaranConstants.java) (revision 10a1136c72ffe94801498ff7fb718dc9b582c521) @@ -64,6 +64,8 @@ public static final String ATTR_NEXT_ACTIVITY_URL = "nextActivityUrl"; public static final String ATTR_SUMMARY_LIST = "summaryList"; + + public static final String ATTR_HAS_FAULTY_SESSION = "hasFaultySession"; public static final String ATTR_USER_LIST = "userList"; Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/dokumaranApplicationContext.xml =================================================================== diff -u -rb15a3b889da23ac048a689fc2d661df42571b229 -r10a1136c72ffe94801498ff7fb718dc9b582c521 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/dokumaranApplicationContext.xml (.../dokumaranApplicationContext.xml) (revision b15a3b889da23ac048a689fc2d661df42571b229) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/dokumaranApplicationContext.xml (.../dokumaranApplicationContext.xml) (revision 10a1136c72ffe94801498ff7fb718dc9b582c521) @@ -59,9 +59,6 @@ - - - Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/dto/SessionDTO.java =================================================================== diff -u -rb15a3b889da23ac048a689fc2d661df42571b229 -r10a1136c72ffe94801498ff7fb718dc9b582c521 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/dto/SessionDTO.java (.../SessionDTO.java) (revision b15a3b889da23ac048a689fc2d661df42571b229) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/dto/SessionDTO.java (.../SessionDTO.java) (revision 10a1136c72ffe94801498ff7fb718dc9b582c521) @@ -28,6 +28,7 @@ private Long sessionId; private String sessionName; private String padId; + private boolean sessionFaulty; public Long getSessionId() { return sessionId; @@ -52,4 +53,12 @@ public void setPadId(String padId) { this.padId = padId; } + + public boolean isSessionFaulty() { + return sessionFaulty; + } + + public void setSessionFaulty(boolean sessionFaulty) { + this.sessionFaulty = sessionFaulty; + } } Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/DokumaranService.java =================================================================== diff -u -reeb7734f1d37604e1b9e14b4df3214d5cdd0338b -r10a1136c72ffe94801498ff7fb718dc9b582c521 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/DokumaranService.java (.../DokumaranService.java) (revision eeb7734f1d37604e1b9e14b4df3214d5cdd0338b) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/DokumaranService.java (.../DokumaranService.java) (revision 10a1136c72ffe94801498ff7fb718dc9b582c521) @@ -41,14 +41,6 @@ import org.apache.log4j.Logger; import org.apache.tomcat.util.json.JSONException; import org.apache.tomcat.util.json.JSONObject; -import org.lamsfoundation.lams.contentrepository.AccessDeniedException; -import org.lamsfoundation.lams.contentrepository.ICredentials; -import org.lamsfoundation.lams.contentrepository.ITicket; -import org.lamsfoundation.lams.contentrepository.IVersionedNode; -import org.lamsfoundation.lams.contentrepository.LoginException; -import org.lamsfoundation.lams.contentrepository.WorkspaceNotFoundException; -import org.lamsfoundation.lams.contentrepository.service.IRepositoryService; -import org.lamsfoundation.lams.contentrepository.service.SimpleCredentials; import org.lamsfoundation.lams.learning.service.ILearnerService; import org.lamsfoundation.lams.learningdesign.service.ExportToolContentException; import org.lamsfoundation.lams.learningdesign.service.IExportToolContentService; @@ -83,7 +75,6 @@ import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; -import org.lamsfoundation.lams.util.HashUtil; import org.lamsfoundation.lams.util.JsonUtil; import org.lamsfoundation.lams.util.MessageService; import org.lamsfoundation.lams.util.audit.IAuditService; @@ -111,7 +102,6 @@ private MessageService messageService; // system services - private IRepositoryService repositoryService; private ILamsToolService toolService; @@ -132,71 +122,7 @@ // ******************************************************************************* // Service method // ******************************************************************************* - /** - * Try to get the file. If forceLogin = false and an access denied exception occurs, call this method again to get a - * new ticket and retry file lookup. If forceLogin = true and it then fails then throw exception. - * - * @param uuid - * @param versionId - * @param relativePath - * @param attemptCount - * @return file node - * @throws ImscpApplicationException - */ - private IVersionedNode getFile(Long uuid, Long versionId, String relativePath) - throws DokumaranApplicationException { - ITicket tic = getRepositoryLoginTicket(); - - try { - - return repositoryService.getFileItem(tic, uuid, versionId, relativePath); - - } catch (AccessDeniedException e) { - - String error = "Unable to access repository to get file uuid " + uuid + " version id " + versionId - + " path " + relativePath + "."; - - error = error + "AccessDeniedException: " + e.getMessage() + " Unable to retry further."; - DokumaranService.log.error(error); - throw new DokumaranApplicationException(error, e); - - } catch (Exception e) { - - String error = "Unable to access repository to get file uuid " + uuid + " version id " + versionId - + " path " + relativePath + "." + " Exception: " + e.getMessage(); - DokumaranService.log.error(error); - throw new DokumaranApplicationException(error, e); - - } - } - - /** - * This method verifies the credentials of the Dokumaran Tool and gives it the Ticket to login and - * access the Content Repository. - * - * A valid ticket is needed in order to access the content from the repository. This method would be called evertime - * the tool needs to upload/download files from the content repository. - * - * @return ITicket The ticket for repostory access - * @throws DokumaranApplicationException - */ - private ITicket getRepositoryLoginTicket() throws DokumaranApplicationException { - ICredentials credentials = new SimpleCredentials(dokumaranToolContentHandler.getRepositoryUser(), - dokumaranToolContentHandler.getRepositoryId()); - try { - ITicket ticket = repositoryService.login(credentials, - dokumaranToolContentHandler.getRepositoryWorkspaceName()); - return ticket; - } catch (AccessDeniedException ae) { - throw new DokumaranApplicationException("Access Denied to repository." + ae.getMessage()); - } catch (WorkspaceNotFoundException we) { - throw new DokumaranApplicationException("Workspace not found." + we.getMessage()); - } catch (LoginException e) { - throw new DokumaranApplicationException("Login failed." + e.getMessage()); - } - } - @Override public Dokumaran getDokumaranByContentId(Long contentId) { Dokumaran rs = dokumaranDao.getByContentId(contentId); @@ -459,6 +385,11 @@ String padId = session.getPadId(); group.setPadId(padId); + + //mark all session that has had problems with pad initializations so that they could be fixed in monitoring by a teacher + if (StringUtils.isEmpty(session.getEtherpadReadOnlyId()) || StringUtils.isEmpty(session.getEtherpadGroupId())) { + group.setSessionFaulty(true); + } groupList.add(group); } @@ -754,78 +685,81 @@ session.setDokumaran(dokumaran); dokumaranSessionDao.saveObject(session); - // //create pad in a new thread so it doesn't affect session creation operation - // Thread t = new Thread( - // new CreatePadThread(this, toolSessionId, dokumaran.getInstructions())); - // t.start(); - + //create pad in a try-catch block so it doesn't affect session creation operation try { - String groupIdentifier = DokumaranConstants.PREFIX_REGULAR_GROUP + toolSessionId; + createPad(dokumaran, session); + } catch (Exception e) { + log.warn(e.getMessage(), e); + } - // in case sharedPadId is present - all sessions will share the same padId - if (dokumaran.isSharedPadEnabled()) { + } + + @Override + public void createPad(Dokumaran dokumaran, DokumaranSession session) throws DokumaranConfigurationException { + Long toolSessionId = session.getSessionId(); + Long toolContentId = dokumaran.getContentId(); + String groupIdentifier = DokumaranConstants.PREFIX_REGULAR_GROUP + toolSessionId; - // find existing pad in any of the sessions associated with this toolContentId - List sessions = dokumaranSessionDao.getByContentId(toolContentId); - DokumaranSession sessionWithAlreadyCreatedPad = null; - for (DokumaranSession sessionIter : sessions) { - if (StringUtils.isNotBlank(session.getEtherpadGroupId())) { - sessionWithAlreadyCreatedPad = sessionIter; - break; - } - } + // in case sharedPadId is present - all sessions will share the same padId + if (dokumaran.isSharedPadEnabled()) { - if (sessionWithAlreadyCreatedPad == null) { - ToolSession toolSession = toolService.getToolSession(toolSessionId); - Long lessonId = toolSession.getLesson().getLessonId(); - groupIdentifier = DokumaranConstants.PREFIX_SHARED_GROUP + dokumaran.getSharedPadId() + lessonId; - - } else { - session.setEtherpadGroupId(sessionWithAlreadyCreatedPad.getEtherpadGroupId()); - session.setEtherpadReadOnlyId(sessionWithAlreadyCreatedPad.getEtherpadReadOnlyId()); - dokumaranSessionDao.saveObject(session); - return; + // find existing pad in any of the sessions associated with this toolContentId + List sessions = dokumaranSessionDao.getByContentId(toolContentId); + DokumaranSession sessionWithAlreadyCreatedPad = null; + for (DokumaranSession sessionIter : sessions) { + if (StringUtils.isNotBlank(session.getEtherpadGroupId())) { + sessionWithAlreadyCreatedPad = sessionIter; + break; } } - EPLiteClient client = initializeEPLiteClient(); + if (sessionWithAlreadyCreatedPad == null) { + ToolSession toolSession = toolService.getToolSession(toolSessionId); + Long lessonId = toolSession.getLesson().getLessonId(); + groupIdentifier = DokumaranConstants.PREFIX_SHARED_GROUP + dokumaran.getSharedPadId() + lessonId; - // create Etherpad Group assossiated with this session - Map map = client.createGroupIfNotExistsFor(groupIdentifier); - String groupId = (String) map.get("groupID"); - session.setEtherpadGroupId(groupId); - String padId = session.getPadId(); - - boolean isPadAlreadyCreated = false; - try { - client.createGroupPad(groupId, DokumaranConstants.DEFAULT_PAD_NAME); - } catch (EPLiteException e) { - // allow recreating existing pads - if ("padName does already exist".equals(e.getMessage())) { - isPadAlreadyCreated = true; - //throw exception in all other cases - } else { - throw e; - } + } else { + session.setEtherpadGroupId(sessionWithAlreadyCreatedPad.getEtherpadGroupId()); + session.setEtherpadReadOnlyId(sessionWithAlreadyCreatedPad.getEtherpadReadOnlyId()); + dokumaranSessionDao.saveObject(session); + return; } + } - // set initial content - if (!dokumaran.isSharedPadEnabled() || !isPadAlreadyCreated) { - String etherpadHtml = "" - + dokumaran.getInstructions().replaceAll("[\n\r\f]", "").replaceAll(" ", "") - + ""; - client.setHTML(padId, etherpadHtml); - } + EPLiteClient client = initializeEPLiteClient(); - // gets read-only id - String etherpadReadOnlyId = (String) client.getReadOnlyID(padId).get("readOnlyID"); - session.setEtherpadReadOnlyId(etherpadReadOnlyId); + // create Etherpad Group assossiated with this session + Map map = client.createGroupIfNotExistsFor(groupIdentifier); + String groupId = (String) map.get("groupID"); + session.setEtherpadGroupId(groupId); + String padId = session.getPadId(); - dokumaranSessionDao.saveObject(session); - } catch (Exception e) { - log.warn(e.getMessage(), e); + boolean isPadAlreadyCreated = false; + try { + client.createGroupPad(groupId, DokumaranConstants.DEFAULT_PAD_NAME); + } catch (EPLiteException e) { + // allow recreating existing pads + if ("padName does already exist".equals(e.getMessage())) { + isPadAlreadyCreated = true; + // throw exception in all other cases + } else { + throw e; + } } + // set initial content + if (!dokumaran.isSharedPadEnabled() || !isPadAlreadyCreated) { + String etherpadHtml = "" + + dokumaran.getInstructions().replaceAll("[\n\r\f]", "").replaceAll(" ", "") + + ""; + client.setHTML(padId, etherpadHtml); + } + + // gets read-only id + String etherpadReadOnlyId = (String) client.getReadOnlyID(padId).get("readOnlyID"); + session.setEtherpadReadOnlyId(etherpadReadOnlyId); + + dokumaranSessionDao.saveObject(session); } @Override @@ -897,6 +831,11 @@ String etherpadSessionIds = ""; for (DokumaranSession session : sessionList) { String groupId = session.getEtherpadGroupId(); + + //skip sessions that has had problems with pad initializations so that they could be fixed in monitoring by a teacher + if (StringUtils.isEmpty(session.getEtherpadReadOnlyId()) || StringUtils.isEmpty(groupId)) { + continue; + } // search for already existing user's session String userSessionId = null; @@ -965,24 +904,6 @@ String etherpadServerUrl = etherpadServerUrlConfig.getConfigValue(); String etherpadApiKey = etherpadApiKeyConfig.getConfigValue(); client = new EPLiteClient(etherpadServerUrl, etherpadApiKey); - - // // get the API key from the config table and create EPLiteClient using it - // DokumaranConfigItem lamsServerUrlConfig = getConfigItem(ConfigurationKeys.SERVER_URL); - // DokumaranConfigItem etherpadApiKeyConfig = getConfigItem(DokumaranConfigItem.KEY_API_KEY); - // if (etherpadApiKeyConfig == null || etherpadApiKeyConfig.getConfigValue() == null - // || lamsServerUrlConfig == null || lamsServerUrlConfig.getConfigValue() == null) { - // throw new DokumaranConfigurationException("Dokumaran settings are not configured. apiKeyConfig=" + - // etherpadApiKeyConfig - // + " etherpadServerUrlConfig=" + lamsServerUrlConfig + " Please seek help from your administrator"); - // } - // - // // create EPLiteClient - // String lamsServerUrl = lamsServerUrlConfig.getConfigValue(); - // URI uri = new URI(url); - // String domain = uri.getHost(); - // String etherpadServerUrl = lamsServerUrlConfig.getConfigValue(); - // String etherpadApiKey = etherpadApiKeyConfig.getConfigValue(); - // client = new EPLiteClient(etherpadServerUrl, etherpadApiKey); } return client; } @@ -1068,10 +989,6 @@ this.messageService = messageService; } - public void setRepositoryService(IRepositoryService repositoryService) { - this.repositoryService = repositoryService; - } - public void setDokumaranDao(DokumaranDAO dokumaranDao) { this.dokumaranDao = dokumaranDao; } Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/IDokumaranService.java =================================================================== diff -u -r3135ffa870d30b00e33204b2ab83954665ce8d61 -r10a1136c72ffe94801498ff7fb718dc9b582c521 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/IDokumaranService.java (.../IDokumaranService.java) (revision 3135ffa870d30b00e33204b2ab83954665ce8d61) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/IDokumaranService.java (.../IDokumaranService.java) (revision 10a1136c72ffe94801498ff7fb718dc9b582c521) @@ -115,6 +115,15 @@ * @throws DokumaranConfigurationException */ EPLiteClient initializeEPLiteClient() throws DokumaranConfigurationException; + + /** + * Creates pad on Etherpad server side. + * + * @param dokumaran + * @param session + * @throws DokumaranConfigurationException + */ + void createPad(Dokumaran dokumaran, DokumaranSession session) throws DokumaranConfigurationException; // ********** for user methods ************* /** Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/util/DokumaranToolContentHandler.java =================================================================== diff -u -rb15a3b889da23ac048a689fc2d661df42571b229 -r10a1136c72ffe94801498ff7fb718dc9b582c521 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/util/DokumaranToolContentHandler.java (.../DokumaranToolContentHandler.java) (revision b15a3b889da23ac048a689fc2d661df42571b229) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/util/DokumaranToolContentHandler.java (.../DokumaranToolContentHandler.java) (revision 10a1136c72ffe94801498ff7fb718dc9b582c521) @@ -32,11 +32,9 @@ */ public class DokumaranToolContentHandler extends ToolContentHandler { - private static String repositoryWorkspaceName = "shareddokumaranworkspace"; - private static String repositoryUser = "shareddokumaran"; - //shareddokumaran - private static char[] repositoryId = { 'l', 'a', 'm', 's', '-', 's', 'h', 'a', 'r', 'e', 'd', 'r', 'e', 's', 'o', - 'u', 'r', 'c', 'e', 's' }; + private static String repositoryWorkspaceName = "dokumaranworkspace"; + private static String repositoryUser = "dokumaran"; + private static char[] repositoryId = { 'l', 'a', 'm', 's', '-', 'd', 'o', 'k', 'u', 'm', 'a', 'r', 'a', 'n' }; /** * @@ -45,31 +43,16 @@ super(); } - /* - * (non-Javadoc) - * - * @see org.lamsfoundation.lams.contentrepository.client.ToolContentHandler#getRepositoryWorkspaceName() - */ @Override public String getRepositoryWorkspaceName() { return repositoryWorkspaceName; } - /* - * (non-Javadoc) - * - * @see org.lamsfoundation.lams.contentrepository.client.ToolContentHandler#getRepositoryUser() - */ @Override public String getRepositoryUser() { return repositoryUser; } - /* - * (non-Javadoc) - * - * @see org.lamsfoundation.lams.contentrepository.client.ToolContentHandler#getRepositoryId() - */ @Override public char[] getRepositoryId() { return repositoryId; Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/MonitoringAction.java =================================================================== diff -u -r1749733feed614e1f96fe2876e3cebe2c62ecb56 -r10a1136c72ffe94801498ff7fb718dc9b582c521 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/MonitoringAction.java (.../MonitoringAction.java) (revision 1749733feed614e1f96fe2876e3cebe2c62ecb56) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/action/MonitoringAction.java (.../MonitoringAction.java) (revision 10a1136c72ffe94801498ff7fb718dc9b582c521) @@ -25,7 +25,9 @@ package org.lamsfoundation.lams.tool.dokumaran.web.action; import java.io.IOException; +import java.io.PrintWriter; import java.net.URISyntaxException; +import java.net.URLEncoder; import java.util.List; import javax.servlet.ServletException; @@ -71,6 +73,8 @@ if (param.equals("summary")) { return summary(mapping, form, request, response); + } else if (param.equals("fixFaultySession")) { + return fixFaultySession(mapping, form, request, response); } return mapping.findForward(DokumaranConstants.ERROR); @@ -89,6 +93,10 @@ Long contentId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); IDokumaranService service = getDokumaranService(); List groupList = service.getSummary(contentId); + boolean hasFaultySession = false; + for (SessionDTO group : groupList) { + hasFaultySession |= group.isSessionFaulty(); + } Dokumaran dokumaran = service.getDokumaranByContentId(contentId); @@ -100,6 +108,7 @@ // 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); @@ -126,7 +135,33 @@ return mapping.findForward(DokumaranConstants.SUCCESS); } + + private ActionForward fixFaultySession(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws DokumaranConfigurationException, ServletException, IOException { + 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 + ")."); + service.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()); + return null; + } + + return null; + } + // ************************************************************************************* // Private method // ************************************************************************************* Index: lams_tool_doku/web/WEB-INF/struts-config.xml =================================================================== diff -u -rb15a3b889da23ac048a689fc2d661df42571b229 -r10a1136c72ffe94801498ff7fb718dc9b582c521 --- lams_tool_doku/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision b15a3b889da23ac048a689fc2d661df42571b229) +++ lams_tool_doku/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision 10a1136c72ffe94801498ff7fb718dc9b582c521) @@ -131,6 +131,10 @@ + + <%@ include file="/common/tabbedheader.jsp" %> + @@ -55,33 +98,47 @@
- -
- - - "> - - - - - "> - - - -
- -
+ + + +
+ + + + + +
+ +
+ + + +
+
+
@@ -100,25 +157,3 @@ <%@ include file="advanceoptions.jsp"%> - - - - - - - - - - - - - - - -
- ${faultySession.sessionName} - - -
-
-