/** * <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.commons.memberlist.ui; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import org.olat.basesecurity.BaseSecurityModule; import org.olat.commons.memberlist.manager.MembersExportManager; import org.olat.commons.memberlist.ui.MembersAvatarDisplayRunController.IdentityComparator; import org.olat.core.commons.fullWebApp.popup.BaseFullWebappPopupLayoutFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; import org.olat.core.gui.components.link.LinkPopupSettings; 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.creator.ControllerCreator; import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; import org.olat.core.gui.media.MediaResource; import org.olat.core.gui.translator.Translator; import org.olat.core.helpers.Settings; import org.olat.core.id.Identity; import org.olat.core.id.IdentityEnvironment; import org.olat.core.id.Roles; import org.olat.core.id.UserConstants; import org.olat.core.util.Util; import org.olat.course.assessment.manager.UserCourseInformationsManager; import org.olat.course.nodes.members.Member; import org.olat.course.nodes.members.MembersCourseNodeRunController; import org.olat.course.run.environment.CourseEnvironment; import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupMembership; import org.olat.group.ui.main.MemberListTableModel; import org.olat.group.ui.main.MemberView; import org.olat.modules.co.ContactFormController; import org.olat.repository.RepositoryEntry; import org.olat.user.DisplayPortraitManager; import org.olat.user.UserManager; import org.olat.user.propertyhandlers.UserPropertyHandler; import org.springframework.beans.factory.annotation.Autowired; /** * Initial Date: 29.03.2017 * @author fkiefer, fabian.kiefer@frentix.com, www.frentix.com */ public class MembersListDisplayRunController extends BasicController { public static final String USER_PROPS_ID = MembersCourseNodeRunController.class.getName(); public static final int USER_PROPS_OFFSET = 500; private Link printLink; private Link allEmailLink; private Link downloadLink; private FormBasicController mailCtrl; private ContactFormController emailController; private CloseableModalController cmc; private List<Member> ownerList; private List<Member> coachList; private List<Member> participantList; private List<Member> waitingtList; private List<Identity> owners; private List<Identity> coaches; private List<Identity> participants; private List<Identity> waiting; private final boolean showOwners; private final boolean showCoaches; private final boolean showParticipants; private final boolean showWaiting; private final List<UserPropertyHandler> userPropertyHandlers; private final CourseEnvironment courseEnv; private final BusinessGroup businessGroup; private final RepositoryEntry repoEntry; protected FlexiTableElement ownersTable, coachesTable, participantsTable, waitingTable; protected MemberListTableModel ownersModel, coachesModel, participantsModel, waitingModel; private MembersTableController ownersTableCtrl, coachesTableCtrl, participantsTableCtrl, waitingTableCtrl; private Map<Long,BusinessGroupMembership> groupmemberships; private Map<Long,Date> recentLaunches, initialLaunches; private VelocityContainer mainVC; @Autowired private UserManager userManager; @Autowired private MembersExportManager exportManager; @Autowired private BaseSecurityModule securityModule; @Autowired private UserCourseInformationsManager userInfosMgr; public MembersListDisplayRunController(UserRequest ureq, WindowControl wControl, Translator translator, CourseEnvironment courseEnv, BusinessGroup businessGroup, List<Identity> owners, List<Identity> coaches, List<Identity> participants, List<Identity> waiting, boolean canEmail, boolean canDownload, boolean deduplicateList, boolean showOwners, boolean showCoaches, boolean showParticipants, boolean showWaiting, boolean editable) { super(ureq, wControl); Translator fallback = userManager.getPropertyHandlerTranslator(getTranslator()); setTranslator(Util.createPackageTranslator(translator, fallback, getLocale())); mainVC = createVelocityContainer("membersTable"); this.courseEnv = courseEnv; this.businessGroup = businessGroup; this.repoEntry = courseEnv != null ? courseEnv.getCourseGroupManager().getCourseEntry() : null; userPropertyHandlers = userManager.getUserPropertyHandlersFor(USER_PROPS_ID, false); // lists this.owners = owners; this.coaches = coaches; this.participants = participants; this.waiting = waiting; // flags this.showOwners = showOwners; this.showCoaches = showCoaches; this.showParticipants = showParticipants; this.showWaiting = showWaiting; if(canEmail) { allEmailLink = LinkFactory.createLink(null, "email", "email.all", "members.email.title", getTranslator(), mainVC, this, Link.BUTTON); allEmailLink.setIconLeftCSS("o_icon o_icon_mail"); } IdentityEnvironment idEnv = ureq.getUserSession().getIdentityEnvironment(); Identity ownId = idEnv.getIdentity(); Roles roles = idEnv.getRoles(); if (editable && (roles.isOLATAdmin() || roles.isGroupManager() || owners.contains(ownId) || coaches.contains(ownId) || (canDownload && !waiting.contains(ownId)))) { downloadLink = LinkFactory.createLink(null, "download", "download", "members.download", getTranslator(), mainVC, this, Link.BUTTON); downloadLink.setIconLeftCSS("o_icon o_icon_download"); printLink = LinkFactory.createButton("print", mainVC, this); printLink.setIconLeftCSS("o_icon o_icon_print o_icon-lg"); printLink.setPopup(new LinkPopupSettings(700, 500, "print-members")); } Comparator<Identity> idComparator = new IdentityComparator(); Collections.sort(owners, idComparator); ownerList = convertIdentitiesToMembers(owners); Collections.sort(coaches, idComparator); coachList = convertIdentitiesToMembers(coaches); Collections.sort(participants, idComparator); participantList = convertIdentitiesToMembers(participants); Collections.sort(waiting, idComparator); waitingtList = convertIdentitiesToMembers(waiting); Set<MemberView> duplicateCatcher = new HashSet<>(); boolean userLastTimeVisible = cacheGroupMemberships(ureq); if (showOwners && !owners.isEmpty()) { ownersTableCtrl = new MembersTableController(ureq, wControl, owners, duplicateCatcher, recentLaunches, initialLaunches, userPropertyHandlers, groupmemberships, repoEntry, businessGroup, courseEnv, deduplicateList, getTranslator(), editable, canEmail, userLastTimeVisible); listenTo(ownersTableCtrl); mainVC.put("ownerList", ownersTableCtrl.getInitialComponent()); } if (showCoaches && !coaches.isEmpty()) { coachesTableCtrl = new MembersTableController(ureq, wControl, coaches, duplicateCatcher, recentLaunches, initialLaunches, userPropertyHandlers, groupmemberships, repoEntry, businessGroup, courseEnv, deduplicateList, getTranslator(), editable, canEmail, userLastTimeVisible); listenTo(coachesTableCtrl); mainVC.put("coachList", coachesTableCtrl.getInitialComponent()); } if (showParticipants && !participants.isEmpty()) { participantsTableCtrl = new MembersTableController(ureq, wControl, participants, duplicateCatcher, recentLaunches, initialLaunches, userPropertyHandlers, groupmemberships, repoEntry, businessGroup, courseEnv, deduplicateList, getTranslator(), editable, canEmail, userLastTimeVisible); listenTo(participantsTableCtrl); mainVC.put("participantList", participantsTableCtrl.getInitialComponent()); } if (showWaiting && !waiting.isEmpty()) { waitingTableCtrl = new MembersTableController(ureq, wControl, waiting, duplicateCatcher, recentLaunches, initialLaunches, userPropertyHandlers, groupmemberships, repoEntry, businessGroup, courseEnv, deduplicateList, getTranslator(), editable, canEmail, userLastTimeVisible); listenTo(waitingTableCtrl); mainVC.put("waitingList", waitingTableCtrl.getInitialComponent()); } putInitialPanel(mainVC); } @Override public void event(UserRequest ureq, Component source, Event event) { if (source == printLink) { doPrint(ureq); } else if(source == allEmailLink) { doEmail(ureq); } else if (source == downloadLink) { doExport(ureq); } } @Override protected void event(UserRequest ureq, Controller source, Event event) { if(source == cmc) { cleanUp(); } else if (source == emailController) { cmc.deactivate(); cleanUp(); } else if(source == mailCtrl) { cmc.deactivate(); cleanUp(); } super.event(ureq, source, event); } private void cleanUp() { removeAsListenerAndDispose(emailController); removeAsListenerAndDispose(mailCtrl); removeAsListenerAndDispose(cmc); emailController = null; mailCtrl = null; cmc = null; } private boolean cacheGroupMemberships (UserRequest ureq) { boolean isUserLastVisitVisible = securityModule.isUserLastVisitVisible(ureq.getUserSession().getRoles()); if (isUserLastVisitVisible) { if (businessGroup != null) { List<BusinessGroup> groups = new ArrayList<>(); groups.add(businessGroup); groupmemberships = exportManager.getGroupMembershipMap(groups); } if (repoEntry != null) { initialLaunches = userInfosMgr.getInitialLaunchDates(repoEntry.getOlatResource().getResourceableId()); recentLaunches = userInfosMgr.getRecentLaunchDates(repoEntry.getOlatResource()); } } return isUserLastVisitVisible; } @Override protected void doDispose() { // } private void doEmail(UserRequest ureq) { if(mailCtrl != null || cmc != null) return; removeAsListenerAndDispose(cmc); removeAsListenerAndDispose(mailCtrl); mailCtrl = new MembersMailController(ureq, getWindowControl(), getTranslator(), courseEnv, ownerList, coachList, participantList, waitingtList, createBodyTemplate()); listenTo(mailCtrl); String title = translate("members.email.title"); cmc = new CloseableModalController(getWindowControl(), translate("close"), mailCtrl.getInitialComponent(), true, title); listenTo(cmc); cmc.activate(); } private String createBodyTemplate() { if (courseEnv == null) { String groupName = businessGroup.getName(); // Build REST URL to business group, use hack via group manager to access StringBuilder groupLink = new StringBuilder(); groupLink.append(Settings.getServerContextPathURI()) .append("/url/BusinessGroup/").append(businessGroup.getKey()); return translate("email.body.template", new String[]{groupName, groupLink.toString()}); } else { String courseName = courseEnv.getCourseTitle(); // Build REST URL to course element, use hack via group manager to access repo entry StringBuilder courseLink = new StringBuilder(); RepositoryEntry entry = courseEnv.getCourseGroupManager().getCourseEntry(); courseLink.append(Settings.getServerContextPathURI()) .append("/url/RepositoryEntry/").append(entry.getKey()); return translate("email.body.template", new String[]{courseName, courseLink.toString()}); } } private void doExport(UserRequest ureq) { MediaResource resource = exportManager.getXlsMediaResource(showOwners, showCoaches, showParticipants, showWaiting, owners, coaches, participants, waiting, getTranslator(), userPropertyHandlers, repoEntry, businessGroup); ureq.getDispatchResult().setResultingMediaResource(resource); } private void doPrint(UserRequest ureq) { ControllerCreator printControllerCreator = new ControllerCreator() { @Override public Controller createController(UserRequest lureq, WindowControl lwControl) { lwControl.getWindowBackOffice().getChiefController().addBodyCssClass("o_cmembers_print"); return new MembersPrintController(lureq, lwControl, userPropertyHandlers, getTranslator(), ownerList, coachList, participantList, waitingtList, showOwners, showCoaches, showParticipants, showWaiting, courseEnv != null ? courseEnv.getCourseTitle() : businessGroup.getName()); } }; ControllerCreator layoutCtrlr = BaseFullWebappPopupLayoutFactory.createPrintPopupLayout(printControllerCreator); openInNewBrowserWindow(ureq, layoutCtrlr); } private List<Member> convertIdentitiesToMembers(List<Identity> identities) { List<Member> memberList = new ArrayList<>(); for (Identity identity : identities) { Member member = createMember(identity); memberList.add(member); } return memberList; } private Member createMember(Identity identity) { boolean hasPortrait = DisplayPortraitManager.getInstance().hasPortrait(identity.getName()); String portraitCssClass; String gender = identity.getUser().getProperty(UserConstants.GENDER, Locale.ENGLISH); if ("male".equalsIgnoreCase(gender)) { portraitCssClass = DisplayPortraitManager.DUMMY_MALE_BIG_CSS_CLASS; } else if ("female".equalsIgnoreCase(gender)) { portraitCssClass = DisplayPortraitManager.DUMMY_FEMALE_BIG_CSS_CLASS; } else { portraitCssClass = DisplayPortraitManager.DUMMY_BIG_CSS_CLASS; } String fullname = userManager.getUserDisplayName(identity); return new Member(identity, fullname, userPropertyHandlers, getLocale(), hasPortrait, portraitCssClass); } }