diff --git a/src/main/java/org/olat/repository/CatalogEntry.java b/src/main/java/org/olat/repository/CatalogEntry.java index c4c8ce21c83ce283bb759f662e310aad9f0abac0..0760c0c9e4ab55607b6784bf2de9ca0589316d8d 100644 --- a/src/main/java/org/olat/repository/CatalogEntry.java +++ b/src/main/java/org/olat/repository/CatalogEntry.java @@ -169,10 +169,24 @@ public interface CatalogEntry extends CatalogEntryRef, CreateInfo, Persistable, /** * get position of entry * - * @return + * @return Integer */ public Integer getPosition(); + /** + * get short title + * + * @return String + */ + public String getShortTitle(); + + /** + * set short title + * + * @param shortTitle + */ + public void setShortTitle(String shortTitle); + public enum OrderBy { name, diff --git a/src/main/java/org/olat/repository/RepositoryModule.java b/src/main/java/org/olat/repository/RepositoryModule.java index 6cffc38f960262d5cf24d6309e24df5278dc0d83..f40ed446bdd3a6d0de7483fddee7caa44af88bb7 100644 --- a/src/main/java/org/olat/repository/RepositoryModule.java +++ b/src/main/java/org/olat/repository/RepositoryModule.java @@ -19,11 +19,11 @@ */ package org.olat.repository; +import org.apache.logging.log4j.Logger; import org.olat.NewControllerFactory; import org.olat.core.configuration.AbstractSpringModule; import org.olat.core.id.Roles; import org.olat.core.id.context.SiteContextEntryControllerCreator; -import org.apache.logging.log4j.Logger; import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; import org.olat.core.util.coordinate.CoordinatorManager; @@ -55,6 +55,7 @@ public class RepositoryModule extends AbstractSpringModule { private static final String CATALOG_SITE_ENABLED = "site.catalog.enable"; private static final String CATALOG_ENABLED = "catalog.enable"; private static final String CATALOG_BROWSING_ENABLED = "catalog.brwosing.enable"; + private static final String CATALOG_ADD_AT_LAST = "catalog.add.last"; private static final String MYCOURSES_SEARCH_ENABLED = "mycourses.search.enabled"; private static final String MYCOURSES_ALL_RESOURCES_ENABLED = "mycourses.all.resources.enabled"; @@ -75,6 +76,8 @@ public class RepositoryModule extends AbstractSpringModule { private boolean catalogEnabled; @Value("${repo.catalog.browsing.enable}") private boolean catalogBrowsingEnabled; + @Value("${catalog.add.last:true}") + private boolean catalogAddLast; @Value("${repo.managed}") private boolean managedRepositoryEntries; @@ -208,6 +211,11 @@ public class RepositoryModule extends AbstractSpringModule { if(StringHelper.containsNonWhitespace(taxonomyTreeKeyObj)) { taxonomyTreeKey = taxonomyTreeKeyObj; } + + String catalogAddLastObj = getStringPropertyValue(CATALOG_ADD_AT_LAST, true); + if(StringHelper.containsNonWhitespace(taxonomyTreeKeyObj)) { + catalogAddLast = "true".equals(catalogAddLastObj); + } } /** @@ -270,6 +278,15 @@ public class RepositoryModule extends AbstractSpringModule { catalogBrowsingEnabled = enabled; setStringProperty(CATALOG_BROWSING_ENABLED, Boolean.toString(enabled), true); } + + public boolean isCatalogAddAtLast() { + return catalogAddLast; + } + + public void setCatalogAddAtLast(boolean addAtLast) { + catalogAddLast = addAtLast; + setStringProperty(CATALOG_ADD_AT_LAST, Boolean.toString(addAtLast), true); + } public boolean isMyCoursesSearchEnabled() { return myCoursesSearchEnabled; diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties index 02fff67d7e549c3daa2c621c7b1ad238f0e35a26..7a255f8e03b0a677dd1dd9b8e07db44474b8d4a0 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties @@ -459,7 +459,7 @@ orderby.author=Dozent orderby.automatic=Automatisch orderby.creationDate=Erstellungsdatum orderby.completion=$org.olat.modules.assessment.ui\:learning.progress -orderby.custom=Vorsortiert +orderby.custom=Geordnet orderby.favorit=Favorit orderby.lastModified=Zuletzt ge\u00E4ndert orderby.lastVisited=Zuletzt besucht diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties index a568be07f410012c2437b1b1ce78dfda8d15c48d..94eec8732324abf7fe1356101dc9a540b1a60935 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties @@ -459,7 +459,7 @@ orderby.author=Author orderby.automatic=Automatic orderby.completion=$org.olat.modules.assessment.ui\:learning.progress orderby.creationDate=Creation date -orderby.custom=Presorted +orderby.custom=Arranged orderby.favorit=Favourite orderby.lastModified=Last modified orderby.lastVisited=Last visited diff --git a/src/main/java/org/olat/repository/manager/CatalogManager.java b/src/main/java/org/olat/repository/manager/CatalogManager.java index 21f191ce40c3ed74f2f43ed0d70ee4cb8c62f2da..8182259f533f1a6481ee78d894c01eab7d1ff0be 100644 --- a/src/main/java/org/olat/repository/manager/CatalogManager.java +++ b/src/main/java/org/olat/repository/manager/CatalogManager.java @@ -66,6 +66,8 @@ import org.olat.repository.CatalogEntryRef; import org.olat.repository.RepositoryDeletionModule; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryRef; +import org.olat.repository.RepositoryEntryStatusEnum; +import org.olat.repository.RepositoryModule; import org.olat.repository.RepositoryService; import org.olat.repository.controllers.EntryChangedEvent; import org.olat.repository.controllers.EntryChangedEvent.Change; @@ -114,6 +116,8 @@ public class CatalogManager implements UserDataDeletable, InitializingBean { @Autowired private SecurityGroupDAO securityGroupDao; @Autowired + private RepositoryModule repositoryModule; + @Autowired private RepositoryService repositoryService; @Autowired private OrganisationService organisationService; @@ -306,9 +310,17 @@ public class CatalogManager implements UserDataDeletable, InitializingBean { public void deleteCatalogEntry(RepositoryEntryRef entry, CatalogEntry parent) { CatalogEntry ce = getCatalogEntryBy(entry, parent); + parent = loadCatalogEntry(parent); + if(ce != null) { SecurityGroup owner = ce.getOwnerGroup(); + List<CatalogEntry> catalogEntries = parent.getChildren(); + + catalogEntries.remove(ce); + updateCatalogEntry(parent); + dbInstance.getCurrentEntityManager().remove(ce); + if (owner != null) { log.debug("deleteCatalogEntry case_1: delete owner-group={}", owner); securityGroupDao.deleteSecurityGroup(owner); @@ -324,14 +336,22 @@ public class CatalogManager implements UserDataDeletable, InitializingBean { * @param ce */ public void deleteCatalogEntry(CatalogEntry ce) { - final boolean debug = log.isDebugEnabled(); - if(debug) log.debug("deleteCatalogEntry start... ce={}", ce); + log.debug("deleteCatalogEntry start... ce={}", ce); + + //reload the detached catalog entry, delete it and then the owner group + ce = getCatalogEntryByKey(ce.getKey()); if (ce.getType() == CatalogEntry.TYPE_LEAF) { - //reload the detached catalog entry, delete it and then the owner group - ce = getCatalogEntryByKey(ce.getKey()); if(ce != null) { SecurityGroup owner = ce.getOwnerGroup(); + + if (ce.getParent() != null) { + CatalogEntry parent = ce.getParent(); + List<CatalogEntry> catalogEntries = parent.getChildren(); + catalogEntries.remove(ce); + updateCatalogEntry(parent); + } + dbInstance.getCurrentEntityManager().remove(ce); if (owner != null) { log.debug("deleteCatalogEntry case_1: delete owner-group={}", owner); @@ -340,15 +360,23 @@ public class CatalogManager implements UserDataDeletable, InitializingBean { } } else { List<SecurityGroup> secGroupsToBeDeleted = new ArrayList<>(); + deleteCatalogSubtree(ce,secGroupsToBeDeleted); // after deleting all entries, delete all secGroups corresponding for (Iterator<SecurityGroup> iter = secGroupsToBeDeleted.iterator(); iter.hasNext();) { SecurityGroup grp = iter.next(); - if(debug) log.debug("deleteCatalogEntry case_2: delete groups of deleteCatalogSubtree grp={}", grp); + log.debug("deleteCatalogEntry case_2: delete groups of deleteCatalogSubtree grp={}", grp); securityGroupDao.deleteSecurityGroup(grp); } + + if (ce.getParent() != null) { + CatalogEntry parent = ce.getParent(); + List<CatalogEntry> catalogEntries = parent.getChildren(); + catalogEntries.remove(ce); + updateCatalogEntry(parent); + } } - if(debug) log.debug("deleteCatalogEntry END"); + log.debug("deleteCatalogEntry END"); } /** @@ -550,20 +578,92 @@ public class CatalogManager implements UserDataDeletable, InitializingBean { * @param newEntry */ public void addCatalogEntry(CatalogEntry parent, CatalogEntry newEntry) { - parent = getCatalogEntryByKey(parent.getKey()); + parent = loadCatalogEntry(parent); boolean debug = log.isDebugEnabled(); if(debug) log.debug("addCatalogEntry parent={}", parent); if(debug) log.debug("addCatalogEntry newEntry={}", newEntry); if(debug) log.debug("addCatalogEntry newEntry.getOwnerGroup()={}", newEntry.getOwnerGroup()); - List<CatalogEntry> catEntries = parent.getChildren(); newEntry.setParent(parent); saveCatalogEntry(newEntry); - catEntries.add(newEntry); - updateCatalogEntry(parent); + + addToChildren(parent, newEntry); + dbInstance.commitAndCloseSession(); } + + private void addToChildren(CatalogEntry parentEntry, CatalogEntry newEntry) { + parentEntry = loadCatalogEntry(parentEntry); + newEntry = loadCatalogEntry(newEntry); + List<CatalogEntry> catEntries = parentEntry.getChildren(); + int index = 0; + boolean added = false; + String closed = RepositoryEntryStatusEnum.closed.name(); + RepositoryEntry repoEntry = newEntry.getRepositoryEntry(); + + if(catEntries.isEmpty()) { + catEntries.add(newEntry); + return; + } + + cleanNullEntries(catEntries); + + for (CatalogEntry catalogEntry : catEntries) { + // Add entries + if (catalogEntry.getType() == CatalogEntry.TYPE_LEAF && newEntry.getType() == CatalogEntry.TYPE_LEAF) { + if (repositoryModule.isCatalogAddAtLast()) { + // Closed entry to the end + if (repoEntry.getStatus().equals(closed)) { + catEntries.add(newEntry); + added = true; + break; + } + // Not closed entry to the end of not closed entries + else if (catalogEntry.getRepositoryEntry().getStatus().equals(closed)) { + catEntries.add(index, newEntry); + added = true; + break; + } + } else { + // Closed entry to the beginning of closed + if (repoEntry.getStatus().equals(closed) && catalogEntry.getRepositoryEntry().getStatus().equals(closed)) { + catEntries.add(index, newEntry); + added = true; + break; + } + // Not closed entry to the beginning of not closed entries + else if (!repoEntry.getStatus().equals(closed) && !catalogEntry.getRepositoryEntry().getStatus().equals(closed)) { + catEntries.add(index, newEntry); + added = true; + break; + } + } + } + // Add categories + else if (newEntry.getType() == CatalogEntry.TYPE_NODE) { + if (repositoryModule.isCatalogAddAtLast()) { + if (catalogEntry.getType() == CatalogEntry.TYPE_LEAF) { + catEntries.add(index, newEntry); + added = true; + break; + } + } else { + catEntries.add(0, newEntry); + added = true; + break; + } + } + index++; + } + + // If not added already, add it to the bottom of the list + if (!added) { + catEntries.add(newEntry); + } + + updateCatalogEntry(parentEntry); + } /** * Find all CatalogEntries which can act as catalog roots. Frankly speaking @@ -617,38 +717,12 @@ public class CatalogManager implements UserDataDeletable, InitializingBean { public CatalogEntry addCatalogCategory(CatalogEntry ce, CatalogEntry parentCe) { if(parentCe != null) { - parentCe = loadCatalogEntry(parentCe.getKey()); + parentCe = loadCatalogEntry(parentCe); } ce.setParent(parentCe); saveCatalogEntry(ce); - - if (parentCe != null) { - List<CatalogEntry> catEntries = parentCe.getChildren(); - if(catEntries.isEmpty()) { - catEntries.add(ce); - } else { - cleanNullEntries(catEntries); - - boolean added = false; - List<CatalogEntry> catalogEntries = new ArrayList<>(catEntries); - for (CatalogEntry catalogEntry : catalogEntries) { - if (catalogEntry.getType() == ce.getType()) { - catEntries.add(catEntries.indexOf(catalogEntry), ce); - added = true; - break; - } - } - - if(!added) { - if(ce.getType() == CatalogEntry.TYPE_NODE) { - catEntries.add(0, ce); - } else { - catEntries.add(ce); - } - } - updateCatalogEntry(parentCe); - } - } + + addToChildren(parentCe, ce); dbInstance.commitAndCloseSession(); return ce; @@ -671,7 +745,8 @@ public class CatalogManager implements UserDataDeletable, InitializingBean { public boolean moveCatalogEntry(CatalogEntry toBeMovedEntry, CatalogEntry newParentEntry) { // reload current item to prevent stale object modification toBeMovedEntry = loadCatalogEntry(toBeMovedEntry); - newParentEntry = loadCatalogEntry(newParentEntry); + newParentEntry = loadCatalogEntry(newParentEntry); + // check that the new parent is not a leaf if (newParentEntry.getType() == CatalogEntry.TYPE_LEAF) return false; // check that the new parent is not a child of the to be moved entry @@ -683,9 +758,26 @@ public class CatalogManager implements UserDataDeletable, InitializingBean { } tempEntry = tempEntry.getParent(); } + // Check that the new parent doesn't contain the entry already and remove it from its list + List<CatalogEntry> newParentChildren = newParentEntry.getChildren(); + for (CatalogEntry newParentChild : newParentChildren) { + if (newParentChild.getType() == CatalogEntry.TYPE_LEAF && newParentChild.getRepositoryEntry().equals(toBeMovedEntry.getRepositoryEntry())) { + // Entry is already existing + return false; + } + } + // Get the old parent and remove it from its list + CatalogEntry oldParentEntry; + if (toBeMovedEntry.getParent() != null) { + oldParentEntry = toBeMovedEntry.getParent(); + List<CatalogEntry> oldChildren = oldParentEntry.getChildren(); + oldChildren.remove(toBeMovedEntry); + updateCatalogEntry(oldParentEntry); + } // set new parent and save toBeMovedEntry.setParent(newParentEntry); updateCatalogEntry(toBeMovedEntry); + addToChildren(newParentEntry, toBeMovedEntry); dbInstance.commitAndCloseSession(); return true; } @@ -871,4 +963,26 @@ public class CatalogManager implements UserDataDeletable, InitializingBean { return 1; } + + public int setPosition(Long childEntryKey, int position) { + CatalogEntry childEntry = getCatalogEntryByKey(childEntryKey); + CatalogEntry parentEntry = childEntry.getParent(); + List<CatalogEntry> children = parentEntry.getChildren(); + + if (position >= 0 && position < children.size()) { + children.remove(children.indexOf(childEntry)); + children.add(position, childEntry); + + updateCatalogEntry(parentEntry); + dbInstance.commitAndCloseSession(); + + return 0; + } else if (position < 0) { + return 1; + } else if (position >= children.size()) { + return 2; + } else { + return -1; + } + } } diff --git a/src/main/java/org/olat/repository/model/CatalogEntryImpl.java b/src/main/java/org/olat/repository/model/CatalogEntryImpl.java index 7ed96fb7c0c9cecf5ceaaa6ae172e6a10b6c489b..a3f07ebcfa5a3e5ff97b52c98a9e7be492c6a212 100644 --- a/src/main/java/org/olat/repository/model/CatalogEntryImpl.java +++ b/src/main/java/org/olat/repository/model/CatalogEntryImpl.java @@ -31,6 +31,7 @@ import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; @@ -85,9 +86,12 @@ public class CatalogEntryImpl implements CatalogEntry { @Column(name="creationdate", nullable=false, insertable=true, updatable=false) private Date creationDate; - @Column(name = "name", unique = false, nullable = false, length = 100) + @Column(name = "name", unique = false, nullable = false) private String name; + @Column(name = "short_title", unique = false, nullable = true) + private String shortTitle; + @Column(name = "style", unique = false, nullable = true) private String styleString; @@ -105,7 +109,7 @@ public class CatalogEntryImpl implements CatalogEntry { @JoinColumn(name = "parent_id", nullable = true, insertable = true, updatable = true) private CatalogEntry parent; - @OneToMany(targetEntity = CatalogEntryImpl.class, mappedBy = "parent") + @OneToMany(targetEntity = CatalogEntryImpl.class, mappedBy = "parent", fetch = FetchType.LAZY) @OrderColumn(name = "order_index") private List<CatalogEntry> children; @@ -139,13 +143,23 @@ public class CatalogEntryImpl implements CatalogEntry { public String getName() { return name; } - + @Override public void setName(String name) { if (name.length() > 100) throw new AssertException("CatalogEntry: Name is limited to 100 characters."); this.name = name; } + + @Override + public String getShortTitle() { + return shortTitle; + } + + @Override + public void setShortTitle(String shortTitle) { + this.shortTitle = shortTitle; + } public String getStyleString() { return styleString; diff --git a/src/main/java/org/olat/repository/ui/admin/CatalogAdminController.java b/src/main/java/org/olat/repository/ui/admin/CatalogAdminController.java index e2c7d1ecdef5688ee5060bc135a92979862f4a3e..5b422a058069105adaaeb6522aff5b4e1285072f 100644 --- a/src/main/java/org/olat/repository/ui/admin/CatalogAdminController.java +++ b/src/main/java/org/olat/repository/ui/admin/CatalogAdminController.java @@ -23,6 +23,7 @@ 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.MultipleSelectionElement; +import org.olat.core.gui.components.form.flexible.elements.SingleSelection; 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.control.Controller; @@ -40,7 +41,11 @@ import org.springframework.beans.factory.annotation.Autowired; */ public class CatalogAdminController extends FormBasicController { - private MultipleSelectionElement enableEl, enableBrowsingEl, siteEl; + private MultipleSelectionElement enableEl; + private MultipleSelectionElement enableBrowsingEl; + private MultipleSelectionElement siteEl; + private SingleSelection addEntryPosEl; + @Autowired private RepositoryModule repositoryModule; @@ -73,6 +78,18 @@ public class CatalogAdminController extends FormBasicController { siteEl.select("xx", repositoryModule.isCatalogSiteEnabled()); siteEl.setEnabled(enabled); siteEl.addActionListener(FormEvent.ONCLICK); + + String[] addEntryKeys = {AddEntryPosition.top.name(), AddEntryPosition.bottom.name()}; + String[] addEntryValues = {translate("catalog.addposition." + AddEntryPosition.top.name()), translate("catalog.addposition." + AddEntryPosition.bottom.name())}; + + addEntryPosEl = uifactory.addDropdownSingleselect("catalog.addposition", "catalog.addposition", formLayout, addEntryKeys, addEntryValues); + if (repositoryModule.isCatalogAddAtLast()) { + addEntryPosEl.select(AddEntryPosition.bottom.name(), true); + } else { + addEntryPosEl.select(AddEntryPosition.top.name(), true); + } + addEntryPosEl.setEnabled(enabled); + addEntryPosEl.addActionListener(FormEvent.ONCHANGE); } @Override @@ -87,10 +104,17 @@ public class CatalogAdminController extends FormBasicController { repositoryModule.setCatalogEnabled(enabled); siteEl.setEnabled(enabled); enableBrowsingEl.setEnabled(enabled); + addEntryPosEl.setEnabled(enabled); } else if(source == siteEl) { repositoryModule.setCatalogSiteEnabled(siteEl.isSelected(0)); } else if(source == enableBrowsingEl) { repositoryModule.setCatalogBrowsingEnabled(enableBrowsingEl.isSelected(0)); + } else if (source == addEntryPosEl) { + if (addEntryPosEl.getSelectedKey().equals(AddEntryPosition.bottom.name())) { + repositoryModule.setCatalogAddAtLast(true); + } else { + repositoryModule.setCatalogAddAtLast(false); + } } super.formInnerEvent(ureq, source, event); } @@ -99,4 +123,9 @@ public class CatalogAdminController extends FormBasicController { protected void formOK(UserRequest ureq) { // } + + private enum AddEntryPosition { + top, + bottom; + } } \ No newline at end of file diff --git a/src/main/java/org/olat/repository/ui/admin/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/repository/ui/admin/_i18n/LocalStrings_de.properties index a60ad8bccd3d16c54e1fc3f47a62e6e428a7c074..306dd7abc5fe4e5694e46b59cbc0653cab55657e 100644 --- a/src/main/java/org/olat/repository/ui/admin/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/repository/ui/admin/_i18n/LocalStrings_de.properties @@ -2,6 +2,9 @@ admin.catalog.settings=Katalog settings admin.menu.title=Katalog admin.menu.title.alt=Katalog +catalog.addposition=Neue Eintr\u00e4ge hinzuf\u00fcgen +catalog.addposition.bottom=Am Ende +catalog.addposition.top=Am Anfang catalog.browsing=Katalog in "Kurse" catalog.enable=Katalog einschalten catalog.site=Katalog in eigener Site diff --git a/src/main/java/org/olat/repository/ui/admin/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/repository/ui/admin/_i18n/LocalStrings_en.properties index d97343f5bbbb46352016641fc0fa90987cfc2f11..e05ce14753398b136cbfeacc75d874ecdba88dc4 100644 --- a/src/main/java/org/olat/repository/ui/admin/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/repository/ui/admin/_i18n/LocalStrings_en.properties @@ -2,6 +2,9 @@ admin.catalog.settings=Catalog settings admin.menu.title=Catalog admin.menu.title.alt=Catalog +catalog.addposition=Add new entries +catalog.addposition.bottom=At the end +catalog.addposition.top=At the beginning catalog.enable=Enable catalog catalog.browsing=Catalog in "Courses" catalog.site=Catalog in its own site \ No newline at end of file diff --git a/src/main/java/org/olat/repository/ui/catalog/CatalogEntryEditController.java b/src/main/java/org/olat/repository/ui/catalog/CatalogEntryEditController.java index afbb5166d81669943120bfa6a6a5678308c0c9d1..c321ec0eda830896577d5d1d2bd45ec5640019ee 100644 --- a/src/main/java/org/olat/repository/ui/catalog/CatalogEntryEditController.java +++ b/src/main/java/org/olat/repository/ui/catalog/CatalogEntryEditController.java @@ -118,13 +118,12 @@ public class CatalogEntryEditController extends FormBasicController { nameEl.setMandatory(true); nameEl.setNotEmptyCheck("form.legende.mandatory"); - /* - String shortTitle = catalogEntry == null ? "" : catalogEntry.get() != null ? catalogEntry.getDescription() : ""; + String shortTitle = catalogEntry == null ? "" : catalogEntry.getShortTitle() != null ? catalogEntry.getShortTitle() : ""; shortTitleEl = uifactory.addTextElement("shortTitle", "entry.shorttitle", 255, shortTitle, formLayout); shortTitleEl.setElementCssClass("o_sel_cat_short_title"); shortTitleEl.setMandatory(true); shortTitleEl.setNotEmptyCheck("form.legende.mandatory"); - */ + shortTitleEl.setHelpText(translate("catalog.popup.edit.shorttitle.desc")); String desc = catalogEntry == null ? "" : catalogEntry.getDescription(); descriptionEl = uifactory.addRichTextElementForStringDataMinimalistic("description", "entry.description", desc, 10, -1, formLayout, getWindowControl()); @@ -179,16 +178,8 @@ public class CatalogEntryEditController extends FormBasicController { protected boolean validateFormLogic(UserRequest ureq) { boolean allOk = super.validateFormLogic(ureq); - nameEl.clearError(); - if(StringHelper.containsNonWhitespace(nameEl.getValue())) { - if(nameEl.getValue().length() > 99) { - nameEl.setErrorKey("input.toolong", new String[]{ "100" }); - allOk &= false; - } - } else { - nameEl.setErrorKey("form.legende.mandatory", null); - allOk &= false; - } + allOk &= validateTextInput(nameEl, 100); + allOk &= validateTextInput(shortTitleEl, 16); styleEl.clearError(); if(!styleEl.isOneSelected()) { @@ -198,6 +189,21 @@ public class CatalogEntryEditController extends FormBasicController { return allOk; } + + private boolean validateTextInput(TextElement textElement, int lenght) { + textElement.clearError(); + if(StringHelper.containsNonWhitespace(nameEl.getValue())) { + if(textElement.getValue().length() > lenght) { + textElement.setErrorKey("input.toolong", new String[]{ String.valueOf(lenght) }); + return false; + } + } else { + textElement.setErrorKey("form.legende.mandatory", null); + return false; + } + + return true; + } @Override protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { @@ -235,6 +241,7 @@ public class CatalogEntryEditController extends FormBasicController { catalogEntry.setStyle(null); } catalogEntry.setDescription(descriptionEl.getValue()); + catalogEntry.setShortTitle(shortTitleEl.getValue()); if(catalogEntry.getKey() == null) { //a new one diff --git a/src/main/java/org/olat/repository/ui/catalog/CatalogEntryPositionDialogController.java b/src/main/java/org/olat/repository/ui/catalog/CatalogEntryPositionDialogController.java new file mode 100644 index 0000000000000000000000000000000000000000..bd4a62c41ee508c70332783d57cf30998d046291 --- /dev/null +++ b/src/main/java/org/olat/repository/ui/catalog/CatalogEntryPositionDialogController.java @@ -0,0 +1,147 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <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> + * Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <hr> + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * This file has been modified by the OpenOLAT community. Changes are licensed + * under the Apache 2.0 license as the original file. + */ +package org.olat.repository.ui.catalog; + +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.FormLink; +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.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +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.util.Util; +import org.olat.repository.CatalogEntry; +import org.olat.repository.manager.CatalogManager; +import org.springframework.beans.factory.annotation.Autowired; + +/* + * Date: 24 Feb 2020<br> + * @author Alexander Boeckle + */ +public class CatalogEntryPositionDialogController extends FormBasicController { + Long catalogEntryKey; + int position; + int smallest; + int biggest; + + CatalogEntry catalogEntry; + + @Autowired + CatalogManager catalogManager; + + FormLink smallestFormLink; + FormLink smallerFormLink; + FormLink biggestFormLink; + FormLink biggerFormLink; + TextElement positionTextElement; + + public CatalogEntryPositionDialogController(UserRequest ureq, WindowControl wControl, Long catalogEntryKey, int smallest, int biggest) { + super(ureq, wControl, "catPosition", Util.createPackageTranslator(CatalogNodeManagerController.class, ureq.getLocale())); + + catalogEntry = catalogManager.getCatalogEntryByKey(catalogEntryKey); + this.biggest = biggest + 1; + this.smallest = smallest + 1; + this.catalogEntryKey = catalogEntryKey; + this.position = catalogEntry.getPosition() + 1; + + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + flc.contextPut("catalog_entry_name", catalogEntry.getName()); + + smallestFormLink = uifactory.addFormLink("catalog.popup.position.smallest", formLayout, Link.BUTTON); + smallerFormLink = uifactory.addFormLink("catalog.popup.position.smaller", formLayout, Link.BUTTON); + positionTextElement = uifactory.addTextElement("catalog.popup.position.set", 5, String.valueOf(position), formLayout); + positionTextElement.setDisplaySize(4); + positionTextElement.setMandatory(true); + positionTextElement.setElementCssClass("o_centered_form"); + biggerFormLink = uifactory.addFormLink("catalog.popup.position.bigger", formLayout, Link.BUTTON); + biggestFormLink = uifactory.addFormLink("catalog.popup.position.biggest", formLayout, Link.BUTTON); + + FormLayoutContainer filterButtonLayout = FormLayoutContainer.createButtonLayout("save", getTranslator()); + filterButtonLayout.setRootForm(mainForm); + formLayout.add(filterButtonLayout); + + uifactory.addFormSubmitButton("catalog.popup.position.save", filterButtonLayout); + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = super.validateFormLogic(ureq); + try { + position = Integer.parseInt(positionTextElement.getValue()); + + if (position < smallest || position > biggest) { + positionTextElement.setErrorKey("catalog.popup.position.error.number", new String[]{String.valueOf(smallest), String.valueOf(biggest)}); + allOk&=false; + } + } catch (Exception e) { + positionTextElement.setErrorKey("catalog.popup.position.error.number.format", null); + allOk&=false; + } + + return allOk; + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if (source == smallerFormLink && position > smallest) { + position -= 1; + positionTextElement.setValue(String.valueOf(position)); + } else if (source == smallestFormLink) { + position = smallest + 1; + positionTextElement.setValue(String.valueOf(smallest)); + } else if (source == biggerFormLink && position < biggest) { + position += 1; + positionTextElement.setValue(String.valueOf(position)); + } else if (source == biggestFormLink) { + position = biggest + 1; + positionTextElement.setValue(String.valueOf(biggest)); + } + } + + @Override + protected void formOK(UserRequest ureq) { + catalogManager.setPosition(catalogEntryKey, position - 1); + fireEvent(ureq, Event.DONE_EVENT); + } + + @Override + protected void formCancelled(UserRequest ureq) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } + + @Override + protected void doDispose() { + // + } +} diff --git a/src/main/java/org/olat/repository/ui/catalog/CatalogEntryRow.java b/src/main/java/org/olat/repository/ui/catalog/CatalogEntryRow.java index 254f5ca60a73680a511bd288596d3461d1290643..59926fb2ba36ca1cd609db3dc051dc7d960c199d 100644 --- a/src/main/java/org/olat/repository/ui/catalog/CatalogEntryRow.java +++ b/src/main/java/org/olat/repository/ui/catalog/CatalogEntryRow.java @@ -22,6 +22,7 @@ package org.olat.repository.ui.catalog; import java.util.Date; import java.util.List; +import org.olat.core.gui.components.form.flexible.elements.FormLink; import org.olat.core.id.OLATResourceable; import org.olat.core.util.StringHelper; import org.olat.core.util.resource.OresHelper; @@ -44,7 +45,7 @@ public class CatalogEntryRow implements RepositoryEntryRef, RepositoryEntryLight private Long key; private Long catEntryKey; - private int position; + private Integer position; private String name; private String authors; private String shortenedDescription; @@ -66,6 +67,8 @@ public class CatalogEntryRow implements RepositoryEntryRef, RepositoryEntryLight private Date lifecycleStart; private Date lifecycleEnd; + private FormLink positionLink; + private List<PriceMethod> accessTypes; private OLATResourceable olatResource; @@ -103,7 +106,7 @@ public class CatalogEntryRow implements RepositoryEntryRef, RepositoryEntryLight public CatalogEntryRow(RepositoryEntry view, CatalogEntry cat) { this(view); - position = cat.getPosition() == null ? 0 : cat.getPosition().intValue(); + position = cat.getPosition() == null ? 0 : cat.getPosition(); catEntryKey = cat.getKey(); } @@ -186,7 +189,7 @@ public class CatalogEntryRow implements RepositoryEntryRef, RepositoryEntryLight return lifecycleEnd; } - public int getPosition() { + public Integer getPosition() { return position; } @@ -222,4 +225,12 @@ public class CatalogEntryRow implements RepositoryEntryRef, RepositoryEntryLight public String getAuthors() { return authors; } + + public FormLink getPositionLink() { + return positionLink; + } + + public void setPositionLink(FormLink positionLink) { + this.positionLink = positionLink; + } } \ No newline at end of file diff --git a/src/main/java/org/olat/repository/ui/catalog/CatalogEntryRowModel.java b/src/main/java/org/olat/repository/ui/catalog/CatalogEntryRowModel.java index 16011ea7ad636c3fc9f8a5e6be2290063cbd93b7..11b711c28df8549d9469dec367392fac292fca67 100644 --- a/src/main/java/org/olat/repository/ui/catalog/CatalogEntryRowModel.java +++ b/src/main/java/org/olat/repository/ui/catalog/CatalogEntryRowModel.java @@ -76,7 +76,7 @@ public class CatalogEntryRowModel extends DefaultFlexiTableDataModel<CatalogEntr case detailsSupported: return item; case move: return item; case delete: return item; - case position: return item.getPosition(); + case position: return item.getPositionLink(); } return null; } diff --git a/src/main/java/org/olat/repository/ui/catalog/CatalogManagerController.java b/src/main/java/org/olat/repository/ui/catalog/CatalogManagerController.java index 5b5a7865508a9f487dec661f2d14e2cebfefc1d7..fd3a5c8b08a1d8f356c6a65ab58bcea06f7f0ea0 100644 --- a/src/main/java/org/olat/repository/ui/catalog/CatalogManagerController.java +++ b/src/main/java/org/olat/repository/ui/catalog/CatalogManagerController.java @@ -63,9 +63,10 @@ public class CatalogManagerController extends BasicController implements Activat List<CatalogEntry> rootNodes = catalogManager.getRootCatalogEntries(); if(rootNodes.size() == 1) { - catalogCtrl = new CatalogNodeManagerController(ureq, getWindowControl(), getWindowControl(), rootNodes.get(0), toolbarPanel, false); + CatalogEntry root = rootNodes.get(0); + catalogCtrl = new CatalogNodeManagerController(ureq, getWindowControl(), getWindowControl(), root, toolbarPanel, false); listenTo(catalogCtrl); - toolbarPanel.pushController("Catalog", catalogCtrl); + toolbarPanel.pushController(root.getShortTitle(), catalogCtrl); catalogCtrl.initToolbar(); } } diff --git a/src/main/java/org/olat/repository/ui/catalog/CatalogNodeController.java b/src/main/java/org/olat/repository/ui/catalog/CatalogNodeController.java index d52e9e7cfd4f24dacec37813d79dbaea310829b6..ada3d9e5274c0f6dc653ca0e0e4235292c004451 100644 --- a/src/main/java/org/olat/repository/ui/catalog/CatalogNodeController.java +++ b/src/main/java/org/olat/repository/ui/catalog/CatalogNodeController.java @@ -97,7 +97,8 @@ public class CatalogNodeController extends BasicController implements Activateab } else { mainVC.contextPut("listStyle", Style.tiles.name()); } - mainVC.contextPut("catalogEntryName", catalogEntry.getName()); + mainVC.contextPut("catalogEntryTitle", catalogEntry.getName()); + mainVC.contextPut("catalogEntryShortTitle", catalogEntry.getShortTitle()); int level = 0; CatalogEntry parent = catalogEntry.getParent(); while (parent != null) { @@ -114,7 +115,7 @@ public class CatalogNodeController extends BasicController implements Activateab mainVC.contextPut("catThumbnail", image.getName()); } - List<CatalogEntry> childCe = catalogEntry.getChildren(); + List<CatalogEntry> childCe = catalogManager.getChildrenOf(catalogEntry); List<String> subCategories = new ArrayList<>(); int count = 0; for (CatalogEntry entry : childCe) { @@ -129,13 +130,22 @@ public class CatalogNodeController extends BasicController implements Activateab mainVC.contextPut("k" + cmpId, entry.getKey()); String title = StringHelper.escapeHtml(entry.getName()); + String shortTitle; + if (entry.getShortTitle() == null) { + shortTitle = StringHelper.escapeHtml(entry.getName()); + } else { + shortTitle = StringHelper.escapeHtml(entry.getShortTitle()); + } + Link link = LinkFactory.createCustomLink(cmpId, "select_node", cmpId, Link.LINK + Link.NONTRANSLATED, mainVC, this); link.setCustomDisplayText(title); link.setIconLeftCSS("o_icon o_icon_catalog_sub"); link.setUserObject(entry.getKey()); subCategories.add(Integer.toString(count)); String titleId = "title_" + count; + String shortTitleId = "short_title_" + count; mainVC.contextPut(titleId, title); + mainVC.contextPut(shortTitleId, shortTitle); } } mainVC.contextPut("subCategories", subCategories); @@ -146,7 +156,7 @@ public class CatalogNodeController extends BasicController implements Activateab searchParams.setParentEntry(catalogEntry); searchParams.setClosed(Boolean.FALSE); - entryListController = new RepositoryEntryListController(ureq, wControl, searchParams, true, false, "catalog", stackPanel); + entryListController = new RepositoryEntryListController(ureq, wControl, searchParams, true, false, false, "catalog", stackPanel); if(!entryListController.isEmpty() || searchParams.getFilters() != null) { mainVC.put("entries", entryListController.getInitialComponent()); } @@ -157,7 +167,8 @@ public class CatalogNodeController extends BasicController implements Activateab = new SearchMyRepositoryEntryViewParams(getIdentity(), ureq.getUserSession().getRoles()); searchClosedParams.setParentEntry(catalogEntry); searchClosedParams.setClosed(Boolean.TRUE); - closedEntryListController = new RepositoryEntryListController(ureq, wControl, searchClosedParams, true, false, "catalog-closed", stackPanel); + + closedEntryListController = new RepositoryEntryListController(ureq, wControl, searchClosedParams, true, false, false, "catalog-closed", stackPanel); if(!closedEntryListController.isEmpty() || searchClosedParams.getFilters() != null) { mainVC.put("closedEntries", closedEntryListController.getInitialComponent()); } @@ -206,7 +217,7 @@ public class CatalogNodeController extends BasicController implements Activateab childNodeController = new CatalogNodeController(ureq, bwControl, rootwControl, entry, stackPanel, wrapInMainPanel); listenTo(childNodeController); - stackPanel.pushController(entry.getName(), childNodeController); + stackPanel.pushController(entry.getShortTitle(), childNodeController); addToHistory(ureq, childNodeController); } diff --git a/src/main/java/org/olat/repository/ui/catalog/CatalogNodeManagerController.java b/src/main/java/org/olat/repository/ui/catalog/CatalogNodeManagerController.java index 84f5163423126968e03db7b681e76f7cb67b57f6..9bf5331e622cff5841178d3541f6e279c59530c1 100644 --- a/src/main/java/org/olat/repository/ui/catalog/CatalogNodeManagerController.java +++ b/src/main/java/org/olat/repository/ui/catalog/CatalogNodeManagerController.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import org.olat.NewControllerFactory; import org.olat.admin.securitygroup.gui.GroupController; @@ -37,6 +38,7 @@ import org.olat.core.gui.components.Component; 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.BooleanCellRenderer; @@ -51,11 +53,14 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlex import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.stack.PopEvent; import org.olat.core.gui.components.stack.TooledStackedPanel; import org.olat.core.gui.components.stack.TooledStackedPanel.Align; 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.CalloutSettings; +import org.olat.core.gui.control.generic.closablewrapper.CloseableCalloutWindowController; import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; import org.olat.core.gui.control.generic.dtabs.Activateable2; import org.olat.core.gui.control.generic.modal.DialogBoxController; @@ -121,13 +126,17 @@ public class CatalogNodeManagerController extends FormBasicController implements public static final OLATResourceable lockRes = OresHelper.createOLATResourceableType("CatalogNodeManagerController"); private final TooledStackedPanel toolbarPanel; + private final AtomicInteger counter = new AtomicInteger(); private GroupController groupCtrl; private CloseableModalController cmc; private ContactFormController contactCtrl; private RepositorySearchController entrySearchCtrl; + private CatalogEntryPositionDialogController positionCtrl; + private CloseableCalloutWindowController positionCalloutCtrl; private CatalogNodeManagerController childNodeCtrl; + private CatalogNodeManagerController positionMoveCtrl; private CatalogEntryMoveController categoryMoveCtrl; private CatalogEntryMoveController entryResourceMoveCtrl; private CatalogEntryEditController addEntryCtrl, editEntryCtrl; @@ -159,6 +168,7 @@ public class CatalogNodeManagerController extends FormBasicController implements private static final String CMD_UP = "leaf_up"; private static final String CMD_DOWN = "leaf_down"; + private static final String CMD_SET_POSITION = "set_position"; private LockResult catModificationLock; private final MapperKey mapperThumbnailKey; @@ -206,6 +216,42 @@ public class CatalogNodeManagerController extends FormBasicController implements isOrdering = false; flc.contextPut("isOrdering", isOrdering); + this.toolbarPanel.addListener(this); + + if(isAdministrator) { + isLocalTreeAdmin = false; + } else { + isLocalTreeAdmin = localTreeAdmin || catalogManager.isOwner(catalogEntry, getIdentity()); + } + + initForm(ureq); + + loadEntryInfos(); + loadNodesChildren(); + loadResources(ureq); + //catch the events from the velocity template + flc.getFormItemComponent().addListener(this); + } + + public CatalogNodeManagerController(UserRequest ureq, WindowControl wControl, WindowControl rootwControl, + CatalogEntry catalogEntry, TooledStackedPanel stackPanel, boolean localTreeAdmin, boolean isOrdering) { + super(ureq, wControl, "node"); + setTranslator(Util.createPackageTranslator(RepositoryService.class, ureq.getLocale(), getTranslator())); + + this.toolbarPanel = stackPanel; + this.catalogEntry = catalogEntry; + this.rootwControl = rootwControl; + mapperThumbnailKey = mapperService.register(null, "catalogentryImage", new CatalogEntryImageMapper()); + + Roles roles = ureq.getUserSession().getRoles(); + isAuthor = roles.isAuthor(); + isGuest = roles.isGuestOnly(); + isAdministrator = roles.isAdministrator() || roles.isLearnResourceManager(); + this.isOrdering = isOrdering; + flc.contextPut("isOrdering", isOrdering); + + this.toolbarPanel.addListener(this); + if(isAdministrator) { isLocalTreeAdmin = false; } else { @@ -244,11 +290,11 @@ public class CatalogNodeManagerController extends FormBasicController implements leafColumns = new ArrayList<>(); - FlexiTableColumnModel entriesColumnsModel = getCatalogFlexiTableColumnModel("opened-", true); + FlexiTableColumnModel entriesColumnsModel = getCatalogFlexiTableColumnModel("opened-", !isOrdering); entriesModel = new CatalogEntryRowModel(entriesColumnsModel); entriesEl = uifactory.addTableElement(getWindowControl(), "entries", entriesModel, getTranslator(), formLayout); - FlexiTableColumnModel closedEntriesColumnsModel = getCatalogFlexiTableColumnModel("closed-", true); + FlexiTableColumnModel closedEntriesColumnsModel = getCatalogFlexiTableColumnModel("closed-", !isOrdering); closedEntriesModel = new CatalogEntryRowModel(closedEntriesColumnsModel); closedEntriesEl = uifactory.addTableElement(getWindowControl(), "closedEntries", closedEntriesModel, getTranslator(), formLayout); @@ -262,25 +308,29 @@ public class CatalogNodeManagerController extends FormBasicController implements FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); DefaultFlexiColumnModel columnModel; - leafUpColumnModel = new DefaultFlexiColumnModel(false, Cols.up.i18nKey(), Cols.up.ordinal(), CMD_UP, false, null); - leafUpColumnModel.setCellRenderer(new BooleanCellRenderer( - new StaticFlexiCellRenderer("", CMD_UP, "o_icon o_icon-lg o_icon_move_up"), - null)); - leafUpColumnModel.setIconHeader("o_icon o_icon_fw o_icon-lg o_icon_move_up"); - leafUpColumnModel.setAlignment(FlexiColumnModel.ALIGNMENT_ICON); - columnsModel.addFlexiColumnModel(leafUpColumnModel); - - leafDownColumnModel = new DefaultFlexiColumnModel(false, Cols.down.i18nKey(), Cols.down.ordinal(), CMD_DOWN, false, null); - leafDownColumnModel.setCellRenderer(new BooleanCellRenderer( - new StaticFlexiCellRenderer("", CMD_DOWN, "o_icon o_icon-lg o_icon_move_down"), - null)); - leafDownColumnModel.setIconHeader("o_icon o_icon_fw o_icon-lg o_icon_move_down"); - leafDownColumnModel.setAlignment(FlexiColumnModel.ALIGNMENT_ICON); - columnsModel.addFlexiColumnModel(leafDownColumnModel); - - leafPositionColumnModel = new DefaultFlexiColumnModel(false, Cols.position.i18nKey(), Cols.position.ordinal(), sortEnabled, Cols.position.name()); - columnsModel.addFlexiColumnModel(leafPositionColumnModel); - leafColumns.add(leafPositionColumnModel); + if (!sortEnabled) { + leafUpColumnModel = new DefaultFlexiColumnModel(true, Cols.up.i18nKey(), Cols.up.ordinal(), CMD_UP, false, null); + leafUpColumnModel.setCellRenderer(new BooleanCellRenderer( + new StaticFlexiCellRenderer("", CMD_UP, "o_icon o_icon-lg o_icon_move_up"), + null)); + leafUpColumnModel.setIconHeader("o_icon o_icon_fw o_icon-lg o_icon_move_up"); + leafUpColumnModel.setAlignment(FlexiColumnModel.ALIGNMENT_ICON); + leafUpColumnModel.setAlwaysVisible(true); + columnsModel.addFlexiColumnModel(leafUpColumnModel); + + leafDownColumnModel = new DefaultFlexiColumnModel(true, Cols.down.i18nKey(), Cols.down.ordinal(), CMD_DOWN, false, null); + leafDownColumnModel.setCellRenderer(new BooleanCellRenderer( + new StaticFlexiCellRenderer("", CMD_DOWN, "o_icon o_icon-lg o_icon_move_down"), + null)); + leafDownColumnModel.setIconHeader("o_icon o_icon_fw o_icon-lg o_icon_move_down"); + leafDownColumnModel.setAlignment(FlexiColumnModel.ALIGNMENT_ICON); + leafDownColumnModel.setAlwaysVisible(true); + columnsModel.addFlexiColumnModel(leafDownColumnModel); + + + leafPositionColumnModel = new DefaultFlexiColumnModel(true, Cols.position.i18nKey(), Cols.position.ordinal(), false, null); + columnsModel.addFlexiColumnModel(leafPositionColumnModel); + } columnModel = new DefaultFlexiColumnModel(false, Cols.key.i18nKey(), Cols.key.ordinal(), sortEnabled, OrderBy.key.name()); leafColumns.add(columnModel); @@ -349,10 +399,13 @@ public class CatalogNodeManagerController extends FormBasicController implements leafColumns.add(columnModel); columnsModel.addFlexiColumnModel(columnModel); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.delete.i18nKey(), translate(Cols.delete.i18nKey()), cmdPrefix + "delete")); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.move.i18nKey(), translate(Cols.move.i18nKey()), cmdPrefix + "move")); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.detailsSupported.i18nKey(), Cols.detailsSupported.ordinal(), cmdPrefix + "details", - new StaticFlexiCellRenderer("", cmdPrefix + "details", "o_icon o_icon-lg o_icon_details", translate("details")))); + if (!isOrdering) { + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.delete.i18nKey(), translate(Cols.delete.i18nKey()), cmdPrefix + "delete")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.move.i18nKey(), translate(Cols.move.i18nKey()), cmdPrefix + "move")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.detailsSupported.i18nKey(), Cols.detailsSupported.ordinal(), cmdPrefix + "details", + new StaticFlexiCellRenderer("", cmdPrefix + "details", "o_icon o_icon-lg o_icon_details", translate("details")))); + } + return columnsModel; } @@ -360,23 +413,24 @@ public class CatalogNodeManagerController extends FormBasicController implements //add the table FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); - nodeUpColumnModel = new DefaultFlexiColumnModel(false, NodeCols.up.i18nKey(), NodeCols.up.ordinal(), CMD_UP, false, null); + nodeUpColumnModel = new DefaultFlexiColumnModel(true, NodeCols.up.i18nKey(), NodeCols.up.ordinal(), CMD_UP, false, null); nodeUpColumnModel.setCellRenderer(new BooleanCellRenderer( new StaticFlexiCellRenderer("", CMD_UP, "o_icon o_icon_fw o_icon-lg o_icon_move_up"), null)); nodeUpColumnModel.setIconHeader("o_icon o_icon_fw o_icon-lg o_icon_move_up"); nodeUpColumnModel.setAlignment(FlexiColumnModel.ALIGNMENT_ICON); + nodeUpColumnModel.setAlwaysVisible(true); - nodeDownColumnModel = new DefaultFlexiColumnModel(false, NodeCols.down.i18nKey(), NodeCols.down.ordinal(), CMD_DOWN, false, null); + nodeDownColumnModel = new DefaultFlexiColumnModel(true, NodeCols.down.i18nKey(), NodeCols.down.ordinal(), CMD_DOWN, false, null); nodeDownColumnModel.setCellRenderer(new BooleanCellRenderer( new StaticFlexiCellRenderer("", CMD_DOWN, "o_icon o_icon_fw o_icon-lg o_icon_move_down"), null)); nodeDownColumnModel.setIconHeader("o_icon o_icon_fw o_icon-lg o_icon_move_down"); nodeDownColumnModel.setAlignment(FlexiColumnModel.ALIGNMENT_ICON); + nodeDownColumnModel.setAlwaysVisible(true); nodePositionColumnModel = new DefaultFlexiColumnModel(true, NodeCols.position.i18nKey(), NodeCols.position.ordinal(), false, null); - columnsModel.addFlexiColumnModel(nodeUpColumnModel); columnsModel.addFlexiColumnModel(nodeDownColumnModel); @@ -388,7 +442,9 @@ public class CatalogNodeManagerController extends FormBasicController implements } private void loadEntryInfos() { - flc.contextPut("catalogEntryName", catalogEntry.getName()); + catalogEntry = catalogManager.loadCatalogEntry(catalogEntry); + flc.contextPut("catalogEntryTitle", catalogEntry.getName()); + flc.contextPut("catalogEntryShortTitle", catalogEntry.getShortTitle()); if(StringHelper.containsNonWhitespace(catalogEntry.getDescription())) { flc.contextPut("catalogEntryDesc", catalogEntry.getDescription()); } @@ -404,7 +460,7 @@ public class CatalogNodeManagerController extends FormBasicController implements } private void loadResources(UserRequest ureq) { - catalogEntry = catalogManager.getCatalogEntryByKey(catalogEntry.getKey()); + catalogEntry = catalogManager.loadCatalogEntry(catalogEntry); List<CatalogEntry> detachedChildren = catalogManager.getChildrenOf(catalogEntry); SearchRepositoryEntryParameters params = new SearchRepositoryEntryParameters(getIdentity(), ureq.getUserSession().getRoles()); @@ -455,14 +511,22 @@ public class CatalogNodeManagerController extends FormBasicController implements } if(entry.getEntryStatus() == RepositoryEntryStatusEnum.closed) { + FormLink positionLink = uifactory.addFormLink("position_" + counter.incrementAndGet(), "positionClosedEntries", String.valueOf(row.getPosition() + 1), null, null, Link.NONTRANSLATED); + positionLink.setUserObject(row); + row.setPositionLink(positionLink); + closedItems.add(row); } else { + FormLink positionLink = uifactory.addFormLink("position_" + counter.incrementAndGet(), "positionEntries", String.valueOf(row.getPosition() + 1), null, null, Link.NONTRANSLATED); + positionLink.setUserObject(row); + row.setPositionLink(positionLink); + items.add(row); } } Comparator<CatalogEntryRow> comparator = (row1, row2) -> { - return ((Integer)row1.getPosition()).compareTo(row2.getPosition()); + return row1.getPosition().compareTo(row2.getPosition()); }; Collections.sort(items, comparator); @@ -475,16 +539,25 @@ public class CatalogNodeManagerController extends FormBasicController implements closedEntriesModel.setObjects(closedItems); closedEntriesEl.reset(true, true, true); closedEntriesEl.setVisible(closedEntriesModel.getRowCount() > 0); + + flc.setDirty(true); } protected void loadNodesChildren() { + catalogEntry = catalogManager.loadCatalogEntry(catalogEntry); List<CatalogEntry> catalogChildren = catalogManager.getChildrenOf(catalogEntry); List<String> subCategories = new ArrayList<>(); List<NodeEntryRow> nodeEntries = new ArrayList<>(); int count = 0; for (CatalogEntry entry : catalogChildren) { if(entry != null && entry.getType() == CatalogEntry.TYPE_NODE) { - nodeEntries.add(new NodeEntryRow(entry)); + NodeEntryRow row = new NodeEntryRow(entry); + + FormLink positionLink = uifactory.addFormLink("position_" + counter.incrementAndGet(), "positionNodes", String.valueOf(row.getPosition() + 1), null, null, Link.NONTRANSLATED); + positionLink.setUserObject(row); + row.setPositionLink(positionLink); + + nodeEntries.add(row); String cmpId = "cat_" + (++count); @@ -496,13 +569,21 @@ public class CatalogNodeManagerController extends FormBasicController implements flc.contextPut("k" + cmpId, entry.getKey()); String title = StringHelper.escapeHtml(entry.getName()); + String shortTitle; + if (entry.getShortTitle() == null) { + shortTitle = StringHelper.escapeHtml(entry.getName()); + } else { + shortTitle = StringHelper.escapeHtml(entry.getShortTitle()); + } Link link = LinkFactory.createCustomLink(cmpId, "select_node", cmpId, Link.LINK + Link.NONTRANSLATED, flc.getFormItemComponent(), this); link.setIconLeftCSS("o_icon o_icon_catalog_sub"); link.setCustomDisplayText(title); link.setUserObject(entry.getKey()); subCategories.add(Integer.toString(count)); String titleId = "title_" + count; + String shortTitleId = "short_title_" + count; flc.contextPut(titleId, title); + flc.contextPut(shortTitleId, shortTitle); } } flc.contextPut("subCategories", subCategories); @@ -516,6 +597,8 @@ public class CatalogNodeManagerController extends FormBasicController implements nodeEntriesModel.setObjects(nodeEntries); nodeEntriesEl.reset(true, true, true); nodeEntriesEl.setVisible(nodeEntriesModel.getRowCount() > 0); + + flc.setDirty(true); } protected void initToolbar() { @@ -525,55 +608,89 @@ public class CatalogNodeManagerController extends FormBasicController implements if (canAdministrateCategory || canAddLinks) { if (canAdministrateCategory) { - orderLink = LinkFactory.createToolLink("order", translate("tools.order.catalog"), this, "o_icon_order"); - orderLink.setElementCssClass("o_sel_catalog_order_category"); - toolbarPanel.addTool(orderLink, Align.right); + if (orderLink == null) { + orderLink = LinkFactory.createToolLink("order", translate("tools.order.catalog"), this, "o_icon_order"); + orderLink.setElementCssClass("o_sel_catalog_order_category"); + toolbarPanel.addTool(orderLink, Align.right); + } else { + orderLink.setVisible(true); + } } if (canAdministrateCategory) { - editLink = LinkFactory.createToolLink("edit", translate("tools.edit.catalog.category"), this, "o_icon_edit"); - editLink.setElementCssClass("o_sel_catalog_edit_category"); - toolbarPanel.addTool(editLink, Align.left); + if (editLink == null) { + editLink = LinkFactory.createToolLink("edit", translate("tools.edit.catalog.category"), this, "o_icon_edit"); + editLink.setElementCssClass("o_sel_catalog_edit_category"); + toolbarPanel.addTool(editLink, Align.left); + } else { + editLink.setVisible(true); + } } if (canAdministrateCategory) { - nominateLink = LinkFactory.createToolLink("nominate", translate("tools.edit.catalog.category.ownergroup"), this, "o_icon_user"); - nominateLink.setElementCssClass("o_sel_catalog_category_owner"); - toolbarPanel.addTool(nominateLink, Align.right); + if (nominateLink == null) { + nominateLink = LinkFactory.createToolLink("nominate", translate("tools.edit.catalog.category.ownergroup"), this, "o_icon_user"); + nominateLink.setElementCssClass("o_sel_catalog_category_owner"); + toolbarPanel.addTool(nominateLink, Align.right); + } else { + nominateLink.setVisible(true); + } } if (canAddLinks) { - contactLink = LinkFactory.createToolLink("contact", translate("tools.new.catalog.categoryrequest"), this, "o_icon_mail"); - contactLink.setElementCssClass("o_sel_catalog_contact_owner"); - toolbarPanel.addTool(contactLink, Align.right); + if (contactLink == null) { + contactLink = LinkFactory.createToolLink("contact", translate("tools.new.catalog.categoryrequest"), this, "o_icon_mail"); + contactLink.setElementCssClass("o_sel_catalog_contact_owner"); + toolbarPanel.addTool(contactLink, Align.right); + } else { + nominateLink.setVisible(true); + } } if (canAdministrateCategory && catalogEntry.getParent() != null) { // delete root? very dangerous, disabled! - deleteLink = LinkFactory.createToolLink("delete", translate("tools.delete.catalog.entry"), this, "o_icon_delete"); - deleteLink.setElementCssClass("o_sel_catalog_delete_category"); - toolbarPanel.addTool(deleteLink, Align.left); + if (deleteLink == null) { + deleteLink = LinkFactory.createToolLink("delete", translate("tools.delete.catalog.entry"), this, "o_icon_delete"); + deleteLink.setElementCssClass("o_sel_catalog_delete_category"); + toolbarPanel.addTool(deleteLink, Align.left); + } else { + deleteLink.setVisible(true); + } } if (canAdministrateCategory && catalogEntry.getParent() != null) { - moveLink = LinkFactory.createToolLink("move", translate("tools.move.catalog.entry"), this, "o_icon_move"); - moveLink.setElementCssClass("o_sel_catalog_move_category"); - toolbarPanel.addTool(moveLink, Align.left); + if (moveLink == null) { + moveLink = LinkFactory.createToolLink("move", translate("tools.move.catalog.entry"), this, "o_icon_move"); + moveLink.setElementCssClass("o_sel_catalog_move_category"); + toolbarPanel.addTool(moveLink, Align.left); + } else { + moveLink.setVisible(true); + } } } if(isAdministrator || isLocalTreeAdmin || isAuthor) { if (canAddSubCategories) { - addCategoryLink = LinkFactory.createToolLink("addResource", translate("tools.add.catalog.category"), this, "o_icon_catalog_sub"); - addCategoryLink.setElementCssClass("o_sel_catalog_add_category"); - toolbarPanel.addTool(addCategoryLink, Align.left); + if (addCategoryLink == null) { + addCategoryLink = LinkFactory.createToolLink("addResource", translate("tools.add.catalog.category"), this, "o_icon_catalog_sub"); + addCategoryLink.setElementCssClass("o_sel_catalog_add_category"); + toolbarPanel.addTool(addCategoryLink, Align.left); + } else { + addCategoryLink.setVisible(true); + } + } if (canAddLinks) { - addResourceLink = LinkFactory.createToolLink("addResource", translate("tools.add.catalog.link"), this, "o_icon_add"); - addResourceLink.setElementCssClass("o_sel_catalog_add_link_to_resource"); - toolbarPanel.addTool(addResourceLink, Align.left); + if (addResourceLink == null) { + addResourceLink = LinkFactory.createToolLink("addResource", translate("tools.add.catalog.link"), this, "o_icon_add"); + addResourceLink.setElementCssClass("o_sel_catalog_add_link_to_resource"); + toolbarPanel.addTool(addResourceLink, Align.left); + } else { + addResourceLink.setVisible(true); + } } } } @Override protected void doDispose() { - // + this.toolbarPanel.removeListener(this); + releaseLock(); } @Override @@ -645,7 +762,7 @@ public class CatalogNodeManagerController extends FormBasicController implements doMoveCatalogEntry(row.getCatEntryKey(), cmd, ureq); } else if (cmd.equals(CMD_UP)) { doMoveCatalogEntry(row.getCatEntryKey(), cmd, ureq); - } + } } } else if(closedEntriesEl == source) { if(event instanceof SelectionEvent) { @@ -664,7 +781,7 @@ public class CatalogNodeManagerController extends FormBasicController implements doMoveCatalogEntry(row.getCatEntryKey(), cmd, ureq); } else if (cmd.equals(CMD_UP)) { doMoveCatalogEntry(row.getCatEntryKey(), cmd, ureq); - } + } } } else if (nodeEntriesEl == source) { if (event instanceof SelectionEvent) { @@ -675,8 +792,31 @@ public class CatalogNodeManagerController extends FormBasicController implements doMoveCatalogEntry(row.getKey(), cmd, ureq); } else if (cmd.equals(CMD_UP)) { doMoveCatalogEntry(row.getKey(), cmd, ureq); - } + } } + } else if(source instanceof FormLink) { + FormLink link = (FormLink) source; + + if("positionNodes".equals(link.getCmd())) { + int size = nodeEntriesModel.getObjects().size(); + int smallest = nodeEntriesModel.getObject(0).getPosition(); + int biggest = nodeEntriesModel.getObject(size - 1).getPosition(); + + doOpenPositionDialog(ureq, link, smallest, biggest); + } else if("positionEntries".equals(link.getCmd())) { + int size = entriesModel.getObjects().size(); + int smallest = entriesModel.getObject(0).getPosition(); + int biggest = entriesModel.getObject(size - 1).getPosition(); + + doOpenPositionDialog(ureq, link, smallest, biggest); + } else if("positionClosedEntries".equals(link.getCmd())) { + int size = closedEntriesModel.getObjects().size(); + int smallest = closedEntriesModel.getObject(0).getPosition(); + int biggest = closedEntriesModel.getObject(size - 1).getPosition(); + + doOpenPositionDialog(ureq, link, smallest, biggest); + } + } super.formInnerEvent(ureq, source, event); @@ -718,6 +858,13 @@ public class CatalogNodeManagerController extends FormBasicController implements logWarn("Not a valid long: " + node, e); } } + } else if (toolbarPanel == source) { + if (event instanceof PopEvent) { + loadNodesChildren(); + loadResources(ureq); + loadEntryInfos(); + } + } super.event(ureq, source, event); } @@ -738,6 +885,7 @@ public class CatalogNodeManagerController extends FormBasicController implements } cmc.deactivate(); cleanUp(); + toolbarPanel.changeDisplayname(catalogEntry.getShortTitle()); fireEvent(ureq, Event.CHANGED_EVENT); } else if(categoryMoveCtrl == source) { cmc.deactivate(); @@ -773,6 +921,7 @@ public class CatalogNodeManagerController extends FormBasicController implements } } else if(childNodeCtrl == source) { if(event == Event.BACK_EVENT) { + toolbarPanel.popController(childNodeCtrl); toolbarPanel.popUpToController(this); removeAsListenerAndDispose(childNodeCtrl); childNodeCtrl = null; @@ -801,27 +950,37 @@ public class CatalogNodeManagerController extends FormBasicController implements CatalogEntryRow row = (CatalogEntryRow)dialogDeleteLink.getUserObject(); catalogManager.deleteCatalogEntry(row, catalogEntry); loadResources(ureq); +// toolbarPanel.popController(this); + fireEvent(ureq, Event.BACK_EVENT); } } else if(entryResourceMoveCtrl == source) { + CatalogEntry moveMe = entryResourceMoveCtrl.getMoveMe(); if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) { - CatalogEntry moveMe = entryResourceMoveCtrl.getMoveMe(); showInfo("tools.move.catalog.entry.success", moveMe.getName()); loadResources(ureq); + } else if (event == Event.FAILED_EVENT) { + showError("tools.move.catalog.entry.success", moveMe.getName()); } cmc.deactivate(); cleanUp(); + } else if (positionCtrl == source) { + if (event == Event.DONE_EVENT) { + loadNodesChildren(); + loadResources(ureq); + } + positionCalloutCtrl.deactivate(); + cleanUp(); + fireEvent(ureq, Event.CHANGED_EVENT); } else if(cmc == source) { + loadNodesChildren(); + loadResources(ureq); cleanUp(); } super.event(ureq, source, event); } private void cleanUp() { - //remove the lock, always - if (catModificationLock != null && catModificationLock.isSuccess()) { - CoordinatorManager.getInstance().getCoordinator().getLocker().releaseLock(catModificationLock); - catModificationLock = null; - } + releaseLock(); removeAsListenerAndDispose(cmc); removeAsListenerAndDispose(groupCtrl); @@ -829,12 +988,27 @@ public class CatalogNodeManagerController extends FormBasicController implements removeAsListenerAndDispose(addEntryCtrl); removeAsListenerAndDispose(editEntryCtrl); removeAsListenerAndDispose(entrySearchCtrl); + removeAsListenerAndDispose(positionCtrl); + removeAsListenerAndDispose(positionCalloutCtrl); + removeAsListenerAndDispose(positionMoveCtrl); + cmc = null; groupCtrl = null; contactCtrl = null; addEntryCtrl = null; editEntryCtrl = null; entrySearchCtrl = null; + positionCtrl = null; + positionCalloutCtrl = null; + positionMoveCtrl = null; + } + + private void releaseLock() { + //remove the lock, always + if (catModificationLock != null && catModificationLock.isSuccess()) { + CoordinatorManager.getInstance().getCoordinator().getLocker().releaseLock(catModificationLock); + catModificationLock = null; + } } private CatalogNodeManagerController selectCatalogEntry(UserRequest ureq, CatalogEntry entry) { @@ -847,7 +1021,7 @@ public class CatalogNodeManagerController extends FormBasicController implements childNodeCtrl = new CatalogNodeManagerController(ureq, bwControl, rootwControl, entry, toolbarPanel, isLocalTreeAdmin); listenTo(childNodeCtrl); - toolbarPanel.pushController(entry.getName(), childNodeCtrl); + toolbarPanel.pushController(entry.getShortTitle(), childNodeCtrl); childNodeCtrl.initToolbar(); addToHistory(ureq, childNodeCtrl); @@ -856,57 +1030,27 @@ public class CatalogNodeManagerController extends FormBasicController implements } private void doActivateOrdering(UserRequest ureq) { - initForm(ureq); - - loadEntryInfos(); - loadNodesChildren(); - loadResources(ureq); - - if (isOrdering) { - entriesEl.setColumnModelVisible(leafUpColumnModel, false); - entriesEl.setColumnModelVisible(leafDownColumnModel, false); - entriesEl.setColumnModelVisible(leafPositionColumnModel, false); - - closedEntriesEl.setColumnModelVisible(leafUpColumnModel, false); - closedEntriesEl.setColumnModelVisible(leafDownColumnModel, false); - closedEntriesEl.setColumnModelVisible(leafPositionColumnModel, false); - - entriesEl.reset(); - closedEntriesEl.reset(); + catModificationLock = CoordinatorManager.getInstance().getCoordinator().getLocker().acquireLock(lockRes, getIdentity(), LOCK_TOKEN); + if (catModificationLock.isSuccess() && !isOrdering) { + boolean activateOrdering = false; + activateOrdering |= nodeEntriesModel.getObjects().size() > 1; + activateOrdering |= entriesModel.getObjects().size() > 1; + activateOrdering |= closedEntriesModel.getObjects().size() > 1; - for (DefaultFlexiColumnModel columnModel : leafColumns) { - columnModel.setSortable(true); + if (activateOrdering) { + positionMoveCtrl = new CatalogNodeManagerController(ureq, getWindowControl(), rootwControl, catalogEntry, toolbarPanel, isLocalTreeAdmin, true); + listenTo(positionMoveCtrl); + + cmc = new CloseableModalController(getWindowControl(), "close", positionMoveCtrl.getInitialComponent(), true, translate("tools.order.catalog")); + listenTo(cmc); + cmc.activate(); + } else { + showWarning("catalog.position.deactivated"); } - -// for (int i =entriesModel.getColumnCount(); i) { -// entriesModel.getTableColumnModel().getColumnModel(i).setSortable(false); -// } - - nodeEntriesEl.setColumnModelVisible(nodeUpColumnModel, false); - nodeEntriesEl.setColumnModelVisible(nodeDownColumnModel, false); - nodeEntriesEl.reset(); } else { - entriesEl.setColumnModelVisible(leafUpColumnModel, true); - entriesEl.setColumnModelVisible(leafDownColumnModel, true); - entriesEl.setColumnModelVisible(leafPositionColumnModel, true); - - closedEntriesEl.setColumnModelVisible(leafUpColumnModel, true); - closedEntriesEl.setColumnModelVisible(leafDownColumnModel, true); - closedEntriesEl.setColumnModelVisible(leafPositionColumnModel, true); - - entriesEl.reset(); - closedEntriesEl.reset(); - - for (DefaultFlexiColumnModel columnModel : leafColumns) { - columnModel.setSortable(false); - } - - nodeEntriesEl.setColumnModelVisible(nodeUpColumnModel, true); - nodeEntriesEl.setColumnModelVisible(nodeDownColumnModel, true); - nodeEntriesEl.reset(); + String ownerName = userManager.getUserDisplayName(catModificationLock.getOwner()); + showError("catalog.locked.by", ownerName); } - isOrdering = !isOrdering; - flc.contextPut("isOrdering", isOrdering); } private void doMoveCatalogEntry(Long key, String command, UserRequest ureq) { @@ -918,25 +1062,63 @@ public class CatalogNodeManagerController extends FormBasicController implements loadResources(ureq); } + private void doOpenPositionDialog(UserRequest ureq, FormLink link, int smallest, int biggest) { + removeAsListenerAndDispose(positionCalloutCtrl); + removeAsListenerAndDispose(positionCtrl); + + catModificationLock = CoordinatorManager.getInstance().getCoordinator().getLocker().acquireLock(lockRes, getIdentity(), LOCK_TOKEN); + if (catModificationLock.isSuccess()) { + Object rowObject = link.getUserObject(); + + + if (rowObject instanceof NodeEntryRow) { + NodeEntryRow row = (NodeEntryRow) rowObject; + positionCtrl = new CatalogEntryPositionDialogController(ureq, getWindowControl(), row.getKey(), smallest, biggest); + } else if (rowObject instanceof CatalogEntryRow) { + CatalogEntryRow row = (CatalogEntryRow) rowObject; + positionCtrl = new CatalogEntryPositionDialogController(ureq, getWindowControl(), row.getCatEntryKey(), smallest, biggest); + } else { + return; + } + + listenTo(positionCtrl); + + CalloutSettings settings = new CalloutSettings(true); + positionCalloutCtrl = new CloseableCalloutWindowController(ureq, getWindowControl(),positionCtrl.getInitialComponent(), link.getFormDispatchId(), "", true, "", settings); + listenTo(positionCalloutCtrl); + positionCalloutCtrl.activate(); + + } else { + String ownerName = userManager.getUserDisplayName(catModificationLock.getOwner()); + showError("catalog.locked.by", ownerName); + } + } + private void doAddResource(UserRequest ureq) { removeAsListenerAndDispose(entrySearchCtrl); removeAsListenerAndDispose(cmc); - - entrySearchCtrl = new RepositorySearchController(translate("choose"), ureq, getWindowControl(), true, false, new String[0], false, null); - listenTo(entrySearchCtrl); - // OLAT-Admin has search form - if (isAdministrator) { - entrySearchCtrl.displaySearchForm(); - } - // an Author gets the list of his repository - else { - // admin is responsible for not inserting wrong visibility entries!! - entrySearchCtrl.doSearchByOwnerLimitAccess(ureq.getIdentity()); + + catModificationLock = CoordinatorManager.getInstance().getCoordinator().getLocker().acquireLock(lockRes, getIdentity(), LOCK_TOKEN); + if (catModificationLock.isSuccess()) { + entrySearchCtrl = new RepositorySearchController(translate("choose"), ureq, getWindowControl(), true, false, new String[0], false, null); + listenTo(entrySearchCtrl); + // OLAT-Admin has search form + if (isAdministrator) { + entrySearchCtrl.displaySearchForm(); + } + // an Author gets the list of his repository + else { + // admin is responsible for not inserting wrong visibility entries!! + entrySearchCtrl.doSearchByOwnerLimitAccess(ureq.getIdentity()); + } + // open form in dialog + cmc = new CloseableModalController(getWindowControl(), "close", entrySearchCtrl.getInitialComponent(), true, translate("tools.add.catalog.link")); + listenTo(cmc); + cmc.activate(); + } else { + String ownerName = userManager.getUserDisplayName(catModificationLock.getOwner()); + showError("catalog.locked.by", ownerName); } - // open form in dialog - cmc = new CloseableModalController(getWindowControl(), "close", entrySearchCtrl.getInitialComponent(), true, translate("tools.add.catalog.link")); - listenTo(cmc); - cmc.activate(); } private void doAddResource(UserRequest ureq, RepositoryEntry selectedEntry) { diff --git a/src/main/java/org/olat/repository/ui/catalog/CatalogSiteMainController.java b/src/main/java/org/olat/repository/ui/catalog/CatalogSiteMainController.java index abfc1cd5d108feed9e926527ef64fc900a695574..c488df4c0d1be502c6707af763b8438b35b21dfe 100644 --- a/src/main/java/org/olat/repository/ui/catalog/CatalogSiteMainController.java +++ b/src/main/java/org/olat/repository/ui/catalog/CatalogSiteMainController.java @@ -22,7 +22,6 @@ package org.olat.repository.ui.catalog; import java.util.List; import org.olat.core.CoreSpringFactory; -import org.olat.core.commons.chiefcontrollers.BaseChiefController; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.stack.BreadcrumbedStackedPanel; @@ -30,13 +29,10 @@ 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.gui.control.generic.dtabs.Activateable2; -import org.olat.core.gui.translator.Translator; import org.olat.core.id.context.ContextEntry; import org.olat.core.id.context.StateEntry; -import org.olat.core.util.Util; import org.olat.repository.CatalogEntry; import org.olat.repository.manager.CatalogManager; -import org.olat.repository.ui.catalog.CatalogNodeController; /** * @@ -53,16 +49,19 @@ public class CatalogSiteMainController extends BasicController implements Activa super(ureq, wControl); stackPanel = new BreadcrumbedStackedPanel("catstack", getTranslator(), this); + stackPanel.setInvisibleCrumb(0); // show root level + putInitialPanel(stackPanel); CatalogManager catalogManager = CoreSpringFactory.getImpl(CatalogManager.class); List<CatalogEntry> rootNodes = catalogManager.getRootCatalogEntries(); + CatalogEntry root = rootNodes.get(0); + // use same title as catalog site title + if(rootNodes.size() == 1) { - nodeController = new CatalogNodeController(ureq, getWindowControl(), getWindowControl(), rootNodes.get(0), stackPanel, true); + nodeController = new CatalogNodeController(ureq, getWindowControl(), getWindowControl(), root, stackPanel, true); } - // use same title as catalog site title - Translator catTrans = Util.createPackageTranslator(BaseChiefController.class, getLocale()); - stackPanel.pushController(catTrans.translate("topnav.catalog"), nodeController); + stackPanel.pushController(root.getShortTitle(), nodeController); } @Override diff --git a/src/main/java/org/olat/repository/ui/catalog/NodeEntryRow.java b/src/main/java/org/olat/repository/ui/catalog/NodeEntryRow.java index e785878faf188b2806d2c035cc865c4ea89f264b..29cbb493df5de03a9c3d733d02a40e7207f2f7c1 100644 --- a/src/main/java/org/olat/repository/ui/catalog/NodeEntryRow.java +++ b/src/main/java/org/olat/repository/ui/catalog/NodeEntryRow.java @@ -21,6 +21,7 @@ package org.olat.repository.ui.catalog; import java.util.Date; +import org.olat.core.gui.components.form.flexible.elements.FormLink; import org.olat.repository.CatalogEntry; /** @@ -35,6 +36,7 @@ public class NodeEntryRow { private String name; private Date creationDate; private int position; + private FormLink positionLink; public NodeEntryRow(CatalogEntry view) { key = view.getKey(); @@ -62,4 +64,12 @@ public class NodeEntryRow { public int getPosition() { return position; } + + public FormLink getPositionLink() { + return positionLink; + } + + public void setPositionLink(FormLink positionLink) { + this.positionLink = positionLink; + } } \ No newline at end of file diff --git a/src/main/java/org/olat/repository/ui/catalog/NodeEntryRowModel.java b/src/main/java/org/olat/repository/ui/catalog/NodeEntryRowModel.java index 1f30361da3849d4a0658d5d6806ed739c6479490..129fe0e43b875b1360d41023ad13c06a6071ff2b 100644 --- a/src/main/java/org/olat/repository/ui/catalog/NodeEntryRowModel.java +++ b/src/main/java/org/olat/repository/ui/catalog/NodeEntryRowModel.java @@ -58,9 +58,9 @@ public class NodeEntryRowModel extends DefaultFlexiTableDataModel<NodeEntryRow> case type: return item; case displayName: return item.getDisplayname(); case creationDate: return item.getCreationDate(); - case position: return item.getPosition(); + case position: return item.getPositionLink(); + default: return "ERROR"; } - return null; } public enum NodeCols { diff --git a/src/main/java/org/olat/repository/ui/catalog/_content/catPosition.html b/src/main/java/org/olat/repository/ui/catalog/_content/catPosition.html new file mode 100644 index 0000000000000000000000000000000000000000..04c9e5729b3d8714a252ca3e6539bccb34e2c042 --- /dev/null +++ b/src/main/java/org/olat/repository/ui/catalog/_content/catPosition.html @@ -0,0 +1,32 @@ + <div class="row"> + <div class="col-sm-12 form-group"> + <center> + <h4>$r.get("catalog_entry_name")</h4> + </center> + </div> + </div> + <div class="row"> + <center> + <div class="col-sm-12 form-group"> + <div class="o_block_inline">$r.render("catalog.popup.position.smallest")</div> + <div class="o_block_inline">$r.render("catalog.popup.position.smaller")</div> + + <div class="o_block_inline #if($f.hasError('catalog.popup.position.set')) has-error #end"> + $r.render("catalog.popup.position.set") + </div> + <div class="o_block_inline">$r.render("catalog.popup.position.bigger")</div> + <div class="o_block_inline">$r.render("catalog.popup.position.biggest")</div> + #if($f.hasError("catalog.popup.position.set")) + <div class=""> + $r.render("catalog.popup.position.set_ERROR") + </div> + #end + </div> + </center> + </div> + + <div class="row"> + <div class="col-sm-offset-3 col-sm-6 form-group"> + <center>$r.render("save")</center> + </div> + </div> diff --git a/src/main/java/org/olat/repository/ui/catalog/_content/node.html b/src/main/java/org/olat/repository/ui/catalog/_content/node.html index 232d65918ad5ef51b67093377bad931a9ea6af44..486c8ee254a85875fd3f6a1e85991138fd883b88 100644 --- a/src/main/java/org/olat/repository/ui/catalog/_content/node.html +++ b/src/main/java/org/olat/repository/ui/catalog/_content/node.html @@ -3,18 +3,19 @@ #if ($isGuest) <div class="o_warning">${r.translate("filtered.first")}${r.render("cat.login")}${r.translate("filtered.second")}</div> #end - + + #if (!$isOrdering) <div class="o_level o_level_${catalogLevel} row"> <div class="o_visual"> #if($catThumbnail) - <img src="$mapperThumbnailUrl/${catThumbnail}" alt="$r.escapeHtml($catalogEntryName)"/> + <img src="$mapperThumbnailUrl/${catThumbnail}" alt="$r.escapeHtml($catalogEntryTitle)"/> #else <div class="o_visual_not_available"></div> #end </div> <div class="o_meta clearfix"> - <h2 class="o_title"> - $r.escapeHtml($catalogEntryName) + <h2 class="o_title" title="$catalogEntryShortTitle"> + $r.escapeHtml($catalogEntryTitle) </h2> #if($catalogEntryDesc) <div class="o_desc o_user_content_block"> @@ -23,7 +24,6 @@ #end </div> </div> - #if(!$isOrdering) #if($subCategories.size() != 0) #if($listStyle == "list") <div class="o_sublevels_list row clearfix"> @@ -57,12 +57,13 @@ #foreach($id in $subCategories) #set($imgId = "image_${id}") #set($catId = "kcat_${id}") - <div class="o_sublevel"> + #set($shortTitleId = "short_title_${id}") + <div class="o_sublevel" title="$catalogEntryTitle"> <div class="o_visual"><a $r.hrefAndOnclick("img_select",false,false,"node","$r.get($catId)")> <span class="o_visual_not_available" #if($r.get($imgId)) style="background-image:url('$mapperThumbnailUrl/${r.get($imgId)}');" #end></span> </a></div> <div class="o_meta"> - <h4 class="o_title">$r.render("cat_${id}")</h4> + <h4 class="o_title">$r.get("short_title_${id}")</h4> </div> </div> #end @@ -82,35 +83,38 @@ #end #if($r.available("closedEntries") && $r.visible("closedEntries")) + <br> <h3><i class="o_icon o_CourseModule_icon_closed"> </i> $r.translate("closed.resources.title")</h3> $r.render("closedEntries") #end - #if($extLink || $guestExtLink) - <div class="o_extlink clearfix o_block_large_bottom"> - <h4>$r.translate("cat.externalLink")</h4> - #if($extLink) - <div class="o_copy_code o_nowrap"><a href="javascript:;" id="o_extlink"><i class="o_icon o_icon-lg o_icon-fw o_icon_qrcode"> </i></a><input type="text" value="$extLink" onclick="this.select()"/> - <script> - /* <![CDATA[ */ - jQuery(function() { - o_QRCodePopup('o_extlink', '$extLink', 'right'); - }); - /* ]]> */ - </script> - </div> - #end - #if($guestExtLink) - <div class="o_copy_code o_nowrap"><a href="javascript:;" id="o_guestextlink"><i class="o_icon o_icon-lg o_icon-fw o_icon_qrcode"> </i></a><input type="text" value="$guestExtLink" onclick="this.select()"/> - <script> - /* <![CDATA[ */ - jQuery(function() { - o_QRCodePopup('o_guestextlink', '$guestExtLink', 'right'); - }); - /* ]]> */ - </script> - </div> + #if(!$isOrdering) + #if($extLink || $guestExtLink) + <div class="o_extlink clearfix o_block_large_bottom"> + <h4>$r.translate("cat.externalLink")</h4> + #if($extLink) + <div class="o_copy_code o_nowrap"><a href="javascript:;" id="o_extlink"><i class="o_icon o_icon-lg o_icon-fw o_icon_qrcode"> </i></a><input type="text" value="$extLink" onclick="this.select()"/> + <script> + /* <![CDATA[ */ + jQuery(function() { + o_QRCodePopup('o_extlink', '$extLink', 'right'); + }); + /* ]]> */ + </script> + </div> + #end + #if($guestExtLink) + <div class="o_copy_code o_nowrap"><a href="javascript:;" id="o_guestextlink"><i class="o_icon o_icon-lg o_icon-fw o_icon_qrcode"> </i></a><input type="text" value="$guestExtLink" onclick="this.select()"/> + <script> + /* <![CDATA[ */ + jQuery(function() { + o_QRCodePopup('o_guestextlink', '$guestExtLink', 'right'); + }); + /* ]]> */ + </script> + </div> + #end + </div> #end - </div> #end </div> \ No newline at end of file diff --git a/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_de.properties index 2c01bc12f67d898ae5a2e06a1a5f8f90ecf43507..6ce5125fdc385d2bef8afa9d123fd2805073e647 100644 --- a/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_de.properties @@ -7,6 +7,15 @@ cat.login=Login cat.move.submit=Element verschieben. cat.move.title=Eintrag an Kategorie anh\u00E4ngen\! catalog.locked.by=Die Aktion kann nicht ausgef\u00fchrt werden, da der Katalog zur Zeit vom Benutzer {0} bearbeitet wird. +catalog.popup.edit.shorttitle.desc=Setzen Sie einen Kurztitel zur Anzeige bei den Tiles. +catalog.popup.position.error.number.format=Nur Zahlen eingeben +catalog.popup.position.error.number=Werte von {0} bis {1} sind zul\u00e4ssig +catalog.popup.position.bigger=\u003E +catalog.popup.position.biggest=\u226B +catalog.popup.position.save=Speichern +catalog.popup.position.smaller=\u003C +catalog.popup.position.smallest=\u226A +catalog.position.deactivated=Bitte f\u00FCgen Sie weiter Elemente hinzu um die Sortierung zu verändern! catalog.tree.add.already.exists=Die Lernressource {0} ist bereits in dieser Katalogkategorie vorhanden. catalog.tree.add.intro=W\u00E4hlen Sie eine Kategorie aus, in die Sie die Lernressource {0} verschieben m\u00F6chten. catalog.tree.add.title=Lernressource "{0}" in Katalog hinzuf\u00FCgen @@ -27,7 +36,7 @@ contact.caretaker=Anfrage schicken contact.to.groupname.caretaker=Verwaltergruppe der Kategorie dialog.modal.leaf.delete.text=Wollen Sie den Link "{0}" wirklich l\u00F6schen? dialog.modal.subtree.delete.text=Wollen Sie die Kategorie "{0}" und alle damit verbundenen Unterkategorien respektive Links, wirklich l\u00F6schen? -entry.category=Name +entry.category=Titel entry.description=Beschreibung entry.leaf=Lernressource entry.shorttitle=Kurztitel @@ -55,4 +64,5 @@ tools.move.catalog.entry.success=Der Katalogeintrag "{0}" wurde erfolgreich vers tools.new.catalog.categoryrequest=Verwalter kontaktieren tools.order.catalog=Manuell ordnen tools.pastestructure=Struktur einf\u00FCgen +tools.set.catalog.position=Position anpassen entry.pic=Bild diff --git a/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_en.properties index 6bbc8a90b90aeb6ce2603a3eedb54e5afd568878..5240d1290a633068556b96e0d8faeb6af826a496 100644 --- a/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/repository/ui/catalog/_i18n/LocalStrings_en.properties @@ -10,6 +10,15 @@ catalog.classic=Catalog in learning resources catalog.courses=My courses catalog.locked.by=Cannot start action at this time because this catalog is currently being edited by user {0} catalog.new=Catalog in own site +catalog.popup.edit.shorttitle.desc=Add a short title for tiles view. +catalog.popup.position.error.number.format=Only numeric inputs +catalog.popup.position.error.number=Only values from {0} to {1} +catalog.popup.position.bigger=\u003E +catalog.popup.position.biggest=\u226B +catalog.popup.position.save=Save +catalog.popup.position.smaller=\u003C +catalog.popup.position.smallest=\u226A +catalog.position.deactivated=Please add more elements to customize the order! catalog.tree.add.already.exists=The learning resource {0} is already attached to this catalog category catalog.tree.add.intro=Select a catalog category to which you want to move the learning resource {0} catalog.tree.add.title=Add learning resource "{0}" to catalog @@ -23,7 +32,7 @@ contact.caretaker=Send request contact.to.groupname.caretaker=Administrator group of category dialog.modal.leaf.delete.text=Do you really want to delete the link "{0}"? dialog.modal.subtree.delete.text=Do you really want to delete category "{0}" as well as all associated sub-categories or links? -entry.category=Name +entry.category=Title entry.description=Description entry.leaf=Learning resource entry.pic=Image @@ -56,3 +65,4 @@ tools.move.catalog.entry.success=Catalog entry "{0}" successfully moved tools.order.catalog=Manual ordering tools.new.catalog.categoryrequest=Contact administrator tools.pastestructure=Insert structure +tools.set.catalog.position=Modifiy position diff --git a/src/main/java/org/olat/repository/ui/list/OverviewRepositoryListController.java b/src/main/java/org/olat/repository/ui/list/OverviewRepositoryListController.java index d607b447dcff1f6689ab2349ae75156c0401388e..5386cd22990abcfbe9f3b75a7f0d4d0d5ad0b9c2 100644 --- a/src/main/java/org/olat/repository/ui/list/OverviewRepositoryListController.java +++ b/src/main/java/org/olat/repository/ui/list/OverviewRepositoryListController.java @@ -297,7 +297,7 @@ public class OverviewRepositoryListController extends BasicController implements ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores)); WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); markedStackPanel = new BreadcrumbedStackedPanel("mrkstack", getTranslator(), this); - markedCtrl = new RepositoryEntryListController(ureq, bwControl, searchParams, true, false, "marked", markedStackPanel); + markedCtrl = new RepositoryEntryListController(ureq, bwControl, searchParams, true, false, true, "marked", markedStackPanel); markedStackPanel.pushController(translate("search.mark"), markedCtrl); listenTo(markedCtrl); currentCtrl = markedCtrl; @@ -320,7 +320,7 @@ public class OverviewRepositoryListController extends BasicController implements ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores)); WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); myCoursesStackPanel = new BreadcrumbedStackedPanel("mystack", getTranslator(), this); - myCoursesCtrl = new RepositoryEntryListController(ureq, bwControl, searchParams, true, false, "my", myCoursesStackPanel); + myCoursesCtrl = new RepositoryEntryListController(ureq, bwControl, searchParams, true, false, true, "my", myCoursesStackPanel); myCoursesStackPanel.pushController(translate("search.mycourses.student"), myCoursesCtrl); listenTo(myCoursesCtrl); currentCtrl = myCoursesCtrl; @@ -391,7 +391,7 @@ public class OverviewRepositoryListController extends BasicController implements ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores)); WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); searchCoursesStackPanel = new BreadcrumbedStackedPanel("search", getTranslator(), this); - searchCoursesCtrl = new RepositoryEntryListController(ureq, bwControl, searchParams, false, true, "my-search", searchCoursesStackPanel); + searchCoursesCtrl = new RepositoryEntryListController(ureq, bwControl, searchParams, false, true, true, "my-search", searchCoursesStackPanel); searchCoursesStackPanel.pushController(translate("search.mycourses.student"), searchCoursesCtrl); listenTo(searchCoursesCtrl); currentCtrl = searchCoursesCtrl; @@ -413,7 +413,7 @@ public class OverviewRepositoryListController extends BasicController implements ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores)); WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); myCoursesStackPanel = new BreadcrumbedStackedPanel("mystack", getTranslator(), this); - closedCoursesCtrl = new RepositoryEntryListController(ureq, bwControl, searchParams, true, false, "closed", myCoursesStackPanel); + closedCoursesCtrl = new RepositoryEntryListController(ureq, bwControl, searchParams, true, false, true, "closed", myCoursesStackPanel); myCoursesStackPanel.pushController(translate("search.mycourses.student"), closedCoursesCtrl); listenTo(closedCoursesCtrl); currentCtrl = closedCoursesCtrl; diff --git a/src/main/java/org/olat/repository/ui/list/RepositoryEntryListController.java b/src/main/java/org/olat/repository/ui/list/RepositoryEntryListController.java index 2199f297bc976e2d9506e07baa91731fdaa711dd..7d9e6aeba9d7afbc13397866fbdc33bf61b5ae0e 100644 --- a/src/main/java/org/olat/repository/ui/list/RepositoryEntryListController.java +++ b/src/main/java/org/olat/repository/ui/list/RepositoryEntryListController.java @@ -106,6 +106,7 @@ public class RepositoryEntryListController extends FormBasicController private final List<Link> orderByLinks = new ArrayList<>(); private boolean withSearch; + private boolean withSavedSettings; private final String name; private FlexiTableElement tableEl; @@ -135,13 +136,14 @@ public class RepositoryEntryListController extends FormBasicController public RepositoryEntryListController(UserRequest ureq, WindowControl wControl, SearchMyRepositoryEntryViewParams searchParams, boolean load, - boolean withSearch, String name, BreadcrumbPanel stackPanel) { + boolean withSearch, boolean withSavedSettings, String name, BreadcrumbPanel stackPanel) { super(ureq, wControl, "repoentry_table"); setTranslator(Util.createPackageTranslator(RepositoryManager.class, getLocale(), getTranslator())); mapperThumbnailKey = mapperService.register(null, "repositoryentryImage", new RepositoryEntryImageMapper()); this.name = name; this.stackPanel = stackPanel; this.withSearch = withSearch; + this.withSavedSettings = withSavedSettings; guestOnly = ureq.getUserSession().getRoles().isGuestOnly(); OLATResourceable ores = OresHelper.createOLATResourceableType("MyCoursesSite"); @@ -235,9 +237,15 @@ public class RepositoryEntryListController extends FormBasicController initSorters(tableEl); tableEl.setAndLoadPersistedPreferences(ureq, "re-list-v2-".concat(name)); + + if (!withSavedSettings) { + SortKey sortKey = new SortKey(OrderBy.custom.name(), true); + tableEl.sort(sortKey); + } + loadFilterPreferences(ureq); } - + private void initFilters(FlexiTableElement tableElement) { List<FlexiTableFilter> filters = new ArrayList<>(16); filters.add(new FlexiTableFilter(translate("filter.show.all"), Filter.showAll.name(), true)); diff --git a/src/main/java/org/olat/upgrade/OLATUpgrade_15_pre_4.java b/src/main/java/org/olat/upgrade/OLATUpgrade_15_pre_5.java similarity index 95% rename from src/main/java/org/olat/upgrade/OLATUpgrade_15_pre_4.java rename to src/main/java/org/olat/upgrade/OLATUpgrade_15_pre_5.java index c00d1667f3605277f8a41807c44c676dd82f90bf..d1f3fdfb2963d1c73641bf2b796bc6e4d6257fa1 100644 --- a/src/main/java/org/olat/upgrade/OLATUpgrade_15_pre_4.java +++ b/src/main/java/org/olat/upgrade/OLATUpgrade_15_pre_5.java @@ -41,11 +41,11 @@ import org.springframework.beans.factory.annotation.Autowired; * @author aboeckle, alexander.boeckle@frentix.com, http://www.frentix.com * */ -public class OLATUpgrade_15_pre_4 extends OLATUpgrade { +public class OLATUpgrade_15_pre_5 extends OLATUpgrade { - private static final Logger log = Tracing.createLoggerFor(OLATUpgrade_15_pre_4.class); + private static final Logger log = Tracing.createLoggerFor(OLATUpgrade_15_pre_5.class); - private static final String VERSION = "OLAT_15.pre.4"; + private static final String VERSION = "OLAT_15.pre.5"; private static final String CATALOG_ORDER_INDEX = "CATALOG ORDER INDEX"; private AtomicInteger migrationCounter = new AtomicInteger(0); @@ -53,7 +53,7 @@ public class OLATUpgrade_15_pre_4 extends OLATUpgrade { @Autowired private DB dbInstance; - public OLATUpgrade_15_pre_4() { + public OLATUpgrade_15_pre_5() { super(); } @@ -78,9 +78,9 @@ public class OLATUpgrade_15_pre_4 extends OLATUpgrade { uhd.setInstallationComplete(allOk); upgradeManager.setUpgradesHistory(uhd, VERSION); if(allOk) { - log.info(Tracing.M_AUDIT, "Finished OLATUpgrade_15_pre_4 successfully!"); + log.info(Tracing.M_AUDIT, "Finished OLATUpgrade_15_pre_5 successfully!"); } else { - log.info(Tracing.M_AUDIT, "OLATUpgrade_15_pre_4 not finished, try to restart OpenOlat!"); + log.info(Tracing.M_AUDIT, "OLATUpgrade_15_pre_5 not finished, try to restart OpenOlat!"); } return allOk; } diff --git a/src/main/java/org/olat/upgrade/_spring/databaseUpgradeContext.xml b/src/main/java/org/olat/upgrade/_spring/databaseUpgradeContext.xml index 53762a4d93acb03e261d4c8d774bfb771dd5ccf2..882f8e8cad8999420b72b4f852151224b8ae13c2 100644 --- a/src/main/java/org/olat/upgrade/_spring/databaseUpgradeContext.xml +++ b/src/main/java/org/olat/upgrade/_spring/databaseUpgradeContext.xml @@ -224,6 +224,10 @@ <constructor-arg index="0" value="OLAT_15.pre.4" /> <property name="alterDbStatements" value="alter_15_pre_0_to_15_pre_4.sql" /> </bean> + <bean id="database_upgrade_15_pre_5" class="org.olat.upgrade.DatabaseUpgrade"> + <constructor-arg index="0" value="OLAT_15.pre.5" /> + <property name="alterDbStatements" value="alter_15_pre_0_to_15_pre_5.sql" /> + </bean> </list> </property> </bean> diff --git a/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml b/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml index e3ba4be72ea0c375ad9b55c62d66f8163aa6ff06..d84720f54986300e1e8efa09ee2ec5075d2d67ea 100644 --- a/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml +++ b/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml @@ -54,7 +54,7 @@ <bean id="upgrade_14_0_5" class="org.olat.upgrade.OLATUpgrade_14_0_5"/> <bean id="upgrade_14_1_0" class="org.olat.upgrade.OLATUpgrade_14_1_0"/> <bean id="upgrade_14_2_0" class="org.olat.upgrade.OLATUpgrade_14_2_0"/> - <bean id="upgrade_15_pre_4" class="org.olat.upgrade.OLATUpgrade_15_pre_4"/><!-- because really quicker as pre.0 --> + <bean id="upgrade_15_pre_5" class="org.olat.upgrade.OLATUpgrade_15_pre_5"/><!-- because really quicker as pre.0 --> <bean id="upgrade_15_pre_0" class="org.olat.upgrade.OLATUpgrade_15_pre_0"/> </list> </property> diff --git a/src/main/resources/database/mysql/alter_15_pre_0_to_15_pre_5.sql b/src/main/resources/database/mysql/alter_15_pre_0_to_15_pre_5.sql new file mode 100644 index 0000000000000000000000000000000000000000..3a7de8e9146c691ee489f5578a5d0109f99e8c85 --- /dev/null +++ b/src/main/resources/database/mysql/alter_15_pre_0_to_15_pre_5.sql @@ -0,0 +1,2 @@ +-- CATALOG +UPDATE o_catentry SET short_title = name; \ No newline at end of file diff --git a/src/main/resources/database/oracle/alter_15_pre_0_to_15_pre_5.sql b/src/main/resources/database/oracle/alter_15_pre_0_to_15_pre_5.sql new file mode 100644 index 0000000000000000000000000000000000000000..3a7de8e9146c691ee489f5578a5d0109f99e8c85 --- /dev/null +++ b/src/main/resources/database/oracle/alter_15_pre_0_to_15_pre_5.sql @@ -0,0 +1,2 @@ +-- CATALOG +UPDATE o_catentry SET short_title = name; \ No newline at end of file diff --git a/src/main/resources/database/postgresql/alter_15_pre_0_to_15_pre_5.sql b/src/main/resources/database/postgresql/alter_15_pre_0_to_15_pre_5.sql new file mode 100644 index 0000000000000000000000000000000000000000..3a7de8e9146c691ee489f5578a5d0109f99e8c85 --- /dev/null +++ b/src/main/resources/database/postgresql/alter_15_pre_0_to_15_pre_5.sql @@ -0,0 +1,2 @@ +-- CATALOG +UPDATE o_catentry SET short_title = name; \ No newline at end of file diff --git a/src/test/java/org/olat/repository/RepositoryManagerTest.java b/src/test/java/org/olat/repository/RepositoryManagerTest.java index 57af128295da9e17f0a45e1677a2dc8d6586af78..297da1001c67b838f9a784996ef7bb0279d85fb9 100644 --- a/src/test/java/org/olat/repository/RepositoryManagerTest.java +++ b/src/test/java/org/olat/repository/RepositoryManagerTest.java @@ -56,6 +56,15 @@ import org.olat.core.util.resource.OresHelper; import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupService; import org.olat.group.manager.BusinessGroupRelationDAO; +import org.olat.repository.LeavingStatusList; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryEntryAllowToLeaveOptions; +import org.olat.repository.RepositoryEntryManagedFlag; +import org.olat.repository.RepositoryEntryOrder; +import org.olat.repository.RepositoryEntrySecurity; +import org.olat.repository.RepositoryEntryStatusEnum; +import org.olat.repository.RepositoryManager; +import org.olat.repository.RepositoryService; import org.olat.repository.manager.RepositoryEntryLifecycleDAO; import org.olat.repository.manager.RepositoryEntryRelationDAO; import org.olat.repository.model.RepositoryEntryLifecycle; diff --git a/src/test/java/org/olat/repository/manager/RepositoryServiceImplTest.java b/src/test/java/org/olat/repository/manager/RepositoryServiceImplTest.java index 2120a6fbbe63a7bb1b7dd4a0bc2735ae49d8ccee..221b6beed141e9684a3af0538fcce3f686d133fd 100644 --- a/src/test/java/org/olat/repository/manager/RepositoryServiceImplTest.java +++ b/src/test/java/org/olat/repository/manager/RepositoryServiceImplTest.java @@ -137,7 +137,7 @@ public class RepositoryServiceImplTest extends OlatTestCase { catEntry.setName("Soft"); catEntry.setRepositoryEntry(re); catEntry.setParent(rootEntries.get(0)); - catalogManager.saveCatalogEntry(catEntry); + catalogManager.addCatalogEntry(rootEntries.get(0), catEntry); dbInstance.commit(); //check the catalog diff --git a/src/test/java/org/olat/repository/ui/catalog/CatalogManagerTest.java b/src/test/java/org/olat/repository/ui/catalog/CatalogManagerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b1cb2d93cb065a1e9370cb0d94fd4ae71b041af9 --- /dev/null +++ b/src/test/java/org/olat/repository/ui/catalog/CatalogManagerTest.java @@ -0,0 +1,665 @@ +/** + * <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.repository.ui.catalog; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.Random; + +import org.junit.Assert; +import org.junit.Test; +import org.olat.basesecurity.BaseSecurity; +import org.olat.basesecurity.OrganisationService; +import org.olat.basesecurity.manager.SecurityGroupDAO; +import org.olat.core.commons.persistence.DB; +import org.olat.core.id.Identity; +import org.olat.core.id.OLATResourceable; +import org.olat.core.id.Organisation; +import org.olat.course.CourseModule; +import org.olat.repository.CatalogEntry; +import org.olat.repository.CatalogEntry.Style; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryEntryStatusEnum; +import org.olat.repository.RepositoryManager; +import org.olat.repository.RepositoryService; +import org.olat.repository.manager.CatalogManager; +import org.olat.resource.OLATResource; +import org.olat.resource.OLATResourceManager; +import org.olat.test.JunitTestHelper; +import org.olat.test.OlatTestCase; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 12.03.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CatalogManagerTest extends OlatTestCase { + + @Autowired + private DB dbInstance; + @Autowired + private CatalogManager catalogManager; + @Autowired + private RepositoryManager repositoryManager; + @Autowired + private OLATResourceManager orm; + @Autowired + private RepositoryService repositoryService; + @Autowired + private OrganisationService organisationService; + @Autowired + private BaseSecurity securityManager; + @Autowired + private SecurityGroupDAO securityGroupDao; + + Random random = new Random(); + + private void afterPropoertiesSet() { + try { + catalogManager.afterPropertiesSet(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private CatalogEntry generateEntry(int type, String name, Style style) { + CatalogEntry catalogEntry = catalogManager.createCatalogEntry(); + + catalogEntry.setName(name); + catalogEntry.setType(type); + catalogEntry.setStyle(style); + + return catalogEntry; + } + + private CatalogEntry saveEntry(CatalogEntry catalogEntry, CatalogEntry parentEntry) { + parentEntry = catalogManager.loadCatalogEntry(parentEntry); + + catalogEntry.setParent(parentEntry); + catalogManager.saveCatalogEntry(catalogEntry); + + List<CatalogEntry> children = parentEntry.getChildren(); + children.add(catalogEntry); + catalogManager.updateCatalogEntry(parentEntry); + dbInstance.commit(); + + return catalogEntry; + } + + private CatalogEntry getRootEntry() { + return catalogManager.getRootCatalogEntries().get(0); + } + + private RepositoryEntry createRepository(String displayName, final Long resourceableId) { + OLATResourceable resourceable = new OLATResourceable() { + @Override + public String getResourceableTypeName() { return CourseModule.ORES_TYPE_COURSE;} + @Override + public Long getResourceableId() {return resourceableId;} + }; + + // create course and persist as OLATResourceImpl + + OLATResource r = orm.findResourceable(resourceable); + if(r == null) { + r = orm.createOLATResourceInstance(resourceable); + } + dbInstance.saveObject(r); + dbInstance.intermediateCommit(); + + RepositoryEntry d = repositoryManager.lookupRepositoryEntry(resourceable, false); + if(d == null) { + Organisation defOrganisation = organisationService.getDefaultOrganisation(); + d = repositoryService.create(null, "Rei Ayanami", "-", displayName, "Repo entry", + r, RepositoryEntryStatusEnum.trash, defOrganisation); + dbInstance.saveObject(d); + } + dbInstance.intermediateCommit(); + return d; + } + + @Test + public void createCatalogEntry() { + afterPropoertiesSet(); + CatalogEntry catalogEntry = catalogManager.createCatalogEntry(); + + Assert.assertNotNull(catalogEntry); + Assert.assertNotNull(catalogEntry.getOwnerGroup()); + } + + @Test + public void getNodesChildrenOf() { + afterPropoertiesSet(); + + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry parentEntry = generateEntry(CatalogEntry.TYPE_NODE, "1parent", Style.compact); + CatalogEntry child1 = generateEntry(CatalogEntry.TYPE_NODE, "1child1", Style.compact); + CatalogEntry child2 = generateEntry(CatalogEntry.TYPE_NODE, "1child2", Style.compact); + + parentEntry.setParent(rootEntry); + catalogManager.saveCatalogEntry(parentEntry); + dbInstance.commit(); + + List<CatalogEntry> rootChildren = rootEntry.getChildren(); + rootChildren.add(parentEntry); + catalogManager.saveCatalogEntry(rootEntry); + dbInstance.commit(); + + child1.setParent(parentEntry); + catalogManager.saveCatalogEntry(child1); + child2.setParent(parentEntry); + catalogManager.saveCatalogEntry(child2); + dbInstance.commit(); + + List<CatalogEntry> children = parentEntry.getChildren(); + children.add(child1); + children.add(child2); + catalogManager.saveCatalogEntry(parentEntry); + dbInstance.commit(); + + children = catalogManager.getNodesChildrenOf(parentEntry); + + Assert.assertNotNull(children); + Assert.assertArrayEquals(new int[] {2}, new int[] {children.size()}); + } + + @Test + public void getChildrenOf() { + afterPropoertiesSet(); + + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry parentEntry = generateEntry(CatalogEntry.TYPE_NODE, "2parent", Style.compact); + CatalogEntry child1 = generateEntry(CatalogEntry.TYPE_NODE, "2child1", Style.compact); + CatalogEntry child2 = generateEntry(CatalogEntry.TYPE_NODE, "2child2", Style.compact); + CatalogEntry child3 = generateEntry(CatalogEntry.TYPE_LEAF, "2child3", null); + CatalogEntry child4 = generateEntry(CatalogEntry.TYPE_LEAF, "2child4", null); + + parentEntry.setParent(rootEntry); + catalogManager.saveCatalogEntry(parentEntry); + dbInstance.commit(); + + List<CatalogEntry> rootChildren = rootEntry.getChildren(); + rootChildren.add(parentEntry); + catalogManager.saveCatalogEntry(rootEntry); + dbInstance.commit(); + + child1.setParent(parentEntry); + catalogManager.saveCatalogEntry(child1); + child2.setParent(parentEntry); + catalogManager.saveCatalogEntry(child2); + child3.setParent(parentEntry); + catalogManager.saveCatalogEntry(child3); + child4.setParent(parentEntry); + catalogManager.saveCatalogEntry(child4); + dbInstance.commit(); + + List<CatalogEntry> children = parentEntry.getChildren(); + children.add(child1); + children.add(child2); + children.add(child3); + children.add(child4); + catalogManager.saveCatalogEntry(parentEntry); + dbInstance.commit(); + + children = catalogManager.getChildrenOf(parentEntry); + + Assert.assertNotNull(children); + Assert.assertArrayEquals(new int[] {4}, new int[] {children.size()}); + } + + @Test + public void getAllCatalogNodes() { + afterPropoertiesSet(); + + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry parentEntry = generateEntry(CatalogEntry.TYPE_NODE, "3parent", Style.compact); + CatalogEntry child1 = generateEntry(CatalogEntry.TYPE_NODE, "3child1", Style.compact); + CatalogEntry child2 = generateEntry(CatalogEntry.TYPE_NODE, "3child2", Style.compact); + + parentEntry.setParent(rootEntry); + catalogManager.saveCatalogEntry(parentEntry); + dbInstance.commit(); + + List<CatalogEntry> rootChildren = rootEntry.getChildren(); + rootChildren.add(parentEntry); + catalogManager.saveCatalogEntry(rootEntry); + dbInstance.commit(); + + child1.setParent(parentEntry); + catalogManager.saveCatalogEntry(child1); + child2.setParent(parentEntry); + catalogManager.saveCatalogEntry(child2); + dbInstance.commit(); + + List<CatalogEntry> children = parentEntry.getChildren(); + children.add(child1); + children.add(child2); + catalogManager.saveCatalogEntry(parentEntry); + dbInstance.commit(); + + List<CatalogEntry> nodes = catalogManager.getAllCatalogNodes(); + + Assert.assertNotNull(nodes); + for (CatalogEntry catalogEntry : nodes) { + Assert.assertTrue(catalogEntry.getType() == CatalogEntry.TYPE_NODE); + } + } + + @Test + public void hasChildEntries() { + afterPropoertiesSet(); + + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry child1 = generateEntry(CatalogEntry.TYPE_LEAF, "4child1", null); + CatalogEntry child2 = generateEntry(CatalogEntry.TYPE_NODE, "4child2", Style.compact); + + child1.setParent(rootEntry); + catalogManager.saveCatalogEntry(child1); + child2.setParent(rootEntry); + catalogManager.saveCatalogEntry(child2); + dbInstance.commit(); + + List<CatalogEntry> children = rootEntry.getChildren(); + children.add(child1); + children.add(child2); + catalogManager.saveCatalogEntry(rootEntry); + dbInstance.commit(); + + Assert.assertTrue(catalogManager.hasChildEntries(rootEntry, CatalogEntry.TYPE_LEAF)); + Assert.assertTrue(catalogManager.hasChildEntries(rootEntry, CatalogEntry.TYPE_NODE)); + } + + @Test + public void countChildrenOf() { + afterPropoertiesSet(); + + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry parentEntry = generateEntry(CatalogEntry.TYPE_NODE, "5parent", Style.compact); + CatalogEntry child1 = generateEntry(CatalogEntry.TYPE_NODE, "5child1", Style.compact); + CatalogEntry child2 = generateEntry(CatalogEntry.TYPE_NODE, "5child2", Style.compact); + CatalogEntry child3 = generateEntry(CatalogEntry.TYPE_LEAF, "5child3", null); + CatalogEntry child4 = generateEntry(CatalogEntry.TYPE_LEAF, "5child4", null); + + parentEntry.setParent(rootEntry); + catalogManager.saveCatalogEntry(parentEntry); + dbInstance.commit(); + + List<CatalogEntry> rootChildren = rootEntry.getChildren(); + rootChildren.add(parentEntry); + catalogManager.saveCatalogEntry(rootEntry); + dbInstance.commit(); + + child1.setParent(parentEntry); + catalogManager.saveCatalogEntry(child1); + child2.setParent(parentEntry); + catalogManager.saveCatalogEntry(child2); + child3.setParent(parentEntry); + catalogManager.saveCatalogEntry(child3); + child4.setParent(parentEntry); + catalogManager.saveCatalogEntry(child4); + dbInstance.commit(); + + List<CatalogEntry> children = parentEntry.getChildren(); + children.add(child1); + children.add(child2); + children.add(child3); + children.add(child4); + catalogManager.saveCatalogEntry(parentEntry); + dbInstance.commit(); + + children = catalogManager.getChildrenOf(parentEntry); + + Assert.assertArrayEquals(new int[] {2, 2}, new int[] { + catalogManager.countChildrenOf(parentEntry, CatalogEntry.TYPE_LEAF), + catalogManager.countChildrenOf(parentEntry, CatalogEntry.TYPE_NODE) + }); + } + + @Test + public void loadCatalogEntryByKey() { + afterPropoertiesSet(); + + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry catalogEntry = generateEntry(CatalogEntry.TYPE_NODE, "6parent", Style.compact); + + saveEntry(catalogEntry, rootEntry); + + CatalogEntry compareEntry = catalogManager.getCatalogEntryByKey(catalogEntry.getKey()); + + Assert.assertTrue(catalogEntry.equals(compareEntry)); + } + + @Test + public void saveCatalogEntry() { + afterPropoertiesSet(); + + String name = "7SaveTestName"; + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry catalogEntry = generateEntry(CatalogEntry.TYPE_NODE, name, Style.compact); + + saveEntry(catalogEntry, rootEntry); + + CatalogEntry compareEntry = catalogManager.getCatalogEntryByKey(catalogEntry.getKey()); + + Assert.assertEquals(catalogEntry.getName(), compareEntry.getName()); + } + + @Test + public void deleteCatalogEntry() { + afterPropoertiesSet(); + + String name = "8DeleteTestName"; + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry parentEntry = generateEntry(CatalogEntry.TYPE_NODE, "8parentDelete", Style.compact); + CatalogEntry catalogEntry1 = generateEntry(CatalogEntry.TYPE_NODE, name, Style.compact); + CatalogEntry catalogEntry2 = generateEntry(CatalogEntry.TYPE_LEAF, name, null); + CatalogEntry catalogEntry3 = generateEntry(CatalogEntry.TYPE_LEAF, name, null); + + parentEntry = saveEntry(parentEntry, rootEntry); + catalogEntry1 = saveEntry(catalogEntry1, parentEntry); + catalogEntry2 = saveEntry(catalogEntry2, parentEntry); + catalogEntry3 = saveEntry(catalogEntry3, parentEntry); + + catalogManager.deleteCatalogEntry(catalogEntry2); + catalogManager.deleteCatalogEntry(catalogEntry1); + dbInstance.commit(); + + List<CatalogEntry> children = catalogManager.loadCatalogEntry(parentEntry).getChildren(); + System.out.println(children.size()); + + Assert.assertTrue(catalogManager.loadCatalogEntry(catalogEntry2) == null); + assertThat(children).containsExactlyInAnyOrder(catalogEntry3); + } + + @Test + public void updateCatalogEntry() { + afterPropoertiesSet(); + + String name = "9UpdateTestName"; + String update = " - updated"; + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry parentEntry = generateEntry(CatalogEntry.TYPE_NODE, "9parentDelete", Style.compact); + CatalogEntry catalogEntry1 = generateEntry(CatalogEntry.TYPE_NODE, name, Style.compact); + + parentEntry = saveEntry(parentEntry, rootEntry); + catalogEntry1 = saveEntry(catalogEntry1, parentEntry); + + catalogEntry1.setName(name + update); + catalogManager.updateCatalogEntry(catalogEntry1); + catalogEntry1 = catalogManager.loadCatalogEntry(catalogEntry1); + + assertThat(catalogEntry1.getName()).isEqualTo(name + update); + } + + @Test + public void getCatalogEntriesReferencing() { + afterPropoertiesSet(); + + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry parentEntry1 = generateEntry(CatalogEntry.TYPE_NODE, "10parent1", Style.compact); + CatalogEntry parentEntry2 = generateEntry(CatalogEntry.TYPE_NODE, "10parent2", Style.compact); + CatalogEntry catalogEntry1 = generateEntry(CatalogEntry.TYPE_NODE, "10parent1", Style.compact); + CatalogEntry catalogEntry2 = generateEntry(CatalogEntry.TYPE_NODE, "10parent1", Style.compact); + + RepositoryEntry re = createRepository("10test-entry", random.nextLong()); + catalogEntry1.setRepositoryEntry(re); + catalogEntry2.setRepositoryEntry(re); + + parentEntry1 = saveEntry(parentEntry1, rootEntry); + catalogEntry1 = saveEntry(catalogEntry1, parentEntry1); + parentEntry2 = saveEntry(parentEntry2, rootEntry); + catalogEntry2 = saveEntry(catalogEntry2, parentEntry1); + + assertThat(catalogManager.getCatalogEntriesReferencing(re)).containsExactlyInAnyOrder(catalogEntry1, catalogEntry2); + } + + @Test + public void getCatalogCategoriesFor() { + afterPropoertiesSet(); + + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry parentEntry1 = generateEntry(CatalogEntry.TYPE_NODE, "11parent1", Style.compact); + CatalogEntry parentEntry2 = generateEntry(CatalogEntry.TYPE_NODE, "11parent2", Style.compact); + CatalogEntry catalogEntry1 = generateEntry(CatalogEntry.TYPE_NODE, "11parent1", Style.compact); + CatalogEntry catalogEntry2 = generateEntry(CatalogEntry.TYPE_NODE, "11parent1", Style.compact); + + RepositoryEntry re = createRepository("test-entry", random.nextLong()); + catalogEntry1.setRepositoryEntry(re); + catalogEntry2.setRepositoryEntry(re); + + parentEntry1 = saveEntry(parentEntry1, rootEntry); + catalogEntry1 = saveEntry(catalogEntry1, parentEntry1); + parentEntry2 = saveEntry(parentEntry2, rootEntry); + catalogEntry2 = saveEntry(catalogEntry2, parentEntry2); + + assertThat(catalogManager.getCatalogCategoriesFor(re)).containsExactlyInAnyOrder(parentEntry1, parentEntry2); + } + + @Test + public void getCatalogEntryBy() { + afterPropoertiesSet(); + + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry parentEntry1 = generateEntry(CatalogEntry.TYPE_NODE, "12parent1", Style.compact); + CatalogEntry parentEntry2 = generateEntry(CatalogEntry.TYPE_NODE, "12parent2", Style.compact); + CatalogEntry catalogEntry1 = generateEntry(CatalogEntry.TYPE_NODE, "12parent1", Style.compact); + CatalogEntry catalogEntry2 = generateEntry(CatalogEntry.TYPE_NODE, "12parent1", Style.compact); + + RepositoryEntry re = createRepository("test-entry", random.nextLong()); + catalogEntry1.setRepositoryEntry(re); + + parentEntry1 = saveEntry(parentEntry1, rootEntry); + catalogEntry1 = saveEntry(catalogEntry1, parentEntry1); + parentEntry2 = saveEntry(parentEntry2, rootEntry); + catalogEntry2 = saveEntry(catalogEntry2, parentEntry2); + + assertThat(catalogManager.getCatalogEntryBy(re, parentEntry1)).isEqualTo(catalogEntry1); + assertThat(catalogManager.getCatalogEntryBy(re, parentEntry2)).isNull(); + } + + @Test + public void isOwner() { + afterPropoertiesSet(); + + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry parentEntry1 = generateEntry(CatalogEntry.TYPE_NODE, "13parent1", Style.compact); + CatalogEntry catalogEntry1 = generateEntry(CatalogEntry.TYPE_NODE, "13parent1", Style.compact); + + parentEntry1 = saveEntry(parentEntry1, rootEntry); + catalogEntry1 = saveEntry(catalogEntry1, parentEntry1); + + Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("13catalog-test-identity"); + Identity admin = securityManager.findIdentityByName("administrator"); + + securityGroupDao.addIdentityToSecurityGroup(admin, catalogEntry1.getOwnerGroup()); + dbInstance.commit(); + + assertThat(catalogManager.isOwner(admin)).isTrue(); + assertThat(catalogManager.isOwner(id1)).isFalse(); + assertThat(catalogManager.isOwner(catalogEntry1, admin)).isTrue(); + } + + @Test + public void getOwners() { + afterPropoertiesSet(); + + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry parentEntry1 = generateEntry(CatalogEntry.TYPE_NODE, "14parent1", Style.compact); + CatalogEntry parentEntry2 = generateEntry(CatalogEntry.TYPE_NODE, "14parent2", Style.compact); + CatalogEntry catalogEntry1 = generateEntry(CatalogEntry.TYPE_NODE, "14parent1", Style.compact); + CatalogEntry catalogEntry2 = generateEntry(CatalogEntry.TYPE_NODE, "14parent1", Style.compact); + + RepositoryEntry re = createRepository("test-entry", random.nextLong()); + catalogEntry1.setRepositoryEntry(re); + + parentEntry1 = saveEntry(parentEntry1, rootEntry); + catalogEntry1 = saveEntry(catalogEntry1, parentEntry1); + parentEntry2 = saveEntry(parentEntry2, rootEntry); + catalogEntry2 = saveEntry(catalogEntry2, parentEntry2); + + Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser("14catalog-test-identity"); + Identity admin = securityManager.findIdentityByName("administrator"); + + securityGroupDao.addIdentityToSecurityGroup(admin, catalogEntry1.getOwnerGroup()); + securityGroupDao.addIdentityToSecurityGroup(admin, catalogEntry2.getOwnerGroup()); + securityGroupDao.addIdentityToSecurityGroup(id1, catalogEntry2.getOwnerGroup()); + dbInstance.commit(); + + assertThat(catalogManager.getOwners(catalogEntry1)).contains(admin); + assertThat(catalogManager.getOwners(catalogEntry2)).contains(admin, id1); + } + + @Test + public void addCatalogEntry() { + afterPropoertiesSet(); + + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry parentEntry1 = generateEntry(CatalogEntry.TYPE_NODE, "15parent1", Style.compact); + CatalogEntry parentEntry2 = generateEntry(CatalogEntry.TYPE_NODE, "15parent2", Style.compact); + CatalogEntry catalogEntry1 = generateEntry(CatalogEntry.TYPE_LEAF, "15child1", null); + CatalogEntry catalogEntry2 = generateEntry(CatalogEntry.TYPE_LEAF, "15child2", null); + + catalogManager.addCatalogEntry(rootEntry, parentEntry1); + catalogManager.addCatalogEntry(rootEntry, parentEntry2); + catalogManager.addCatalogEntry(parentEntry1, catalogEntry1); + catalogManager.addCatalogEntry(parentEntry2, catalogEntry2); + + rootEntry = catalogManager.loadCatalogEntry(rootEntry); + parentEntry1 = catalogManager.loadCatalogEntry(parentEntry1); + parentEntry2 = catalogManager.loadCatalogEntry(parentEntry2); + catalogEntry1 = catalogManager.loadCatalogEntry(catalogEntry1); + catalogEntry2 = catalogManager.loadCatalogEntry(catalogEntry2); + + assertThat(rootEntry.getChildren()).contains(parentEntry1, parentEntry2); + assertThat(parentEntry1.getChildren()).contains(catalogEntry1); + assertThat(parentEntry2.getChildren()).contains(catalogEntry2); + + assertThat(parentEntry1.getChildren()).doesNotContain(catalogEntry2); + assertThat(parentEntry2.getChildren()).doesNotContain(catalogEntry1); + } + + @Test + public void getRootCatalogEntries() { + afterPropoertiesSet(); + assertThat(catalogManager.getRootCatalogEntries()).hasSize(1); + } + + @Test + public void moveCatalogEntry() { + afterPropoertiesSet(); + + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry parentEntryA = generateEntry(CatalogEntry.TYPE_NODE, "16parentA", Style.compact); + CatalogEntry parentEntryAA = generateEntry(CatalogEntry.TYPE_NODE, "16parentAA", Style.compact); + CatalogEntry parentEntryB = generateEntry(CatalogEntry.TYPE_NODE, "16parentB", Style.compact); + CatalogEntry parentEntryBA = generateEntry(CatalogEntry.TYPE_NODE, "16parentBA", Style.compact); + CatalogEntry catalogEntryAA1 = generateEntry(CatalogEntry.TYPE_LEAF, "16childAA1", null); + CatalogEntry catalogEntryAA2 = generateEntry(CatalogEntry.TYPE_LEAF, "16childAA2", null); + CatalogEntry catalogEntryAA3 = generateEntry(CatalogEntry.TYPE_LEAF, "16childAA3", null); + CatalogEntry catalogEntryB1 = generateEntry(CatalogEntry.TYPE_LEAF, "16childB1", null); + + catalogEntryAA1.setRepositoryEntry(createRepository("16test-entry" + random.nextInt(), random.nextLong())); + catalogEntryAA2.setRepositoryEntry(createRepository("16test-entry" + random.nextInt(), random.nextLong())); + catalogEntryAA3.setRepositoryEntry(createRepository("16test-entry" + random.nextInt(), random.nextLong())); + + catalogManager.addCatalogEntry(rootEntry, parentEntryA); + catalogManager.addCatalogEntry(rootEntry, parentEntryB); + catalogManager.addCatalogEntry(parentEntryA, parentEntryAA); + catalogManager.addCatalogEntry(parentEntryB, parentEntryBA); + + catalogManager.addCatalogEntry(parentEntryAA, catalogEntryAA1); + catalogManager.addCatalogEntry(parentEntryAA, catalogEntryAA2); + catalogManager.addCatalogEntry(parentEntryAA, catalogEntryAA3); + catalogManager.addCatalogEntry(parentEntryB, catalogEntryB1); + + parentEntryA = catalogManager.loadCatalogEntry(parentEntryA); + parentEntryAA = catalogManager.loadCatalogEntry(parentEntryAA); + parentEntryB = catalogManager.loadCatalogEntry(parentEntryA); + parentEntryBA = catalogManager.loadCatalogEntry(parentEntryBA); + + catalogEntryAA1 = catalogManager.loadCatalogEntry(catalogEntryAA1); + catalogEntryAA2 = catalogManager.loadCatalogEntry(catalogEntryAA2); + catalogEntryAA3 = catalogManager.loadCatalogEntry(catalogEntryAA3); + catalogEntryB1 = catalogManager.loadCatalogEntry(catalogEntryB1); + + assertThat(catalogManager.moveCatalogEntry(parentEntryA, parentEntryAA)).isFalse(); + assertThat(catalogEntryAA3.getPosition()).isEqualTo(2); + assertThat(catalogManager.moveCatalogEntry(catalogEntryAA2, parentEntryBA)).isTrue(); + assertThat(catalogEntryAA2.getPosition()).isEqualTo(1); + assertThat(catalogManager.moveCatalogEntry(parentEntryAA, parentEntryBA)); + assertThat(catalogEntryB1.getPosition()).isEqualTo(1); + assertThat(parentEntryAA.getPosition()).isEqualTo(0); + } + + @Test + public void reorderCatalogEntry() { + afterPropoertiesSet(); + + CatalogEntry rootEntry = getRootEntry(); + CatalogEntry parentEntryA = generateEntry(CatalogEntry.TYPE_NODE, "17parentA", Style.compact); + CatalogEntry parentEntryAA = generateEntry(CatalogEntry.TYPE_NODE, "17parentAA", Style.compact); + CatalogEntry parentEntryB = generateEntry(CatalogEntry.TYPE_NODE, "17parentB", Style.compact); + CatalogEntry parentEntryBA = generateEntry(CatalogEntry.TYPE_NODE, "17parentBA", Style.compact); + CatalogEntry catalogEntryAA1 = generateEntry(CatalogEntry.TYPE_LEAF, "17childAA1", null); + CatalogEntry catalogEntryAA2 = generateEntry(CatalogEntry.TYPE_LEAF, "17childAA2", null); + CatalogEntry catalogEntryAA3 = generateEntry(CatalogEntry.TYPE_LEAF, "17childAA3", null); + CatalogEntry catalogEntryB1 = generateEntry(CatalogEntry.TYPE_LEAF, "17childB1", null); + + catalogEntryAA1.setRepositoryEntry(createRepository("17test-entry" + random.nextInt(), random.nextLong())); + catalogEntryAA2.setRepositoryEntry(createRepository("17test-entry" + random.nextInt(), random.nextLong())); + catalogEntryAA3.setRepositoryEntry(createRepository("17test-entry" + random.nextInt(), random.nextLong())); + + catalogManager.addCatalogEntry(rootEntry, parentEntryA); + catalogManager.addCatalogEntry(rootEntry, parentEntryB); + catalogManager.addCatalogEntry(parentEntryA, parentEntryAA); + catalogManager.addCatalogEntry(parentEntryB, parentEntryBA); + + catalogManager.addCatalogEntry(parentEntryAA, catalogEntryAA1); + catalogManager.addCatalogEntry(parentEntryAA, catalogEntryAA2); + catalogManager.addCatalogEntry(parentEntryAA, catalogEntryAA3); + catalogManager.addCatalogEntry(parentEntryB, catalogEntryB1); + + parentEntryA = catalogManager.loadCatalogEntry(parentEntryA); + parentEntryAA = catalogManager.loadCatalogEntry(parentEntryAA); + parentEntryB = catalogManager.loadCatalogEntry(parentEntryA); + parentEntryBA = catalogManager.loadCatalogEntry(parentEntryBA); + + catalogEntryAA1 = catalogManager.loadCatalogEntry(catalogEntryAA1); + catalogEntryAA2 = catalogManager.loadCatalogEntry(catalogEntryAA2); + catalogEntryAA3 = catalogManager.loadCatalogEntry(catalogEntryAA3); + catalogEntryB1 = catalogManager.loadCatalogEntry(catalogEntryB1); + + assertThat(catalogManager.reorderCatalogEntry(parentEntryA.getKey(), catalogEntryB1.getKey(), true)).isEqualTo(1); + assertThat(catalogManager.reorderCatalogEntry(parentEntryAA.getKey(), catalogEntryAA1.getKey(), false)).isEqualTo(0); + + catalogEntryAA1 = catalogManager.loadCatalogEntry(catalogEntryAA1); + assertThat(catalogEntryAA1.getPosition()).isEqualTo(1); + + assertThat(catalogManager.setPosition(catalogEntryB1.getKey(), 10)).isEqualTo(2); + assertThat(catalogManager.setPosition(catalogEntryAA2.getKey(), 0)).isEqualTo(0); + + catalogEntryAA2 = catalogManager.loadCatalogEntry(catalogEntryAA2); + assertThat(catalogEntryAA2.getPosition()).isEqualTo(0); + } + +} \ No newline at end of file diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java index 5f2d79787a17a399b1d6ea98e88f1967b24cbd1b..a7e62c4b13987bb40a10b076a2a9af69e4ed3151 100644 --- a/src/test/java/org/olat/test/AllTestsJunit4.java +++ b/src/test/java/org/olat/test/AllTestsJunit4.java @@ -155,6 +155,7 @@ import org.junit.runners.Suite; org.olat.user.manager.UserDataExportServiceTest.class, org.olat.user.manager.AbsenceLeaveDAOTest.class, org.olat.repository.manager.AutomaticLifecycleServiceTest.class, + org.olat.repository.ui.catalog.CatalogManagerTest.class, org.olat.repository.manager.RepositoryEntryDAOTest.class, org.olat.repository.manager.RepositoryEntryLifecycleDAOTest.class, org.olat.repository.manager.RepositoryEntryRelationDAOTest.class,