package org.sigmah.client.ui.presenter.admin.orgunits;
/*
* #%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 org.sigmah.client.cache.UserLocalCache;
import org.sigmah.client.dispatch.CommandResultHandler;
import org.sigmah.client.event.UpdateEvent;
import org.sigmah.client.event.handler.UpdateHandler;
import org.sigmah.client.i18n.I18N;
import org.sigmah.client.inject.Injector;
import org.sigmah.client.page.Page;
import org.sigmah.client.page.PageRequest;
import org.sigmah.client.page.RequestParameter;
import org.sigmah.client.ui.notif.ConfirmCallback;
import org.sigmah.client.ui.notif.N10N;
import org.sigmah.client.ui.presenter.admin.AbstractAdminPresenter;
import org.sigmah.client.ui.view.admin.orgunits.OrgUnitsAdminView;
import org.sigmah.client.ui.widget.HasTreeGrid;
import org.sigmah.client.ui.widget.HasTreeGrid.TreeGridEventHandler;
import org.sigmah.client.ui.widget.button.Button;
import org.sigmah.shared.command.RemoveOrgUnit;
import org.sigmah.shared.command.result.VoidResult;
import org.sigmah.shared.dispatch.FunctionalException;
import org.sigmah.shared.dto.organization.OrganizationDTO;
import org.sigmah.shared.dto.orgunit.OrgUnitDTO;
import com.allen_sauer.gwt.log.client.Log;
import com.extjs.gxt.ui.client.event.BaseEvent;
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.event.SelectionChangedEvent;
import com.extjs.gxt.ui.client.event.SelectionChangedListener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.widget.Component;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/**
* Admin OrgUnits Presenter which manages {@link OrgUnitsAdminView}.
*
* @author Maxime Lombard (mlombard@ideia.fr)
* @author Denis Colliot (dcolliot@ideia.fr)
*/
@SuppressWarnings("deprecation")
@Singleton
public class OrgUnitsAdminPresenter extends AbstractAdminPresenter<OrgUnitsAdminPresenter.View> {
/**
* Description of the view managed by this presenter.
*/
@ImplementedBy(OrgUnitsAdminView.class)
public static interface View extends AbstractAdminPresenter.View, HasTreeGrid<OrgUnitDTO> {
Button getAddButton();
Button getMoveButton();
Button getRemoveButton();
Component getMainPanel();
}
/**
* Tree grid refresh delay (in milliseconds).<br>
* This delay is a 'trick' to make the tree grid refresh work.
*/
private static final int REFRESH_DELAY = 2000;
/**
* The client-side local cache.
*/
private final UserLocalCache localCache;
/**
* Presenters's initialization.
*
* @param view
* Presenter's view interface.
* @param injector
* Injected client injector.
*/
@Inject
protected OrgUnitsAdminPresenter(View view, Injector injector) {
super(view, injector);
this.localCache = injector.getClientCache();
}
/**
* {@inheritDoc}
*/
@Override
public Page getPage() {
return Page.ADMIN_ORG_UNITS;
}
/**
* {@inheritDoc}
*/
@Override
public void onBind() {
// --
// Grid name cell handler.
// --
view.setTreeGridEventHandler(new TreeGridEventHandler<OrgUnitDTO>() {
@Override
public void onRowClickEvent(final OrgUnitDTO rowElement) {
if (rowElement == null) {
return;
}
eventBus.navigateRequest(Page.ORGUNIT_DASHBOARD.requestWith(RequestParameter.ID, rowElement.getId()));
}
});
// --
// On OrgUnit creation/move event.
// --
registerHandler(eventBus.addHandler(UpdateEvent.getType(), new UpdateHandler() {
@Override
public void onUpdate(final UpdateEvent event) {
if (event.concern(UpdateEvent.ORG_UNIT_UPDATE)) {
refreshCache();
}
}
}));
// --
// Add button handler.
// --
view.getAddButton().addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(final ButtonEvent be) {
final OrgUnitDTO parent = view.getTreeGrid().getSelectionModel().getSelectedItem();
if (parent == null) {
return;
}
eventBus.navigateRequest(Page.ADMIN_ADD_ORG_UNIT.requestWith(RequestParameter.ID, parent.getId()));
}
});
// --
// Move button handler.
// --
view.getMoveButton().addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(final ButtonEvent be) {
final OrgUnitDTO moved = view.getTreeGrid().getSelectionModel().getSelectedItem();
if (moved == null) {
return;
}
eventBus.navigateRequest(Page.ADMIN_MOVE_ORG_UNIT.request().addData(RequestParameter.DTO, moved));
}
});
// --
// Delete button handler.
// --
view.getRemoveButton().addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(final ButtonEvent be) {
final OrgUnitDTO toDelete = view.getTreeGrid().getSelectionModel().getSelectedItem();
if (toDelete == null) {
return;
}
onDeleteAction(toDelete);
}
});
// --
// Tree grid selection change handler.
// --
view.getTreeGrid().getSelectionModel().addSelectionChangedListener(new SelectionChangedListener<OrgUnitDTO>() {
@Override
public void selectionChanged(final SelectionChangedEvent<OrgUnitDTO> se) {
onSelectionChange(se.getSelectedItem());
}
});
// --
// Tree grid attach listener handler.
// --
view.getTreeGrid().addListener(Events.Attach, new Listener<BaseEvent>() {
@Override
public void handleEvent(final BaseEvent be) {
view.getTreeGrid().expandAll();
}
});
}
/**
* {@inheritDoc}
*/
@Override
public void onPageRequest(final PageRequest request) {
view.getAddButton().setEnabled(false);
view.getMoveButton().setEnabled(false);
view.getRemoveButton().setEnabled(false);
refreshTree();
}
// ---------------------------------------------------------------------------------------------------------------
//
// UTILITY METHODS.
//
// ---------------------------------------------------------------------------------------------------------------
/**
* Callback executed on tree grid selection change.
*
* @param selection
* The new selected item.
*/
private void onSelectionChange(final OrgUnitDTO selection) {
final boolean addEnabled = selection != null;
final boolean moveEnabled = selection != null;
final boolean removeEnabled = selection != null && selection.getParent() != null && selection.getChildCount() == 0;
view.getAddButton().setEnabled(addEnabled);
view.getMoveButton().setEnabled(moveEnabled);
view.getRemoveButton().setEnabled(removeEnabled);
view.getRemoveButton().setTitle(" ");
view.getRemoveButton().removeToolTip();
if (!removeEnabled && selection != null) {
if (selection.getParent() == null) {
view.getRemoveButton().setTitle(I18N.CONSTANTS.adminOrgUnitRemoveIsRoot());
} else if (selection.getChildCount() != 0) {
view.getRemoveButton().setTitle(I18N.CONSTANTS.adminOrgUnitRemoveHasChildren());
}
}
}
/**
* Refreshes the local organization cache.<br>
* Once it has been refreshed, refreshes the orgunits tree grid.
*/
private void refreshCache() {
localCache.refreshOrganization(new AsyncCallback<OrganizationDTO>() {
@Override
public void onFailure(final Throwable caught) {
refreshTree();
}
@Override
public void onSuccess(final OrganizationDTO result) {
refreshTree();
}
});
}
/**
* Refreshes the OrgUnits tree grid.
*/
private void refreshTree() {
// Gets user's organization.
localCache.getOrganizationCache().get(new AsyncCallback<OrgUnitDTO>() {
@Override
public void onFailure(final Throwable e) {
if (Log.isErrorEnabled()) {
Log.error("An error occured while refreshing the org units tree grid.", e);
}
// Digest.
}
@Override
public void onSuccess(final OrgUnitDTO result) {
if (result == null) {
return;
}
view.getStore().removeAll();
view.getStore().add(result, true);
view.getTreeGrid().expandAll();
new Timer() {
@Override
public void run() {
view.getTreeGrid().expandAll();
}
}.schedule(REFRESH_DELAY);
}
});
}
/**
* Callback executed on delete event.
*
* @param removed
* The selected item to remove.
*/
private void onDeleteAction(final OrgUnitDTO removed) {
N10N.confirmation(I18N.CONSTANTS.adminOrgUnitRemove(), I18N.MESSAGES.adminOrgUnitRemoveConfirm(removed.getName()), new ConfirmCallback() {
@Override
public void onAction() {
if (removed.getChildCount() != 0) {
N10N.warn(I18N.CONSTANTS.adminOrgUnitRemoveUnavailable(), I18N.CONSTANTS.adminOrgUnitRemoveHasChildren());
return;
}
if (removed.getParent() == null) {
N10N.warn(I18N.CONSTANTS.adminOrgUnitRemoveUnavailable(), I18N.CONSTANTS.adminOrgUnitRemoveIsRoot());
return;
}
dispatch.execute(new RemoveOrgUnit(removed.getId()), new CommandResultHandler<VoidResult>() {
@Override
public void onCommandFailure(final Throwable caught) {
N10N.warn(I18N.CONSTANTS.adminOrgUnitRemoveUnavailable(), I18N.CONSTANTS.adminOrgUnitRemoveHasChildrenOrProjects());
refreshCache();
}
@Override
protected void onFunctionalException(final FunctionalException exception) {
super.onFunctionalException(exception);
refreshCache();
}
@Override
public void onCommandSuccess(final VoidResult result) {
N10N.infoNotif(I18N.CONSTANTS.infoConfirmation(), I18N.CONSTANTS.adminOrgUnitRemoveSucceed());
refreshCache();
}
});
}
});
}
}