/** * <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.info.portlet; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Locale; import org.olat.NewControllerFactory; import org.olat.commons.info.manager.InfoMessageFrontendManager; import org.olat.commons.info.model.InfoMessage; import org.olat.core.commons.services.notifications.NotificationsManager; import org.olat.core.commons.services.notifications.SubscriptionInfo; import org.olat.core.commons.services.notifications.model.SubscriptionListItem; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.Window; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; import org.olat.core.gui.components.table.BaseTableDataModelWithoutFilter; import org.olat.core.gui.components.table.ColumnDescriptor; import org.olat.core.gui.components.table.CustomCellRenderer; import org.olat.core.gui.components.table.CustomRenderColumnDescriptor; import org.olat.core.gui.components.table.TableController; import org.olat.core.gui.components.table.TableGuiConfiguration; import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.portal.AbstractPortletRunController; import org.olat.core.gui.control.generic.portal.PortletDefaultTableDataModel; import org.olat.core.gui.control.generic.portal.PortletEntry; import org.olat.core.gui.control.generic.portal.PortletToolSortingControllerImpl; import org.olat.core.gui.control.generic.portal.SortingCriteria; import org.olat.core.gui.render.Renderer; import org.olat.core.gui.render.StringOutput; import org.olat.core.gui.translator.Translator; import org.olat.core.id.context.BusinessControl; import org.olat.core.id.context.BusinessControlFactory; import org.olat.core.util.Formatter; import org.olat.core.util.StringHelper; import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.event.GenericEventListener; import org.olat.core.util.filter.FilterFactory; /** * * Description:<br> * Show the last five infos * * <P> * Initial Date: 27 juil. 2010 <br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ public class InfoMessagePortletRunController extends AbstractPortletRunController<InfoSubscriptionItem> implements GenericEventListener { private Link showAllLink; private TableController tableController; private VelocityContainer portletVC; private boolean newInfos = false; public InfoMessagePortletRunController(WindowControl wControl, UserRequest ureq, Translator trans, String portletName, int defaultMaxentries) { super(wControl, ureq, trans, portletName, defaultMaxentries); portletVC = createVelocityContainer("infosPortlet"); showAllLink = LinkFactory.createLink("portlet.showall", portletVC, this); showAllLink.setIconRightCSS("o_icon o_icon_start"); TableGuiConfiguration tableConfig = new TableGuiConfiguration(); tableConfig.setTableEmptyMessage(translate("portlet.no_messages")); tableConfig.setDisplayTableHeader(false); tableConfig.setCustomCssClass("o_portlet_table"); tableConfig.setDisplayRowCount(false); tableConfig.setPageingEnabled(false); tableConfig.setDownloadOffered(false); tableConfig.setSortingEnabled(false); removeAsListenerAndDispose(tableController); tableController = new TableController(tableConfig, ureq, getWindowControl(), getTranslator()); tableController.addColumnDescriptor(new CustomRenderColumnDescriptor("peekview.title", 0, null, ureq.getLocale(), ColumnDescriptor.ALIGNMENT_LEFT, new InfoNodeRenderer())); listenTo(tableController); sortingTermsList.add(SortingCriteria.DATE_SORTING); sortingCriteria = getPersistentSortingConfiguration(ureq); sortingCriteria.setSortingTerm(SortingCriteria.DATE_SORTING); reloadModel(sortingCriteria); portletVC.put("table", tableController.getInitialComponent()); CoordinatorManager.getInstance().getCoordinator().getEventBus().registerFor(this, getIdentity(), InfoMessageFrontendManager.oresFrontend); putInitialPanel(portletVC); getWindowControl().getWindowBackOffice().addCycleListener(this); } @Override protected SortingCriteria createDefaultSortingCriteria() { SortingCriteria sortingCriteria = new SortingCriteria(sortingTermsList, getDefaultMaxEntries()); sortingCriteria.setAscending(false); return sortingCriteria; } @Override public synchronized void doDispose() { getWindowControl().getWindowBackOffice().removeCycleListener(this); CoordinatorManager.getInstance().getCoordinator().getEventBus().deregisterFor(this, InfoMessageFrontendManager.oresFrontend); super.doDispose(); } @Override public void event(Event event) { if("new_info_message".equals(event.getCommand())) { newInfos = true; } else if (event == Window.BEFORE_INLINE_RENDERING) { if(newInfos) { reloadModel(sortingCriteria); newInfos = false; } } } @Override protected Comparator<InfoSubscriptionItem> getComparator(SortingCriteria criteria) { return new InfoPortletEntryComparator(criteria); } /** * * @param items * @return */ private List<PortletEntry<InfoSubscriptionItem>> convertToPortletEntryList(List<InfoSubscriptionItem> infos) { List<PortletEntry<InfoSubscriptionItem>> convertedList = new ArrayList<PortletEntry<InfoSubscriptionItem>>(); long i = 0; for(InfoSubscriptionItem info:infos) { convertedList.add(new InfoPortletEntry(i++, info)); } return convertedList; } @Override protected void reloadModel(SortingCriteria criteria) { List<SubscriptionInfo> infos = NotificationsManager.getInstance().getSubscriptionInfos(getIdentity(), "InfoMessage"); List<InfoSubscriptionItem> items = new ArrayList<InfoSubscriptionItem>(); for(SubscriptionInfo info:infos) { for(SubscriptionListItem item:info.getSubscriptionListItems()) { items.add(new InfoSubscriptionItem(info, item)); } } items = getSortedList(items, criteria); List<PortletEntry<InfoSubscriptionItem>> entries = convertToPortletEntryList(items); InfosTableModel model = new InfosTableModel(entries); tableController.setTableDataModel(model); } @Override protected void reloadModel(List<PortletEntry<InfoSubscriptionItem>> sortedItems) { InfosTableModel model = new InfosTableModel(sortedItems); tableController.setTableDataModel(model); } protected PortletToolSortingControllerImpl<InfoSubscriptionItem> createSortingTool(UserRequest ureq, WindowControl wControl) { if(portletToolsController==null) { final List<PortletEntry<InfoSubscriptionItem>> empty = Collections.<PortletEntry<InfoSubscriptionItem>>emptyList(); final PortletDefaultTableDataModel<InfoSubscriptionItem> defaultModel = new PortletDefaultTableDataModel<InfoSubscriptionItem>(empty, 2) { @Override public Object getValueAt(int row, int col) { return null; } }; portletToolsController = new PortletToolSortingControllerImpl<InfoSubscriptionItem>(ureq, wControl, getTranslator(), sortingCriteria, defaultModel, empty); portletToolsController.setConfigManualSorting(false); portletToolsController.setConfigAutoSorting(true); portletToolsController.addControllerListener(this); } return portletToolsController; } @Override protected void event(UserRequest ureq, Component source, Event event) { if(source == showAllLink) { Calendar cal = Calendar.getInstance(); cal.setTime(new Date()); cal.add(Calendar.MONTH, -1); // fxdiff activate homes tab in top navigation and activate the correct // menu item String resourceUrl = "[HomeSite:" + ureq.getIdentity().getKey() + "][notifications:0][type=" + InfoMessage.class.getSimpleName() + ":0]" + BusinessControlFactory.getInstance().getContextEntryStringForDate(cal.getTime()); BusinessControl bc = BusinessControlFactory.getInstance().createFromString(resourceUrl); WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(bc, getWindowControl()); NewControllerFactory.getInstance().launch(ureq, bwControl); } } public class InfosTableModel extends BaseTableDataModelWithoutFilter<PortletEntry<InfoSubscriptionItem>> { private final List<PortletEntry<InfoSubscriptionItem>> infos; public InfosTableModel(List<PortletEntry<InfoSubscriptionItem>> infos) { this.infos = infos; } @Override public int getColumnCount() { return 1; } @Override public int getRowCount() { return infos.size(); } @Override public Object getValueAt(int row, int col) { InfoPortletEntry entry = (InfoPortletEntry)infos.get(row); switch(col) { case 0: return entry.getValue(); default: return entry; } } } public class InfoNodeRenderer implements CustomCellRenderer { @Override public void render(StringOutput sb, Renderer renderer, Object val, Locale locale, int alignment, String action) { if(val instanceof InfoSubscriptionItem) { InfoSubscriptionItem isi = (InfoSubscriptionItem)val; SubscriptionListItem item = isi.getItem(); SubscriptionInfo info = isi.getInfo(); //title String title = info.getTitle(SubscriptionInfo.MIME_PLAIN); title = StringHelper.escapeHtml(title); int key = info.hashCode(); StringBuilder tipSb = null; String tip = item.getDescriptionTooltip(); boolean tooltip = StringHelper.containsNonWhitespace(tip); if(tooltip) { tipSb = new StringBuilder(); if(StringHelper.isHtml(tip)) { tip = FilterFactory.getHtmlTagAndDescapingFilter().filter(tip); } tip = Formatter.escWithBR(Formatter.truncate(tip, 256)).toString(); tipSb.append("<b>").append(title).append(":</b>").append("<br/>").append(tip); sb.append("<span id='o_sel_info_msg_title_").append(key).append("'>"); } else { sb.append("<span>"); } sb.append(Formatter.truncate(title, 30)).append("</span> "); //link String itemDesc = StringHelper.escapeHtml(item.getDescription()); String infoTitle = Formatter.truncate(itemDesc, 30); sb.append("<a id='o_sel_info_msg_link_").append(key).append("' href=\"").append(item.getLink()).append("\" class=\"o_portlet_infomessage_link\""); sb.append(">") .append(infoTitle) .append("</a>"); if(tooltip) { sb.append("<div id='o_sel_info_tooltip_").append(key).append("' style='display:none'>").append(tipSb.toString()).append("</div>"); sb.append("<script type='text/javascript'>/* <![CDATA[ */") .append("jQuery(function() {") .append(" jQuery('#o_sel_info_msg_title_").append(key).append(",#o_sel_info_msg_link_").append(key).append("').tooltip({") .append(" html: true,") .append(" title: function(){ return jQuery('#o_sel_info_tooltip_").append(key).append("').html(); }") .append(" });") .append("});") .append("/* ]]> */</script>"); } } else { sb.append("-"); } } } }