// // Copyright (c) 2011 Linkeos. // // This file is part of Elveos.org. // Elveos.org is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the // Free Software Foundation, either version 3 of the License, or (at your // option) any later version. // // Elveos.org is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // You should have received a copy of the GNU General Public License along // with Elveos.org. If not, see http://www.gnu.org/licenses/. // package com.bloatit.web.linkable.activity; import java.text.SimpleDateFormat; import java.util.Date; import com.bloatit.data.DaoFeature.FeatureState; import com.bloatit.framework.utils.PageIterable; import com.bloatit.framework.utils.datetime.DateUtils; import com.bloatit.framework.webprocessor.components.HtmlDiv; import com.bloatit.framework.webprocessor.components.HtmlImage; import com.bloatit.framework.webprocessor.components.HtmlParagraph; import com.bloatit.framework.webprocessor.components.HtmlSpan; import com.bloatit.framework.webprocessor.components.HtmlTitle; import com.bloatit.framework.webprocessor.components.PlaceHolderElement; import com.bloatit.framework.webprocessor.components.meta.HtmlElement; import com.bloatit.framework.webprocessor.components.meta.HtmlMixedText; import com.bloatit.framework.webprocessor.components.meta.HtmlNode; import com.bloatit.framework.webprocessor.context.Context; import com.bloatit.mail.ActivityEventVisitor; import com.bloatit.mail.ActivityEventVisitor.BugEntries; import com.bloatit.mail.ActivityEventVisitor.DayAgreggator; import com.bloatit.mail.ActivityEventVisitor.Entries; import com.bloatit.mail.ActivityEventVisitor.FeatureEntries; import com.bloatit.mail.EventFeatureComponent; import com.bloatit.mail.HtmlEntry; import com.bloatit.model.Event; import com.bloatit.model.Image; import com.bloatit.model.Member; import com.bloatit.model.managers.EventManager; import com.bloatit.model.right.AuthToken; import com.bloatit.web.WebConfiguration; import com.bloatit.web.url.ActivityAtomFeedUrl; import com.bloatit.web.url.ActivityPageUrl; import com.bloatit.web.url.ChooseFeatureTypePageUrl; import com.bloatit.web.url.FeatureListPageUrl; import com.bloatit.web.url.ManageFollowPageUrl; import com.bloatit.web.url.ReadActivityActionUrl; /** * A simple renderer for teams that display only their name on one line, plus a * link to their page */ public class HtmlActivityBlock extends HtmlDiv { private static final int MIN_LEFT_RIGHT_DIFF = 50; private static final int MIN_DAY_HEIGHT = 70; private Date lastWatchedEvents; public HtmlActivityBlock(final Member member) { super("activity-block"); if (AuthToken.isAuthenticated()) { lastWatchedEvents = AuthToken.getMember().getLastWatchedEvents(); } else { lastWatchedEvents = DateUtils.dawnOfTime(); } if (AuthToken.isAuthenticated() && AuthToken.getMember().equals(member)) { final HtmlDiv menuBar = new HtmlDiv("menu_bar"); add(menuBar); { final HtmlDiv menuBarItemNewFeature = new HtmlDiv("menu_bar_item"); menuBar.add(menuBarItemNewFeature); { final HtmlDiv menuBarItemImage = new HtmlDiv("menu_bar_item_image"); menuBarItemNewFeature.add(menuBarItemImage); menuBarItemImage.add(new HtmlImage(new Image(WebConfiguration.getImgIdeaSmall()), Context.tr("Request a feature"))); final HtmlDiv menuBarItemLink = new HtmlDiv("menu_bar_item_link"); menuBarItemNewFeature.add(menuBarItemLink); menuBarItemLink.add(new ChooseFeatureTypePageUrl().getHtmlLink(Context.tr("Request a feature"))); } final HtmlDiv menuBarItemManageFollow = new HtmlDiv("menu_bar_item"); menuBar.add(menuBarItemManageFollow); { final HtmlDiv menuBarItemImage = new HtmlDiv("menu_bar_item_image"); menuBarItemManageFollow.add(menuBarItemImage); menuBarItemImage.add(new HtmlImage(new Image(WebConfiguration.getImgManageSmall()), Context.tr("Manage activity"))); final HtmlDiv menuBarItemLink = new HtmlDiv("menu_bar_item_link"); menuBarItemManageFollow.add(menuBarItemLink); menuBarItemLink.add(new ManageFollowPageUrl().getHtmlLink(Context.tr("Manage activity"))); } final HtmlDiv menuBarItemRSS = new HtmlDiv("menu_bar_item"); menuBar.add(menuBarItemRSS); { final HtmlDiv menuBarItemImage = new HtmlDiv("menu_bar_item_image"); menuBarItemRSS.add(menuBarItemImage); menuBarItemImage.add(new HtmlImage(new Image(WebConfiguration.getImgRssSmall()), Context.tr("My custom Rss feed"))); final HtmlDiv menuBarItemLink = new HtmlDiv("menu_bar_item_link"); menuBarItemRSS.add(menuBarItemLink); menuBarItemLink.add(new ActivityAtomFeedUrl(member).getHtmlLink(Context.tr("Rss feed"))); } final HtmlDiv menuBarItemSetAsRead = new HtmlDiv("menu_bar_right_item"); menuBar.add(menuBarItemSetAsRead); { menuBarItemSetAsRead.add(new ReadActivityActionUrl(Context.getSession().getShortKey()).getHtmlLink(Context.tr("set as read"))); } final HtmlDiv menuBarItemGlobalActivity = new HtmlDiv("menu_bar_right_item"); menuBar.add(menuBarItemGlobalActivity); { final ActivityPageUrl activityPageUrl = new ActivityPageUrl(); menuBarItemGlobalActivity.add(activityPageUrl.getHtmlLink(Context.tr("global activity"))); } } } else { if (AuthToken.isAuthenticated()) { final HtmlDiv menuBar = new HtmlDiv("menu_bar"); add(menuBar); { final HtmlDiv menuBarItemMyActivity = new HtmlDiv("menu_bar_right_item"); menuBar.add(menuBarItemMyActivity); { final ActivityPageUrl activityPageUrl = new ActivityPageUrl(); activityPageUrl.setMember(AuthToken.getMember()); menuBarItemMyActivity.add(activityPageUrl.getHtmlLink(Context.tr("my activity"))); } } } if (member == null) { add(new HtmlTitle(Context.tr("Global Elveos activity"), 1)); } else { add(new HtmlTitle(Context.tr("{0}''s activity", member.getDisplayName()), 1)); } } PageIterable<Event> events = (member == null ? EventManager.getAllEvents() : EventManager.getAllEventByMember(member)); events.setPageSize(100); if (events.size() == 0) { HtmlDiv alt = new HtmlDiv("alt_activity_block"); alt.add(new HtmlParagraph(Context.tr("Your activity page is empty because you are not following any content yet."))); alt.add(new HtmlParagraph().add(new HtmlMixedText(Context.tr("You can look for <0::feature requests you like>, and <1::follow> them !"), new FeatureListPageUrl().getHtmlLink(), new HtmlSpan("strong")))); alt.add(new HtmlParagraph().add(new HtmlMixedText(Context.tr("Or <0::create a new feature request>."), new ChooseFeatureTypePageUrl().getHtmlLink()))); add(alt); } else { { final HtmlDiv activityBlockTwoColumn = new HtmlDiv("activity-block-two-column"); add(activityBlockTwoColumn); final HtmlDiv leftColumn = new HtmlDiv("left_column"); activityBlockTwoColumn.add(leftColumn); final HtmlDiv timeColumn = new HtmlDiv("time_column"); final PlaceHolderElement daysPlaceHolder = new PlaceHolderElement(); activityBlockTwoColumn.add(timeColumn); { final HtmlDiv timeColumnHeader = new HtmlDiv("time_column_header"); timeColumn.add(timeColumnHeader); timeColumn.add(daysPlaceHolder); final HtmlDiv timeColumnFooter = new HtmlDiv("time_column_footer"); timeColumn.add(timeColumnFooter); } final HtmlDiv rightColumn = new HtmlDiv("right_column"); activityBlockTwoColumn.add(rightColumn); final ActivityEventVisitor visitor = new ActivityEventVisitor(Context.getLocalizator()); for (Event event : events) { event.getEvent().accept(visitor); } fillTimeLine(leftColumn, daysPlaceHolder, rightColumn, visitor, false); } final HtmlDiv activityBlockOneColumn = new HtmlDiv("activity-block-one-column"); add(activityBlockOneColumn); { final HtmlDiv timeColumn = new HtmlDiv("time_column"); final PlaceHolderElement daysPlaceHolder = new PlaceHolderElement(); activityBlockOneColumn.add(timeColumn); { final HtmlDiv timeColumnHeader = new HtmlDiv("time_column_header"); timeColumn.add(timeColumnHeader); timeColumn.add(daysPlaceHolder); final HtmlDiv timeColumnFooter = new HtmlDiv("time_column_footer"); timeColumn.add(timeColumnFooter); } final HtmlDiv rightColumn = new HtmlDiv("right_column"); activityBlockOneColumn.add(rightColumn); final ActivityEventVisitor visitor = new ActivityEventVisitor(Context.getLocalizator()); for (Event event : events) { event.getEvent().accept(visitor); } fillTimeLine(null, daysPlaceHolder, rightColumn, visitor, true); } } } private void fillTimeLine(final HtmlDiv leftColumn, final PlaceHolderElement daysPlaceHolder, final HtmlDiv rightColumn, final ActivityEventVisitor visitor, final boolean rightOnly) { final SimpleDateFormat dayFormat = new SimpleDateFormat("MMM d", Context.getLocalizator().getLocale()); // boolean insertToLeft = false; int leftOffset = 50; int rightOffset = 0; int leftStartOffset = -MIN_LEFT_RIGHT_DIFF; int rightStartOffset = 0; int dayOffset = 0; if (!rightOnly) { leftColumn.add(generateSpacer(leftOffset)); } for (final DayAgreggator day : visitor.getDays()) { int lastOffset = 0; HtmlElement element = null; // for (Entry<Feature, Entries> e : day.getFeatures().entrySet()) { for (final Entries<?> e : day.getEntries()) { if (e instanceof FeatureEntries) { FeatureEntries f = (FeatureEntries) e; if(f.getKey().getFeatureState() == FeatureState.DISCARDED) { continue; } EventFeatureComponent featureComponent = new EventFeatureComponent(f.getKey(), Context.getLocalizator(), true); for (HtmlEntry entry : e) { HtmlElement entryElement = entry.generateForWebSite(); featureComponent.add(entryElement); if (entry.getDate().after(lastWatchedEvents)) { entryElement.setCssClass("unseen-entry"); } } element = featureComponent; } else if (e instanceof BugEntries) { continue; // throw new NotImplementedException(); } final int blockHeight = 69 + 24 * e.size() + 30; element.addAttribute("style", "height: " + (blockHeight - 30) + "px;"); int offset; if (!rightOnly && leftOffset < rightOffset) { if (leftOffset < dayOffset) { leftColumn.add(generateSpacer(dayOffset - leftOffset)); leftOffset = dayOffset; } if (leftOffset - rightStartOffset < MIN_LEFT_RIGHT_DIFF) { final int space = MIN_LEFT_RIGHT_DIFF - (leftOffset - rightStartOffset); leftColumn.add(generateSpacer(space)); leftOffset += space; } leftColumn.add(element); offset = leftOffset; leftStartOffset = offset; leftOffset += blockHeight; } else { if (rightOffset < dayOffset) { rightColumn.add(generateSpacer(dayOffset - rightOffset)); rightOffset = dayOffset; } if (rightOffset - leftStartOffset < MIN_LEFT_RIGHT_DIFF) { final int space = MIN_LEFT_RIGHT_DIFF - (rightOffset - leftStartOffset); leftColumn.add(generateSpacer(space)); rightOffset += space; } rightColumn.add(element); offset = rightOffset; rightStartOffset = offset; rightOffset += blockHeight; } if (offset > lastOffset) { lastOffset = offset; } // insertToLeft = !insertToLeft; } int height; height = lastOffset - dayOffset + 70; if (height < MIN_DAY_HEIGHT) { height = MIN_DAY_HEIGHT; } dayOffset += height; daysPlaceHolder.add(generateDay(dayFormat.format(day.getDate().getTime()), height)); } } private HtmlNode generateDay(final String text, final int height) { final HtmlDiv dayBlock = new HtmlDiv("day"); dayBlock.addText(text); dayBlock.addAttribute("style", "height: " + height + "px;"); return dayBlock; } private HtmlNode generateSpacer(final int height) { final HtmlDiv dayBlock = new HtmlDiv("spacer"); dayBlock.addAttribute("style", "height: " + height + "px;"); return dayBlock; } }