From b8a9224da6efd252f5643d06d0b488ab6e64ee89 Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Mon, 1 Apr 2019 10:49:25 +0200
Subject: [PATCH] OO-4000: configure the resource folder in administration

---
 .../version/_i18n/LocalStrings_en.properties  |  33 +++--
 .../library/manager/LibraryManagerImpl.java   |  11 +-
 .../library/ui/LibraryAdminController.java    | 126 +++++++++++++++++-
 .../library/ui/LibraryMainController.java     |  88 ++----------
 .../modules/library/ui/_content/overview.html |   7 +-
 .../ui/_i18n/LocalStrings_de.properties       |   4 +
 .../ui/_i18n/LocalStrings_en.properties       |  20 ++-
 7 files changed, 183 insertions(+), 106 deletions(-)

diff --git a/src/main/java/org/olat/core/commons/services/vfs/ui/version/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/commons/services/vfs/ui/version/_i18n/LocalStrings_en.properties
index 3c999ef2934..38e696ea488 100644
--- a/src/main/java/org/olat/core/commons/services/vfs/ui/version/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/core/commons/services/vfs/ui/version/_i18n/LocalStrings_en.properties
@@ -1,12 +1,24 @@
-#Tue Dec 18 22:46:41 CET 2012
+#Mon Apr 01 10:46:06 CEST 2019
 confirm.delete.orphans=Do you really want to delete all orphan versions?
 confirm.prune.history=Do you really want to delete all versions that exceed the configured version limit?
+download=Download
+dx=dr
 form.version=Versioning
 meta.comment.title=Lock
 meta.locked=File locked
 meta.retainlock=Continue locking of file for other users
 meta.unlock=Unlock file for other users
+table.empty=No orphan version left
+table.header.author=Author
+table.header.comment=Comment
+table.header.date=Date
+table.header.file=File
+table.header.id=Id
+table.header.nr=Revision
+table.header.size=Size
+table.header.versions=Number of versions
 version.author=Author
+version.clean.up=Delete orphan version
 version.comment=Comment
 version.comment.alltitle=Comment/lock
 version.comment.description=Changes are tracked in this document. Please comment your modifications.
@@ -19,28 +31,23 @@ version.deletedBy=Deleted by
 version.deletedFiles=Deleted files
 version.download=Download
 version.initialRevision=Initial version
-version.name=File
-version.noDeletedFiles=There are no deleted files with a change log.
-version.noRevisions=There are no revisions of this file yet.
-version.nr=Revision
-version.restore=Restore
-version.restore.comment=Version {0} restored
-version.restore.failed=File could not be restored.
-table.empty=No orphan version left
-table.header.file=File
-table.header.size=Size
-table.header.versions=Number of versions
-version.clean.up=Delete orphan version
 version.intro=Please set the maximum number of versions for a folder component file (group folder, course folder, etc.).
 version.maintenance.intro=File versions management
 version.maintenance.title=Management
+version.name=File
+version.noDeletedFiles=There are no deleted files with a change log.
+version.noRevisions=There are no revisions of this file yet.
 version.notANumber=No number selected
+version.nr=Revision
 version.numOfVersions=Number of versions
 version.off=Versioning deactivated
 version.orphan.size=Orphan versions size
 version.orphan.size.calc=Calculate size
 version.orphan.size.calculating=Calculating...
 version.prune.history=Cleanup versions
+version.restore=Restore
+version.restore.comment=Version {0} restored
+version.restore.failed=File could not be restored.
 version.show.orphans=List orphan versions
 version.title=Versioning
 version.unlimited=Unlimited
diff --git a/src/main/java/org/olat/modules/library/manager/LibraryManagerImpl.java b/src/main/java/org/olat/modules/library/manager/LibraryManagerImpl.java
index 3609a45f426..e73db478d76 100644
--- a/src/main/java/org/olat/modules/library/manager/LibraryManagerImpl.java
+++ b/src/main/java/org/olat/modules/library/manager/LibraryManagerImpl.java
@@ -51,6 +51,7 @@ import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSItem;
 import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.core.util.vfs.VFSManager;
