package org.sigmah.client.ui.presenter.admin.users;
/*
* #%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 com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.form.ComboBox;
import com.extjs.gxt.ui.client.widget.form.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.sigmah.client.dispatch.CommandResultHandler;
import org.sigmah.client.event.UpdateEvent;
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.N10N;
import org.sigmah.client.ui.presenter.base.AbstractPagePresenter;
import org.sigmah.client.ui.view.admin.users.UserEditView;
import org.sigmah.client.ui.view.base.ViewInterface;
import org.sigmah.client.ui.widget.button.Button;
import org.sigmah.client.ui.widget.form.FormPanel;
import org.sigmah.client.util.ClientUtils;
import org.sigmah.client.util.EnumModel;
import org.sigmah.shared.Language;
import org.sigmah.shared.command.CreateEntity;
import org.sigmah.shared.command.GetContact;
import org.sigmah.shared.command.GetContactModels;
import org.sigmah.shared.command.GetContacts;
import org.sigmah.shared.command.GetOrgUnits;
import org.sigmah.shared.command.GetProfiles;
import org.sigmah.shared.command.GetUserUnitsByUser;
import org.sigmah.shared.command.result.CreateResult;
import org.sigmah.shared.command.result.ListResult;
import org.sigmah.shared.command.result.UserUnitsResult;
import org.sigmah.shared.dto.ContactDTO;
import org.sigmah.shared.dto.ContactModelDTO;
import org.sigmah.shared.dto.UserDTO;
import org.sigmah.shared.dto.UserUnitDTO;
import org.sigmah.shared.dto.orgunit.OrgUnitDTO;
import org.sigmah.shared.dto.orgunit.OrgUnitDTO.Mode;
import org.sigmah.shared.dto.profile.ProfileDTO;
import org.sigmah.shared.dto.referential.ContactModelType;
/**
* Admin user create/edit Presenter
*
* @author Mehdi Benabdeslam (mehdi.benabdeslam@netapsys.fr) v2.0
* @author Denis Colliot (dcolliot@ideia.fr) (v2.0)
*/
@Singleton
public class UserEditPresenter extends AbstractPagePresenter<UserEditPresenter.View> {
/**
* The view interface managed by this presenter.
*/
@ImplementedBy(UserEditView.class)
public static interface View extends ViewInterface {
/**
* Clears the view form.
*/
void clearForm();
ComboBox<EnumModel<Language>> getLanguageField();
Field<String> getEmailField();
Field<Object> getChangePwdLink();
Field<String> getPwdField();
Field<String> getFirstNameField();
Field<String> getNameField();
ComboBox<ContactDTO> getContactOrganizationField();
ComboBox<ContactModelDTO> getContactModelField();
FormPanel getForm();
Button getCreateButton();
ListStore<UserUnitDTO> getUserUnitStore();
Button getAddUserUnitButton();
void setAvailableOrgUnits(List<OrgUnitDTO> orgUnits);
void setAvailableProfiles(List<ProfileDTO> profiles);
void attachProfileHandler(UserUnitActionHandler userUnitActionHandler);
}
public interface UserUnitActionHandler {
void onAddProfile(UserUnitDTO userUnitDTO, ProfileDTO profileDTO);
void onRemoveProfile(UserUnitDTO userUnitDTO, ProfileDTO profileDTO);
void onRemoveUserUnit(UserUnitDTO userUnitDTO);
}
/**
* The edited user.<br>
* Set to {@code null} in case of creation.
*/
private UserDTO user;
/**
* The contact from which the user should be created.
*/
private ContactDTO contact;
/**
* Presenter's initialization.
*
* @param view
* The view.
* @param injector
* The application injector.
*/
@Inject
protected UserEditPresenter(View view, Injector injector) {
super(view, injector);
}
/**
* {@inheritDoc}
*/
@Override
public Page getPage() {
return Page.ADMIN_USER_EDIT;
}
/**
* {@inheritDoc}
*/
@Override
public void onBind() {
// --
// Create button event handler.
// --
view.getCreateButton().addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(final ButtonEvent event) {
onCreateUser();
}
});
// --
// Add profile button event handler.
// --
view.getAddUserUnitButton().addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent event) {
UserUnitDTO userUnit = new UserUnitDTO();
// If this UserUnit is the first one, he is considered as the main UserUnit
userUnit.setMainUserUnit(view.getUserUnitStore().getCount() == 0);
userUnit.setProfiles(new ArrayList<ProfileDTO>());
view.getUserUnitStore().add(userUnit);
}
});
view.attachProfileHandler(new UserUnitActionHandler() {
@Override
public void onAddProfile(UserUnitDTO userUnit, ProfileDTO profileDTO) {
userUnit.getProfiles().add(profileDTO);
}
@Override
public void onRemoveProfile(UserUnitDTO userUnit, ProfileDTO profileDTO) {
userUnit.getProfiles().remove(profileDTO);
}
@Override
public void onRemoveUserUnit(UserUnitDTO userUnitDTO) {
view.getUserUnitStore().remove(userUnitDTO);
}
});
}
/**
* {@inheritDoc}
*/
@Override
public void onPageRequest(final PageRequest request) {
view.clearForm();
setPageTitle(I18N.CONSTANTS.newUser());
view.getUserUnitStore().removeAll();
user = request.getData(RequestParameter.DTO);
Integer contactId = request.getParameterInteger(RequestParameter.CONTACT_ID);
if (contactId != null) {
dispatch.execute(new GetContact(contactId, ContactDTO.Mode.BASIC_INFORMATION), new CommandResultHandler<ContactDTO>() {
@Override
protected void onCommandSuccess(ContactDTO contact) {
UserEditPresenter.this.contact = contact;
view.getNameField().setValue(contact.getName());
view.getFirstNameField().setValue(contact.getFirstname());
view.getEmailField().setValue(contact.getEmail());
view.getContactOrganizationField().setReadOnly(true);
view.getContactModelField().setReadOnly(true);
loadData();
}
});
} else {
loadData();
}
if (user == null) {
view.getContactModelField().setReadOnly(false);
view.getContactOrganizationField().setReadOnly(false);
// Creation mode.
return;
}
// Edition mode.
view.getNameField().setValue(user.getName());
view.getFirstNameField().setValue(user.getFirstName());
view.getEmailField().setValue(user.getEmail());
view.getChangePwdLink().setVisible(true);
view.getLanguageField().setValue(new EnumModel<Language>(Language.fromString(user.getLocale())));
// Contact fields are only editable when creating a user
view.getContactModelField().setReadOnly(true);
view.getContactOrganizationField().setReadOnly(true);
if (user.getMainOrgUnit() != null && ClientUtils.isNotBlank(user.getMainOrgUnit().getFullName())) {
final OrgUnitDTO orgUnitDTOLight = new OrgUnitDTO();
orgUnitDTOLight.setId(user.getMainOrgUnit().getId());
orgUnitDTOLight.setFullName(user.getMainOrgUnit().getFullName());
}
dispatch.execute(new GetUserUnitsByUser(user.getId(), Mode.WITH_TREE), new CommandResultHandler<UserUnitsResult>() {
@Override
protected void onCommandSuccess(UserUnitsResult result) {
if (result.getMainUserUnit() != null) {
view.getUserUnitStore().add(result.getMainUserUnit());
}
if (result.getSecondaryUserUnits() != null) {
view.getUserUnitStore().add(result.getSecondaryUserUnits());
}
}
});
}
private void loadData() {
// --
// Loads org units.
// --
dispatch.execute(new GetOrgUnits(Mode.WITH_TREE), new CommandResultHandler<ListResult<OrgUnitDTO>>() {
@Override
public void onCommandFailure(final Throwable caught) {
N10N.error(I18N.CONSTANTS.adminChoiceProblem());
}
@Override
public void onCommandSuccess(final ListResult<OrgUnitDTO> result) {
List<OrgUnitDTO> orgUnitDTOs = new ArrayList<OrgUnitDTO>();
for (OrgUnitDTO orgUnitDTO : result.getData()) {
orgUnitDTOs.addAll(crawlOrgUnits(orgUnitDTO));
}
view.setAvailableOrgUnits(orgUnitDTOs);
if (contact != null && contact.getMainOrgUnit() != null) {
UserUnitDTO userUnitDTO = new UserUnitDTO();
userUnitDTO.setMainUserUnit(true);
userUnitDTO.setOrgUnit(contact.getMainOrgUnit());
userUnitDTO.setProfiles(new ArrayList<ProfileDTO>());
view.getUserUnitStore().add(userUnitDTO);
for (OrgUnitDTO orgUnitDTO : contact.getSecondaryOrgUnits()) {
userUnitDTO = new UserUnitDTO();
userUnitDTO.setMainUserUnit(false);
userUnitDTO.setOrgUnit(orgUnitDTO);
userUnitDTO.setProfiles(new ArrayList<ProfileDTO>());
view.getUserUnitStore().add(userUnitDTO);
}
}
}
});
// --
// Loads profiles.
// --
dispatch.execute(new GetProfiles(ProfileDTO.Mode.BASE), new CommandResultHandler<ListResult<ProfileDTO>>() {
@Override
public void onCommandFailure(final Throwable arg0) {
N10N.error(I18N.CONSTANTS.adminChoiceProblem());
}
@Override
public void onCommandSuccess(final ListResult<ProfileDTO> result) {
if (result != null) {
view.setAvailableProfiles(result.getList());
}
}
});
// --
// Loads contact organizations
// --
dispatch.execute(new GetContacts(ContactModelType.ORGANIZATION), new AsyncCallback<ListResult<ContactDTO>>() {
@Override
public void onFailure(Throwable throwable) {
N10N.error(I18N.CONSTANTS.adminChoiceProblem());
}
@Override
public void onSuccess(ListResult<ContactDTO> result) {
if (result == null) {
return;
}
view.getContactOrganizationField().setValue(null);
view.getContactOrganizationField().getStore().removeAll();
view.getContactOrganizationField().getStore().add(result.getList());
ContactDTO userContact = contact;
if (user != null) {
userContact = user.getContact();
}
// Let's find the default contact
for (ContactDTO contactDTO : result.getList()) {
if (userContact != null) {
// Let's find the user contact
if (contactDTO.getId().equals(userContact.getParent().getId())) {
view.getContactOrganizationField().setValue(contactDTO);
return;
}
continue;
}
if (contactDTO.getOrganizationId() != null) {
// This contact is related to an Organization so let's make it the default value
view.getContactOrganizationField().setValue(contactDTO);
return;
}
}
}
});
// --
// Loads contact models
// --
dispatch.execute(new GetContactModels(ContactModelType.INDIVIDUAL, true), new AsyncCallback<ListResult<ContactModelDTO>>() {
@Override
public void onFailure(Throwable throwable) {
N10N.error(I18N.CONSTANTS.adminChoiceProblem());
}
@Override
public void onSuccess(ListResult<ContactModelDTO> result) {
if (result == null) {
return;
}
view.getContactModelField().setValue(null);
view.getContactModelField().getStore().removeAll();
view.getContactModelField().getStore().add(result.getList());
ContactDTO userContact = contact;
if (user != null) {
userContact = user.getContact();
}
// Let's find the default contact model
// The contact model with the smallest id can be considered as the default one
Integer minId = null;
for (ContactModelDTO contactModelDTO : result.getList()) {
if (userContact != null) {
if (contactModelDTO.getId().equals(userContact.getContactModel().getId())) {
view.getContactModelField().setValue(contactModelDTO);
return;
}
continue;
}
if (minId != null && minId <= contactModelDTO.getId()) {
continue;
}
minId = contactModelDTO.getId();
view.getContactModelField().setValue(contactModelDTO);
}
}
});
}
// ---------------------------------------------------------------------------------------------------------------
//
// UTILITY METHODS.
//
// ---------------------------------------------------------------------------------------------------------------
/**
* Method executed on user creation or edition.
*/
private void onCreateUser() {
if (!view.getForm().isValid()) {
return;
}
// --
// Collects form fields values.
// --
final String name = view.getNameField().getValue();
final String firstName = view.getFirstNameField().getValue();
final String email = view.getEmailField().getValue().trim();
final Integer contactModelId = view.getContactModelField().getValue().getId();
final Integer contactOrganizationId = view.getContactOrganizationField().getValue().getId();
// Gets the value only if the admin wants to change the password.
final String password = view.getPwdField().isVisible() ? view.getPwdField().getValue() : null;
final EnumModel<Language> languageValue = view.getLanguageField().getValue();
// --
// Validates specific form data.
// --
final MatchResult matcher = ClientUtils.EMAIL_CLIENT_REGEXP.exec(email);
if (matcher == null) {
N10N.warn(I18N.CONSTANTS.createFormIncomplete(), I18N.MESSAGES.invalidEmailAddress());
return;
}
UserUnitDTO mainUserUnit = view.getUserUnitStore().findModel(UserUnitDTO.MAIN_USER_UNIT, true);
if (mainUserUnit == null || mainUserUnit.getProfiles().isEmpty()) {
N10N.warn(I18N.CONSTANTS.createFormIncomplete(), I18N.MESSAGES.createUserFormIncompleteDetails());
return;
}
List<UserUnitDTO> secondaryUserUnits = view.getUserUnitStore().findModels(UserUnitDTO.MAIN_USER_UNIT, false);
for (UserUnitDTO unit : secondaryUserUnits) {
if (unit.getProfiles().isEmpty()) {
N10N.warn(I18N.CONSTANTS.createFormIncomplete(), I18N.MESSAGES.createUserFormIncompleteDetails());
return;
}
}
UserUnitsResult userUnitsResult = new UserUnitsResult();
userUnitsResult.setMainUserUnit(mainUserUnit);
userUnitsResult.setSecondaryUserUnits(secondaryUserUnits);
// --
// Executes command process.
// --
final Map<String, Object> userProperties = new HashMap<String, Object>();
userProperties.put(UserDTO.ID, user != null ? user.getId() : null);
userProperties.put(UserDTO.NAME, name);
userProperties.put(UserDTO.FIRST_NAME, firstName);
userProperties.put(UserDTO.PASSWORD, password);
userProperties.put(UserDTO.EMAIL, email);
userProperties.put(UserDTO.LOCALE, languageValue.getEnum());
userProperties.put(UserDTO.USER_UNITS, userUnitsResult);
userProperties.put(UserDTO.CONTACT_MODEL, contactModelId);
userProperties.put(UserDTO.CONTACT_ORGANIZATION, contactOrganizationId);
userProperties.put(UserDTO.CONTACT, contact != null ? contact.getId() : null);
dispatch.execute(new CreateEntity(UserDTO.ENTITY_NAME, userProperties), new CommandResultHandler<CreateResult>() {
@Override
public void onCommandFailure(final Throwable caught) {
N10N.warn(I18N.CONSTANTS.adminUserCreationBox(), I18N.MESSAGES.adminUserCreationFailure(firstName + ' ' + name));
}
@Override
public void onCommandSuccess(final CreateResult result) {
eventBus.fireEvent(new UpdateEvent(UpdateEvent.USER_UPDATE));
if (user != null) {
N10N.infoNotif(I18N.CONSTANTS.adminUserCreationBox(), I18N.MESSAGES.adminUserUpdateSuccess(name));
} else {
N10N.infoNotif(I18N.CONSTANTS.adminUserCreationBox(), I18N.MESSAGES.adminUserCreationSuccess(name));
}
hideView();
}
}, view.getCreateButton());
}
/**
* Fills recursively the units field with the children of the given org {@code unit}.
*/
private List<OrgUnitDTO> crawlOrgUnits(OrgUnitDTO unit) {
List<OrgUnitDTO> orgUnits = new ArrayList<OrgUnitDTO>();
orgUnits.add(unit);
for (final OrgUnitDTO child : unit.getChildrenOrgUnits()) {
orgUnits.addAll(crawlOrgUnits(child));
}
return orgUnits;
}
}