package de.dhbw.humbuch.view; import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.NoSuchElementException; import java.util.Set; import com.google.common.eventbus.EventBus; import com.google.inject.Inject; import com.vaadin.data.Container.Filter; import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.data.util.BeanItemContainer; import com.vaadin.data.util.filter.Compare.Equal; import com.vaadin.data.util.filter.Not; import com.vaadin.data.util.filter.Or; import com.vaadin.data.util.filter.SimpleStringFilter; import com.vaadin.event.FieldEvents.TextChangeEvent; import com.vaadin.event.FieldEvents.TextChangeListener; import com.vaadin.navigator.View; import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; import com.vaadin.server.StreamResource; import com.vaadin.ui.AbstractTextField.TextChangeEventMode; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.CheckBox; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Table; import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; import de.davherrmann.mvvm.BasicState; import de.davherrmann.mvvm.State; import de.davherrmann.mvvm.StateChangeListener; import de.davherrmann.mvvm.ViewModelComposer; import de.davherrmann.mvvm.annotations.BindState; import de.dhbw.humbuch.event.MessageEvent; import de.dhbw.humbuch.event.MessageEvent.Type; import de.dhbw.humbuch.model.entity.BorrowedMaterial; import de.dhbw.humbuch.model.entity.Dunning; import de.dhbw.humbuch.util.PDFDunning; import de.dhbw.humbuch.util.PDFHandler; import de.dhbw.humbuch.view.components.PrintingComponent; import de.dhbw.humbuch.viewmodel.DunningViewModel; import de.dhbw.humbuch.viewmodel.DunningViewModel.Dunnings; /** * Provides the {@link View} to display and manage {@link Dunning}s * @author Johannes Idelhauser * @author Martin Wentzel */ public class DunningView extends VerticalLayout implements View, ViewInformation { private static final long serialVersionUID = 1284094636968999625L; private static final String TITLE = "Mahnungen"; private static final String TABLE_LASTNAME = "student.lastname"; private static final String TABLE_FIRSTNAME = "student.firstname"; private static final String TABLE_GRADE = "student.grade"; private static final String TABLE_TYPE = "type"; private static final String TABLE_STATUS = "status"; private CheckBox cbOpenDunnings = new CheckBox("Nur offene Mahnungen anzeigen"); private Button btnDunningSent = new Button("Als versendet markieren"); private Button btnShowDunning = new Button("Mahnung anzeigen"); private Table tblDunnings; private TextField txtFilter; private DunningViewModel dunningViewModel; @BindState(Dunnings.class) public final State<Collection<Dunning>> dunnings = new BasicState<>(Collection.class); private EventBus eventBus; private BeanItemContainer<Dunning> tableData; @Inject public DunningView(ViewModelComposer viewModelComposer, DunningViewModel dunningViewModel, EventBus eventBus) { this.dunningViewModel = dunningViewModel; this.eventBus = eventBus; init(); bindViewModel(viewModelComposer, dunningViewModel); } /** * Creates UI elements and initializes the View */ private void init() { HorizontalLayout head = new HorizontalLayout(); head.setWidth("100%"); head.setSpacing(true); //Filter VerticalLayout filterLayout = new VerticalLayout(); txtFilter = new TextField(); txtFilter.setImmediate(true); txtFilter.setInputPrompt("Nach Name, Vorname oder Klasse filtern..."); txtFilter.setWidth("50%"); txtFilter.setTextChangeEventMode(TextChangeEventMode.EAGER); filterLayout.addComponent(txtFilter); filterLayout.addComponent(cbOpenDunnings); head.addComponent(filterLayout); head.setExpandRatio(filterLayout, 1); head.setComponentAlignment(filterLayout, Alignment.MIDDLE_LEFT); //Buttons HorizontalLayout buttons = new HorizontalLayout(); buttons.setSpacing(true); buttons.addComponent(btnDunningSent); buttons.addComponent(btnShowDunning); btnDunningSent.setEnabled(false); btnShowDunning.setEnabled(false); head.addComponent(buttons); head.setComponentAlignment(buttons, Alignment.TOP_RIGHT); addComponent(head); //Table tblDunnings = new Table(); tblDunnings.setSelectable(true); tblDunnings.setSizeFull(); tblDunnings.setImmediate(true); tblDunnings.setColumnCollapsingAllowed(true); tableData = new BeanItemContainer<Dunning>(Dunning.class); tableData.addNestedContainerProperty(TABLE_LASTNAME); tableData.addNestedContainerProperty(TABLE_FIRSTNAME); tableData.addNestedContainerProperty(TABLE_GRADE); tblDunnings.setContainerDataSource(tableData); tblDunnings.setVisibleColumns(new Object[] { TABLE_LASTNAME, TABLE_FIRSTNAME, TABLE_GRADE, TABLE_TYPE, TABLE_STATUS }); tblDunnings.setColumnHeader(TABLE_LASTNAME, "Name"); tblDunnings.setColumnHeader(TABLE_FIRSTNAME, "Vorname"); tblDunnings.setColumnHeader(TABLE_GRADE, "Klasse"); tblDunnings.setColumnHeader(TABLE_TYPE, "Typ"); tblDunnings.setColumnHeader(TABLE_STATUS, "Status"); addComponent(tblDunnings); setExpandRatio(tblDunnings, 1); setSizeFull(); setSpacing(true); setMargin(true); addListener(); } /** * Adds listeners to different UI elements as well as to states. */ private void addListener() { /** * Listens for changes in all dunning collection an adds them to the * container */ dunnings.addStateChangeListener(new StateChangeListener() { @Override public void stateChange(Object value) { tableData.removeAllItems(); for (Dunning dunning : dunnings.get()) { tblDunnings.addItem(dunning); } } }); /** * Enables/disables the buttons */ tblDunnings.addValueChangeListener(new Table.ValueChangeListener() { private static final long serialVersionUID = -4224382328843243771L; @Override public void valueChange(ValueChangeEvent event) { Dunning item = (Dunning) tblDunnings.getValue(); btnShowDunning.setEnabled(item != null); //Check if the selected dunning can be marked as sent if (item != null && item.getStatus() == Dunning.Status.OPENED) { btnDunningSent.setEnabled(item != null); } else { btnDunningSent.setEnabled(false); } } }); /** * Set the send status of the dunning */ btnDunningSent.addClickListener(new ClickListener() { private static final long serialVersionUID = 7963891536949402850L; @Override public void buttonClick(ClickEvent event) { Dunning item = (Dunning) tblDunnings.getValue(); item.setStatus(Dunning.Status.SENT); dunningViewModel.doUpdateDunning(item); } }); /** * Open the pdf with the dunning */ btnShowDunning.addClickListener(new ClickListener() { private static final long serialVersionUID = -1285703858095198175L; @Override public void buttonClick(ClickEvent event) { Dunning item = (Dunning) tblDunnings.getValue(); Set<List<BorrowedMaterial>> setBorrowedMaterial = new HashSet<List<BorrowedMaterial>>(); setBorrowedMaterial.add(new ArrayList<BorrowedMaterial>(item.getBorrowedMaterials())); ByteArrayOutputStream baos; if(item.getType() == Dunning.Type.TYPE1) { baos = PDFDunning.createFirstDunning(setBorrowedMaterial).createByteArrayOutputStreamForPDF(); } else { baos = PDFDunning.createSecondDunning(setBorrowedMaterial).createByteArrayOutputStreamForPDF(); } String fileNameIncludingHash = ""+ new Date().hashCode() + "_MAHNUNG_"+item.getStudent().getFirstname()+"_"+item.getStudent().getLastname(); if(baos == null) { eventBus.post(new MessageEvent("Fehler", "PDF konnte nicht erstellt werden", Type.ERROR)); return; } StreamResource sr = new StreamResource(new PDFHandler.PDFStreamSource(baos), fileNameIncludingHash); new PrintingComponent(sr, "Mahnung"); } }); /** * Provides the live search of the table by adding a filter after every * keypress in the search field. */ txtFilter.addTextChangeListener(new TextChangeListener() { private static final long serialVersionUID = -1684545652234105334L; Filter filter = null; @Override public void textChange(TextChangeEvent event) { if (filter != null) { tableData.removeContainerFilter(filter); } SimpleStringFilter cond1 = new SimpleStringFilter(TABLE_LASTNAME, event.getText(), true, false); SimpleStringFilter cond2 = new SimpleStringFilter(TABLE_FIRSTNAME, event.getText(), true, false); SimpleStringFilter cond3 = new SimpleStringFilter(TABLE_GRADE, event.getText(), true, false); filter = new Or(cond1, cond2, cond3); tableData.addContainerFilter(filter); } }); cbOpenDunnings.addValueChangeListener(new ValueChangeListener() { private static final long serialVersionUID = 1L; @Override public void valueChange(ValueChangeEvent event) { Filter filter = new Not(new Equal(TABLE_STATUS, Dunning.Status.CLOSED)); if(cbOpenDunnings.getValue() == true) { tableData.addContainerFilter(filter); } else { tableData.removeContainerFilter(filter); } tblDunnings.setValue(null); } }); } @Override public void enter(ViewChangeEvent event) { tblDunnings.setValue(null); dunningViewModel.refresh(); cbOpenDunnings.setValue(true); } private void bindViewModel(ViewModelComposer viewModelComposer, Object... viewModels) { try { viewModelComposer.bind(this, viewModels); } catch (IllegalAccessException | NoSuchElementException | UnsupportedOperationException e) { e.printStackTrace(); } } @Override public String getTitle() { return TITLE; } }