+import org.olat.core.util.vfs.filters.VFSLeafButSystemFilter;
 import org.olat.core.util.vfs.filters.VFSSystemItemFilter;
 import org.olat.modules.library.LibraryEvent;
 import org.olat.modules.library.LibraryManager;
@@ -118,6 +119,7 @@ public class LibraryManagerImpl implements LibraryManager, InitializingBean, Gen
 		// Instantiate handle for library upload folder, which is stored directly in
 		// the bcroot folder (hence the null parent argument).
 		uploadFolder = VFSManager.olatRootContainer(LIBRARY_UPLOAD_FOLDER_NAME, null);
+		uploadFolder.setDefaultItemFilter(new VFSLeafButSystemFilter());
 		
 		coordinator.getCoordinator().getEventBus().registerFor(this, null, IDENTITY_EVENT_CHANNEL);
 	}
@@ -309,9 +311,12 @@ public class LibraryManagerImpl implements LibraryManager, InitializingBean, Gen
 	 */
 	@Override
 	public void removeExistingLockFile(){
-		File lockFile = new File(getSharedFolder().getBasefile(), NO_FOLDER_INDEXING_LOCKFILE);
-		if (lockFile.exists()) {
-			lockFile.delete();
+		LocalFolderImpl folder = getSharedFolder();
+		if(folder != null && folder.exists()) {
+			File lockFile = new File(folder.getBasefile(), NO_FOLDER_INDEXING_LOCKFILE);
+			if (lockFile.exists()) {
+				lockFile.delete();
+			}
 		}
 	}
 	
diff --git a/src/main/java/org/olat/modules/library/ui/LibraryAdminController.java b/src/main/java/org/olat/modules/library/ui/LibraryAdminController.java
index 07105958cb7..60dbaf182e0 100644
--- a/src/main/java/org/olat/modules/library/ui/LibraryAdminController.java
+++ b/src/main/java/org/olat/modules/library/ui/LibraryAdminController.java
@@ -22,16 +22,26 @@ package org.olat.modules.library.ui;
 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.MultipleSelectionElement;
+import org.olat.core.gui.components.form.flexible.elements.StaticTextElement;
 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.gui.control.generic.closablewrapper.CloseableModalController;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.mail.MailHelper;
+import org.olat.fileresource.types.SharedFolderFileResource;
+import org.olat.modules.library.LibraryManager;
 import org.olat.modules.library.LibraryModule;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryService;
+import org.olat.repository.controllers.ReferencableEntriesSearchController;
 import org.springframework.beans.factory.annotation.Autowired;
 
 /**
@@ -47,15 +57,40 @@ public class LibraryAdminController extends FormBasicController {
 	private MultipleSelectionElement enableEl;
 	private TextElement mailAfterUploadEl;
 	private TextElement mailAfterFreeingEl;
+	private FormLink addSharedFolderButton;
+	private FormLink removeSharedFolderButton;
+	private StaticTextElement sharedFolderNameEl;
+	private FormLayoutContainer sharedFolderCont;
+	
+	private CloseableModalController cmc;
+	private ReferencableEntriesSearchController chooseFolderCtr;
 	
 	@Autowired
 	private LibraryModule libraryModule;
+	@Autowired
+	private LibraryManager libraryManager;
+	@Autowired
+	private RepositoryService repositoryService;
 	
 	public LibraryAdminController(UserRequest ureq, WindowControl wControl) {
 		super(ureq, wControl);
-		
 		initForm(ureq);
 		updateUI();
+		initSharedFolder();
+	}
+	
+	private void initSharedFolder() {
+		String entryKey = libraryModule.getLibraryEntryKey();
+		if(StringHelper.isLong(entryKey)) {
+			RepositoryEntry libraryEntry = repositoryService.loadByKey(Long.valueOf(entryKey));
+			if(libraryEntry != null) {
+				doSelectSharedFolder(libraryEntry);
+			} else {
+				doRemoveSharedFolder();
+			}
+		} else {
+			doRemoveSharedFolder();
+		}
 	}
 
 	@Override
@@ -68,6 +103,14 @@ public class LibraryAdminController extends FormBasicController {
 		enableEl.addActionListener(FormEvent.ONCHANGE);
 		enableEl.select("xx", enabled);
 		
+		sharedFolderNameEl = uifactory.addStaticTextElement("library.shared.folder", "library.shared.folder",
+				translate("library.no.sharedfolder"), formLayout);
+		
+		sharedFolderCont = FormLayoutContainer.createButtonLayout("sharedButtons", getTranslator());
+		formLayout.add(sharedFolderCont);
+		removeSharedFolderButton = uifactory.addFormLink("remove.shared.folder", sharedFolderCont, Link.BUTTON);
+		addSharedFolderButton = uifactory.addFormLink("add.shared.folder", sharedFolderCont, Link.BUTTON);
+		
 		String mailAfterUpload = libraryModule.getEmailContactsToNotifyAfterUpload();
 		mailAfterUploadEl = uifactory.addTextElement("library.configuration.mail.after.upload", 256, mailAfterUpload, formLayout);
 		
@@ -83,6 +126,8 @@ public class LibraryAdminController extends FormBasicController {
 		boolean enabled = enableEl.isAtLeastSelected(1);
 		mailAfterUploadEl.setVisible(enabled);
 		mailAfterFreeingEl.setVisible(enabled);
+		sharedFolderNameEl.setVisible(enabled);
+		sharedFolderCont.setVisible(enabled);
 	}
 
 	@Override
@@ -90,10 +135,36 @@ public class LibraryAdminController extends FormBasicController {
 		//
 	}
 
+	@Override
+	protected void event(UserRequest ureq, Controller source, Event event) {
+		if(chooseFolderCtr == source) {
+			if (event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRY_SELECTED) {
+				RepositoryEntry repoEntry = chooseFolderCtr.getSelectedEntry();
+				doSelectSharedFolder(repoEntry);
+			}
+			cmc.deactivate();
+			cleanUp();
+		} else if(cmc == source) {
+			cleanUp();
+		}
+		super.event(ureq, source, event);
+	}
+	
+	private void cleanUp() {
+		removeAsListenerAndDispose(chooseFolderCtr);
+		removeAsListenerAndDispose(cmc);
+		chooseFolderCtr = null;
+		cmc = null;
+	}
+
 	@Override
 	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
 		if(enableEl == source) {
 			updateUI();
+		} else if(removeSharedFolderButton == source) {
+			doRemoveSharedFolder();
+		} else if(addSharedFolderButton == source) {
+			doDisplaySearchController(ureq);
 		}
 		super.formInnerEvent(ureq, source, event);
 	}
@@ -123,6 +194,59 @@ public class LibraryAdminController extends FormBasicController {
 		if(enabled) {
 			libraryModule.setEmailContactsToNotifyAfterUpload(mailAfterUploadEl.getValue());
 			libraryModule.setEmailContactsToNotifyAfterFreeing(mailAfterFreeingEl.getValue());
+			
+			RepositoryEntry sharedFolder = (RepositoryEntry)sharedFolderNameEl.getUserObject();
+			if(sharedFolder == null) {
+				libraryModule.setLibraryEntryKey(null);
+				libraryManager.removeExistingLockFile();
+			} else if(!sharedFolder.getKey().toString().equals(libraryModule.getLibraryEntryKey())) {
+				libraryManager.removeExistingLockFile();
+				libraryModule.setLibraryEntryKey(sharedFolder.getKey().toString());
+				libraryManager.lockFolderAndPreventDoubleIndexing();
+			}	
+		} else {
+			libraryManager.removeExistingLockFile();
 		}
 	}
+	
+	/**
+	 * Displays the shared folder search controller
+	 * 
+	 * @param ureq
+	 */
+	private void doDisplaySearchController(UserRequest ureq) {
+		if(chooseFolderCtr != null) return;
+		
+		String choose = translate("library.catalog.choose.folder.link");
+		chooseFolderCtr = new ReferencableEntriesSearchController(getWindowControl(), ureq, SharedFolderFileResource.TYPE_NAME, choose);
+		listenTo(chooseFolderCtr);
+		
+		String title = translate("add.shared.folder");
+		cmc = new CloseableModalController(getWindowControl(), "close", chooseFolderCtr.getInitialComponent(), true, title);
+		listenTo(cmc);
+		cmc.activate();
+	}
+	
+	/**
+	 * Updates configuration with selected shared folder.
+	 * 
+	 * @param repoEntry The shared folder entry
+	 * @param ureq The user request
+	 */
+	private void doSelectSharedFolder(RepositoryEntry repoEntry) {
+		sharedFolderNameEl.setValue(StringHelper.escapeHtml(repoEntry.getDisplayname()));
+		sharedFolderNameEl.setUserObject(repoEntry);
+		removeSharedFolderButton.setVisible(true);
+	}
+
+	/**
+	 * Removes the current shared folder from the configuration
+	 * 
+	 * @param ureq The user request
+	 */
+	private void doRemoveSharedFolder() {			
+		sharedFolderNameEl.setValue(translate("library.no.sharedfolder"));
+		sharedFolderNameEl.setUserObject(null);
+		removeSharedFolderButton.setVisible(false);
+	}
 }
