From 4d18281d0ddc66d13ede3d4fe6b125b1dae0db55 Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Thu, 28 Feb 2013 13:39:45 +0100 Subject: [PATCH] OO-535: more stuff in admin... --- .../table/FlexiTableClassicRenderer.java | 3 +- .../java/org/olat/modules/qpool/Pool.java | 2 + .../modules/qpool/QuestionPoolService.java | 17 ++ .../org/olat/modules/qpool/StudyField.java | 2 + .../impl/PdfQuestionPoolServiceProvider.java | 13 +- .../impl/TextQuestionPoolServiceProvider.java | 7 +- .../modules/qpool/manager/CollectionDAO.java | 20 +- .../qpool/manager/NullPoolService.java | 2 +- .../olat/modules/qpool/manager/PoolDAO.java | 49 ++++- .../qpool/manager/QuestionItemDAO.java | 21 +- .../manager/QuestionPoolServiceImpl.java | 43 +++- .../modules/qpool/manager/StudyFieldDAO.java | 3 +- .../modules/qpool/model/CollectionToItem.java | 7 +- .../olat/modules/qpool/model/PoolImpl.java | 28 +++ .../modules/qpool/model/QuestionItemImpl.java | 17 +- .../qpool/ui/CreateCollectionController.java | 2 +- .../qpool/ui/FilePreviewController.java | 65 ++++++ .../olat/modules/qpool/ui/PoolDataModel.java | 130 +++++++++++ .../modules/qpool/ui/PoolEditController.java | 97 ++++++++ .../org/olat/modules/qpool/ui/PoolRow.java | 49 +++++ .../qpool/ui/PoolsAdminController.java | 207 ++++++++++++++++++ .../org/olat/modules/qpool/ui/QPoolEvent.java | 2 + .../ui/QuestionPoolMainEditorController.java | 51 ++++- .../qpool/ui/StudyFieldAdminController.java | 15 ++ .../modules/qpool/ui/StudyFieldTreeModel.java | 78 +++++++ .../qpool/ui/TextPreviewController.java | 98 +++++++++ .../qpool/ui/_content/admin_study_fields.html | 2 + .../qpool/ui/_content/file_preview.html | 1 + .../qpool/ui/_content/pools_admin.html | 14 ++ .../qpool/ui/_content/text_preview.html | 1 + .../qpool/ui/_i18n/LocalStrings_de.properties | 7 + .../java/org/olat/search/SearchService.java | 4 +- .../search/service/SearchServiceImpl.java | 5 +- .../service/indexer/QuestionItemIndexer.java | 19 ++ .../database/mysql/alter_8_4_0_to_9_0_0.sql | 10 +- .../FileResourceValidatorTest.java | 19 ++ .../modules/qpool/manager/PoolDAOTest.java | 2 +- 37 files changed, 1048 insertions(+), 64 deletions(-) create mode 100644 src/main/java/org/olat/modules/qpool/ui/FilePreviewController.java create mode 100644 src/main/java/org/olat/modules/qpool/ui/PoolDataModel.java create mode 100644 src/main/java/org/olat/modules/qpool/ui/PoolEditController.java create mode 100644 src/main/java/org/olat/modules/qpool/ui/PoolRow.java create mode 100644 src/main/java/org/olat/modules/qpool/ui/PoolsAdminController.java create mode 100644 src/main/java/org/olat/modules/qpool/ui/StudyFieldTreeModel.java create mode 100644 src/main/java/org/olat/modules/qpool/ui/TextPreviewController.java create mode 100644 src/main/java/org/olat/modules/qpool/ui/_content/file_preview.html create mode 100644 src/main/java/org/olat/modules/qpool/ui/_content/pools_admin.html create mode 100644 src/main/java/org/olat/modules/qpool/ui/_content/text_preview.html diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableClassicRenderer.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableClassicRenderer.java index fd8cdab350e..c67e7224d0f 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableClassicRenderer.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableClassicRenderer.java @@ -78,7 +78,8 @@ class FlexiTableClassicRenderer implements ComponentRenderer { // build rows target.append("<tbody>"); // the really selected rowid (from the tabledatamodel) - + + dataModel.load(0, rows); for (int i = 0; i < rows; i++) { // use alternating css class String cssClass; diff --git a/src/main/java/org/olat/modules/qpool/Pool.java b/src/main/java/org/olat/modules/qpool/Pool.java index 168350f8a19..06ace8a52f5 100644 --- a/src/main/java/org/olat/modules/qpool/Pool.java +++ b/src/main/java/org/olat/modules/qpool/Pool.java @@ -36,5 +36,7 @@ public interface Pool { public Date getLastModified(); public String getName(); + + public void setName(String name); } diff --git a/src/main/java/org/olat/modules/qpool/QuestionPoolService.java b/src/main/java/org/olat/modules/qpool/QuestionPoolService.java index 43819bf5310..dcb24f125f7 100644 --- a/src/main/java/org/olat/modules/qpool/QuestionPoolService.java +++ b/src/main/java/org/olat/modules/qpool/QuestionPoolService.java @@ -96,4 +96,21 @@ public interface QuestionPoolService { public List<QuestionItem> getItemsOfCollection(QuestionItemCollection collection, int firstResult, int maxResults, SortKey... orderBy); + + //study field admin + public List<StudyField> getStudyFields(); + + + //pool administration + public void createPool(Identity identity, String name); + + public Pool updatePool(Pool pool); + + public void deletePool(Pool pool); + + public int countPools(); + + public List<Pool> getPools(int firstResult, int maxResults, SortKey... orderBy); + + } diff --git a/src/main/java/org/olat/modules/qpool/StudyField.java b/src/main/java/org/olat/modules/qpool/StudyField.java index 098e926cb0c..6ae0a755460 100644 --- a/src/main/java/org/olat/modules/qpool/StudyField.java +++ b/src/main/java/org/olat/modules/qpool/StudyField.java @@ -36,4 +36,6 @@ public interface StudyField { public Date getLastModified(); public String getField(); + + public StudyField getParentField(); } diff --git a/src/main/java/org/olat/modules/qpool/impl/PdfQuestionPoolServiceProvider.java b/src/main/java/org/olat/modules/qpool/impl/PdfQuestionPoolServiceProvider.java index 87e64c5631b..1d315ebe781 100644 --- a/src/main/java/org/olat/modules/qpool/impl/PdfQuestionPoolServiceProvider.java +++ b/src/main/java/org/olat/modules/qpool/impl/PdfQuestionPoolServiceProvider.java @@ -27,6 +27,7 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.util.vfs.VFSLeaf; import org.olat.modules.qpool.QuestionItem; import org.olat.modules.qpool.QuestionPoolSPI; +import org.olat.modules.qpool.ui.FilePreviewController; /** * @@ -62,15 +63,13 @@ public class PdfQuestionPoolServiceProvider implements QuestionPoolSPI { @Override public Controller getPreviewController(UserRequest ureq, WindowControl wControl, QuestionItem item) { - return null; + FilePreviewController fileController = new FilePreviewController(ureq, wControl, item); + return fileController; } @Override public Controller getEditableController(UserRequest ureq, WindowControl wControl, QuestionItem item) { - return null; + FilePreviewController fileController = new FilePreviewController(ureq, wControl, item); + return fileController; } - - - - -} +} \ No newline at end of file diff --git a/src/main/java/org/olat/modules/qpool/impl/TextQuestionPoolServiceProvider.java b/src/main/java/org/olat/modules/qpool/impl/TextQuestionPoolServiceProvider.java index efd6b386755..43b3fa82978 100644 --- a/src/main/java/org/olat/modules/qpool/impl/TextQuestionPoolServiceProvider.java +++ b/src/main/java/org/olat/modules/qpool/impl/TextQuestionPoolServiceProvider.java @@ -27,6 +27,7 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.util.vfs.VFSLeaf; import org.olat.modules.qpool.QuestionItem; import org.olat.modules.qpool.QuestionPoolSPI; +import org.olat.modules.qpool.ui.TextPreviewController; /** * @@ -60,11 +61,13 @@ public class TextQuestionPoolServiceProvider implements QuestionPoolSPI { @Override public Controller getPreviewController(UserRequest ureq, WindowControl wControl, QuestionItem item) { - return null; + TextPreviewController txtController = new TextPreviewController(ureq, wControl, item); + return txtController; } @Override public Controller getEditableController(UserRequest ureq, WindowControl wControl, QuestionItem item) { - return null; + TextPreviewController txtController = new TextPreviewController(ureq, wControl, item); + return txtController; } } diff --git a/src/main/java/org/olat/modules/qpool/manager/CollectionDAO.java b/src/main/java/org/olat/modules/qpool/manager/CollectionDAO.java index 4de4ac4a60f..8e47f2accb1 100644 --- a/src/main/java/org/olat/modules/qpool/manager/CollectionDAO.java +++ b/src/main/java/org/olat/modules/qpool/manager/CollectionDAO.java @@ -19,6 +19,7 @@ */ package org.olat.modules.qpool.manager; +import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -32,6 +33,7 @@ import org.olat.modules.qpool.QuestionItem; import org.olat.modules.qpool.QuestionItemCollection; import org.olat.modules.qpool.model.CollectionToItem; import org.olat.modules.qpool.model.QuestionItemCollectionImpl; +import org.olat.modules.qpool.model.QuestionItemImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -73,7 +75,7 @@ public class CollectionDAO { } public void addItemToCollection(QuestionItem item, QuestionItemCollection collection) { - QuestionItem lockedItem = questionItemDao.loadForUpdate(item.getKey()); + QuestionItemImpl lockedItem = questionItemDao.loadForUpdate(item.getKey()); if(!isInCollection(collection, lockedItem)) { CollectionToItem coll2Item = new CollectionToItem(); coll2Item.setCreationDate(new Date()); @@ -84,7 +86,7 @@ public class CollectionDAO { dbInstance.commit(); } - public boolean isInCollection(QuestionItemCollection collection, QuestionItem item) { + public boolean isInCollection(QuestionItemCollection collection, QuestionItemImpl item) { StringBuilder sb = new StringBuilder(); sb.append("select count(coll2item) from qcollection2item coll2item where coll2item.collection.key=:collectionKey and coll2item.item.key=:itemKey"); Number count = dbInstance.getCurrentEntityManager() @@ -131,4 +133,18 @@ public class CollectionDAO { .setParameter("identityKey", me.getKey()) .getResultList(); } + + public int deleteItemFromCollections(List<QuestionItem> items) { + List<Long> keys = new ArrayList<Long>(); + for(QuestionItem item:items) { + keys.add(item.getKey()); + } + + StringBuilder sb = new StringBuilder(); + sb.append("delete from qcollection2item coll2item where coll2item.item.key in (:itemKeys)"); + return dbInstance.getCurrentEntityManager() + .createQuery(sb.toString()) + .setParameter("itemKeys", keys) + .executeUpdate(); + } } diff --git a/src/main/java/org/olat/modules/qpool/manager/NullPoolService.java b/src/main/java/org/olat/modules/qpool/manager/NullPoolService.java index 685691003ba..6bacf5973ce 100644 --- a/src/main/java/org/olat/modules/qpool/manager/NullPoolService.java +++ b/src/main/java/org/olat/modules/qpool/manager/NullPoolService.java @@ -90,7 +90,7 @@ public class NullPoolService implements ApplicationListener<ContextRefreshedEven int numOfQuestions = questionItemDao.getNumOfQuestions(); if(numOfQuestions < 3) { - List<Pool> pools = poolDao.getPools(); + List<Pool> pools = poolDao.getPools(0, -1); for(int i=0; i<200; i++) { long randomIndex = Math.round(Math.random() * (fields.size() - 1)); StudyField field = fields.get((int)randomIndex); diff --git a/src/main/java/org/olat/modules/qpool/manager/PoolDAO.java b/src/main/java/org/olat/modules/qpool/manager/PoolDAO.java index bc75a34b800..8f241341c59 100644 --- a/src/main/java/org/olat/modules/qpool/manager/PoolDAO.java +++ b/src/main/java/org/olat/modules/qpool/manager/PoolDAO.java @@ -25,6 +25,8 @@ import java.util.List; import javax.persistence.TypedQuery; +import org.olat.basesecurity.BaseSecurity; +import org.olat.basesecurity.SecurityGroup; import org.olat.core.commons.persistence.DB; import org.olat.core.commons.persistence.PersistenceHelper; import org.olat.core.commons.persistence.SortKey; @@ -48,13 +50,18 @@ public class PoolDAO { private DB dbInstance; @Autowired private QuestionItemDAO questionItemDao; + @Autowired + private BaseSecurity securityManager; - - public Pool createPool(String name) { + public PoolImpl createPool(String name) { PoolImpl pool = new PoolImpl(); pool.setCreationDate(new Date()); pool.setLastModified(new Date()); pool.setName(name); + SecurityGroup ownerGroup = securityManager.createAndPersistSecurityGroup(); + pool.setOwnerGroup(ownerGroup); + SecurityGroup participantGroup = securityManager.createAndPersistSecurityGroup(); + pool.setParticipantGroup(participantGroup); dbInstance.getCurrentEntityManager().persist(pool); return pool; } @@ -73,6 +80,22 @@ public class PoolDAO { .executeUpdate(); } + public Pool updatePool(Pool pool) { + return dbInstance.getCurrentEntityManager().merge(pool); + } + + public void deletePool(Pool pool) { + StringBuilder sb = new StringBuilder(); + sb.append("delete from qpool2item pool2item where pool2item.pool.key=:poolKey"); + dbInstance.getCurrentEntityManager() + .createQuery(sb.toString()) + .setParameter("poolKey", pool.getKey()) + .executeUpdate(); + + PoolImpl poolRef = dbInstance.getCurrentEntityManager().getReference(PoolImpl.class, pool.getKey()); + dbInstance.getCurrentEntityManager().remove(poolRef); + } + public int getNumOfPools() { StringBuilder sb = new StringBuilder(); sb.append("select count(pool) from qpool pool"); @@ -81,13 +104,27 @@ public class PoolDAO { .getSingleResult().intValue(); } - public List<Pool> getPools() { + public int countPools() { + StringBuilder sb = new StringBuilder(); + sb.append("select count(pool) from qpool pool"); + return dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), Number.class) + .getSingleResult().intValue(); + } + + public List<Pool> getPools(int firstResult, int maxResults) { StringBuilder sb = new StringBuilder(); sb.append("select pool from qpool pool"); - return dbInstance.getCurrentEntityManager() - .createQuery(sb.toString(), Pool.class) - .getResultList(); + TypedQuery<Pool> query = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), Pool.class); + if(firstResult >= 0) { + query.setFirstResult(firstResult); + } + if(maxResults > 0) { + query.setMaxResults(maxResults); + } + return query.getResultList(); } public void addItemToPool(QuestionItem item, Pool pool) { diff --git a/src/main/java/org/olat/modules/qpool/manager/QuestionItemDAO.java b/src/main/java/org/olat/modules/qpool/manager/QuestionItemDAO.java index 935de6092c2..48c27536530 100644 --- a/src/main/java/org/olat/modules/qpool/manager/QuestionItemDAO.java +++ b/src/main/java/org/olat/modules/qpool/manager/QuestionItemDAO.java @@ -87,11 +87,11 @@ public class QuestionItemDAO { item.setStudyField(field); item.setDirectory(generateDir(uuid)); item.setRootFilename(rootFilename); - SecurityGroup authorGroup = securityManager.createAndPersistSecurityGroup(); - item.setAuthorGroup(authorGroup); + SecurityGroup ownerGroup = securityManager.createAndPersistSecurityGroup(); + item.setOwnerGroup(ownerGroup); dbInstance.getCurrentEntityManager().persist(item); if(owner != null) { - securityManager.addIdentityToSecurityGroup(owner, authorGroup); + securityManager.addIdentityToSecurityGroup(owner, ownerGroup); } return item; } @@ -110,10 +110,9 @@ public class QuestionItemDAO { return sb.toString(); } - public void addAuthors(List<Identity> authors, QuestionItem item) { QuestionItemImpl lockedItem = loadForUpdate(item.getKey()); - SecurityGroup secGroup = lockedItem.getAuthorGroup(); + SecurityGroup secGroup = lockedItem.getOwnerGroup(); for(Identity author:authors) { if(!securityManager.isIdentityInSecurityGroup(author, secGroup)) { securityManager.addIdentityToSecurityGroup(author, secGroup); @@ -125,10 +124,10 @@ public class QuestionItemDAO { public int countItems(Identity me) { StringBuilder sb = new StringBuilder(); sb.append("select count(item) from questionitem item") - .append(" inner join item.authorGroup authorGroup ") - .append(" where authorGroup in (") + .append(" inner join item.ownerGroup ownerGroup ") + .append(" where ownerGroup in (") .append(" select vmember.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as vmember ") - .append(" where vmember.identity.key=:identityKey and vmember.securityGroup=authorGroup") + .append(" where vmember.identity.key=:identityKey and vmember.securityGroup=ownerGroup") .append(" )"); return dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Number.class) @@ -139,10 +138,10 @@ public class QuestionItemDAO { public List<QuestionItem> getItems(Identity me, int firstResult, int maxResults, SortKey... orderBy) { StringBuilder sb = new StringBuilder(); sb.append("select item from questionitem item") - .append(" inner join item.authorGroup authorGroup ") - .append(" where authorGroup in (") + .append(" inner join item.ownerGroup ownerGroup ") + .append(" where ownerGroup in (") .append(" select vmember.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as vmember ") - .append(" where vmember.identity.key=:identityKey and vmember.securityGroup=authorGroup") + .append(" where vmember.identity.key=:identityKey and vmember.securityGroup=ownerGroup") .append(" )"); TypedQuery<QuestionItem> query = dbInstance.getCurrentEntityManager() diff --git a/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java b/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java index aea658ec407..2bca0b4dd32 100644 --- a/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java +++ b/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.UUID; import org.apache.commons.io.IOUtils; +import org.olat.basesecurity.BaseSecurity; import org.olat.core.commons.persistence.DB; import org.olat.core.commons.persistence.SortKey; import org.olat.core.id.Identity; @@ -46,6 +47,8 @@ import org.olat.modules.qpool.QuestionItemCollection; import org.olat.modules.qpool.QuestionPoolModule; import org.olat.modules.qpool.QuestionPoolSPI; import org.olat.modules.qpool.QuestionPoolService; +import org.olat.modules.qpool.StudyField; +import org.olat.modules.qpool.model.PoolImpl; import org.olat.modules.qpool.model.QuestionItemImpl; import org.olat.resource.OLATResource; import org.springframework.beans.factory.annotation.Autowired; @@ -74,6 +77,8 @@ public class QuestionPoolServiceImpl implements QuestionPoolService { private QuestionItemDAO questionItemDao; @Autowired private QuestionPoolModule qpoolModule; + @Autowired + private BaseSecurity securityManager; @Override @@ -90,6 +95,7 @@ public class QuestionPoolServiceImpl implements QuestionPoolService { poolDao.deleteFromPools(items); questionItemDao.deleteFromShares(items); + collectionDao.deleteItemFromCollections(items); //TODO unmark questionItemDao.delete(items); } @@ -229,7 +235,7 @@ public class QuestionPoolServiceImpl implements QuestionPoolService { @Override public List<Pool> getPools(Identity identity) { - return poolDao.getPools(); + return poolDao.getPools(0, -1); } @Override @@ -318,4 +324,39 @@ public class QuestionPoolServiceImpl implements QuestionPoolService { int maxResults, SortKey... orderBy) { return collectionDao.getItemsOfCollection(collection, firstResult, maxResults, orderBy); } + + @Override + public void createPool(Identity identity, String name) { + PoolImpl pool = poolDao.createPool(name); + securityManager.addIdentityToSecurityGroup(identity, pool.getOwnerGroup()); + } + + @Override + public Pool updatePool(Pool pool) { + return poolDao.updatePool(pool); + } + + @Override + public void deletePool(Pool pool) { + poolDao.deletePool(pool); + } + + @Override + public int countPools() { + return poolDao.countPools(); + } + + @Override + public List<Pool> getPools(int firstResult, int maxResults, SortKey... orderBy) { + return poolDao.getPools(firstResult, maxResults); + } + + @Override + public List<StudyField> getStudyFields() { + return studyFieldDao.loadAllFields(); + } + + + + } diff --git a/src/main/java/org/olat/modules/qpool/manager/StudyFieldDAO.java b/src/main/java/org/olat/modules/qpool/manager/StudyFieldDAO.java index 160ce247c7b..51b55392caa 100644 --- a/src/main/java/org/olat/modules/qpool/manager/StudyFieldDAO.java +++ b/src/main/java/org/olat/modules/qpool/manager/StudyFieldDAO.java @@ -73,7 +73,8 @@ public class StudyFieldDAO { public List<StudyField> loadAllFields() { StringBuilder sb = new StringBuilder(); - sb.append("select f from qstudyfield f "); + sb.append("select f from qstudyfield f ") + .append(" left join fetch f.parentField pf"); return dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), StudyField.class) .getResultList(); diff --git a/src/main/java/org/olat/modules/qpool/model/CollectionToItem.java b/src/main/java/org/olat/modules/qpool/model/CollectionToItem.java index a48951cb3f9..065069028c9 100644 --- a/src/main/java/org/olat/modules/qpool/model/CollectionToItem.java +++ b/src/main/java/org/olat/modules/qpool/model/CollectionToItem.java @@ -35,7 +35,6 @@ import javax.persistence.TemporalType; import org.hibernate.annotations.GenericGenerator; import org.olat.core.id.CreateInfo; import org.olat.core.id.Persistable; -import org.olat.modules.qpool.QuestionItem; import org.olat.modules.qpool.QuestionItemCollection; /** @@ -66,7 +65,7 @@ public class CollectionToItem implements CreateInfo, Persistable { @ManyToOne(targetEntity=QuestionItemImpl.class,fetch=FetchType.LAZY,optional=false) @JoinColumn(name="fk_item_id", nullable=false, updatable=false) - private QuestionItem item; + private QuestionItemImpl item; @Override public Long getKey() { @@ -94,11 +93,11 @@ public class CollectionToItem implements CreateInfo, Persistable { this.collection = collection; } - public QuestionItem getItem() { + public QuestionItemImpl getItem() { return item; } - public void setItem(QuestionItem item) { + public void setItem(QuestionItemImpl item) { this.item = item; } diff --git a/src/main/java/org/olat/modules/qpool/model/PoolImpl.java b/src/main/java/org/olat/modules/qpool/model/PoolImpl.java index b9edbd99256..cff85f5ef66 100644 --- a/src/main/java/org/olat/modules/qpool/model/PoolImpl.java +++ b/src/main/java/org/olat/modules/qpool/model/PoolImpl.java @@ -23,8 +23,11 @@ import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.Table; @@ -32,6 +35,8 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.hibernate.annotations.GenericGenerator; +import org.olat.basesecurity.SecurityGroup; +import org.olat.basesecurity.SecurityGroupImpl; import org.olat.core.id.CreateInfo; import org.olat.core.id.ModifiedInfo; import org.olat.core.id.Persistable; @@ -69,6 +74,13 @@ public class PoolImpl implements Pool, CreateInfo, ModifiedInfo, Persistable { @Column(name="q_name", nullable=false, insertable=true, updatable=true) private String name; + @ManyToOne(targetEntity=SecurityGroupImpl.class,fetch=FetchType.LAZY,optional=false) + @JoinColumn(name="fk_ownergroup", nullable=false, insertable=true, updatable=false) + private SecurityGroup ownerGroup; + @ManyToOne(targetEntity=SecurityGroupImpl.class,fetch=FetchType.LAZY,optional=false) + @JoinColumn(name="fk_participantgroup", nullable=false, insertable=true, updatable=false) + private SecurityGroup participantGroup; + public Long getKey() { return key; @@ -102,6 +114,22 @@ public class PoolImpl implements Pool, CreateInfo, ModifiedInfo, Persistable { this.name = name; } + public SecurityGroup getOwnerGroup() { + return ownerGroup; + } + + public void setOwnerGroup(SecurityGroup ownerGroup) { + this.ownerGroup = ownerGroup; + } + + public SecurityGroup getParticipantGroup() { + return participantGroup; + } + + public void setParticipantGroup(SecurityGroup participantGroup) { + this.participantGroup = participantGroup; + } + @Override public int hashCode() { return key == null ? 19456 : key.hashCode(); diff --git a/src/main/java/org/olat/modules/qpool/model/QuestionItemImpl.java b/src/main/java/org/olat/modules/qpool/model/QuestionItemImpl.java index af13a894d17..c1b7735b03b 100644 --- a/src/main/java/org/olat/modules/qpool/model/QuestionItemImpl.java +++ b/src/main/java/org/olat/modules/qpool/model/QuestionItemImpl.java @@ -91,8 +91,8 @@ public class QuestionItemImpl implements QuestionItem, CreateInfo, ModifiedInfo, @Column(name="q_copyright", nullable=true, insertable=true, updatable=true) private String copyright; @ManyToOne(targetEntity=SecurityGroupImpl.class,fetch=FetchType.LAZY,optional=false) - @JoinColumn(name="fk_author_grp_id", nullable=false, insertable=true, updatable=false) - private SecurityGroup authorGroup; + @JoinColumn(name="fk_ownergroup", nullable=false, insertable=true, updatable=false) + private SecurityGroup ownerGroup; //usage @Column(name="q_point", nullable=true, insertable=true, updatable=true) @@ -137,7 +137,6 @@ public class QuestionItemImpl implements QuestionItem, CreateInfo, ModifiedInfo, this.key = key; } - @Override public String getUuid() { return uuid; } @@ -146,17 +145,14 @@ public class QuestionItemImpl implements QuestionItem, CreateInfo, ModifiedInfo, this.uuid = uuid; } - @Override public String getResourceableTypeName() { return "QuestionItem"; } - @Override public Long getResourceableId() { return getKey(); } - @Override public Date getCreationDate() { return creationDate; } @@ -262,7 +258,6 @@ public class QuestionItemImpl implements QuestionItem, CreateInfo, ModifiedInfo, this.selectivity = selectivity; } - @Override @Transient public QuestionStatus getQuestionStatus() { if(StringHelper.containsNonWhitespace(status)) { @@ -287,12 +282,12 @@ public class QuestionItemImpl implements QuestionItem, CreateInfo, ModifiedInfo, this.copyright = copyright; } - public SecurityGroup getAuthorGroup() { - return authorGroup; + public SecurityGroup getOwnerGroup() { + return ownerGroup; } - public void setAuthorGroup(SecurityGroup authorGroup) { - this.authorGroup = authorGroup; + public void setOwnerGroup(SecurityGroup ownerGroup) { + this.ownerGroup = ownerGroup; } public BigDecimal getDifficulty() { diff --git a/src/main/java/org/olat/modules/qpool/ui/CreateCollectionController.java b/src/main/java/org/olat/modules/qpool/ui/CreateCollectionController.java index 167cccc2223..c121bbcc1d8 100644 --- a/src/main/java/org/olat/modules/qpool/ui/CreateCollectionController.java +++ b/src/main/java/org/olat/modules/qpool/ui/CreateCollectionController.java @@ -83,7 +83,7 @@ public class CreateCollectionController extends FormBasicController { String name = nameEl.getValue(); nameEl.clearError(); if(!StringHelper.containsNonWhitespace(name)) { - nameEl.setErrorKey("", null); + nameEl.setErrorKey("form.mandatory.hover", null); } return allOk && super.validateFormLogic(ureq); diff --git a/src/main/java/org/olat/modules/qpool/ui/FilePreviewController.java b/src/main/java/org/olat/modules/qpool/ui/FilePreviewController.java new file mode 100644 index 00000000000..4639bbd3691 --- /dev/null +++ b/src/main/java/org/olat/modules/qpool/ui/FilePreviewController.java @@ -0,0 +1,65 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.modules.qpool.ui; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.util.vfs.VFSLeaf; +import org.olat.modules.qpool.QuestionItem; +import org.olat.modules.qpool.QuestionPoolService; + +/** + * + * Initial date: 27.02.2013<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class FilePreviewController extends BasicController { + + private final VelocityContainer mainVC; + + public FilePreviewController(UserRequest ureq, WindowControl wControl, QuestionItem qitem) { + super(ureq, wControl); + QuestionPoolService qpoolService = CoreSpringFactory.getImpl(QuestionPoolService.class); + mainVC = createVelocityContainer("file_preview"); + + VFSLeaf leaf = qpoolService.getRootFile(qitem); + if(leaf != null) { + mainVC.contextPut("filename", leaf.getName()); + } + + putInitialPanel(mainVC); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + // + } +} diff --git a/src/main/java/org/olat/modules/qpool/ui/PoolDataModel.java b/src/main/java/org/olat/modules/qpool/ui/PoolDataModel.java new file mode 100644 index 00000000000..53687914abc --- /dev/null +++ b/src/main/java/org/olat/modules/qpool/ui/PoolDataModel.java @@ -0,0 +1,130 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.modules.qpool.ui; + +import java.util.ArrayList; +import java.util.List; + +import org.olat.core.commons.persistence.SortKey; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModel; +import org.olat.core.gui.components.table.TableDataModel; +import org.olat.core.gui.translator.Translator; +import org.olat.modules.qpool.ui.PoolsAdminController.PoolSource; + +/** + * + * Initial date: 23.01.2013<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class PoolDataModel implements FlexiTableDataModel, TableDataModel<PoolRow> { + + private List<PoolRow> rows; + private PoolSource source; + private FlexiTableColumnModel columnModel; + private final Translator translator; + + public PoolDataModel(FlexiTableColumnModel columnModel, PoolSource source, Translator translator) { + this.columnModel = columnModel; + this.translator = translator; + this.source = source; + } + + @Override + public FlexiTableColumnModel getTableColumnModel() { + return columnModel; + } + + @Override + public void setTableColumnModel(FlexiTableColumnModel tableColumnModel) { + this.columnModel = tableColumnModel; + } + + @Override + public int getRowCount() { + return source.getNumOfItems(); + } + + @Override + public PoolRow getObject(int row) { + return rows.get(row); + } + + @Override + public void setObjects(List<PoolRow> objects) { + rows = new ArrayList<PoolRow>(objects); + } + + @Override + public void load(int firstResult, int maxResults, SortKey... orderBy) { + if(rows == null) { + rows = new ArrayList<PoolRow>(); + } + + for(int i=rows.size(); i<firstResult; i++) { + rows.add(null); + } + List<PoolRow> newRows = source.getRows(firstResult, maxResults, orderBy); + for(int i=0; i<newRows.size(); i++) { + int rowIndex = i + firstResult; + if(rowIndex < rows.size()) { + rows.set(rowIndex, newRows.get(i)); + } else { + rows.add(newRows.get(i)); + } + } + } + + @Override + public int getColumnCount() { + return columnModel.getColumnCount(); + } + + @Override + public PoolDataModel createCopyWithEmptyList() { + return new PoolDataModel(columnModel, source, translator); + } + + @Override + public Object getValueAt(int row, int col) { + PoolRow item = getObject(row); + switch(Cols.values()[col]) { + case id: return item.getKey(); + case name: return item.getName(); + default: return ""; + } + } + + public enum Cols { + id("pool.key"), + name("pool.name"); + + private final String i18nKey; + + private Cols(String i18nKey) { + this.i18nKey = i18nKey; + } + + public String i18nKey() { + return i18nKey; + } + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/modules/qpool/ui/PoolEditController.java b/src/main/java/org/olat/modules/qpool/ui/PoolEditController.java new file mode 100644 index 00000000000..2f9573695b2 --- /dev/null +++ b/src/main/java/org/olat/modules/qpool/ui/PoolEditController.java @@ -0,0 +1,97 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.modules.qpool.ui; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.TextElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.util.StringHelper; +import org.olat.modules.qpool.Pool; + +/** + * + * Initial date: 21.02.2013<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class PoolEditController extends FormBasicController { + + private TextElement nameEl; + private final Pool pool; + + public PoolEditController(UserRequest ureq, WindowControl wControl, Pool pool) { + super(ureq, wControl); + this.pool = pool; + initForm(ureq); + } + + public Pool getPool() { + return pool; + } + + public String getName() { + return nameEl.getValue(); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + String name = pool == null ? "" : pool.getName(); + nameEl = uifactory.addTextElement("pool.name", "pool.name", 128, name, formLayout); + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + buttonsCont.setRootForm(mainForm); + formLayout.add(buttonsCont); + uifactory.addFormSubmitButton("ok", "ok", buttonsCont); + uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl()); + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = true; + + nameEl.clearError(); + if(!StringHelper.containsNonWhitespace(nameEl.getValue())) { + nameEl.setErrorKey("form.mandatory.hover", null); + allOk = false; + } + + return allOk && super.validateFormLogic(ureq); + } + + @Override + protected void formOK(UserRequest ureq) { + fireEvent(ureq, Event.DONE_EVENT); + } + + @Override + protected void formCancelled(UserRequest ureq) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } +} diff --git a/src/main/java/org/olat/modules/qpool/ui/PoolRow.java b/src/main/java/org/olat/modules/qpool/ui/PoolRow.java new file mode 100644 index 00000000000..c77df18698a --- /dev/null +++ b/src/main/java/org/olat/modules/qpool/ui/PoolRow.java @@ -0,0 +1,49 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.modules.qpool.ui; + +import org.olat.modules.qpool.Pool; + +/** + * + * Initial date: 28.02.2013<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class PoolRow { + + private final Pool pool; + + public PoolRow(Pool pool) { + this.pool = pool; + } + + public Long getKey() { + return pool.getKey(); + } + + public String getName() { + return pool.getName(); + } + + public Pool getPool() { + return pool; + } +} diff --git a/src/main/java/org/olat/modules/qpool/ui/PoolsAdminController.java b/src/main/java/org/olat/modules/qpool/ui/PoolsAdminController.java new file mode 100644 index 00000000000..4bc368e2327 --- /dev/null +++ b/src/main/java/org/olat/modules/qpool/ui/PoolsAdminController.java @@ -0,0 +1,207 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.modules.qpool.ui; + +import java.util.ArrayList; +import java.util.List; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.commons.persistence.SortKey; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement; +import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableRendererType; +import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; +import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; +import org.olat.core.gui.control.generic.modal.DialogBoxController; +import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory; +import org.olat.modules.qpool.Pool; +import org.olat.modules.qpool.QuestionPoolService; +import org.olat.modules.qpool.ui.PoolDataModel.Cols; + +/** + * + * Initial date: 21.02.2013<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class PoolsAdminController extends FormBasicController { + + private FormLink createPool; + + private PoolDataModel model; + private FlexiTableElement poolTable; + private CloseableModalController cmc; + private PoolEditController poolEditCtrl; + private DialogBoxController confirmDeleteCtrl; + + private final QuestionPoolService qpoolService; + + public PoolsAdminController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl, "pools_admin"); + qpoolService = CoreSpringFactory.getImpl(QuestionPoolService.class); + initForm(ureq); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + //add the table + FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.id.i18nKey(), Cols.id.ordinal(), true, "key")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.name.i18nKey(), Cols.name.ordinal(), true, "name")); + columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("edit", translate("edit"), "edit-pool")); + columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("delete", translate("delete"), "delete-pool")); + + model = new PoolDataModel(columnsModel, new PoolSource(), getTranslator()); + poolTable = uifactory.addTableElement(ureq, "pools", model, 20, getTranslator(), formLayout); + poolTable.setRendererType(FlexiTableRendererType.classic); + + createPool = uifactory.addFormLink("create.pool", formLayout, Link.BUTTON); + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(source == createPool) { + doEditPool(ureq, null); + } else if(source == poolTable) { + if(event instanceof SelectionEvent) { + SelectionEvent se = (SelectionEvent)event; + if("edit-pool".equals(se.getCommand())) { + PoolRow row = model.getObject(se.getIndex()); + doEditPool(ureq, row.getPool()); + } else if("delete-pool".equals(se.getCommand())) { + PoolRow row = model.getObject(se.getIndex()); + doConfirmDelete(ureq, row.getPool()); + } + } + } + super.formInnerEvent(ureq, source, event); + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if(source == poolEditCtrl) { + if(event == Event.DONE_EVENT) { + Pool pool = poolEditCtrl.getPool(); + if(pool == null) { + doCreate(ureq, poolEditCtrl.getName()); + } else { + doEdit(ureq, pool, poolEditCtrl.getName()); + } + } + cmc.deactivate(); + cleanUp(); + } else if(source == confirmDeleteCtrl) { + if(DialogBoxUIFactory.isOkEvent(event) || DialogBoxUIFactory.isYesEvent(event)) { + Pool pool = (Pool)confirmDeleteCtrl.getUserObject(); + doDelete(ureq, pool); + } + } else if(source == cmc) { + cleanUp(); + } + } + + private void cleanUp() { + removeAsListenerAndDispose(poolEditCtrl); + removeAsListenerAndDispose(cmc); + poolEditCtrl = null; + cmc = null; + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + private void doConfirmDelete(UserRequest ureq, Pool pool) { + String title = translate("delete.pool"); + String text = translate("delete.pool.confirm", new String[]{ pool.getName() }); + confirmDeleteCtrl = activateOkCancelDialog(ureq, title, text, confirmDeleteCtrl); + confirmDeleteCtrl.setUserObject(pool); + } + + private void doDelete(UserRequest ureq, Pool pool) { + qpoolService.deletePool(pool); + poolTable.reset(); + fireEvent(ureq, new QPoolEvent(QPoolEvent.POOL_DELETED)); + } + + private void doEditPool(UserRequest ureq, Pool pool) { + removeAsListenerAndDispose(poolEditCtrl); + poolEditCtrl = new PoolEditController(ureq, getWindowControl(), pool); + listenTo(poolEditCtrl); + + cmc = new CloseableModalController(getWindowControl(), translate("close"), + poolEditCtrl.getInitialComponent(), true, translate("edit.pool")); + cmc.activate(); + listenTo(cmc); + } + + private void doCreate(UserRequest ureq, String name) { + qpoolService.createPool(getIdentity(), name); + poolTable.reset(); + fireEvent(ureq, new QPoolEvent(QPoolEvent.POOL_CREATED)); + } + + private void doEdit(UserRequest ureq, Pool pool, String name) { + pool.setName(name); + qpoolService.updatePool(pool); + poolTable.reset(); + fireEvent(ureq, new QPoolEvent(QPoolEvent.POOL_CREATED)); + } + + private PoolRow forgeRow(Pool pool) { + PoolRow row = new PoolRow(pool); + return row; + } + + public class PoolSource { + + public int getNumOfItems() { + return qpoolService.countPools(); + } + + public List<PoolRow> getRows(int firstResult, int maxResults, SortKey... orderBy) { + List<Pool> pools = qpoolService.getPools(firstResult, maxResults, orderBy); + List<PoolRow> rows = new ArrayList<PoolRow>(pools.size()); + for(Pool pool:pools) { + rows.add(forgeRow(pool)); + } + return rows; + } + } +} diff --git a/src/main/java/org/olat/modules/qpool/ui/QPoolEvent.java b/src/main/java/org/olat/modules/qpool/ui/QPoolEvent.java index 0145449f447..5210cb3e970 100644 --- a/src/main/java/org/olat/modules/qpool/ui/QPoolEvent.java +++ b/src/main/java/org/olat/modules/qpool/ui/QPoolEvent.java @@ -35,6 +35,8 @@ public class QPoolEvent extends MultiUserEvent { public static final String ITEM_MARKED = "qpool-item-marked"; public static final String ITEM_DELETED = "qpool-item-deleted"; public static final String COLL_CREATED = "qpool-coll-created"; + public static final String POOL_CREATED = "qpool-pool-created"; + public static final String POOL_DELETED = "qpool-pool-deleted"; public QPoolEvent(String cmd) { diff --git a/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java b/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java index 8ca712cdce2..4dd7623d3ef 100644 --- a/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java +++ b/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java @@ -57,7 +57,7 @@ import org.olat.modules.qpool.QuestionPoolService; public class QuestionPoolMainEditorController extends BasicController implements Activateable2, StackedControllerAware { private final MenuTree menuTree; - private GenericTreeNode sharesNode, myNode; + private GenericTreeNode sharesNode, myNode, poolNode; private final Panel content; private StackedController stackPanel; @@ -68,6 +68,8 @@ public class QuestionPoolMainEditorController extends BasicController implements private QuestionsController collItemsCtrl; private QuestionsController selectedPoolCtrl; private QuestionsController markedQuestionsCtrl; + + private PoolsAdminController poolAdminCtrl; private StudyFieldAdminController studyFieldCtrl; private LayoutMain3ColsController columnLayoutCtr; private QuestionPoolAdminStatisticsController adminStatisticsCtrl; @@ -123,6 +125,8 @@ public class QuestionPoolMainEditorController extends BasicController implements doSelectAdmin(ureq); } else if("menu.admin.studyfields".equals(uNode)) { doSelectAdminStudyFields(ureq); + } else if("menu.admin.pools".equals(uNode)) { + doSelectAdminPools(ureq); } else if("menu.database.my".equals(uNode)) { doSelectMyQuestions(ureq); } else if("menu.database.favorit".equals(uNode)) { @@ -150,6 +154,10 @@ public class QuestionPoolMainEditorController extends BasicController implements } else if(QPoolEvent.COLL_CREATED.equals(event.getCommand())) { buildMySubTreeModel(myNode); menuTree.setDirty(true); + } else if(QPoolEvent.POOL_CREATED.equals(event.getCommand()) + || QPoolEvent.POOL_DELETED.equals(event.getCommand())) { + buildPoolSubTreeModel(poolNode); + menuTree.setDirty(true); } } super.event(ureq, source, event); @@ -205,6 +213,14 @@ public class QuestionPoolMainEditorController extends BasicController implements content.setContent(studyFieldCtrl.getInitialComponent()); } + private void doSelectAdminPools(UserRequest ureq) { + if(poolAdminCtrl == null) { + poolAdminCtrl = new PoolsAdminController(ureq, getWindowControl()); + listenTo(poolAdminCtrl); + } + content.setContent(poolAdminCtrl.getInitialComponent()); + } + private void doSelectMyQuestions(UserRequest ureq) { if(myQuestionsCtrl == null) { myQuestionsCtrl = new QuestionsController(ureq, getWindowControl(), new MyQuestionItemsSource(getIdentity())); @@ -277,16 +293,11 @@ public class QuestionPoolMainEditorController extends BasicController implements //pools - GenericTreeNode poolNode = new GenericTreeNode(translate("menu.pools"), "menu.pools.alt"); + poolNode = new GenericTreeNode(translate("menu.pools"), "menu.pools.alt"); poolNode.setCssClass("o_sel_qpool_pools"); rootNode.addChild(poolNode); - List<Pool> pools = qpoolService.getPools(getIdentity()); - for(Pool pool:pools) { - GenericTreeNode node = new GenericTreeNode(pool.getName(), pool); - node.setIconCssClass("o_sel_qpool_pool"); - poolNode.addChild(node); - } + buildPoolSubTreeModel(poolNode); //shares sharesNode = new GenericTreeNode(translate("menu.share"), "menu.share"); @@ -298,12 +309,32 @@ public class QuestionPoolMainEditorController extends BasicController implements GenericTreeNode adminNode = new GenericTreeNode(translate("menu.admin"), "menu.admin"); adminNode.setCssClass("o_sel_qpool_admin"); rootNode.addChild(adminNode); + buildAdminSubTreeModel(adminNode); + + return gtm; + } + + private void buildPoolSubTreeModel(GenericTreeNode poolNode) { + poolNode.removeAllChildren(); + + List<Pool> pools = qpoolService.getPools(getIdentity()); + for(Pool pool:pools) { + GenericTreeNode node = new GenericTreeNode(pool.getName(), pool); + node.setIconCssClass("o_sel_qpool_pool"); + poolNode.addChild(node); + } + } + + private void buildAdminSubTreeModel(GenericTreeNode adminNode) { + adminNode.removeAllChildren(); GenericTreeNode node = new GenericTreeNode(translate("menu.admin.studyfields"), "menu.admin.studyfields"); node.setIconCssClass("o_sel_qpool_study_fields"); adminNode.addChild(node); - - return gtm; + + node = new GenericTreeNode(translate("menu.admin.pools"), "menu.admin.pools"); + node.setIconCssClass("o_sel_qpool_study_pools"); + adminNode.addChild(node); } private void buildMySubTreeModel(GenericTreeNode myNode) { diff --git a/src/main/java/org/olat/modules/qpool/ui/StudyFieldAdminController.java b/src/main/java/org/olat/modules/qpool/ui/StudyFieldAdminController.java index 18f84826d36..3abdc2b49fc 100644 --- a/src/main/java/org/olat/modules/qpool/ui/StudyFieldAdminController.java +++ b/src/main/java/org/olat/modules/qpool/ui/StudyFieldAdminController.java @@ -21,6 +21,7 @@ package org.olat.modules.qpool.ui; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.tree.MenuTree; import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; @@ -34,12 +35,26 @@ import org.olat.core.gui.control.controller.BasicController; */ public class StudyFieldAdminController extends BasicController { + private final MenuTree studyFieldTree; + private final StudyFieldTreeModel studyFieldTreeModel; + + private final VelocityContainer mainVC; public StudyFieldAdminController(UserRequest ureq, WindowControl wControl) { super(ureq, wControl); mainVC = createVelocityContainer("admin_study_fields"); + + studyFieldTree = new MenuTree("qpoolTree"); + studyFieldTreeModel = new StudyFieldTreeModel(); + studyFieldTree.setTreeModel(studyFieldTreeModel); + studyFieldTree.setSelectedNode(studyFieldTree.getTreeModel().getRootNode()); + studyFieldTree.setDropEnabled(false); + studyFieldTree.addListener(this); + studyFieldTree.setRootVisible(false); + + mainVC.put("tree", studyFieldTree); putInitialPanel(mainVC); } diff --git a/src/main/java/org/olat/modules/qpool/ui/StudyFieldTreeModel.java b/src/main/java/org/olat/modules/qpool/ui/StudyFieldTreeModel.java new file mode 100644 index 00000000000..00fc4993911 --- /dev/null +++ b/src/main/java/org/olat/modules/qpool/ui/StudyFieldTreeModel.java @@ -0,0 +1,78 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.modules.qpool.ui; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.gui.components.tree.GenericTreeModel; +import org.olat.core.gui.components.tree.GenericTreeNode; +import org.olat.modules.qpool.QuestionPoolService; +import org.olat.modules.qpool.StudyField; + +/** + * + * Initial date: 28.02.2013<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class StudyFieldTreeModel extends GenericTreeModel { + + private static final long serialVersionUID = 3032222581990406868L; + private QuestionPoolService qpoolService; + + public StudyFieldTreeModel() { + qpoolService = CoreSpringFactory.getImpl(QuestionPoolService.class); + + buildTree(); + } + + private void buildTree() { + GenericTreeNode rootNode = new GenericTreeNode("root", "root"); + setRootNode(rootNode); + + List<StudyField> fields = qpoolService.getStudyFields(); + Map<Long,GenericTreeNode> fieldKeyToNode = new HashMap<Long, GenericTreeNode>(); + for(StudyField field:fields) { + Long key = field.getKey(); + GenericTreeNode node = fieldKeyToNode.get(key); + if(node == null) { + node = new GenericTreeNode(field.getField(), field); + fieldKeyToNode.put(key, node); + } + + StudyField parentField = field.getParentField(); + if(parentField == null) { + //this is a root + rootNode.addChild(node); + } else { + Long parentKey = parentField.getKey(); + GenericTreeNode parentNode = fieldKeyToNode.get(parentKey); + if(parentNode == null) { + parentNode = new GenericTreeNode(parentField.getField(), parentField); + fieldKeyToNode.put(key, parentNode); + } + parentNode.addChild(node); + } + } + } +} diff --git a/src/main/java/org/olat/modules/qpool/ui/TextPreviewController.java b/src/main/java/org/olat/modules/qpool/ui/TextPreviewController.java new file mode 100644 index 00000000000..58588092554 --- /dev/null +++ b/src/main/java/org/olat/modules/qpool/ui/TextPreviewController.java @@ -0,0 +1,98 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.modules.qpool.ui; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringWriter; + +import org.apache.commons.io.IOUtils; +import org.olat.core.CoreSpringFactory; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.util.vfs.VFSLeaf; +import org.olat.modules.qpool.QuestionItem; +import org.olat.modules.qpool.QuestionPoolService; + +/** + * + * Initial date: 27.02.2013<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class TextPreviewController extends BasicController { + + private final VelocityContainer mainVC; + private final QuestionPoolService qpoolService; + + public TextPreviewController(UserRequest ureq, WindowControl wControl, QuestionItem qitem) { + super(ureq, wControl); + qpoolService = CoreSpringFactory.getImpl(QuestionPoolService.class); + mainVC = createVelocityContainer("text_preview"); + + VFSLeaf leaf = qpoolService.getRootFile(qitem); + if(leaf == null) { + //no data to preview + } else { + String txt = readSummary(leaf); + mainVC.contextPut("text", txt); + } + putInitialPanel(mainVC); + } + + @Override + protected void doDispose() { + // + } + + protected String readSummary(VFSLeaf leaf) { + StringWriter out = new StringWriter(); + InputStream in = leaf.getInputStream(); + InputStreamReader inr = new InputStreamReader(in); + try { + char[] buffer = new char[4096]; + + int count = 0; + int n = 0; + while (-1 != (n = inr.read(buffer))) { + out.write(buffer, 0, n); + count += n; + if(count >= 10000) { + break; + } + } + } catch (Exception e) { + logError("", e); + } finally { + IOUtils.closeQuietly(inr); + IOUtils.closeQuietly(in); + } + return out.toString(); + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + // + } +} diff --git a/src/main/java/org/olat/modules/qpool/ui/_content/admin_study_fields.html b/src/main/java/org/olat/modules/qpool/ui/_content/admin_study_fields.html index 06c9c2558fd..18c5abd0ca5 100644 --- a/src/main/java/org/olat/modules/qpool/ui/_content/admin_study_fields.html +++ b/src/main/java/org/olat/modules/qpool/ui/_content/admin_study_fields.html @@ -1,4 +1,6 @@ <fieldset> <legend>$r.translate("menu.admin.studyfields")</legend> + + $r.render("tree") </fieldset> \ No newline at end of file diff --git a/src/main/java/org/olat/modules/qpool/ui/_content/file_preview.html b/src/main/java/org/olat/modules/qpool/ui/_content/file_preview.html new file mode 100644 index 00000000000..0a9ab81ff41 --- /dev/null +++ b/src/main/java/org/olat/modules/qpool/ui/_content/file_preview.html @@ -0,0 +1 @@ +$filename \ No newline at end of file diff --git a/src/main/java/org/olat/modules/qpool/ui/_content/pools_admin.html b/src/main/java/org/olat/modules/qpool/ui/_content/pools_admin.html new file mode 100644 index 00000000000..8997df0ef41 --- /dev/null +++ b/src/main/java/org/olat/modules/qpool/ui/_content/pools_admin.html @@ -0,0 +1,14 @@ +<fieldset> + <legend>$r.translate("menu.admin.pools")</legend> + $r.render("pools") + <div class="b_clearfix o_qpool_button_bar_box"> + <div class="o_qpool_button_bar"> + $r.render("create.pool") + </div> + </div> +</fieldset> + + + + + diff --git a/src/main/java/org/olat/modules/qpool/ui/_content/text_preview.html b/src/main/java/org/olat/modules/qpool/ui/_content/text_preview.html new file mode 100644 index 00000000000..9427842596c --- /dev/null +++ b/src/main/java/org/olat/modules/qpool/ui/_content/text_preview.html @@ -0,0 +1 @@ +$text \ No newline at end of file diff --git a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties index ae0b8e6fb11..b1dbd43b552 100644 --- a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties @@ -20,6 +20,7 @@ menu.pools=Pool menu.pools.alt=Pool menu.pools.main=Katalog menu.pools.main.alt=Katalog +menu.admin.pools=Pools Verwaltung menu.share=Freigaben metadatas=Metadaten item.copyright=Copyright @@ -46,6 +47,12 @@ item.shared=Frage {0} wurde freigegeben. item.pooled=Frage {0} wurde im Pool hinzugefügt. item.deleted=Frage wurde gelöscht. item.collectioned=Frage {0} wurde in der Liste hinzugefügt. +pool.key=ID +pool.name=Name +create.pool=Pool erstellen +delete.pool=Pool löschen +delete.pool.confirm=Wollen Sie wirklich diesen Pool "{0}" löschen? +edit.pool=Pool editieren inWork=In Bearbeitung inReview=In Review used=Verwendet diff --git a/src/main/java/org/olat/search/SearchService.java b/src/main/java/org/olat/search/SearchService.java index f6a24578eed..f1b279c9082 100644 --- a/src/main/java/org/olat/search/SearchService.java +++ b/src/main/java/org/olat/search/SearchService.java @@ -49,7 +49,9 @@ public interface SearchService { * @param doHighlighting Highlights founded text fragements in result * @return Search result for queury */ - public SearchResults doSearch(String queryString, List<String> condQueries, Identity identity, Roles roles, int firstResult, int maxReturns, boolean doHighlighting) throws ServiceNotAvailableException, ParseException, QueryException; + public SearchResults doSearch(String queryString, List<String> condQueries, Identity identity, Roles roles, + int firstResult, int maxReturns, boolean doHighlighting) + throws ServiceNotAvailableException, ParseException, QueryException; /** * Check a query for similar words. diff --git a/src/main/java/org/olat/search/service/SearchServiceImpl.java b/src/main/java/org/olat/search/service/SearchServiceImpl.java index 63a85970c9b..cd8696af6ef 100644 --- a/src/main/java/org/olat/search/service/SearchServiceImpl.java +++ b/src/main/java/org/olat/search/service/SearchServiceImpl.java @@ -187,7 +187,9 @@ public class SearchServiceImpl implements SearchService { * @return SearchResults object for this query */ @Override - public SearchResults doSearch(String queryString, List<String> condQueries, Identity identity, Roles roles, int firstResult, int maxResults, boolean doHighlighting) throws ServiceNotAvailableException, ParseException { + public SearchResults doSearch(String queryString, List<String> condQueries, Identity identity, Roles roles, + int firstResult, int maxResults, boolean doHighlighting) + throws ServiceNotAvailableException, ParseException { try { if (!existIndex()) { log.warn("Index does not exist, can't search for queryString: "+queryString); @@ -213,7 +215,6 @@ public class SearchServiceImpl implements SearchService { query.add(condQuery, Occur.MUST); } } - if (log.isDebug()) log.debug("query=" + query); long startTime = System.currentTimeMillis(); diff --git a/src/main/java/org/olat/search/service/indexer/QuestionItemIndexer.java b/src/main/java/org/olat/search/service/indexer/QuestionItemIndexer.java index 4150f38d5e5..f1a80bcffe7 100644 --- a/src/main/java/org/olat/search/service/indexer/QuestionItemIndexer.java +++ b/src/main/java/org/olat/search/service/indexer/QuestionItemIndexer.java @@ -1,3 +1,22 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ package org.olat.search.service.indexer; import java.io.IOException; diff --git a/src/main/resources/database/mysql/alter_8_4_0_to_9_0_0.sql b/src/main/resources/database/mysql/alter_8_4_0_to_9_0_0.sql index 308df5e13cb..a56993ae711 100644 --- a/src/main/resources/database/mysql/alter_8_4_0_to_9_0_0.sql +++ b/src/main/resources/database/mysql/alter_8_4_0_to_9_0_0.sql @@ -12,6 +12,8 @@ create table if not exists o_qp_pool ( creationdate datetime not null, lastmodified datetime not null, q_name varchar(255) not null, + fk_ownergroup bigint, + fk_participantgroup bigint, primary key (id) ); @@ -48,7 +50,7 @@ create table if not exists o_qp_item ( q_dir varchar(32), q_root_filename varchar(255), fk_study_field bigint, - fk_author_grp_id bigint, + fk_ownergroup bigint, primary key (id) ); @@ -85,6 +87,10 @@ create table if not exists o_qp_collection_2_item ( primary key (id) ); + +alter table o_qp_pool add constraint idx_qp_pool_owner_grp_id foreign key (fk_ownergroup) references o_bs_secgroup(id); +alter table o_qp_pool add constraint idx_qp_pool_part_grp_id foreign key (fk_participantgroup) references o_bs_secgroup(id); + alter table o_qp_pool_2_item add constraint idx_qp_pool_2_item_pool_id foreign key (fk_pool_id) references o_qp_pool(id); alter table o_qp_pool_2_item add constraint idx_qp_pool_2_item_item_id foreign key (fk_item_id) references o_qp_item(id); alter table o_qp_pool_2_item add unique (fk_pool_id, fk_item_id); @@ -100,7 +106,7 @@ alter table o_qp_collection_2_item add constraint idx_qp_coll_item_id foreign ke alter table o_qp_collection_2_item add unique (fk_collection_id, fk_item_id); alter table o_qp_item add constraint idx_qp_pool_2_field_id foreign key (fk_study_field) references o_qp_study_field(id); -alter table o_qp_item add constraint idx_qp_item_author_grp_id foreign key (fk_author_grp_id) references o_bs_secgroup(id); +alter table o_qp_item add constraint idx_qp_item_owner_id foreign key (fk_ownergroup) references o_bs_secgroup(id); alter table o_qp_study_field add constraint idx_qp_field_2_parent_id foreign key (fk_parent_field) references o_qp_study_field(id); diff --git a/src/test/java/org/olat/modules/ims/qti/fileresource/FileResourceValidatorTest.java b/src/test/java/org/olat/modules/ims/qti/fileresource/FileResourceValidatorTest.java index c28b7e1eb55..9e2585c8dca 100644 --- a/src/test/java/org/olat/modules/ims/qti/fileresource/FileResourceValidatorTest.java +++ b/src/test/java/org/olat/modules/ims/qti/fileresource/FileResourceValidatorTest.java @@ -1,3 +1,22 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ package org.olat.modules.ims.qti.fileresource; import static org.junit.Assert.assertNotNull; diff --git a/src/test/java/org/olat/modules/qpool/manager/PoolDAOTest.java b/src/test/java/org/olat/modules/qpool/manager/PoolDAOTest.java index 72f243c78ab..210f92d2e34 100644 --- a/src/test/java/org/olat/modules/qpool/manager/PoolDAOTest.java +++ b/src/test/java/org/olat/modules/qpool/manager/PoolDAOTest.java @@ -70,7 +70,7 @@ public class PoolDAOTest extends OlatTestCase { dbInstance.commitAndCloseSession(); //get pools - List<Pool> pools = poolDao.getPools(); + List<Pool> pools = poolDao.getPools(0, -1); Assert.assertNotNull(pools); Assert.assertTrue(pools.size() >= 1); int numOfPools = poolDao.getNumOfPools(); -- GitLab