/**
* <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.author;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.olat.NewControllerFactory;
import org.olat.admin.user.UserSearchController;
import org.olat.basesecurity.GroupRoles;
import org.olat.basesecurity.events.MultiIdentityChosenEvent;
import org.olat.basesecurity.events.SingleIdentityChosenEvent;
import org.olat.core.commons.persistence.DB;
import org.olat.core.commons.persistence.SortKey;
import org.olat.core.commons.services.mark.Mark;
import org.olat.core.commons.services.mark.MarkManager;
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.dropdown.Dropdown.Spacer;
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.FlexiTableFilter;
import org.olat.core.gui.components.form.flexible.elements.FlexiTableSortOptions;
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;
import org.olat.core.gui.components.form.flexible.impl.elements.table.DateFlexiCellRenderer;
import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel;
import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer;
import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiColumnModel;
import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableCssDelegate;
import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory;
import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableRendererType;
import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableSearchEvent;
import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent;
import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer;
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.TooledStackedPanel;
import org.olat.core.gui.components.stack.TooledStackedPanel.Align;
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.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;
import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
import org.olat.core.gui.control.generic.wizard.StepsMainRunController;
import org.olat.core.gui.media.MediaResource;
import org.olat.core.gui.translator.Translator;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.id.Roles;
import org.olat.core.id.context.ContextEntry;
import org.olat.core.id.context.StateEntry;
import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
import org.olat.core.util.StringHelper;
import org.olat.core.util.Util;
import org.olat.core.util.coordinate.LockResult;
import org.olat.core.util.resource.OresHelper;
import org.olat.course.CorruptedCourseException;
import org.olat.course.CourseModule;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryEntryManagedFlag;
import org.olat.repository.RepositoryEntryRef;
import org.olat.repository.RepositoryManager;
import org.olat.repository.RepositoryModule;
import org.olat.repository.RepositoryService;
import org.olat.repository.controllers.EntryChangedEvent;
import org.olat.repository.controllers.EntryChangedEvent.Change;
import org.olat.repository.handlers.RepositoryHandler;
import org.olat.repository.handlers.RepositoryHandlerFactory;
import org.olat.repository.handlers.RepositoryHandlerFactory.OrderedRepositoryHandler;
import org.olat.repository.model.SearchAuthorRepositoryEntryViewParams;
import org.olat.repository.model.SearchAuthorRepositoryEntryViewParams.OrderBy;
import org.olat.repository.ui.RepositoyUIFactory;
import org.olat.repository.ui.author.AuthoringEntryDataModel.Cols;
import org.olat.user.UserManager;
import org.olat.util.logging.activity.LoggingResourceable;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 28.04.2014<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.comx
*
*/
public class AuthorListController extends FormBasicController implements Activateable2, AuthoringEntryDataSourceUIFactory, FlexiTableCssDelegate {
private final String i18nName;
protected FlexiTableElement tableEl;
private final TooledStackedPanel stackPanel;
private boolean withSearch;
private AuthoringEntryDataModel model;
private AuthoringEntryDataSource dataSource;
private final SearchAuthorRepositoryEntryViewParams searchParams;
private ToolsController toolsCtrl;
protected CloseableModalController cmc;
private SendMailController sendMailCtrl;
private StepsMainRunController wizardCtrl;
private AuthorSearchController searchCtrl;
private UserSearchController userSearchCtr;
private DialogBoxController copyDialogCtrl;
private CopyRepositoryEntryController copyCtrl;
private ConfirmCloseController closeCtrl;
private ConfirmDeleteSoftlyController confirmDeleteCtrl;
private ImportRepositoryEntryController importCtrl;
private CreateEntryController createCtrl;
protected CloseableCalloutWindowController toolsCalloutCtrl;
protected boolean isOlatAdmin;
protected boolean hasAuthorRight;
private Link importLink;
private Dropdown createDropdown;
private FormLink sendMailButton, addOwnersButton, deleteButton, copyButton;
private LockResult lockResult;
private final AtomicInteger counter = new AtomicInteger();
//only used as marker for dirty, model cannot load specific rows
private final List<Long> dirtyRows = new ArrayList<>();
@Autowired
private DB dbInstance;
@Autowired
private UserManager userManager;
@Autowired
private MarkManager markManager;
@Autowired
protected RepositoryModule repositoryModule;
@Autowired
protected RepositoryService repositoryService;
@Autowired
protected RepositoryManager repositoryManager;
@Autowired
protected RepositoryHandlerFactory repositoryHandlerFactory;
public AuthorListController(UserRequest ureq, WindowControl wControl, String i18nName,
SearchAuthorRepositoryEntryViewParams searchParams, boolean withSearch) {
super(ureq, wControl, "entries");
setTranslator(Util.createPackageTranslator(RepositoryService.class, getLocale(), getTranslator()));
this.i18nName = i18nName;
this.withSearch = withSearch;
this.searchParams = searchParams;
OLATResourceable ores = OresHelper.createOLATResourceableType("RepositorySite");
ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores));
Roles roles = ureq.getUserSession().getRoles();
isOlatAdmin = roles.isOLATAdmin() || roles.isInstitutionalResourceManager();
hasAuthorRight = roles.isAuthor() || roles.isInstitutionalResourceManager() || roles.isOLATAdmin();
dataSource = new AuthoringEntryDataSource(searchParams, this);
initForm(ureq);
stackPanel = new TooledStackedPanel(i18nName, getTranslator(), this);
stackPanel.pushController(translate(i18nName), this);
initTools();
}
protected void initTools() {
if(!withSearch && hasAuthorRight) {
importLink = LinkFactory.createLink("cmd.import.ressource", getTranslator(), this);
importLink.setDomReplacementWrapperRequired(false);
importLink.setIconLeftCSS("o_icon o_icon_import");
importLink.setElementCssClass("o_sel_author_import");
stackPanel.addTool(importLink, Align.left);
List<OrderedRepositoryHandler> handlers = repositoryHandlerFactory.getOrderRepositoryHandlers();
createDropdown = new Dropdown("cmd.create.ressource", "cmd.create.ressource", false, getTranslator());
createDropdown.setElementCssClass("o_sel_author_create");
createDropdown.setIconCSS("o_icon o_icon_add");
int lastGroup = 0;
for(OrderedRepositoryHandler orderedHandler:handlers) {
RepositoryHandler handler = orderedHandler.getHandler();
if(handler != null && handler.isCreate()) {
// for each 10-group, create a separator
int group = orderedHandler.getOrder() / 10;
if (group > lastGroup) {
createDropdown.addComponent(new Spacer("spacer" + orderedHandler.getOrder()));
lastGroup = group;
}
addCreateLink(handler, createDropdown);
}
}
stackPanel.addTool(createDropdown, Align.left);
}
}
public String getI18nName() {
return i18nName;
}
@Override
public Translator getTranslator() {
return super.getTranslator();
}
private void addCreateLink(RepositoryHandler handler, Dropdown dropdown) {
Link createLink = LinkFactory.createLink(handler.getSupportedType(), getTranslator(), this);
createLink.setIconLeftCSS("o_icon o_icon-fw " + RepositoyUIFactory.getIconCssClass(handler.getSupportedType()));
createLink.setElementCssClass("o_sel_author_create-" + handler.getSupportedType());
createLink.setUserObject(handler);
dropdown.addComponent(createLink);
}
public boolean isEmpty() {
return dataSource.getRowCount() == 0;
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
//search form
if(withSearch) {
setFormDescription("table.search.author.desc");
searchCtrl = new AuthorSearchController(ureq, getWindowControl(), true, mainForm);
searchCtrl.setEnabled(false);
listenTo(searchCtrl);
}
//add the table
FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.key.i18nKey(), Cols.key.ordinal(), true, OrderBy.key.name()));
DefaultFlexiColumnModel markColumn = new DefaultFlexiColumnModel(true, Cols.mark.i18nKey(), Cols.mark.ordinal(), true, OrderBy.favorit.name());
markColumn.setExportable(false);
columnsModel.addFlexiColumnModel(markColumn);
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.type.i18nKey(), Cols.type.ordinal(), true, OrderBy.type.name(),
FlexiColumnModel.ALIGNMENT_LEFT, new TypeRenderer()));
FlexiCellRenderer renderer = new StaticFlexiCellRenderer("select", new TextFlexiCellRenderer());
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.displayName.i18nKey(), Cols.displayName.ordinal(), "select",
true, OrderBy.displayname.name(), renderer));
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.authors.i18nKey(), Cols.authors.ordinal(),
true, OrderBy.authors.name()));
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.location.i18nKey(), Cols.location.ordinal(),
true, OrderBy.location.name()));
if(repositoryModule.isManagedRepositoryEntries()) {
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.externalId.i18nKey(), Cols.externalId.ordinal(),
true, OrderBy.externalId.name()));
}
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.externalRef.i18nKey(), Cols.externalRef.ordinal(),
true, OrderBy.externalRef.name()));
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.lifecycleLabel.i18nKey(), Cols.lifecycleLabel.ordinal(),
true, OrderBy.lifecycleLabel.name()));
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.lifecycleSoftkey.i18nKey(), Cols.lifecycleSoftkey.ordinal(),
true, OrderBy.lifecycleSoftkey.name()));
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.lifecycleStart.i18nKey(), Cols.lifecycleStart.ordinal(),
true, OrderBy.lifecycleStart.name(), FlexiColumnModel.ALIGNMENT_LEFT, new DateFlexiCellRenderer(getLocale())));
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.lifecycleEnd.i18nKey(), Cols.lifecycleEnd.ordinal(),
true, OrderBy.lifecycleEnd.name(), FlexiColumnModel.ALIGNMENT_LEFT, new DateFlexiCellRenderer(getLocale())));
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.author.i18nKey(), Cols.author.ordinal(),
true, OrderBy.author.name()));
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.access.i18nKey(), Cols.access.ordinal(),
true, OrderBy.access.name(), FlexiColumnModel.ALIGNMENT_LEFT, new AccessRenderer()));
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.ac.i18nKey(), Cols.ac.ordinal(),
true, OrderBy.ac.name(), FlexiColumnModel.ALIGNMENT_LEFT, new ACRenderer()));
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.creationDate.i18nKey(), Cols.creationDate.ordinal(),
true, OrderBy.creationDate.name()));
columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.lastUsage.i18nKey(), Cols.lastUsage.ordinal(),
true, OrderBy.lastUsage.name()));
initActionsColumns(columnsModel);
model = new AuthoringEntryDataModel(dataSource, columnsModel);
tableEl = uifactory.addTableElement(getWindowControl(), "table", model, 20, false, getTranslator(), formLayout);
tableEl.setSearchEnabled(withSearch);
tableEl.setCssDelegate(this);
tableEl.setExportEnabled(true);
tableEl.setExtendedSearch(searchCtrl);
tableEl.setCustomizeColumns(true);
tableEl.setElementCssClass("o_coursetable");
tableEl.setShowAllRowsEnabled(true);
tableEl.setMultiSelect(true);
tableEl.setSelectAllEnable(true);
tableEl.setEmtpyTableMessageKey("table.sEmptyTable");
tableEl.setSortSettings(new FlexiTableSortOptions(true, new SortKey(OrderBy.displayname.name(), true)));
tableEl.setAndLoadPersistedPreferences(ureq, "authors-list-" + i18nName);
if(!withSearch) {
tableEl.reloadData();
tableEl.setFilters(null, getFilters(), false);
}
initBatchButtons(formLayout);
}
protected void initActionsColumns(FlexiTableColumnModel columnsModel) {
DefaultFlexiColumnModel detailsColumn = new DefaultFlexiColumnModel(Cols.detailsSupported.i18nKey(), Cols.detailsSupported.ordinal(), "details",
new StaticFlexiCellRenderer("", "details", "o_icon o_icon-lg o_icon_details", translate("details")));
detailsColumn.setExportable(false);
columnsModel.addFlexiColumnModel(detailsColumn);
if(hasAuthorRight) {
DefaultFlexiColumnModel editColumn = new DefaultFlexiColumnModel(Cols.editionSupported.i18nKey(), Cols.editionSupported.ordinal(), "edit",
new BooleanCellRenderer(new StaticFlexiCellRenderer("", "edit", "o_icon o_icon-lg o_icon_edit", translate("edit")), null));
editColumn.setExportable(false);
columnsModel.addFlexiColumnModel(editColumn);
DefaultFlexiColumnModel toolsColumn = new DefaultFlexiColumnModel(Cols.tools.i18nKey(), Cols.tools.ordinal());
toolsColumn.setExportable(false);
columnsModel.addFlexiColumnModel(toolsColumn);
}
}
protected void initBatchButtons(FormItemContainer formLayout) {
if(hasAuthorRight) {
sendMailButton = uifactory.addFormLink("tools.send.mail", formLayout, Link.BUTTON);
addOwnersButton = uifactory.addFormLink("tools.add.owners", formLayout, Link.BUTTON);
copyButton = uifactory.addFormLink("details.copy", formLayout, Link.BUTTON);
deleteButton = uifactory.addFormLink("details.delete", formLayout, Link.BUTTON);
}
}
private List<FlexiTableFilter> getFilters() {
List<OrderedRepositoryHandler> supportedHandlers = repositoryHandlerFactory.getOrderRepositoryHandlers();
List<FlexiTableFilter> resources = new ArrayList<>(supportedHandlers.size() + 1);
int lastGroup = 0;
for(OrderedRepositoryHandler handler:supportedHandlers) {
// for each 10-group, crate a separator
int group = handler.getOrder() / 10;
if (group > lastGroup) {
resources.add(FlexiTableFilter.SPACER);
lastGroup = group;
}
String type = handler.getHandler().getSupportedType();
String inconLeftCss = RepositoyUIFactory.getIconCssClass(type);
resources.add(new FlexiTableFilter(translate(type), type, inconLeftCss));
}
return resources;
}
@Override
public String getWrapperCssClass(FlexiTableRendererType type) {
return null;
}
@Override
public String getTableCssClass(FlexiTableRendererType type) {
return null;
}
@Override
public String getRowCssClass(FlexiTableRendererType type, int pos) {
AuthoringEntryRow row = model.getObject(pos);
if(row.getAccess() == 0) {
return "o_entry_deleted";
}
if(row.getRepositoryEntryStatus().isClosed()) {
return "o_entry_closed";
}
if(row.getRepositoryEntryStatus().isUnpublished()) {
return "o_entry_unpublished";
}
return null;
}
public TooledStackedPanel getStackPanel() {
return stackPanel;
}
@Override
protected void doDispose() {
//
}
@Override
public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
if(state instanceof AuthorListState) {
AuthorListState se = (AuthorListState)state;
if(se.getTableState() != null) {
tableEl.setStateEntry(ureq, se.getTableState());
}
if(se.getSearchEvent() != null) {
searchCtrl.update(se.getSearchEvent());
doSearch(ureq, se.getSearchEvent());
}
}
}
@Override
public void event(UserRequest ureq, Component source, Event event) {
if(importLink == source) {
doImport(ureq);
} else if(source instanceof Link && ((Link)source).getUserObject() instanceof RepositoryHandler) {
RepositoryHandler handler = (RepositoryHandler)((Link)source).getUserObject();
if(handler != null) {
doCreate(ureq, handler);
}
}
super.event(ureq, source, event);
}
@Override
protected void event(UserRequest ureq, Controller source, Event event) {
if(cmc == source) {
cleanUp();
} else if(createCtrl == source) {
cmc.deactivate();
if(Event.DONE_EVENT.equals(event)) {
launchEditDescription(ureq, createCtrl.getAddedEntry());
reloadRows();
cleanUp();
} else if(CreateRepositoryEntryController.CREATION_WIZARD.equals(event)) {
doPostCreateWizard(ureq, createCtrl.getAddedEntry(), createCtrl.getHandler());
} else {
cleanUp();
}
} else if(copyCtrl == source) {
cmc.deactivate();
if (event == Event.DONE_EVENT) {
reloadRows();
launchEditDescription(ureq, copyCtrl.getCopiedEntry());
}
cleanUp();
} else if(importCtrl == source) {
cmc.deactivate();
if(Event.DONE_EVENT.equals(event)) {
reloadRows();
launchEditDescription(ureq, importCtrl.getImportedEntry());
}
cleanUp();
} else if(wizardCtrl == source) {
if (event.equals(Event.CHANGED_EVENT) || event.equals(Event.CANCELLED_EVENT)) {
getWindowControl().pop();
RepositoryEntry newEntry = (RepositoryEntry)wizardCtrl.getRunContext().get("authoringNewEntry");
reloadRows();
cleanUp();
launchEditDescription(ureq, newEntry);
}
} else if(searchCtrl == source) {
if(event instanceof SearchEvent) {
SearchEvent se = (SearchEvent)event;
doSearch(ureq, se);
} else if(event == Event.CANCELLED_EVENT) {
searchParams.setResourceTypes(null);
searchParams.setIdAndRefs(null);
searchParams.setAuthor(null);
searchParams.setDisplayname(null);
searchParams.setDescription(null);
searchParams.setOwnedResourcesOnly(false);
}
} else if(userSearchCtr == source) {
@SuppressWarnings("unchecked")
List<AuthoringEntryRow> rows = (List<AuthoringEntryRow>)userSearchCtr.getUserObject();
if (event instanceof MultiIdentityChosenEvent) {
MultiIdentityChosenEvent mice = (MultiIdentityChosenEvent) event;
doAddOwners(mice.getChosenIdentities(), rows);
} else if (event instanceof SingleIdentityChosenEvent) {
SingleIdentityChosenEvent sice = (SingleIdentityChosenEvent) event;
List<Identity> futureOwners = Collections.singletonList(sice.getChosenIdentity());
doAddOwners(futureOwners, rows);
}
cmc.deactivate();
cleanUp();
} else if(sendMailCtrl == source) {
cmc.deactivate();
cleanUp();
} else if(toolsCtrl == source) {
if(event == Event.DONE_EVENT) {
toolsCalloutCtrl.deactivate();
cleanUp();
}
} else if(closeCtrl == source) {
if(event == Event.CANCELLED_EVENT) {
cmc.deactivate();
cleanUp();
} else if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
cmc.deactivate();
reloadRows();
cleanUp();
}
} else if(confirmDeleteCtrl == source) {
if(event == Event.CANCELLED_EVENT) {
cmc.deactivate();
cleanUp();
} else if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
cmc.deactivate();
reloadRows();
cleanUp();
}
} else if(copyDialogCtrl == source) {
if (DialogBoxUIFactory.isYesEvent(event)) {
@SuppressWarnings("unchecked")
List<AuthoringEntryRow> rows = (List<AuthoringEntryRow>)copyDialogCtrl.getUserObject();
doCompleteCopy(rows);
reloadRows();
}
}
super.event(ureq, source, event);
}
protected void cleanUp() {
removeAsListenerAndDispose(confirmDeleteCtrl);
removeAsListenerAndDispose(toolsCalloutCtrl);
removeAsListenerAndDispose(userSearchCtr);
removeAsListenerAndDispose(sendMailCtrl);
removeAsListenerAndDispose(createCtrl);
removeAsListenerAndDispose(importCtrl);
removeAsListenerAndDispose(wizardCtrl);
removeAsListenerAndDispose(toolsCtrl);
removeAsListenerAndDispose(closeCtrl);
removeAsListenerAndDispose(cmc);
confirmDeleteCtrl = null;
toolsCalloutCtrl = null;
userSearchCtr = null;
sendMailCtrl = null;
createCtrl = null;
importCtrl = null;
wizardCtrl = null;
toolsCtrl = null;
closeCtrl = null;
cmc = null;
}
@Override
protected void formOK(UserRequest ureq) {
//
}
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if(addOwnersButton == source) {
List<AuthoringEntryRow> rows = getMultiSelectedRows();
if(!rows.isEmpty()) {
doAddOwners(ureq, rows);
} else {
showWarning("bulk.update.nothing.selected");
}
} else if(sendMailButton == source) {
List<AuthoringEntryRow> rows = getMultiSelectedRows();
if(!rows.isEmpty()) {
doSendMail(ureq, rows);
} else {
showWarning("bulk.update.nothing.selected");
}
} else if(copyButton == source) {
List<AuthoringEntryRow> rows = getMultiSelectedRows();
if(!rows.isEmpty()) {
doConfirmCopy(ureq, rows);
} else {
showWarning("bulk.update.nothing.selected");
}
} else if(deleteButton == source) {
List<AuthoringEntryRow> rows = getMultiSelectedRows();
if(!rows.isEmpty()) {
doDelete(ureq, rows);
} else {
showWarning("bulk.update.nothing.selected");
}
} else if(source instanceof FormLink) {
FormLink link = (FormLink)source;
String cmd = link.getCmd();
if("mark".equals(cmd)) {
AuthoringEntryRow row = (AuthoringEntryRow)link.getUserObject();
boolean marked = doMark(ureq, row);
link.setIconLeftCSS(marked ? "o_icon o_icon_bookmark o_icon-lg" : "o_icon o_icon_bookmark_add o_icon-lg");
link.setTitle(translate(marked ? "details.bookmark.remove" : "details.bookmark"));
link.getComponent().setDirty(true);
row.setMarked(marked);
} else if("tools".equals(cmd)) {
AuthoringEntryRow row = (AuthoringEntryRow)link.getUserObject();
doOpenTools(ureq, row, link);
}
} else if(source == tableEl) {
if(event instanceof SelectionEvent) {
SelectionEvent se = (SelectionEvent)event;
String cmd = se.getCommand();
AuthoringEntryRow row = model.getObject(se.getIndex());
if("details".equals(cmd)) {
launchDetails(ureq, row);
} else if("edit".equals(cmd)) {
launchEditor(ureq, row);
} else if("select".equals(cmd)) {
launch(ureq, row);
}
} else if(event instanceof FlexiTableSearchEvent) {
AuthorListState stateEntry = new AuthorListState();
stateEntry.setTableState(tableEl.getStateEntry());
addToHistory(ureq, stateEntry);
}
}
super.formInnerEvent(ureq, source, event);
}
@Override
protected void propagateDirtinessToContainer(FormItem fiSrc, FormEvent event) {
//do not update the
}
public void addDirtyRows(Long entryKey) {
dirtyRows.add(entryKey);
}
protected void reloadDirtyRows() {
if(dirtyRows.size() > 0) {
reloadRows();
}
}
protected void reloadRows() {
tableEl.deselectAll();
tableEl.reloadData();
dirtyRows.clear();
}
private void doOpenTools(UserRequest ureq, AuthoringEntryRow row, FormLink link) {
removeAsListenerAndDispose(toolsCtrl);
removeAsListenerAndDispose(toolsCalloutCtrl);
RepositoryEntry entry = repositoryService.loadByKey(row.getKey());
if(entry == null) {
tableEl.reloadData();
showWarning("repositoryentry.not.existing");
} else {
toolsCtrl = new ToolsController(ureq, getWindowControl(), row, entry);
listenTo(toolsCtrl);
toolsCalloutCtrl = new CloseableCalloutWindowController(ureq, getWindowControl(),
toolsCtrl.getInitialComponent(), link.getFormDispatchId(), "", true, "");
listenTo(toolsCalloutCtrl);
toolsCalloutCtrl.activate();
}
}
private void doImport(UserRequest ureq) {
if(importCtrl != null) return;
removeAsListenerAndDispose(importCtrl);
importCtrl = new ImportRepositoryEntryController(ureq, getWindowControl());
listenTo(importCtrl);
removeAsListenerAndDispose(cmc);
String title = translate("cmd.import.ressource");
cmc = new CloseableModalController(getWindowControl(), translate("close"), importCtrl.getInitialComponent(),
true, title);
listenTo(cmc);
cmc.activate();
}
private void doCreate(UserRequest ureq, RepositoryHandler handler) {
if(createCtrl != null) return;
removeAsListenerAndDispose(createCtrl);
createCtrl = handler.createCreateRepositoryEntryController(ureq, getWindowControl());
listenTo(createCtrl);
removeAsListenerAndDispose(cmc);
String title = translate(handler.getCreateLabelI18nKey());
cmc = new CloseableModalController(getWindowControl(), translate("close"), createCtrl.getInitialComponent(),
true, title);
cmc.setCustomWindowCSS("o_sel_author_create_popup");
listenTo(cmc);
cmc.activate();
}
protected boolean doMark(UserRequest ureq, AuthoringEntryRow row) {
OLATResourceable item = OresHelper.createOLATResourceableInstance("RepositoryEntry", row.getKey());
if(markManager.isMarked(item, getIdentity(), null)) {
markManager.removeMark(item, getIdentity(), null);
dbInstance.commit();//before sending, save the changes
EntryChangedEvent e = new EntryChangedEvent(row, getIdentity(), Change.removeBookmark, i18nName);
ureq.getUserSession().getSingleUserEventCenter().fireEventToListenersOf(e, RepositoryService.REPOSITORY_EVENT_ORES);
return false;
}
String businessPath = "[RepositoryEntry:" + item.getResourceableId() + "]";
markManager.setMark(item, getIdentity(), null, businessPath);
dbInstance.commit();//before sending, save the changes
EntryChangedEvent e = new EntryChangedEvent(row, getIdentity(), Change.addBookmark, i18nName);
ureq.getUserSession().getSingleUserEventCenter().fireEventToListenersOf(e, RepositoryService.REPOSITORY_EVENT_ORES);
return true;
}
private void doPostCreateWizard(UserRequest ureq, RepositoryEntry newEntry, RepositoryHandler handler) {
if(wizardCtrl != null) return;
cleanUp();
wizardCtrl = handler.createWizardController(newEntry, ureq, getWindowControl());
wizardCtrl.getRunContext().put("authoringNewEntry", newEntry);
listenTo(wizardCtrl);
getWindowControl().pushAsModalDialog(wizardCtrl.getInitialComponent());
}
private void doSearch(UserRequest ureq, SearchEvent se) {
if(StringHelper.containsNonWhitespace(se.getType())) {
searchParams.setResourceTypes(Collections.singletonList(se.getType()));
} else {
searchParams.setResourceTypes(null);
}
searchParams.setIdAndRefs(se.getId());
searchParams.setAuthor(se.getAuthor());
searchParams.setOwnedResourcesOnly(se.isOwnedResourcesOnly());
searchParams.setDisplayname(se.getDisplayname());
searchParams.setDescription(se.getDescription());
tableEl.reset(true, true, true);
AuthorListState stateEntry = new AuthorListState();
stateEntry.setSearchEvent(se);
stateEntry.setTableState(tableEl.getStateEntry());
addToHistory(ureq, stateEntry);
}
protected List<AuthoringEntryRow> getMultiSelectedRows() {
Set<Integer> selections = tableEl.getMultiSelectedIndex();
List<AuthoringEntryRow> rows = new ArrayList<>(selections.size());
if(selections.isEmpty()) {
} else {
for(Integer i:selections) {
AuthoringEntryRow row = model.getObject(i.intValue());
if(row != null) {
rows.add(row);
}
}
}
return rows;
}
private void doSendMail(UserRequest ureq, List<AuthoringEntryRow> rows) {
if(sendMailCtrl != null) return;
removeAsListenerAndDispose(userSearchCtr);
sendMailCtrl = new SendMailController(ureq, getWindowControl(), rows);
listenTo(sendMailCtrl);
String title = translate("tools.send.mail");
cmc = new CloseableModalController(getWindowControl(), translate("close"), sendMailCtrl.getInitialComponent(),
true, title);
listenTo(cmc);
cmc.activate();
}
private void doAddOwners(UserRequest ureq, List<AuthoringEntryRow> rows) {
if(userSearchCtr != null) return;
Roles roles = ureq.getUserSession().getRoles();
List<AuthoringEntryRow> manageableRows = new ArrayList<>(rows.size());
for(AuthoringEntryRow row:rows) {
boolean managed = RepositoryEntryManagedFlag.isManaged(row.getManagedFlags(), RepositoryEntryManagedFlag.membersmanagement);
boolean canAddOwner = roles.isOLATAdmin() || repositoryService.hasRole(ureq.getIdentity(), row, GroupRoles.owner.name())
|| repositoryManager.isInstitutionalRessourceManagerFor(getIdentity(), roles, row);
if(canAddOwner && !managed) {
manageableRows.add(row);
}
}
if(manageableRows.isEmpty()) {
showWarning("bulk.update.nothing.applicable.selected");
} else {
removeAsListenerAndDispose(userSearchCtr);
userSearchCtr = new UserSearchController(ureq, getWindowControl(), false, true, UserSearchController.ACTION_KEY_CHOOSE_FINISH);
userSearchCtr.setUserObject(manageableRows);
listenTo(userSearchCtr);
String title = translate("tools.add.owners");
cmc = new CloseableModalController(getWindowControl(), translate("close"), userSearchCtr.getInitialComponent(),
true, title);
listenTo(cmc);
cmc.activate();
}
}
private void doAddOwners(List<Identity> futureOwners, List<AuthoringEntryRow> rows) {
for(AuthoringEntryRow row:rows) {
RepositoryEntry re = repositoryService.loadByKey(row.getKey());
for(Identity futureOwner:futureOwners) {
repositoryService.addRole(futureOwner, re, GroupRoles.owner.name());
}
}
}
private void doConfirmCopy(UserRequest ureq, List<AuthoringEntryRow> rows) {
boolean deleted = false;
Roles roles = ureq.getUserSession().getRoles();
List<AuthoringEntryRow> copyableRows = new ArrayList<>(rows.size());
for(AuthoringEntryRow row:rows) {
RepositoryEntry entry = repositoryService.loadByKey(row.getKey());
if(entry == null) {
deleted = true;
} else {
boolean isInstitutionalResourceManager = repositoryManager.isInstitutionalRessourceManagerFor(getIdentity(), roles, row);
boolean isOwner = roles.isOLATAdmin()
|| repositoryService.hasRole(ureq.getIdentity(), row, GroupRoles.owner.name())
|| isInstitutionalResourceManager;
boolean isAuthor = roles.isOLATAdmin() || roles.isAuthor() || isInstitutionalResourceManager;
boolean copyManaged = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.copy);
boolean canCopy = (isAuthor || isOwner) && (entry.getCanCopy() || isOwner) && !copyManaged;
if(canCopy) {
copyableRows.add(row);
}
}
}
if(deleted) {
showWarning("repositoryentry.not.existing");
tableEl.reloadData();
} else if(copyableRows.isEmpty()) {
showWarning("bulk.update.nothing.applicable.selected");
} else {
StringBuilder sb = new StringBuilder();
for(AuthoringEntryRow row:copyableRows) {
if(sb.length() > 0) sb.append(", ");
sb.append(StringHelper.escapeHtml(row.getDisplayname()));
}
String dialogText = (copyableRows.size() != rows.size())
? translate("details.copy.confirm.warning", sb.toString()) : translate("details.copy.confirm", sb.toString());
copyDialogCtrl = activateYesNoDialog(ureq, translate("details.copy"), dialogText, copyDialogCtrl);
copyDialogCtrl.setUserObject(copyableRows);
}
}
private void doCompleteCopy(List<AuthoringEntryRow> rows) {
for(AuthoringEntryRow row:rows) {
RepositoryEntry sourceEntry = repositoryService.loadByKey(row.getKey());
String displayname = "Copy of " + sourceEntry.getDisplayname();
if(displayname.length() > 99) {
displayname = displayname.substring(0, 99);
}
repositoryService.copy(sourceEntry, getIdentity(), displayname);
}
showInfo("details.copy.success", new String[]{ Integer.toString(rows.size()) });
}
private void doCloseResource(UserRequest ureq, AuthoringEntryRow row) {
removeAsListenerAndDispose(closeCtrl);
RepositoryEntry entry = repositoryService.loadByKey(row.getKey());
List<RepositoryEntry> entryToClose = Collections.singletonList(entry);
closeCtrl = new ConfirmCloseController(ureq, getWindowControl(), entryToClose);
listenTo(closeCtrl);
String title = translate("read.only.header", entry.getDisplayname());
cmc = new CloseableModalController(getWindowControl(), "close", closeCtrl.getInitialComponent(), true, title);
listenTo(cmc);
cmc.activate();
}
private void doOverrideCloseResource(UserRequest ureq, AuthoringEntryRow row) {
try {
RepositoryHandler handler = repositoryHandlerFactory.getRepositoryHandler(row.getResourceType());
if(handler != null) {
String businessPath = "[RepositoryEntry:" + row.getKey() + "]";
ureq.getUserSession().putEntry("override_readonly_" + row.getKey(), Boolean.TRUE);
if(!NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl())) {
tableEl.reloadData();
}
}
} catch (CorruptedCourseException e) {
logError("Course corrupted: " + row.getKey() + " (" + row.getOLATResourceable().getResourceableId() + ")", e);
showError("cif.error.corrupted");
}
}
protected void doCopy(UserRequest ureq, AuthoringEntryRow row) {
removeAsListenerAndDispose(cmc);
removeAsListenerAndDispose(copyCtrl);
RepositoryEntry entry = repositoryService.loadByKey(row.getKey());
copyCtrl = new CopyRepositoryEntryController(ureq, getWindowControl(), entry);
listenTo(copyCtrl);
String title = translate("details.copy");
cmc = new CloseableModalController(getWindowControl(), translate("close"), copyCtrl.getInitialComponent(), true, title);
listenTo(cmc);
cmc.activate();
}
private void doDelete(UserRequest ureq, List<AuthoringEntryRow> rows) {
Roles roles = ureq.getUserSession().getRoles();
List<Long> deleteableRowKeys = new ArrayList<>(rows.size());
for(AuthoringEntryRow row:rows) {
boolean managed = RepositoryEntryManagedFlag.isManaged(row.getManagedFlags(), RepositoryEntryManagedFlag.delete);
boolean canDelete = roles.isOLATAdmin() || repositoryService.hasRole(ureq.getIdentity(), row, GroupRoles.owner.name())
|| repositoryManager.isInstitutionalRessourceManagerFor(getIdentity(), roles, row);
if(canDelete && !managed) {
deleteableRowKeys.add(row.getKey());
}
}
List<RepositoryEntry> entriesToDelete = repositoryManager.lookupRepositoryEntries(deleteableRowKeys);
if(entriesToDelete.isEmpty()) {
showWarning("bulk.update.nothing.applicable.selected");
} else {
removeAsListenerAndDispose(confirmDeleteCtrl);
removeAsListenerAndDispose(cmc);
confirmDeleteCtrl = new ConfirmDeleteSoftlyController(ureq, getWindowControl(), entriesToDelete, rows.size() != entriesToDelete.size());
listenTo(confirmDeleteCtrl);
String title = translate("details.delete");
cmc = new CloseableModalController(getWindowControl(), translate("close"), confirmDeleteCtrl.getInitialComponent(), true, title);
listenTo(cmc);
cmc.activate();
}
}
protected void doDownload(UserRequest ureq, AuthoringEntryRow row) {
RepositoryHandler typeToDownload = repositoryHandlerFactory.getRepositoryHandler(row.getResourceType());
if (typeToDownload == null) {
StringBuilder sb = new StringBuilder(translate("error.download"));
sb.append(": No download handler for repository entry: ")
.append(row.getKey());
showError(sb.toString());
return;
}
RepositoryEntry entry = repositoryService.loadByKey(row.getKey());
OLATResourceable ores = entry.getOlatResource();
if (ores == null) {
showError("error.download");
return;
}
boolean isAlreadyLocked = typeToDownload.isLocked(ores);
try {
lockResult = typeToDownload.acquireLock(ores, ureq.getIdentity());
if(lockResult == null || (lockResult !=null && lockResult.isSuccess() && !isAlreadyLocked)) {
MediaResource mr = typeToDownload.getAsMediaResource(ores, false);
if(mr!=null) {
repositoryService.incrementDownloadCounter(entry);
ureq.getDispatchResult().setResultingMediaResource(mr);
} else {
showError("error.export");
fireEvent(ureq, Event.FAILED_EVENT);
}
} else if(lockResult !=null && lockResult.isSuccess() && isAlreadyLocked) {
String fullName = userManager.getUserDisplayName(lockResult.getOwner());
showInfo("warning.course.alreadylocked.bySameUser", fullName);
lockResult = null; //invalid lock, it was already locked
} else {
String fullName = userManager.getUserDisplayName(lockResult.getOwner());
showInfo("warning.course.alreadylocked", fullName);
}
} finally {
if((lockResult!=null && lockResult.isSuccess() && !isAlreadyLocked)) {
typeToDownload.releaseLock(lockResult);
lockResult = null;
}
}
}
private void launch(UserRequest ureq, AuthoringEntryRow row) {
try {
RepositoryHandler handler = repositoryHandlerFactory.getRepositoryHandler(row.getResourceType());
if(handler != null) {
String businessPath = "[RepositoryEntry:" + row.getKey() + "]";
if(!NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl())) {
tableEl.reloadData();
}
}
} catch (CorruptedCourseException e) {
logError("Course corrupted: " + row.getKey() + " (" + row.getOLATResourceable().getResourceableId() + ")", e);
showError("cif.error.corrupted");
}
}
private void launchCatalog(UserRequest ureq, RepositoryEntryRef ref) {
String businessPath = "[RepositoryEntry:" + ref.getKey() + "][Catalog:0]";
NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
}
private void launchDetails(UserRequest ureq, RepositoryEntryRef ref) {
String businessPath = "[RepositoryEntry:" + ref.getKey() + "][Infos:0]";
if(!NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl())) {
tableEl.reloadData();
}
}
private void launchEditDescription(UserRequest ureq, RepositoryEntry re) {
if(re != null) {
RepositoryHandler handler = repositoryHandlerFactory.getRepositoryHandler(re);
if(handler != null) {
String businessPath = "[RepositoryEntry:" + re.getKey() + "][EditDescription:0]";
if(!NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl())) {
tableEl.reloadData();
}
}
}
}
private void launchEditDescription(UserRequest ureq, RepositoryEntryRef re) {
String businessPath = "[RepositoryEntry:" + re.getKey() + "][EditDescription:0]";
if(!NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl())) {
tableEl.reloadData();
}
}
private void launchEditor(UserRequest ureq, AuthoringEntryRow row) {
try {
String businessPath = "[RepositoryEntry:" + row.getKey() + "][Editor:0]";
if(!NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl())) {
tableEl.reloadData();
}
} catch (CorruptedCourseException e) {
logError("Course corrupted: " + row.getKey() + " (" + row.getOLATResourceable().getResourceableId() + ")", e);
showError("cif.error.corrupted");
}
}
private void launchMembers(UserRequest ureq, AuthoringEntryRow row) {
try {
String businessPath = "[RepositoryEntry:" + row.getKey() + "][MembersMgmt:0]";
NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
} catch (CorruptedCourseException e) {
logError("Course corrupted: " + row.getKey() + " (" + row.getOLATResourceable().getResourceableId() + ")", e);
showError("cif.error.corrupted");
}
}
@Override
public void forgeLinks(AuthoringEntryRow row) {
//mark
FormLink markLink = uifactory.addFormLink("mark_" + counter.incrementAndGet(), "mark", "", null, null, Link.NONTRANSLATED);
markLink.setIconLeftCSS(row.isMarked() ? Mark.MARK_CSS_LARGE : Mark.MARK_ADD_CSS_LARGE);
markLink.setTitle(translate(row.isMarked() ? "details.bookmark.remove" : "details.bookmark"));
markLink.setUserObject(row);
row.setMarkLink(markLink);
//tools
FormLink toolsLink = uifactory.addFormLink("tools_" + counter.incrementAndGet(), "tools", "", null, null, Link.NONTRANSLATED);
toolsLink.setIconLeftCSS("o_icon o_icon_actions o_icon-lg");
toolsLink.setUserObject(row);
row.setToolsLink(toolsLink);
}
private class ToolsController extends BasicController {
private final AuthoringEntryRow row;
private final VelocityContainer mainVC;
private boolean isOwner;
private boolean isAuthor;
public ToolsController(UserRequest ureq, WindowControl wControl, AuthoringEntryRow row, RepositoryEntry entry) {
super(ureq, wControl);
setTranslator(AuthorListController.this.getTranslator());
this.row = row;
Identity identity = getIdentity();
Roles roles = ureq.getUserSession().getRoles();
boolean isInstitutionalResourceManager = !roles.isGuestOnly()
&& repositoryManager.isInstitutionalRessourceManagerFor(identity, roles, entry);
isOwner = isOlatAdmin || repositoryService.hasRole(ureq.getIdentity(), entry, GroupRoles.owner.name())
|| isInstitutionalResourceManager;
isAuthor = isOlatAdmin || roles.isAuthor() | isInstitutionalResourceManager;
RepositoryHandler handler = repositoryHandlerFactory.getRepositoryHandler(entry);
mainVC = createVelocityContainer("tools");
List<String> links = new ArrayList<>();
if(isOwner) {
addLink("tools.edit.description", "description", "o_icon o_icon-fw o_icon_details", links);
if(repositoryModule.isCatalogEnabled()) {
addLink("tools.edit.catalog", "catalog", "o_icon o_icon-fw o_icon_catalog", links);
}
addLink("details.members", "members", "o_icon o_icon-fw o_icon_membersmanagement", links);
}
boolean copyManaged = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.copy);
boolean canCopy = (isAuthor || isOwner) && (entry.getCanCopy() || isOwner) && !copyManaged;
boolean canDownload = entry.getCanDownload() && handler.supportsDownload();
// disable download for courses if not author or owner
if (entry.getOlatResource().getResourceableTypeName().equals(CourseModule.getCourseTypeName()) && !(isOwner || isAuthor)) {
canDownload = false;
}
// always enable download for owners
if (isOwner && handler.supportsDownload()) {
canDownload = true;
}
if(canCopy || canDownload) {
links.add("-");
if (canCopy) {
addLink("details.copy", "copy", "o_icon o_icon-fw o_icon_copy", links);
}
if(canDownload) {
addLink("details.download", "download", "o_icon o_icon-fw o_icon_download", links);
}
}
boolean canClose = OresHelper.isOfType(entry.getOlatResource(), CourseModule.class)
&& !RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.close)
&& !entry.getRepositoryEntryStatus().isClosed()
&& !entry.getRepositoryEntryStatus().isUnpublished();
if(isOwner) {
boolean deleteManaged = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.delete);
if(canClose || !deleteManaged) {
links.add("-");
}
boolean closed = entry.getRepositoryEntryStatus().isClosed();
if(closed && "CourseModule".equals(entry.getOlatResource().getResourceableTypeName())) {
addLink("details.override.close", "override-close", "o_icon o_icon-fw o_icon_close_resource", links);
} else if(canClose) {
addLink("details.close.ressoure", "close", "o_icon o_icon-fw o_icon_close_resource", links);
}
if(!deleteManaged) {
addLink("details.delete", "delete", "o_icon o_icon-fw o_icon_delete_item", links);
}
}
mainVC.contextPut("links", links);
putInitialPanel(mainVC);
}
private void addLink(String name, String cmd, String iconCSS, List<String> links) {
Link link = LinkFactory.createLink(name, cmd, getTranslator(), mainVC, this, Link.LINK);
if(iconCSS != null) {
link.setIconLeftCSS(iconCSS);
}
mainVC.put(name, link);
links.add(name);
}
@Override
protected void event(UserRequest ureq, Component source, Event event) {
fireEvent(ureq, Event.DONE_EVENT);
if(source instanceof Link) {
Link link = (Link)source;
String cmd = link.getCommand();
if("description".equals(cmd)) {
launchEditDescription(ureq, row);
} else if("catalog".equals(cmd)) {
launchCatalog(ureq, row);
} else if("members".equals(cmd)) {
launchMembers(ureq, row);
} else if("copy".equals(cmd)) {
doCopy(ureq, row);
} else if("download".equals(cmd)) {
doDownload(ureq, row);
} else if("close".equals(cmd)) {
doCloseResource(ureq, row);
} else if("override-close".equals(cmd)) {
doOverrideCloseResource(ureq, row);
} else if("delete".equals(cmd)) {
doDelete(ureq, Collections.singletonList(row));
}
}
}
@Override
protected void doDispose() {
//
}
}
}