/*
* 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 org.eurekastreams.server.action.request.profile.SetFollowingStatusRequest;
import org.eurekastreams.server.domain.EntityType;
import org.eurekastreams.server.domain.Follower;
import org.eurekastreams.server.domain.Follower.FollowerStatus;
import org.eurekastreams.server.domain.FollowerStatusable;
import org.eurekastreams.server.search.modelview.DomainGroupModelView;
import org.eurekastreams.server.search.modelview.PersonModelView.Role;
import org.eurekastreams.web.client.events.EventBus;
import org.eurekastreams.web.client.events.Observer;
import org.eurekastreams.web.client.events.ShowNotificationEvent;
import org.eurekastreams.web.client.events.data.BaseDataRequestResponseEvent;
import org.eurekastreams.web.client.events.data.DeletedGroupMemberResponseEvent;
import org.eurekastreams.web.client.events.data.DeletedPersonFollowerResponseEvent;
import org.eurekastreams.web.client.events.data.InsertedGroupMemberResponseEvent;
import org.eurekastreams.web.client.events.data.InsertedPersonFollowerResponseEvent;
import org.eurekastreams.web.client.model.GroupMembersModel;
import org.eurekastreams.web.client.model.GroupMembershipRequestModel;
import org.eurekastreams.web.client.model.PersonFollowersModel;
import org.eurekastreams.web.client.ui.Session;
import org.eurekastreams.web.client.ui.common.notifier.Notification;
import org.eurekastreams.web.client.ui.pages.master.StaticResourceBundle;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
/**
* Panel to show the following status of a person or group, allowing the user to update the status.
*/
public class FollowPanel extends FlowPanel
{
/**
* The unfollow link.
*/
private final Label unfollowLink = new Label("");
/**
* The follow link.
*/
private final Label followLink = new Label("");
/**
* A style name to switch this state to after the user requests access to a private group.
*/
private String pendingGroupJoinedStateStyleName;
/**
* Whether request is required to join this group.
*/
private boolean requestRequiredToJoin;
/**
* Constructor.
*
* @param inFollowable
* the stream to show the follow widget for.
*/
public FollowPanel(final FollowerStatusable inFollowable)
{
this(inFollowable, null, StaticResourceBundle.INSTANCE.coreCss().unFollowLink(), StaticResourceBundle.INSTANCE
.coreCss().followLink(), false, (ClickHandler) null, (String) null);
}
/**
* Constructor.
*
* @param inFollowable
* the stream to show the follow widget for.
* @param followStyle
* Style for the follow button.
* @param unfollowStyle
* Style for the unfollow button.
* @param commonStyle
* Style for both buttons.
* @param showTooltips
* Show tooltips.
* @param inPendingGroupJoinedStateStyleName
* style name to show pending group join
*/
public FollowPanel(final FollowerStatusable inFollowable, final String followStyle, final String unfollowStyle,
final String commonStyle, final boolean showTooltips, final String inPendingGroupJoinedStateStyleName)
{
this(inFollowable, followStyle, unfollowStyle, commonStyle, showTooltips, (ClickHandler) null,
inPendingGroupJoinedStateStyleName);
}
/**
* Constructor.
*
* @param inFollowable
* the stream to show the follow widget for.
* @param followStyle
* Style for the follow button.
* @param unfollowStyle
* Style for the unfollow button.
* @param commonStyle
* Style for both buttons.
* @param showTooltips
* Show tooltips.
* @param onFollowHandler
* additional handler to call on follow.
* @param inPendingGroupJoinedStateStyleName
* style name to show pending group join
*/
public FollowPanel(final FollowerStatusable inFollowable, final String followStyle, final String unfollowStyle,
final String commonStyle, final boolean showTooltips, final ClickHandler onFollowHandler,
final String inPendingGroupJoinedStateStyleName)
{
pendingGroupJoinedStateStyleName = inPendingGroupJoinedStateStyleName;
FollowerStatus status = inFollowable.getFollowerStatus();
if (inFollowable instanceof DomainGroupModelView && ((DomainGroupModelView) inFollowable).isPublic() != null
&& !((DomainGroupModelView) inFollowable).isPublic()
&& !Session.getInstance().getCurrentPerson().getRoles().contains(Role.SYSTEM_ADMIN))
{
this.requestRequiredToJoin = true;
}
else
{
this.requestRequiredToJoin = false;
}
if (status == null)
{
return;
}
unfollowLink.setVisible(false);
followLink.setVisible(false);
if (showTooltips)
{
if (requestRequiredToJoin)
{
followLink.setTitle("Request access to this stream");
}
else
{
followLink.setTitle("Follow this stream");
}
unfollowLink.setTitle("Stop following this stream");
}
if (unfollowStyle != null)
{
unfollowLink.addStyleName(unfollowStyle);
}
if (commonStyle != null)
{
unfollowLink.addStyleName(commonStyle);
}
unfollowLink.addClickHandler(new ClickHandler()
{
public void onClick(final ClickEvent event)
{
SetFollowingStatusRequest request = new SetFollowingStatusRequest(Session.getInstance()
.getCurrentPerson().getAccountId(), inFollowable.getUniqueId(), inFollowable.getEntityType(),
false, Follower.FollowerStatus.NOTFOLLOWING);
if (inFollowable.getEntityType() == EntityType.PERSON)
{
PersonFollowersModel.getInstance().insert(request);
}
else if (inFollowable.getEntityType() == EntityType.GROUP)
{
GroupMembersModel.getInstance().insert(request);
}
else
{
Window.alert("Unsupported");
}
unfollowLink.setVisible(false);
followLink.setVisible(true);
}
});
this.add(unfollowLink);
if (followStyle != null)
{
followLink.addStyleName(followStyle);
}
if (commonStyle != null)
{
followLink.addStyleName(commonStyle);
}
followLink.addClickHandler(new ClickHandler()
{
public void onClick(final ClickEvent event)
{
SetFollowingStatusRequest request = new SetFollowingStatusRequest(Session.getInstance()
.getCurrentPerson().getAccountId(), inFollowable.getUniqueId(), inFollowable.getEntityType(),
false, Follower.FollowerStatus.FOLLOWING);
if (inFollowable.getEntityType() == EntityType.PERSON)
{
PersonFollowersModel.getInstance().insert(request);
}
else if (inFollowable.getEntityType() == EntityType.GROUP)
{
if (requestRequiredToJoin)
{
// private group, we're not admin - request access
GroupMembershipRequestModel.getInstance().insert(inFollowable.getUniqueId());
if (pendingGroupJoinedStateStyleName != null)
{
// the page gave us a style to switch to to show pending state
if (followLink != null)
{
followLink.setVisible(false);
}
if (unfollowLink != null)
{
unfollowLink.setVisible(false);
}
clear();
Label newLabel = new Label("");
newLabel.setStyleName(pendingGroupJoinedStateStyleName);
newLabel.setTitle("Access to this stream has been requested.");
add(newLabel);
// show a notification
Session.getInstance()
.getEventBus()
.notifyObservers(
new ShowNotificationEvent(new Notification(
"Your request for access has been sent")));
}
}
else
{
// public group - join
GroupMembersModel.getInstance().insert(request);
}
}
unfollowLink.setVisible(true);
followLink.setVisible(false);
}
});
if (null != onFollowHandler)
{
followLink.addClickHandler(onFollowHandler);
}
this.add(followLink);
switch (status)
{
case FOLLOWING:
unfollowLink.setVisible(true);
break;
case NOTFOLLOWING:
followLink.setVisible(true);
break;
default:
break;
}
// listen to stream follow/unfollow events and adjust accordingly. If stream is listed multiple times
// on a page (e.g. Discovery page) this will keep the follow/unfollow links in sync for all instances.
EventBus.getInstance().addObservers(
new Observer<BaseDataRequestResponseEvent<SetFollowingStatusRequest, Integer>>()
{
public void update(final BaseDataRequestResponseEvent<SetFollowingStatusRequest, Integer> inArg1)
{
if (inFollowable.getEntityType() == inArg1.getRequest().getTargetEntityType()
&& inFollowable.getUniqueId() == inArg1.getRequest().getTargetUniqueId())
{
switch (inArg1.getRequest().getFollowerStatus())
{
case FOLLOWING:
followLink.setVisible(false);
unfollowLink.setVisible(true);
break;
case NOTFOLLOWING:
unfollowLink.setVisible(false);
followLink.setVisible(true);
break;
default:
break;
}
}
}
}, InsertedPersonFollowerResponseEvent.class, InsertedGroupMemberResponseEvent.class,
DeletedPersonFollowerResponseEvent.class, DeletedGroupMemberResponseEvent.class);
}
}