Index: lams_central/src/java/org/lamsfoundation/lams/web/controller/SearchQBController.java =================================================================== diff -u --- lams_central/src/java/org/lamsfoundation/lams/web/controller/SearchQBController.java (revision 0) +++ lams_central/src/java/org/lamsfoundation/lams/web/controller/SearchQBController.java (revision a109b7b66649bbed86abf584a192c6af194946ef) @@ -0,0 +1,221 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.web.controller; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.math.NumberUtils; +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.learningdesign.ToolActivity; +import org.lamsfoundation.lams.lesson.Lesson; +import org.lamsfoundation.lams.qb.model.QbOption; +import org.lamsfoundation.lams.qb.model.QbQuestion; +import org.lamsfoundation.lams.qb.service.IQbService; +import org.lamsfoundation.lams.questions.Answer; +import org.lamsfoundation.lams.questions.Question; +import org.lamsfoundation.lams.questions.QuestionExporter; +import org.lamsfoundation.lams.questions.QuestionParser; +import org.lamsfoundation.lams.tool.Tool; +import org.lamsfoundation.lams.tool.ToolAccessMode; +import org.lamsfoundation.lams.tool.ToolAdapterContentManager; +import org.lamsfoundation.lams.tool.ToolContent; +import org.lamsfoundation.lams.tool.ToolContentManager; +import org.lamsfoundation.lams.tool.exception.DataMissingException; +import org.lamsfoundation.lams.tool.exception.ToolException; +import org.lamsfoundation.lams.tool.service.LamsCoreToolService; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.CentralConstants; +import org.lamsfoundation.lams.util.CommonConstants; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.lamsfoundation.lams.web.util.SessionMap; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Controller; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.util.HtmlUtils; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * @author Andrey Balan + */ +@Controller +@RequestMapping("/searchQB") +public class SearchQBController { + + private static Logger log = Logger.getLogger(SearchQBController.class); + + public static final String PARAM_SEARCH = "_search"; + public static final String PARAM_SEARCH_FIELD = "searchField"; + public static final String PARAM_SEARCH_OPERATION = "searchOper"; + public static final String PARAM_SEARCH_STRING = "searchString"; + + @Autowired + private IQbService qbService; + + @Autowired + private IUserManagementService userManagementService; + + @RequestMapping("/start") + private String start(HttpServletRequest request) { + ToolAccessMode mode = WebUtil.readToolAccessModeAuthorDefaulted(request); + request.setAttribute(AttributeNames.ATTR_MODE, mode.toString()); + + Long toolContentId = WebUtil.readLongParam(request, "toolContentId"); + ToolContent toolContent = (ToolContent) userManagementService.findById(ToolContent.class, toolContentId); + if (toolContent == null) { + String error = "The toolContentID " + toolContentId + + " is not valid. No such record exists on the database."; + throw new DataMissingException(error); + } + Tool tool = toolContent.getTool(); + String toolSignature = tool.getToolSignature(); + + int questionType; + boolean questionTypeHidden; + if (CommonConstants.TOOL_SIGNATURE_SCRATCHIE.equals(toolSignature) || CommonConstants.TOOL_SIGNATURE_MCQ.equals(toolSignature)) { + questionType = QbQuestion.TYPE_MULTIPLE_CHOICE_SINGLE_ANSWER; + questionTypeHidden = true; + + } else { + questionType = 2; + questionTypeHidden = false; + } + request.setAttribute("questionType", questionType); + request.setAttribute("questionTypeHidden", questionTypeHidden); + + return "qb/search"; + } + + /** + * Returns an xml representation of the lesson grid for a course for gradebook + * + * This has two modes, learnerView and monitorView + * + * Learner view will get the data specific to one user + * + * Monitor will get the data average for whole lessons. + */ + @RequestMapping("/getPagedQuestions") + @ResponseBody + private String getPagedQuestions(HttpServletRequest request, HttpServletResponse response) { + + Integer questionType = WebUtil.readIntParam(request, "questionType"); +// boolean isPrivate = WebUtil.readBooleanParam(request, "isPrivate"); + + // Getting the params passed in from the jqGrid + int page = WebUtil.readIntParam(request, CommonConstants.PARAM_PAGE); + int rowLimit = WebUtil.readIntParam(request, CommonConstants.PARAM_ROWS); + String sortOrder = WebUtil.readStrParam(request, CommonConstants.PARAM_SORD); + String sortBy = WebUtil.readStrParam(request, CommonConstants.PARAM_SIDX, true); + if (StringUtils.isEmpty(sortBy)) { + sortBy = "userName"; + } + String searchString = WebUtil.readStrParam(request, "searchString", true); + + // Get the user list from the db + List questions = qbService.getPagedQbQuestions(questionType, page - 1, rowLimit, sortBy, sortOrder, + searchString); + int countQuestions = qbService.getCountQbQuestions(questionType, searchString); + int totalPages = Double.valueOf(Math.ceil(Double.valueOf(countQuestions) / Double.valueOf(rowLimit))) + .intValue(); + + ArrayNode rows = JsonNodeFactory.instance.arrayNode(); + int i = 1; + for (QbQuestion question : questions) { + + ArrayNode questionData = JsonNodeFactory.instance.arrayNode(); + questionData.add(question.getUid()); + questionData.add(HtmlUtils.htmlEscape(question.getName())); + String description = question.getDescription() == null ? "" : question.getDescription().replaceAll("\\<.*?\\>", ""); + questionData.add(HtmlUtils.htmlEscape(description)); + + ObjectNode userRow = JsonNodeFactory.instance.objectNode(); + userRow.put("id", i++); + userRow.set("cell", questionData); + + rows.add(userRow); + } + + ObjectNode responseJSON = JsonNodeFactory.instance.objectNode(); + responseJSON.put("total", totalPages); + responseJSON.put("page", page); + responseJSON.put("records", countQuestions); + responseJSON.set("rows", rows); + + response.setContentType("application/json;charset=utf-8"); + return responseJSON.toString(); + } + + @RequestMapping("/displayQuestionDetails") + private String displayQuestionDetails(HttpServletRequest request) { + Long questionUid = WebUtil.readLongParam(request, "questionUid"); + QbQuestion qbQuestion = (QbQuestion) userManagementService.findById(QbQuestion.class, questionUid); + request.setAttribute("question", qbQuestion); + + return "qb/qbQuestionDetails"; + } + + @RequestMapping("/addQuestion") + private String addQuestion(HttpServletRequest request) { + Long questionUid = WebUtil.readLongParam(request, "questionUid"); + Long toolContentId = WebUtil.readLongParam(request, "toolContentId"); + + return "qb/"; + } +} \ No newline at end of file Index: lams_central/web/includes/javascript/jquery.highlight.js =================================================================== diff -u --- lams_central/web/includes/javascript/jquery.highlight.js (revision 0) +++ lams_central/web/includes/javascript/jquery.highlight.js (revision a109b7b66649bbed86abf584a192c6af194946ef) @@ -0,0 +1,107 @@ +/* + * jQuery Highlight plugin + * + * Based on highlight v3 by Johann Burkard + * http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html + * + * Code a little bit refactored and cleaned (in my humble opinion). + * Most important changes: + * - has an option to highlight only entire words (wordsOnly - false by default), + * - has an option to be case sensitive (caseSensitive - false by default) + * - highlight element tag and class names can be specified in options + * + * Usage: + * // wrap every occurrance of text 'lorem' in content + * // with (default options) + * $('#content').highlight('lorem'); + * + * // search for and highlight more terms at once + * // so you can save some time on traversing DOM + * $('#content').highlight(['lorem', 'ipsum']); + * $('#content').highlight('lorem ipsum'); + * + * // search only for entire word 'lorem' + * $('#content').highlight('lorem', { wordsOnly: true }); + * + * // don't ignore case during search of term 'lorem' + * $('#content').highlight('lorem', { caseSensitive: true }); + * + * // wrap every occurrance of term 'ipsum' in content + * // with + * $('#content').highlight('ipsum', { element: 'em', className: 'important' }); + * + * // remove default highlight + * $('#content').unhighlight(); + * + * // remove custom highlight + * $('#content').unhighlight({ element: 'em', className: 'important' }); + * + * + * Copyright (c) 2009 Bartek Szopka + * + * Licensed under MIT license. + * + */ + +jQuery.extend({ + highlight: function (node, re, nodeName, className) { + if (node.nodeType === 3) { + var match = node.data.match(re); + if (match) { + var highlight = document.createElement(nodeName || 'span'); + highlight.className = className || 'highlight'; + var wordNode = node.splitText(match.index); + wordNode.splitText(match[0].length); + var wordClone = wordNode.cloneNode(true); + highlight.appendChild(wordClone); + wordNode.parentNode.replaceChild(highlight, wordNode); + return 1; //skip added node in parent + } + } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children + !/(script|style)/i.test(node.tagName) && // ignore script and style nodes + !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted + for (var i = 0; i < node.childNodes.length; i++) { + i += jQuery.highlight(node.childNodes[i], re, nodeName, className); + } + } + return 0; + } +}); + +jQuery.fn.unhighlight = function (options) { + var settings = { className: 'highlight', element: 'span' }; + jQuery.extend(settings, options); + + return this.find(settings.element + "." + settings.className).each(function () { + var parent = this.parentNode; + parent.replaceChild(this.firstChild, this); + parent.normalize(); + }).end(); +}; + +jQuery.fn.highlight = function (words, options) { + var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false }; + jQuery.extend(settings, options); + + if (words.constructor === String) { + words = [words]; + } + words = jQuery.grep(words, function(word, i){ + return word != ''; + }); + words = jQuery.map(words, function(word, i) { + return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + }); + if (words.length == 0) { return this; }; + + var flag = settings.caseSensitive ? "" : "i"; + var pattern = "(" + words.join("|") + ")"; + if (settings.wordsOnly) { + pattern = "\\b" + pattern + "\\b"; + } + var re = new RegExp(pattern, flag); + + return this.each(function () { + jQuery.highlight(this, re, settings.element, settings.className); + }); +}; \ No newline at end of file Index: lams_central/web/qb/qbQuestionDetails.jsp =================================================================== diff -u --- lams_central/web/qb/qbQuestionDetails.jsp (revision 0) +++ lams_central/web/qb/qbQuestionDetails.jsp (revision a109b7b66649bbed86abf584a192c6af194946ef) @@ -0,0 +1,75 @@ + +<%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=utf-8" %> +<%@ taglib uri="tags-lams" prefix="lams" %> +<%@ taglib uri="tags-fmt" prefix="fmt" %> +<%@ taglib uri="tags-core" prefix="c" %> +<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> + +
+
+ +
+ Version: ${question.version} +
+ +
+ +
+ +
+ +
+ + + + + + + + + + + + + + +
+ + + + + class="text-success"> + ${i.index+1}) + + + +
+ + + +
+
+
+ +
+ + +
+ + + + + +
+ + + +
+ "> + + + +
Index: lams_central/web/qb/search.jsp =================================================================== diff -u --- lams_central/web/qb/search.jsp (revision 0) +++ lams_central/web/qb/search.jsp (revision a109b7b66649bbed86abf584a192c6af194946ef) @@ -0,0 +1,288 @@ + +<%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=utf-8"%> +<%@ taglib uri="tags-lams" prefix="lams"%> +<%@ taglib uri="tags-fmt" prefix="fmt"%> +<%@ taglib uri="tags-core" prefix="c"%> + + + + Question Bank Search + + + + + + + + + + + + + +
+
+ Search question bank + + +
+ +
+ +
+ + + Type: Multiple choice +
+ + + +
+
+
+
+
+ +
+
+ + + + +
+ +
+ +
Index: lams_common/src/java/org/lamsfoundation/lams/qb/dao/IQbDAO.java =================================================================== diff -u -r2e9ee1c2451a05981f05e9edf89bb3356cf2b147 -ra109b7b66649bbed86abf584a192c6af194946ef --- lams_common/src/java/org/lamsfoundation/lams/qb/dao/IQbDAO.java (.../IQbDAO.java) (revision 2e9ee1c2451a05981f05e9edf89bb3356cf2b147) +++ lams_common/src/java/org/lamsfoundation/lams/qb/dao/IQbDAO.java (.../IQbDAO.java) (revision a109b7b66649bbed86abf584a192c6af194946ef) @@ -1,11 +1,26 @@ package org.lamsfoundation.lams.qb.dao; +import java.util.List; + import org.lamsfoundation.lams.dao.IBaseDAO; +import org.lamsfoundation.lams.qb.model.QbQuestion; public interface IQbDAO extends IBaseDAO { + + /** + * @param qbQuestionUid + * @return QbQuestion object with the specified uid + */ + QbQuestion getQbQuestionByUid(Long qbQuestionUid); + // finds next question ID for Question Bank question int getMaxQuestionId(); // finds next version for given question ID for Question Bank question int getMaxQuestionVersion(Integer qbQuestionId); + + List getPagedQbQuestions(Integer questionType, int page, int size, String sortBy, + String sortOrder, String searchString); + + int getCountQbQuestions(Integer questionType, String searchString); } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/qb/dao/hibernate/QbDAO.java =================================================================== diff -u -r2e9ee1c2451a05981f05e9edf89bb3356cf2b147 -ra109b7b66649bbed86abf584a192c6af194946ef --- lams_common/src/java/org/lamsfoundation/lams/qb/dao/hibernate/QbDAO.java (.../QbDAO.java) (revision 2e9ee1c2451a05981f05e9edf89bb3356cf2b147) +++ lams_common/src/java/org/lamsfoundation/lams/qb/dao/hibernate/QbDAO.java (.../QbDAO.java) (revision a109b7b66649bbed86abf584a192c6af194946ef) @@ -1,12 +1,22 @@ package org.lamsfoundation.lams.qb.dao.hibernate; +import java.util.List; + +import org.hibernate.query.NativeQuery; +import org.hibernate.query.Query; import org.lamsfoundation.lams.dao.hibernate.LAMSBaseDAO; import org.lamsfoundation.lams.qb.dao.IQbDAO; +import org.lamsfoundation.lams.qb.model.QbQuestion; public class QbDAO extends LAMSBaseDAO implements IQbDAO { private static final String FIND_MAX_QUESTION_ID = "SELECT MAX(questionId) FROM QbQuestion"; private static final String FIND_MAX_VERSION = "SELECT MAX(version) FROM QbQuestion AS q WHERE q.questionId = :questionId"; + + @Override + public QbQuestion getQbQuestionByUid(Long qbQuestionUid) { + return (QbQuestion) this.find(QbQuestion.class, qbQuestionUid); + } @Override public int getMaxQuestionId() { @@ -22,4 +32,81 @@ Integer max = (Integer) result; return max == null ? 1 : max + 1; } + + @Override + public List getPagedQbQuestions(Integer questionType, int page, int size, String sortBy, + String sortOrder, String searchString) { + final String SELECT_QUESTIONS = "SELECT DISTINCT question.* " + + " FROM lams_qb_question question " + + " LEFT OUTER JOIN lams_qb_option qboption ON qboption.qb_question_uid = question.uid " + + " WHERE question.type = :questionType " + + " AND question.local = 0 " + + " AND (question.description LIKE CONCAT('%', :searchString, '%')" + + " OR question.name LIKE CONCAT('%', :searchString, '%') " + + " OR qboption.name LIKE CONCAT('%', :searchString, '%')) "; + final String ORDER_BY_NAME = "ORDER BY question.name "; + final String ORDER_BY_SMTH_ELSE = "ORDER BY question.question_id "; + + StringBuilder bldr = new StringBuilder(SELECT_QUESTIONS); + if ("smth_else".equalsIgnoreCase(sortBy)) { + bldr.append(ORDER_BY_SMTH_ELSE); + } else { + bldr.append(ORDER_BY_NAME); + } + bldr.append(sortOrder); + + NativeQuery query = getSession().createNativeQuery(bldr.toString()); + query.setParameter("questionType", questionType); + // support for custom search from a toolbar + searchString = searchString == null ? "" : searchString; + query.setParameter("searchString", searchString); + query.setFirstResult(page * size); + query.setMaxResults(size); + query.addEntity(QbQuestion.class); + List queryResults = (List) query.list(); + +// ArrayList userDtos = new ArrayList(); +// if (queryResults != null && queryResults.size() > 0) { +// for (Object[] element : queryResults) { +// +// Long userId = ((Number) element[0]).longValue(); +// String firstName = (String) element[1]; +// String lastName = (String) element[2]; +// String login = (String) element[3]; +// float grade = element[4] == null ? 0 : ((Number) element[4]).floatValue(); +// Long portraitId = element[5] == null ? null : ((Number) element[5]).longValue(); +// +// QbQuestion userDto = new QbQuestion(); +// userDto.setUserId(userId); +// userDto.setFirstName(firstName); +// userDto.setLastName(lastName); +// userDto.setLogin(login); +// userDto.setGrade(grade); +// userDto.setPortraitId(portraitId); +// userDtos.add(userDto); +// } +// +// } + + return queryResults; + } + + @Override + public int getCountQbQuestions(Integer questionType, String searchString) { + final String SELECT_QUESTIONS = "SELECT COUNT(*) " + + " FROM lams_qb_question question " + + " LEFT OUTER JOIN lams_qb_option qboption ON qboption.qb_question_uid = question.uid " + + " AND question.type = :questionType " + + " AND (question.description LIKE CONCAT('%', :searchString, '%')" + + " OR question.name LIKE CONCAT('%', :searchString, '%') " + + " OR qboption.name LIKE CONCAT('%', :searchString, '%')) "; + + Query query = getSession().createNativeQuery(SELECT_QUESTIONS); + query.setParameter("questionType", questionType); + // support for custom search from a toolbar + searchString = searchString == null ? "" : searchString; + query.setParameter("searchString", searchString); + int result = ((Number) query.uniqueResult()).intValue(); + return result; + } } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java =================================================================== diff -u -rf24a82ae2ef1cbaa92dfd356226f6c3edcd5e404 -ra109b7b66649bbed86abf584a192c6af194946ef --- lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java (.../IQbService.java) (revision f24a82ae2ef1cbaa92dfd356226f6c3edcd5e404) +++ lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java (.../IQbService.java) (revision a109b7b66649bbed86abf584a192c6af194946ef) @@ -1,5 +1,9 @@ package org.lamsfoundation.lams.qb.service; +import java.util.List; + +import org.lamsfoundation.lams.qb.model.QbQuestion; + public interface IQbService { // statuses of comparing QB question coming from authoring with data existing in DB @@ -12,10 +16,21 @@ static final int QUESTION_MODIFIED_VERSION_BUMP = 2; // it is a new question static final int QUESTION_MODIFIED_ID_BUMP = 3; + + /** + * @param qbQuestionUid + * @return QbQuestion object with the specified uid + */ + QbQuestion getQbQuestionByUid(Long qbQuestionUid); // finds next question ID for Question Bank question int getMaxQuestionId(); // finds next version for given question ID for Question Bank question int getMaxQuestionVersion(Integer qbQuestionId); + + List getPagedQbQuestions(Integer questionType, int page, int size, String sortBy, + String sortOrder, String searchString); + + int getCountQbQuestions(Integer questionType, String searchString); } Index: lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java =================================================================== diff -u -r2e9ee1c2451a05981f05e9edf89bb3356cf2b147 -ra109b7b66649bbed86abf584a192c6af194946ef --- lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java (.../QbService.java) (revision 2e9ee1c2451a05981f05e9edf89bb3356cf2b147) +++ lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java (.../QbService.java) (revision a109b7b66649bbed86abf584a192c6af194946ef) @@ -1,10 +1,18 @@ package org.lamsfoundation.lams.qb.service; +import java.util.List; + import org.lamsfoundation.lams.qb.dao.IQbDAO; +import org.lamsfoundation.lams.qb.model.QbQuestion; public class QbService implements IQbService { private IQbDAO qbDAO; + + @Override + public QbQuestion getQbQuestionByUid(Long qbQuestionUid) { + return qbDAO.getQbQuestionByUid(qbQuestionUid); + } @Override public int getMaxQuestionId() { @@ -15,6 +23,17 @@ public int getMaxQuestionVersion(Integer qbQuestionId) { return qbDAO.getMaxQuestionVersion(qbQuestionId); } + + @Override + public List getPagedQbQuestions(Integer questionType, int page, int size, String sortBy, + String sortOrder, String searchString) { + return qbDAO.getPagedQbQuestions(questionType, page, size, sortBy, sortOrder, searchString); + } + + @Override + public int getCountQbQuestions(Integer questionType, String searchString) { + return qbDAO.getCountQbQuestions(questionType, searchString); + } public void setQbDAO(IQbDAO qbDAO) { this.qbDAO = qbDAO; Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java =================================================================== diff -u -r6de3d240b76c900f96a93ab784838f2153fbe7c5 -ra109b7b66649bbed86abf584a192c6af194946ef --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java (.../ScratchieServiceImpl.java) (revision 6de3d240b76c900f96a93ab784838f2153fbe7c5) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java (.../ScratchieServiceImpl.java) (revision a109b7b66649bbed86abf584a192c6af194946ef) @@ -210,7 +210,10 @@ @Override public void saveOrUpdateScratchie(Scratchie scratchie) { for (ScratchieItem item : scratchie.getScratchieItems()) { - scratchieItemDao.saveObject(item.getQbQuestion()); + //update only in case QbQuestion was modified, to prevent updating the same QbQuestions received from SesssionMap + if (item.getQbQuestionModified() != IQbService.QUESTION_MODIFIED_NONE) { + scratchieItemDao.saveObject(item.getQbQuestion()); + } scratchieItemDao.saveObject(item); } scratchieDao.saveObject(scratchie); Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/AuthoringController.java =================================================================== diff -u -r6de3d240b76c900f96a93ab784838f2153fbe7c5 -ra109b7b66649bbed86abf584a192c6af194946ef --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/AuthoringController.java (.../AuthoringController.java) (revision 6de3d240b76c900f96a93ab784838f2153fbe7c5) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/AuthoringController.java (.../AuthoringController.java) (revision a109b7b66649bbed86abf584a192c6af194946ef) @@ -127,10 +127,6 @@ private String starting(@ModelAttribute("authoringForm") ScratchieForm authoringForm, HttpServletRequest request) throws ServletException { - - // save toolContentID into HTTPSession - Long contentId = new Long(WebUtil.readLongParam(request, ScratchieConstants.PARAM_TOOL_CONTENT_ID)); - List items = null; Scratchie scratchie = null; @@ -143,6 +139,10 @@ String contentFolderID = WebUtil.readStrParam(request, AttributeNames.PARAM_CONTENT_FOLDER_ID); sessionMap.put(AttributeNames.PARAM_CONTENT_FOLDER_ID, contentFolderID); authoringForm.setContentFolderID(contentFolderID); + + // save toolContentID into HTTPSession + Long contentId = new Long(WebUtil.readLongParam(request, ScratchieConstants.PARAM_TOOL_CONTENT_ID)); + sessionMap.put(ScratchieConstants.PARAM_TOOL_CONTENT_ID, contentId); try { scratchie = scratchieService.getScratchieByContentId(contentId); @@ -404,14 +404,52 @@ request.setAttribute(AttributeNames.PARAM_CONTENT_FOLDER_ID, contentFolderID); return "pages/authoring/parts/additem"; } + + /** + * QB callback handler which adds selected QbQuestion into question list. + */ + @RequestMapping(value = "/importQbQuestion", method = RequestMethod.POST) + private String importQbQuestion(HttpServletRequest request) { + String sessionMapID = WebUtil.readStrParam(request, ScratchieConstants.ATTR_SESSION_MAP_ID); + SessionMap sessionMap = (SessionMap) request.getSession() + .getAttribute(sessionMapID); + SortedSet itemList = getItemList(sessionMap); + + Long qbQuestionUid = WebUtil.readLongParam(request, "qbQuestionUid"); + QbQuestion qbQuestion = qbService.getQbQuestionByUid(qbQuestionUid); + + //create new ScratchieItem and assign imported qbQuestion to it + ScratchieItem item = new ScratchieItem(); + item.setQbQuestion(qbQuestion); + int maxSeq = 1; + if (itemList != null && itemList.size() > 0) { + ScratchieItem last = itemList.last(); + maxSeq = last.getDisplayOrder() + 1; + } + item.setDisplayOrder(maxSeq); + item.setQbQuestionModified(IQbService.QUESTION_MODIFIED_NONE); + itemList.add(item); + + // evict everything manually as we do not use DTOs, just real entities + // without eviction changes would be saved immediately into DB +// scratchieService.releaseFromCache(item); +// scratchieService.releaseFromCache(item); +// scratchieService.releaseFromCache(item.getQbQuestion()); + +// request.setAttribute("qbQuestionModified", item.getQbQuestionModified()); + + // set session map ID so that itemlist.jsp can get sessionMAP + request.setAttribute(ScratchieConstants.ATTR_SESSION_MAP_ID, sessionMapID); + return "pages/authoring/parts/itemlist"; + } + /** * This method will get necessary information from assessment question form and save or update into * HttpSession AssessmentQuestionList. Notice, this save is not persist them into database, just save * HttpSession temporarily. Only they will be persist when the entire authoring page is being * persisted. */ - @RequestMapping(value = "/saveItem", method = RequestMethod.POST) private String saveItem(@ModelAttribute("scratchieItemForm") ScratchieItemForm scratchieItemForm, HttpServletRequest request) { Index: lams_tool_scratchie/web/pages/authoring/parts/itemlist.jsp =================================================================== diff -u -rfba7287887f6dd83d3098100af6320cccf1f3e36 -ra109b7b66649bbed86abf584a192c6af194946ef --- lams_tool_scratchie/web/pages/authoring/parts/itemlist.jsp (.../itemlist.jsp) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) +++ lams_tool_scratchie/web/pages/authoring/parts/itemlist.jsp (.../itemlist.jsp) (revision a109b7b66649bbed86abf584a192c6af194946ef) @@ -26,13 +26,27 @@
+ +
+ + + ?sessionMapID=${sessionMapID} + + + + + + Import from question bank +
+