Index: lams_central/src/java/org/lamsfoundation/lams/web/qb/QbCollectionController.java =================================================================== diff -u -r0eb673cae894e38f77a6470467da5f26111b3862 -r33b937e6fb979aa7a58fd0f33d1ecf474150155b --- lams_central/src/java/org/lamsfoundation/lams/web/qb/QbCollectionController.java (.../QbCollectionController.java) (revision 0eb673cae894e38f77a6470467da5f26111b3862) +++ lams_central/src/java/org/lamsfoundation/lams/web/qb/QbCollectionController.java (.../QbCollectionController.java) (revision 33b937e6fb979aa7a58fd0f33d1ecf474150155b) @@ -23,6 +23,7 @@ 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; @@ -158,21 +159,30 @@ @RequestMapping("/removeCollectionQuestions") @ResponseBody - public void removeCollectionQuestions(@RequestParam long collectionUid, @RequestParam String included, + 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++) { - qbService.removeQuestionFromCollection(collectionUid, includedJSON.get(index).asLong()); + 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()); } - qbService.removeQuestionFromCollection(collectionUid, excludedSet); + retainedQuestions = qbService.removeQuestionFromCollection(collectionUid, excludedSet); } + + return JsonUtil.toString(retainedQuestions); } @RequestMapping("/addCollectionQuestions") Index: lams_central/web/qb/collection.jsp =================================================================== diff -u -r0eb673cae894e38f77a6470467da5f26111b3862 -r33b937e6fb979aa7a58fd0f33d1ecf474150155b --- lams_central/web/qb/collection.jsp (.../collection.jsp) (revision 0eb673cae894e38f77a6470467da5f26111b3862) +++ lams_central/web/qb/collection.jsp (.../collection.jsp) (revision 33b937e6fb979aa7a58fd0f33d1ecf474150155b) @@ -125,13 +125,11 @@ // 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'), - included = grid.data('included'); + 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 = $('') - .prop('checked', included === null) .prependTo(selectAllCell) .change(function(){ // start with deselecting every question on current page @@ -156,6 +154,8 @@ 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(); @@ -169,9 +169,6 @@ alert("Error!"); } }).jqGrid('filterToolbar'); - - - collectionGrid.data('included', []); }); }); @@ -189,14 +186,29 @@ $.ajax({ 'url' : 'qb/collection/removeCollectionQuestions.do', 'type' : 'POST', - 'dataType' : 'text', + 'dataType' : 'json', 'data' : { 'collectionUid' : grid.data('collectionUid'), 'included' : included ? JSON.stringify(included) : null, 'excluded' : excluded ? JSON.stringify(excluded) : null }, 'cache' : false - }).done(function(){ + }).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'); }); } @@ -324,10 +336,7 @@
- <%-- Do not allow removing questions from public collection --%> - - - +
Transfer questions to Index: lams_common/src/java/org/lamsfoundation/lams/qb/dao/IQbDAO.java =================================================================== diff -u -r730a7378ea82a88512217331afdbd1f0f0346d61 -r33b937e6fb979aa7a58fd0f33d1ecf474150155b --- lams_common/src/java/org/lamsfoundation/lams/qb/dao/IQbDAO.java (.../IQbDAO.java) (revision 730a7378ea82a88512217331afdbd1f0f0346d61) +++ lams_common/src/java/org/lamsfoundation/lams/qb/dao/IQbDAO.java (.../IQbDAO.java) (revision 33b937e6fb979aa7a58fd0f33d1ecf474150155b) @@ -7,6 +7,7 @@ import org.lamsfoundation.lams.dao.IBaseDAO; import org.lamsfoundation.lams.learningdesign.ToolActivity; +import org.lamsfoundation.lams.qb.model.QbCollection; import org.lamsfoundation.lams.qb.model.QbQuestion; public interface IQbDAO extends IBaseDAO { @@ -49,11 +50,14 @@ List getCollectionQuestions(long collectionUid, Integer offset, Integer limit, String orderBy, String orderDirection, String search); + List getQuestionCollections(long qbQuestionUid); + int countCollectionQuestions(long collectionUid, String search); void addCollectionQuestion(long collectionUid, long qbQuestionUid); void removeCollectionQuestion(long collectionUid, long qbQuestionUid); Set getCollectionQuestionUidsExcluded(long collectionUid, Collection qbQuestionUids); + } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/qb/dao/hibernate/QbDAO.java =================================================================== diff -u -r730a7378ea82a88512217331afdbd1f0f0346d61 -r33b937e6fb979aa7a58fd0f33d1ecf474150155b --- lams_common/src/java/org/lamsfoundation/lams/qb/dao/hibernate/QbDAO.java (.../QbDAO.java) (revision 730a7378ea82a88512217331afdbd1f0f0346d61) +++ lams_common/src/java/org/lamsfoundation/lams/qb/dao/hibernate/QbDAO.java (.../QbDAO.java) (revision 33b937e6fb979aa7a58fd0f33d1ecf474150155b) @@ -16,6 +16,7 @@ import org.lamsfoundation.lams.dao.hibernate.LAMSBaseDAO; import org.lamsfoundation.lams.learningdesign.ToolActivity; import org.lamsfoundation.lams.qb.dao.IQbDAO; +import org.lamsfoundation.lams.qb.model.QbCollection; import org.lamsfoundation.lams.qb.model.QbQuestion; public class QbDAO extends LAMSBaseDAO implements IQbDAO { @@ -51,9 +52,12 @@ + "BurningQuestionLike AS bl ON bl.burningQuestion = b WHERE b.scratchieItem.qbQuestion.uid = :qbQuestionUid " + "GROUP BY b.question ORDER BY COUNT(bl.uid) DESC"; - private static final String FIND_COLLECTION_QUESTIONS = "SELECT q.* FROM lams_qb_collection_question AS c " - + "JOIN lams_qb_question AS q ON c.qb_question_uid = q.uid WHERE c.collection_uid = :collectionUid"; + private static final String FIND_COLLECTION_QUESTIONS = "SELECT q.* FROM lams_qb_collection_question AS cq " + + "JOIN lams_qb_question AS q ON cq.qb_question_uid = q.uid WHERE cq.collection_uid = :collectionUid"; + private static final String FIND_QUESTION_COLLECTIONS = "SELECT c.* FROM lams_qb_collection_question AS cq " + + "JOIN lams_qb_collection AS c ON cq.collection_uid = c.uid WHERE cq.qb_question_uid = :qbQuestionUid"; + private static final String ADD_COLLECTION_QUESTION = "INSERT INTO lams_qb_collection_question VALUES (:collectionUid, :qbQuestionUid)"; private static final String EXISTS_COLLECTION_QUESTION = "SELECT 1 FROM lams_qb_collection_question WHERE collection_uid = :collectionUid " @@ -240,6 +244,13 @@ @SuppressWarnings("unchecked") @Override + public List getQuestionCollections(long qbQuestionUid) { + return getSession().createNativeQuery(FIND_QUESTION_COLLECTIONS).setParameter("qbQuestionUid", qbQuestionUid) + .list(); + } + + @SuppressWarnings("unchecked") + @Override public List getCollectionQuestions(long collectionUid, Integer offset, Integer limit, String orderBy, String orderDirection, String search) { Query query = prepareCollectionQuestionsQuery(collectionUid, orderBy, orderDirection, search, false); Index: lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java =================================================================== diff -u -r374f47ea57a62a77e6faf1bb9713de1f9f53c1be -r33b937e6fb979aa7a58fd0f33d1ecf474150155b --- lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java (.../IQbService.java) (revision 374f47ea57a62a77e6faf1bb9713de1f9f53c1be) +++ lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java (.../IQbService.java) (revision 33b937e6fb979aa7a58fd0f33d1ecf474150155b) @@ -81,7 +81,7 @@ void addQuestionToCollection(long sourceCollectionUid, long targetCollectionUid, Collection excludedQbQuestionUids, boolean copy); - void removeQuestionFromCollection(long collectionUid, long qbQuestionUid); + boolean removeQuestionFromCollection(long collectionUid, long qbQuestionUid); - void removeQuestionFromCollection(long collectionUid, Collection excludedQbQuestionUids); + Collection removeQuestionFromCollection(long collectionUid, Collection excludedQbQuestionUids); } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java =================================================================== diff -u -r0eb673cae894e38f77a6470467da5f26111b3862 -r33b937e6fb979aa7a58fd0f33d1ecf474150155b --- lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java (.../QbService.java) (revision 0eb673cae894e38f77a6470467da5f26111b3862) +++ lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java (.../QbService.java) (revision 33b937e6fb979aa7a58fd0f33d1ecf474150155b) @@ -27,6 +27,7 @@ import org.lamsfoundation.lams.qb.model.QbCollection; import org.lamsfoundation.lams.qb.model.QbOption; import org.lamsfoundation.lams.qb.model.QbQuestion; +import org.lamsfoundation.lams.qb.model.QbToolQuestion; import org.lamsfoundation.lams.tool.service.ILamsCoreToolService; import org.lamsfoundation.lams.usermanagement.Organisation; import org.lamsfoundation.lams.usermanagement.Role; @@ -258,7 +259,7 @@ if (!result.isEmpty()) { return result.get(0); } - + // is an user does not have a private collection yet, create it QbCollection collection = new QbCollection(); collection.setName("Private questions"); @@ -311,6 +312,18 @@ qbDAO.delete(collection); } + public boolean removeQuestion(long qbQuestionUid) { + Map properties = new HashMap<>(); + properties.put("qbQuestion.uid", qbQuestionUid); + long activityCount = qbDAO.countByProperties(QbToolQuestion.class, properties); + if (activityCount > 0) { + // if the question is used in a Learning Design, do not allow to remove it + return false; + } + qbDAO.deleteById(QbQuestion.class, qbQuestionUid); + return true; + } + @Override public Organisation shareCollection(long collectionUid, int organisationId) { QbCollection collection = (QbCollection) qbDAO.find(QbCollection.class, collectionUid); @@ -366,16 +379,28 @@ } @Override - public void removeQuestionFromCollection(long collectionUid, long qbQuestionUid) { + public boolean removeQuestionFromCollection(long collectionUid, long qbQuestionUid) { + Collection collections = qbDAO.getQuestionCollections(qbQuestionUid); + int size = collections.size(); + if (size <= 1) { + // if the question is in its last collection, try to remove it permanently + return removeQuestion(qbQuestionUid); + } qbDAO.removeCollectionQuestion(collectionUid, qbQuestionUid); + return true; } @Override - public void removeQuestionFromCollection(long collectionUid, Collection excludedQbQuestionUids) { + public Collection removeQuestionFromCollection(long collectionUid, Collection excludedQbQuestionUids) { Collection includedUids = qbDAO.getCollectionQuestionUidsExcluded(collectionUid, excludedQbQuestionUids); + Collection retainedQuestionUids = new HashSet<>(); for (Long uid : includedUids) { - qbDAO.removeCollectionQuestion(collectionUid, uid); + boolean deleted = removeQuestionFromCollection(collectionUid, uid); + if (!deleted) { + retainedQuestionUids.add(uid); + } } + return retainedQuestionUids; } @Override