diff --git a/src/main/java/org/olat/modules/library/ui/LibraryMainController.java b/src/main/java/org/olat/modules/library/ui/LibraryMainController.java
index 16f3e11c1ea..6704fc802a2 100644
--- a/src/main/java/org/olat/modules/library/ui/LibraryMainController.java
+++ b/src/main/java/org/olat/modules/library/ui/LibraryMainController.java
@@ -76,7 +76,6 @@ import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.core.util.vfs.VFSManager;
 import org.olat.core.util.vfs.filters.VFSContainerFilter;
-import org.olat.fileresource.types.SharedFolderFileResource;
 import org.olat.modules.library.LibraryEvent;
 import org.olat.modules.library.LibraryManager;
 import org.olat.modules.library.LibraryModule;
@@ -86,7 +85,6 @@ import org.olat.modules.library.ui.event.OpenFolderEvent;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryRelationType;
 import org.olat.repository.RepositoryService;
-import org.olat.repository.controllers.ReferencableEntriesSearchController;
 import org.springframework.beans.factory.annotation.Autowired;
 
 
@@ -104,12 +102,14 @@ public class LibraryMainController extends MainLayoutBasicController implements
 	private static final String GUI_CONF_LAYOUT_KEY = "library_layout_conf";
 	private static final String I18N_UPLOAD_FOLDER_DISPLAYNAME = "library.upload.folder.displayname";
 
