/* * 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.common.notification; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; import org.eurekastreams.server.domain.NotificationFilterPreferenceDTO; 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.GotNotificationFilterPreferencesResponseEvent; import org.eurekastreams.web.client.events.data.UpdatedNotificationFilterPreferencesResponseEvent; import org.eurekastreams.web.client.model.NotificationFilterPreferencesModel; import org.eurekastreams.web.client.ui.Session; import org.eurekastreams.web.client.ui.common.notifier.Notification; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.DivElement; import com.google.gwt.event.dom.client.ClickEvent; 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.uibinder.client.UiHandler; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.HasValue; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Widget; /** * Personal Settings Panel Composite. */ public class NotificationSettingsWidget extends Composite { /** Binder for building UI. */ private static LocalUiBinder binder = GWT.create(LocalUiBinder.class); /** List of notification preference categories. */ private static final Map<String, String> PREF_CATEGORIES = new LinkedHashMap<String, String>(); static { PREF_CATEGORIES.put("POST_TO_PERSONAL_STREAM", "Someone posts on my stream"); PREF_CATEGORIES.put("LIKE", "Someone likes one of my posts"); PREF_CATEGORIES.put("COMMENT", "Someone comments on one of my posts or a post I've commented on"); PREF_CATEGORIES.put("FOLLOW", "Someone follows my stream or a group I coordinate"); } /** Index of all the checkboxes by controlling preference. */ private final Map<NotificationFilterPreferenceDTO, HasValue<Boolean>> checkboxIndex = // \n new TreeMap<NotificationFilterPreferenceDTO, HasValue<Boolean>>(new Comparator<NotificationFilterPreferenceDTO>() { public int compare(final NotificationFilterPreferenceDTO inO1, final NotificationFilterPreferenceDTO inO2) { int cmp = inO1.getNotifierType().compareTo(inO2.getNotifierType()); return cmp != 0 ? cmp : inO1.getNotificationCategory().compareTo(inO2.getNotificationCategory()); } }); /** Local styles. */ @UiField LocalStyle style; /** Top bar. */ @UiField DivElement topBar; /** UI element acting as the back button. */ @UiField Label backButton; /** UI element acting as the save button. */ @UiField Label saveButton; /** UI element acting as the cancel button. */ @UiField Label cancelButton; /** Main settings grid. */ @UiField Grid settingsGrid; /** Command widget will invoke to request it be closed/removed. */ private Command closeCommand; /** Observer (for unwiring). */ private final Observer<UpdatedNotificationFilterPreferencesResponseEvent> settingsSavedObserver = // \n new Observer<UpdatedNotificationFilterPreferencesResponseEvent>() { public void update(final UpdatedNotificationFilterPreferencesResponseEvent arg1) { EventBus.getInstance().notifyObservers(new ShowNotificationEvent(new Notification("Settings saved"))); closeCommand.execute(); } }; /** Observer (for unwiring). */ private final Observer<GotNotificationFilterPreferencesResponseEvent> gotDataObserver = // \n new Observer<GotNotificationFilterPreferencesResponseEvent>() { public void update(final GotNotificationFilterPreferencesResponseEvent ev) { EventBus.getInstance().removeObserver(ev, this); buildNotificationFilterGrid(ev.getResponse().getNotifierTypes(), PREF_CATEGORIES, ev.getResponse() .getPreferences()); } }; /** * Constructor. * * @param showTopBar * If the top bar should be shown. */ public NotificationSettingsWidget(final boolean showTopBar) { initWidget(binder.createAndBindUi(this)); if (!showTopBar) { topBar.removeFromParent(); } // listen for model events final EventBus eventBus = Session.getInstance().getEventBus(); eventBus.addObserver(UpdatedNotificationFilterPreferencesResponseEvent.class, settingsSavedObserver); eventBus.addObserver(GotNotificationFilterPreferencesResponseEvent.class, gotDataObserver); // request data NotificationFilterPreferencesModel.getInstance().fetch(null, true); } /** * Provides the command the widget will invoke to request it be closed/removed. * * @param inCloseCommand * the command. */ public void setCloseCommand(final Command inCloseCommand) { closeCommand = inCloseCommand; } /** * {@inheritDoc} */ @Override protected void onDetach() { super.onDetach(); final EventBus eventBus = EventBus.getInstance(); eventBus.removeObserver(UpdatedNotificationFilterPreferencesResponseEvent.class, settingsSavedObserver); eventBus.removeObserver(GotNotificationFilterPreferencesResponseEvent.class, gotDataObserver); } /** * Gathers settings and sends to model to send to server. * * @param ev * Event. */ @UiHandler("saveButton") void saveChanges(final ClickEvent ev) { ArrayList<NotificationFilterPreferenceDTO> selected = new ArrayList<NotificationFilterPreferenceDTO>(); for (Entry<NotificationFilterPreferenceDTO, HasValue<Boolean>> entry : checkboxIndex.entrySet()) { if (!entry.getValue().getValue()) { selected.add(entry.getKey()); } } NotificationFilterPreferencesModel.getInstance().update(selected); } /** * Requests the widget be closed. * * @param ev * Event. */ @UiHandler({ "cancelButton", "backButton" }) void cancel(final ClickEvent ev) { closeCommand.execute(); } /** * Builds the personal/group grid for notification preferences. * * @param notifiers * List of notifiers. * @param categories * Names and enum values of the notification preference categories to include in this grid. * @param filters * User's current notification preferences. * @return Grid. */ private Grid buildNotificationFilterGrid(final Map<String, String> notifiers, final Map<String, String> categories, final Collection<NotificationFilterPreferenceDTO> filters) { Grid grid = settingsGrid; grid.resize(1 + categories.size(), 1 + notifiers.size()); // display each category name (one per row) int row = 0; for (String categoryName : categories.values()) { row++; grid.setText(row, 0, categoryName); } // display each notifier column int col = 0; for (Map.Entry<String, String> entry : notifiers.entrySet()) { col++; final String notifierType = entry.getKey(); // display the names of the notifiers grid.setText(0, col, entry.getValue()); grid.getColumnFormatter().addStyleName(col, style.gridColumn()); // create the checkboxes for that notifier per category row = 0; for (String category : categories.keySet()) { row++; CheckBox checkBox = new CheckBox(); checkBox.setValue(true); grid.setWidget(row, col, checkBox); checkboxIndex.put(new NotificationFilterPreferenceDTO(notifierType, category), checkBox); } } // uncheck checkboxes for suppressed entries for (NotificationFilterPreferenceDTO pref : filters) { pref.setPersonId(0); HasValue<Boolean> checkBox = checkboxIndex.get(pref); if (checkBox != null) { checkBox.setValue(false); } } return grid; } /** * Local styles. */ interface LocalStyle extends CssResource { /** @return Settings grid column style. */ @ClassName("grid-column") String gridColumn(); } /** * Binder for building UI. */ interface LocalUiBinder extends UiBinder<Widget, NotificationSettingsWidget> { } }