// // 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.team.tabs; import com.bloatit.data.DaoUserContent; import com.bloatit.framework.exceptions.highlevel.ShallNotPassException; import com.bloatit.framework.utils.PageIterable; import com.bloatit.framework.utils.i18n.DateLocale.FormatStyle; import com.bloatit.framework.webprocessor.annotations.ParamContainer; import com.bloatit.framework.webprocessor.annotations.SubParamContainer; import com.bloatit.framework.webprocessor.components.HtmlDiv; import com.bloatit.framework.webprocessor.components.HtmlLink; import com.bloatit.framework.webprocessor.components.HtmlParagraph; import com.bloatit.framework.webprocessor.components.HtmlRenderer; import com.bloatit.framework.webprocessor.components.HtmlSpan; import com.bloatit.framework.webprocessor.components.HtmlTitleBlock; import com.bloatit.framework.webprocessor.components.PlaceHolderElement; import com.bloatit.framework.webprocessor.components.advanced.HtmlTabBlock.HtmlTab; import com.bloatit.framework.webprocessor.components.meta.HtmlBranch; 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.model.Bug; import com.bloatit.model.Comment; import com.bloatit.model.Comment.ParentType; import com.bloatit.model.Contribution; import com.bloatit.model.Feature; import com.bloatit.model.FileMetadata; import com.bloatit.model.Kudos; import com.bloatit.model.Member; import com.bloatit.model.Offer; import com.bloatit.model.Release; import com.bloatit.model.Team; import com.bloatit.model.Translation; import com.bloatit.model.UserContent; import com.bloatit.model.UserContentInterface; import com.bloatit.model.right.UnauthorizedOperationException; import com.bloatit.web.components.HtmlPagedList; import com.bloatit.web.components.history.HistoryVisitor; import com.bloatit.web.linkable.features.FeaturesTools; import com.bloatit.web.linkable.master.HtmlDefineParagraph; import com.bloatit.web.url.BugPageUrl; import com.bloatit.web.url.FileResourceUrl; import com.bloatit.web.url.MemberPageUrl; import com.bloatit.web.url.TeamPageUrl; @ParamContainer(value = "historyTab", isComponent = true) public class HistoryTab extends HtmlTab { private final Team team; private final TeamPageUrl url; @SuppressWarnings("unused") @SubParamContainer private HtmlPagedList<UserContent<? extends DaoUserContent>> pagedHistory; public HistoryTab(final Team team, final String title, final String tabKey, final TeamPageUrl url) { super(title, tabKey); this.team = team; this.url = url; } @Override public HtmlNode generateBody() { final HtmlDiv master = new HtmlDiv("tab_pane"); // Displaying list of user recent history final HtmlTitleBlock recent = new HtmlTitleBlock(Context.tr("Recent history"), 1); master.add(recent); final HtmlDiv recentHistory = new HtmlDiv("recent_history"); recent.add(recentHistory); final PageIterable<UserContent<? extends DaoUserContent>> history = team.getHistory(); if (history.size() == 0) { recent.add(new HtmlParagraph(Context.tr("No recent history"))); } final TeamPageUrl clonedUrl = url.clone(); HtmlPagedList<UserContent<? extends DaoUserContent>> feed; feed = new HtmlPagedList<UserContent<? extends DaoUserContent>>(new HistoryRenderer(), history, clonedUrl, clonedUrl.getHistoryUrl() .getPagedHistoryUrl()); recentHistory.add(feed); return master; } /** * Paged renderer for the history feed */ private static final class HistoryRenderer implements HtmlRenderer<UserContent<? extends DaoUserContent>> { public HistoryRenderer() { super(); } @Override public HtmlNode generate(final UserContent<? extends DaoUserContent> content) { return content.accept(new HistoryVisitor() { @Override public HtmlElement visit(final Translation model) { return new HtmlParagraph("translation"); } @Override public HtmlElement visit(final Kudos model) { return new HtmlParagraph("kudos"); } @Override public HtmlElement visit(final Contribution model) { final HtmlSpan contribSpan = new HtmlSpan("feed_contribution"); final HtmlMixedText mixedText = new HtmlMixedText(Context.tr("<0::Contributed>"), contribSpan); return generateFeatureFeedStructure(mixedText, model.getFeature(), model); } @Override public HtmlElement visit(final Feature model) { final HtmlSpan featureSpan = new HtmlSpan("feed_feature"); final HtmlMixedText mixedText = new HtmlMixedText(Context.tr("Requested <0::feature>"), featureSpan); return generateFeatureFeedStructure(mixedText, model, model); } @Override public HtmlElement visit(final Offer model) { final HtmlSpan offerSpan = new HtmlSpan("feed_offer"); final HtmlMixedText mixedText = new HtmlMixedText(Context.tr("Made an <0::offer>"), offerSpan); return generateFeatureFeedStructure(mixedText, model.getFeature(), model); } @Override public HtmlElement visit(final Release model) { final HtmlSpan releaseSpan = new HtmlSpan("feed_release"); final HtmlMixedText mixedText = new HtmlMixedText(Context.tr("Made a <0::release>"), releaseSpan); return generateFeatureFeedStructure(mixedText, model.getFeature(), model); } @Override public HtmlElement visit(final Bug model) { final HtmlSpan bugSpan = new HtmlSpan("feed_bug"); final HtmlLink bugUrl = new BugPageUrl(model).getHtmlLink(model.getTitle()); bugUrl.setCssClass("bug_link"); final HtmlMixedText mixedText = new HtmlMixedText(Context.tr("Reported <0::bug> (<1::>)"), bugSpan, bugUrl); return generateFeatureFeedStructure(mixedText, model.getFeature(), model); } @Override public HtmlElement visit(final FileMetadata model) { final HtmlSpan fileSpan = new HtmlSpan("feed_file"); final HtmlMixedText mixedText = new HtmlMixedText(Context.tr("Uploaded a <0::file>"), fileSpan); final HtmlLink htmlLink = new FileResourceUrl(model).getHtmlLink(model.getFileName()); final HtmlElement secondLine = generateFeedSecondLine(Context.tr("File: "), htmlLink); return generateFeedStructure(mixedText, secondLine, model); } @Override public HtmlElement visit(Comment model) { final HtmlSpan commentSpan = new HtmlSpan("feed_comment"); HtmlMixedText mixedText; if (model.getParentType() == ParentType.COMMENT) { final Member commenter = model.getParentComment().getMember(); HtmlLink commenterUrl; commenterUrl = new MemberPageUrl(commenter).getHtmlLink(commenter.getDisplayName()); mixedText = new HtmlMixedText(Context.tr("Replied to a <0::comment> (from <1::>)"), commentSpan, commenterUrl); while (model.getParentType() == ParentType.COMMENT) { model = model.getParentComment(); } } else { mixedText = new HtmlMixedText(Context.tr("<0::Commented>"), commentSpan); } switch (model.getParentType()) { case BUG: final HtmlLink link = new BugPageUrl(model.getParentBug()).getHtmlLink(model.getParentBug().getTitle()); final HtmlElement secondLine = generateFeedSecondLine(Context.tr("Bug: "), link); return generateFeedStructure(mixedText, secondLine, model); case FEATURE: return generateFeatureFeedStructure(mixedText, model.getParentFeature(), model); case COMMENT: // Nothing to do here break; } return new PlaceHolderElement(); } }); } /** * Generates a second line of a feed * * @param item the String to display at the start of the second line * @param target the element to display after <code>item</code> * @return the element to add as a second line */ private HtmlElement generateFeedSecondLine(final String item, final HtmlElement target) { return new HtmlDefineParagraph(item, target); } /** * Generates a complete structure of a feed for elements that have a * feature on their second line * <p> * This is a convenience method for * {@link #generateFeedStructure(HtmlElement, HtmlElement, UserContentInterface)} * that avoids having to create the feature second line * </p> * * @param firstLine the element to show on the first line * @param feature the <code>feature</code> to display on the second line * @param content the UserContent that originates everything, so we can * get its creation date * @return the element to add in the feed */ private HtmlElement generateFeatureFeedStructure(final HtmlElement firstLine, final Feature feature, final UserContentInterface content) { final PlaceHolderElement ph = new PlaceHolderElement(); try { ph.add(generateFeedSecondLine(Context.tr("Feature: "), FeaturesTools.generateFeatureTitle(feature))); } catch (final UnauthorizedOperationException e) { throw new ShallNotPassException("Cannot access some feature information.", e); } return generateFeedStructure(firstLine, ph, content); } /** * Creates a complete feed item to add to the feed * * @param firstLine the first line of the feed item * @param secondLine the second line of the feed item * @param content the UserContent that originates everything, so we can * get its creation date * @return the element to add in the feed */ private HtmlElement generateFeedStructure(final HtmlElement firstLine, final HtmlElement secondLine, final UserContentInterface content) { final HtmlDiv master = new HtmlDiv("feed_item"); // Title master.add(new HtmlDiv("feed_item_title").add(firstLine)); final HtmlDiv historyDetail = new HtmlDiv("feed_content"); master.add(historyDetail); historyDetail.add(new HtmlDiv("feed_item_description").add(secondLine)); // Author final HtmlBranch authorBox = new HtmlDiv("feed_item_author"); historyDetail.add(authorBox); final MemberPageUrl to = new MemberPageUrl(content.getMember()); authorBox.add(new HtmlDefineParagraph(Context.tr("Author: "), to.getHtmlLink(content.getMember().getDisplayName()))); // Date final HtmlBranch dateBox = new HtmlDiv("feed_item_date"); historyDetail.add(dateBox); final String dateString = Context.tr("Date: {0}", Context.getLocalizator().getDate(content.getCreationDate()).toString(FormatStyle.LONG)); dateBox.addText(dateString); return master; } } }