/*
* Copyright (c) 2011 Lockheed Martin Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eurekastreams.web.client.ui.pages.discover;
import java.util.Date;
import org.eurekastreams.commons.formatting.DateFormatter;
import org.eurekastreams.server.domain.EntityType;
import org.eurekastreams.server.domain.Page;
import org.eurekastreams.server.domain.dto.StreamDTO;
import org.eurekastreams.server.search.modelview.DomainGroupModelView;
import org.eurekastreams.server.search.modelview.PersonModelView.Role;
import org.eurekastreams.web.client.history.CreateUrlRequest;
import org.eurekastreams.web.client.jsni.WidgetJSNIFacadeImpl;
import org.eurekastreams.web.client.model.BlockedSuggestionModel;
import org.eurekastreams.web.client.ui.Session;
import org.eurekastreams.web.client.ui.pages.master.CoreCss;
import org.eurekastreams.web.client.ui.pages.master.StaticResourceBundle;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
/**
* FlowPanel for the four simple lists of StreamDTOs on the Discover page.
*/
public class DiscoverListItemPanel extends Composite
{
/**
* The type subtext type to show under the name.
*/
public enum ListItemType
{
/**
* Mutual follower(s).
*/
MUTUAL_FOLLOWERS,
/**
* Daily viewer(s).
*/
DAILY_VIEWERS,
/**
* Follower(s).
*/
FOLLOWERS,
/**
* Formatted time ago.
*/
TIME_AGO
};
/** Binder for building UI. */
private static LocalUiBinder binder = GWT.create(LocalUiBinder.class);
/** JSNI. */
private static WidgetJSNIFacadeImpl jsniFacade = new WidgetJSNIFacadeImpl();
/**
* Local styles.
*/
interface LocalStyle extends CssResource
{
/** @return Button style. */
@ClassName("request-button")
String requestButton();
/** @return Button style. */
@ClassName("pending-button")
String pendingButton();
/** @return Apply to the follow panel to allow custom styling. */
@ClassName("follow-controls-panel")
String followControlsPanel();
/** @return Button style. */
@ClassName("follow-button")
String followButton();
/** @return Button style. */
@ClassName("unfollow-button")
String unfollowButton();
/** @return Button style. */
@ClassName("block-button")
String blockButton();
/** @return When multiple controls are in the follower controls panel. */
String multi();
}
/** Local styles. */
@UiField
LocalStyle style;
/** Global styles. */
@UiField(provided = true)
CoreCss coreCss;
/** Name link. */
@UiField
Hyperlink streamNameLink;
/** Displays info about stream. */
@UiField
Element streamInfoText;
/**
* Constructor.
*
* @param inStreamDTO
* the streamDTO to represent
* @param inListItemType
* list item type
*/
public DiscoverListItemPanel(final StreamDTO inStreamDTO, final ListItemType inListItemType)
{
this(inStreamDTO, inListItemType, false);
}
/**
* Constructor.
*
* @param inStreamDTO
* the streamDTO to represent
* @param inListItemType
* list item type
* @param showBlockSuggestion
* show block suggestion controls.
*/
public DiscoverListItemPanel(final StreamDTO inStreamDTO, final ListItemType inListItemType,
final boolean showBlockSuggestion)
{
coreCss = StaticResourceBundle.INSTANCE.coreCss();
HTMLPanel main = (HTMLPanel) binder.createAndBindUi(this);
initWidget(main);
// set text and link for name; assume group if not person
Page linkPage = (inStreamDTO.getEntityType() == EntityType.PERSON) ? Page.PEOPLE : Page.GROUPS;
String nameUrl = Session.getInstance().generateUrl(//
new CreateUrlRequest(linkPage, inStreamDTO.getUniqueId()));
streamNameLink.setTargetHistoryToken(nameUrl);
streamNameLink.setText(inStreamDTO.getDisplayName());
streamNameLink.setTitle(inStreamDTO.getDisplayName());
// set info text
switch (inListItemType)
{
case MUTUAL_FOLLOWERS:
if (inStreamDTO.getFollowersCount() == 1)
{
streamInfoText.setInnerText("1 Mutual Follower");
}
else
{
streamInfoText.setInnerText(Integer.toString(inStreamDTO.getFollowersCount()) + " Mutual Followers");
}
break;
case DAILY_VIEWERS:
if (inStreamDTO.getFollowersCount() == 1)
{
streamInfoText.setInnerText("1 Daily Viewer");
}
else
{
streamInfoText.setInnerText(Integer.toString(inStreamDTO.getFollowersCount()) + " Daily Viewers");
}
break;
case FOLLOWERS:
if (inStreamDTO.getFollowersCount() == 1)
{
streamInfoText.setInnerText("1 Follower");
}
else
{
streamInfoText.setInnerText(Integer.toString(inStreamDTO.getFollowersCount()) + " Followers");
}
break;
case TIME_AGO:
DateFormatter dateFormatter = new DateFormatter(new Date());
streamInfoText.setInnerText(dateFormatter.timeAgo(inStreamDTO.getDateAdded(), true));
break;
default:
break;
}
// add following controls if not the current person
if (inStreamDTO.getEntityType() != EntityType.PERSON
|| inStreamDTO.getEntityId() != Session.getInstance().getCurrentPerson().getEntityId())
{
final FollowPanel followPanel;
ClickHandler clickHandler = null;
if (showBlockSuggestion)
{
// NOTE: this is a hack - this doesn't have anything to do with blocking suggestions, it just happens
// that the only list that removes streams after joining them happens to be the one that allows streams
// to be blocked
clickHandler = new ClickHandler()
{
public void onClick(final ClickEvent event)
{
removeFromParent();
}
};
}
// it's not the current user - see if it's a private group, and if we're not admin
if (inStreamDTO.getEntityType() == EntityType.GROUP && inStreamDTO instanceof DomainGroupModelView
&& ((DomainGroupModelView) inStreamDTO).isPublic() != null
&& !((DomainGroupModelView) inStreamDTO).isPublic()
&& !Session.getInstance().getCurrentPerson().getRoles().contains(Role.SYSTEM_ADMIN))
{
// this is a private group and we're not an admin, so we gotta request access
// note: no click handler since you can't join this group - just show it as pending
followPanel = new FollowPanel(inStreamDTO, style.requestButton(), style.unfollowButton(),
coreCss.buttonLabel(), true, style.pendingButton());
}
else
{
// either not a private group, or we're admin and it doesn't matter - just show join/unjoin
followPanel = new FollowPanel(inStreamDTO, style.followButton(), style.unfollowButton(),
coreCss.buttonLabel(), true, clickHandler, null);
}
if (!showBlockSuggestion)
{
followPanel.addStyleName(style.followControlsPanel());
main.add(followPanel);
}
else
{
Panel panel = new FlowPanel();
panel.addStyleName(style.followControlsPanel());
panel.addStyleName(style.multi());
panel.add(followPanel);
final Label block = new Label();
block.addStyleName(style.blockButton());
block.setTitle("Block this suggestion");
block.addClickHandler(new ClickHandler()
{
public void onClick(final ClickEvent arg0)
{
if (jsniFacade.confirm("Are you sure you want to block this suggestion?"))
{
BlockedSuggestionModel.getInstance().insert(inStreamDTO.getStreamScopeId());
removeFromParent();
}
}
});
panel.add(block);
main.add(panel);
}
}
}
/**
* Binder for building UI.
*/
interface LocalUiBinder extends UiBinder<Widget, DiscoverListItemPanel>
{
}
}