/** * <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.modules.assessment.ui; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.BaseSecurityModule; 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.FlexiTableFilter; 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.form.flexible.impl.elements.table.DefaultFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; 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.link.LinkFactory; import org.olat.core.gui.components.stack.BreadcrumbPanelAware; import org.olat.core.gui.components.stack.TooledStackedPanel; import org.olat.core.gui.components.stack.TooledStackedPanel.Align; 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.dtabs.Activateable2; import org.olat.core.id.Identity; import org.olat.core.id.context.ContextEntry; import org.olat.core.id.context.StateEntry; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.course.assessment.AssessmentModule; import org.olat.course.assessment.AssessmentToolManager; import org.olat.course.assessment.bulk.PassedCellRenderer; import org.olat.course.assessment.model.SearchAssessedIdentityParams; import org.olat.course.assessment.ui.tool.AssessedIdentityListProvider; import org.olat.course.assessment.ui.tool.AssessmentStatusCellRenderer; import org.olat.course.assessment.ui.tool.AssessmentToolConstants; import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupService; import org.olat.group.model.SearchBusinessGroupParams; import org.olat.modules.assessment.AssessmentEntry; import org.olat.modules.assessment.AssessmentToolOptions; import org.olat.modules.assessment.model.AssessmentEntryStatus; import org.olat.modules.assessment.ui.AssessedIdentityListTableModel.IdentityCourseElementCols; import org.olat.repository.RepositoryEntry; import org.olat.repository.handlers.RepositoryHandler; import org.olat.repository.handlers.RepositoryHandlerFactory; import org.olat.repository.ui.RepositoyUIFactory; import org.olat.user.UserManager; import org.olat.user.propertyhandlers.UserPropertyHandler; import org.springframework.beans.factory.annotation.Autowired; /** * * Initial date: 06.10.2015<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ public class AssessedIdentityListController extends FormBasicController implements Activateable2 { private final RepositoryEntry testEntry; private final AssessableResource element; private final boolean isAdministrativeUser; private SearchAssessedIdentityParams searchParams; private final List<UserPropertyHandler> userPropertyHandlers; private final AssessmentToolSecurityCallback assessmentCallback; private Link nextLink, previousLink; private FlexiTableElement tableEl; private final TooledStackedPanel stackPanel; private AssessedIdentityListTableModel usersTableModel; private List<Controller> toolsCtrl; private AssessedIdentityController currentIdentityCtrl; @Autowired private UserManager userManager; @Autowired private BaseSecurity securityManager; @Autowired private BaseSecurityModule securityModule; @Autowired private BusinessGroupService businessGroupService; @Autowired private AssessmentToolManager assessmentToolManager; @Autowired private RepositoryHandlerFactory repositoryHandlerFactory; public AssessedIdentityListController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel, RepositoryEntry testEntry, AssessableResource element, AssessmentToolSecurityCallback assessmentCallback) { super(ureq, wControl, "identity_element"); setTranslator(Util.createPackageTranslator(AssessmentModule.class, getLocale(), getTranslator())); setTranslator(userManager.getPropertyHandlerTranslator(getTranslator())); this.element = element; this.testEntry = testEntry; this.stackPanel = stackPanel; this.assessmentCallback = assessmentCallback; isAdministrativeUser = securityModule.isUserAllowedAdminProps(ureq.getUserSession().getRoles()); userPropertyHandlers = userManager.getUserPropertyHandlersFor(AssessmentToolConstants.usageIdentifyer, isAdministrativeUser); initForm(ureq); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { if(formLayout instanceof FormLayoutContainer) { FormLayoutContainer layoutCont = (FormLayoutContainer)formLayout; layoutCont.contextPut("title", testEntry.getDisplayname()); RepositoryHandler handler = repositoryHandlerFactory.getRepositoryHandler(testEntry); layoutCont.contextPut("cssClass", RepositoyUIFactory.getIconCssClass(handler.getSupportedType())); } //add the table FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); if(isAdministrativeUser) { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(IdentityCourseElementCols.username, "select")); } int colIndex = AssessmentToolConstants.USER_PROPS_OFFSET; for (int i = 0; i < userPropertyHandlers.size(); i++) { UserPropertyHandler userPropertyHandler = userPropertyHandlers.get(i); boolean visible = UserManager.getInstance().isMandatoryUserProperty(AssessmentToolConstants.usageIdentifyer , userPropertyHandler); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(visible, userPropertyHandler.i18nColumnDescriptorLabelKey(), colIndex, "select", true, "userProp-" + colIndex)); colIndex++; } if(element.hasAttemptsConfigured()) { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(IdentityCourseElementCols.attempts, "select")); } if(element.hasScoreConfigured()) { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(IdentityCourseElementCols.min, "select", new ScoreCellRenderer())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(IdentityCourseElementCols.max, "select", new ScoreCellRenderer())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(IdentityCourseElementCols.score, "select", new ScoreCellRenderer())); } if(element.hasPassedConfigured()) { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(IdentityCourseElementCols.passed, new PassedCellRenderer())); } columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(IdentityCourseElementCols.assessmentStatus, new AssessmentStatusCellRenderer(getLocale()))); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(IdentityCourseElementCols.initialLaunchDate, "select")); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(IdentityCourseElementCols.lastScoreUpdate, "select")); //columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(IdentityCourseElementCols.certificate, new DownloadCertificateCellRenderer())); usersTableModel = new AssessedIdentityListTableModel(columnsModel, element); usersTableModel.setCertificateMap(new ConcurrentHashMap<>()); tableEl = uifactory.addTableElement(getWindowControl(), "table", usersTableModel, 20, false, getTranslator(), formLayout); tableEl.setExportEnabled(true); tableEl.setSearchEnabled(new AssessedIdentityListProvider(getIdentity(), testEntry, testEntry, null, assessmentCallback), ureq.getUserSession()); List<FlexiTableFilter> filters = new ArrayList<>(); filters.add(new FlexiTableFilter(translate("filter.passed"), "passed")); filters.add(new FlexiTableFilter(translate("filter.failed"), "failed")); filters.add(new FlexiTableFilter(translate("filter.inProgress"), "inProgress")); filters.add(new FlexiTableFilter(translate("filter.inReview"), "inReview")); filters.add(new FlexiTableFilter(translate("filter.done"), "done")); tableEl.setFilters("", filters, false); if(assessmentCallback.canAssessBusinessGoupMembers()) { List<BusinessGroup> coachedGroups; if(assessmentCallback.isAdmin()) { SearchBusinessGroupParams params = new SearchBusinessGroupParams(); coachedGroups = businessGroupService.findBusinessGroups(params, testEntry, 0, -1); } else { coachedGroups = assessmentCallback.getCoachedGroups(); } if(coachedGroups.size() > 0) { List<FlexiTableFilter> groupFilters = new ArrayList<>(); for(BusinessGroup coachedGroup:coachedGroups) { String groupName = StringHelper.escapeHtml(coachedGroup.getName()); groupFilters.add(new FlexiTableFilter(groupName, coachedGroup.getKey().toString(), "o_icon o_icon_group")); } tableEl.setExtendedFilterButton(translate("filter.groups"), groupFilters); } } } public class AToolsOptions extends AssessmentToolOptions { @Override public List<Identity> getIdentities() { return assessmentToolManager.getAssessedIdentities(getIdentity(), searchParams); } } private void updateModel(UserRequest ureq, String searchString, List<FlexiTableFilter> filters, List<FlexiTableFilter> extendedFilters) { SearchAssessedIdentityParams params = new SearchAssessedIdentityParams(testEntry, null, testEntry, assessmentCallback); List<AssessmentEntryStatus> assessmentStatus = null; if(filters != null && filters.size() > 0) { assessmentStatus = new ArrayList<>(filters.size()); for(FlexiTableFilter filter:filters) { if("passed".equals(filter.getFilter())) { params.setPassed(true); } else if("failed".equals(filter.getFilter())) { params.setFailed(true); } else if(AssessmentEntryStatus.isValueOf(filter.getFilter())){ assessmentStatus.add(AssessmentEntryStatus.valueOf(filter.getFilter())); } } } params.setAssessmentStatus(assessmentStatus); List<Long> businessGroupKeys = null; if(extendedFilters != null && extendedFilters.size() > 0) { businessGroupKeys = new ArrayList<>(extendedFilters.size()); for(FlexiTableFilter extendedFilter:extendedFilters) { if(StringHelper.isLong(extendedFilter.getFilter())) { businessGroupKeys.add(Long.parseLong(extendedFilter.getFilter())); } } } params.setBusinessGroupKeys(businessGroupKeys); params.setSearchString(searchString); List<Identity> assessedIdentities = assessmentToolManager.getAssessedIdentities(getIdentity(), params); List<AssessmentEntry> assessmentEntries = assessmentToolManager.getAssessmentEntries(getIdentity(), params, null); Map<Long,AssessmentEntry> entryMap = new HashMap<>(); assessmentEntries.stream().filter((entry) -> entry.getIdentity() != null) .forEach((entry) -> entryMap.put(entry.getIdentity().getKey(), entry)); List<AssessedIdentityElementRow> rows = new ArrayList<>(assessedIdentities.size()); for(Identity assessedIdentity:assessedIdentities) { AssessmentEntry entry = entryMap.get(assessedIdentity.getKey()); rows.add(new AssessedIdentityElementRow(assessedIdentity, entry, userPropertyHandlers, getLocale())); } usersTableModel.setObjects(rows); if(filters != null && filters.size() > 0 && filters.get(0) != null) { usersTableModel.filter(Collections.singletonList(filters.get(0))); } tableEl.reloadData(); searchParams = params; List<String> toolCmpNames = new ArrayList<>(); AssessmentToolOptions asOptions = new AssessmentToolOptions(); asOptions.setAdmin(assessmentCallback.isAdmin()); asOptions.setIdentities(assessedIdentities); List<Controller> tools = element.createAssessmentTools(ureq, getWindowControl(), stackPanel, testEntry, asOptions); int count = 0; if(tools.size() > 0) { for(Controller tool:tools) { listenTo(tool); String toolCmpName = "ctrl_" + (count++); flc.put(toolCmpName, tool.getInitialComponent()); toolCmpNames.add(toolCmpName); if(tool instanceof BreadcrumbPanelAware) { ((BreadcrumbPanelAware)tool).setBreadcrumbPanel(stackPanel); } } } if(toolsCtrl != null) { for(Controller toolCtrl:toolsCtrl) { removeAsListenerAndDispose(toolCtrl); } } toolsCtrl = tools; flc.contextPut("toolCmpNames", toolCmpNames); } @Override protected void doDispose() { // } @Override public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { String filter = null; if(state instanceof AssessedIdentityListState) { AssessedIdentityListState listState = (AssessedIdentityListState)state; if(StringHelper.containsNonWhitespace(listState.getFilter())) { filter = listState.getFilter(); } } tableEl.setSelectedFilterKey(filter); updateModel(ureq, null, tableEl.getSelectedFilters(), null); if(entries != null && entries.size() > 0) { String resourceType = entries.get(0).getOLATResourceable().getResourceableTypeName(); if("Identity".equals(resourceType)) { Long identityKey = entries.get(0).getOLATResourceable().getResourceableId(); for(int i=usersTableModel.getRowCount(); i--> 0; ) { AssessedIdentityElementRow row = usersTableModel.getObject(i); if(row.getIdentityKey().equals(identityKey)) { doSelect(ureq, row); } } } } } @Override protected void formOK(UserRequest ureq) { // } @Override public void event(UserRequest ureq, Component source, Event event) { if(previousLink == source) { doPrevious(ureq); } else if(nextLink == source) { doNext(ureq); } super.event(ureq, source, event); } @Override public void event(UserRequest ureq, Controller source, Event event) { if(currentIdentityCtrl == source) { if(event == Event.CHANGED_EVENT) { updateModel(ureq, null, null, null); } else if(event == Event.DONE_EVENT) { updateModel(ureq, null, null, null); stackPanel.popController(currentIdentityCtrl); } else if(event == Event.CANCELLED_EVENT) { stackPanel.popController(currentIdentityCtrl); } } else if(toolsCtrl != null && toolsCtrl.contains(source)) { if(event == Event.CHANGED_EVENT) { updateModel(ureq, null, null, null); } } super.event(ureq, source, event); } @Override protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { if(tableEl == source) { if(event instanceof SelectionEvent) { SelectionEvent se = (SelectionEvent)event; String cmd = se.getCommand(); AssessedIdentityElementRow row = usersTableModel.getObject(se.getIndex()); if("select".equals(cmd)) { doSelect(ureq, row); } } else if(event instanceof FlexiTableSearchEvent) { FlexiTableSearchEvent ftse = (FlexiTableSearchEvent)event; updateModel(ureq, ftse.getSearch(), ftse.getFilters(), ftse.getExtendedFilters()); } } super.formInnerEvent(ureq, source, event); } private void doNext(UserRequest ureq) { stackPanel.popController(currentIdentityCtrl); Identity currentIdentity = currentIdentityCtrl.getAssessedIdentity(); int index = getIndexOf(currentIdentity); if(index >= 0) { int nextIndex = index + 1;//next if(nextIndex >= 0 && nextIndex < usersTableModel.getRowCount()) { doSelect(ureq, usersTableModel.getObject(nextIndex)); } else if(usersTableModel.getRowCount() > 0) { doSelect(ureq, usersTableModel.getObject(0)); } } } private void doPrevious(UserRequest ureq) { stackPanel.popController(currentIdentityCtrl); Identity currentIdentity = currentIdentityCtrl.getAssessedIdentity(); int index = getIndexOf(currentIdentity); if(index >= 0) { int previousIndex = index - 1;//next if(previousIndex >= 0 && previousIndex < usersTableModel.getRowCount()) { doSelect(ureq, usersTableModel.getObject(previousIndex)); } else if(usersTableModel.getRowCount() > 0) { doSelect(ureq, usersTableModel.getObject(usersTableModel.getRowCount() - 1)); } } } private int getIndexOf(Identity identity) { for(int i=usersTableModel.getRowCount(); i-->0; ) { Long rowIdentityKey = usersTableModel.getObject(i).getIdentityKey(); if(rowIdentityKey.equals(identity.getKey())) { return i; } } return -1; } private void doSelect(UserRequest ureq, AssessedIdentityElementRow row) { removeAsListenerAndDispose(currentIdentityCtrl); Identity assessedIdentity = securityManager.loadIdentityByKey(row.getIdentityKey()); String fullName = userManager.getUserDisplayName(assessedIdentity); currentIdentityCtrl = new AssessedIdentityRepositoryEntryController(ureq, getWindowControl(), stackPanel, testEntry, assessedIdentity, element); listenTo(currentIdentityCtrl); stackPanel.pushController(fullName, currentIdentityCtrl); previousLink = LinkFactory.createToolLink("previouselement","", this, "o_icon_previous_toolbar"); previousLink.setTitle(translate("command.previous")); stackPanel.addTool(previousLink, Align.rightEdge, false, "o_tool_previous"); nextLink = LinkFactory.createToolLink("nextelement","", this, "o_icon_next_toolbar"); nextLink.setTitle(translate("command.next")); stackPanel.addTool(nextLink, Align.rightEdge, false, "o_tool_next"); } }