package org.sigmah.client.ui.presenter.admin.models.project;
/*
* #%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.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.RequestParameter;
import org.sigmah.client.ui.notif.ConfirmCallback;
import org.sigmah.client.ui.notif.N10N;
import org.sigmah.client.ui.presenter.admin.models.base.IsModelTabPresenter;
import org.sigmah.client.ui.presenter.base.AbstractPresenter;
import org.sigmah.client.ui.view.admin.models.project.PhaseModelsAdminView;
import org.sigmah.client.ui.view.base.ViewInterface;
import org.sigmah.client.ui.widget.HasGrid;
import org.sigmah.client.ui.widget.HasGrid.GridEventHandler;
import org.sigmah.client.ui.widget.button.Button;
import org.sigmah.client.util.ClientUtils;
import org.sigmah.shared.command.Delete;
import org.sigmah.shared.command.result.VoidResult;
import org.sigmah.shared.dto.PhaseModelDTO;
import org.sigmah.shared.dto.ProjectModelDTO;
import com.extjs.gxt.ui.client.event.ButtonEvent;
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.google.inject.ImplementedBy;
import com.google.inject.Inject;
/**
* Phase models administration presenter that manages the {@link PhaseModelsAdminView}.
*
* @author Denis Colliot (dcolliot@ideia.fr)
*/
public class PhaseModelsAdminPresenter extends AbstractPresenter<PhaseModelsAdminPresenter.View>
implements
IsModelTabPresenter<ProjectModelDTO, PhaseModelsAdminPresenter.View> {
/**
* Description of the view managed by this presenter.
*/
@ImplementedBy(PhaseModelsAdminView.class)
public static interface View extends ViewInterface, HasGrid<PhaseModelDTO> {
Button getAddButton();
Button getDeleteButton();
void setToolbarEnabled(boolean enabled);
}
/**
* The provided current model.
*/
private ProjectModelDTO currentModel;
/**
* Presenter's initialization.
*
* @param view
* The view managed by this presenter.
* @param injector
* The application injector.
*/
@Inject
public PhaseModelsAdminPresenter(final View view, final Injector injector) {
super(view, injector);
}
/**
* {@inheritDoc}
*/
@Override
public void onBind() {
// --
// Grid events handler.
// --
view.setGridEventHandler(new GridEventHandler<PhaseModelDTO>() {
@Override
public void onRowClickEvent(final PhaseModelDTO rowElement) {
eventBus.navigateRequest(Page.ADMIN_EDIT_PHASE_MODEL.request().addData(RequestParameter.DTO, rowElement)
.addData(RequestParameter.CONTENT, view.getStore().getModels()).addData(RequestParameter.MODEL, currentModel));
}
});
// --
// Grid selection change handler.
// --
view.getGrid().getSelectionModel().addSelectionChangedListener(new SelectionChangedListener<PhaseModelDTO>() {
@Override
public void selectionChanged(final SelectionChangedEvent<PhaseModelDTO> event) {
final boolean singleSelection = ClientUtils.isNotEmpty(event.getSelection()) && event.getSelection().size() == 1;
view.getDeleteButton().setEnabled(singleSelection && currentModel.isEditable());
}
});
// --
// Add button handler.
// --
view.getAddButton().addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(final ButtonEvent event) {
eventBus.navigateRequest(Page.ADMIN_EDIT_PHASE_MODEL.request().addData(RequestParameter.MODEL, currentModel));
}
});
// --
// Delete button handler.
// --
view.getDeleteButton().addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(final ButtonEvent event) {
onDeleteAction(view.getGrid().getSelectionModel().getSelectedItem());
}
});
// --
// On phase model creation/update event.
// --
registerHandler(eventBus.addHandler(UpdateEvent.getType(), new UpdateHandler() {
@Override
public void onUpdate(final UpdateEvent event) {
if (event.concern(UpdateEvent.PHASE_MODEL_UPDATE)) {
final ProjectModelDTO projectModel = event.getParam(0);
loadTab(projectModel);
}
}
}));
}
/**
* {@inheritDoc}
*/
@Override
public String getTabTitle() {
return I18N.CONSTANTS.adminProjectModelPhases();
}
/**
* {@inheritDoc}
*/
@Override
public void loadTab(final ProjectModelDTO model) {
this.currentModel = model;
view.setToolbarEnabled(currentModel.isEditable());
// --
// Populating the store and initializing phase models 'root' property.
// --
view.getStore().removeAll();
final PhaseModelDTO rootPhase = model.getRootPhaseModel();
for (final PhaseModelDTO phaseModel : model.getPhaseModels()) {
phaseModel.setRoot(rootPhase != null && rootPhase.equals(phaseModel));
view.getStore().add(phaseModel);
}
view.getStore().commitChanges();
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasValueChanged() {
return false;
}
// ---------------------------------------------------------------------------------------------------------------
//
// UTILITY METHODS.
//
// ---------------------------------------------------------------------------------------------------------------
/**
* Callback executed on delete button action.
*
* @param phaseModel
* The selected phase model to delete.
*/
private void onDeleteAction(final PhaseModelDTO phaseModel) {
if (currentModel == null || phaseModel == null) {
return;
}
// Only a phase model within a project model in 'DRAFT' status is allowed to be deleted.
if (!currentModel.isEditable()) {
return;
}
// Cannot delete root phase model.
if (currentModel.getRootPhaseModel() != null) {
if (currentModel.getRootPhaseModel().getId().equals(phaseModel.getId())) {
N10N.warn(I18N.CONSTANTS.deletionError(), I18N.CONSTANTS.deleteRootPhaseModelError());
return;
}
}
final String confirmMessageDetials;
if (currentModel.getPhaseModels() == null || currentModel.getPhaseModels().size() == 1) {
// Cannot delete the last phase model.
confirmMessageDetials = I18N.CONSTANTS.deleteRootPhaseModelConfirm();
} else {
confirmMessageDetials = I18N.CONSTANTS.deletePhaseModelConfirm();
}
N10N.confirmation(I18N.CONSTANTS.deleteConfirm(), confirmMessageDetials, new ConfirmCallback() {
@Override
public void onAction() {
dispatch.execute(new Delete(PhaseModelDTO.ENTITY_NAME, phaseModel.getId()), new CommandResultHandler<VoidResult>() {
@Override
public void onCommandFailure(final Throwable caught) {
N10N.error(I18N.CONSTANTS.deletionError(), I18N.MESSAGES.entityDeleteEventError(phaseModel.getName()));
}
@Override
public void onCommandSuccess(final VoidResult result) {
// Updates the phase models store.
updateStore(phaseModel);
// Updates the current project model.
currentModel.getPhaseModels().clear();
currentModel.getPhaseModels().addAll(view.getStore().getModels());
// Shows notification.
N10N.infoNotif(I18N.CONSTANTS.deleteConfirm(), I18N.CONSTANTS.adminPhaseModelDeleteDetail());
}
});
}
});
}
/**
* Updates the phase models store after a model is deleted.<br>
* Removes the given deleted {@code phaseModel} and updates the entire store's successors.
*
* @param phaseModelDeleted
* The deleted phase model.
*/
private void updateStore(final PhaseModelDTO phaseModelDeleted) {
view.getStore().remove(phaseModelDeleted);
// Check if the deleted model is other phase models' successors,if so, delete that relation
for (final PhaseModelDTO phaseModel : view.getStore().getModels()) {
if (ClientUtils.isEmpty(phaseModel.getSuccessors())) {
continue;
}
if (phaseModel.getSuccessors().contains(phaseModelDeleted)) {
phaseModel.getSuccessors().remove(phaseModelDeleted);
view.getStore().update(phaseModel);
}
}
view.getStore().commitChanges();
}
}