/* * Copyright (c) 2009-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.profile; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import org.eurekastreams.commons.client.ActionProcessor; import org.eurekastreams.server.action.request.directory.GetDirectorySearchResultsRequest; import org.eurekastreams.server.action.request.profile.GetPendingGroupsRequest; import org.eurekastreams.server.action.request.stream.GetFlaggedActivitiesByOrgRequest; import org.eurekastreams.server.domain.Page; import org.eurekastreams.server.domain.ResourceSortCriteria; import org.eurekastreams.server.domain.ResourceSortCriterion; import org.eurekastreams.server.domain.ResourceSortCriterion.SortDirection; import org.eurekastreams.server.domain.ResourceSortCriterion.SortField; import org.eurekastreams.server.domain.stream.StreamScope.ScopeType; import org.eurekastreams.server.search.modelview.OrganizationModelView; import org.eurekastreams.server.search.modelview.PersonModelView; import org.eurekastreams.web.client.events.EventBus; import org.eurekastreams.web.client.events.Observer; import org.eurekastreams.web.client.events.SetBannerEvent; import org.eurekastreams.web.client.events.ShowNotificationEvent; import org.eurekastreams.web.client.events.StreamRequestEvent; import org.eurekastreams.web.client.events.SwitchToFilterOnPagedFilterPanelEvent; import org.eurekastreams.web.client.events.UpdateHistoryEvent; import org.eurekastreams.web.client.events.UpdatedHistoryParametersEvent; import org.eurekastreams.web.client.events.data.AuthorizeUpdateOrganizationResponseEvent; import org.eurekastreams.web.client.events.data.DeletedActivityResponseEvent; import org.eurekastreams.web.client.events.data.GotFlaggedActivitiesResponseEvent; import org.eurekastreams.web.client.events.data.GotOrganizationEmployeesResponseEvent; import org.eurekastreams.web.client.events.data.GotOrganizationGroupsResponseEvent; import org.eurekastreams.web.client.events.data.GotOrganizationModelViewInformationResponseEvent; import org.eurekastreams.web.client.events.data.GotOrganizationSubOrgsResponseEvent; import org.eurekastreams.web.client.events.data.GotPendingGroupsResponseEvent; import org.eurekastreams.web.client.events.data.UpdatedActivityFlagResponseEvent; import org.eurekastreams.web.client.events.data.UpdatedReviewPendingGroupResponseEvent; import org.eurekastreams.web.client.history.CreateUrlRequest; import org.eurekastreams.web.client.model.FlaggedActivityModel; import org.eurekastreams.web.client.model.OrganizationEmployeesModel; import org.eurekastreams.web.client.model.OrganizationGroupsModel; import org.eurekastreams.web.client.model.OrganizationModel; import org.eurekastreams.web.client.model.OrganizationSubOrgsModel; import org.eurekastreams.web.client.model.PendingGroupsModel; import org.eurekastreams.web.client.ui.Session; import org.eurekastreams.web.client.ui.common.LeftBarPanel; import org.eurekastreams.web.client.ui.common.Pager; import org.eurekastreams.web.client.ui.common.notifier.Notification; import org.eurekastreams.web.client.ui.common.pagedlist.GroupRenderer; import org.eurekastreams.web.client.ui.common.pagedlist.OrganizationRenderer; import org.eurekastreams.web.client.ui.common.pagedlist.PagedListPanel; import org.eurekastreams.web.client.ui.common.pagedlist.PendingGroupRenderer; import org.eurekastreams.web.client.ui.common.pagedlist.PersonRenderer; import org.eurekastreams.web.client.ui.common.pagedlist.SingleColumnPagedListRenderer; import org.eurekastreams.web.client.ui.common.stream.StreamJsonRequestFactory; import org.eurekastreams.web.client.ui.common.stream.StreamPanel; import org.eurekastreams.web.client.ui.common.stream.renderers.ShowRecipient; import org.eurekastreams.web.client.ui.common.stream.renderers.StreamMessageItemRenderer; import org.eurekastreams.web.client.ui.common.tabs.SimpleTab; import org.eurekastreams.web.client.ui.common.tabs.TabContainerPanel; import org.eurekastreams.web.client.ui.pages.master.StaticResourceBundle; import org.eurekastreams.web.client.ui.pages.profile.widgets.BreadcrumbPanel; import org.eurekastreams.web.client.ui.pages.profile.widgets.ConnectionsPanel; import org.eurekastreams.web.client.ui.pages.profile.widgets.OrgAboutPanel; import org.eurekastreams.web.client.ui.pages.profile.widgets.PeopleListPanel; import org.eurekastreams.web.client.ui.pages.profile.widgets.PopularHashtagsPanel; import org.eurekastreams.web.client.utility.BaseActivityLinkBuilder; import org.eurekastreams.web.client.utility.InContextActivityLinkBuilder; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Hyperlink; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.SimplePanel; /** * Displays a summary of a person's profile. */ public class OrganizationProfilePanel extends FlowPanel { /** * Spacing panel -- we use floats in on the ProfilePage, so make sure nothing below it intrudes. */ SimplePanel clearPanel = new SimplePanel(); /** * Holds the PortalPage section of the profile display. */ private TabContainerPanel portalPage = null; /** * Panel that shows the bread crumb navigation. */ private final BreadcrumbPanel breadCrumbPanel; /** * Link to go to the profile settings page. */ private final Hyperlink profileSettingsLink; /** * Link to add a new sub org. */ private final Hyperlink addSubOrgLink; /** * Panel that holds the tabbed portion of the profile display. */ private final FlowPanel portalPageContainer = new FlowPanel(); /** * Left bar container. */ private final FlowPanel leftBarContainer = new FlowPanel(); /** * panel that holds the profile summary. */ private final LeftBarPanel leftBarPanel = new LeftBarPanel(); /** * The org. */ private OrganizationModelView org; /** * Connections Panel Holds the Small boxes with the connect counts. */ private ConnectionsPanel connectionsPanel; /** * Action Processor. */ private final ActionProcessor processor = Session.getInstance().getActionProcessor(); /** Number of flagged activities (for use on the admin tab label). */ private int flaggedActivityCount = 0; /** Number of pending groups (for use on the admin tab label). */ private int pendingGroupCount = 0; /** * Number of group decendents. Track this local so we can adjust connctions tab number when approving pending groups * without going back to server. */ private int orgDescendantGroupCount = 0; /** * Constructor. * * @param accountId * the account id. */ public OrganizationProfilePanel(final String accountId) { RootPanel.get().addStyleName(StaticResourceBundle.INSTANCE.coreCss().profile()); profileSettingsLink = new Hyperlink("Configure", ""); addSubOrgLink = new Hyperlink("", ""); final Hyperlink addGroupLink = new Hyperlink("", Session.getInstance().generateUrl( new CreateUrlRequest(Page.NEW_GROUP, accountId))); ActionProcessor inProcessor = Session.getInstance().getActionProcessor(); addGroupLink.setVisible(false); portalPageContainer.addStyleName(StaticResourceBundle.INSTANCE.coreCss().profilePageContainer()); profileSettingsLink.addStyleName(StaticResourceBundle.INSTANCE.coreCss().configureTab()); profileSettingsLink.addStyleName(StaticResourceBundle.INSTANCE.coreCss().hidden()); addSubOrgLink.addStyleName(StaticResourceBundle.INSTANCE.coreCss().profileAddSubOrg()); addSubOrgLink.addStyleName(StaticResourceBundle.INSTANCE.coreCss().hidden()); addGroupLink.addStyleName(StaticResourceBundle.INSTANCE.coreCss().profileAddGroup()); leftBarContainer.addStyleName(StaticResourceBundle.INSTANCE.coreCss().leftBarContainer()); breadCrumbPanel = new BreadcrumbPanel(inProcessor); this.add(breadCrumbPanel); this.add(addSubOrgLink); this.add(addGroupLink); this.add(profileSettingsLink); leftBarContainer.add(leftBarPanel); this.add(leftBarContainer); this.add(portalPageContainer); this.add(clearPanel); this.addStyleName(StaticResourceBundle.INSTANCE.coreCss().profilePage()); EventBus.getInstance().addObserver(GotOrganizationModelViewInformationResponseEvent.class, new Observer<GotOrganizationModelViewInformationResponseEvent>() { public void update(final GotOrganizationModelViewInformationResponseEvent event) { addGroupLink.setVisible(true); setEntity(event.getResponse()); } }); OrganizationModel.getInstance().fetch(accountId, false); } /** * We have the Person, so set up the Profile summary. * * @param inOrg * the person whose profile is being displayed */ public void setEntity(final OrganizationModelView inOrg) { org = inOrg; leftBarPanel.clear(); portalPageContainer.clear(); // Set the banner. Session.getInstance().getEventBus().notifyObservers(new SetBannerEvent(org)); breadCrumbPanel.setOrganization(org); // Update the Profile summary leftBarPanel.clear(); leftBarPanel.addChildWidget(new OrgAboutPanel(org.getName(), org.getEntityId(), org.getAvatarId(), org.getUrl(), org.getDescription())); leftBarPanel.addChildWidget(new PopularHashtagsPanel(ScopeType.ORGANIZATION, org.getShortName())); connectionsPanel = new ConnectionsPanel(); orgDescendantGroupCount = org.getDescendantGroupCount(); connectionsPanel.addConnection("Employees", "Recently Added", org.getDescendantEmployeeCount()); connectionsPanel.addConnection("Groups", "Recently Added", orgDescendantGroupCount, StaticResourceBundle.INSTANCE.coreCss().center()); connectionsPanel.addConnection("Sub Orgs", null, org.getChildOrganizationCount()); leftBarPanel.addChildWidget(connectionsPanel); leftBarPanel.addChildWidget(new PeopleListPanel(new HashSet<PersonModelView>(org.getLeaders()), "Leadership", PeopleListPanel.DISPLAY_ALL, null, null, null)); final StreamPanel streamContent = new StreamPanel(ShowRecipient.ALL); String jsonRequest = StreamJsonRequestFactory.setOrganization(org.getShortName(), StreamJsonRequestFactory.getEmptyRequest()).toString(); EventBus.getInstance().notifyObservers(new StreamRequestEvent(org.getName(), jsonRequest)); portalPage = new TabContainerPanel(); portalPage.addTab(new SimpleTab("Stream", streamContent)); portalPage.addTab(buildConnectionsTab()); Session.getInstance().getEventBus().addObserver(AuthorizeUpdateOrganizationResponseEvent.class, new Observer<AuthorizeUpdateOrganizationResponseEvent>() { public void update(final AuthorizeUpdateOrganizationResponseEvent event) { if (event.getResponse()) { profileSettingsLink.setTargetHistoryToken(Session.getInstance().generateUrl( new CreateUrlRequest(Page.ORG_SETTINGS, org.getShortName()))); addSubOrgLink.setTargetHistoryToken(Session.getInstance().generateUrl( new CreateUrlRequest(Page.NEW_ORG, org.getShortName()))); profileSettingsLink.removeStyleName(StaticResourceBundle.INSTANCE.coreCss().hidden()); addSubOrgLink.removeStyleName(StaticResourceBundle.INSTANCE.coreCss().hidden()); RootPanel.get().addStyleName(StaticResourceBundle.INSTANCE.coreCss().authenticated()); final SimpleTab adminTab = buildAdminTab(); portalPage.addTab(adminTab); // if heading for admin tab on initial entry to the org profile page, then do it switchToAdminTabFilterIfRequested(); // listen for history change event so that notifications can later send user to admin // tab Session.getInstance().getEventBus().addObserver(UpdatedHistoryParametersEvent.class, new Observer<UpdatedHistoryParametersEvent>() { public void update(final UpdatedHistoryParametersEvent inArg1) { switchToAdminTabFilterIfRequested(); } }); } } }); OrganizationModel.getInstance().authorize(org.getShortName(), false); portalPage.init(); portalPage.setStyleName(StaticResourceBundle.INSTANCE.coreCss().profileGadgetsContainer()); portalPageContainer.add(portalPage); } /** * Switches to the admin tab and filters thereon if URL parameters dictate. */ private void switchToAdminTabFilterIfRequested() { if ("Admin".equals(Session.getInstance().getParameterValue("tab"))) { portalPage.switchToTab("Admin"); String adminFilter = Session.getInstance().getParameterValue("adminFilter"); if (adminFilter != null) { // remove parameter from the URL. Since changing filters does not keep it updated, we // don't want to be on a different filter with this still in the URL. HashMap<String, String> params = new HashMap<String, String>(); params.put("adminFilter", null); Session.getInstance().getEventBus().notifyObservers( new UpdateHistoryEvent(new CreateUrlRequest(params, false))); Session.getInstance().getEventBus().notifyObservers( new SwitchToFilterOnPagedFilterPanelEvent("admin", adminFilter, "", true)); } } } /** * Builds the connections tab. * * @return The tab. */ private SimpleTab buildConnectionsTab() { // Connection Tab List<ResourceSortCriterion> critsForDataAdded = new ArrayList<ResourceSortCriterion>(); critsForDataAdded.add(new ResourceSortCriterion(SortField.DATE_ADDED, SortDirection.DESCENDING)); List<ResourceSortCriterion> critsForFollowers = new ArrayList<ResourceSortCriterion>(); critsForFollowers.add(new ResourceSortCriterion(SortField.FOLLOWERS_COUNT, SortDirection.DESCENDING)); final PagedListPanel connectionTabContent = new PagedListPanel("connections", StaticResourceBundle.INSTANCE .coreCss().tab(), "Connections"); Session.getInstance().getEventBus().addObserver(GotOrganizationEmployeesResponseEvent.class, new Observer<GotOrganizationEmployeesResponseEvent>() { public void update(final GotOrganizationEmployeesResponseEvent event) { connectionTabContent.render(event.getResponse(), "No people are in this organization."); } }); Session.getInstance().getEventBus().addObserver(GotOrganizationGroupsResponseEvent.class, new Observer<GotOrganizationGroupsResponseEvent>() { public void update(final GotOrganizationGroupsResponseEvent event) { connectionTabContent.render(event.getResponse(), "No groups are in this organization."); } }); Session.getInstance().getEventBus().addObserver(GotOrganizationSubOrgsResponseEvent.class, new Observer<GotOrganizationSubOrgsResponseEvent>() { public void update(final GotOrganizationSubOrgsResponseEvent event) { connectionTabContent.render(event.getResponse(), "No sub organizations are in this organization."); } }); connectionTabContent.addSet("Employees", OrganizationEmployeesModel.getInstance(), new PersonRenderer(false), new GetDirectorySearchResultsRequest(org.getShortName(), 0, 0, new ResourceSortCriteria( critsForDataAdded)), "Recently Added"); connectionTabContent.addSet("Employees", OrganizationEmployeesModel.getInstance(), new PersonRenderer(false), new GetDirectorySearchResultsRequest(org.getShortName(), 0, 0, new ResourceSortCriteria( critsForFollowers)), "Followers"); connectionTabContent.addSet("Groups", OrganizationGroupsModel.getInstance(), new GroupRenderer(), new GetDirectorySearchResultsRequest(org.getShortName(), 0, 0, new ResourceSortCriteria( critsForDataAdded)), "Recently Added"); connectionTabContent.addSet("Groups", OrganizationGroupsModel.getInstance(), new GroupRenderer(), new GetDirectorySearchResultsRequest(org.getShortName(), 0, 0, new ResourceSortCriteria( critsForFollowers)), "Followers"); connectionTabContent.addSet("Sub Orgs", OrganizationSubOrgsModel.getInstance(), new OrganizationRenderer(), new GetDirectorySearchResultsRequest(org.getShortName(), 0, 0, new ResourceSortCriteria( critsForDataAdded))); SimpleTab connTab = new SimpleTab("Connections", connectionTabContent); connTab.setParamsToClear(PagedListPanel.URL_PARAM_LIST_ID, PagedListPanel.URL_PARAM_FILTER, PagedListPanel.URL_PARAM_SORT, Pager.URL_PARAM_START_INDEX, Pager.URL_PARAM_END_INDEX); return connTab; } /** * Builds the admin tab. * * @return The tab. */ private SimpleTab buildAdminTab() { final EventBus eventBus = Session.getInstance().getEventBus(); final String flaggedActivitiesFilterName = "Flagged Activities"; final String pendingGroupsFilterName = "Group Requests"; // set up the tab itself final PagedListPanel adminTabContent = new PagedListPanel("admin", new SingleColumnPagedListRenderer(), "tab", "Admin"); final SimpleTab adminTab = new SimpleTab("Admin", adminTabContent); adminTab.setParamsToClear(PagedListPanel.URL_PARAM_LIST_ID, PagedListPanel.URL_PARAM_FILTER, PagedListPanel.URL_PARAM_SORT, Pager.URL_PARAM_START_INDEX, Pager.URL_PARAM_END_INDEX); // wire up the data retrieval events eventBus.addObserver(GotFlaggedActivitiesResponseEvent.class, new Observer<GotFlaggedActivitiesResponseEvent>() { public void update(final GotFlaggedActivitiesResponseEvent event) { if (flaggedActivitiesFilterName.equals(adminTabContent.getCurrentFilter())) { adminTabContent.render(event.getResponse(), "No flagged activities."); } flaggedActivityCount = event.getResponse().getTotal(); adminTabContent.setFilterTitle(flaggedActivitiesFilterName, "Flagged Activities (" + flaggedActivityCount + ")"); adminTab.setTitle("Admin (" + (flaggedActivityCount + pendingGroupCount) + ")"); } }); eventBus.addObserver(GotPendingGroupsResponseEvent.class, new Observer<GotPendingGroupsResponseEvent>() { public void update(final GotPendingGroupsResponseEvent event) { if (pendingGroupsFilterName.equals(adminTabContent.getCurrentFilter())) { adminTabContent.render(event.getResponse(), "No pending group requests."); } pendingGroupCount = event.getResponse().getTotal(); adminTabContent.setFilterTitle(pendingGroupsFilterName, "Group Requests (" + pendingGroupCount + ")"); adminTab.setTitle("Admin (" + (flaggedActivityCount + pendingGroupCount) + ")"); } }); // request the data to get the counts // We need the counts for both of the lists, but at most one list will perform an initial data load, we need to // force the load. (Only the list which is visible will load; if the tab is inactive then there are zero // visible lists.) FlaggedActivityModel.getInstance().fetch(new GetFlaggedActivitiesByOrgRequest(org.getEntityId(), 0, 1), false); PendingGroupsModel.getInstance().fetch(new GetPendingGroupsRequest(org.getShortName(), 0, 1), false); // wire up events to refresh the list when something is removed eventBus.addObserver(UpdatedActivityFlagResponseEvent.class, new Observer<UpdatedActivityFlagResponseEvent>() { public void update(final UpdatedActivityFlagResponseEvent ev) { eventBus.notifyObservers(new ShowNotificationEvent(new Notification( "The flagged activity has been allowed"))); adminTabContent.reload(); } }); eventBus.addObserver(UpdatedReviewPendingGroupResponseEvent.class, new Observer<UpdatedReviewPendingGroupResponseEvent>() { public void update(final UpdatedReviewPendingGroupResponseEvent ev) { adminTabContent.reload(); if ((ev.getResponse()).getApproved()) { orgDescendantGroupCount++; connectionsPanel.updateCount("Groups", orgDescendantGroupCount); } } }); eventBus.addObserver(DeletedActivityResponseEvent.class, new Observer<DeletedActivityResponseEvent>() { public void update(final DeletedActivityResponseEvent ev) { adminTabContent.reload(); } }); // prepare the StaticResourceBundle.INSTANCE.coreCss().filters() // flagged content StaticResourceBundle.INSTANCE.coreCss().filter() StreamMessageItemRenderer flaggedRenderer = new StreamMessageItemRenderer(ShowRecipient.ALL); flaggedRenderer.setShowManageFlagged(true); flaggedRenderer.setShowComment(true); BaseActivityLinkBuilder activityLinkBuilder = new InContextActivityLinkBuilder(); activityLinkBuilder.addExtraParameter("manageFlagged", "true"); flaggedRenderer.setActivityLinkBuilder(activityLinkBuilder); adminTabContent.addSet(flaggedActivitiesFilterName, FlaggedActivityModel.getInstance(), flaggedRenderer, new GetFlaggedActivitiesByOrgRequest(org.getEntityId(), 0, 0)); // pending groups StaticResourceBundle.INSTANCE.coreCss().filter() adminTabContent.addSet(pendingGroupsFilterName, PendingGroupsModel.getInstance(), new PendingGroupRenderer(), new GetPendingGroupsRequest(org.getShortName(), 0, 0)); return adminTab; } }