/** * 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.controllers; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.olat.core.CoreSpringFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.dropdown.Dropdown; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; import org.olat.core.gui.components.segmentedview.SegmentViewComponent; import org.olat.core.gui.components.segmentedview.SegmentViewEvent; import org.olat.core.gui.components.segmentedview.SegmentViewFactory; import org.olat.core.gui.components.velocity.VelocityContainer; 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.controller.BasicController; import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; import org.olat.core.id.Roles; import org.olat.fileresource.types.BlogFileResource; import org.olat.fileresource.types.ImsCPFileResource; import org.olat.fileresource.types.ImsQTI21Resource; import org.olat.fileresource.types.PodcastFileResource; import org.olat.fileresource.types.ScormCPFileResource; import org.olat.fileresource.types.VideoFileResource; import org.olat.fileresource.types.WikiResource; import org.olat.group.BusinessGroupModule; import org.olat.ims.qti.fileresource.SurveyFileResource; import org.olat.ims.qti.fileresource.TestFileResource; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryService; import org.olat.repository.controllers.RepositorySearchController.Can; import org.olat.repository.handlers.RepositoryHandler; import org.olat.repository.handlers.RepositoryHandlerFactory; import org.olat.repository.ui.RepositoryTableModel; import org.olat.repository.ui.author.CreateEntryController; import org.olat.repository.ui.author.ImportRepositoryEntryController; import org.springframework.beans.factory.annotation.Autowired; /** * * Description: Implements a repository entry search workflow * used by OLAT authors. Entries can be found that are either owned by * the user or visible to authors in conjunction with the canReference * flag. * @author gnaegi * Initial Date: Aug 17, 2006 * */ public class ReferencableEntriesSearchController extends BasicController { public static final Event EVENT_REPOSITORY_ENTRY_SELECTED = new Event("event.repository.entry.selected"); public static final Event EVENT_REPOSITORY_ENTRIES_SELECTED = new Event("event.repository.entries.selected"); private static final String CMD_SEARCH_ENTRIES = "cmd.searchEntries"; private static final String CMD_ADMIN_SEARCH_ENTRIES = "cmd.adminSearchEntries"; private static final String CMD_ALL_ENTRIES = "cmd.allEntries"; private static final String CMD_MY_ENTRIES = "cmd.myEntries"; private VelocityContainer mainVC; private RepositorySearchController searchCtr; private String[] limitTypes; private SegmentViewComponent segmentView; private Link myEntriesLink, allEntriesLink, searchEntriesLink, adminEntriesLink; private Link importRessourceButton; private Component createRessourceCmp; private CreateEntryController createController; private ImportRepositoryEntryController importController; private CloseableModalController cmc; private RepositoryEntry selectedRepositoryEntry; private List<RepositoryEntry> selectedRepositoryEntries; private final boolean canImport; private final Can canBe; private Object userObject; @Autowired private RepositoryHandlerFactory repositoryHandlerFactory; public ReferencableEntriesSearchController(WindowControl wControl, UserRequest ureq, String limitType, String commandLabel) { this(wControl, ureq, new String[]{ limitType }, null, commandLabel, true, true, false, false, Can.referenceable); } public ReferencableEntriesSearchController(WindowControl wControl, UserRequest ureq, String[] limitTypes, String commandLabel) { this(wControl, ureq, limitTypes, null, commandLabel, true, true, false, false, Can.referenceable); } public ReferencableEntriesSearchController(WindowControl wControl, UserRequest ureq, String[] limitTypes, String commandLabel, boolean canImport, boolean canCreate, boolean multiSelect, boolean adminSearch) { this(wControl, ureq, limitTypes, null, commandLabel, canImport, canCreate, multiSelect, adminSearch, Can.referenceable); } public ReferencableEntriesSearchController(WindowControl wControl, UserRequest ureq, String[] limitTypes, RepositoryEntryFilter filter, String commandLabel, boolean canImport, boolean canCreate, boolean multiSelect, boolean adminSearch, Can canBe) { super(ureq, wControl); this.canBe = canBe; this.canImport = canImport; this.limitTypes = limitTypes; setBasePackage(RepositoryService.class); mainVC = createVelocityContainer("referencableSearch"); if(limitTypes != null && limitTypes.length == 1 && limitTypes[0] != null) { mainVC.contextPut("titleCss", "o_icon o_" + limitTypes[0] + "_icon"); } // add repo search controller searchCtr = new RepositorySearchController(commandLabel, ureq, getWindowControl(), false, multiSelect, limitTypes, filter); listenTo(searchCtr); // do instantiate buttons if (canCreate && limitTypes != null) { List<String> creatorTypes = new ArrayList<>(limitTypes.length); for(String limitType:limitTypes) { RepositoryHandler handler = repositoryHandlerFactory.getRepositoryHandler(limitType); if(handler.isCreate()) { creatorTypes.add(limitType); } } if(creatorTypes.size() == 1) { Link createButton = LinkFactory.createButtonSmall("cmd.create.ressource", mainVC, this); createButton.setElementCssClass("o_sel_repo_popup_create_resource"); RepositoryHandler handler = repositoryHandlerFactory.getRepositoryHandler(creatorTypes.get(0)); createButton.setUserObject(handler); createRessourceCmp = createButton; } else if(creatorTypes.size() > 1) { Dropdown dropdown = new Dropdown("cmd.create.ressource", "cmd.create.ressource", false, getTranslator()); dropdown.setElementCssClass("o_sel_repo_popup_create_resources"); dropdown.setButton(true); mainVC.put("cmd.create.ressource", dropdown); for(String limitType:creatorTypes) { RepositoryHandler handler = repositoryHandlerFactory.getRepositoryHandler(limitType); Link createLink = LinkFactory.createLink(handler.getSupportedType(), getTranslator(), this); createLink.setUserObject(handler); dropdown.addComponent(createLink); } createRessourceCmp = dropdown; } } if (canImport && isImportButtonVisible()) { importRessourceButton = LinkFactory.createButtonSmall("cmd.import.ressource", mainVC, this); importRessourceButton.setElementCssClass("o_sel_repo_popup_import_resource"); } segmentView = SegmentViewFactory.createSegmentView("segments", mainVC, this); allEntriesLink = LinkFactory.createCustomLink(CMD_ALL_ENTRIES, CMD_ALL_ENTRIES, "referencableSearch." + CMD_ALL_ENTRIES, Link.LINK, mainVC, this); allEntriesLink.setElementCssClass("o_sel_repo_popup_all_resources"); segmentView.addSegment(allEntriesLink, false); myEntriesLink = LinkFactory.createCustomLink(CMD_MY_ENTRIES, CMD_MY_ENTRIES, "referencableSearch." + CMD_MY_ENTRIES, Link.LINK, mainVC, this); myEntriesLink.setElementCssClass("o_sel_repo_popup_my_resources"); segmentView.addSegment(myEntriesLink, true); searchEntriesLink = LinkFactory.createCustomLink(CMD_SEARCH_ENTRIES, CMD_SEARCH_ENTRIES, "referencableSearch." + CMD_SEARCH_ENTRIES, Link.LINK, mainVC, this); searchEntriesLink.setElementCssClass("o_sel_repo_popup_search_resources"); segmentView.addSegment(searchEntriesLink, false); if(adminSearch && isAdminSearchVisible(limitTypes, ureq)) { adminEntriesLink = LinkFactory.createCustomLink(CMD_ADMIN_SEARCH_ENTRIES, CMD_ADMIN_SEARCH_ENTRIES, "referencableSearch." + CMD_ADMIN_SEARCH_ENTRIES, Link.LINK, mainVC, this); adminEntriesLink.setElementCssClass("o_sel_repo_popup_admin_search_resources"); segmentView.addSegment(adminEntriesLink, false); } searchCtr.doSearchByOwnerLimitType(ureq.getIdentity(), limitTypes); searchCtr.enableSearchforAllXXAbleInSearchForm(canBe); mainVC.put("searchCtr", searchCtr.getInitialComponent()); putInitialPanel(mainVC); } public Object getUserObject() { return userObject; } public void setUserObject(Object userObject) { this.userObject = userObject; } /** * Admin. search allow group managers to search all courses * @param limitingTypes * @param ureq * @return */ private boolean isAdminSearchVisible(String[] limitingTypes, UserRequest ureq) { Roles roles = ureq.getUserSession().getRoles(); return limitingTypes != null && limitingTypes.length == 1 && "CourseModule".equals(limitingTypes[0]) && (roles.isOLATAdmin() || (roles.isInstitutionalResourceManager() && roles.isGroupManager()) || (roles.isGroupManager() && CoreSpringFactory.getImpl(BusinessGroupModule.class).isGroupManagersAllowedToLinkCourses())); } /** * if building block can be imported, return true * * @return */ private boolean isImportButtonVisible() { if(!canImport) return false; List<String> limitTypeList = Arrays.asList(limitTypes); String[] importAllowed = new String[] { ImsQTI21Resource.TYPE_NAME, TestFileResource.TYPE_NAME, WikiResource.TYPE_NAME, ImsCPFileResource.TYPE_NAME, ScormCPFileResource.TYPE_NAME, SurveyFileResource.TYPE_NAME, BlogFileResource.TYPE_NAME, PodcastFileResource.TYPE_NAME, VideoFileResource.TYPE_NAME }; if (Collections.indexOfSubList(Arrays.asList(importAllowed), limitTypeList) != -1) { return true; } return false; } /** * @return Returns the selectedEntry. */ public RepositoryEntry getSelectedEntry() { return selectedRepositoryEntry; } /** * @return Returns the selected entries */ public List<RepositoryEntry> getSelectedEntries() { if(selectedRepositoryEntries == null && selectedRepositoryEntry != null) { return Collections.singletonList(selectedRepositoryEntry); } return selectedRepositoryEntries; } @Override public void event(UserRequest ureq, Component source, Event event) { if(source == segmentView) { if(event instanceof SegmentViewEvent) { SegmentViewEvent sve = (SegmentViewEvent)event; String segmentCName = sve.getComponentName(); Component clickedLink = mainVC.getComponent(segmentCName); if (clickedLink == myEntriesLink) { searchCtr.doSearchByOwnerLimitType(ureq.getIdentity(), limitTypes); } else if (clickedLink == allEntriesLink){ switch(canBe) { case referenceable: searchCtr.doSearchForReferencableResourcesLimitType(ureq.getIdentity(), limitTypes, ureq.getUserSession().getRoles()); break; case copyable: searchCtr.doSearchForCopyableResourcesLimitType(ureq.getIdentity(), limitTypes, ureq.getUserSession().getRoles()); break; case all: searchCtr.doSearchByTypeLimitAccess(limitTypes, ureq); break; } } else if (clickedLink == searchEntriesLink){ searchCtr.displaySearchForm(); } else if (clickedLink == adminEntriesLink) { searchCtr.displayAdminSearchForm(); } mainVC.setDirty(true); } } else if(source == createRessourceCmp || (source instanceof Link && ((Link)source).getUserObject() instanceof RepositoryHandler)) { removeAsListenerAndDispose(cmc); removeAsListenerAndDispose(createController); RepositoryHandler handler = (RepositoryHandler)((Link)source).getUserObject(); createController = handler.createCreateRepositoryEntryController(ureq, getWindowControl()); listenTo(createController); String title = translate(handler.getCreateLabelI18nKey()); cmc = new CloseableModalController(getWindowControl(), translate("close"), createController.getInitialComponent(), true, title); cmc.setCustomWindowCSS("o_sel_author_create_popup"); listenTo(cmc); cmc.activate(); } else if (source == importRessourceButton) { removeAsListenerAndDispose(importController); importController = new ImportRepositoryEntryController(ureq, getWindowControl(), limitTypes); listenTo(importController); removeAsListenerAndDispose(cmc); cmc = new CloseableModalController(getWindowControl(), translate("close"), importController.getInitialComponent(), true, ""); listenTo(cmc); cmc.activate(); } } @Override public void event(UserRequest ureq, Controller source, Event event) { String cmd = event.getCommand(); if (source == searchCtr) { if (cmd.equals(RepositoryTableModel.TABLE_ACTION_SELECT_LINK)) { // done, user selected a repo entry selectedRepositoryEntry = searchCtr.getSelectedEntry(); selectedRepositoryEntries = null; fireEvent(ureq, EVENT_REPOSITORY_ENTRY_SELECTED); } else if (cmd.equals(RepositoryTableModel.TABLE_ACTION_SELECT_ENTRIES)) { selectedRepositoryEntry = null; selectedRepositoryEntries = searchCtr.getSelectedEntries(); fireEvent(ureq, EVENT_REPOSITORY_ENTRIES_SELECTED); } //initLinks(); } else if (source == createController) { if (event.equals(Event.DONE_EVENT)) { cmc.deactivate(); selectedRepositoryEntry = createController.getAddedEntry(); fireEvent(ureq, EVENT_REPOSITORY_ENTRY_SELECTED); // info message String message = translate("message.entry.selected", new String[] { selectedRepositoryEntry.getDisplayname(), selectedRepositoryEntry.getResourcename()}); getWindowControl().setInfo(message); } else if (event.equals(Event.CANCELLED_EVENT)) { cmc.deactivate(); } else if (event.equals(Event.FAILED_EVENT)) { showError("add.failed"); } } else if (source == importController) { if (event.equals(Event.DONE_EVENT)) { cmc.deactivate(); selectedRepositoryEntry = importController.getImportedEntry(); fireEvent(ureq, EVENT_REPOSITORY_ENTRY_SELECTED); // info message String message = translate("message.entry.selected", new String[] { selectedRepositoryEntry.getDisplayname(), selectedRepositoryEntry.getResourcename()}); getWindowControl().setInfo(message); } else if (event.equals(Event.CANCELLED_EVENT)) { cmc.deactivate(); } else if (event.equals(Event.FAILED_EVENT)) { showError("add.failed"); } } } /** * @see org.olat.core.gui.control.DefaultController#doDispose(boolean) */ protected void doDispose() { // } }