package org.sigmah.client.ui.view.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 java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.sigmah.client.i18n.I18N;
import org.sigmah.client.ui.presenter.admin.users.UserEditPresenter;
import org.sigmah.client.ui.res.icon.IconImageBundle;
import org.sigmah.client.ui.view.base.AbstractPopupView;
import org.sigmah.client.ui.widget.button.Button;
import org.sigmah.client.ui.widget.button.ClickableLabel;
import org.sigmah.client.ui.widget.form.ComboboxButtonField;
import org.sigmah.client.ui.widget.form.FormPanel;
import org.sigmah.client.ui.widget.form.Forms;
import org.sigmah.client.ui.widget.form.ListComboBox;
import org.sigmah.client.ui.widget.popup.PopupWidget;
import org.sigmah.client.util.ClientUtils;
import org.sigmah.client.util.EnumModel;
import org.sigmah.shared.Language;
import org.sigmah.shared.dto.ContactDTO;
import org.sigmah.shared.dto.ContactModelDTO;
import org.sigmah.shared.dto.UserUnitDTO;
import org.sigmah.shared.dto.orgunit.OrgUnitDTO;
import org.sigmah.shared.dto.profile.ProfileDTO;
import org.sigmah.shared.dto.util.EntityConstants;
import org.sigmah.shared.util.Pair;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.KeyListener;
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.store.ListStore;
import com.extjs.gxt.ui.client.store.StoreEvent;
import com.extjs.gxt.ui.client.store.StoreListener;
import com.extjs.gxt.ui.client.widget.form.ComboBox;
import com.extjs.gxt.ui.client.widget.form.Field;
import com.extjs.gxt.ui.client.widget.form.LabelField;
import com.extjs.gxt.ui.client.widget.form.TextField;
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.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.inject.Singleton;
/**
* Admin Users View
*
* @author Mehdi Benabdeslam (mehdi.benabdeslam@netapsys.fr) v2.0
* @author Denis Colliot (dcolliot@ideia.fr) (v2.0)
*/
@Singleton
public class UserEditView extends AbstractPopupView<PopupWidget> implements UserEditPresenter.View {
// CSS style names.
private static final String STYLE_FLEXIBILITY_ACTION = "flexibility-action";
private FormPanel formPanel;
private TextField<String> nameField;
private TextField<String> firstNameField;
private TextField<String> pwdField;
private TextField<String> checkPwdField;
private LabelField changePwdLink;
private TextField<String> emailField;
private ComboBox<EnumModel<Language>> languageField;
private ComboBox<ContactDTO> contactOrganizationField;
private ComboBox<ContactModelDTO> contactModelField;
private Grid<UserUnitDTO> secondaryUserUnitsGrid;
private List<ListStore<OrgUnitDTO>> orgUnitStores;
private List<OrgUnitDTO> availableOrgUnits = Collections.emptyList();
private List<ListStore<ProfileDTO>> profileStores;
private List<ProfileDTO> availableProfiles = Collections.emptyList();
private Button addUserUnitButton;
private UserEditPresenter.UserUnitActionHandler userUnitActionHandler;
private Button createButton;
/**
* Popup initialization.
*/
public UserEditView() {
super(new PopupWidget(true), 800);
}
/**
* {@inheritDoc}
*/
@Override
public void initialize() {
orgUnitStores = new ArrayList<ListStore<OrgUnitDTO>>();
profileStores = new ArrayList<ListStore<ProfileDTO>>();
// --
// Name field.
// --
nameField = Forms.text(I18N.CONSTANTS.adminUsersName(), true);
// --
// First name field.
// --
firstNameField = Forms.text(I18N.CONSTANTS.adminUsersFirstName(), true);
// --
// Email field.
// --
emailField = Forms.text(I18N.CONSTANTS.adminUsersEmail(), true);
emailField.setRegex(EntityConstants.EMAIL_REGULAR_EXPRESSION);
emailField.getMessages().setRegexText(I18N.MESSAGES.invalidEmailAddress());
// --
// Change password field.
// --
changePwdLink = Forms.label(null);
changePwdLink.setValue(I18N.CONSTANTS.editPassword());
changePwdLink.setHideLabel(true);
changePwdLink.addStyleName(STYLE_FLEXIBILITY_ACTION);
changePwdLink.addListener(Events.OnClick, new Listener<BaseEvent>() {
@Override
public void handleEvent(final BaseEvent event) {
// Display the password fields when the admin wants to change the user's password.
final boolean visibilityState = !pwdField.isVisible();
pwdField.setVisible(visibilityState);
pwdField.setAllowBlank(!visibilityState);
checkPwdField.setVisible(visibilityState);
checkPwdField.setAllowBlank(!visibilityState);
if (pwdField.isVisible()) {
checkPwdField.clearInvalid();
} else if (ClientUtils.isNotBlank(checkPwdField.getValue())) {
if (!checkPwdField.getValue().equals(pwdField.getValue())) {
checkPwdField.forceInvalid(I18N.MESSAGES.pwdMatchProblem());
} else {
checkPwdField.clearInvalid();
}
}
}
});
// --
// Password field.
// --
pwdField = Forms.text(I18N.CONSTANTS.password(), false);
pwdField.hide();
pwdField.setPassword(true);
pwdField.addKeyListener(new KeyListener() {
@Override
public void componentKeyUp(final ComponentEvent event) {
checkPwdField.setAllowBlank(ClientUtils.isBlank(pwdField.getValue()));
}
});
// --
// Check password field.
// --
checkPwdField = Forms.text(I18N.CONSTANTS.confirmPassword(), false);
checkPwdField.hide();
checkPwdField.setPassword(true);
checkPwdField.addKeyListener(new KeyListener() {
@Override
public void componentKeyUp(final ComponentEvent event) {
if (ClientUtils.isNotBlank(checkPwdField.getValue())) {
pwdField.setAllowBlank(false);
if (!checkPwdField.getValue().equals(pwdField.getValue())) {
checkPwdField.forceInvalid(I18N.MESSAGES.pwdMatchProblem());
} else {
checkPwdField.clearInvalid();
}
} else {
pwdField.setAllowBlank(true);
}
}
});
// --
// Contact organization field
// --
contactOrganizationField = Forms.combobox(I18N.CONSTANTS.adminUserContactOrganizationFieldLabel(), false, ContactDTO.ID, ContactDTO.FULLNAME);
// --
// Contact model field
// --
contactModelField = Forms.combobox(I18N.CONSTANTS.adminUserContactModelFieldLabel(), false, ContactModelDTO.ID, ContactModelDTO.NAME);
// --
// Language field.
// --
languageField = Forms.combobox(I18N.CONSTANTS.adminUsersLocale(), true, EnumModel.VALUE_FIELD, EnumModel.DISPLAY_FIELD);
languageField.getStore().add(new EnumModel<Language>(Language.FR));
languageField.getStore().add(new EnumModel<Language>(Language.EN));
languageField.getStore().add(new EnumModel<Language>(Language.ES));
// --
// Hierarchy field
// --
ColumnConfig hierarchyColumnConfig = new ColumnConfig("hierarchy", I18N.CONSTANTS.adminHierarchy(), 150);
hierarchyColumnConfig.setSortable(false);
hierarchyColumnConfig.setRenderer(new GridCellRenderer() {
@Override
public Object render(ModelData modelData, String s, ColumnData columnData, int i, int i1, ListStore listStore, Grid grid) {
return ((UserUnitDTO) modelData).getMainUserUnit() ? I18N.CONSTANTS.adminIsMainOrgUnit() : I18N.CONSTANTS.adminIsSecondaryOrgUnit();
}
});
// --
// OrgUnits field.
// --
final ColumnConfig orgUnitColumnConfig = new ColumnConfig(UserUnitDTO.ORG_UNIT, I18N.CONSTANTS.orgunit(), 500);
orgUnitColumnConfig.setSortable(false);
orgUnitColumnConfig.setRenderer(new GridCellRenderer() {
@Override
public Object render(final ModelData model, String property, ColumnData config, int rowIndex, int colIndex, ListStore store, Grid grid) {
ComboBox<OrgUnitDTO> orgUnitComboBox = Forms.combobox(null, true, OrgUnitDTO.ID, OrgUnitDTO.FULL_NAME,
I18N.CONSTANTS.adminUserCreationOrgUnitChoice(), new ListStore<OrgUnitDTO>());
orgUnitComboBox.getStore().add(availableOrgUnits);
OrgUnitDTO orgUnit = ((UserUnitDTO) model).getOrgUnit();
if (orgUnit != null) {
orgUnitComboBox.setValue(orgUnit);
}
orgUnitStores.add(orgUnitComboBox.getStore());
orgUnitComboBox.addSelectionChangedListener(new SelectionChangedListener<OrgUnitDTO>() {
@Override
public void selectionChanged(SelectionChangedEvent<OrgUnitDTO> event) {
((UserUnitDTO) model).setOrgUnit(event.getSelectedItem());
}
});
return orgUnitComboBox;
}
});
// --
// Profiles adapter field.
// --
ColumnConfig profilesColumnConfig = new ColumnConfig(UserUnitDTO.PROFILES, I18N.CONSTANTS.adminProfiles(), 500);
profilesColumnConfig.setSortable(false);
profilesColumnConfig.setRenderer(new GridCellRenderer() {
@Override
public Object render(final ModelData model, String property, ColumnData config, int rowIndex, int colIndex, ListStore store, Grid grid) {
final ListComboBox<ProfileDTO> profileListComboBox = new ListComboBox<ProfileDTO>(ProfileDTO.ID, ProfileDTO.NAME);
List<ProfileDTO> profiles = model.get(property);
profileListComboBox.getListStore().add(profiles);
profileListComboBox.getListStore().addStoreListener(new StoreListener<ProfileDTO>() {
@Override
public void storeAdd(StoreEvent<ProfileDTO> event) {
// The data is not in event.getModel() but in event.getModels() (which contains only one element)...
userUnitActionHandler.onAddProfile((UserUnitDTO) model, event.getModels().get(0));
}
@Override
public void storeRemove(StoreEvent<ProfileDTO> event) {
userUnitActionHandler.onRemoveProfile((UserUnitDTO) model, event.getModel());
}
});
setAvailableProfiles(profileListComboBox.getAvailableValuesStore(), availableProfiles);
profileStores.add(profileListComboBox.getAvailableValuesStore());
profileListComboBox.initComponent();
return profileListComboBox;
}
});
ColumnConfig actionsColumnConfig = new ColumnConfig("actions", "", 150);
actionsColumnConfig.setSortable(false);
actionsColumnConfig.setFixed(true);
actionsColumnConfig.setRenderer(new GridCellRenderer() {
@Override
public Object render(final ModelData model, String property, ColumnData config, int rowIndex, int colIndex, ListStore store, Grid grid) {
if (((UserUnitDTO) model).getMainUserUnit()) {
return null;
}
Button removeUserUnitButton = new Button(I18N.CONSTANTS.removeItem());
removeUserUnitButton.addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent event) {
userUnitActionHandler.onRemoveUserUnit((UserUnitDTO) model);
}
});
return removeUserUnitButton;
}
});
ColumnModel columnModel = new ColumnModel(Arrays.asList(hierarchyColumnConfig, orgUnitColumnConfig, profilesColumnConfig, actionsColumnConfig));
secondaryUserUnitsGrid = new Grid<UserUnitDTO>(new ListStore<UserUnitDTO>(), columnModel);
secondaryUserUnitsGrid.setAutoExpandColumn(UserUnitDTO.ORG_UNIT);
secondaryUserUnitsGrid.getView().setForceFit(true);
secondaryUserUnitsGrid.setAutoHeight(true);
addUserUnitButton = new Button(I18N.CONSTANTS.adminAddUserUnitButtonLabel());
// --
// Create button.
// --
createButton = Forms.button(I18N.CONSTANTS.save(), IconImageBundle.ICONS.save());
// --
// Form initialization.
// --
formPanel = Forms.panel(130);
formPanel.add(nameField);
formPanel.add(firstNameField);
formPanel.add(emailField);
formPanel.add(changePwdLink);
formPanel.add(pwdField);
formPanel.add(checkPwdField);
formPanel.add(contactOrganizationField);
formPanel.add(contactModelField);
formPanel.add(languageField);
formPanel.add(secondaryUserUnitsGrid);
formPanel.addButton(addUserUnitButton);
formPanel.addButton(createButton);
initPopup(formPanel);
}
/**
* {@inheritDoc}
*/
@Override
public void clearForm() {
nameField.clear();
firstNameField.clear();
emailField.clear();
pwdField.clear();
checkPwdField.clear();
languageField.clearSelections();
secondaryUserUnitsGrid.getStore().removeAll();
orgUnitStores = new ArrayList<ListStore<OrgUnitDTO>>();
profileStores = new ArrayList<ListStore<ProfileDTO>>();
pwdField.hide();
changePwdLink.setVisible(false);
checkPwdField.hide();
}
/**
* {@inheritDoc}
*/
@Override
public Field<String> getNameField() {
return nameField;
}
/**
* {@inheritDoc}
*/
@Override
public Field<String> getFirstNameField() {
return firstNameField;
}
/**
* {@inheritDoc}
*/
@Override
public Field<String> getPwdField() {
return pwdField;
}
/**
* {@inheritDoc}
*/
@Override
public Field<Object> getChangePwdLink() {
return changePwdLink;
}
/**
* {@inheritDoc}
*/
@Override
public Field<String> getEmailField() {
return emailField;
}
@Override
public ComboBox<ContactDTO> getContactOrganizationField() {
return contactOrganizationField;
}
@Override
public ComboBox<ContactModelDTO> getContactModelField() {
return contactModelField;
}
/**
* {@inheritDoc}
*/
@Override
public ComboBox<EnumModel<Language>> getLanguageField() {
return languageField;
}
/**
* {@inheritDoc}
*/
@Override
public FormPanel getForm() {
return formPanel;
}
/**
* {@inheritDoc}
*/
@Override
public Button getCreateButton() {
return createButton;
}
@Override
public ListStore<UserUnitDTO> getUserUnitStore() {
return secondaryUserUnitsGrid.getStore();
}
@Override
public Button getAddUserUnitButton() {
return addUserUnitButton;
}
@Override
public void setAvailableOrgUnits(List<OrgUnitDTO> orgUnits) {
availableOrgUnits = orgUnits;
for (ListStore<OrgUnitDTO> orgUnitStore : orgUnitStores) {
orgUnitStore.removeAll();
orgUnitStore.add(orgUnits);
}
}
@Override
public void setAvailableProfiles(List<ProfileDTO> profiles) {
availableProfiles = profiles;
for (ListStore<ProfileDTO> profileStore : profileStores) {
setAvailableProfiles(profileStore, profiles);
}
}
private void setAvailableProfiles(ListStore<ProfileDTO> store, List<ProfileDTO> profiles) {
store.removeAll();
for (ProfileDTO profile : profiles) {
if (store.findModel(ProfileDTO.ID, profile.getId()) != null) {
continue;
}
store.add(profile);
}
}
@Override
public void attachProfileHandler(UserEditPresenter.UserUnitActionHandler userUnitActionHandler) {
this.userUnitActionHandler = userUnitActionHandler;
}
}