package pl.net.bluesoft.rnd.processtool.ui.substitutions;
import com.vaadin.Application;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Validator;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.data.util.PropertyFormatter;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.ui.*;
import org.aperteworkflow.util.liferay.LiferayBridge;
import pl.net.bluesoft.rnd.processtool.ProcessToolContext;
import pl.net.bluesoft.rnd.processtool.bpm.ProcessToolBpmSession;
import pl.net.bluesoft.rnd.processtool.model.UserData;
import pl.net.bluesoft.rnd.processtool.model.UserSubstitution;
import pl.net.bluesoft.rnd.processtool.ui.widgets.ProcessToolGuiCallback;
import pl.net.bluesoft.rnd.util.i18n.I18NSource;
import org.aperteworkflow.util.vaadin.TransactionProvider;
import org.aperteworkflow.util.vaadin.ui.table.LocalizedPagedTable;
import pl.net.bluesoft.util.lang.Maps;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import static pl.net.bluesoft.util.lang.DateUtil.truncHours;
import static pl.net.bluesoft.util.lang.cquery.CQuery.from;
import static org.aperteworkflow.util.vaadin.VaadinExceptionHandler.Util.withErrorHandling;
import static org.aperteworkflow.util.vaadin.VaadinUtility.*;
/**
* User: POlszewski
* Date: 2011-09-09
* Time: 13:05:13
*/
public class SubstitutionsMainPane extends VerticalLayout implements Refreshable {
private Application application;
private I18NSource i18NSource;
private TransactionProvider transactionProvider;
private Window detailsWindow = null;
private BeanItemContainer<UserSubstitution> container = new BeanItemContainer<UserSubstitution>(UserSubstitution.class);
private BeanItemContainer<UserData> userDataContainer = new BeanItemContainer<UserData>(UserData.class);
private Map<String, UserData> usersByLogin;
public SubstitutionsMainPane(Application application, I18NSource i18NSource, TransactionProvider transactionProvider) {
this.application = application;
this.i18NSource = i18NSource;
this.transactionProvider = transactionProvider;
setWidth("100%");
initWidget();
loadData();
}
private void initWidget() {
removeAllComponents();
Label titleLabel = new Label(getMessage("user.substitutions.title"));
titleLabel.addStyleName("h1 color processtool-title");
titleLabel.setWidth("100%");
Button addEntryButton = addIcon(application);
addEntryButton.setCaption(getMessage("substitutions.substitution"));
addEntryButton.addListener(new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
showItemDetails(null);
}
});
HorizontalLayout headerLayout = new HorizontalLayout();
headerLayout.setWidth("100%");
headerLayout.setSpacing(true);
headerLayout.addComponent(addEntryButton);
addComponent(horizontalLayout(titleLabel, getRefreshButton()));
addComponent(headerLayout);
Map<String, Table.ColumnGenerator> customColumns = new HashMap<String, Table.ColumnGenerator>();
customColumns.put("user", createUserRealNameColumn());
customColumns.put("userSubstitute", createUserRealNameColumn());
customColumns.put("dateFrom", createDateColumn());
customColumns.put("dateTo", createDateColumn());
customColumns.put("delete", createDeleteColumn(container));
String[] visibleColumns = new String[] {"user", "userSubstitute", "dateFrom", "dateTo", "delete"};
String[] columnHeaders = new String[] {getMessage("substitutions.user"), getMessage("substitutions.user.substitute"),
getMessage("substitutions.date.from"), getMessage("substitutions.date.to"),
getMessage("pagedtable.delete")};
LocalizedPagedTable table = pagedTable(container, visibleColumns, columnHeaders, customColumns, new ItemClickEvent.ItemClickListener() {
@Override
public void itemClick(ItemClickEvent event) {
showItemDetails(container.getItem(event.getItemId()));
}
});
Component c = wrapPagedTable(i18NSource, table);
addComponent(c);
setExpandRatio(c, 1);
}
private void loadData() {
container.removeAllItems();
userDataContainer.removeAllItems();
transactionProvider.withTransaction(new ProcessToolGuiCallback() {
@Override
public void callback(ProcessToolContext ctx, ProcessToolBpmSession session) {
container.addAll(ctx.getUserSubstitutionDAO().findAllEagerUserFetch());
usersByLogin = Maps.collectionToMap(LiferayBridge.getAllUsersByCurrentUser(session.getUser(ctx)), "login");
userDataContainer.addAll(usersByLogin.values());
userDataContainer.sort(new String[]{ "realName" }, new boolean[]{ true });
}
});
}
public void refreshData() {
loadData();
}
private Component getRefreshButton() {
Button button = refreshIcon(application);
button.addListener(new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
withErrorHandling(getApplication(), new Runnable() {
public void run() {
refreshData();
}
});
}
});
return button;
}
private Form createSubstitutionForm(final BeanItem<UserSubstitution> item, final boolean add) {
UserSubstitution subst = item.getBean();
if (subst.getUser() != null) {
subst.setUser(usersByLogin.get(subst.getUser().getLogin()));
}
if (subst.getUserSubstitute() != null) {
subst.setUserSubstitute(usersByLogin.get(subst.getUserSubstitute().getLogin()));
}
final Form form = new Form() {
@Override
protected void attachField(Object propertyId, Field field) {
if (field.getValue() == null && field.getType() == String.class) {
field.setValue("");
}
super.attachField(propertyId, field);
}
};
form.setLocale(application.getLocale());
form.setFormFieldFactory(new FormFieldFactory(){
@Override
public Field createField(Item item, Object propertyId, Component component) {
if ("user".equals(propertyId)) {
Select s = select(getMessage("substitutions.user"), userDataContainer, "filteredName");
s.setRequired(true);
s.setRequiredError("Substituted User required");
return s;
}
if ("userSubstitute".equals(propertyId)) {
Select s = select(getMessage("substitutions.user.substitute"), userDataContainer, "filteredName");
s.setRequired(true);
s.setRequiredError("Substituting User required");
s.setWidth(250, UNITS_PIXELS);
return s;
}
if ("dateFrom".equals(propertyId)) {
DateField df = createDateField(getMessage("substitutions.date.from"));
df.setRequired(true);
df.setRequiredError(getMessage("substitutions.date.from.required"));
return df;
}
if ("dateTo".equals(propertyId)) {
DateField df = createDateField(getMessage("substitutions.date.to"));
df.setRequired(true);
df.setRequiredError(getMessage("substitutions.date.to.required"));
return df;
}
return null;
}
});
form.setItemDataSource(item);
form.setVisibleItemProperties(new String[]{ "user", "userSubstitute", "dateFrom", "dateTo" });
form.setValidationVisible(false);
form.setValidationVisibleOnCommit(false);
form.setImmediate(true);
form.setWriteThrough(false);
Button cancelButton = smallButton(getMessage("button.cancel"));
cancelButton.addListener(new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
form.discard();
application.getMainWindow().removeWindow(detailsWindow);
detailsWindow = null;
}
});
Button saveButton = smallButton(getMessage("button.save"));
saveButton.addListener(new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
Map<Field, String> messages = new LinkedHashMap<Field, String>();
for (Object propertyId : form.getItemPropertyIds()) {
Field field = form.getField(propertyId);
try {
field.validate();
}
catch (Validator.InvalidValueException e) {
messages.put(field, e.getMessage());
}
}
if (messages.isEmpty()) {
form.commit();
saveSubstitution(item.getBean());
if (add) {
container.addBean(item.getBean());
}
}
else {
validationNotification(application, i18NSource, from(messages.values()).toString("<br/>"));
}
application.getMainWindow().removeWindow(detailsWindow);
detailsWindow = null;
}
});
form.setFooter(horizontalLayout(Alignment.MIDDLE_CENTER, cancelButton, saveButton));
return form;
}
private void showItemDetails(BeanItem<UserSubstitution> item) {
if (detailsWindow != null) {
return;
}
boolean isNew = item == null;
if (item == null) {
item = new BeanItem<UserSubstitution>(new UserSubstitution());
}
wrapWithModalWindow(createSubstitutionForm(item, isNew));
application.getMainWindow().addWindow(detailsWindow);
}
private void wrapWithModalWindow(Form form) {
Panel panel = new Panel();
panel.setWidth("550px");
panel.setScrollable(true);
panel.addComponent(form);
detailsWindow = modalWindow(getMessage("substitutions.Substitution"), panel);
}
private void saveSubstitution(final UserSubstitution item) {
item.setDateFrom(truncHours(item.getDateFrom()));
item.setDateTo(truncHours(item.getDateTo()));
transactionProvider.withTransaction(new ProcessToolGuiCallback() {
@Override
public void callback(ProcessToolContext ctx, ProcessToolBpmSession session) {
item.setUser(ctx.getUserDataDAO().loadOrCreateUserByLogin(item.getUser()));
item.setUserSubstitute(ctx.getUserDataDAO().loadOrCreateUserByLogin(item.getUserSubstitute()));
ctx.getUserSubstitutionDAO().saveOrUpdate(item);
}
});
}
private Table.ColumnGenerator createUserRealNameColumn() {
return new Table.ColumnGenerator() {
@Override
public Component generateCell(Table source, final Object itemId, Object columnId) {
Property prop = source.getItem(itemId).getItemProperty(columnId);
if (prop.getType().equals(UserData.class)) {
Label l = new Label();
l.setPropertyDataSource(new PropertyFormatter(prop) {
@Override
public String format(Object o) {
return ((UserData)o).getRealName();
}
@Override
public Object parse(String s) throws Exception {
throw new UnsupportedOperationException();
}
});
return l;
}
return null;
}
};
}
private Table.ColumnGenerator createDateColumn() {
return new Table.ColumnGenerator() {
@Override
public Component generateCell(Table source, final Object itemId, Object columnId) {
Property prop = source.getItem(itemId).getItemProperty(columnId);
if (prop.getType().equals(Date.class)) {
DateField df = createDateField(null);
df.setRequired(true);
df.setReadOnly(true);
df.setPropertyDataSource(prop);
return df;
}
return null;
}
};
}
private Table.ColumnGenerator createDeleteColumn(final BeanItemContainer container) {
return new Table.ColumnGenerator() {
@Override
public Component generateCell(Table source, final Object itemId, Object columnId) {
Button b = smallButton(getMessage("pagedtable.delete"));
b.addListener(new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
final UserSubstitution item = (UserSubstitution)container.getItem(itemId).getBean();
container.removeItem(itemId);
transactionProvider.withTransaction(new ProcessToolGuiCallback() {
@Override
public void callback(ProcessToolContext ctx, ProcessToolBpmSession session) {
ctx.getUserSubstitutionDAO().deleteById(item.getId());
}
});
}
});
return b;
}
};
}
public Application getApplication() {
return application;
}
private PopupDateField createDateField(String caption) {
PopupDateField dateField = new PopupDateField(caption);
dateField.setDateFormat("yyyy-MM-dd");
dateField.setResolution(PopupDateField.RESOLUTION_DAY);
dateField.setImmediate(true);
return dateField;
}
private String getMessage(String key) {
return i18NSource.getMessage(key);
}
}