package de.flower.rmt.ui.panel.activityfeed; import de.flower.common.ui.ajax.event.AjaxEventListener; import de.flower.common.ui.ajax.markup.html.AjaxLink; import de.flower.common.ui.ajax.markup.repeater.AjaxAppendingRefreshingView; import de.flower.common.ui.panel.BasePanel; import de.flower.rmt.model.db.entity.Activity; import de.flower.rmt.model.db.entity.Invitation; import de.flower.rmt.model.db.entity.event.Event; import de.flower.rmt.service.IActivityManager; import de.flower.rmt.ui.model.ActivityModel; import de.flower.rmt.ui.panel.activityfeed.renderer.ActivityMessageRenderer; import de.flower.rmt.util.Dates; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.markup.repeater.util.ModelIteratorAdapter; import org.apache.wicket.model.IModel; import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.spring.injection.annot.SpringBean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.List; /** * Panel displays activity feed. * * @author flowerrrr */ public class ActivityFeedPanel extends BasePanel { private final static Logger log = LoggerFactory.getLogger(ActivityFeedPanel.class); @SpringBean private IActivityManager activityManager; private int currentPage = 0; public ActivityFeedPanel() { super(); add(new AjaxEventListener(Invitation.class, Event.class)); WebMarkupContainer listContainer = new WebMarkupContainer("listContainer"); final AjaxAppendingRefreshingView<Activity> list = new AjaxAppendingRefreshingView<Activity>("list", getListModel(currentPage)) { // EntityListView<Activity> list = new EntityListView<Activity>("list", getListModel()) { @Override protected void populateItem(final Item<Activity> item) { item.add(new Label("date", getDateLabel(item.getModelObject().getDate()))); String message = renderMessage(item.getModelObject()); item.add(new Label("message", message).setEscapeModelStrings(false)); item.setVisible(message != null); } @Override protected Iterator<IModel<Activity>> getItemModels() { return transform((IModel<List<Activity>>) getDefaultModel()); } }; listContainer.add(list); add(listContainer); add(new AjaxLink.NoIndicatingAjaxLink<Void>("more") { @Override public void onClick(final AjaxRequestTarget target) { // load next N items Iterator<IModel<Activity>> itemModels = getNextPageItemModels(); if (itemModels.hasNext()) { list.appendNewItems(target, itemModels); } else { // no more items to load setVisible(false); target.add(this); } } }); } private Iterator<IModel<Activity>> transform(final IModel<List<Activity>> model) { return new ModelIteratorAdapter<Activity>(model.getObject().iterator()) { @Override protected IModel<Activity> model(final Activity object) { return new ActivityModel(object); } }; } private String renderMessage(final Activity activity) { String message = null; try { message = ActivityMessageRenderer.toString(activity.getMessage()); } catch (Exception e) { // changing the message types used to persist activities often causes errors when rendering old messages. // use warn level as it is not a core feature of the app. log.warn("Could not render [" + activity + "]: " + e.toString()); } return message; } private IModel<List<Activity>> getListModel(final int page) { return new LoadableDetachableModel<List<Activity>>() { @Override protected List<Activity> load() { // whenever implementation of message classes change we risk a deserialization error // when loading those messages. try { return activityManager.findLastN(page, 10); } catch (Exception e) { log.error("Could not load activities: " + e.getMessage(), e); return Collections.emptyList(); } } }; } private Iterator<IModel<Activity>> getNextPageItemModels() { currentPage++; return transform(getListModel(currentPage)); } private String getDateLabel(Date date) { return Dates.formatFacebook(date); } }