package org.sigmah.client.ui.widget.form;
/*
* #%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.user.client.rpc.AsyncCallback;
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.extjs.gxt.ui.client.store.StoreEvent;
import com.extjs.gxt.ui.client.store.StoreListener;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.AdapterField;
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.TextField;
import com.extjs.gxt.ui.client.widget.form.Validator;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.sigmah.client.dispatch.DispatchAsync;
import org.sigmah.client.i18n.I18N;
import org.sigmah.client.ui.res.icon.IconImageBundle;
import org.sigmah.shared.command.GetContactModels;
import org.sigmah.shared.command.GetOrgUnits;
import org.sigmah.shared.command.result.ListResult;
import org.sigmah.shared.dto.ContactDTO;
import org.sigmah.shared.dto.ContactModelDTO;
import org.sigmah.shared.dto.orgunit.OrgUnitDTO;
import org.sigmah.shared.dto.referential.ContactModelType;
import org.sigmah.shared.dto.referential.ValueEventChangeType;
import com.allen_sauer.gwt.log.client.Log;
public class ContactListComboBox extends ListComboBox<ContactDTO> {
private boolean initialized = false;
private int limit;
private ContactModelType allowedType;
private Set<Integer> allowedContactModelIds;
private ChangeHandler changeHandler;
private CreateContactHandler createContactHandler;
private Button createButton;
private DispatchAsync dispatch;
public ContactListComboBox(DispatchAsync dispatch) {
this(0, null, Collections.<Integer>emptySet(), dispatch);
}
public ContactListComboBox(int limit, ContactModelType allowedType, Set<Integer> allowedContactModelIds, DispatchAsync dispatch) {
super(ContactDTO.ID, ContactDTO.FULLNAME);
this.limit = limit;
this.allowedType = allowedType;
this.allowedContactModelIds = allowedContactModelIds;
this.dispatch = dispatch;
}
public void setChangeHandler(ChangeHandler changeHandler) {
this.changeHandler = changeHandler;
}
public void setCreateContactHandler(CreateContactHandler createContactHandler) {
this.createContactHandler = createContactHandler;
}
@Override
public void initComponent() {
super.initComponent();
applyStoreListeners();
}
public void initListStore(List<ContactDTO> contacts) {
for (ContactDTO contact : contacts) {
getAvailableValuesStore().remove(contact);
}
getListStore().add(contacts);
initialized = true;
}
@Override
protected void buildComponent() {
super.buildComponent();
createButton = Forms.button(I18N.CONSTANTS.createContact(), IconImageBundle.ICONS.create());
getButtonPanel().add(createButton);
applyButtonListeners();
}
private void applyStoreListeners() {
getListStore().addStoreListener(new StoreListener<ContactDTO>() {
@Override
public void storeAdd(StoreEvent event) {
List<ContactDTO> models = event.getModels();
if (models == null) {
models = new ArrayList<ContactDTO>(1);
models.add((ContactDTO) event.getModel());
}
if (limit > 0 && getListStore().getCount() > limit) {
// event.setCancelled(true) doesn't work because the element is already added...
// Let's remove it
for (ContactDTO contactDTO : models) {
getListStore().remove(contactDTO);
getAvailableValuesStore().add(contactDTO);
}
}
for (ContactDTO contactDTO : models) {
// Avoid selection of filtered type and models
if (contactDTO.getContactModel().getType() == allowedType) {
continue;
}
if (allowedContactModelIds == null || allowedContactModelIds.isEmpty() || allowedContactModelIds.contains(contactDTO.getContactModel().getId())) {
continue;
}
getListStore().remove(contactDTO);
getAvailableValuesStore().add(contactDTO);
}
if (initialized) {
handleChange(models, ValueEventChangeType.ADD);
}
}
@Override
public void storeRemove(StoreEvent event) {
List<ContactDTO> models = event.getModels();
if (models == null) {
models = new ArrayList<ContactDTO>(1);
models.add((ContactDTO) event.getModel());
}
handleChange(models, ValueEventChangeType.REMOVE);
}
@Override
public void storeClear(StoreEvent event) {
List<ContactDTO> models = event.getModels();
if (models == null) {
models = new ArrayList<ContactDTO>(1);
models.add((ContactDTO) event.getModel());
}
handleChange(models, ValueEventChangeType.REMOVE);
}
});
}
private void applyButtonListeners() {
createButton.addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent ce) {
showContactCreator();
}
});
}
private void checkReadWriteStatus() {
if (getField() == null) {
return;
}
boolean readOnly = limit > 0 && getListStore().getCount() >= limit;
getField().setReadOnly(readOnly);
}
private void handleChange(List<ContactDTO> contacts, ValueEventChangeType changeType) {
checkReadWriteStatus();
if (changeHandler == null) {
return;
}
changeHandler.handleChange(contacts, changeType);
}
private void showContactCreator() {
final Window window = new Window();
window.setPlain(true);
window.setModal(true);
window.setBlinkModal(true);
window.setLayout(new FitLayout());
window.setSize(700, 300);
window.setHeadingHtml(I18N.CONSTANTS.createContactDialogTitle());
final ComboBox<ContactModelDTO> contactModelComboBox = Forms.combobox(I18N.CONSTANTS.contactModelLabel(), true, ContactModelDTO.ID, ContactModelDTO.NAME);
final TextField<String> emailField = Forms.text(I18N.CONSTANTS.contactEmailAddress(), false);
final TextField<String> firstNameField = Forms.text(I18N.CONSTANTS.contactFirstName(), false);
final TextField<String> familyNameField = Forms.text(I18N.CONSTANTS.contactFamilyName(), false);
final TextField<String> organizationNameField = Forms.text(I18N.CONSTANTS.contactOrganizationName(), false);
firstNameField.setVisible(false);
familyNameField.setVisible(false);
organizationNameField.setVisible(false);
final ComboBox<OrgUnitDTO> mainOrgUnitComboBox = Forms.combobox(I18N.CONSTANTS.contactMainOrgUnit(), true, OrgUnitDTO.ID, OrgUnitDTO.FULL_NAME);
final ListComboBox<OrgUnitDTO> secondaryOrgUnitsComboBox = new ListComboBox<OrgUnitDTO>(OrgUnitDTO.ID, OrgUnitDTO.FULL_NAME);
secondaryOrgUnitsComboBox.initComponent();
final AdapterField secondaryOrgUnitsFieldAdapter = Forms.adapter(I18N.CONSTANTS.contactSecondaryOrgUnits(), secondaryOrgUnitsComboBox);
secondaryOrgUnitsFieldAdapter.setVisible(false);
dispatch.execute(new GetContactModels(allowedType, allowedContactModelIds, true), new AsyncCallback<ListResult<ContactModelDTO>>() {
@Override
public void onFailure(Throwable caught) {
Log.error("Error while retrieving contact models for contact creation dialog.");
}
@Override
public void onSuccess(ListResult<ContactModelDTO> result) {
contactModelComboBox.getStore().add(result.getList());
}
});
dispatch.execute(new GetOrgUnits(OrgUnitDTO.Mode.WITH_TREE), new AsyncCallback<ListResult<OrgUnitDTO>>() {
@Override
public void onFailure(Throwable caught) {
Log.error("Error while retrieving org units for contact creation dialog.");
}
@Override
public void onSuccess(ListResult<OrgUnitDTO> result) {
for (OrgUnitDTO orgUnitDTO : result.getData()) {
fillOrgUnitsComboboxes(orgUnitDTO, mainOrgUnitComboBox, secondaryOrgUnitsComboBox);
}
}
});
mainOrgUnitComboBox.addSelectionChangedListener(new SelectionChangedListener<OrgUnitDTO>() {
@Override
public void selectionChanged(SelectionChangedEvent<OrgUnitDTO> se) {
if (se.getSelectedItem() == null) {
secondaryOrgUnitsFieldAdapter.setVisible(false);
return;
}
secondaryOrgUnitsFieldAdapter.setVisible(true);
}
});
contactModelComboBox.addSelectionChangedListener(new SelectionChangedListener<ContactModelDTO>() {
@Override
public void selectionChanged(SelectionChangedEvent<ContactModelDTO> event) {
ContactModelType currentType = null;
if (event.getSelectedItem() != null) {
currentType = event.getSelectedItem().getType();
}
firstNameField.setVisible(currentType == ContactModelType.INDIVIDUAL);
familyNameField.setVisible(currentType == ContactModelType.INDIVIDUAL);
organizationNameField.setVisible(currentType == ContactModelType.ORGANIZATION);
firstNameField.setAllowBlank(currentType != ContactModelType.INDIVIDUAL);
familyNameField.setAllowBlank(currentType != ContactModelType.INDIVIDUAL);
organizationNameField.setAllowBlank(currentType != ContactModelType.ORGANIZATION);
}
});
org.sigmah.client.ui.widget.button.Button button = Forms.button(I18N.CONSTANTS.createContact());
final FormPanel formPanel = Forms.panel(200);
formPanel.add(contactModelComboBox);
formPanel.add(emailField);
formPanel.add(firstNameField);
formPanel.add(familyNameField);
formPanel.add(organizationNameField);
formPanel.add(mainOrgUnitComboBox);
formPanel.add(secondaryOrgUnitsFieldAdapter);
formPanel.getButtonBar().add(button);
button.addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent event) {
if (!formPanel.isValid()) {
return;
}
createContactHandler.handleContactCreation(contactModelComboBox.getValue(), emailField.getValue(),
firstNameField.getValue(), familyNameField.getValue(), organizationNameField.getValue(),
mainOrgUnitComboBox.getValue(), secondaryOrgUnitsComboBox.getListStore().getModels());
window.hide();
}
});
window.add(formPanel);
window.show();
}
private void fillOrgUnitsComboboxes(OrgUnitDTO unit, final ComboBox<OrgUnitDTO> mainOrgUnitComboBox, final ListComboBox<OrgUnitDTO> secondaryOrgUnitsComboBox) {
mainOrgUnitComboBox.getStore().add(unit);
secondaryOrgUnitsComboBox.getAvailableValuesStore().add(unit);
final Set<OrgUnitDTO> children = unit.getChildrenOrgUnits();
if (children != null && !children.isEmpty()) {
for (final OrgUnitDTO child : children) {
fillOrgUnitsComboboxes(child, mainOrgUnitComboBox, secondaryOrgUnitsComboBox);
}
}
}
private boolean isFormValid(ContactModelDTO contactModelDTO, OrgUnitDTO mainOrgUnitDTO, List<OrgUnitDTO> secondaryOrgUnits) {
if (contactModelDTO == null) {
return false;
}
// a contact cannot only have secondary org units
return mainOrgUnitDTO != null || secondaryOrgUnits == null || secondaryOrgUnits.isEmpty();
}
public interface CreateContactHandler {
void handleContactCreation(ContactModelDTO contactModelDTO, String email, String firstName, String familyName, String organizationName, OrgUnitDTO mainOrgUnit, List<OrgUnitDTO> secondaryOrgUnits);
}
public interface ChangeHandler {
void handleChange(List<ContactDTO> contacts, ValueEventChangeType changeType);
}
}