+	private Link editLink;
+	private Link reviewLink;
+	private Link uploadLink;
 	private MenuTree menuTree;
 	private LibraryTreeModel treeModel;
 	private VelocityContainer overviewVC;
 	
 	private CatalogController catalogCtr;
-	private ReferencableEntriesSearchController chooseFolderCtr;
 	private CloseableModalController dialogCtr;
 	private FolderRunController editFolderCtr;
 	private NewCatalogItemController newCatalogItemCtr;
@@ -164,7 +164,7 @@ public class LibraryMainController extends MainLayoutBasicController implements
 		mapperBaseURL = registerCacheableMapper(ureq, "LibrarySite", mapper);
 		thumbnailMapperBaseURL = registerCacheableMapper(ureq, "LibraryThumbnail", thumbnailMapper);
 		
-		initCtrs(ureq);
+		initCtrs(ureq, catalogEntry);
 	}
 
 	@Override
@@ -180,14 +180,12 @@ public class LibraryMainController extends MainLayoutBasicController implements
 		}
 	}
 	
-	private Link configLink, editLink, reviewLink, uploadLink;
-
 	/**
 	 * Initialize the content
 	 * 
 	 * @param ureq
 	 */
-	public void initCtrs(UserRequest ureq) {
+	private void initCtrs(UserRequest ureq, RepositoryEntry catalogEntry) {
 		// Menu tree
 		menuTree = new MenuTree("menuTree");
 		menuTree.setExpandSelectedNode(false);
@@ -198,21 +196,16 @@ public class LibraryMainController extends MainLayoutBasicController implements
 		overviewVC = createVelocityContainer("overview");
 		overviewVC.contextPut("cssIconClass", ICON_CSS_CLASS);
 		
-		RepositoryEntry repoEntry = libraryManager.getCatalogRepoEntry();
 		boolean isAdmin = ureq.getUserSession().getRoles().isAdministrator();
 		boolean isOwner = false;
-		if (repoEntry != null) {
-			isOwner = repositoryService.hasRoleExpanded(getIdentity(), repoEntry,
+		if (catalogEntry != null) {
+			isOwner = repositoryService.hasRoleExpanded(getIdentity(), catalogEntry,
 					OrganisationRoles.administrator.name(), OrganisationRoles.learnresourcemanager.name(),
 					GroupRoles.owner.name());
 		}
 
 		//admin tools
 		if (isAdmin || isOwner) {
-			if (isAdmin) {
-				configLink = LinkFactory.createButton("library.toolbox.configure", overviewVC, this);
-				configLink.setIconLeftCSS("o_icon o_icon_customize o_icon-lg");
-			}
 			// add edit link
 			editLink = LinkFactory.createButton("edit", overviewVC, this);
 			editLink.setIconLeftCSS("o_icon o_icon-lg o_icon_edit");
@@ -225,6 +218,8 @@ public class LibraryMainController extends MainLayoutBasicController implements
 				reviewLink.setCustomDisplayText(translate("library.toolbox.review.singular"));
 			} else if (numNewItems > 1){
 				reviewLink.setCustomDisplayText(translate("library.toolbox.review.plural", Integer.toString(numNewItems)));
+			} else {
+				reviewLink.setVisible(false);
 			}
 		}
 		uploadLink = LinkFactory.createButton("library.toolbox.upload", overviewVC, this);
@@ -320,8 +315,6 @@ public class LibraryMainController extends MainLayoutBasicController implements
 					}	
 				}
 			}
