package org.sigmah.client.ui.view;
/*
* #%L
* Sigmah
* %%
* Copyright (C) 2010 - 2016 URD
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.sigmah.client.i18n.I18N;
import org.sigmah.client.ui.presenter.DashboardPresenter;
import org.sigmah.client.ui.presenter.contact.dashboardlist.ContactsListWidget;
import org.sigmah.client.ui.presenter.project.treegrid.ProjectsListWidget;
import org.sigmah.client.ui.res.icon.IconImageBundle;
import org.sigmah.client.ui.view.base.AbstractView;
import org.sigmah.client.ui.widget.button.Button;
import org.sigmah.client.ui.widget.form.Forms;
import org.sigmah.client.ui.widget.layout.Layouts;
import org.sigmah.client.ui.widget.layout.Layouts.Margin;
import org.sigmah.client.ui.widget.orgunit.OrgUnitTreeGrid;
import org.sigmah.client.ui.widget.panel.Panels;
import org.sigmah.client.util.ClientUtils;
import org.sigmah.client.util.DateUtils;
import org.sigmah.shared.dto.reminder.MonitoredPointDTO;
import org.sigmah.shared.dto.reminder.ReminderDTO;
import com.extjs.gxt.ui.client.Style.LayoutRegion;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.Component;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Label;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnData;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
import com.extjs.gxt.ui.client.widget.grid.filters.DateFilter;
import com.extjs.gxt.ui.client.widget.grid.filters.GridFilters;
import com.extjs.gxt.ui.client.widget.grid.filters.StringFilter;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import org.sigmah.client.ui.presenter.DashboardPresenter.ReminderOrMonitoredPointHandler;
/**
* Dashboard view.
*
* @author Tom Miette (tmiette@ideia.fr)
* @author Denis Colliot (dcolliot@ideia.fr)
*/
@Singleton
public class DashboardView extends AbstractView implements DashboardPresenter.View {
/**
* Reminders expected date label style name.
*/
private static final String EXPECTED_DATE_LABEL_STYLE = "points-date-exceeded";
@Inject
private Provider<ContactsListWidget> contactsListWidgetProvider;
@Inject
private Provider<ProjectsListWidget> projectsListWidgetProvider;
private ContentPanel remindersPanel;
private ListStore<ReminderDTO> remindersStore;
private ContentPanel monitoredPointsPanel;
private ListStore<MonitoredPointDTO> monitoredPointsStore;
private LayoutContainer menuButtonsContainer;
private ContentPanel orgUnitsPanel;
private OrgUnitTreeGrid orgUnitsTreeGrid;
private ContactsListWidget contactsListWidget;
private ProjectsListWidget projectsListWidget;
private static ReminderOrMonitoredPointHandler handler;
final ReminderOrMonitoredPointHandler getReminderOrMonitoredPointHandler() {
return handler;
}
/**
* {@inheritDoc}
*/
@Override
public void setReminderOrMonitoredPointHandler(final ReminderOrMonitoredPointHandler handler) {
this.handler = handler;
}
/**
* {@inheritDoc}
*/
@Override
public void initialize() {
// --
// Left panel (Reminders + MonitoredPoints + Buttons).
// --
final LayoutContainer leftContainer = Layouts.vBox();
leftContainer.add(createRemindersPanel(), Layouts.vBoxData(Margin.BOTTOM));
leftContainer.add(createMonitoredPointsPanel(), Layouts.vBoxData(Margin.BOTTOM));
leftContainer.add(createMenuButtonsPanel(), Layouts.vBoxData());
add(leftContainer, Layouts.borderLayoutData(LayoutRegion.WEST, Layouts.LEFT_COLUMN_WIDTH));
// --
// Center panel (OrgUnits + Contacts + Projects).
// --
final LayoutContainer centerContainer = Layouts.vBox();
// --
// Center-Up panel (OrgUnits + Contacts).
// --
final LayoutContainer centerUpContainer = Layouts.hBox();
centerUpContainer.add(createOrgUnitsPanel(), Layouts.hBoxData(1.0));
centerUpContainer.add(createContactsPanel(), Layouts.hBoxData(1.0, Margin.LEFT));
centerContainer.add(centerUpContainer, Layouts.vBoxData(1.0, Margin.BOTTOM, Margin.LEFT));
centerContainer.add(createProjectsPanel(), Layouts.vBoxData(1.0, Margin.LEFT));
add(centerContainer);
}
/**
* {@inheritDoc}
*/
@Override
public Component getRemindersPanel() {
return remindersPanel;
}
/**
* {@inheritDoc}
*/
@Override
public ListStore<ReminderDTO> getRemindersStore() {
return remindersStore;
}
/**
* {@inheritDoc}
*/
@Override
public Component getMonitoredPointsPanel() {
return monitoredPointsPanel;
}
/**
* {@inheritDoc}
*/
@Override
public ListStore<MonitoredPointDTO> getMonitoredPointsStore() {
return monitoredPointsStore;
}
/**
* {@inheritDoc}
*/
@Override
public void clearMenuButtons() {
menuButtonsContainer.removeAll();
}
/**
* {@inheritDoc}
*/
@Override
public void addMenuButton(final String buttonText, final AbstractImagePrototype buttonIcon, final Listener<ButtonEvent> clickHandler) {
if (ClientUtils.isBlank(buttonText)) {
throw new IllegalArgumentException("Invalid button text.");
}
final Button button = Forms.button(buttonText, buttonIcon);
if (clickHandler != null) {
button.addListener(Events.OnClick, clickHandler);
}
menuButtonsContainer.add(button, Layouts.vBoxData());
}
/**
* {@inheritDoc}
*/
@Override
public void layoutButtons() {
menuButtonsContainer.layout();
}
/**
* {@inheritDoc}
*/
@Override
public void layoutViews() {
if (contactsListWidget != null) {
contactsListWidget.getView().syncSize();
projectsListWidget.getView().syncSize();
}
}
/**
* {@inheritDoc}
*/
@Override
public OrgUnitTreeGrid getOrgUnitsTreeGrid() {
return orgUnitsTreeGrid;
}
/**
* {@inheritDoc}
*/
@Override
public void setPanelsTitleSuffix(final String suffix) {
orgUnitsPanel.setHeadingText(I18N.CONSTANTS.orgunitTree() + suffix);
projectsListWidget.setTitleSupplier(new ProjectsListWidget.TitleSupplier() {
@Override
public String supplyTitle(int projectCount) {
return ProjectsListWidget.DEFAULT_TITLE_SUPPLIER.supplyTitle(projectCount) + suffix;
}
});
}
/**
* {@inheritDoc}
*/
@Override
public ContactsListWidget getContactsList() {
return contactsListWidget;
}
/**
* {@inheritDoc}
*/
@Override
public ProjectsListWidget getProjectsList() {
return projectsListWidget;
}
// -------------------------------------------------------------------------------------------
//
// UTILITY METHODS.
//
// -------------------------------------------------------------------------------------------
/**
* Creates the reminders component.
*
* @return The reminders component widget.
*/
private Component createRemindersPanel() {
remindersStore = new ListStore<ReminderDTO>();
final Grid<ReminderDTO> reminderGrid = new Grid<ReminderDTO>(remindersStore, new ColumnModel(createRemindersGridColumns()));
reminderGrid.getView().setForceFit(true);
reminderGrid.setAutoExpandColumn(ReminderDTO.LABEL);
remindersPanel = Panels.content(I18N.CONSTANTS.reminderPoints());
remindersPanel.add(reminderGrid);
return remindersPanel;
}
/**
* Creates the monitored points component.
*
* @return The monitored points component widget.
*/
private Component createMonitoredPointsPanel() {
monitoredPointsStore = new ListStore<MonitoredPointDTO>();
final Grid<MonitoredPointDTO> monitoredPointsGrid = new Grid<MonitoredPointDTO>(monitoredPointsStore, new ColumnModel(createMonitoredPointsGridColumns()));
monitoredPointsGrid.getView().setForceFit(true);
monitoredPointsGrid.setAutoExpandColumn(MonitoredPointDTO.LABEL);
final GridFilters filters = new GridFilters();
filters.setLocal(true);
filters.addFilter(new StringFilter(MonitoredPointDTO.LABEL));
filters.addFilter(new DateFilter(MonitoredPointDTO.EXPECTED_DATE));
monitoredPointsGrid.addPlugin(filters);
monitoredPointsPanel = Panels.content(I18N.CONSTANTS.monitoredPoints());
monitoredPointsPanel.add(monitoredPointsGrid);
return monitoredPointsPanel;
}
/**
* Creates the menu buttons component.
*
* @return The menu buttons component widget.
*/
private Component createMenuButtonsPanel() {
final ContentPanel menuButtonsPanel = Panels.content(I18N.CONSTANTS.menu());
menuButtonsContainer = Layouts.vBox();
menuButtonsPanel.add(menuButtonsContainer);
return menuButtonsPanel;
}
/**
* Creates the OrgUnits component.
*
* @return The OrgUnits component widget.
*/
private Component createOrgUnitsPanel() {
orgUnitsPanel = Panels.content(I18N.CONSTANTS.orgunitTree());
orgUnitsTreeGrid = new OrgUnitTreeGrid(false);
orgUnitsPanel.setTopComponent(orgUnitsTreeGrid.getToolbar());
orgUnitsPanel.add(orgUnitsTreeGrid.getTreeGrid());
return orgUnitsPanel;
}
/**
* Creates the contacts component.
*
* @return The contacts component widget.
*/
private Widget createContactsPanel() {
contactsListWidget = contactsListWidgetProvider.get();
contactsListWidget.initialize();
return contactsListWidget.getView().asWidget();
}
/**
* Creates the projects component.
*
* @return The projects component widget.
*/
private Widget createProjectsPanel() {
projectsListWidget = projectsListWidgetProvider.get();
projectsListWidget.initialize();
return projectsListWidget.getView().asWidget();
}
/**
* Builds the reminders grid columns configuration.
*
* @return The reminders grid columns list.
*/
private static List<ColumnConfig> createRemindersGridColumns() {
final DateTimeFormat format = DateUtils.DATE_SHORT;
final Date now = new Date();
// Icon column.
final ColumnConfig iconColumn = new ColumnConfig();
iconColumn.setId("icon");
iconColumn.setHeaderHtml("");
iconColumn.setWidth(16);
iconColumn.setResizable(false);
iconColumn.setRenderer(new GridCellRenderer<ReminderDTO>() {
@Override
public Object render(final ReminderDTO model, final String property, final ColumnData config, final int rowIndex, final int colIndex,
final ListStore<ReminderDTO> store, final Grid<ReminderDTO> grid) {
if (DateUtils.DAY_COMPARATOR.compare(now, model.getExpectedDate()) > 0) {
return IconImageBundle.ICONS.overdueReminder().createImage();
} else {
return IconImageBundle.ICONS.openedReminder().createImage();
}
}
});
// Label column.
final ColumnConfig labelColumn = new ColumnConfig();
labelColumn.setId(ReminderDTO.LABEL);
labelColumn.setHeaderHtml(I18N.CONSTANTS.monitoredPointLabel());
labelColumn.setWidth(100);
// Ajout du HREF
labelColumn.setRenderer(new GridCellRenderer<ReminderDTO>() {
@Override
public Object render(final ReminderDTO model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<ReminderDTO> store,
Grid<ReminderDTO> grid) {
final com.google.gwt.user.client.ui.Label label = new com.google.gwt.user.client.ui.Label((String) model.get(property));
label.addStyleName("hyperlink-label");
label.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
handler.onLabelClickEvent(model.getProjectId());
}
});
label.setTitle(I18N.CONSTANTS.projectLabelWithDots() + ' ' + model.getProjectCode() + " - " + model.getProjectName());
return label;
}
});
// Expected date column.
final ColumnConfig expectedDateColumn = new ColumnConfig();
expectedDateColumn.setId(ReminderDTO.EXPECTED_DATE);
expectedDateColumn.setHeaderHtml(I18N.CONSTANTS.monitoredPointExpectedDate());
expectedDateColumn.setWidth(60);
expectedDateColumn.setDateTimeFormat(format);
expectedDateColumn.setRenderer(new GridCellRenderer<ReminderDTO>() {
@Override
public Object render(final ReminderDTO model, final String property, final ColumnData config, final int rowIndex, final int colIndex,
final ListStore<ReminderDTO> store, final Grid<ReminderDTO> grid) {
final Label label = new Label(format.format(model.getExpectedDate()));
if (!model.isCompleted() && DateUtils.DAY_COMPARATOR.compare(now, model.getExpectedDate()) > 0) {
label.addStyleName(EXPECTED_DATE_LABEL_STYLE);
}
return label;
}
});
return Arrays.asList(new ColumnConfig[] {
iconColumn,
labelColumn,
expectedDateColumn
});
}
/**
* Builds the monitored points grid columns configuration.
*
* @return The monitored points grid columns list.
*/
private static List<ColumnConfig> createMonitoredPointsGridColumns() {
final DateTimeFormat format = DateUtils.DATE_SHORT;
final Date now = new Date();
// Icon
final ColumnConfig iconColumn = new ColumnConfig();
iconColumn.setId("icon");
iconColumn.setHeaderHtml("");
iconColumn.setWidth(16);
iconColumn.setResizable(false);
iconColumn.setRenderer(new GridCellRenderer<MonitoredPointDTO>() {
@Override
public Object render(final MonitoredPointDTO model, final String property, final ColumnData config, final int rowIndex, final int colIndex,
final ListStore<MonitoredPointDTO> store, final Grid<MonitoredPointDTO> grid) {
if (DateUtils.DAY_COMPARATOR.compare(now, model.getExpectedDate()) > 0) {
return IconImageBundle.ICONS.overduePoint().createImage();
} else {
return IconImageBundle.ICONS.openedPoint().createImage();
}
}
});
// Label.
final ColumnConfig labelColumn = new ColumnConfig();
labelColumn.setId(MonitoredPointDTO.LABEL);
labelColumn.setHeaderHtml(I18N.CONSTANTS.monitoredPointLabel());
labelColumn.setWidth(100);
labelColumn.setRenderer(new GridCellRenderer<MonitoredPointDTO>() {
@Override
public Object render(final MonitoredPointDTO model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<MonitoredPointDTO> store,
Grid<MonitoredPointDTO> grid) {
final com.google.gwt.user.client.ui.Label label = new com.google.gwt.user.client.ui.Label((String) model.get(property));
label.addStyleName("hyperlink-label");
label.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
handler.onLabelClickEvent(model.getProjectId());
}
});
label.setTitle(I18N.CONSTANTS.projectLabelWithDots() + ' ' + model.getProjectCode() + " - " + model.getProjectName());
return label;
}
});
// Expected date.
final ColumnConfig expectedDateColumn = new ColumnConfig();
expectedDateColumn.setId(MonitoredPointDTO.EXPECTED_DATE);
expectedDateColumn.setHeaderHtml(I18N.CONSTANTS.monitoredPointExpectedDate());
expectedDateColumn.setWidth(60);
expectedDateColumn.setDateTimeFormat(format);
expectedDateColumn.setRenderer(new GridCellRenderer<MonitoredPointDTO>() {
@Override
public Object render(final MonitoredPointDTO model, final String property, final ColumnData config, final int rowIndex, final int colIndex,
final ListStore<MonitoredPointDTO> store, final Grid<MonitoredPointDTO> grid) {
final Label label = new Label(format.format(model.getExpectedDate()));
if (!model.isCompleted() && DateUtils.DAY_COMPARATOR.compare(now, model.getExpectedDate()) > 0) {
label.addStyleName(EXPECTED_DATE_LABEL_STYLE);
}
return label;
}
});
return Arrays.asList(new ColumnConfig[] {
iconColumn,
labelColumn,
expectedDateColumn
});
}
}