package org.activityinfo.ui.client.page.entry; /* * #%L * ActivityInfo Server * %% * Copyright (C) 2009 - 2013 UNICEF * %% * 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 com.extjs.gxt.ui.client.Style.LayoutRegion; import com.extjs.gxt.ui.client.event.FieldEvent; import com.extjs.gxt.ui.client.event.Listener; import com.extjs.gxt.ui.client.event.MessageBoxEvent; import com.extjs.gxt.ui.client.event.SelectionChangedEvent; import com.extjs.gxt.ui.client.event.SelectionChangedListener; import com.extjs.gxt.ui.client.util.Margins; import com.extjs.gxt.ui.client.widget.Dialog; import com.extjs.gxt.ui.client.widget.Label; import com.extjs.gxt.ui.client.widget.LayoutContainer; import com.extjs.gxt.ui.client.widget.MessageBox; import com.extjs.gxt.ui.client.widget.TabItem; import com.extjs.gxt.ui.client.widget.layout.BorderLayout; import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData; import com.extjs.gxt.ui.client.widget.layout.FitLayout; import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.inject.Inject; import org.activityinfo.i18n.shared.I18N; import org.activityinfo.legacy.client.Dispatcher; import org.activityinfo.legacy.client.callback.SuccessCallback; import org.activityinfo.legacy.client.monitor.MaskingAsyncMonitor; import org.activityinfo.legacy.shared.adapter.ResourceLocatorAdaptor; import org.activityinfo.legacy.shared.command.*; import org.activityinfo.legacy.shared.command.result.VoidResult; import org.activityinfo.legacy.shared.model.ActivityFormDTO; import org.activityinfo.legacy.shared.model.SchemaDTO; import org.activityinfo.legacy.shared.model.SiteDTO; import org.activityinfo.legacy.shared.model.UserDatabaseDTO; import org.activityinfo.model.legacy.CuidAdapter; import org.activityinfo.ui.client.ClientContext; import org.activityinfo.ui.client.EventBus; import org.activityinfo.ui.client.component.importDialog.ImportPresenter; import org.activityinfo.ui.client.page.NavigationCallback; import org.activityinfo.ui.client.page.NavigationEvent; import org.activityinfo.ui.client.page.NavigationHandler; import org.activityinfo.ui.client.page.Page; import org.activityinfo.ui.client.page.PageId; import org.activityinfo.ui.client.page.PageState; import org.activityinfo.ui.client.page.common.toolbar.ActionListener; import org.activityinfo.ui.client.page.common.toolbar.ActionToolBar; import org.activityinfo.ui.client.page.common.toolbar.UIActions; import org.activityinfo.ui.client.page.entry.column.DefaultColumnModelProvider; import org.activityinfo.ui.client.page.entry.form.PrintDataEntryForm; import org.activityinfo.ui.client.page.entry.form.SiteDialogCallback; import org.activityinfo.ui.client.page.entry.form.SiteDialogLauncher; import org.activityinfo.ui.client.page.entry.grouping.GroupingComboBox; import org.activityinfo.ui.client.page.entry.place.DataEntryPlace; import org.activityinfo.ui.client.page.entry.sitehistory.SiteHistoryTab; import org.activityinfo.ui.client.page.instance.InstancePage; import org.activityinfo.ui.client.page.instance.InstancePlace; import org.activityinfo.ui.client.page.report.ExportDialog; import org.activityinfo.ui.client.style.legacy.icon.IconImageBundle; import java.util.Set; /** * This is the container for the DataEntry page. */ public class DataEntryPage extends LayoutContainer implements Page, ActionListener { private static final boolean IMPORT_FUNCTION_ENABLED = true; public static final PageId PAGE_ID = new PageId("data-entry"); private final Dispatcher dispatcher; private final EventBus eventBus; private GroupingComboBox groupingComboBox; private FilterPane filterPane; private SiteGridPanel gridPanel; private CollapsibleTabPanel tabPanel; private DetailTab detailTab; private MonthlyReportsPanel monthlyPanel; private TabItem monthlyTab; private DataEntryPlace currentPlace = new DataEntryPlace(); private AttachmentsTab attachmentsTab; private SiteHistoryTab siteHistoryTab; private ActionToolBar toolBar; @Inject public DataEntryPage(final EventBus eventBus, Dispatcher dispatcher) { this.eventBus = eventBus; this.dispatcher = dispatcher; setLayout(new BorderLayout()); addFilterPane(); addCenter(); } private void addFilterPane() { filterPane = new FilterPane(dispatcher); BorderLayoutData filterLayout = new BorderLayoutData(LayoutRegion.WEST); filterLayout.setCollapsible(true); filterLayout.setMargins(new Margins(0, 5, 0, 0)); filterLayout.setSplit(true); add(filterPane, filterLayout); filterPane.getSet().addValueChangeHandler(new ValueChangeHandler<Filter>() { @Override public void onValueChange(ValueChangeEvent<Filter> event) { eventBus.fireEvent(new NavigationEvent(NavigationHandler.NAVIGATION_REQUESTED, currentPlace.copy().setFilter(event.getValue()))); } }); } private void addCenter() { gridPanel = new SiteGridPanel(dispatcher, new DefaultColumnModelProvider(dispatcher)); gridPanel.setTopComponent(createToolBar()); LayoutContainer center = new LayoutContainer(); center.setLayout(new BorderLayout()); center.add(gridPanel, new BorderLayoutData(LayoutRegion.CENTER)); gridPanel.addSelectionChangedListener(new SelectionChangedListener<SiteDTO>() { @Override public void selectionChanged(SelectionChangedEvent<SiteDTO> se) { onSiteSelected(se); } }); detailTab = new DetailTab(dispatcher); monthlyPanel = new MonthlyReportsPanel(dispatcher); monthlyTab = new TabItem(I18N.CONSTANTS.monthlyReports()); monthlyTab.setLayout(new FitLayout()); monthlyTab.add(monthlyPanel); attachmentsTab = new AttachmentsTab(dispatcher, eventBus); siteHistoryTab = new SiteHistoryTab(dispatcher); tabPanel = new CollapsibleTabPanel(); tabPanel.add(detailTab); tabPanel.add(monthlyTab); tabPanel.add(attachmentsTab); tabPanel.add(siteHistoryTab); tabPanel.setSelection(detailTab); center.add(tabPanel, tabPanel.getBorderLayoutData()); onNoSelection(); add(center, new BorderLayoutData(LayoutRegion.CENTER)); } private ActionToolBar createToolBar() { toolBar = new ActionToolBar(this); groupingComboBox = new GroupingComboBox(dispatcher); groupingComboBox.withSelectionListener(new Listener<FieldEvent>() { @Override public void handleEvent(FieldEvent be) { eventBus.fireEvent(new NavigationEvent(NavigationHandler.NAVIGATION_REQUESTED, currentPlace.copy().setGrouping(groupingComboBox.getGroupingModel()))); } }); toolBar.add(new Label(I18N.CONSTANTS.grouping())); toolBar.add(groupingComboBox); toolBar.addButton(UIActions.ADD, I18N.CONSTANTS.newSite(), IconImageBundle.ICONS.add()); toolBar.addButton(UIActions.EDIT, I18N.CONSTANTS.edit(), IconImageBundle.ICONS.edit()); toolBar.addDeleteButton(I18N.CONSTANTS.deleteSite()); toolBar.add(new SeparatorToolItem()); toolBar.addButton(UIActions.OPEN_TABLE, I18N.CONSTANTS.openTable(), IconImageBundle.ICONS.table()); toolBar.add(new SeparatorToolItem()); if (IMPORT_FUNCTION_ENABLED) { toolBar.addImportButton(); } toolBar.addExcelExportButton(); toolBar.addPrintButton(); toolBar.addButton("EMBED", I18N.CONSTANTS.embed(), IconImageBundle.ICONS.embed()); return toolBar; } private void onSiteSelected(final SelectionChangedEvent<SiteDTO> se) { if (se.getSelection().isEmpty()) { onNoSelection(); } else { final SiteDTO site = se.getSelectedItem(); int activityId = site.getActivityId(); dispatcher.execute(new GetActivityForm(activityId), new AsyncCallback<ActivityFormDTO>() { @Override public void onFailure(Throwable caught) { // TODO Auto-generated method stub } @Override public void onSuccess(ActivityFormDTO activity) { updateSelection(activity, site); } }); } } private void updateSelection(ActivityFormDTO activity, SiteDTO site) { boolean permissionToEdit = activity.isAllowedToEdit(site); toolBar.setActionEnabled(UIActions.EDIT, permissionToEdit && !site.isLinked()); toolBar.setActionEnabled(UIActions.DELETE, permissionToEdit && !site.isLinked()); toolBar.setActionEnabled(UIActions.OPEN_TABLE, site != null); detailTab.setSite(site); attachmentsTab.setSite(site); if (activity.getReportingFrequency() == ActivityFormDTO.REPORT_MONTHLY) { monthlyPanel.load(site); monthlyPanel.setReadOnly(!permissionToEdit); monthlyTab.setEnabled(true); } else { monthlyTab.setEnabled(false); if (tabPanel.getSelectedItem() == monthlyTab) { tabPanel.setSelection(detailTab); } } siteHistoryTab.setSite(site); } private void onNoSelection() { toolBar.setActionEnabled(UIActions.EDIT, false); toolBar.setActionEnabled(UIActions.DELETE, false); toolBar.setActionEnabled(UIActions.OPEN_TABLE, false); monthlyPanel.onNoSelection(); } @Override public void shutdown() { // TODO Auto-generated method stub } @Override public PageId getPageId() { return PAGE_ID; } @Override public Object getWidget() { return this; } @Override public void requestToNavigateAway(PageState place, NavigationCallback callback) { callback.onDecided(true); } @Override public String beforeWindowCloses() { return null; } @Override public boolean navigate(PageState place) { currentPlace = (DataEntryPlace) place; if (!currentPlace.getFilter().isRestricted(DimensionType.Activity) && !currentPlace.getFilter().isRestricted(DimensionType.Database)) { redirectToFirstActivity(); } else { doNavigate(); } return true; } private void redirectToFirstActivity() { dispatcher.execute(new GetSchema(), new AsyncCallback<SchemaDTO>() { @Override public void onFailure(Throwable caught) { } @Override public void onSuccess(SchemaDTO result) { for (UserDatabaseDTO db : result.getDatabases()) { if (!db.getActivities().isEmpty()) { currentPlace.getFilter() .addRestriction(DimensionType.Activity, db.getActivities().get(0).getId()); doNavigate(); return; } } } }); } private void doNavigate() { Filter filter = currentPlace.getFilter(); gridPanel.load(currentPlace.getGrouping(), filter); groupingComboBox.setFilter(filter); filterPane.getSet().applyBaseFilter(filter); // currently the print form only does one activity Set<Integer> activities = filter.getRestrictions(DimensionType.Activity); toolBar.setActionEnabled(UIActions.PRINT, activities.size() == 1); // also embedding is only implemented for one activity toolBar.setActionEnabled("EMBED", activities.size() == 1); if (IMPORT_FUNCTION_ENABLED) { toolBar.setActionEnabled(UIActions.IMPORT, activities.size() == 1); } // adding is also only enabled for one activity, but we have to // lookup to see whether it possible for this activity toolBar.setActionEnabled(UIActions.ADD, false); if (activities.size() == 1) { enableToolbarButtons(activities.iterator().next()); } onNoSelection(); } private void enableToolbarButtons(final int activityId) { dispatcher.execute(new GetSchema(), new AsyncCallback<SchemaDTO>() { @Override public void onFailure(Throwable caught) { } @Override public void onSuccess(SchemaDTO result) { boolean isAllowed = result.getActivityById(activityId).isEditAllowed(); toolBar.setActionEnabled(UIActions.ADD, isAllowed); if (IMPORT_FUNCTION_ENABLED) { toolBar.setActionEnabled("IMPORT", isAllowed); } } }); } @Override public void onUIAction(String actionId) { if (UIActions.ADD.equals(actionId)) { SiteDialogLauncher formHelper = new SiteDialogLauncher(dispatcher, eventBus); formHelper.addSite(currentPlace.getFilter(), new SiteDialogCallback() { @Override public void onSaved() { gridPanel.refresh(); } }); } else if (UIActions.EDIT.equals(actionId)) { final SiteDTO selection = gridPanel.getSelection(); SiteDialogLauncher launcher = new SiteDialogLauncher(dispatcher, eventBus); launcher.editSite(selection, new SiteDialogCallback() { @Override public void onSaved() { gridPanel.refresh(); } }); }else if (UIActions.OPEN_TABLE.equals(actionId)) { final SiteDTO selection = gridPanel.getSelection(); eventBus.fireEvent(new NavigationEvent( NavigationHandler.NAVIGATION_REQUESTED, new InstancePlace(selection.getFormClassId(), InstancePage.TABLE_PAGE_ID))); } else if (UIActions.DELETE.equals(actionId)) { MessageBox.confirm(ClientContext.getAppTitle(), I18N.MESSAGES.confirmDeleteSite(), new Listener<MessageBoxEvent>() { @Override public void handleEvent(MessageBoxEvent be) { if (be.getButtonClicked().getItemId().equals(Dialog.YES)) { delete(); } } }); } else if (UIActions.PRINT.equals(actionId)) { int activityId = currentPlace.getFilter().getRestrictedCategory(DimensionType.Activity); PrintDataEntryForm form = new PrintDataEntryForm(dispatcher); form.print(activityId); } else if (UIActions.EXPORT.equals(actionId)) { ExportDialog dialog = new ExportDialog(dispatcher); dialog.exportSites(currentPlace.getFilter()); } else if ("EMBED".equals(actionId)) { EmbedDialog dialog = new EmbedDialog(dispatcher); dialog.show(currentPlace); } else if (IMPORT_FUNCTION_ENABLED && UIActions.IMPORT.equals(actionId)) { doImport(); } } protected void doImport() { final int activityId = currentPlace.getFilter().getRestrictedCategory(DimensionType.Activity); final ResourceLocatorAdaptor resourceLocator = new ResourceLocatorAdaptor(dispatcher); ImportPresenter.showPresenter(CuidAdapter.activityFormClass(activityId), resourceLocator) .then(new SuccessCallback<ImportPresenter>() { @Override public void onSuccess(ImportPresenter result) { result.show(); } }); } private void delete() { dispatcher.execute(new DeleteSite(gridPanel.getSelection().getId()), new MaskingAsyncMonitor(this, I18N.CONSTANTS.deleting()), new AsyncCallback<VoidResult>() { @Override public void onFailure(Throwable caught) { // handled by monitor } @Override public void onSuccess(VoidResult result) { gridPanel.refresh(); } }); } }