-		} else if (source == configLink) {
-			displaySearchController(ureq);
 		} else if (source == editLink) {
 			displayEditController(ureq);
 		} else if (source == uploadLink) {
@@ -407,24 +400,7 @@ public class LibraryMainController extends MainLayoutBasicController implements
 	@Override
 	protected void event(UserRequest ureq, Controller source, Event event) {
 		if (source == dialogCtr) {
-			if (chooseFolderCtr != null) removeAsListenerAndDispose(chooseFolderCtr);
-			removeAsListenerAndDispose(dialogCtr);
-		} else if (source == chooseFolderCtr) {
-			if (event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRY_SELECTED) {
-				
-				// remove old lockfile if any present
-				if (libraryManager.getSharedFolder()!=null){
-					libraryManager.removeExistingLockFile();
-				}				
-				// close and save
-				RepositoryEntry repoEntry = chooseFolderCtr.getSelectedEntry();
-				updateRepositoryEntry(ureq, repoEntry);
-				// display the overview panel
-				columnLayoutCtr.setCol3(overviewVC);
-			}
-			removeAsListenerAndDispose(chooseFolderCtr);
-			dialogCtr.deactivate();
-			removeAsListenerAndDispose(dialogCtr);
+			//
 		} else if (source == editLayoutCtr) {
 			if (event == Event.BACK_EVENT) {
 				removeAsListenerAndDispose(editLayoutCtr);
@@ -531,34 +507,6 @@ public class LibraryMainController extends MainLayoutBasicController implements
 		}
 	}
 	
-	private void updateRepositoryEntry(UserRequest ureq, RepositoryEntry repoEntry) {
-		if(libraryOres != null) {
-			CoordinatorManager.getInstance().getCoordinator().getEventBus().deregisterFor(this, libraryOres);
-		}
-
-		libraryManager.setCatalogRepoEntry(repoEntry);
-		// lock selected folder to prevent indexing twice (resourcefolder / library - Indexer)
-		libraryManager.lockFolderAndPreventDoubleIndexing();
-		libraryOres = OresHelper.createOLATResourceableInstance(LibrarySite.class, repoEntry.getOlatResource().getResourceableId());
-
-		basePath = "/repository/" + repoEntry.getOlatResource().getResourceableId() + "/" + libraryManager.getSharedFolder().getName();
-
-	//update tree
-		initializeMenuTreeAndCatalog(ureq);
-		//update repository entry for all controllers;
-		newCatalogItemCtr.updateRepositoryEntry(ureq, libraryOres);
-		catalogCtr.updateRepositoryEntry(libraryOres);
-		mostRatedFilesCtr.updateRepositoryEntry(ureq, libraryOres);
-		mostViewedFilesCtr.updateView(ureq.getLocale());
-		newestFilesCtr.updateView(ureq.getLocale());
-		
-		//update url mapper
-		final Mapper mapper = new LibraryMapper(libraryManager);
-		final Mapper thumbnailMapper = new LibraryThumbnailMapper(basePath);
-		mapperBaseURL = registerCacheableMapper(ureq, "LibrarySite", mapper);
-		thumbnailMapperBaseURL = registerCacheableMapper(ureq, "LibraryThumbnail", thumbnailMapper);
-	}
-	
 	private void openFile(UserRequest ureq, OpenFileEvent openFolderEvent) {
 		CatalogItem item = openFolderEvent.getItem();
 		String fileName = item.getName();
@@ -606,20 +554,6 @@ public class LibraryMainController extends MainLayoutBasicController implements
 		}
 	}
 
-	/**
-	 * Displays the shared folder search controller
-	 * 
-	 * @param ureq
-	 */
-	private void displaySearchController(UserRequest ureq) {
-		String choose = translate("library.catalog.choose.folder.link");
-		chooseFolderCtr = new ReferencableEntriesSearchController(getWindowControl(), ureq, SharedFolderFileResource.TYPE_NAME, choose);
-		listenTo(chooseFolderCtr);
-		dialogCtr = new CloseableModalController(getWindowControl(), getTranslator().translate("close"), chooseFolderCtr.getInitialComponent());
-		listenTo(dialogCtr);
-		dialogCtr.activate();
-	}
-
 	/**
 	 * Displays the shared folder edit controller
 	 * 
@@ -754,7 +688,7 @@ public class LibraryMainController extends MainLayoutBasicController implements
 	}
 	
 	private void displayReviewController(UserRequest ureq) {
-		if ((libraryManager.getUploadFolder() != null) && (libraryManager.getUploadFolder().getItems().size() > 0)) {
+		if (libraryManager.getUploadFolder() != null && !libraryManager.getUploadFolder().getItems().isEmpty()) {
 			if (reviewController != null) {
 				removeAsListenerAndDispose(this.reviewController);
 			}
diff --git a/src/main/java/org/olat/modules/library/ui/_content/overview.html b/src/main/java/org/olat/modules/library/ui/_content/overview.html
index 6aea9dd4aff..6645e7f8d92 100644
--- a/src/main/java/org/olat/modules/library/ui/_content/overview.html
+++ b/src/main/java/org/olat/modules/library/ui/_content/overview.html
@@ -2,18 +2,15 @@
 	<div class="row">
 		<div class="col-sm-12 o_header_with_buttons">
 			<h2><i class="o_icon $cssIconClass"> </i> $r.translate("library.title")</h2>
-			#if($r.available("library.toolbox.review.singular") || $r.available("edit") || $r.available("library.toolbox.configure"))
+			#if($r.available("library.toolbox.review.singular") || $r.available("edit"))
 			<div class="o_button_group ">
-				<div class="btn-group">
+				<div class='#if($r.visible("library.toolbox.review.singular") && $r.visible("edit")) btn-group #end'>
 					#if($r.available("library.toolbox.review.singular"))
 						$r.render("library.toolbox.review.singular")
 					#end
 					#if($r.available("edit"))
 						$r.render("edit")
 					#end
-					#if($r.available("library.toolbox.configure"))
-						$r.render("library.toolbox.configure")
-					#end
 				</div>
 			</div>
 			#end
diff --git a/src/main/java/org/olat/modules/library/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/library/ui/_i18n/LocalStrings_de.properties
index a22591524c6..dd69276b07f 100644
--- a/src/main/java/org/olat/modules/library/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/library/ui/_i18n/LocalStrings_de.properties
@@ -15,6 +15,7 @@ acceptstep.notification.msg.subject=Bibliothek\: Dokument "{0}" wurde freigegebe
 acceptstep.notification.title=Benachrichtigung
 acceptstep.notification.ui.body=Meldung
 acceptstep.notification.ui.subject=Betreff
+add.shared.folder=Ressourcenordner auswählen
 admin.menu.title=Bibliothek
 admin.menu.title.alt=Konfiguration Bibliothek
 error.mail.message.empty=Es muss eine Mitteilung angegeben werden.
@@ -38,6 +39,7 @@ library.configuration.title=Bibliothek
 library.configuration.mail.after.upload=Email nach hochladen
 library.configuration.mail.after.freeing=Email nach freischalten
 library.enable=Bibliothek einschalten
+library.no.sharedfolder=Nicht konfiguriert
 library.notification.noNews=Seit {0} wurden der Bibliothek keine neuen Dokumente hinzugef\u00FCgt
 library.notification.noSubscription=Sie haben die Benachrichtigung f\u00FCr neue Dokumente nicht abonniert
 library.notification.title=Neue Dokumente
@@ -58,6 +60,7 @@ library.toolbox.search=Suche
 library.toolbox.upload=Neues Dokument einstellen
 library.toolbox.upload.desc=Haben Sie interesannte Dokumenten zu verteilen? Sie k\u00F6nnen diese Dokumenten hier hochladen.
 library.toolbox.useractions=Aktionen
+library.shared.folder=Ressourcenordner
 library.upload.folder.displayname=library_upload
 library.uploadnotification.body=Es wurde ein neues Dokument zur \u00DCberpr\u00FCfung eingestellt\: {0}. Das Dokument wird in den kommenden Tagen f\u00FCr die Freigabe \u00FCberpr\u00FCft. Vielen Dank f\u00FCr Ihre Mitarbeit\!
 library.uploadnotification.subject=OLAT Lernplattform Bibliothek-Upload
@@ -79,6 +82,7 @@ reject.message.default.subject=Bibliothek\: Dokument "{0}" wurde abgelehnt
 reject.message.from=Von
 reject.message.subject=Betreff
 reject.message.to=An
+remove.shared.folder=Ressourcenordner entfern
 review.explanation=Diese Dokumente m\u00FCssen zuerst \u00FCberpr\u00FCft werden, bevor sie in die Bibliothek eingestellt werden d\u00FCrfen.
 review.title=Sie haben {0} Dokument(en) zu \u00FCberpr\u00FCfen
 search=Volltextsuche
diff --git a/src/main/java/org/olat/modules/library/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/library/ui/_i18n/LocalStrings_en.properties
index 7a3cbc73a4c..5099b33617e 100644
--- a/src/main/java/org/olat/modules/library/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/library/ui/_i18n/LocalStrings_en.properties
@@ -1,4 +1,4 @@
-#Thu May 26 12:16:49 CEST 2011
+#Mon Apr 01 10:48:03 CEST 2019
 accept.wizard.title=Accept document
 acceptstep.destination.description=Select a folder from the library to which the document should be added.
 acceptstep.destination.noselectionerror=You have to select at least one target folder.
@@ -15,12 +15,14 @@ acceptstep.notification.msg.subject=Library\: document "{0}" has been approved
 acceptstep.notification.title=Notification
 acceptstep.notification.ui.body=Message
 acceptstep.notification.ui.subject=Subject
+add.shared.folder=Select resource folder
 admin.menu.title=Library
 admin.menu.title.alt=Configuration of the library
 error.mail.message.empty=The message is mandatory.
-error.mail.subject.empty=The subject is mandatory.
 error.mail.not.valid=You must enter a valid e-mail address.
+error.mail.subject.empty=The subject is mandatory.
 library.catalog.choose.folder.link=Select a folder
+library.catalog.download=Download
 library.catalog.file.not.found=The file could not be found. Maybe it has been deleted in the meantime by someone else.
 library.catalog.folder.cannot.be.edited=This folder can not be edited because there is no content available. Add content first.
 library.catalog.folder.not.found=The folder could not be found.
@@ -30,13 +32,14 @@ library.catalog.hide.details=Hide details
 library.catalog.intro=Welcome to the library\! Here you will find important documents and interesting content.
 library.catalog.none.setup=Documents can not be approved since the library is not yet configured properly. Select a resource folder first as your library base.
 library.catalog.permalink=This is a permanent link to this document. Select this link using the right mouse button to copy the link. Then you can use the link in your documents or emails. <p />Attention\: only members of this platform will be able to open this link (login required).
+library.catalog.send.mail=Send as email
 library.catalog.show.details=more
 library.catalog.title=Catalog "{0}"
-library.catalog.send.mail=Send as email
-library.catalog.download=Download
-library.configuration.title=Library
-library.configuration.mail.after.upload=Email after upload
 library.configuration.mail.after.freeing=Email after freeing
+library.configuration.mail.after.upload=Email after upload
+library.configuration.title=Library
+library.enable=Enable library
+library.no.sharedfolder=Not configured
 library.notification.noNews=Since {0} no more new documents have been added to the library
 library.notification.noSubscription=You are not registered for the new documents notifications
 library.notification.title=New documents
@@ -45,6 +48,7 @@ library.notifications.header=New documents have been added to the library
 library.notifications.title={0} new documents in the library
 library.notifications.titleOne={0} new documents in the library
 library.review.error=To be reviewed documents can not be displayed.
+library.shared.folder=Shared folder
 library.title=Library
 library.toolbox.adminactions=Administration
 library.toolbox.configure=Configure
@@ -55,6 +59,7 @@ library.toolbox.review.plural={0} new documents to review
 library.toolbox.review.singular=One new document to review
 library.toolbox.search=Search
 library.toolbox.upload=Submit document
+library.toolbox.upload.desc=Did you have an interessant document to share? You can upload this document here.
 library.toolbox.useractions=Actions
 library.upload.folder.displayname=library_upload
 library.uploadnotification.body=A new document has been submitted to the library\: {0}. The document will be reviewed for publication within the next days. Thank you very much for your contribution\!
@@ -66,8 +71,8 @@ mf.filename=Name
 mf.filename.title=File name
 mf.newFilename=New file name
 mf.newFilename.error=File names must only contain the characters ._- , 0-9 and a-z A-Z and not be longer than 64 characters.
-order.relevance=Relevance
 order.publication=Publication date
+order.relevance=Relevance
 order.title=Title
 reject.form.cancel=Cancel
 reject.form.submit=Reject document
@@ -77,6 +82,7 @@ reject.message.default.subject=Library\: document "{0}" has been rejected
 reject.message.from=From
 reject.message.subject=Subject
 reject.message.to=To
+remove.shared.folder=Remove resource folder
 review.explanation=This documents must first be reviewed before they can be added to the library.
 review.title=You have {0} documents to review
 search=Full text search
-- 
GitLab