Index: lams_admin/web/WEB-INF/lams.tld
===================================================================
diff -u -rc5b655c3c11fa9d9b1d76e0ef602acf6363e45f9 -r9a772f5ba1954a3a719a19e7ae237b6b09dc76ef
--- lams_admin/web/WEB-INF/lams.tld (.../lams.tld) (revision c5b655c3c11fa9d9b1d76e0ef602acf6363e45f9)
+++ lams_admin/web/WEB-INF/lams.tld (.../lams.tld) (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -13,28 +13,36 @@
- Output the basic URL for the current webapp. e.g. http://server/lams/tool/nb11/
- Base URL for the current web app
+ Output the Server URL as defined in the lams.xml configuration file.
+ LAMS URL
- WebAppURL
- org.lamsfoundation.lams.web.tag.WebAppURLTag
+ LAMSURL
+ org.lamsfoundation.lams.web.tag.LAMSURLTag
empty
- Output a random number for the learner and passon flash movies to communicate directly.
- generate unique ID
+ Converts text from \n or \r\n to <BR> before rendering
+ Converts text from \n or \r\n to <BR> before rendering
- generateID
- org.lamsfoundation.lams.web.tag.GenerateIDTag
+ out
+ org.lamsfoundation.lams.web.tag.MultiLinesOutputTag
empty
- Output a random number for the learner and passon flash movies to communicate directly.
- id
+ Converts text from \n or \r\n to <BR> before rendering
+ value
+ true
+
+ true
+
+
+
+ Converts text from \n or \r\n to <BR> before rendering
+ escapeHtml
false
true
@@ -44,6 +52,26 @@
+ Render html tag with direction and language
+ Render html tag with direction and language
+
+
+ html
+ org.lamsfoundation.lams.web.tag.HtmlTag
+ JSP
+
+
+ Render html tag with direction and language
+ xhtml
+ false
+
+ true
+
+
+
+
+
+
Get the configuration value for the specified key
Configuration value
@@ -64,28 +92,17 @@
- Output the Server URL as defined in the lams.xml configuration file.
- LAMS URL
+ Output a random number for the learner and passon flash movies to communicate directly.
+ generate unique ID
- LAMSURL
- org.lamsfoundation.lams.web.tag.LAMSURLTag
+ generateID
+ org.lamsfoundation.lams.web.tag.GenerateIDTag
empty
-
-
-
- Render html tag with direction and language
- Render html tag with direction and language
-
-
- html
- org.lamsfoundation.lams.web.tag.HtmlTag
- JSP
-
- Render html tag with direction and language
- xhtml
+ Output a random number for the learner and passon flash movies to communicate directly.
+ id
false
true
@@ -95,26 +112,29 @@
- Converts text from \n or \r\n to <BR> before rendering
- Converts text from \n or \r\n to <BR> before rendering
+ Output the basic URL for the current webapp. e.g. http://server/lams/tool/nb11/
+ Base URL for the current web app
- out
- org.lamsfoundation.lams.web.tag.MultiLinesOutputTag
+ WebAppURL
+ org.lamsfoundation.lams.web.tag.WebAppURLTag
empty
-
- Converts text from \n or \r\n to <BR> before rendering
- value
- true
+
+
- true
+ Converts role name into form usable as message resources key
+ Converts role name into form usable as message resources key
+
+
+ role
+ org.lamsfoundation.lams.web.tag.RoleTag
+ empty
-
- Converts text from \n or \r\n to <BR> before rendering
- escapeHtml
- false
+ Converts role name into form usable as message resources key
+ role
+ true
true
@@ -167,17 +187,17 @@
- Converts role name into form usable as message resources key
- Converts role name into form usable as message resources key
+ Output details from the shared session UserDTO object
+ user details
- role
- org.lamsfoundation.lams.web.tag.RoleTag
+ user
+ org.lamsfoundation.lams.web.tag.UserTag
empty
- Converts role name into form usable as message resources key
- role
+ Output details from the shared session UserDTO object
+ property
true
true
@@ -213,27 +233,7 @@
-
- Output details from the shared session UserDTO object
- user details
-
-
- user
- org.lamsfoundation.lams.web.tag.UserTag
- empty
-
-
- Output details from the shared session UserDTO object
- property
- true
-
- true
-
-
-
-
-
STRUTS-textarea
org.lamsfoundation.lams.web.tag.MultiLinesTextareaTag
@@ -289,11 +289,6 @@
true
- index
- false
- true
-
-
indexed
false
true
@@ -466,6 +461,10 @@
ImgButtonWrapper
/WEB-INF/tags/ImgButtonWrapper.tag
+
+
+ TextSearch
+ /WEB-INF/tags/TextSearch.tag
textarea
Index: lams_admin/web/WEB-INF/tags/TextSearch.tag
===================================================================
diff -u
--- lams_admin/web/WEB-INF/tags/TextSearch.tag (revision 0)
+++ lams_admin/web/WEB-INF/tags/TextSearch.tag (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -0,0 +1,136 @@
+<%
+/****************************************************************
+ * 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
+ * ****************************************************************
+ */
+
+ /**
+ * TextSearch.tag
+ * Author: Marcin Cieslak
+ * Description: Displays form for creating text search conditions.
+ */
+
+ %>
+<%@ 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" %>
+
+<%-- 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" %>
+<%@ attribute name="formID" required="false" rtexprvalue="true" %>
+<%@ attribute name="headingLabelKey" required="false" rtexprvalue="true" %>
+<%@ attribute name="allWordsLabelKey" required="false" rtexprvalue="true" %>
+<%@ attribute name="phraseLabelKey" required="false" rtexprvalue="true" %>
+<%@ attribute name="anyWordsLabelKey" required="false" rtexprvalue="true" %>
+<%@ attribute name="excludedWordsLabelKey" required="false" rtexprvalue="true" %>
+<%@ attribute name="saveButtonLabelKey" required="false" rtexprvalue="true" %>
+<%@ attribute name="cancelButtonLabelKey" required="false" rtexprvalue="true" %>
+<%@ attribute name="cancelAction" required="false" rtexprvalue="true" %>
+
+<%-- Default value for message key --%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
Index: lams_central/build.xml
===================================================================
diff -u -rc234c64ad9ff9d713f6d8e3331d0c20075e49303 -r9a772f5ba1954a3a719a19e7ae237b6b09dc76ef
--- lams_central/build.xml (.../build.xml) (revision c234c64ad9ff9d713f6d8e3331d0c20075e49303)
+++ lams_central/build.xml (.../build.xml) (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -165,6 +165,7 @@
+
Index: lams_central/conf/language/lams/ApplicationResources.properties
===================================================================
diff -u -r5bd95ffef22a2fdc60414cfd9cfb22968b88c13b -r9a772f5ba1954a3a719a19e7ae237b6b09dc76ef
--- lams_central/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 5bd95ffef22a2fdc60414cfd9cfb22968b88c13b)
+++ lams_central/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -232,4 +232,69 @@
videorecorder.instructions.fck =Click the record button to start and stop recording. Once a recording is completed, you can review it by clicking the play button. When ready to add the video, click the tick button.
-#======= End labels: Exported 224 labels for en AU =====
+index.planner =Planner
+planner.title =Pedagogical Planner
+label.description =Description
+planner.saved =All acitvities were saved successfully.
+planner.not.saved =There were errors in activities. Not all acitvities were saved.
+error.planner.title.blank =Sequence title must not be blank.
+label.planner.not.supported =This activity does not support the planner.
+button.planner.save =Save template
+button.planner.preview =Preview
+button.planner.view.full.author =View in Full Author
+
+label.planner.grouping.type=Group type
+label.planner.grouping.type.random=Random grouping
+label.planner.grouping.type.chosen=Choose in Monitor
+label.planner.grouping.type.learner.choice=Learner's choice
+label.planner.grouping.number.of.groups=Number of groups
+label.planner.grouping.number.of.learners=Number of learners
+error.planner.grouping.number.integer=Provided value must be a positive integer number.
+label.planner.grouping.equal.group.size=Equal group sizes
+msg.planner.not.saved =Are you sure you want to close? If you have not saved the design, changes you have made will be lost.
+label.planner.editing.advice=Editing advice
+label.planner.branch.empty =This branch is empty.
+label.planner.branch=Branch
+label.planner.branch.default=(default)
+label.planner.option=Option
+
+button.planner.editor.open=Open editor
+msg.planner.node.locked=This node is locked. You can not edit it.
+button.planner.save.node=Save node
+label.planner.create.subnode=Create subnode
+label.planner.edit.node=Edit node
+label.planner.root.node=Planner
+msg.planner.open.template=This node opens a planner template.
+msg.planner.remove.node=Remove node
+label.planner.empty.subnode=There are no subnodes defined.
+label.planner.description.brief=Brief description (for parent node)
+label.planner.description.full=Full description (for self)
+label.planner.root.choose=Choose a planner from one of the following activity categories:
+msg.planner.remove.warning=Are you sure you want to remove this node and all of its subnodes?
+
+label.planner.node.type=This node:
+label.planner.node.type.subnodes=has subnodes
+label.planner.node.type.template=opens a template
+label.planner.remove.file=Remove file
+label.planner.change.file=Change file:
+label.planner.uploaded.template=Uploaded template file:
+msg.planner.move.node.up=Move node up
+msg.planner.move.node.down=Move node down
+label.planner.choose.file=Choose a template file:
+error.planner.node.title.blank=Node title must not be blank.
+error.planner.repository=There was a file respository error. Template file was not saved.
+error.planner.file.empty=You must upload a file.
+error.planner.file.bad.extension=Template file must have a ZIP or LAS extension.
+
+error.planner.tools=There were tool errors. Learning design could not be retrieved.
+error.planner.learning.design.retrieve=Learning design could not be retrieved.
+error.planner.file.open=There was an error while opening the template file.
+error.planner.editor=There was an error while opening the editor.
+error.planner.export=There was an error while exporting the node.
+error.planner.import=There was an error while importing the node.
+label.planner.export=Export node
+label.planner.import=Import node
+
+label.planner.import.instruction=Please select Pedagogical Planner node to import. The import file must be a .zip file exported from LAMS 2 or above.
+label.planner.grouping.view.students=View students before selection
+#======= End labels: Exported 222 labels for en AU =====
Index: lams_central/conf/language/lams/ApplicationResources_en_AU.properties
===================================================================
diff -u -r5bd95ffef22a2fdc60414cfd9cfb22968b88c13b -r9a772f5ba1954a3a719a19e7ae237b6b09dc76ef
--- lams_central/conf/language/lams/ApplicationResources_en_AU.properties (.../ApplicationResources_en_AU.properties) (revision 5bd95ffef22a2fdc60414cfd9cfb22968b88c13b)
+++ lams_central/conf/language/lams/ApplicationResources_en_AU.properties (.../ApplicationResources_en_AU.properties) (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -232,4 +232,69 @@
videorecorder.instructions.fck =Click the record button to start and stop recording. Once a recording is completed, you can review it by clicking the play button. When ready to add the video, click the tick button.
-#======= End labels: Exported 224 labels for en AU =====
+index.planner =Planner
+planner.title =Pedagogical Planner
+label.description =Description
+planner.saved =All acitvities were saved successfully.
+planner.not.saved =There were errors in activities. Not all acitvities were saved.
+error.planner.title.blank =Sequence title must not be blank.
+label.planner.not.supported =This activity does not support the planner.
+button.planner.save =Save template
+button.planner.preview =Preview
+button.planner.view.full.author =View in Full Author
+
+label.planner.grouping.type=Group type
+label.planner.grouping.type.random=Random grouping
+label.planner.grouping.type.chosen=Choose in Monitor
+label.planner.grouping.type.learner.choice=Learner's choice
+label.planner.grouping.number.of.groups=Number of groups
+label.planner.grouping.number.of.learners=Number of learners
+error.planner.grouping.number.integer=Provided value must be a positive integer number.
+label.planner.grouping.equal.group.size=Equal group sizes
+msg.planner.not.saved =Are you sure you want to close? If you have not saved the design, changes you have made will be lost.
+label.planner.editing.advice=Editing advice
+label.planner.branch.empty =This branch is empty.
+label.planner.branch=Branch
+label.planner.branch.default=(default)
+label.planner.option=Option
+
+button.planner.editor.open=Open editor
+msg.planner.node.locked=This node is locked. You can not edit it.
+button.planner.save.node=Save node
+label.planner.create.subnode=Create subnode
+label.planner.edit.node=Edit node
+label.planner.root.node=Planner
+msg.planner.open.template=This node opens a planner template.
+msg.planner.remove.node=Remove node
+label.planner.empty.subnode=There are no subnodes defined.
+label.planner.description.brief=Brief description (for parent node)
+label.planner.description.full=Full description (for self)
+label.planner.root.choose=Choose a planner from one of the following activity categories:
+msg.planner.remove.warning=Are you sure you want to remove this node and all of its subnodes?
+
+label.planner.node.type=This node:
+label.planner.node.type.subnodes=has subnodes
+label.planner.node.type.template=opens a template
+label.planner.remove.file=Remove file
+label.planner.change.file=Change file:
+label.planner.uploaded.template=Uploaded template file:
+msg.planner.move.node.up=Move node up
+msg.planner.move.node.down=Move node down
+label.planner.choose.file=Choose a template file:
+error.planner.node.title.blank=Node title must not be blank.
+error.planner.repository=There was a file respository error. Template file was not saved.
+error.planner.file.empty=You must upload a file.
+error.planner.file.bad.extension=Template file must have a ZIP or LAS extension.
+
+error.planner.tools=There were tool errors. Learning design could not be retrieved.
+error.planner.learning.design.retrieve=Learning design could not be retrieved.
+error.planner.file.open=There was an error while opening the template file.
+error.planner.editor=There was an error while opening the editor.
+error.planner.export=There was an error while exporting the node.
+error.planner.import=There was an error while importing the node.
+label.planner.export=Export node
+label.planner.import=Import node
+
+label.planner.import.instruction=Please select Pedagogical Planner node to import. The import file must be a .zip file exported from LAMS 2 or above.
+label.planner.grouping.view.students=View students before selection
+#======= End labels: Exported 222 labels for en AU =====
Index: lams_central/conf/xdoclet/taglibs.xml
===================================================================
diff -u -rc697b5c30ab742ab453859355b35cd518856334f -r9a772f5ba1954a3a719a19e7ae237b6b09dc76ef
--- lams_central/conf/xdoclet/taglibs.xml (.../taglibs.xml) (revision c697b5c30ab742ab453859355b35cd518856334f)
+++ lams_central/conf/xdoclet/taglibs.xml (.../taglibs.xml) (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -65,7 +65,7 @@
fck-editor
- /WEB-INF/jstl/tlds/FCKeditor.tld
+ /WEB-INF/fckeditor/tlds/FCKeditor.tld
Index: lams_central/src/java/org/lamsfoundation/lams/authoring/service/AuthoringService.java
===================================================================
diff -u -rc697b5c30ab742ab453859355b35cd518856334f -r9a772f5ba1954a3a719a19e7ae237b6b09dc76ef
--- lams_central/src/java/org/lamsfoundation/lams/authoring/service/AuthoringService.java (.../AuthoringService.java) (revision c697b5c30ab742ab453859355b35cd518856334f)
+++ lams_central/src/java/org/lamsfoundation/lams/authoring/service/AuthoringService.java (.../AuthoringService.java) (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -534,8 +534,8 @@
}
if (design != null) { /*
- * only the user who is editing the design may unlock it
- */
+ * only the user who is editing the design may unlock it
+ */
if (design.getEditOverrideUser().equals(user)) {
design.setEditOverrideLock(false);
design.setEditOverrideUser(null);
@@ -1363,17 +1363,18 @@
HashSet newCompeteces = new HashSet();
Set oldCompetences = originalLearningDesign.getCompetences();
- for (Competence competence : oldCompetences) {
- Competence newCompetence = competence.createCopy(competence);
- newCompetence.setLearningDesign(newLearningDesign);
+ if (oldCompetences != null) {
+ for (Competence competence : oldCompetences) {
+ Competence newCompetence = competence.createCopy(competence);
+ newCompetence.setLearningDesign(newLearningDesign);
- // check for existing competences to prevent duplicates
- if (competenceDAO.getCompetence(newLearningDesign, newCompetence.getTitle()) == null) {
- competenceDAO.saveOrUpdate(newCompetence);
+ // check for existing competences to prevent duplicates
+ if (competenceDAO.getCompetence(newLearningDesign, newCompetence.getTitle()) == null) {
+ competenceDAO.saveOrUpdate(newCompetence);
+ }
+ newCompeteces.add(newCompetence);
}
- newCompeteces.add(newCompetence);
}
-
if (newLearningDesign.getCompetences() != null) {
if (!insert) {
newLearningDesign.getCompetences().clear();
Index: lams_central/src/java/org/lamsfoundation/lams/util/CentralConstants.java
===================================================================
diff -u -rc697b5c30ab742ab453859355b35cd518856334f -r9a772f5ba1954a3a719a19e7ae237b6b09dc76ef
--- lams_central/src/java/org/lamsfoundation/lams/util/CentralConstants.java (.../CentralConstants.java) (revision c697b5c30ab742ab453859355b35cd518856334f)
+++ lams_central/src/java/org/lamsfoundation/lams/util/CentralConstants.java (.../CentralConstants.java) (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -155,6 +155,8 @@
public static final String PARAM_CREATE_SUBNODE = "createSubnode";
+ public static final String PARAM_IMPORT_NODE = "importNode";
+
public static final String PARAM_UID = "uid";
public static final String CENTRAL_TOOL_CONTENT_HANDLER_BEAN_NAME = "centralToolContentHandler";
Index: lams_central/src/java/org/lamsfoundation/lams/web/planner/PedagogicalPlannerAction.java
===================================================================
diff -u -r5a30100855d83534e76db8dec0d0b603a1a1ded8 -r9a772f5ba1954a3a719a19e7ae237b6b09dc76ef
--- lams_central/src/java/org/lamsfoundation/lams/web/planner/PedagogicalPlannerAction.java (.../PedagogicalPlannerAction.java) (revision 5a30100855d83534e76db8dec0d0b603a1a1ded8)
+++ lams_central/src/java/org/lamsfoundation/lams/web/planner/PedagogicalPlannerAction.java (.../PedagogicalPlannerAction.java) (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -23,15 +23,21 @@
/* $$Id$$ */
package org.lamsfoundation.lams.web.planner;
+import java.io.BufferedInputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@@ -76,15 +82,22 @@
import org.lamsfoundation.lams.usermanagement.service.IUserManagementService;
import org.lamsfoundation.lams.util.CentralConstants;
import org.lamsfoundation.lams.util.CentralToolContentHandler;
+import org.lamsfoundation.lams.util.Configuration;
+import org.lamsfoundation.lams.util.ConfigurationKeys;
import org.lamsfoundation.lams.util.FileUtil;
+import org.lamsfoundation.lams.util.FileUtilException;
import org.lamsfoundation.lams.util.MessageService;
import org.lamsfoundation.lams.util.WebUtil;
+import org.lamsfoundation.lams.util.zipfile.ZipFileUtil;
+import org.lamsfoundation.lams.util.zipfile.ZipFileUtilException;
import org.lamsfoundation.lams.web.action.LamsDispatchAction;
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.thoughtworks.xstream.XStream;
+
/**
* Action managing Pedagogical Planner base page and non-tool activities.
*
@@ -105,6 +118,7 @@
private static final String FILE_EXTENSION_ZIP = ".zip";
private static final String FILE_EXTENSION_LAS = ".las";
+ // ActionForwards
private static final String FORWARD_TEMPLATE = "template";
private static final String FORWARD_PREVIEW = "preview";
private static final String FORWARD_SEQUENCE_CHOOSER = "sequenceChooser";
@@ -123,8 +137,9 @@
private static MessageService messageService;
private static PedagogicalPlannerDAO pedagogicalPlannerDAO;
private static ToolContentHandler contentHandler;
+ private static final String PEDAGOGICAL_PLANNER_DAO_BEAN_NAME = "pedagogicalPlannerDAO";
- // Error messages used in class
+ // Keys of error messages used in this class. They are ment to be displayed for user.
private static final String ERROR_KEY_TOOL_ERRORS = "error.planner.tools.";
private static final String ERROR_KEY_NODE_TITLE_BLANK = "error.planner.node.title.blank";
private static final String ERROR_KEY_REPOSITORY = "error.planner.repository";
@@ -133,7 +148,10 @@
private static final String ERROR_KEY_FILE_OPEN = "error.planner.file.open";
private static final String ERROR_KEY_LEARNING_DESIGN_COULD_NOT_BE_RETRIEVED = "error.planner.learning.design.retrieve";
private static final String ERROR_KEY_EDITOR = "error.planner.editor";
+ private static final String ERROR_KEY_EXPORT = "error.planner.export";
+ private static final String ERROR_KEY_IMPORT = "error.planner.import";
+ // Error messages used in this class. They are ment to be thrown.
private static final String ERROR_USER_NOT_FOUND = "User not found.";
private static final String ERROR_NOT_PROPER_FILE = "The sequence template does not exist or is not a proper file.";
private static final String ERROR_TOO_MANY_OPTIONS = "Number of options in options activity is limited to "
@@ -145,112 +163,71 @@
private static Logger log = Logger.getLogger(PedagogicalPlannerAction.class);
- private static final String PEDAGOGICAL_PLANNER_DAO_BEAN_NAME = "pedagogicalPlannerDAO";
+ // Paths used in templateBase.jsp
private static final String IMAGE_PATH_GATE = "images/stop.gif";
private static final String PATH_ACTIVITY_NO_PLANNER_SUPPORT = "/pedagogical_planner/defaultActivityForm.jsp";
private static final String IMAGE_PATH_GROUPING = "images/grouping.gif";
+ // Parts of paths used in importing/exporting nodes
+
+ private static final String NODE_FILE_NAME = "node.xml";
+ private static final String DIR_CONTENT = "content";
+ private static final String DIR_TEMPLATES = "template";
+
+ private static final String EXPORT_NODE_FOLDER_SUFFIX = "export_node";
+ private static final String EXPORT_NODE_CONTENT_ZIP_PREFIX = "content_";
+ private static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition";
+ private static final String RESPONSE_CONTENT_TYPE_DOWNLOAD = "application/x-download";
+ private static final String ENCODING_UTF_8 = "UTF-8";
+ private static final String DIR_UPLOADED_NODE_SUFFIX = "_uploaded_node";
+ private static final String EXPORT_NODE_ZIP_PREFIX = "lams_planner_node_";
+
+ private static final int FILE_COPY_BUFFER_SIZE = 1024;
+
@Override
/**
- * Go straight to start().
+ * Go straight to open sequence node.
*/
public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
return openSequenceNode(mapping, form, request, response);
}
+ /*----------------------- TEMPLATE CHOOSER METHODS --------------------*/
+
/**
* The main method for opening and parsing template (chosen learning desing).
*
* @param mapping
* @param form
* @param request
- * @param response
+ * @param fileUuid
+ * @param fileName
* @return
* @throws ServletException
- * @throws IOException
*/
private ActionForward openTemplate(ActionMapping mapping, ActionForm form, HttpServletRequest request,
Long fileUuid, String fileName) throws ServletException {
- // Get the learning design template zip file
+
ActionMessages errors = new ActionMessages();
- File designFile = null;
-
- try {
- designFile = copyFileFromRepository(fileUuid, fileName);
- } catch (Exception e) {
- PedagogicalPlannerAction.log.error(e);
- errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(PedagogicalPlannerAction.ERROR_KEY_FILE_OPEN));
+ // Open the learning design stored in the repository.
+ LearningDesign learningDesign = importLearningDesign(fileUuid, fileName, errors);
+ if (!errors.isEmpty()) {
saveErrors(request, errors);
+ // If anything goes wrong, open the root node. Errors will be displayed at top.
+ // This approach is used widely in this action.
return openSequenceNode(mapping, form, request, (Long) null);
}
- if (!designFile.exists() || designFile.isDirectory()) {
- PedagogicalPlannerAction.log.error(PedagogicalPlannerAction.ERROR_NOT_PROPER_FILE);
- errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(PedagogicalPlannerAction.ERROR_KEY_FILE_OPEN));
- saveErrors(request, errors);
- return openSequenceNode(mapping, form, request, (Long) null);
- }
- HttpSession session = SessionManager.getSession();
- UserDTO userDto = (UserDTO) session.getAttribute(AttributeNames.USER);
- User user = (User) getUserManagementService().findById(User.class, userDto.getUserID());
- if (user == null) {
- throw new ServletException(PedagogicalPlannerAction.ERROR_USER_NOT_FOUND);
- }
- List toolsErrorMsgs = new ArrayList();
- Long learningDesignID = null;
- LearningDesign learningDesign = null;
- List learningDesignErrorMsgs = new ArrayList();
- // Extract the template
-
- try {
- Object[] ldResults = getExportService().importLearningDesign(designFile, user, null, toolsErrorMsgs, "");
- designFile.delete();
- learningDesignID = (Long) ldResults[0];
- learningDesignErrorMsgs = (List) ldResults[1];
- toolsErrorMsgs = (List) ldResults[2];
- learningDesign = getAuthoringService().getLearningDesign(learningDesignID);
- } catch (ImportToolContentException e) {
- PedagogicalPlannerAction.log.error(e);
- errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
- PedagogicalPlannerAction.ERROR_KEY_LEARNING_DESIGN_COULD_NOT_BE_RETRIEVED));
- saveErrors(request, errors);
- return openSequenceNode(mapping, form, request, (Long) null);
- }
-
- if ((learningDesignID == null || learningDesignID.longValue() == -1) && learningDesignErrorMsgs.size() == 0) {
- errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
- PedagogicalPlannerAction.ERROR_KEY_LEARNING_DESIGN_COULD_NOT_BE_RETRIEVED));
- saveErrors(request, errors);
- return openSequenceNode(mapping, form, request, (Long) null);
- }
- if (learningDesignErrorMsgs.size() > 0) {
- for (String error : learningDesignErrorMsgs) {
- PedagogicalPlannerAction.log.error(error);
- }
- errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
- PedagogicalPlannerAction.ERROR_KEY_LEARNING_DESIGN_COULD_NOT_BE_RETRIEVED));
- saveErrors(request, errors);
- return openSequenceNode(mapping, form, request, (Long) null);
- }
- if (toolsErrorMsgs.size() > 0) {
- for (String error : toolsErrorMsgs) {
- PedagogicalPlannerAction.log.error(error);
- }
- errors
- .add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
- PedagogicalPlannerAction.ERROR_KEY_TOOL_ERRORS));
- return openSequenceNode(mapping, form, request, (Long) null);
- }
-
List activities = new ArrayList();
- // create DTOs that hold all the necessary information of the activities
+ // Create DTOs that hold all the necessary information of the activities
Activity activity = learningDesign.getFirstActivity();
+ PedagogicalPlannerAction.log.debug("Parsing learning design activities");
try {
while (activity != null) {
- // Iterate through all the activities
+ // Iterate through all the activities, detecting type of each one
addActivityToPlanner(learningDesign, activities, activity);
Transition transitionTo = activity.getTransitionTo();
if (transitionTo == null) {
@@ -267,6 +244,7 @@
return openSequenceNode(mapping, form, request, (Long) null);
}
+ // Recalculate how many activities actually support the planner
int activitySupportingPlannerCount = 0;
for (PedagogicalPlannerActivityDTO activityDTO : activities) {
if (activityDTO.getSupportsPlanner()) {
@@ -278,7 +256,7 @@
planner.setActivitySupportingPlannerCount(activitySupportingPlannerCount);
planner.setSequenceTitle(learningDesign.getTitle());
planner.setActivities(activities);
- planner.setLearningDesignID(learningDesignID);
+ planner.setLearningDesignID(learningDesign.getLearningDesignId());
// Some additional options for submitting activity forms; should be moved to configuration file in the future
planner.setSendInPortions(false);
@@ -290,99 +268,6 @@
}
/**
- * Saves additional, non tool bound template details - currently only the title.
- *
- * @param mapping
- * @param form
- * @param request
- * @param response
- * @return
- * @throws IOException
- */
- public ActionForward saveSequenceDetails(ActionMapping mapping, ActionForm form, HttpServletRequest request,
- HttpServletResponse response) throws IOException {
- String sequenceTitle = WebUtil.readStrParam(request, CentralConstants.PARAM_SEQUENCE_TITLE, true);
- Long learningDesignID = WebUtil.readLongParam(request, CentralConstants.PARAM_LEARNING_DESIGN_ID);
- Integer callAttemptedID = WebUtil.readIntParam(request, CentralConstants.PARAM_CALL_ATTEMPTED_ID);
- // We send a message in format "&"; it is then parsed in JavaScript
- String responseSuffix = PedagogicalPlannerAction.CHAR_AMPERSAND + callAttemptedID;
-
- if (StringUtils.isEmpty(sequenceTitle)) {
- String blankTitleError = getMessageService().getMessage(CentralConstants.ERROR_PLANNER_TITLE_BLANK);
- writeAJAXResponse(response, blankTitleError + responseSuffix);
- } else {
- LearningDesign learningDesign = getAuthoringService().getLearningDesign(learningDesignID);
- learningDesign.setTitle(sequenceTitle);
- getAuthoringService().saveLearningDesign(learningDesign);
- writeAJAXResponse(response, PedagogicalPlannerAction.STRING_OK + responseSuffix);
- }
- return null;
- }
-
- public ActionForward initGrouping(ActionMapping mapping, ActionForm form, HttpServletRequest request,
- HttpServletResponse response) {
- PedagogicalPlannerGroupingForm plannerForm = (PedagogicalPlannerGroupingForm) form;
- Long groupingId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID);
- Grouping grouping = getAuthoringService().getGroupingById(groupingId);
- plannerForm.fillForm(grouping);
- return mapping.findForward(CentralConstants.FORWARD_GROUPING);
- }
-
- public ActionForward saveOrUpdateGroupingForm(ActionMapping mapping, ActionForm form, HttpServletRequest request,
- HttpServletResponse response) {
- PedagogicalPlannerGroupingForm plannerForm = (PedagogicalPlannerGroupingForm) form;
- ActionMessages errors = plannerForm.validate();
- if (errors.isEmpty()) {
- Grouping grouping = getAuthoringService().getGroupingById(plannerForm.getToolContentID());
- if (grouping.isRandomGrouping()) {
- RandomGrouping randomGrouping = (RandomGrouping) grouping;
- Integer number = StringUtils.isEmpty(plannerForm.getNumberOfGroups()) ? null : Integer
- .parseInt(plannerForm.getNumberOfGroups());
- randomGrouping.setNumberOfGroups(number);
-
- number = StringUtils.isEmpty(plannerForm.getLearnersPerGroup()) ? null : Integer.parseInt(plannerForm
- .getLearnersPerGroup());
- randomGrouping.setLearnersPerGroup(number);
- } else if (grouping.isLearnerChoiceGrouping()) {
- LearnerChoiceGrouping learnerChoiceGrouping = (LearnerChoiceGrouping) grouping;
- Integer number = StringUtils.isEmpty(plannerForm.getNumberOfGroups()) ? null : Integer
- .parseInt(plannerForm.getNumberOfGroups());
- learnerChoiceGrouping.setNumberOfGroups(number);
-
- number = StringUtils.isEmpty(plannerForm.getLearnersPerGroup()) ? null : Integer.parseInt(plannerForm
- .getLearnersPerGroup());
- learnerChoiceGrouping.setLearnersPerGroup(number);
- learnerChoiceGrouping.setEqualNumberOfLearnersPerGroup(plannerForm.getEqualGroupSizes());
- } else {
- Integer number = StringUtils.isEmpty(plannerForm.getNumberOfGroups()) ? null : Integer
- .parseInt(plannerForm.getNumberOfGroups());
- grouping.setMaxNumberOfGroups(number);
- }
- } else {
- saveMessages(request, errors);
- }
- return mapping.findForward(CentralConstants.FORWARD_GROUPING);
- }
-
- public ActionForward startPreview(ActionMapping mapping, ActionForm form, HttpServletRequest request,
- HttpServletResponse response) {
- Long learningDesignID = WebUtil.readLongParam(request, CentralConstants.PARAM_LEARNING_DESIGN_ID);
- HttpSession session = SessionManager.getSession();
- UserDTO userDto = (UserDTO) session.getAttribute(AttributeNames.USER);
-
- // Start preview the same way as in authoring
- Lesson lesson = getMonitoringService().initializeLessonForPreview("Preview", null, learningDesignID,
- userDto.getUserID(), null, false, false, false);
- getMonitoringService().createPreviewClassForLesson(userDto.getUserID(), lesson.getLessonId());
-
- getMonitoringService().startLesson(lesson.getLessonId(), userDto.getUserID());
- String newPath = mapping.findForward(PedagogicalPlannerAction.FORWARD_PREVIEW).getPath();
- newPath = newPath + PedagogicalPlannerAction.CHAR_AMPERSAND + AttributeNames.PARAM_LESSON_ID
- + PedagogicalPlannerAction.CHAR_EQUALS + lesson.getLessonId();
- return new ActionForward(newPath, true);
- }
-
- /**
* Recognises activitiy type and creates proper DTO for web pages use. For branching and options it can be called
* recursevely.
*
@@ -397,6 +282,8 @@
*/
private PedagogicalPlannerActivityDTO addActivityToPlanner(LearningDesign learningDesign,
List activities, Activity activity) throws ServletException {
+ PedagogicalPlannerAction.log.debug("Parsing activity: " + activity.getTitle());
+
// Check if the activity is contained in some complex activity: branching or options
boolean isNested = activity.getParentActivity() != null
&& (activity.getParentActivity().isBranchingActivity() || activity.isOptionsActivity());
@@ -537,6 +424,7 @@
}
addedDTO.setLastNestedActivity(true);
} else {
+ // If unknown/unsupported activity
addedDTO = new PedagogicalPlannerActivityDTO(null, activity.getTitle(), false,
PedagogicalPlannerAction.PATH_ACTIVITY_NO_PLANNER_SUPPORT, activity.getLibraryActivityUiImage(),
null, null);
@@ -545,51 +433,119 @@
return addedDTO;
}
+ /**
+ * Starts a lesson preview, both in sequence chooser and in template base.
+ *
+ * @param mapping
+ * @param form
+ * @param request
+ * @param response
+ * @return
+ * @throws ServletException
+ */
+ public ActionForward startPreview(ActionMapping mapping, ActionForm form, HttpServletRequest request,
+ HttpServletResponse response) throws ServletException {
+
+ Long learningDesignID = WebUtil.readLongParam(request, CentralConstants.PARAM_LEARNING_DESIGN_ID, true);
+ if (learningDesignID == null) {
+ Long nodeUid = WebUtil.readLongParam(request, CentralConstants.PARAM_UID);
+ PedagogicalPlannerSequenceNode node = getPedagogicalPlannerDAO().getByUid(nodeUid);
+ ActionMessages errors = new ActionMessages();
+ LearningDesign learningDesign = importLearningDesign(node.getFileUuid(), node.getFileName(), errors);
+ if (!errors.isEmpty()) {
+ ActionMessage error = (ActionMessage) errors.get().next();
+ String errorMessage = getMessageService().getMessage(error.getKey());
+ throw new ServletException(errorMessage);
+ }
+ learningDesignID = learningDesign.getLearningDesignId();
+ }
+ HttpSession session = SessionManager.getSession();
+ UserDTO userDto = (UserDTO) session.getAttribute(AttributeNames.USER);
+
+ // Start preview the same way as in authoring
+ PedagogicalPlannerAction.log.debug("Opening preview for learnind design id: " + learningDesignID);
+ Lesson lesson = getMonitoringService().initializeLessonForPreview("Preview", null, learningDesignID,
+ userDto.getUserID(), null, false, false, false);
+ getMonitoringService().createPreviewClassForLesson(userDto.getUserID(), lesson.getLessonId());
+
+ getMonitoringService().startLesson(lesson.getLessonId(), userDto.getUserID());
+ String newPath = mapping.findForward(PedagogicalPlannerAction.FORWARD_PREVIEW).getPath();
+ newPath = newPath + PedagogicalPlannerAction.CHAR_AMPERSAND + AttributeNames.PARAM_LESSON_ID
+ + PedagogicalPlannerAction.CHAR_EQUALS + lesson.getLessonId();
+ return new ActionForward(newPath, true);
+ }
+
+ /**
+ * Reads UID of the node and goes straight to
+ * {@link #openSequenceNode(ActionMapping, ActionForm, HttpServletRequest, Long)}
+ *
+ * @param mapping
+ * @param form
+ * @param request
+ * @param response
+ * @return
+ * @throws IOException
+ * @throws ServletException
+ */
public ActionForward openSequenceNode(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
Long nodeUid = WebUtil.readLongParam(request, CentralConstants.PARAM_UID, true);
return openSequenceNode(mapping, form, request, nodeUid);
}
+ /**
+ * Opens a sequence node and fill the necessary data into DTO and form.
+ *
+ * @param mapping
+ * @param form
+ * @param request
+ * @param nodeUid
+ * @return
+ * @throws ServletException
+ */
public ActionForward openSequenceNode(ActionMapping mapping, ActionForm form, HttpServletRequest request,
Long nodeUid) throws ServletException {
+ // Only SysAdmin can open the editor
Boolean isSysAdmin = request.isUserInRole(Role.SYSADMIN);
Boolean edit = WebUtil.readBooleanParam(request, CentralConstants.PARAM_EDIT, false);
edit &= isSysAdmin;
-
+ // Do we display the root (top) node or an existing one
PedagogicalPlannerSequenceNode node = null;
if (nodeUid == null) {
node = getPedagogicalPlannerDAO().getRootNode();
} else {
node = getPedagogicalPlannerDAO().getByUid(nodeUid);
if (!edit && node.getFileUuid() != null) {
+ // If we are not in the edit mode and we open a node containing a template, then we open the template
return openTemplate(mapping, form, request, node.getFileUuid(), node.getFileName());
}
}
+ PedagogicalPlannerAction.log.debug("Opening sequence node with UID: " + nodeUid);
+
+ // Fill the DTO
List titlePath = getPedagogicalPlannerDAO().getTitlePath(node);
PedagogicalPlannerSequenceNodeDTO dto = new PedagogicalPlannerSequenceNodeDTO(node, titlePath);
+ // Additional DTO parameters
Boolean createSubnode = WebUtil.readBooleanParam(request, CentralConstants.PARAM_CREATE_SUBNODE, false);
+ Boolean importNode = WebUtil.readBooleanParam(request, CentralConstants.PARAM_IMPORT_NODE, false);
dto.setCreateSubnode(createSubnode);
dto.setEdit(edit);
dto.setIsSysAdmin(isSysAdmin);
+ dto.setImportNode(importNode);
request.setAttribute(CentralConstants.ATTR_NODE, dto);
if (edit) {
+ // If we are in edit mode, the node form is displayed, requiring additional parameters
PedagogicalPlannerSequenceNodeForm nodeForm = (PedagogicalPlannerSequenceNodeForm) form;
- nodeForm.setNodeType(node.getFileName() == null ? PedagogicalPlannerSequenceNodeForm.NODE_TYPE_SUBNODES
- : PedagogicalPlannerSequenceNodeForm.NODE_TYPE_TEMPLATE);
- nodeForm.setRemoveFile(false);
- nodeForm.setTitle(dto.getTitle());
- nodeForm.setBriefDescription(dto.getBriefDescription());
- nodeForm.setFullDescription(dto.getFullDescription());
- nodeForm.setFileUuid(node.getFileUuid());
if (createSubnode) {
- if (node.getParent() == null) {
+ // We create a new node, rather than edit the existing one
+ if (node.getContentFolderId() == null) {
try {
- String contentFolderId = getAuthoringService().generateUniqueContentFolder();
+ // If it's a new top level node, we create an uniuqe ID
+ String contentFolderId = FileUtil.generateUniqueContentFolderID();
nodeForm.setContentFolderId(contentFolderId);
} catch (Exception e) {
PedagogicalPlannerAction.log.error(e);
@@ -602,20 +558,42 @@
return openSequenceNode(mapping, form, request, (Long) null);
}
} else {
- nodeForm.setContentFolderId(node.getParent().getContentFolderId());
+ // Whole node tree share the same content folder ID
+ nodeForm.setContentFolderId(node.getContentFolderId());
}
+ } else if (!importNode) {
+ // We fill the form with necessary data
+ nodeForm.setNodeType(node.getFileName() == null ? PedagogicalPlannerSequenceNodeForm.NODE_TYPE_SUBNODES
+ : PedagogicalPlannerSequenceNodeForm.NODE_TYPE_TEMPLATE);
+ nodeForm.setRemoveFile(false);
+ nodeForm.setTitle(dto.getTitle());
+ nodeForm.setBriefDescription(dto.getBriefDescription());
+ nodeForm.setFullDescription(dto.getFullDescription());
+ nodeForm.setFileUuid(node.getFileUuid());
}
}
return mapping.findForward(PedagogicalPlannerAction.FORWARD_SEQUENCE_CHOOSER);
}
+ /**
+ * Saves the created/edited sequence node.
+ *
+ * @param mapping
+ * @param form
+ * @param request
+ * @param response
+ * @return
+ * @throws IOException
+ * @throws ServletException
+ */
public ActionForward saveSequenceNode(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
Long nodeUid = WebUtil.readLongParam(request, CentralConstants.PARAM_UID, true);
PedagogicalPlannerSequenceNode node = null;
PedagogicalPlannerSequenceNodeForm nodeForm = (PedagogicalPlannerSequenceNodeForm) form;
if (nodeUid == null) {
+ // It's a new subnode
node = new PedagogicalPlannerSequenceNode();
Long parentUid = nodeForm.getParentUid() == 0 ? null : nodeForm.getParentUid();
if (parentUid != null) {
@@ -624,10 +602,13 @@
}
node.setOrder(getPedagogicalPlannerDAO().getNextOrderId(parentUid));
} else {
+ // It's an existing node
node = getPedagogicalPlannerDAO().getByUid(nodeUid);
nodeUid = node.getUid();
}
+ PedagogicalPlannerAction.log.debug("Saving sequence node with UID: " + nodeUid);
+ // If anything goes wrong, we need to put back these values
String title = nodeForm.getTitle();
String briefDescription = nodeForm.getBriefDescription();
String fullDescription = nodeForm.getFullDescription();
@@ -640,6 +621,7 @@
node.setBriefDescription(briefDescription);
node.setContentFolderId(nodeForm.getContentFolderId());
+ // Different properties are set, depending on node type: with subnodes or template
if (PedagogicalPlannerSequenceNodeForm.NODE_TYPE_SUBNODES.equals(nodeForm.getNodeType())) {
if (node.getFileUuid() != null) {
getContentHandler().deleteFile(node.getFileUuid());
@@ -652,22 +634,35 @@
node.setFileName(null);
node.setFileUuid(null);
node.setFullDescription(null);
- } else if (nodeForm.getFile() != null) {
+ } else if (nodeForm.getFile() != null && nodeForm.getFile().getFileSize() > 0) {
FormFile file = nodeForm.getFile();
InputStream inputStream = file.getInputStream();
String fileName = file.getFileName();
String type = file.getContentType();
+
+ PedagogicalPlannerAction.log.debug("Uploading to repository file: " + fileName);
+ // Upload to repository
NodeKey nodeKey = getContentHandler().uploadFile(inputStream, fileName, type,
IToolContentHandler.TYPE_OFFLINE);
if (node.getFileUuid() != null) {
getContentHandler().deleteFile(node.getFileUuid());
}
+
+ // If there were subnodes, we delete them now
+ Iterator subnodeIter = node.getSubnodes().iterator();
+ while (subnodeIter.hasNext()) {
+ PedagogicalPlannerSequenceNode subnode = subnodeIter.next();
+ subnodeIter.remove();
+ getPedagogicalPlannerDAO().removeNode(subnode);
+ }
+
node.setFileUuid(nodeKey.getUuid());
node.setFileName(fileName);
node.setFullDescription(null);
}
getPedagogicalPlannerDAO().saveOrUpdateNode(node);
+ // If it was a new subnode, we need to retrieved the assigned UID
nodeUid = node.getUid();
} catch (RepositoryCheckedException e) {
@@ -676,11 +671,15 @@
PedagogicalPlannerAction.log.error(e);
}
}
+
+ // If something went wrong and the new subnode was not saved,
+ // we need to inform the following method of that fact
boolean createSubnode = false;
if (nodeUid == null) {
nodeUid = node.getParent() == null ? null : node.getParent().getUid();
createSubnode = true;
}
+ // Set the parameters, but do not return yet
openSequenceNode(mapping, form, request, nodeUid);
if (!errors.isEmpty()) {
@@ -698,44 +697,75 @@
return mapping.findForward(PedagogicalPlannerAction.FORWARD_SEQUENCE_CHOOSER);
}
+ /**
+ * Validates node form fields.
+ *
+ * @param node
+ * @param form
+ * @return
+ */
private ActionMessages validateNodeForm(PedagogicalPlannerSequenceNode node, PedagogicalPlannerSequenceNodeForm form) {
ActionMessages errors = new ActionMessages();
+ // Title must not be blank
if (StringUtils.isEmpty(form.getTitle())) {
errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
PedagogicalPlannerAction.ERROR_KEY_NODE_TITLE_BLANK));
}
+ // Template must a proper file
if (PedagogicalPlannerSequenceNodeForm.NODE_TYPE_TEMPLATE.equals(form.getNodeType())
&& node.getFileName() == null) {
- if (form.getFile() == null || form.getFile().getFileSize() == 0) {
- errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
- PedagogicalPlannerAction.ERROR_KEY_FILE_EMPTY));
- } else {
- String fileName = form.getFile().getFileName();
- boolean badExtension = false;
- if (fileName.length() >= 4) {
- String extension = fileName.substring(fileName.length() - 4);
- if (!(extension.equalsIgnoreCase(PedagogicalPlannerAction.FILE_EXTENSION_LAS) || extension
- .equalsIgnoreCase(PedagogicalPlannerAction.FILE_EXTENSION_ZIP))) {
- badExtension = true;
- }
- } else {
+ errors.add(validateFormFile(form));
+ }
+ return errors;
+ }
+
+ /**
+ * Validates form file. Used both for templates and exported nodes.
+ *
+ * @param form
+ * @return
+ */
+ private ActionMessages validateFormFile(PedagogicalPlannerSequenceNodeForm form) {
+ ActionMessages errors = new ActionMessages();
+ if (form.getFile() == null || form.getFile().getFileSize() == 0) {
+ errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(PedagogicalPlannerAction.ERROR_KEY_FILE_EMPTY));
+ } else {
+ String fileName = form.getFile().getFileName();
+ boolean badExtension = false;
+ if (fileName.length() >= 4) {
+ String extension = fileName.substring(fileName.length() - 4);
+ if (!(extension.equalsIgnoreCase(PedagogicalPlannerAction.FILE_EXTENSION_LAS) || extension
+ .equalsIgnoreCase(PedagogicalPlannerAction.FILE_EXTENSION_ZIP))) {
badExtension = true;
}
- if (badExtension) {
- errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
- PedagogicalPlannerAction.ERROR_KEY_FILE_BAD_EXTENSION));
- }
-
+ } else {
+ badExtension = true;
}
+ if (badExtension) {
+ errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
+ PedagogicalPlannerAction.ERROR_KEY_FILE_BAD_EXTENSION));
+ }
}
return errors;
}
+ /**
+ * Removes the selected node and all of its subnodes
+ *
+ * @param mapping
+ * @param form
+ * @param request
+ * @param response
+ * @return
+ * @throws IOException
+ * @throws ServletException
+ */
public ActionForward removeSequenceNode(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
Long nodeUid = WebUtil.readLongParam(request, CentralConstants.PARAM_UID);
PedagogicalPlannerSequenceNode node = getPedagogicalPlannerDAO().getByUid(nodeUid);
Long parentUid = node.getParent() == null ? null : node.getParent().getUid();
+ PedagogicalPlannerAction.log.debug("Removing sequence node with UID" + nodeUid);
getPedagogicalPlannerDAO().removeNode(node);
return openSequenceNode(mapping, form, request, parentUid);
}
@@ -767,11 +797,359 @@
return openSequenceNode(mapping, form, request, parentUid);
}
- private File copyFileFromRepository(Long fileUuid, String fileName) throws RepositoryCheckedException, IOException {
- InputStream inputStream = getContentHandler().getFileNode(fileUuid).getFile();
- File file = new File(FileUtil.TEMP_DIR, fileName);
- FileOutputStream fileOutputStream = new FileOutputStream(file);
- byte[] data = new byte[1024];
+ /**
+ * Exports the selected node to a ZIP file. Method is based on a similar one for exporting learning designs.
+ *
+ * @param mapping
+ * @param form
+ * @param request
+ * @param response
+ * @return
+ * @throws ServletException
+ * @throws IOException
+ */
+ public ActionForward exportNode(ActionMapping mapping, ActionForm form, HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+ Long nodeUid = WebUtil.readLongParam(request, CentralConstants.PARAM_UID);
+ ActionMessages errors = new ActionMessages();
+
+ PedagogicalPlannerAction.log.debug("Exporting sequence node with UID" + nodeUid);
+ String zipFilePath = null;
+ // Different browsers handle stream downloads differently LDEV-1243
+ String filename = null;
+ try {
+ zipFilePath = exportNode(nodeUid);
+
+ // get only filename
+ String zipfile = FileUtil.getFileName(zipFilePath);
+
+ // replace spaces (" ") with underscores ("_")
+
+ zipfile = zipfile.replaceAll(" ", "_");
+
+ // write zip file as response stream.
+
+ filename = FileUtil.encodeFilenameForDownload(request, zipfile);
+
+ PedagogicalPlannerAction.log.debug("Final filename to export: " + filename);
+
+ response.setContentType(PedagogicalPlannerAction.RESPONSE_CONTENT_TYPE_DOWNLOAD);
+ // response.setContentType("application/zip");
+ response.setHeader(PedagogicalPlannerAction.HEADER_CONTENT_DISPOSITION, "attachment;filename=" + filename);
+ } catch (Exception e) {
+ PedagogicalPlannerAction.log.error(e);
+ errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(PedagogicalPlannerAction.ERROR_KEY_EXPORT));
+ saveErrors(request, errors);
+ return openSequenceNode(mapping, form, request, nodeUid);
+ }
+ InputStream in = null;
+ ServletOutputStream out = null;
+ try {
+ in = new BufferedInputStream(new FileInputStream(zipFilePath));
+ out = response.getOutputStream();
+ int count = 0;
+
+ int ch;
+ while ((ch = in.read()) != -1) {
+ out.write((char) ch);
+ count++;
+ }
+ PedagogicalPlannerAction.log.debug("Wrote out " + count + " bytes");
+ response.setContentLength(count);
+ out.flush();
+ } finally {
+ /*
+ * If anything goes wrong, we can not display it nicely for the user. Once response.getOutputStream() was
+ * called to write the file data, we can not forward to a JSP page anymore. Maybe there is a way to avoid
+ * it, but currently we are simply throwing an error. So no "catch" clause.
+ */
+ if (in != null) {
+ in.close(); // very important
+ }
+ }
+ return null;
+ }
+
+ /**
+ * The proper method for exporting nodes.
+ *
+ * @param nodeUid
+ * @return
+ * @throws ZipFileUtilException
+ * @throws FileUtilException
+ * @throws IOException
+ * @throws RepositoryCheckedException
+ */
+ private String exportNode(Long nodeUid) throws ZipFileUtilException, FileUtilException, IOException,
+ RepositoryCheckedException {
+ if (nodeUid != null) {
+
+ String rootDir = FileUtil.createTempDirectory(PedagogicalPlannerAction.EXPORT_NODE_FOLDER_SUFFIX);
+ String contentDir = FileUtil.getFullPath(rootDir, PedagogicalPlannerAction.DIR_CONTENT);
+ FileUtil.createDirectory(contentDir);
+
+ String nodeFileName = FileUtil.getFullPath(contentDir, PedagogicalPlannerAction.NODE_FILE_NAME);
+ Writer nodeFile = new OutputStreamWriter(new FileOutputStream(nodeFileName),
+ PedagogicalPlannerAction.ENCODING_UTF_8);
+
+ PedagogicalPlannerSequenceNode node = getPedagogicalPlannerDAO().getByUid(nodeUid);
+ // exporting XML
+ XStream designXml = new XStream();
+ designXml.toXML(node, nodeFile);
+ nodeFile.close();
+
+ PedagogicalPlannerAction.log.debug("Node xml export success");
+
+ // Copy templates' ZIP files from repository
+ File templateDir = new File(contentDir, PedagogicalPlannerAction.DIR_TEMPLATES);
+ exportSubnodeTemplates(node, templateDir);
+
+ // create zip file for fckeditor unique content folder
+ String targetZipFileName = PedagogicalPlannerAction.EXPORT_NODE_CONTENT_ZIP_PREFIX
+ + node.getContentFolderId() + PedagogicalPlannerAction.FILE_EXTENSION_ZIP;
+ String secureDir = Configuration.get(ConfigurationKeys.LAMS_EAR_DIR) + File.separator
+ + FileUtil.LAMS_WWW_DIR + File.separator + FileUtil.LAMS_WWW_SECURE_DIR;
+ String nodeContentDir = FileUtil.getFullPath(secureDir, node.getContentFolderId());
+
+ if (!FileUtil.isEmptyDirectory(nodeContentDir, true)) {
+ PedagogicalPlannerAction.log.debug("Create export node content target zip file. File name is "
+ + targetZipFileName);
+ ZipFileUtil.createZipFile(targetZipFileName, nodeContentDir, contentDir);
+ } else {
+ PedagogicalPlannerAction.log.debug("No such directory (or empty directory): " + nodeContentDir);
+ }
+
+ // zip file name with full path
+ targetZipFileName = PedagogicalPlannerAction.EXPORT_NODE_ZIP_PREFIX + node.getTitle()
+ + PedagogicalPlannerAction.FILE_EXTENSION_ZIP;
+ ;
+ PedagogicalPlannerAction.log
+ .debug("Create export node content zip file. File name is " + targetZipFileName);
+ // create zip file and return zip full file name
+ return ZipFileUtil.createZipFile(targetZipFileName, contentDir, rootDir);
+ }
+ return null;
+ }
+
+ /**
+ * Imports a zipped node. Thi method is based on a similar one for importing learning designs.
+ *
+ * @param mapping
+ * @param form
+ * @param request
+ * @param response
+ * @return
+ * @throws ServletException
+ */
+ public ActionForward importNode(ActionMapping mapping, ActionForm form, HttpServletRequest request,
+ HttpServletResponse response) throws ServletException {
+
+ PedagogicalPlannerSequenceNodeForm nodeForm = (PedagogicalPlannerSequenceNodeForm) form;
+ ActionMessages errors = validateFormFile(nodeForm);
+
+ if (errors.isEmpty()) {
+ try {
+ String uploadPath = FileUtil.createTempDirectory(PedagogicalPlannerAction.DIR_UPLOADED_NODE_SUFFIX);
+ String fileName = nodeForm.getFile().getFileName();
+ File importFile = new File(uploadPath + fileName);
+ PedagogicalPlannerAction.log.debug("Importing a node from file: " + fileName);
+
+ // Copy the submitted file to the hard drive
+ InputStream inputStream = nodeForm.getFile().getInputStream();
+ copyFileFromRepository(inputStream, importFile);
+
+ nodeForm.setFile(null);
+
+ String rootPath = ZipFileUtil.expandZip(new FileInputStream(importFile), fileName);
+ String nodeFilePath = FileUtil.getFullPath(rootPath, PedagogicalPlannerAction.NODE_FILE_NAME);
+
+ PedagogicalPlannerSequenceNode node = (PedagogicalPlannerSequenceNode) FileUtil.getObjectFromXML(null,
+ nodeFilePath);
+
+ // begin fckeditor content folder import
+ String contentZipFileName = PedagogicalPlannerAction.EXPORT_NODE_CONTENT_ZIP_PREFIX
+ + node.getContentFolderId() + PedagogicalPlannerAction.FILE_EXTENSION_ZIP;
+ String secureDir = Configuration.get(ConfigurationKeys.LAMS_EAR_DIR) + File.separator
+ + FileUtil.LAMS_WWW_DIR + File.separator + FileUtil.LAMS_WWW_SECURE_DIR + File.separator
+ + node.getContentFolderId();
+ File contentZipFile = new File(FileUtil.getFullPath(rootPath, contentZipFileName));
+
+ // unzip file to target secure dir if exists
+ if (contentZipFile.exists()) {
+ InputStream is = new FileInputStream(contentZipFile);
+ ZipFileUtil.expandZipToFolder(is, secureDir);
+ }
+
+ // Upload the template files back into the repository
+ File templateDir = new File(rootPath, PedagogicalPlannerAction.DIR_TEMPLATES);
+ importSubnodeTemplates(node, templateDir);
+
+ // The imported node is added as the last one
+ Integer order = getPedagogicalPlannerDAO().getNextOrderId(null);
+ node.setOrder(order);
+ getPedagogicalPlannerDAO().saveOrUpdateNode(node);
+ } catch (Exception e) {
+ PedagogicalPlannerAction.log.error(e);
+ errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(PedagogicalPlannerAction.ERROR_KEY_IMPORT));
+ }
+ }
+ if (!errors.isEmpty()) {
+ saveErrors(request, errors);
+ }
+ return openSequenceNode(mapping, form, request, (Long) null);
+ }
+
+ /**
+ * Imports a learning design for edit/preview template purposes.
+ *
+ * @param fileUuid
+ * @param fileName
+ * @param errors
+ * @return
+ * @throws ServletException
+ */
+ private LearningDesign importLearningDesign(Long fileUuid, String fileName, ActionMessages errors)
+ throws ServletException {
+ File designFile = null;
+ try {
+ designFile = new File(FileUtil.TEMP_DIR, fileName);
+ InputStream inputStream = getContentHandler().getFileNode(fileUuid).getFile();
+ copyFileFromRepository(inputStream, designFile);
+ } catch (Exception e) {
+ PedagogicalPlannerAction.log.error(e);
+ errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(PedagogicalPlannerAction.ERROR_KEY_FILE_OPEN));
+ return null;
+ }
+ if (!designFile.exists() || designFile.isDirectory()) {
+ PedagogicalPlannerAction.log.error(PedagogicalPlannerAction.ERROR_NOT_PROPER_FILE);
+ errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(PedagogicalPlannerAction.ERROR_KEY_FILE_OPEN));
+ return null;
+ }
+
+ HttpSession session = SessionManager.getSession();
+ UserDTO userDto = (UserDTO) session.getAttribute(AttributeNames.USER);
+ User user = (User) getUserManagementService().findById(User.class, userDto.getUserID());
+ if (user == null) {
+ throw new ServletException(PedagogicalPlannerAction.ERROR_USER_NOT_FOUND);
+ }
+ List toolsErrorMsgs = new ArrayList();
+ Long learningDesignID = null;
+ LearningDesign learningDesign = null;
+ List learningDesignErrorMsgs = new ArrayList();
+ // Extract the template
+
+ try {
+ Object[] ldResults = getExportService().importLearningDesign(designFile, user, null, toolsErrorMsgs, "");
+ designFile.delete();
+ learningDesignID = (Long) ldResults[0];
+ learningDesignErrorMsgs = (List) ldResults[1];
+ toolsErrorMsgs = (List) ldResults[2];
+ learningDesign = getAuthoringService().getLearningDesign(learningDesignID);
+ } catch (ImportToolContentException e) {
+ PedagogicalPlannerAction.log.error(e);
+ errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
+ PedagogicalPlannerAction.ERROR_KEY_LEARNING_DESIGN_COULD_NOT_BE_RETRIEVED));
+
+ }
+
+ if ((learningDesignID == null || learningDesignID.longValue() == -1) && learningDesignErrorMsgs.size() == 0) {
+ errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
+ PedagogicalPlannerAction.ERROR_KEY_LEARNING_DESIGN_COULD_NOT_BE_RETRIEVED));
+ return null;
+ }
+ if (learningDesignErrorMsgs.size() > 0) {
+ for (String error : learningDesignErrorMsgs) {
+ PedagogicalPlannerAction.log.error(error);
+ }
+ errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
+ PedagogicalPlannerAction.ERROR_KEY_LEARNING_DESIGN_COULD_NOT_BE_RETRIEVED));
+ return null;
+ }
+ if (toolsErrorMsgs.size() > 0) {
+ for (String error : toolsErrorMsgs) {
+ PedagogicalPlannerAction.log.error(error);
+ }
+ errors
+ .add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
+ PedagogicalPlannerAction.ERROR_KEY_TOOL_ERRORS));
+ return null;
+ }
+ return learningDesign;
+ }
+
+ /**
+ * Copies the template files from repository into the selected dir.
+ *
+ * @param node
+ * @param outputDir
+ * @throws RepositoryCheckedException
+ * @throws IOException
+ */
+ private void exportSubnodeTemplates(PedagogicalPlannerSequenceNode node, File outputDir)
+ throws RepositoryCheckedException, IOException {
+ if (node != null) {
+ if (node.getFileUuid() == null) {
+ if (node.getSubnodes() != null) {
+ for (PedagogicalPlannerSequenceNode subnode : node.getSubnodes()) {
+ exportSubnodeTemplates(subnode, outputDir);
+ }
+ }
+ } else {
+ File uuidDir = new File(outputDir, node.getFileUuid().toString());
+ uuidDir.mkdirs();
+ File targetFile = new File(uuidDir, node.getFileName());
+ InputStream inputStream = getContentHandler().getFileNode(node.getFileUuid()).getFile();
+ PedagogicalPlannerAction.log.debug("Preparing for zipping the template file: " + node.getFileName());
+ copyFileFromRepository(inputStream, targetFile);
+ }
+ }
+ }
+
+ /**
+ * Uploads the templates back into repository. Also sets all the nodes' UIDs to NULL.
+ *
+ * @param node
+ * @param inputDir
+ * @throws RepositoryCheckedException
+ * @throws IOException
+ */
+ private void importSubnodeTemplates(PedagogicalPlannerSequenceNode node, File inputDir)
+ throws RepositoryCheckedException, IOException {
+ if (node != null) {
+ node.setUid(null);
+
+ if (node.getFileUuid() == null) {
+ if (node.getSubnodes() != null) {
+ for (PedagogicalPlannerSequenceNode subnode : node.getSubnodes()) {
+ importSubnodeTemplates(subnode, inputDir);
+ }
+ }
+ } else {
+ File uuidDir = new File(inputDir, node.getFileUuid().toString());
+ File file = new File(uuidDir, node.getFileName());
+ InputStream inputStream = new FileInputStream(file);
+ String fileName = node.getFileName();
+ PedagogicalPlannerAction.log.debug("Uploading into repository a template file: " + fileName);
+ NodeKey nodeKey = getContentHandler().uploadFile(inputStream, fileName,
+ PedagogicalPlannerAction.RESPONSE_CONTENT_TYPE_DOWNLOAD, IToolContentHandler.TYPE_OFFLINE);
+ node.setFileUuid(nodeKey.getUuid());
+ }
+ }
+ }
+
+ /**
+ * Copies a file using the provided input stream.
+ *
+ * @param inputStream
+ * @param targetFile
+ * @throws RepositoryCheckedException
+ * @throws IOException
+ */
+ private void copyFileFromRepository(InputStream inputStream, File targetFile) throws RepositoryCheckedException,
+ IOException {
+
+ FileOutputStream fileOutputStream = new FileOutputStream(targetFile);
+ byte[] data = new byte[PedagogicalPlannerAction.FILE_COPY_BUFFER_SIZE];
int read = 0;
do {
read = inputStream.read(data);
@@ -781,9 +1159,104 @@
} while (read > 0);
fileOutputStream.close();
inputStream.close();
- return file;
}
+ /*----------------------- GROUPING METHODS -------------------------*/
+
+ /**
+ * Fill the grouping with initial data
+ */
+ public ActionForward initGrouping(ActionMapping mapping, ActionForm form, HttpServletRequest request,
+ HttpServletResponse response) {
+ PedagogicalPlannerGroupingForm plannerForm = (PedagogicalPlannerGroupingForm) form;
+ Long groupingId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID);
+ Grouping grouping = getAuthoringService().getGroupingById(groupingId);
+ plannerForm.fillForm(grouping);
+ return mapping.findForward(CentralConstants.FORWARD_GROUPING);
+ }
+
+ /**
+ * Saves parameters of the grouping form, depending on the grouping type.
+ *
+ * @param mapping
+ * @param form
+ * @param request
+ * @param response
+ * @return
+ */
+ public ActionForward saveOrUpdateGroupingForm(ActionMapping mapping, ActionForm form, HttpServletRequest request,
+ HttpServletResponse response) {
+ PedagogicalPlannerAction.log.debug("Saving grouping activity");
+ PedagogicalPlannerGroupingForm plannerForm = (PedagogicalPlannerGroupingForm) form;
+ ActionMessages errors = plannerForm.validate();
+ if (errors.isEmpty()) {
+ Grouping grouping = getAuthoringService().getGroupingById(plannerForm.getToolContentID());
+ if (grouping.isRandomGrouping()) {
+ RandomGrouping randomGrouping = (RandomGrouping) grouping;
+ Integer number = StringUtils.isEmpty(plannerForm.getNumberOfGroups()) ? null : Integer
+ .parseInt(plannerForm.getNumberOfGroups());
+ randomGrouping.setNumberOfGroups(number);
+
+ number = StringUtils.isEmpty(plannerForm.getLearnersPerGroup()) ? null : Integer.parseInt(plannerForm
+ .getLearnersPerGroup());
+ randomGrouping.setLearnersPerGroup(number);
+ } else if (grouping.isLearnerChoiceGrouping()) {
+ LearnerChoiceGrouping learnerChoiceGrouping = (LearnerChoiceGrouping) grouping;
+ Integer number = StringUtils.isEmpty(plannerForm.getNumberOfGroups()) ? null : Integer
+ .parseInt(plannerForm.getNumberOfGroups());
+ learnerChoiceGrouping.setNumberOfGroups(number);
+
+ number = StringUtils.isEmpty(plannerForm.getLearnersPerGroup()) ? null : Integer.parseInt(plannerForm
+ .getLearnersPerGroup());
+ learnerChoiceGrouping.setLearnersPerGroup(number);
+ learnerChoiceGrouping.setEqualNumberOfLearnersPerGroup(plannerForm.getEqualGroupSizes());
+ learnerChoiceGrouping.setViewStudentsBeforeSelection(plannerForm.getViewStudentsBeforeSelection());
+ } else {
+ Integer number = StringUtils.isEmpty(plannerForm.getNumberOfGroups()) ? null : Integer
+ .parseInt(plannerForm.getNumberOfGroups());
+ grouping.setMaxNumberOfGroups(number);
+ }
+ } else {
+ saveMessages(request, errors);
+ }
+ return mapping.findForward(CentralConstants.FORWARD_GROUPING);
+ }
+
+ /*-------------------------- TEMPLATE BASE METHODS -----------------*/
+
+ /**
+ * Saves additional, non tool-bound template details - currently only the title.
+ *
+ * @param mapping
+ * @param form
+ * @param request
+ * @param response
+ * @return
+ * @throws IOException
+ */
+ public ActionForward saveSequenceDetails(ActionMapping mapping, ActionForm form, HttpServletRequest request,
+ HttpServletResponse response) throws IOException {
+ PedagogicalPlannerAction.log.debug("Saving sequence title");
+ String sequenceTitle = WebUtil.readStrParam(request, CentralConstants.PARAM_SEQUENCE_TITLE, true);
+ Long learningDesignID = WebUtil.readLongParam(request, CentralConstants.PARAM_LEARNING_DESIGN_ID);
+ Integer callAttemptedID = WebUtil.readIntParam(request, CentralConstants.PARAM_CALL_ATTEMPTED_ID);
+ // We send a message in format "&"; it is then parsed in JavaScript
+ String responseSuffix = PedagogicalPlannerAction.CHAR_AMPERSAND + callAttemptedID;
+
+ if (StringUtils.isEmpty(sequenceTitle)) {
+ String blankTitleError = getMessageService().getMessage(CentralConstants.ERROR_PLANNER_TITLE_BLANK);
+ writeAJAXResponse(response, blankTitleError + responseSuffix);
+ } else {
+ LearningDesign learningDesign = getAuthoringService().getLearningDesign(learningDesignID);
+ learningDesign.setTitle(sequenceTitle);
+ getAuthoringService().saveLearningDesign(learningDesign);
+ writeAJAXResponse(response, PedagogicalPlannerAction.STRING_OK + responseSuffix);
+ }
+ return null;
+ }
+
+ /*------------------------ SERVICE ACCESS METHODS --------------------*/
+
private IExportToolContentService getExportService() {
if (PedagogicalPlannerAction.exportService == null) {
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServlet()
Index: lams_central/src/java/org/lamsfoundation/lams/web/planner/PedagogicalPlannerGroupingForm.java
===================================================================
diff -u -r00a6e145b37916eb1561ea5c68319b0fc691681b -r9a772f5ba1954a3a719a19e7ae237b6b09dc76ef
--- lams_central/src/java/org/lamsfoundation/lams/web/planner/PedagogicalPlannerGroupingForm.java (.../PedagogicalPlannerGroupingForm.java) (revision 00a6e145b37916eb1561ea5c68319b0fc691681b)
+++ lams_central/src/java/org/lamsfoundation/lams/web/planner/PedagogicalPlannerGroupingForm.java (.../PedagogicalPlannerGroupingForm.java) (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -41,6 +41,7 @@
private String numberOfGroups;
private String learnersPerGroup;
private Boolean equalGroupSizes;
+ private Boolean viewStudentsBeforeSelection;
public Integer getGroupingTypeId() {
return groupingTypeId;
@@ -87,6 +88,7 @@
setLearnersPerGroup(number);
setEqualGroupSizes(learnerChoiceGrouping.getEqualNumberOfLearnersPerGroup());
+ setViewStudentsBeforeSelection(learnerChoiceGrouping.getViewStudentsBeforeSelection());
} else {
String numberOfGroups = grouping.getMaxNumberOfGroups() == null ? null : String.valueOf(grouping
.getMaxNumberOfGroups());
@@ -136,4 +138,12 @@
public void setEqualGroupSizes(Boolean equalGroupsSizes) {
equalGroupSizes = equalGroupsSizes;
}
+
+ public Boolean getViewStudentsBeforeSelection() {
+ return viewStudentsBeforeSelection;
+ }
+
+ public void setViewStudentsBeforeSelection(Boolean viewStudentsBeforeSelection) {
+ this.viewStudentsBeforeSelection = viewStudentsBeforeSelection;
+ }
}
\ No newline at end of file
Index: lams_central/src/java/org/lamsfoundation/lams/web/planner/PedagogicalPlannerSequenceNodeForm.java
===================================================================
diff -u -rc697b5c30ab742ab453859355b35cd518856334f -r9a772f5ba1954a3a719a19e7ae237b6b09dc76ef
--- lams_central/src/java/org/lamsfoundation/lams/web/planner/PedagogicalPlannerSequenceNodeForm.java (.../PedagogicalPlannerSequenceNodeForm.java) (revision c697b5c30ab742ab453859355b35cd518856334f)
+++ lams_central/src/java/org/lamsfoundation/lams/web/planner/PedagogicalPlannerSequenceNodeForm.java (.../PedagogicalPlannerSequenceNodeForm.java) (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -27,6 +27,9 @@
import org.apache.struts.upload.FormFile;
public class PedagogicalPlannerSequenceNodeForm extends ActionForm {
+ public final static String NODE_TYPE_SUBNODES = "subnodes";
+ public final static String NODE_TYPE_TEMPLATE = "template";
+
private Long uid;
private Long parentUid;
private String contentFolderId;
@@ -35,12 +38,9 @@
private String fullDescription;
private FormFile file;
private Boolean removeFile;
- private String nodeType;
+ private String nodeType = PedagogicalPlannerSequenceNodeForm.NODE_TYPE_SUBNODES;
private Long fileUuid;
- public final static String NODE_TYPE_SUBNODES = "subnodes";
- public final static String NODE_TYPE_TEMPLATE = "template";
-
public Long getUid() {
return uid;
}
Index: lams_central/web/WEB-INF/fckeditor/tlds/FCKeditor.tld
===================================================================
diff -u
--- lams_central/web/WEB-INF/fckeditor/tlds/FCKeditor.tld (revision 0)
+++ lams_central/web/WEB-INF/fckeditor/tlds/FCKeditor.tld (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -0,0 +1,129 @@
+
+
+
+ The FCKeditor Tag Library offers a very convenient way to create
+ several FCKeditor instances with different configurations.
+ Additionally, you can check for user-based capabilities.
+
+ FCKeditor Tag Library
+ 2.4
+ FCK
+ http://java.fckeditor.net
+
+
+ Creates a FCKeditor instance with the given parameters. Any
+ parameter except instanceName which is empty or contains
+ whitespaces only will be ignored.
+
+ editor
+ editor
+ net.fckeditor.tags.EditorTag
+ JSP
+
+
+ The unique instance name under which the editor can be
+ retrieved through the API.
+
+ instanceName
+ true
+ true
+ java.lang.String
+
+
+
+ Width of the FCKeditor instance in the browser window.
+
+ width
+ true
+ java.lang.String
+
+
+
+ Height of the FCKeditor instance in the browser window.
+
+ height
+ true
+ java.lang.String
+
+
+
+ The toolbar set which shall be displayed to the user.
+
+ toolbarSet
+ true
+ java.lang.String
+
+
+
+ The path/folder in which the editor is deployed under
+ the given context. The context path will be attached
+ automatically. (e.g. '/fckeditor')
+
+ basePath
+ true
+ java.lang.String
+
+
+
+ Passes any content to the FCKeditor document. Use the
+ jsp:attribute tag for large inline content. \r, \n, and
+ \t will be truncated.
+
+ value
+ true
+ java.lang.String
+
+ ]]>
+
+
+
+
+ Sets a config property of the editor to the supplied value.
+ You may provide any attribute you want for the editor. Set
+ at least one attribute per tag or several attributes with
+ one tag. This tag can only be nested within an editor tag.
+ For all configuration options click
+ here]]>.
+
+ config
+ config
+ net.fckeditor.tags.ConfigTag
+ empty
+ true
+
+ ]]>
+
+
+
+
+ Displays session-dependent and compatibility-related
+ information. This tag is intended for developers only.
+ Response messages cannot be localized, they are English
+ only.
+
+ check
+ check
+ net.fckeditor.tags.CheckTag
+ empty
+
+
+ Provide the feature name you want to check. Valid
+ features are [FileUpload, FileBrowsing,
+ CompatibleBrowser]
+
+ command
+ true
+ java.lang.String
+
+
+]]>
+
+
+
\ No newline at end of file
Fisheye: Tag 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef refers to a dead (removed) revision in file `lams_central/web/WEB-INF/jstl/tlds/FCKeditor.tld'.
Fisheye: No comparison available. Pass `N' to diff?
Index: lams_central/web/WEB-INF/web.xml
===================================================================
diff -u -rbdd916337e3a48589da367f4c8b7705fe3197af2 -r9a772f5ba1954a3a719a19e7ae237b6b09dc76ef
--- lams_central/web/WEB-INF/web.xml (.../web.xml) (revision bdd916337e3a48589da367f4c8b7705fe3197af2)
+++ lams_central/web/WEB-INF/web.xml (.../web.xml) (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -294,6 +294,11 @@
+ GetRecordingServlet
+ org.lamsfoundation.lams.webservice.GetRecordingServlet
+
+
+
copyMultipleToolContent
org.lamsfoundation.lams.authoring.web.CopyMultipleToolContentServlet
@@ -493,6 +498,10 @@
/servlet/notebook/storeNotebookEntry
+ GetRecordingServlet
+ /GetRecording
+
+
copyMultipleToolContent
/servlet/authoring/copyMultipleToolContent
Index: lams_central/web/includes/javascript/pedagogicalPlanner.js
===================================================================
diff -u -rc697b5c30ab742ab453859355b35cd518856334f -r9a772f5ba1954a3a719a19e7ae237b6b09dc76ef
--- lams_central/web/includes/javascript/pedagogicalPlanner.js (.../pedagogicalPlanner.js) (revision c697b5c30ab742ab453859355b35cd518856334f)
+++ lams_central/web/includes/javascript/pedagogicalPlanner.js (.../pedagogicalPlanner.js) (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -138,7 +138,7 @@
if (sequenceDetailsValid && activitiesValid==activitiesResponded){
$('#pedagogicalPlannerInfoArea').show();
if (actionAfterCompleted==ACTION_PREVIEW){
- window.open(startPreviewUrl,'Preview','width=800,height=600,scrollbars=yes,resizable=yes');
+ startPreview(startPreviewUrl);
}
else if (actionAfterCompleted==ACTION_OPEN_AUTHOR){
window.resizeTo(authoring_width,authoring_height);
@@ -154,6 +154,10 @@
}
}
+ function startPreview(url){
+ window.open(url,'Preview','width=800,height=600,scrollbars=yes,resizable=yes');
+ }
+
function closePlanner(text){
if (text==null || confirm(text)){
window.close();
@@ -179,4 +183,6 @@
document.getElementById("fullDescriptionArea").style.display="none";
document.getElementById("fileArea").style.display="block";
}
+
+
}
\ No newline at end of file
Index: lams_central/web/pedagogical_planner/grouping.jsp
===================================================================
diff -u -r5a30100855d83534e76db8dec0d0b603a1a1ded8 -r9a772f5ba1954a3a719a19e7ae237b6b09dc76ef
--- lams_central/web/pedagogical_planner/grouping.jsp (.../grouping.jsp) (revision 5a30100855d83534e76db8dec0d0b603a1a1ded8)
+++ lams_central/web/pedagogical_planner/grouping.jsp (.../grouping.jsp) (revision 9a772f5ba1954a3a719a19e7ae237b6b09dc76ef)
@@ -14,6 +14,10 @@