/**
* <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.group.ui.main;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.olat.NewControllerFactory;
import org.olat.basesecurity.BaseSecurity;
import org.olat.basesecurity.GroupRoles;
import org.olat.collaboration.CollaborationTools;
import org.olat.collaboration.CollaborationToolsFactory;
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.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.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.FlexiTableColumnModel;
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.link.Link;
import org.olat.core.gui.components.table.ColumnDescriptor;
import org.olat.core.gui.components.table.CustomRenderColumnDescriptor;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
import org.olat.core.gui.control.generic.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.Step;
import org.olat.core.gui.control.generic.wizard.StepRunnerCallback;
import org.olat.core.gui.control.generic.wizard.StepsMainRunController;
import org.olat.core.gui.control.generic.wizard.StepsRunContext;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.id.Roles;
import org.olat.core.id.UserConstants;
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.mail.ContactList;
import org.olat.core.util.mail.ContactMessage;
import org.olat.core.util.mail.MailHelper;
import org.olat.core.util.mail.MailPackage;
import org.olat.core.util.mail.MailTemplate;
import org.olat.core.util.resource.OresHelper;
import org.olat.core.util.vfs.Quota;
import org.olat.core.util.vfs.QuotaManager;
import org.olat.group.BusinessGroup;
import org.olat.group.BusinessGroupManagedFlag;
import org.olat.group.BusinessGroupMembership;
import org.olat.group.BusinessGroupModule;
import org.olat.group.BusinessGroupRef;
import org.olat.group.BusinessGroupService;
import org.olat.group.BusinessGroupShort;
import org.olat.group.GroupLoggingAction;
import org.olat.group.area.BGAreaManager;
import org.olat.group.manager.BusinessGroupMailing;
import org.olat.group.manager.BusinessGroupMailing.MailType;
import org.olat.group.model.BusinessGroupQueryParams;
import org.olat.group.model.BusinessGroupRow;
import org.olat.group.model.BusinessGroupSelectionEvent;
import org.olat.group.model.LeaveOption;
import org.olat.group.model.MembershipModification;
import org.olat.group.right.BGRightManager;
import org.olat.group.ui.NewBGController;
import org.olat.group.ui.main.BusinessGroupListFlexiTableModel.Cols;
import org.olat.group.ui.wizard.BGConfigBusinessGroup;
import org.olat.group.ui.wizard.BGConfigToolsStep;
import org.olat.group.ui.wizard.BGCopyBusinessGroup;
import org.olat.group.ui.wizard.BGCopyPreparationStep;
import org.olat.group.ui.wizard.BGEmailSelectReceiversStep;
import org.olat.group.ui.wizard.BGMailNotificationEditController;
import org.olat.group.ui.wizard.BGMergeStep;
import org.olat.group.ui.wizard.BGUserMailTemplate;
import org.olat.group.ui.wizard.BGUserManagementController;
import org.olat.modules.co.ContactFormController;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryEntryRef;
import org.olat.repository.RepositoryEntryShort;
import org.olat.resource.accesscontrol.ACService;
import org.olat.util.logging.activity.LoggingResourceable;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*/
public abstract class AbstractBusinessGroupListController extends FormBasicController implements Activateable2 {
protected static final String TABLE_ACTION_LEAVE = "bgTblLeave";
protected static final String TABLE_ACTION_EDIT = "bgTblEdit";
protected static final String TABLE_ACTION_LAUNCH = "bgTblLaunch";
protected static final String TABLE_ACTION_OPEN = "bgTblOpen";
protected static final String TABLE_ACTION_ACCESS = "bgTblAccess";
protected static final String TABLE_ACTION_DUPLICATE = "bgTblDuplicate";
protected static final String TABLE_ACTION_MERGE = "bgTblMerge";
protected static final String TABLE_ACTION_USERS = "bgTblUser";
protected static final String TABLE_ACTION_CONFIG = "bgTblConfig";
protected static final String TABLE_ACTION_EMAIL = "bgTblEmail";
protected static final String TABLE_ACTION_DELETE = "bgTblDelete";
protected static final String TABLE_ACTION_SELECT = "bgTblSelect";
protected static final BusinessGroupMembershipComparator MEMBERSHIP_COMPARATOR = new BusinessGroupMembershipComparator();
protected FlexiTableElement tableEl;
protected BusinessGroupListFlexiTableModel groupTableModel;
protected BusinessGroupQueryParams lastSearchParams;
private DialogBoxController leaveDialogBox;
protected FormLink createButton, deleteButton, duplicateButton,
configButton, emailButton, usersButton, mergeButton, selectButton;
private ContactFormController contactCtrl;
private NewBGController groupCreateController;
private BGUserManagementController userManagementController;
private BGMailNotificationEditController userManagementSendMailController;
private BusinessGroupDeleteDialogBoxController deleteDialogBox;
private StepsMainRunController emailWizard, businessGroupWizard;
protected BusinessGroupSearchController searchCtrl;
protected CloseableModalController cmc;
private final boolean admin;
protected final boolean readOnly;
private final boolean showAdminTools;
private final boolean startExtendedSearch;
@Autowired
protected MarkManager markManager;
@Autowired
protected BaseSecurity securityManager;
@Autowired
protected BusinessGroupModule groupModule;
@Autowired
protected ACService acService;
@Autowired
protected BGAreaManager areaManager;
@Autowired
protected BGRightManager rightManager;
@Autowired
protected BusinessGroupService businessGroupService;
@Autowired
protected CollaborationToolsFactory collaborationTools;
private BusinessGroupViewFilter filter;
private Object userObject;
private final String prefsKey;
public AbstractBusinessGroupListController(UserRequest ureq, WindowControl wControl, String page, String prefsKey) {
this(ureq, wControl, page, false, false, false, prefsKey, null);
}
public AbstractBusinessGroupListController(UserRequest ureq, WindowControl wControl, String page,
boolean showAdminTools, boolean startExtendedSearch, boolean readOnly, String prefsKey, Object userObject) {
super(ureq, wControl, page);
setTranslator(Util.createPackageTranslator(AbstractBusinessGroupListController.class, ureq.getLocale(), getTranslator()));
Roles roles = ureq.getUserSession().getRoles();
admin = roles.isOLATAdmin() || roles.isGroupManager();
this.readOnly = readOnly;
this.showAdminTools = showAdminTools && admin;
this.userObject = userObject;
this.startExtendedSearch = startExtendedSearch;
this.prefsKey = prefsKey;
initForm(ureq);
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
FlexiTableColumnModel columnModel = initColumnModel();
groupTableModel = initTableModel(columnModel);
tableEl = uifactory.addTableElement(getWindowControl(), "table", groupTableModel, 20, false, getTranslator(), formLayout);
tableEl.setElementCssClass("o_group_list");
FlexiTableSortOptions options = new FlexiTableSortOptions();
options.setFromColumnModel(true);
tableEl.setSortSettings(options);
tableEl.setAndLoadPersistedPreferences(ureq, "gbg-list-" + prefsKey);
searchCtrl = new BusinessGroupSearchController(ureq, getWindowControl(), isAdmin(), true, showAdminTools, isAdmin(), mainForm);
searchCtrl.setEnabled(false);
listenTo(searchCtrl);
tableEl.setSearchEnabled(true);
tableEl.setExtendedSearch(searchCtrl);
if(startExtendedSearch) {
tableEl.expandExtendedSearch(ureq);
}
initButtons(formLayout, ureq);
}
protected abstract FlexiTableColumnModel initColumnModel();
protected final BusinessGroupListFlexiTableModel initTableModel(FlexiTableColumnModel columnModel) {
return new BusinessGroupListFlexiTableModel(columnModel, getLocale());
}
public Object getUserObject() {
return userObject;
}
public BusinessGroupViewFilter getFilter() {
return filter;
}
public void setFilter(BusinessGroupViewFilter filter) {
this.filter = filter;
}
protected abstract void initButtons(FormItemContainer formLayout, UserRequest ureq);
protected void initButtons(FormItemContainer formLayout, UserRequest ureq, boolean create, boolean select, boolean adminTools) {
if(create && groupModule.isAllowedCreate(ureq.getUserSession().getRoles())) {
createButton = uifactory.addFormLink("create.group", formLayout, Link.BUTTON);
createButton.setElementCssClass("o_sel_group_create");
}
if(select) {
tableEl.setMultiSelect(true);
tableEl.setSelectAllEnable(true);
selectButton = uifactory.addFormLink("select", TABLE_ACTION_SELECT, "select", null, formLayout, Link.BUTTON);
}
if(adminTools) {
tableEl.setMultiSelect(true);
tableEl.setSelectAllEnable(true);
boolean canCreateGroup = canCreateBusinessGroup(ureq);
if(canCreateGroup) {
duplicateButton = uifactory.addFormLink("table.duplicate", TABLE_ACTION_DUPLICATE, "table.duplicate", null, formLayout, Link.BUTTON);
mergeButton = uifactory.addFormLink("table.merge", TABLE_ACTION_MERGE, "table.merge", null, formLayout, Link.BUTTON);
}
usersButton = uifactory.addFormLink("table.users.management", TABLE_ACTION_USERS, "table.users.management", null, formLayout, Link.BUTTON);
configButton = uifactory.addFormLink("table.config", TABLE_ACTION_CONFIG, "table.config", null, formLayout, Link.BUTTON);
emailButton = uifactory.addFormLink("table.email", TABLE_ACTION_EMAIL, "table.email", null, formLayout, Link.BUTTON);
if(canCreateGroup) {
deleteButton = uifactory.addFormLink("table.delete", TABLE_ACTION_DELETE, "table.delete", null, formLayout, Link.BUTTON);
}
}
}
protected boolean canCreateBusinessGroup(UserRequest ureq) {
Roles roles = ureq.getUserSession().getRoles();
if(roles.isOLATAdmin() || roles.isGroupManager()
|| (roles.isAuthor() && groupModule.isAuthorAllowedCreate())
|| (!roles.isGuestOnly() && !roles.isInvitee() && groupModule.isUserAllowedCreate())) {
return true;
}
return false;
}
protected boolean isAdmin() {
return admin;
}
protected boolean isEmpty() {
return tableEl == null ? true :
(groupTableModel == null ? true :
groupTableModel.getRowCount() == 0);
}
@Override
protected void doDispose() {
//
}
@Override
public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
//
}
@Override
protected void formOK(UserRequest ureq) {
//
}
protected List<BusinessGroupRow> getSelectedItems() {
Set<Integer> selections = tableEl.getMultiSelectedIndex();
List<BusinessGroupRow> rows = new ArrayList<>(selections.size());
for(Integer i:selections) {
BusinessGroupRow row = groupTableModel.getObject(i.intValue());
if(row != null) {
rows.add(row);
}
}
return rows;
}
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if(createButton == source) {
doCreate(ureq, getWindowControl(), null);
} else if(deleteButton == source) {
confirmDelete(ureq, getSelectedItems());
} else if(duplicateButton == source) {
doCopy(ureq, getSelectedItems());
} else if(configButton == source) {
doConfiguration(ureq, getSelectedItems());
} else if(emailButton == source) {
doEmails(ureq, getSelectedItems());
} else if(usersButton == source) {
doUserManagement(ureq, getSelectedItems());
} else if(mergeButton == source) {
doMerge(ureq, getSelectedItems());
} else if(selectButton == source) {
doSelect(ureq, getSelectedItems());
} else if(source instanceof FormLink) {
FormLink link = (FormLink)source;
String cmd = link.getCmd();
if("mark".equals(cmd)) {
BusinessGroupRow row = (BusinessGroupRow)link.getUserObject();
boolean marked = toogleMark(row);
link.setIconLeftCSS(marked ? "o_icon o_icon_bookmark o_icon-lg" : "o_icon o_icon_bookmark_add o_icon-lg");
link.getComponent().setDirty(true);
} else if("allresources".equals(cmd)) {
BusinessGroupShort bg = (BusinessGroupShort)link.getUserObject();
NewControllerFactory.getInstance().launch("[BusinessGroup:" + bg.getKey() + "][toolresources:0]", ureq, getWindowControl());
} else if("resource".equals(cmd)) {
RepositoryEntryShort re = (RepositoryEntryShort)link.getUserObject();
NewControllerFactory.getInstance().launch("[RepositoryEntry:" + re.getKey() + "]", ureq, getWindowControl());
} else if(link.getUserObject() instanceof BusinessGroupRef) {
BusinessGroupRef item = (BusinessGroupRef)link.getUserObject();
Long businessGroupKey = item.getKey();
BusinessGroup businessGroup = businessGroupService.loadBusinessGroup(businessGroupKey);
if(businessGroup == null) {
groupTableModel.removeBusinessGroup(businessGroupKey);
tableEl.reset();
} else if(TABLE_ACTION_ACCESS.equals(cmd)) {
doAccess(ureq, businessGroup);
} else if(TABLE_ACTION_LEAVE.equals(cmd)) {
doConfirmLeaving(ureq, businessGroup);
}
}
} else if(source == tableEl) {
String cmd = event.getCommand();
if(event instanceof SelectionEvent) {
SelectionEvent se = (SelectionEvent)event;
if(se.getIndex() >= 0 && se.getIndex() < groupTableModel.getRowCount()) {
BusinessGroupRef item = groupTableModel.getObject(se.getIndex());
Long businessGroupKey = item.getKey();
BusinessGroup businessGroup = businessGroupService.loadBusinessGroup(businessGroupKey);
//prevent rs after a group is deleted by someone else
if(businessGroup == null) {
groupTableModel.removeBusinessGroup(businessGroupKey);
tableEl.reset();
} else if(TABLE_ACTION_LAUNCH.equals(cmd)) {
doLaunch(ureq, businessGroup);
} else if(TABLE_ACTION_DELETE.equals(cmd)) {
confirmDelete(ureq, Collections.singletonList(item));
} else if(TABLE_ACTION_LAUNCH.equals(cmd)) {
doLaunch(ureq, businessGroup);
} else if(TABLE_ACTION_EDIT.equals(cmd)) {
doEdit(ureq, businessGroup);
} else if(TABLE_ACTION_LEAVE.equals(cmd)) {
doConfirmLeaving(ureq, businessGroup);
} else if (TABLE_ACTION_ACCESS.equals(cmd)) {
doAccess(ureq, businessGroup);
} else if (TABLE_ACTION_SELECT.equals(cmd)) {
doSelect(ureq, businessGroup);
}
}
} else if(event instanceof FlexiTableSearchEvent) {
doSearch((FlexiTableSearchEvent)event);
}
}
super.formInnerEvent(ureq, source, event);
}
/**
* Add/remove as favorite
* @param item
*/
private boolean toogleMark(BusinessGroupRow item) {
OLATResourceable bgResource = OresHelper.createOLATResourceableInstance("BusinessGroup", item.getKey());
// item.getBusinessGroup().getResource();
if(markManager.isMarked(bgResource, getIdentity(), null)) {
markManager.removeMark(bgResource, getIdentity(), null);
item.setMarked(false);
} else {
String businessPath = "[BusinessGroup:" + item.getKey() + "]";
markManager.setMark(bgResource, getIdentity(), null, businessPath);
item.setMarked(true);
}
return item.isMarked();
}
@Override
protected void event(UserRequest ureq, Controller source, Event event) {
if (source == deleteDialogBox) {
if(event == Event.DONE_EVENT) {
boolean withEmail = deleteDialogBox.isSendMail();
List<BusinessGroup> groupsToDelete = deleteDialogBox.getGroupsToDelete();
doDelete(ureq, withEmail, groupsToDelete);
tableEl.deselectAll();
reloadModel();
}
cmc.deactivate();
cleanUpPopups();
} else if (source == leaveDialogBox) {
if (event != Event.CANCELLED_EVENT && DialogBoxUIFactory.isYesEvent(event)) {
doLeave((BusinessGroup)leaveDialogBox.getUserObject());
tableEl.deselectAll();
reloadModel();
}
} else if (source == groupCreateController) {
BusinessGroup group = null;
if(event == Event.DONE_EVENT) {
group = groupCreateController.getCreatedGroup();
if(group != null) {
tableEl.deselectAll();
reloadModel();
}
}
cmc.deactivate();
cleanUpPopups();
//if new group -> go to the tab
if(group != null) {
String businessPath = "[BusinessGroup:" + group.getKey() + "]";
NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
}
fireEvent(ureq, Event.CHANGED_EVENT);
} else if (source == businessGroupWizard) {
if(event == Event.CANCELLED_EVENT || event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
getWindowControl().pop();
removeAsListenerAndDispose(businessGroupWizard);
businessGroupWizard = null;
if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
reloadModel();
}
}
} else if(source == emailWizard) {
if(event == Event.CANCELLED_EVENT || event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
getWindowControl().pop();
removeAsListenerAndDispose(emailWizard);
emailWizard = null;
if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
tableEl.deselectAll();
}
}
} else if (source == userManagementController) {
cmc.deactivate();
if(event == Event.DONE_EVENT) {
//confirm sending emails
MembershipModification mod = userManagementController.getModifications();
List<BusinessGroup> groups = userManagementController.getGroups();
confirmUserManagementEmail(ureq, mod, groups);
} else {
cleanUpPopups();
}
} else if (source == userManagementSendMailController) {
if(event == Event.DONE_EVENT) {
BGUserMailTemplate sendMail = (BGUserMailTemplate)userManagementSendMailController.getTemplate();
MembershipModification mod = sendMail.getModifications();
List<BusinessGroup> groups = sendMail.getGroups();
finishUserManagement(mod, groups, sendMail, userManagementSendMailController.isSendMail());
reloadModel();
}
cmc.deactivate();
cleanUpPopups();
} else if(source == searchCtrl) {
if(event instanceof SearchEvent) {
doSearch(ureq, (SearchEvent)event);
}
} else if(source == contactCtrl) {
cmc.deactivate();
cleanUpPopups();
} else if (source == cmc) {
cleanUpPopups();
}
super.event(ureq, source, event);
}
@Override
protected void propagateDirtinessToContainer(FormItem fiSrc, FormEvent event) {
//
}
/**
* Aggressive clean up all popup controllers
*/
protected void cleanUpPopups() {
removeAsListenerAndDispose(cmc);
removeAsListenerAndDispose(contactCtrl);
removeAsListenerAndDispose(deleteDialogBox);
removeAsListenerAndDispose(groupCreateController);
removeAsListenerAndDispose(businessGroupWizard);
removeAsListenerAndDispose(leaveDialogBox);
cmc = null;
contactCtrl = null;
leaveDialogBox = null;
deleteDialogBox = null;
groupCreateController = null;
businessGroupWizard = null;
}
/**
* Launch a business group with its business path
* @param ureq
* @param group
*/
protected void doAccess(UserRequest ureq, BusinessGroup group) {
String businessPath = "[BusinessGroup:" + group.getKey() + "]";
NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
}
/**
* Launch a business group with its business path
* @param ureq
* @param group
*/
protected void doLaunch(UserRequest ureq, BusinessGroup group) {
String businessPath = "[BusinessGroup:" + group.getKey() + "]";
NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
}
/**
* Launch a business group with its business path in administration part
* @param ureq
* @param group
*/
protected void doEdit(UserRequest ureq, BusinessGroup group) {
String businessPath = "[BusinessGroup:" + group.getKey() + "][tooladmin:0]";
NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
}
private void doConfirmLeaving(UserRequest ureq, BusinessGroup businessGroup) {
if (businessGroupService.hasRoles(getIdentity(), businessGroup, GroupRoles.coach.name())
|| businessGroupService.hasRoles(getIdentity(), businessGroup, GroupRoles.waiting.name()) ) {
doOpenConfirmLeavingDialog(ureq, businessGroup);
} else {
LeaveOption option = businessGroupService.isAllowToLeaveBusinessGroup(getIdentity(), businessGroup);
if(option.isAllowToLeave()) {
doOpenConfirmLeavingDialog(ureq, businessGroup);
} else {
doAskToLeaveGroup(ureq, businessGroup, option.getContacts());
}
}
}
private void doOpenConfirmLeavingDialog(UserRequest ureq, BusinessGroup businessGroup) {
String groupName = StringHelper.escapeHtml(businessGroup.getName());
leaveDialogBox = activateYesNoDialog(ureq, null, translate("dialog.modal.bg.leave.text", groupName), leaveDialogBox);
leaveDialogBox.setUserObject(businessGroup);
}
private void doAskToLeaveGroup(UserRequest ureq, BusinessGroup businessGroup, ContactList contacts) {
String[] args = new String[]{
businessGroup.getName(),
businessGroup.getKey().toString(),
"",//courses
getIdentity().getUser().getProperty(UserConstants.FIRSTNAME, getLocale()),
getIdentity().getUser().getProperty(UserConstants.LASTNAME, getLocale())
};
ContactMessage msg = new ContactMessage(getIdentity());
msg.setSubject(translate("request.leaving.subject", args));
msg.setBodyText(translate("request.leaving.body", args));
msg.addEmailTo(contacts);
contactCtrl = new ContactFormController(ureq, getWindowControl(), true, false, true, msg);
listenTo(contactCtrl);
cmc = new CloseableModalController(getWindowControl(), "close", contactCtrl.getInitialComponent(),
true, translate("dialog.modal.bg.asktoleave.title"));
cmc.activate();
listenTo(cmc);
}
/**
* Removes user from the group as owner and participant. If
* no other owner are found the user won't be removed from the owner group
*
* @param ureq
*/
private void doLeave(BusinessGroup group) {
List<Identity> identityToRemove = Collections.singletonList(getIdentity());
// 1) remove as owner
if (businessGroupService.hasRoles(getIdentity(), group, GroupRoles.coach.name())) {
List<Identity> ownerList = businessGroupService.getMembers(group, GroupRoles.coach.name());
if (ownerList.size() > 1) {
businessGroupService.removeOwners(getIdentity(), identityToRemove, group);
} else {
// he is the last owner, but there must be at least one oner
// give him a warning, as long as he tries to leave, he gets
// this warning.
getWindowControl().setError(translate("msg.atleastone"));
return;
}
}
// if identity was also owner it must have successfully removed to end here.
// now remove the identity also as participant.
// 2) remove as participant
businessGroupService.removeParticipants(getIdentity(), identityToRemove, group, null);
// 3) remove from waiting list
businessGroupService.removeFromWaitingList(getIdentity(), identityToRemove, group, null);
}
/**
* Create a new business group
* @param ureq
* @param wControl
*/
protected void doCreate(UserRequest ureq, WindowControl wControl, RepositoryEntry re) {
removeAsListenerAndDispose(groupCreateController);
groupCreateController = new NewBGController(ureq, wControl, re, false, null);
listenTo(groupCreateController);
cmc = new CloseableModalController(getWindowControl(), translate("close"), groupCreateController.getInitialComponent(), true, translate("create.form.title"));
cmc.activate();
listenTo(cmc);
}
/**
* Make copies of a list of business groups
* @param ureq
* @param items
*/
private void doCopy(UserRequest ureq, List<? extends BusinessGroupRef> items) {
removeAsListenerAndDispose(businessGroupWizard);
if(items == null || items.isEmpty()) {
showWarning("error.select.one");
return;
}
List<BusinessGroup> groups = toBusinessGroups(ureq, items, true);
if(groups.isEmpty()) {
showWarning("msg.alleastone.editable.group");
return;
}
if(items.size() != groups.size()) {
showWarning("msg.only.editable.group");
return;
}
boolean enableCoursesCopy = businessGroupService.hasResources(groups);
boolean enableAreasCopy = areaManager.countBGAreasOfBusinessGroups(groups) > 0;
boolean enableRightsCopy = rightManager.hasBGRight(groups);
Step start = new BGCopyPreparationStep(ureq, groups, enableCoursesCopy, enableAreasCopy, enableRightsCopy);
StepRunnerCallback finish = new StepRunnerCallback() {
@Override
public Step execute(UserRequest uureq, WindowControl wControl, StepsRunContext runContext) {
@SuppressWarnings("unchecked")
List<BGCopyBusinessGroup> copies = (List<BGCopyBusinessGroup>)runContext.get("groupsCopy");
if(copies != null && !copies.isEmpty()) {
boolean copyAreas = convertToBoolean(runContext, "areas");
boolean copyCollabToolConfig = convertToBoolean(runContext, "tools");
boolean copyRights = convertToBoolean(runContext, "rights");
boolean copyOwners = convertToBoolean(runContext, "owners");
boolean copyParticipants = convertToBoolean(runContext, "participants");
boolean copyMemberVisibility = convertToBoolean(runContext, "membersvisibility");
boolean copyWaitingList = convertToBoolean(runContext, "waitingList");
boolean copyRelations = convertToBoolean(runContext, "resources");
for(BGCopyBusinessGroup copy:copies) {
businessGroupService.copyBusinessGroup(getIdentity(), copy.getOriginal(), copy.getName(), copy.getDescription(),
copy.getMinParticipants(), copy.getMaxParticipants(),
copyAreas, copyCollabToolConfig, copyRights, copyOwners, copyParticipants,
copyMemberVisibility, copyWaitingList, copyRelations);
}
return StepsMainRunController.DONE_MODIFIED;
} else {
return StepsMainRunController.DONE_UNCHANGED;
}
}
};
businessGroupWizard = new StepsMainRunController(ureq, getWindowControl(), start, finish, null, translate("copy.group"), "o_sel_group_copy_wizard");
listenTo(businessGroupWizard);
getWindowControl().pushAsModalDialog(businessGroupWizard.getInitialComponent());
}
private boolean convertToBoolean(StepsRunContext runContext, String key) {
Object obj = runContext.get(key);
if(obj instanceof Boolean) {
return ((Boolean)obj).booleanValue();
} else {
return false;
}
}
/**
*
* @param ureq
* @param items
*/
private void doConfiguration(UserRequest ureq, List<? extends BusinessGroupRef> selectedItems) {
removeAsListenerAndDispose(businessGroupWizard);
if(selectedItems == null || selectedItems.isEmpty()) {
showWarning("error.select.one");
return;
}
final List<BusinessGroup> groups = toBusinessGroups(ureq, selectedItems, true);
if(groups.isEmpty()) {
showWarning("msg.alleastone.editable.group");
return;
}
if(selectedItems.size() != groups.size()) {
showWarning("msg.only.editable.group");
return;
}
if(CollaborationToolsFactory.getInstance().getAvailableTools() == null) {
//init the available tools
CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(groups.get(0));
}
StringBuilder managedNames = new StringBuilder();
for(BusinessGroup group:groups) {
String gname = group.getName() == null ? "???" : group.getName();
if(BusinessGroupManagedFlag.isManaged(group, BusinessGroupManagedFlag.resources)
|| BusinessGroupManagedFlag.isManaged(group, BusinessGroupManagedFlag.tools)) {
if(managedNames.length() > 0) managedNames.append(", ");
managedNames.append(gname);
}
}
if(managedNames.length() > 0) {
showWarning("error.managed.group", managedNames.toString());
return;
}
boolean isAuthor = ureq.getUserSession().getRoles().isAuthor()
|| ureq.getUserSession().getRoles().isInstitutionalResourceManager();
Step start = new BGConfigToolsStep(ureq, isAuthor);
StepRunnerCallback finish = new StepRunnerCallback() {
@Override
public Step execute(UserRequest uureq, WindowControl wControl, StepsRunContext runContext) {
//configuration
BGConfigBusinessGroup configuration = (BGConfigBusinessGroup)runContext.get("configuration");
if(!configuration.getToolsToEnable().isEmpty() || !configuration.getToolsToDisable().isEmpty()) {
for(BusinessGroup group:groups) {
CollaborationTools tools = CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(group);
for(String enabledTool:configuration.getToolsToEnable()) {
tools.setToolEnabled(enabledTool, true);
if(CollaborationTools.TOOL_FOLDER.equals(enabledTool)) {
tools.saveFolderAccess(new Long(configuration.getFolderAccess()));
Quota quota = configuration.getQuota();
if(quota != null) {
String path = tools.getFolderRelPath();
Quota fQuota = QuotaManager.getInstance()
.createQuota(path, quota.getQuotaKB(), quota.getUlLimitKB());
QuotaManager.getInstance()
.setCustomQuotaKB(fQuota);
}
} else if (CollaborationTools.TOOL_CALENDAR.equals(enabledTool)) {
tools.saveCalendarAccess(new Long(configuration.getCalendarAccess()));
}
}
for(String disabledTool:configuration.getToolsToDisable()) {
tools.setToolEnabled(disabledTool, false);
}
}
}
if(configuration.getResources() != null && !configuration.getResources().isEmpty()) {
businessGroupService.addResourcesTo(groups, configuration.getResources());
}
return StepsMainRunController.DONE_MODIFIED;
}
};
businessGroupWizard = new StepsMainRunController(ureq, getWindowControl(), start, finish, null, translate("config.group"), "o_sel_groups_config_wizard");
listenTo(businessGroupWizard);
getWindowControl().pushAsModalDialog(businessGroupWizard.getInitialComponent());
}
/**
*
* @param ureq
* @param items
*/
private void doEmails(UserRequest ureq, List<? extends BusinessGroupRef> selectedItems) {
removeAsListenerAndDispose(emailWizard);
if(selectedItems == null || selectedItems.isEmpty()) {
showWarning("error.select.one");
return;
}
List<BusinessGroup> groups = toBusinessGroups(ureq, selectedItems, true);
if(groups.isEmpty()) {
showWarning("msg.alleastone.editable.group");
return;
}
if(selectedItems.size() != groups.size()) {
showWarning("msg.only.editable.group");
return;
}
Step start = new BGEmailSelectReceiversStep(ureq, groups);
StepRunnerCallback finish = new StepRunnerCallback() {
@Override
public Step execute(UserRequest uureq, WindowControl wControl, StepsRunContext runContext) {
//mails are send by the last controller of the wizard
return StepsMainRunController.DONE_MODIFIED;
}
};
emailWizard = new StepsMainRunController(ureq, getWindowControl(), start, finish, null, translate("email.group"), "o_sel_groups_email_wizard");
listenTo(emailWizard);
getWindowControl().pushAsModalDialog(emailWizard.getInitialComponent());
}
/**
*
* @param ureq
* @param items
*/
private void doUserManagement(UserRequest ureq, List<? extends BusinessGroupRef> selectedItems) {
removeAsListenerAndDispose(cmc);
removeAsListenerAndDispose(userManagementController);
if(selectedItems == null || selectedItems.isEmpty()) {
showWarning("error.select.one");
return;
}
List<BusinessGroup> groups = toBusinessGroups(ureq, selectedItems, true);
if(groups.isEmpty()) {
showWarning("msg.alleastone.editable.group");
return;
}
if(selectedItems.size() != groups.size()) {
showWarning("msg.only.editable.group");
return;
}
StringBuilder managedNames = new StringBuilder();
for(BusinessGroup group:groups) {
String gname = group.getName() == null ? "???" : group.getName();
if(BusinessGroupManagedFlag.isManaged(group, BusinessGroupManagedFlag.membersmanagement)) {
if(managedNames.length() > 0) managedNames.append(", ");
managedNames.append(gname);
}
}
if(managedNames.length() > 0) {
showWarning("error.managed.group", managedNames.toString());
return;
}
userManagementController = new BGUserManagementController(ureq, getWindowControl(), groups);
listenTo(userManagementController);
cmc = new CloseableModalController(getWindowControl(), translate("close"), userManagementController.getInitialComponent(),
true, translate("users.group"));
cmc.activate();
listenTo(cmc);
}
private void confirmUserManagementEmail(UserRequest ureq, MembershipModification mod, List<BusinessGroup> groups) {
removeAsListenerAndDispose(cmc);
removeAsListenerAndDispose(userManagementSendMailController);
MailTemplate defaultTemplate = null;
int totalModification = (mod.size() * groups.size());
if(totalModification == 1) {
MailType type = BusinessGroupMailing.getDefaultTemplateType(mod);
if(type != null) {
defaultTemplate = BusinessGroupMailing.getDefaultTemplate(type, groups.get(0), ureq.getIdentity());
}
}
MailTemplate template = new BGUserMailTemplate(groups, mod, defaultTemplate);
boolean mandatoryEmail = !mod.getAddParticipants().isEmpty() &&
groupModule.isMandatoryEnrolmentEmail(ureq.getUserSession().getRoles());
userManagementSendMailController = new BGMailNotificationEditController(getWindowControl(), ureq, template,
totalModification == 1, totalModification == 1, false, mandatoryEmail);
Component cmp = userManagementSendMailController.getInitialComponent();
listenTo(userManagementSendMailController);
cmc = new CloseableModalController(getWindowControl(), translate("close"), cmp, true, translate("users.group"));
cmc.activate();
listenTo(cmc);
}
private void finishUserManagement(MembershipModification mod, List<BusinessGroup> groups, MailTemplate template, boolean sendMail) {
MailPackage mailing = new MailPackage(template, getWindowControl().getBusinessControl().getAsString(), sendMail);
businessGroupService.updateMembership(getIdentity(), mod, groups, mailing);
MailHelper.printErrorsAndWarnings(mailing.getResult(), getWindowControl(), getLocale());
}
protected void doSearch(UserRequest ureq, SearchEvent event) {
search(event);
//back button
ContextEntry currentEntry = getWindowControl().getBusinessControl().getCurrentContextEntry();
if(currentEntry != null) {
currentEntry.setTransientState(event);
}
addToHistory(ureq, this);
}
protected void doSearch(FlexiTableSearchEvent event) {
BusinessGroupQueryParams params = getDefaultSearchParams();
params.setNameOrDesc(event.getSearch());
loadModel(params);
}
private void search(SearchEvent event) {
if(event == null) {
loadModel(null);
} else {
BusinessGroupQueryParams params = getSearchParams(event);
loadModel(params);
}
}
protected abstract BusinessGroupQueryParams getSearchParams(SearchEvent event);
protected abstract BusinessGroupQueryParams getDefaultSearchParams();
protected boolean doDefaultSearch() {
BusinessGroupQueryParams params = getDefaultSearchParams();
return loadModel(params) > 0;
}
private void doSelect(UserRequest ureq, List<? extends BusinessGroupRef> items) {
List<BusinessGroup> selection = toBusinessGroups(ureq, items, false);
fireEvent(ureq, new BusinessGroupSelectionEvent(selection));
}
private void doSelect(UserRequest ureq, BusinessGroup group) {
List<BusinessGroup> selection = Collections.singletonList(group);
fireEvent(ureq, new BusinessGroupSelectionEvent(selection));
}
/**
*
* @param ureq
* @param items
*/
private void doMerge(UserRequest ureq, List<? extends BusinessGroupRef> selectedItems) {
removeAsListenerAndDispose(businessGroupWizard);
if(selectedItems == null || selectedItems.size() < 2) {
showWarning("error.select.one");
return;
}
final List<BusinessGroup> groups = toBusinessGroups(ureq, selectedItems, true);
if(groups.size() < 2) {
showWarning("msg.alleasttwo.editable.group");
return;
}
if(selectedItems.size() != groups.size()) {
showWarning("msg.only.editable.group");
return;
}
StringBuilder managedNames = new StringBuilder();
for(BusinessGroup group:groups) {
String gname = group.getName() == null ? "???" : StringHelper.escapeHtml(group.getName());
if(StringHelper.containsNonWhitespace(group.getManagedFlagsString())) {
if(managedNames.length() > 0) managedNames.append(", ");
managedNames.append(gname);
}
}
if(managedNames.length() > 0) {
showWarning("error.managed.group", managedNames.toString());
return;
}
Step start = new BGMergeStep(ureq, groups);
StepRunnerCallback finish = new StepRunnerCallback() {
@Override
public Step execute(UserRequest uureq, WindowControl wControl, StepsRunContext runContext) {
BusinessGroup targetGroup = (BusinessGroup)runContext.get("targetGroup");
groups.remove(targetGroup);
businessGroupService.mergeBusinessGroups(getIdentity(), targetGroup, groups, null);
return StepsMainRunController.DONE_MODIFIED;
}
};
businessGroupWizard = new StepsMainRunController(ureq, getWindowControl(), start, finish, null, translate("merge.group"), "o_sel_groups_merge_wizard");
listenTo(businessGroupWizard);
getWindowControl().pushAsModalDialog(businessGroupWizard.getInitialComponent());
}
/**
* Confirmation panel before deleting the groups
* @param ureq
* @param selectedItems
*/
private void confirmDelete(UserRequest ureq, List<? extends BusinessGroupRef> selectedItems) {
List<BusinessGroup> groups = toBusinessGroups(ureq, selectedItems, true);
if(groups.isEmpty()) {
showWarning("msg.alleastone.editable.group");
return;
}
if(selectedItems.size() != groups.size()) {
showWarning("msg.only.editable.group");
return;
}
StringBuilder names = new StringBuilder();
StringBuilder managedNames = new StringBuilder();
for(BusinessGroup group:groups) {
String gname = group.getName() == null ? "???" : group.getName();
if(BusinessGroupManagedFlag.isManaged(group, BusinessGroupManagedFlag.delete)) {
if(managedNames.length() > 0) managedNames.append(", ");
managedNames.append(gname);
} else {
if(names.length() > 0) names.append(", ");
names.append(gname);
}
}
if(managedNames.length() > 0) {
showWarning("error.managed.group", managedNames.toString());
} else {
deleteDialogBox = new BusinessGroupDeleteDialogBoxController(ureq, getWindowControl(), groups);
listenTo(deleteDialogBox);
cmc = new CloseableModalController(getWindowControl(), translate("close"), deleteDialogBox.getInitialComponent(),
true, translate("dialog.modal.bg.delete.title"));
cmc.activate();
listenTo(cmc);
}
}
protected final List<BusinessGroup> toBusinessGroups(UserRequest ureq, List<? extends BusinessGroupRef> items, boolean editableOnly) {
List<Long> groupKeys = new ArrayList<Long>();
for(BusinessGroupRef item:items) {
groupKeys.add(item.getKey());
}
if(editableOnly) {
filterEditableGroupKeys(ureq, groupKeys);
}
List<BusinessGroup> groups = businessGroupService.loadBusinessGroups(groupKeys);
return groups;
}
protected boolean filterEditableGroupKeys(UserRequest ureq, List<Long> groupKeys) {
if(ureq.getUserSession().getRoles().isOLATAdmin() || ureq.getUserSession().getRoles().isGroupManager()) {
return false;
}
int countBefore = groupKeys.size();
for(BGTableItem item:groupTableModel.getObjects()) {
Long groupKey = item.getBusinessGroupKey();
if(groupKeys.contains(groupKey)) {
BusinessGroupMembership membership = item.getMembership();
if(membership == null || !membership.isOwner()) {
groupKeys.remove(groupKey);
}
}
}
return groupKeys.size() != countBefore;
}
/**
* Deletes the group. Checks if user is in owner group,
* otherwise does nothing
*
* @param ureq
* @param doSendMail specifies if notification mails should be sent to users of delted group
*/
private void doDelete(UserRequest ureq, boolean doSendMail, List<BusinessGroup> groups) {
for(BusinessGroup group:groups) {
//check security
boolean ow = ureq.getUserSession().getRoles().isOLATAdmin()
|| ureq.getUserSession().getRoles().isGroupManager()
|| businessGroupService.hasRoles(getIdentity(), group, GroupRoles.coach.name());
if (ow) {
if (doSendMail) {
String businessPath = getWindowControl().getBusinessControl().getAsString();
businessGroupService.deleteBusinessGroupWithMail(group, businessPath, getIdentity(), getLocale());
} else {
businessGroupService.deleteBusinessGroup(group);
}
ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_DELETED, getClass(), LoggingResourceable.wrap(group));
}
}
showInfo("info.group.deleted");
}
protected void reloadModel() {
loadModel(lastSearchParams);
}
protected RepositoryEntryRef getResource() {
return null;
}
protected abstract List<BGTableItem> searchTableItems(BusinessGroupQueryParams params);
protected final int loadModel(BusinessGroupQueryParams params) {
this.lastSearchParams = params;
if(params == null) {
groupTableModel.setEntries(Collections.<BGTableItem>emptyList());
tableEl.reset(true, true, true);
return 0;
} else {
List<BGTableItem> items = searchTableItems(params);
if(filter != null) {
for(Iterator<BGTableItem> groupIt=items.iterator(); groupIt.hasNext(); ) {
if(!filter.accept(groupIt.next())) {
groupIt.remove();
}
}
}
groupTableModel.setEntries(items);
tableEl.reset(true, true, true);
return items.size();
}
}
protected static class RoleColumnDescriptor extends CustomRenderColumnDescriptor {
public RoleColumnDescriptor(Locale locale) {
super(Cols.role.i18n(), Cols.role.ordinal(), null, locale, ColumnDescriptor.ALIGNMENT_LEFT, new BGRoleCellRenderer(locale));
}
@Override
public int compareTo(int rowa, int rowb) {
Object a = table.getTableDataModel().getValueAt(rowa,dataColumn);
Object b = table.getTableDataModel().getValueAt(rowb,dataColumn);
if(a instanceof BusinessGroupMembership && b instanceof BusinessGroupMembership) {
return MEMBERSHIP_COMPARATOR.compare((BusinessGroupMembership)a, (BusinessGroupMembership)b);
}
return super.compareTo(rowa, rowb);
}
}
}