Index: lams_central/src/java/org/lamsfoundation/lams/web/qb/QbCollectionController.java =================================================================== diff -u -r8d2337141f10b26a11e9730f9c44d53a96fcc062 -r0952bdcd231fe03cb52b8d821bc6cc1882b7c369 --- lams_central/src/java/org/lamsfoundation/lams/web/qb/QbCollectionController.java (.../QbCollectionController.java) (revision 8d2337141f10b26a11e9730f9c44d53a96fcc062) +++ lams_central/src/java/org/lamsfoundation/lams/web/qb/QbCollectionController.java (.../QbCollectionController.java) (revision 0952bdcd231fe03cb52b8d821bc6cc1882b7c369) @@ -22,23 +22,17 @@ package org.lamsfoundation.lams.web.qb; -import java.io.IOException; -import java.util.Collection; -import java.util.HashSet; import java.util.List; -import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.lamsfoundation.lams.qb.model.QbQuestion; import org.lamsfoundation.lams.qb.service.IQbService; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; import org.lamsfoundation.lams.util.CommonConstants; -import org.lamsfoundation.lams.util.JsonUtil; import org.lamsfoundation.lams.util.MessageService; import org.lamsfoundation.lams.util.WebUtil; import org.lamsfoundation.lams.web.session.SessionManager; @@ -53,8 +47,6 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.fasterxml.jackson.databind.node.ArrayNode; - @Controller @RequestMapping("/qb/collection") public class QbCollectionController { @@ -71,7 +63,7 @@ public String showUserCollections(Model model) throws Exception { Integer userId = getUserId(); model.addAttribute("collections", qbService.getUserCollections(userId)); - return "qb/collection"; + return "qb/collectionList"; } @RequestMapping("/getCollectionGridData") @@ -144,53 +136,17 @@ return null; } - @RequestMapping("/removeCollectionQuestions") + @RequestMapping("/removeCollectionQuestion") @ResponseBody - public String removeCollectionQuestions(@RequestParam long collectionUid, @RequestParam String included, - @RequestParam String excluded) throws IOException { - // list of questions which could not be removed (they are in their last collection and are used in Learning Designs) - Collection retainedQuestions; - if (StringUtils.isBlank(excluded)) { - ArrayNode includedJSON = JsonUtil.readArray(included); - retainedQuestions = new HashSet<>(); - for (int index = 0; index < includedJSON.size(); index++) { - long qbQuestionUid = includedJSON.get(index).asLong(); - boolean deleted = qbService.removeQuestionFromCollection(collectionUid, qbQuestionUid); - if (!deleted) { - retainedQuestions.add(qbQuestionUid); - } - } - } else { - ArrayNode excludedJSON = JsonUtil.readArray(excluded); - Set excludedSet = new HashSet<>(); - for (int index = 0; index < excludedJSON.size(); index++) { - excludedSet.add(excludedJSON.get(index).asLong()); - } - retainedQuestions = qbService.removeQuestionFromCollection(collectionUid, excludedSet); - } - - return JsonUtil.toString(retainedQuestions); + public void removeCollectionQuestion(@RequestParam long collectionUid, @RequestParam long qbQuestionUid) { + qbService.removeQuestionFromCollection(collectionUid, qbQuestionUid); } - @RequestMapping("/addCollectionQuestions") + @RequestMapping("/addCollectionQuestion") @ResponseBody - public void addCollectionQuestions(@RequestParam(required = false) Long sourceCollectionUid, - @RequestParam long targetCollectionUid, @RequestParam boolean copy, - @RequestParam(required = false) String included, @RequestParam(required = false) String excluded) - throws IOException { - if (StringUtils.isBlank(excluded)) { - ArrayNode includedJSON = JsonUtil.readArray(included); - for (int index = 0; index < includedJSON.size(); index++) { - qbService.addQuestionToCollection(targetCollectionUid, includedJSON.get(index).asLong(), copy); - } - } else { - ArrayNode excludedJSON = JsonUtil.readArray(excluded); - Set excludedSet = new HashSet<>(); - for (int index = 0; index < excludedJSON.size(); index++) { - excludedSet.add(excludedJSON.get(index).asLong()); - } - qbService.addQuestionToCollection(sourceCollectionUid, targetCollectionUid, excludedSet, copy); - } + public void addCollectionQuestion(@RequestParam long targetCollectionUid, @RequestParam boolean copy, + @RequestParam long qbQuestionUid) { + qbService.addQuestionToCollection(targetCollectionUid, qbQuestionUid, copy); } @RequestMapping("/addCollection") Index: lams_central/src/java/org/lamsfoundation/lams/web/qb/QbStatsController.java =================================================================== diff -u -r8d2337141f10b26a11e9730f9c44d53a96fcc062 -r0952bdcd231fe03cb52b8d821bc6cc1882b7c369 --- lams_central/src/java/org/lamsfoundation/lams/web/qb/QbStatsController.java (.../QbStatsController.java) (revision 8d2337141f10b26a11e9730f9c44d53a96fcc062) +++ lams_central/src/java/org/lamsfoundation/lams/web/qb/QbStatsController.java (.../QbStatsController.java) (revision 0952bdcd231fe03cb52b8d821bc6cc1882b7c369) @@ -58,11 +58,19 @@ QbStatsDTO stats = qbService.getQbQuestionStats(qbQuestionUid); model.addAttribute("stats", stats); + Collection existingCollections = qbService.getQuestionCollections(qbQuestionUid); + model.addAttribute("existingCollections", existingCollections); + Integer userId = getUserId(); - Collection collections = qbService.getUserCollections(userId); - collections.removeAll(qbService.getQuestionCollections(qbQuestionUid)); - model.addAttribute("collections", collections); + Collection availableCollections = qbService.getUserCollections(userId); + availableCollections.removeAll(existingCollections); + model.addAttribute("availableCollections", availableCollections); + boolean permanentRemove = existingCollections.size() <= 1; + model.addAttribute("permanentRemove", permanentRemove); + model.addAttribute("permanentRemovePossible", + permanentRemove ? qbService.removeQuestionPossible(qbQuestionUid) : false); + return "qb/stats"; } Index: lams_central/web/qb/collectionList.jsp =================================================================== diff -u -r14dec0981582e0cecba5de70a09f2aa2ef1be35d -r0952bdcd231fe03cb52b8d821bc6cc1882b7c369 --- lams_central/web/qb/collectionList.jsp (.../collectionList.jsp) (revision 14dec0981582e0cecba5de70a09f2aa2ef1be35d) +++ lams_central/web/qb/collectionList.jsp (.../collectionList.jsp) (revision 0952bdcd231fe03cb52b8d821bc6cc1882b7c369) @@ -71,8 +71,6 @@ cmTemplate: { title: false, search: false }, sortorder: "asc", sortname: "name", - multiselect : true, - multiPageSelection : true, pager: true, rowList:[10,20,30,40,50,100], rowNum: 10, @@ -87,83 +85,10 @@ // formatter gets just question uid and creates a button {name:'stats', index:'stats', classes: "stats-cell", sortable:false, width: 10, align: "center", formatter: statsLinkFormatter} ], - onSelectRow : function(id, status, event) { - var grid = $(this), - // if no questions are selected, buttons to manipulate them get disabled - buttons = grid.closest('.ui-jqgrid').siblings('.container-fluid').find('.questionButtons .btn'), - included = grid.data('included'), - excluded = grid.data('excluded'), - selectAllChecked = grid.closest('.ui-jqgrid-view').find('.jqgh_cbox .cbox').prop('checked'); - if (selectAllChecked) { - var index = excluded.indexOf(+id); - // if row is deselected, add it to excluded array - if (index < 0) { - if (!status) { - excluded.push(+id); - } - } else if (status) { - excluded.splice(index, 1); - } - } else { - var index = included.indexOf(+id); - // if row is selected, add it to included array - if (index < 0) { - if (status) { - included.push(+id); - buttons.prop('disabled', false); - } - } else if (!status) { - included.splice(index, 1); - if (included.length === 0) { - buttons.prop('disabled', true); - } - } - } + beforeSelectRow: function(rowid, e) { + // do not select rows at all + return false; }, - gridComplete : function(){ - var grid = $(this), - // if no questions are selected, buttons to manipulate them get disabled - buttons = grid.closest('.ui-jqgrid').siblings('.container-fluid').find('.questionButtons .btn'), - // cell containing "(de)select all" button - selectAllCell = grid.closest('.ui-jqgrid-view').find('.jqgh_cbox > div'); - // remove the default button provided by jqGrid - $('.cbox', selectAllCell).remove(); - // create own button which follows own rules - var selectAllCheckbox = $('') - .prependTo(selectAllCell) - .change(function(){ - // start with deselecting every question on current page - grid.resetSelection(); - if ($(this).prop('checked')){ - // on select all change mode and select all on current page - grid.data('included', null); - grid.data('excluded', []); - $('[role="row"]', grid).each(function(){ - grid.jqGrid('setSelection', +$(this).attr('id'), false); - }); - buttons.prop('disabled', false); - } else { - // on deselect all just change mode - grid.data('excluded', null); - grid.data('included', []); - buttons.prop('disabled', true); - } - }); - grid.resetSelection(); - }, - loadComplete : function(){ - var grid = $(this), - gridView = grid.closest('.ui-jqgrid-view'); - grid.data('excluded', null); - grid.data('included', []); - // remove checkbox next to search bar - $('tr.ui-search-toolbar .cbox', gridView).remove(); - - // do not select row when clicked on stats button - $('.stats-cell', gridView).click(function(event){ - event.stopImmediatePropagation(); - }); - }, loadError: function(xhr,st,err) { collectionGrid.clearGridData(); alert("Error!"); @@ -178,65 +103,6 @@ + "\", \"_blank\")' title='Show stats'>"; } - // remove questions from a collection - function removeCollectionQuestions(button) { - var grid = $(button).closest('.container-fluid').siblings(".ui-jqgrid").find('.collection-grid'), - included = grid.data('included'), - excluded = grid.data('excluded'); - $.ajax({ - 'url' : 'qb/collection/removeCollectionQuestions.do', - 'type' : 'POST', - 'dataType' : 'json', - 'data' : { - 'collectionUid' : grid.data('collectionUid'), - 'included' : included ? JSON.stringify(included) : null, - 'excluded' : excluded ? JSON.stringify(excluded) : null - }, - 'cache' : false - }).done(function(retainedQuestions){ - if (retainedQuestions.length > 0) { - // if some questions have not been removed, inform the user - var message = ""; - if (retainedQuestions.length > 10) { - message += "Multiple questions"; - } else { - message += "Questions with IDs: " - for (var qbQuestionUid of retainedQuestions) { - message += qbQuestionUid + ", "; - } - message = message.substring(0, message.length - 2); - } - message += " have not been removed because they are in their last collection and are used in sequences"; - alert(message); - } - grid.trigger('reloadGrid'); - }); - } - - // add or copy questions to a collection - function addCollectionQuestions(button, copy) { - var grid = $(button).closest('.container-fluid').siblings(".ui-jqgrid").find('.collection-grid'), - sourceCollectionUid = grid.data('collectionUid'), - targetCollectionUid = $(button).closest('.container-fluid').find('.targetCollectionSelect').val(), - included = grid.data('included'), - excluded = grid.data('excluded'); - $.ajax({ - 'url' : 'qb/collection/addCollectionQuestions.do', - 'type' : 'POST', - 'dataType' : 'text', - 'data' : { - 'sourceCollectionUid' : sourceCollectionUid, - 'targetCollectionUid' : targetCollectionUid, - 'copy' : copy, - 'included' : included ? JSON.stringify(included) : null, - 'excluded' : excluded ? JSON.stringify(excluded) : null - }, - 'cache' : false - }).done(function(){ - $('.collection-grid[data-collection-uid="' + targetCollectionUid + '"]').trigger('reloadGrid'); - }); - } - // add a new collection function addCollection() { var name = $('#addCollectionDiv input').val().trim(), @@ -333,37 +199,6 @@
- -
-
- -
-
- Transfer questions to -
-
- -
-
- - -
-
- <%-- Do not display links for collection manipulation for public and private collections --%>
Index: lams_central/web/qb/stats.jsp =================================================================== diff -u -r8d2337141f10b26a11e9730f9c44d53a96fcc062 -r0952bdcd231fe03cb52b8d821bc6cc1882b7c369 --- lams_central/web/qb/stats.jsp (.../stats.jsp) (revision 8d2337141f10b26a11e9730f9c44d53a96fcc062) +++ lams_central/web/qb/stats.jsp (.../stats.jsp) (revision 0952bdcd231fe03cb52b8d821bc6cc1882b7c369) @@ -39,28 +39,60 @@ @@ -114,170 +146,197 @@
- +
Transfer questions to - + +
+ +
+ Existing collections
+ + +
+
+
-

Options

- - - - - - - - + +

Options

+
- # - - Title - - Correct? - - Average selection
(as first choice) -
- - - - + + + + - -
- ${status.index + 1} - - - - - - - - <%--(${empty stats.answersRaw[option.uid] ? 0 : stats.answersRaw[option.uid]})--%> - ${stats.answersPercent[option.uid]}% - + # + + Title + + Correct? + + Average selection
(as first choice) +
- + + + + ${status.index + 1} + + + + + + + + + + + <%--(${empty stats.answersRaw[option.uid] ? 0 : stats.answersRaw[option.uid]})--%> + ${stats.answersPercent[option.uid]}% + + + + + +
-
-
- Average selection chart + +
+
+ Average selection chart +
+
+
-
-
-
+
Burning questions
- - - - - - - - - - - -
- Question - - Likes -
- - - -
+ + + This question does not have any burning questions + + + + + + + + + + + + + +
+ Question + + Likes +
+ + + +
+
+
- Usage + Usage in lessons
- - - - - - - - - - - - - + + + This question is not used in any lesson + + +
- Organisation - - Lesson - - Activity - - Tool type - - Test participant count - - Difficulty index - - Discrimination index - - Point biserial -
- - - + + + + + + + + + + + + + + + + - - + + + + - - - + + + + - - - - - - - - - - - - - - - - - - -
- - - - + + Organisation + + Lesson + + Activity + + Tool type + + Test participant count + + Difficulty index + + Discrimination index + + Point biserial +
+ + + + + + + + + + + + + + + + + + + --- - - - - ---
+ + + + +
@@ -286,32 +345,39 @@ Previous versions
- - - - - - - - - - - - - -
- # - - Created date - - Created ago -
- v${version.version} - - - - -
+ + + This question does not have any previous versions + + + + + + + + + + + + + + + +
+ # + + Created date + + Created ago +
+ v${version.version} + + + + +
+
+
Index: lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java =================================================================== diff -u -r8d2337141f10b26a11e9730f9c44d53a96fcc062 -r0952bdcd231fe03cb52b8d821bc6cc1882b7c369 --- lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java (.../IQbService.java) (revision 8d2337141f10b26a11e9730f9c44d53a96fcc062) +++ lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java (.../IQbService.java) (revision 0952bdcd231fe03cb52b8d821bc6cc1882b7c369) @@ -88,4 +88,8 @@ boolean removeQuestionFromCollection(long collectionUid, long qbQuestionUid); Collection removeQuestionFromCollection(long collectionUid, Collection excludedQbQuestionUids); + + boolean removeQuestion(long qbQuestionUid); + + boolean removeQuestionPossible(long qbQuestionUid); } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java =================================================================== diff -u -r8d2337141f10b26a11e9730f9c44d53a96fcc062 -r0952bdcd231fe03cb52b8d821bc6cc1882b7c369 --- lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java (.../QbService.java) (revision 8d2337141f10b26a11e9730f9c44d53a96fcc062) +++ lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java (.../QbService.java) (revision 0952bdcd231fe03cb52b8d821bc6cc1882b7c369) @@ -317,11 +317,10 @@ qbDAO.delete(collection); } + @Override public boolean removeQuestion(long qbQuestionUid) { - Map properties = new HashMap<>(); - properties.put("qbQuestion.uid", qbQuestionUid); - long activityCount = qbDAO.countByProperties(QbToolQuestion.class, properties); - if (activityCount > 0) { + boolean removeQuestionPossible = removeQuestionPossible(qbQuestionUid); + if (!removeQuestionPossible) { // if the question is used in a Learning Design, do not allow to remove it return false; } @@ -330,6 +329,13 @@ } @Override + public boolean removeQuestionPossible(long qbQuestionUid) { + Map properties = new HashMap<>(); + properties.put("qbQuestion.uid", qbQuestionUid); + return qbDAO.countByProperties(QbToolQuestion.class, properties) == 0; + } + + @Override public Organisation shareCollection(long collectionUid, int organisationId) { QbCollection collection = (QbCollection) qbDAO.find(QbCollection.class, collectionUid); if (collection.getUserId() == null || collection.isPersonal()) {