/* * Copyright (c) 2010-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.settings.stream; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import org.eurekastreams.commons.client.ActionProcessor; import org.eurekastreams.server.action.request.feed.DeleteFeedSubscriptionRequest; import org.eurekastreams.server.domain.gadgetspec.GadgetMetaDataDTO; import org.eurekastreams.server.domain.stream.plugins.FeedSubscriber; import org.eurekastreams.server.domain.stream.plugins.PluginDefinition; import org.eurekastreams.web.client.events.HideNotificationEvent; import org.eurekastreams.web.client.events.Observer; import org.eurekastreams.web.client.events.ShowNotificationEvent; import org.eurekastreams.web.client.events.StreamPluginsUpdateCanceledEvent; import org.eurekastreams.web.client.events.data.DeletedStreamPluginSubscriptionResponseEvent; import org.eurekastreams.web.client.events.data.GotStreamPluginSubscriptionsResponseEvent; import org.eurekastreams.web.client.events.data.InsertedStreamPluginSubscriptionResponseEvent; import org.eurekastreams.web.client.events.data.UpdatedStreamPluginSubscriptionResponseEvent; import org.eurekastreams.web.client.jsni.GadgetMetaDataFetcher; import org.eurekastreams.web.client.jsni.WidgetJSNIFacade; import org.eurekastreams.web.client.jsni.WidgetJSNIFacadeImpl; import org.eurekastreams.web.client.model.BaseModel; import org.eurekastreams.web.client.model.Deletable; import org.eurekastreams.web.client.model.Fetchable; import org.eurekastreams.web.client.ui.Session; import org.eurekastreams.web.client.ui.common.EditPanel; import org.eurekastreams.web.client.ui.common.EditPanel.Mode; import org.eurekastreams.web.client.ui.common.form.FormBuilder.Method; 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.ui.Anchor; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.InlineLabel; import com.google.gwt.user.client.ui.Label; /** * The display for the stream plugin settings tab. * */ public class StreamPluginsSettingsTabContent extends Composite { /** * The action processor. */ ActionProcessor processor; /** * The flow panel. */ FlowPanel panel = new FlowPanel(); /** * The Settings Container Panel. */ FlowPanel streamPluginSettingsContainer = new FlowPanel(); /** * A container panel for available plugins. */ FlowPanel availablePluginsContainer = new FlowPanel(); /** * A container panel for my plugins. */ FlowPanel feedSubscriptionsContainer = new FlowPanel(); /** * Stores available plugins. */ List<PluginDefinition> availablePlugins = new LinkedList<PluginDefinition>(); /** * Available Plugins Meta Data. */ List<GadgetMetaDataDTO> availablePluginsMetaData = new LinkedList<GadgetMetaDataDTO>(); /** * Feed Subscriptions List. */ List<FeedSubscriber> feedSubscriptions = new LinkedList<FeedSubscriber>(); /** * A map of plugin ids to their corresponding container panels. */ HashMap<Long, FlowPanel> availablePluginsById = new HashMap<Long, FlowPanel>(); /** * List of metadata. */ private List<GadgetMetaDataDTO> metadata; /** * BaseModel. */ private final BaseModel model; /** * JSNI facade. */ private final WidgetJSNIFacade jSNIFacade = new WidgetJSNIFacadeImpl(); /** * The default constructor. * * @param inModel * The base model */ public StreamPluginsSettingsTabContent(final BaseModel inModel) { processor = Session.getInstance().getActionProcessor(); model = inModel; Session.getInstance().getEventBus().addObserver(GotStreamPluginSubscriptionsResponseEvent.class, new Observer<GotStreamPluginSubscriptionsResponseEvent>() { public void update(final GotStreamPluginSubscriptionsResponseEvent event) { availablePlugins = event.getResponse().getPlugins(); feedSubscriptions = event.getResponse().getFeedSubcribers(); GadgetMetaDataFetcher gadgetMetaDataFetcher = new GadgetMetaDataFetcher(availablePlugins); gadgetMetaDataFetcher .addOnMetaDataRetrievedCommand(new GadgetMetaDataFetcher.GotGadgetMetaDataCommand() { public void onGotGadgetMetaData(final List<GadgetMetaDataDTO> inMetadata) { metadata = inMetadata; renderPlugins(); renderFeedSubscriptions(); } }); gadgetMetaDataFetcher.fetchMetaData(); } }); Session.getInstance().getEventBus().addObserver(StreamPluginsUpdateCanceledEvent.class, new Observer<StreamPluginsUpdateCanceledEvent>() { public void update(final StreamPluginsUpdateCanceledEvent event) { renderInsides(); } }); Session.getInstance().getEventBus().addObserver(DeletedStreamPluginSubscriptionResponseEvent.class, new Observer<DeletedStreamPluginSubscriptionResponseEvent>() { public void update(final DeletedStreamPluginSubscriptionResponseEvent event) { renderInsides(); Session.getInstance().getEventBus().notifyObservers( new ShowNotificationEvent(new Notification("Stream plugin has been deleted"))); } }); Session.getInstance().getEventBus().addObserver(InsertedStreamPluginSubscriptionResponseEvent.class, new Observer<InsertedStreamPluginSubscriptionResponseEvent>() { public void update(final InsertedStreamPluginSubscriptionResponseEvent arg1) { renderInsides(); Session.getInstance().getEventBus().notifyObservers( new ShowNotificationEvent( new Notification("Stream Plugin has been successfully added."))); } }); Session.getInstance().getEventBus().addObserver(UpdatedStreamPluginSubscriptionResponseEvent.class, new Observer<UpdatedStreamPluginSubscriptionResponseEvent>() { public void update(final UpdatedStreamPluginSubscriptionResponseEvent arg1) { renderInsides(); Session.getInstance().getEventBus().notifyObservers( new ShowNotificationEvent(new Notification( "Stream Plugin has been successfully updated."))); } }); renderInsides(); initWidget(panel); } /** * Render the default view of this tab. */ private void renderInsides() { panel.clear(); streamPluginSettingsContainer.clear(); availablePluginsContainer.clear(); feedSubscriptionsContainer.clear(); feedSubscriptionsContainer.setVisible(true); streamPluginSettingsContainer.addStyleName(StaticResourceBundle.INSTANCE.coreCss() .streamPluginsSettingsContainer()); availablePluginsContainer.addStyleName(StaticResourceBundle.INSTANCE.coreCss().filters()); getPluginsAndFeedSubscriptions(); feedSubscriptionsContainer.addStyleName(StaticResourceBundle.INSTANCE.coreCss() .streamPluginsFeedSubscriptionsContainer()); feedSubscriptions.add(new FeedSubscriber()); streamPluginSettingsContainer.add(availablePluginsContainer); streamPluginSettingsContainer.add(feedSubscriptionsContainer); panel.add(streamPluginSettingsContainer); } /** * Get all available plugins and feed subscriptions. */ public void getPluginsAndFeedSubscriptions() { ((Fetchable<String>) model).fetch(Session.getInstance().getUrlViews().get( Session.getInstance().getUrlViews().size() - 1), true); } /** * Get the metadata for the plugin. * * @param plugin * the plugin. * @return the metadata. */ private GadgetMetaDataDTO getMetaDataForPlugin(final PluginDefinition plugin) { for (GadgetMetaDataDTO metadataItem : metadata) { if (metadataItem.getGadgetDefinition().getId() == plugin.getId()) { return metadataItem; } } return null; } /** * Renders the plugins. */ public void renderPlugins() { availablePluginsContainer.clear(); Label availablePluginsHeader = new Label("Available Plugins"); availablePluginsHeader.addStyleName(StaticResourceBundle.INSTANCE.coreCss().header()); availablePluginsContainer.add(availablePluginsHeader); if (availablePlugins.size() > 0) { availablePluginsMetaData.clear(); for (PluginDefinition availablePlugin : availablePlugins) { availablePluginsMetaData.add(getMetaDataForPlugin(availablePlugin)); } sortPluginsMetaData(); for (final GadgetMetaDataDTO metaDataItem : availablePluginsMetaData) { FlowPanel filterPanel = new FlowPanel(); filterPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().filter()); FlowPanel listItemPanel = new FlowPanel(); listItemPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().streamListItem()); FlowPanel labelContainer = new FlowPanel(); labelContainer.addStyleName(StaticResourceBundle.INSTANCE.coreCss().filterLabel()); Label pluginTitle = new Label(metaDataItem.getTitle()); pluginTitle.addClickHandler(new ClickHandler() { public void onClick(final ClickEvent event) { // clear the notification in case there was one left over from adding a prior plugin Session.getInstance().getEventBus().notifyObservers(new HideNotificationEvent()); selectPlugin(metaDataItem); } }); labelContainer.add(pluginTitle); listItemPanel.add(new Image(metaDataItem.getThumbnail())); listItemPanel.add(labelContainer); filterPanel.add(listItemPanel); availablePluginsContainer.add(filterPanel); availablePluginsById.put(metaDataItem.getGadgetDefinition().getId(), filterPanel); } } else { availablePluginsContainer.add(new Label("No plugins available")); } } /** * Sorts the meta data for the plugins alphabetically. */ private void sortPluginsMetaData() { for (int i = availablePluginsMetaData.size() - 1; i > 0; i--) { for (int j = 0; j < i; j++) { GadgetMetaDataDTO currentPlugin = availablePluginsMetaData.get(j); GadgetMetaDataDTO nextPlugin = availablePluginsMetaData.get(j + 1); if (currentPlugin.getTitle().compareToIgnoreCase(nextPlugin.getTitle()) > 0) { availablePluginsMetaData.set(j, nextPlugin); availablePluginsMetaData.set(j + 1, currentPlugin); } } } } /** * Renders the feed subscriptions. */ public void renderFeedSubscriptions() { feedSubscriptionsContainer.clear(); Label feedSubscriptionsHeader = new Label("My Plugins"); feedSubscriptionsHeader.addStyleName(StaticResourceBundle.INSTANCE.coreCss().header()); feedSubscriptionsContainer.add(feedSubscriptionsHeader); if (feedSubscriptions.size() > 0) { Label feedDescription = new Label("Click on any of the plugins on the left to add them to your stream."); feedDescription.addStyleName(StaticResourceBundle.INSTANCE.coreCss().description()); feedSubscriptionsContainer.add(feedDescription); int count = 0; int size = feedSubscriptions.size(); // for loop start for (final FeedSubscriber feedSubscription : feedSubscriptions) { if (feedSubscription.getFeed() != null) { final GadgetMetaDataDTO metaDataItem = getMetaDataForPlugin(feedSubscription.getFeed().getPlugin()); FlowPanel feedContainer = new FlowPanel(); feedContainer.addStyleName(StaticResourceBundle.INSTANCE.coreCss().streamPluginsMetaData()); if (count == size - 1) { feedContainer.addStyleName(StaticResourceBundle.INSTANCE.coreCss().last()); } count++; FlowPanel imageContainer = new FlowPanel(); imageContainer.addStyleName(StaticResourceBundle.INSTANCE.coreCss().imageContainer()); FlowPanel screenshot = new FlowPanel(); screenshot.addStyleName(StaticResourceBundle.INSTANCE.coreCss().streamPluginsScreenshot()); screenshot.add(new Image(metaDataItem.getScreenshot())); imageContainer.add(screenshot); FlowPanel dataContainer = new FlowPanel(); dataContainer.setStyleName(StaticResourceBundle.INSTANCE.coreCss().gadgetData()); EditPanel editControls = new EditPanel(dataContainer, Mode.EDIT_AND_DELETE); editControls.addEditClickHandler(new ClickHandler() { public void onClick(final ClickEvent event) { editFeedSubscription(feedSubscription, metaDataItem); } }); editControls.addDeleteClickHandler(new ClickHandler() { public void onClick(final ClickEvent arg0) { if (jSNIFacade.confirm("Are you sure you want to unsubscribe to this feed?")) { ((Deletable<DeleteFeedSubscriptionRequest>) model) .delete(new DeleteFeedSubscriptionRequest(feedSubscription.getId(), Session .getInstance().getUrlViews().get( Session.getInstance().getUrlViews().size() - 1))); } } }); dataContainer.add(editControls); Label title = new Label(feedSubscription.getFeed().getTitle()); title.addStyleName(StaticResourceBundle.INSTANCE.coreCss().title()); FlowPanel sourcePanel = new FlowPanel(); sourcePanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().gadgetExtInfo()); sourcePanel.add(new Label("Source: ")); sourcePanel.add(new Anchor(feedSubscription.getFeed().getUrl(), feedSubscription.getFeed().getUrl(), "_new")); dataContainer.add(title); dataContainer.add(sourcePanel); FlowPanel lastUpdatedPanel = new FlowPanel(); lastUpdatedPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().gadgetExtInfo()); if (feedSubscription.getFeed().getTimeAgo() != null) { lastUpdatedPanel.add(new InlineLabel("Last Updated: ")); Label lastUpdateTime = new InlineLabel(feedSubscription.getFeed().getTimeAgo()); lastUpdateTime.addStyleName(StaticResourceBundle.INSTANCE.coreCss().light()); lastUpdatedPanel.add(lastUpdateTime); } if (feedSubscription.getFeed().getIsFeedBroken() != null && feedSubscription.getFeed().getIsFeedBroken()) { Label brokenFeedIndicator = new InlineLabel("Feed may be broken, please check the source."); brokenFeedIndicator.addStyleName(StaticResourceBundle.INSTANCE.coreCss().brokenFeedIndicator()); lastUpdatedPanel.add(brokenFeedIndicator); } if (lastUpdatedPanel.getWidgetCount() > 0) { dataContainer.add(lastUpdatedPanel); } feedContainer.add(imageContainer); feedContainer.add(dataContainer); feedSubscriptionsContainer.add(feedContainer); } } // for loop end } else { Label feedDescription = new Label("No plugins configured. " + "Select an available plugin to publish activity to the stream."); feedDescription.setStyleName(StaticResourceBundle.INSTANCE.coreCss().description()); feedSubscriptionsContainer.add(feedDescription); } } /** * Selects a plugin from the available plugins, allowing the user to add a new one. * * @param selectedMetaData * MetaData of the selected plugin */ public void selectPlugin(final GadgetMetaDataDTO selectedMetaData) { for (FlowPanel pluginPanel : availablePluginsById.values()) { pluginPanel.removeStyleName(StaticResourceBundle.INSTANCE.coreCss().active()); } availablePluginsById.get(selectedMetaData.getGadgetDefinition().getId()).addStyleName( StaticResourceBundle.INSTANCE.coreCss().active()); feedSubscriptionsContainer.setVisible(false); streamPluginSettingsContainer.clear(); streamPluginSettingsContainer.add(availablePluginsContainer); EditFeedSubscriptionPanel addFeedSubscriptionPanel = new EditFeedSubscriptionPanel(selectedMetaData, Method.INSERT); streamPluginSettingsContainer.add(addFeedSubscriptionPanel); addFeedSubscriptionPanel.add(new StreamPluginConfigurationPanel(selectedMetaData.getGadgetDefinition(), model, selectedMetaData)); } /** * Edits a selected feed subscription. * * @param feedSubscription * The feed subscription being edited * @param selectedMetaData * The meta data of the selected feed's plugin */ public void editFeedSubscription(final FeedSubscriber feedSubscription, final GadgetMetaDataDTO selectedMetaData) { feedSubscriptionsContainer.setVisible(false); streamPluginSettingsContainer.clear(); streamPluginSettingsContainer.add(availablePluginsContainer); EditFeedSubscriptionPanel editFeedSubscriptionPanel = new EditFeedSubscriptionPanel(selectedMetaData, Method.UPDATE); streamPluginSettingsContainer.add(editFeedSubscriptionPanel); editFeedSubscriptionPanel.add(new StreamPluginConfigurationPanel(feedSubscription, model, selectedMetaData)); } }