/**
* <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>
* BPS Bildungsportal Sachsen GmbH, http://www.bps-system.de
* <p>
*/
package de.bps.olat.modules.cl;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.olat.basesecurity.BaseSecurity;
import org.olat.basesecurity.BaseSecurityManager;
import org.olat.basesecurity.BaseSecurityModule;
import org.olat.basesecurity.GroupRoles;
import org.olat.core.CoreSpringFactory;
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.FormLink;
import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.components.form.flexible.impl.FormEvent;
import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.components.link.LinkFactory;
import org.olat.core.gui.components.panel.Panel;
import org.olat.core.gui.components.table.ColumnDescriptor;
import org.olat.core.gui.components.table.DefaultColumnDescriptor;
import org.olat.core.gui.components.table.StaticColumnDescriptor;
import org.olat.core.gui.components.table.Table;
import org.olat.core.gui.components.table.TableController;
import org.olat.core.gui.components.table.TableEvent;
import org.olat.core.gui.components.table.TableGuiConfiguration;
import org.olat.core.gui.components.table.TableMultiSelectEvent;
import org.olat.core.gui.components.velocity.VelocityContainer;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
import org.olat.core.gui.media.ExcelMediaResource;
import org.olat.core.gui.render.StringOutput;
import org.olat.core.id.Identity;
import org.olat.core.id.UserConstants;
import org.olat.core.util.StringHelper;
import org.olat.core.util.Util;
import org.olat.course.ICourse;
import org.olat.course.groupsandrights.CourseGroupManager;
import org.olat.course.groupsandrights.CourseRights;
import org.olat.group.BusinessGroup;
import org.olat.group.BusinessGroupService;
import org.olat.user.UserInfoMainController;
import org.olat.user.UserManager;
import org.olat.user.propertyhandlers.UserPropertyHandler;
/**
* Description:<br>
* Display table with checkpoints of the checklist and the choice
* for all identities. Table data can be filtered by learning groups.
*
* <P>
* Initial Date: 22.07.2009 <br>
* @author bja <bja@bps-system.de>
*/
public class ChecklistManageCheckpointsController extends BasicController {
protected final static String EDIT_ACTION = "cl.edit.identity";
protected final static String DETAILS_ACTION = "cl.user.details";
protected static final String USER_PROPS_ID = ChecklistManageCheckpointsController.class.getCanonicalName();
private Identity selectedIdentity;
// GUI
private TableController manageChecklistTable, editChecklistTable;
private CloseableModalController cmc;
private GroupChoiceForm groupForm;
private Panel panel;
private Link closeManageButton, visitingCardButton;
// data
private Checklist checklist;
private ICourse course;
private ChecklistManageTableDataModel manageTableData;
private ChecklistRunTableDataModel editTableData;
private List<BusinessGroup> lstGroups;
private List<Identity> allIdentities, notInGroupIdentities;
private CourseGroupManager cgm;
private final UserManager userManager;
private final BaseSecurity securityManager;
private final BaseSecurityModule securityModule;
private final BusinessGroupService businessGroupService;
private CloseableModalController cmcUserInfo;
private UserInfoMainController uimc;
private final boolean readOnly;
protected ChecklistManageCheckpointsController(UserRequest ureq, WindowControl wControl, Checklist checklist, ICourse course, boolean readOnly) {
super(ureq, wControl, Util.createPackageTranslator(UserPropertyHandler.class, ureq.getLocale()));
this.checklist = checklist;
this.course = course;
this.allIdentities = new ArrayList<Identity>();
this.notInGroupIdentities = new ArrayList<Identity>();
this.lstGroups = new ArrayList<BusinessGroup>();
this.readOnly = readOnly;
securityManager = BaseSecurityManager.getInstance();
userManager = CoreSpringFactory.getImpl(UserManager.class);
securityModule = CoreSpringFactory.getImpl(BaseSecurityModule.class);
businessGroupService = CoreSpringFactory.getImpl(BusinessGroupService.class);
loadData();
cgm = course.getCourseEnvironment().getCourseGroupManager();
Identity identity = ureq.getIdentity();
boolean isAdmin = ureq.getUserSession().getRoles().isOLATAdmin() || cgm.isIdentityCourseAdministrator(identity);
if(isAdmin) {
// collect all identities with results
Set<Identity> identitiesWithResult = new HashSet<>();
for( Checkpoint checkpoint : this.checklist.getCheckpoints() ) {
for( CheckpointResult result : checkpoint.getResults() ) {
identitiesWithResult.add(securityManager.loadIdentityByKey(result.getIdentityId()));
}
}
// collect all identities in learning groups
Set<Identity> identitiesInGroups = new HashSet<>();
identitiesInGroups.addAll(cgm.getParticipantsFromBusinessGroups());
//fxdiff VCRP-1,2: access control of resources
identitiesInGroups.addAll(cgm.getParticipants());
// all identities with result and/or in learning groups
Set<Identity> identitiesAll = new HashSet<Identity>();
identitiesAll.addAll(identitiesInGroups);
identitiesAll.addAll(identitiesWithResult);
allIdentities.addAll(identitiesAll);
// collect all identities not in any learning group
Set<Identity> identitiesNotInGroups = new HashSet<>();
identitiesNotInGroups.addAll(identitiesAll);
identitiesNotInGroups.removeAll(identitiesInGroups);
notInGroupIdentities.addAll(identitiesNotInGroups);
// collect all learning groups
lstGroups.addAll(cgm.getAllBusinessGroups());
} else if(cgm.hasRight(identity, CourseRights.RIGHT_GROUPMANAGEMENT)) {
// collect all identities in learning groups
Set<Identity> identitiesInGroups = new HashSet<>();
identitiesInGroups.addAll(cgm.getParticipantsFromBusinessGroups());
//fxdiff VCRP-1,2: access control of resources
identitiesInGroups.addAll(cgm.getParticipants());
allIdentities.addAll(identitiesInGroups);
// collect all learning groups
lstGroups.addAll(cgm.getAllBusinessGroups());
} else if(cgm.isIdentityCourseCoach(identity)) {
Set<Identity> identitiesInGroups = new HashSet<>();
for( BusinessGroup group : cgm.getAllBusinessGroups() ) {
if(businessGroupService.hasRoles(identity, group, GroupRoles.coach.name())) {
lstGroups.add(group);
identitiesInGroups.addAll(businessGroupService.getMembers(group, GroupRoles.participant.name()));
}
}
allIdentities.addAll(identitiesInGroups);
}
displayChecklist(ureq, isAdmin);
}
private void displayChecklist(UserRequest ureq, boolean isAdmin) {
// add title
VelocityContainer displayChecklistVC = createVelocityContainer("manage");
String listTitle = checklist.getTitle() == null ? "" : checklist.getTitle();
displayChecklistVC.contextPut("checklistTitle", listTitle);
// group choice
removeAsListenerAndDispose(groupForm);
groupForm = new GroupChoiceForm(ureq, getWindowControl(), lstGroups, isAdmin);
listenTo(groupForm);
displayChecklistVC.put("groupForm", groupForm.getInitialComponent());
// the table
panel = new Panel("manageTable");
initManageTable(ureq);
displayChecklistVC.put("manageTable", panel);
// save and close
closeManageButton = LinkFactory.createButton("cl.close", displayChecklistVC, this);
putInitialPanel(displayChecklistVC);
}
private void initManageTable(UserRequest ureq) {
// reload data
loadData();
// load participants
List<Identity> lstIdents = new ArrayList<Identity>();
if(groupForm.getSelection().equals(GroupChoiceForm.CHOICE_ALL)) {
lstIdents.addAll(allIdentities);
} else if(groupForm.getSelection().equals(GroupChoiceForm.CHOICE_OTHERS)) {
lstIdents.addAll(notInGroupIdentities);
} else if(StringHelper.isLong(groupForm.getSelection())) {
Long groupKey = new Long(groupForm.getSelection());
BusinessGroup group = businessGroupService.loadBusinessGroup(groupKey);
lstIdents.addAll(businessGroupService.getMembers(group, GroupRoles.participant.name()));
}
boolean isAdministrativeUser = securityModule.isUserAllowedAdminProps(ureq.getUserSession().getRoles());
List<UserPropertyHandler> userPropertyHandlers = userManager.getUserPropertyHandlersFor(USER_PROPS_ID, isAdministrativeUser);
// prepare table for run view
TableGuiConfiguration tableConfig = new TableGuiConfiguration();
tableConfig.setTableEmptyMessage(translate("cl.table.empty"));
tableConfig.setDownloadOffered(true);
tableConfig.setPreferencesOffered(true, "ExtendedManageTable");
removeAsListenerAndDispose(manageChecklistTable);
manageChecklistTable = new TableController(tableConfig, ureq, getWindowControl(), getTranslator());
listenTo(manageChecklistTable);
int cols = 0;
if(isAdministrativeUser) {
manageChecklistTable.addColumnDescriptor(new DefaultColumnDescriptor("username", 1000, null, getLocale()));
cols++;
}
int i=0;
for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) {
if (userPropertyHandler == null) continue;
boolean visible = UserManager.getInstance().isMandatoryUserProperty(USER_PROPS_ID , userPropertyHandler);
manageChecklistTable.addColumnDescriptor(visible, userPropertyHandler.getColumnDescriptor(i++, DETAILS_ACTION, getLocale()));
cols++;
}
int j = 500;
List<Checkpoint> checkpointList = checklist.getCheckpointsSorted(ChecklistUIFactory.comparatorTitleAsc);
for( Checkpoint checkpoint : checkpointList ) {
String pointTitle = checkpoint.getTitle() == null ? "" : checkpoint.getTitle();
manageChecklistTable.addColumnDescriptor(new ChecklistMultiSelectColumnDescriptor(pointTitle, j++));
cols++;
}
if(!readOnly) {
manageChecklistTable.addColumnDescriptor(new StaticColumnDescriptor(EDIT_ACTION, "cl.edit.title", translate(EDIT_ACTION)));
cols++;
}
manageChecklistTable.setMultiSelect(false);
manageTableData = new ChecklistManageTableDataModel(checkpointList, lstIdents, userPropertyHandlers, cols);
manageChecklistTable.setTableDataModel(manageTableData);
panel.setContent(manageChecklistTable.getInitialComponent());
}
private void initEditTable(UserRequest ureq, Identity identity) {
List<Checkpoint> checkpoints = checklist.getCheckpoints();
editTableData = new ChecklistRunTableDataModel(checkpoints, getTranslator());
TableGuiConfiguration tableConfig = new TableGuiConfiguration();
tableConfig.setTableEmptyMessage(translate("cl.table.empty"));
tableConfig.setDownloadOffered(true);
tableConfig.setPreferencesOffered(true, "ExtendedEditTable");
removeAsListenerAndDispose(editChecklistTable);
editChecklistTable = new TableController(tableConfig, ureq, getWindowControl(), getTranslator());
listenTo(editChecklistTable);
editChecklistTable.addColumnDescriptor(new DefaultColumnDescriptor("cl.table.title", 0, null, ureq.getLocale()));
editChecklistTable.addColumnDescriptor(new DefaultColumnDescriptor("cl.table.description", 1, null, ureq.getLocale()));
editChecklistTable.addColumnDescriptor(new DefaultColumnDescriptor("cl.table.mode", 2, null, ureq.getLocale()));
editChecklistTable.setMultiSelect(true);
editChecklistTable.addMultiSelectAction("cl.close", "close");
editChecklistTable.addMultiSelectAction("cl.save.close", "save");
editChecklistTable.setTableDataModel(editTableData);
for(int i = 0; i<checkpoints.size(); i++) {
Checkpoint checkpoint = editTableData.getObject(i);
boolean selected = checkpoint.getSelectionFor(identity).booleanValue();
editChecklistTable.setMultiSelectSelectedAt(i, selected);
}
}
private void loadData() {
checklist = ChecklistManager.getInstance().loadChecklist(checklist);
}
private void updateCheckpointsFor(Identity identity, BitSet selection) {
ChecklistManager manager = ChecklistManager.getInstance();
int size = checklist.getCheckpoints().size();
for(int i = 0; i < size; i++) {
Checkpoint checkpoint = checklist.getCheckpoints().get(i);
Boolean selected = checkpoint.getSelectionFor(identity);
if(selected.booleanValue() != selection.get(i)) {
checkpoint.setSelectionFor(identity, selection.get(i));
manager.updateCheckpoint(checkpoint);
}
}
}
private void downloadResults(UserRequest ureq) {
int cdcnt = manageTableData.getColumnCount();
int rcnt = manageTableData.getRowCount();
StringBuilder sb = new StringBuilder();
boolean isAdministrativeUser = securityModule.isUserAllowedAdminProps(ureq.getUserSession().getRoles());
List<UserPropertyHandler> userPropertyHandlers = userManager.getUserPropertyHandlersFor(USER_PROPS_ID, isAdministrativeUser);
// additional informations
sb.append(translate("cl.course.title")).append('\t').append(course.getCourseTitle());
sb.append('\n');
String listTitle = checklist.getTitle() == null ? "" : checklist.getTitle();
sb.append(translate("cl.title")).append('\t').append(listTitle);
sb.append('\n').append('\n');
// header
for (int c = 0; c < (cdcnt-1); c++) { // skip last column (action)
ColumnDescriptor cd = manageChecklistTable.getColumnDescriptor(c);
String headerKey = cd.getHeaderKey();
String headerVal = cd.translateHeaderKey() ? translate(headerKey) : headerKey;
sb.append('\t').append(headerVal);
}
sb.append('\n');
// checkpoint description
if(isAdministrativeUser) {
sb.append('\t');
}
for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) {
if (userPropertyHandler == null) continue;
sb.append('\t');
}
for (Checkpoint checkpoint : checklist.getCheckpoints()) {
sb.append('\t').append(checkpoint.getDescription());
}
sb.append('\n');
// data
for (int r = 0; r < rcnt; r++) {
for (int c = 0; c < (cdcnt-1); c++) { // skip last column (action)
ColumnDescriptor cd = manageChecklistTable.getColumnDescriptor(c);
StringOutput so = new StringOutput();
cd.renderValue(so, r, null);
String cellValue = so.toString();
cellValue = StringHelper.stripLineBreaks(cellValue);
sb.append('\t').append(cellValue);
}
sb.append('\n');
}
String res = sb.toString();
String charset = UserManager.getInstance().getUserCharset(ureq.getIdentity());
ExcelMediaResource emr = new ExcelMediaResource(res, charset);
ureq.getDispatchResult().setResultingMediaResource(emr);
}
/**
* @see org.olat.core.gui.control.DefaultController#doDispose()
*/
@Override
protected void doDispose() {
//
}
/**
* @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.components.Component, org.olat.core.gui.control.Event)
*/
@Override
protected void event(UserRequest ureq, Component source, Event event) {
if(source == closeManageButton) {
fireEvent(ureq, Event.DONE_EVENT);
} else if(source == visitingCardButton) {
openVisitingCard(ureq);
}
}
@Override
protected void event(UserRequest ureq, Controller source, Event event) {
if(source == manageChecklistTable) {
if(event.getCommand().equals(Table.COMMANDLINK_ROWACTION_CLICKED)) {
TableEvent tableEvent = (TableEvent)event;
Long identityKey = manageTableData.getParticipantKeyAt(tableEvent.getRowId());
selectedIdentity = securityManager.loadIdentityByKey(identityKey, false);
if(tableEvent.getActionId().equals(EDIT_ACTION)) {
initEditTable(ureq, selectedIdentity);
VelocityContainer vcManageUser = createVelocityContainer("manageUser");
vcManageUser.put("table", editChecklistTable.getInitialComponent());
String name = selectedIdentity.getUser().getProperty(UserConstants.FIRSTNAME, getLocale()) + " " + selectedIdentity.getUser().getProperty(UserConstants.LASTNAME, getLocale());
visitingCardButton = LinkFactory.createLink("cl.manage.user.visitingcard", vcManageUser, this);
visitingCardButton.setCustomDisplayText(name);
removeAsListenerAndDispose(cmc);
cmc = new CloseableModalController(getWindowControl(), translate("cl.close"), vcManageUser, true, translate("cl.edit.title"));
listenTo(cmc);
cmc.activate();
} else if(tableEvent.getActionId().equals(DETAILS_ACTION)) {
openVisitingCard(ureq);
}
}
} else if(source == editChecklistTable) {
if(event instanceof TableMultiSelectEvent) {
TableMultiSelectEvent tmse = (TableMultiSelectEvent)event;
if(tmse.getAction().equals("save")) {
BitSet selection = tmse.getSelection();
updateCheckpointsFor(selectedIdentity, selection);
initManageTable(ureq);
}
cmc.deactivate();
}
} else if(source == groupForm) {
if(event == Event.CHANGED_EVENT) {
initManageTable(ureq);
} else if(event.getCommand().equals(GroupChoiceForm.EXPORT_TABLE)) {
downloadResults(ureq);
}
}
}
private void openVisitingCard(UserRequest ureq) {
removeAsListenerAndDispose(uimc);
uimc = new UserInfoMainController(ureq, getWindowControl(), selectedIdentity, false, false);
listenTo(uimc);
removeAsListenerAndDispose(cmc);
cmcUserInfo = new CloseableModalController(getWindowControl(), translate("cl.close"), uimc.getInitialComponent());
listenTo(cmcUserInfo);
cmcUserInfo.activate();
}
}
class GroupChoiceForm extends FormBasicController {
protected final static String CHOICE_ALL = "cl.choice.all";
protected final static String CHOICE_OTHERS = "cl.choice.others";
protected final static String EXPORT_TABLE = "cl.export";
private List<BusinessGroup> lstGroups;
private SingleSelection groupChoice;
private FormLink exportButton;
private boolean isAdmin;
public GroupChoiceForm(UserRequest ureq, WindowControl wControl, List<BusinessGroup> lstGroups, boolean isAdmin) {
super(ureq, wControl);
this.lstGroups = lstGroups;
this.isAdmin = isAdmin;
initForm(this.flc, this, ureq);
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
FormLayoutContainer mainLayout = FormLayoutContainer.createHorizontalFormLayout("mainLayout", getTranslator());
formLayout.add(mainLayout);
int size = lstGroups.size();
String[] keys = new String[size+2];
String[] values = new String[size+2];
// all option
keys[0] = CHOICE_ALL;
values[0] = translate(CHOICE_ALL);
// others option
int count = 1;
if(isAdmin) {
keys[1] = CHOICE_OTHERS;
values[1] = translate(CHOICE_OTHERS);
count++;
}
// the groups
for(int i = 0; i < size; i++) {
keys[i+count] = lstGroups.get(i).getKey().toString();
values[i+count] = lstGroups.get(i).getName();
}
groupChoice = uifactory.addDropdownSingleselect("cl.choice.groups", "cl.choice.groups", mainLayout, keys, values, null);
groupChoice.addActionListener(FormEvent.ONCHANGE);
groupChoice.select(CHOICE_ALL, true);
exportButton = uifactory.addFormLink(EXPORT_TABLE, EXPORT_TABLE, null, mainLayout, Link.BUTTON);
}
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if(source == groupChoice) {
fireEvent(ureq, Event.CHANGED_EVENT);
} else if(source == exportButton) {
fireEvent(ureq, new Event(EXPORT_TABLE));
}
}
String getSelection() {
return groupChoice.getSelectedKey();
}
@Override
protected void doDispose() {
// nothing to do
}
@Override
protected void formOK(UserRequest ureq) {
// nothing to do
}
}