/** * <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.portfolio.ui; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; import org.olat.basesecurity.BaseSecurityModule; import org.olat.core.commons.persistence.SortKey; import org.olat.core.gui.UserRequest; 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.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.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.form.flexible.impl.elements.table.StaticFlexiCellRenderer; import org.olat.core.gui.components.stack.TooledStackedPanel; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.dtabs.Activateable2; import org.olat.core.id.OLATResourceable; import org.olat.core.id.UserConstants; import org.olat.core.id.context.BusinessControlFactory; 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.resource.OresHelper; import org.olat.group.ui.main.MemberListTableModel.Cols; import org.olat.modules.portfolio.Binder; import org.olat.modules.portfolio.BinderConfiguration; import org.olat.modules.portfolio.BinderSecurityCallback; import org.olat.modules.portfolio.BinderSecurityCallbackFactory; import org.olat.modules.portfolio.PortfolioService; import org.olat.modules.portfolio.model.AccessRights; import org.olat.modules.portfolio.model.AssessedBinder; import org.olat.modules.portfolio.model.AssessedBinderSection; import org.olat.modules.portfolio.model.SharedItemRow; import org.olat.modules.portfolio.ui.SharedItemsDataModel.ShareItemCols; import org.olat.modules.portfolio.ui.renderer.AssessmentEntryCellRenderer; import org.olat.modules.portfolio.ui.renderer.SelectSectionsCellRenderer; import org.olat.user.UserManager; import org.olat.user.propertyhandlers.UserPropertyHandler; import org.springframework.beans.factory.annotation.Autowired; /** * * Initial date: 15.06.2016<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ public class SharedItemsController extends FormBasicController implements Activateable2 { protected static final String USER_PROPS_ID = PortfolioHomeController.class.getCanonicalName(); public static final int USER_PROPS_OFFSET = 500; private FlexiTableElement tableEl; private SharedItemsDataModel model; private final TooledStackedPanel stackPanel; private final boolean isAdministrativeUser; private final List<UserPropertyHandler> userPropertyHandlers; private BinderController binderCtrl; @Autowired private UserManager userManager; @Autowired private PortfolioService portfolioService; @Autowired private BaseSecurityModule securityModule; public SharedItemsController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel) { super(ureq, wControl, "shared_with_me"); this.stackPanel = stackPanel; setTranslator(userManager.getPropertyHandlerTranslator(getTranslator())); isAdministrativeUser = securityModule.isUserAllowedAdminProps(ureq.getUserSession().getRoles()); userPropertyHandlers = userManager.getUserPropertyHandlersFor(USER_PROPS_ID, isAdministrativeUser); initForm(ureq); loadModel(null); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, ShareItemCols.binderKey, "select")); SortKey defaultSortKey = null; if(isAdministrativeUser) { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ShareItemCols.username)); defaultSortKey = new SortKey(Cols.username.name(), true); } // followed by the users fields int colPos = USER_PROPS_OFFSET; for (int i = 0; i < userPropertyHandlers.size(); i++) { UserPropertyHandler userPropertyHandler = userPropertyHandlers.get(i); String propName = userPropertyHandler.getName(); if(defaultSortKey == null && i == 0) { defaultSortKey = new SortKey(propName, true); } else if(UserConstants.LASTNAME.equals(propName) && !isAdministrativeUser) { defaultSortKey = new SortKey(propName, true); } boolean visible = userManager.isMandatoryUserProperty(USER_PROPS_ID , userPropertyHandler); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(visible, userPropertyHandler.i18nColumnDescriptorLabelKey(), colPos, true, propName)); colPos++; } columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ShareItemCols.binderName, "select")); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ShareItemCols.courseName, "select")); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ShareItemCols.lastModified)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ShareItemCols.recentLaunch)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ShareItemCols.openSections, "select")); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ShareItemCols.selectSections, new SelectSectionsCellRenderer())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ShareItemCols.grading, new AssessmentEntryCellRenderer(getTranslator()))); StaticFlexiCellRenderer selectRenderer = new StaticFlexiCellRenderer(translate("select"), "select"); selectRenderer.setIconRightCSS("o_icon-sw o_icon_start"); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, true, "select", -1, "select", false, null, FlexiColumnModel.ALIGNMENT_LEFT, selectRenderer)); model = new SharedItemsDataModel(columnsModel, getLocale()); tableEl = uifactory.addTableElement(getWindowControl(), "table", model, 20, false, getTranslator(), formLayout); tableEl.setSearchEnabled(true); tableEl.setCustomizeColumns(true); tableEl.setElementCssClass("o_binder_shared_items_listing"); tableEl.setEmtpyTableMessageKey("table.sEmptyTable"); tableEl.setPageSize(24); tableEl.setAndLoadPersistedPreferences(ureq, "shared-items"); FlexiTableSortOptions options = new FlexiTableSortOptions(); if(defaultSortKey != null) { options.setDefaultOrderBy(defaultSortKey); } tableEl.setSortSettings(options); } private void loadModel(String searchString) { List<AssessedBinder> assessedBinders = portfolioService.searchSharedBindersWith(getIdentity(), searchString); List<SharedItemRow> rows = new ArrayList<>(assessedBinders.size()); for(AssessedBinder assessedBinder:assessedBinders) { SharedItemRow row = new SharedItemRow(assessedBinder.getAssessedIdentity(), userPropertyHandlers, getLocale()); row.setBinderTitle(assessedBinder.getBinderTitle()); row.setBinderKey(assessedBinder.getBinderKey()); row.setLastModified(assessedBinder.getLastModified()); row.setEntryDisplayName(assessedBinder.getEntryDisplayname()); row.setAssessmentEntry(assessedBinder); row.setRecentLaunch(assessedBinder.getRecentLaunch()); List<AssessedBinderSection> sections = assessedBinder.getSections(); if(sections != null && sections.size() > 1) { Collections.sort(sections, new AssessedBinderSectionComparator()); } row.setSections(sections); row.setNumOfOpenSections(assessedBinder.getNumOfOpenSections()); rows.add(row); } model.setObjects(rows); tableEl.reset(); tableEl.reloadData(); } @Override protected void doDispose() { // } @Override public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { if(entries.isEmpty()) return; Long resId = entries.get(0).getOLATResourceable().getResourceableId(); String resName = entries.get(0).getOLATResourceable().getResourceableTypeName(); if("Binder".equalsIgnoreCase(resName)) { SharedItemRow activatedRow = null; List<SharedItemRow> rows = model.getObjects(); for(SharedItemRow row:rows) { if(row.getBinderKey().equals(resId)) { activatedRow = row; break; } } if(activatedRow != null) { Activateable2 activeateable = doSelectBinder(ureq, activatedRow); if(activeateable != null) { List<ContextEntry> subEntries = entries.subList(1, entries.size()); activeateable.activate(ureq, subEntries, entries.get(0).getTransientState()); } } } } @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(); SharedItemRow row = model.getObject(se.getIndex()); if("select".equals(cmd)) { Activateable2 activeateable = doSelectBinder(ureq, row); if(activeateable != null) { activeateable.activate(ureq, null, null); } } } else if(event instanceof FlexiTableSearchEvent) { FlexiTableSearchEvent se = (FlexiTableSearchEvent)event; loadModel(se.getSearch()); } else if("ONCLICK".equals(event.getCommand())) { String row = ureq.getParameter("select-section"); String expand = ureq.getParameter("expand-section"); if(StringHelper.isLong(row)) { doSelectSection(ureq); } else if(StringHelper.containsNonWhitespace(expand)) { doExpandSections(ureq); } } } super.formInnerEvent(ureq, source, event); } @Override protected void formOK(UserRequest ureq) { // } private void doExpandSections(UserRequest ureq) { try { String row = ureq.getParameter("expand-section"); int index = Integer.parseInt(row); SharedItemRow itemRow = model.getObject(index); if(itemRow != null) { itemRow.setExpandSections(!itemRow.isExpandSections()); } tableEl.getComponent().setDirty(true); } catch (NumberFormatException e) { logError("", e); } } private void doSelectSection(UserRequest ureq) { try { String row = ureq.getParameter("select-section"); int index = Integer.parseInt(row); SharedItemRow itemRow = model.getObject(index); if(itemRow != null) { String sectionParam = ureq.getParameter("section"); int sectionIndex = Integer.parseInt(sectionParam); AssessedBinderSection section = itemRow.getSections().get(sectionIndex); Activateable2 activeateable = doSelectBinder(ureq, itemRow); if(activeateable != null) { List<ContextEntry> entries = new ArrayList<>(2); entries.add(BusinessControlFactory.getInstance().createContextEntry(OresHelper.createOLATResourceableInstance("Entries", 0l))); entries.add(BusinessControlFactory.getInstance().createContextEntry(OresHelper.createOLATResourceableInstance("Section", section.getSectionKey()))); activeateable.activate(ureq, entries, null); } } } catch (Exception e) { logError("", e); } } private BinderController doSelectBinder(UserRequest ureq, SharedItemRow row) { Binder binder = portfolioService.getBinderByKey(row.getBinderKey()); if(binder == null) { showWarning("warning.portfolio.not.found"); return null; } else { removeAsListenerAndDispose(binderCtrl); portfolioService.updateBinderUserInformations(binder, getIdentity()); row.setRecentLaunch(new Date()); OLATResourceable binderOres = OresHelper.createOLATResourceableInstance("Binder", binder.getKey()); WindowControl swControl = addToHistory(ureq, binderOres, null); List<AccessRights> rights = portfolioService.getAccessRights(binder, getIdentity()); BinderSecurityCallback secCallback = BinderSecurityCallbackFactory.getCallbackForCoach(binder, rights); BinderConfiguration config = BinderConfiguration.createConfig(binder); binderCtrl = new BinderController(ureq, swControl, stackPanel, secCallback, binder, config); String displayName = StringHelper.escapeHtml(binder.getTitle()); stackPanel.pushController(displayName, binderCtrl); return binderCtrl; } } private static class AssessedBinderSectionComparator implements Comparator<AssessedBinderSection> { @Override public int compare(AssessedBinderSection o1, AssessedBinderSection o2) { boolean ba = (o1 == null); boolean bb = (o2 == null); int c = ba ? (bb ? 0: -1) : (bb ? 1: 0); if(c == 0) { int p1 = o1.getPos(); int p2 = o2.getPos(); c = Integer.compare(p1, p2); } return c; } } }