ItEr43S20CUAsignarUsuarioAProxectoPlanificacionItEr12S09 : Create a new component to filter the order list.

This commit is contained in:
Susana Montes Pedreira 2010-01-24 21:59:09 +01:00 committed by Javier Moran Rua
parent 8a6ca7c51e
commit 9da53ca91e
14 changed files with 1201 additions and 11 deletions

View file

@ -0,0 +1,275 @@
/*
* This file is part of ###PROJECT_NAME###
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.web.common.components.bandboxsearch;
import static org.navalplanner.web.I18nHelper._;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.navalplanner.web.common.components.finders.IMultipleFiltersFinder;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.HtmlMacroComponent;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.InputEvent;
import org.zkoss.zul.Bandbox;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.Listhead;
import org.zkoss.zul.Listheader;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.SimpleListModel;
import org.zkoss.zul.api.Listbox;
/**
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
@SuppressWarnings("serial")
public class BandboxMultipleSearch extends HtmlMacroComponent {
private Listbox listbox;
private Listhead listhead;
private Bandbox bandbox;
private String widthBandbox;
private String widthListbox;
private IMultipleFiltersFinder multipleFiltersFinder;
private List selectedFilters = new ArrayList();
private String selectedFiltersText = new String("");
public void afterCompose() {
super.afterCompose();
listbox = (Listbox) getFellowIfAny("listbox");
listhead = (Listhead) listbox.getFellowIfAny("listhead");
bandbox = (Bandbox) getFellowIfAny("bandbox");
if (multipleFiltersFinder != null) {
multipleFiltersFinder.init();
listbox.setModel(new SimpleListModel(multipleFiltersFinder
.getMatching("")));
listbox.setItemRenderer(multipleFiltersFinder.getItemRenderer());
addHeaders();
/**
* Search for matching elements while typing on bandbox
*/
bandbox.addEventListener("onChanging", new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
final String inputText = ((InputEvent) event).getValue();
if ((inputText == null) || (inputText.isEmpty())) {
clear();
} else {
String newFilterText = getNewFilterText(inputText);
if ((newFilterText != null)
&& (newFilterText.length() > 2)) {
listbox.setModel(getSubModel(newFilterText));
listbox.invalidate();
} else {
clearListbox();
}
}
}
});
/**
* Pick element from list when selecting
*/
listbox.addEventListener("onSelect", new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
final Object object = getSelectedItem().getValue();
addSelectedElement(object);
bandbox.close();
clearListbox();
}
});
}
updateWidth();
}
private String getNewFilterText(String inputText){
String newFilterText = new String("");
String[] filtersText = inputText.split(",");
newFilterText = getLastText(filtersText);
newFilterText = newFilterText.replace(" ", "");
newFilterText = newFilterText.trim();
return newFilterText;
}
private String getLastText(String[] texts) {
Integer last = texts.length - 1;
if (texts.length > 0) {
return texts[last];
} else {
return "";
}
}
private void clearSelectedElement() {
bandbox.setValue("");
selectedFiltersText = "";
selectedFilters.clear();
}
public void addSelectedElement(Object obj) {
if (obj != null) {
selectedFiltersText = selectedFiltersText
.concat(multipleFiltersFinder.objectToString(obj));
bandbox.setValue(selectedFiltersText);
selectedFilters.add(obj);
}
}
public List getSelectedElements() {
if (this.multipleFiltersFinder != null) {
if (!multipleFiltersFinder.isValidFormatText(selectedFilters,
bandbox.getValue())) {
throw new WrongValueException(bandbox,
_("format filters are not valid"));
}
}
return selectedFilters;
}
/**
* Find {@link Label} which name or type start with prefix
* @param inputText
*/
@SuppressWarnings("unchecked")
private ListModel getSubModel(String inputText) {
List result = multipleFiltersFinder.getMatching(inputText);
return new SimpleListModel(result);
}
/**
* Append headers to listbox header list
*/
@SuppressWarnings("unchecked")
public void addHeaders() {
clearHeaderIfNecessary();
final String[] headers = multipleFiltersFinder.getHeaders();
for (int i = 0; i < headers.length; i++) {
listhead.getChildren().add(new Listheader(headers[i]));
}
}
private void clearHeaderIfNecessary() {
if (listhead.getChildren() != null) {
listhead.getChildren().clear();
}
}
private Listitem getSelectedItem() {
return (Listitem) listbox.getSelectedItems().iterator().next();
}
public void setDisabled(boolean disabled) {
bandbox.setDisabled(disabled);
}
private Object getBean(String beanName) {
HttpServletRequest servletRequest = (HttpServletRequest) Executions
.getCurrent().getNativeRequest();
ServletContext servletContext = servletRequest.getSession()
.getServletContext();
WebApplicationContext webApplicationContext = WebApplicationContextUtils
.getWebApplicationContext(servletContext);
return webApplicationContext.getBean(beanName);
}
public String getFinder() {
return multipleFiltersFinder.getClass().toString();
}
public void setFinder(String classname) {
multipleFiltersFinder = (IMultipleFiltersFinder) getBean(StringUtils
.uncapitalize(classname));
}
/**
* Clears {@link Bandbox} Fills bandbox list model, clear bandbox textbox,
* and set selected label to null
* @param bandbox
*/
public void clear() {
clearListbox();
clearSelectedElement();
}
private void clearListbox() {
List<Object> list = new ArrayList<Object>();
listbox.setModel(new SimpleListModel(list));
listbox.invalidate();
}
public List<Object> asList(ListModel model) {
List<Object> result = new ArrayList<Object>();
for (int i = 0; i < model.getSize(); i++) {
result.add(model.getElementAt(i));
}
return result;
}
public void setListboxEventListener(String event, EventListener listener) {
listbox.addEventListener(event, listener);
}
public String getWidthBandbox() {
return widthBandbox;
}
public void setWidthBandbox(String widthBandbox) {
this.widthBandbox = widthBandbox;
}
public String getWidthListbox() {
return widthListbox;
}
public void setWidthListbox(String widthListbox) {
this.widthListbox = widthListbox;
}
private void updateWidth() {
if ((widthBandbox != null) && (!widthBandbox.isEmpty())) {
this.bandbox.setWidth(widthBandbox);
this.listbox.setWidth(widthListbox);
}
}
}

View file

@ -21,7 +21,9 @@
package org.navalplanner.web.common.components.bandboxsearch;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
@ -57,6 +59,8 @@ public class BandboxSearch extends HtmlMacroComponent {
private IBandboxFinder finder;
private static Map<String, Object> mapMatching = new HashMap<String, Object>();
private String widthBandbox;
private String widthListbox;

View file

@ -0,0 +1,66 @@
/*
* This file is part of ###PROJECT_NAME###
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.web.common.components.finders;
/**
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
public class FilterPair extends Object {
private OrderFilterEnum type;
private String pattern;
private Object value;
public FilterPair() {
}
public FilterPair(OrderFilterEnum type, String pattern, Object value) {
this.type = type;
this.value = value;
this.pattern = pattern;
}
public OrderFilterEnum getType() {
return type;
}
public void setType(OrderFilterEnum type) {
this.type = type;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public String getPattern() {
return pattern;
}
public void setPattern(String pattern) {
this.pattern = pattern;
}
}

View file

@ -0,0 +1,46 @@
/*
* This file is part of ###PROJECT_NAME###
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.web.common.components.finders;
import java.util.List;
import org.zkoss.zul.ListitemRenderer;
/**
* Contract for {@link MultipleFilterFinder}<br />
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
public interface IMultipleFiltersFinder {
void init();
List<FilterPair> getMatching(String filter);
String objectToString(Object obj);
boolean isValidFormatText(List filterValues, String value);
String[] getHeaders();
ListitemRenderer getItemRenderer();
}

View file

@ -0,0 +1,341 @@
/*
* This file is part of ###PROJECT_NAME###
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.web.common.components.finders;
import static org.navalplanner.web.I18nHelper._;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.navalplanner.business.externalcompanies.daos.IExternalCompanyDAO;
import org.navalplanner.business.externalcompanies.entities.ExternalCompany;
import org.navalplanner.business.labels.daos.ILabelDAO;
import org.navalplanner.business.labels.daos.ILabelTypeDAO;
import org.navalplanner.business.labels.entities.Label;
import org.navalplanner.business.labels.entities.LabelType;
import org.navalplanner.business.orders.daos.IOrderDAO;
import org.navalplanner.business.orders.entities.Order;
import org.navalplanner.business.orders.entities.OrderStatusEnum;
import org.navalplanner.business.qualityforms.entities.QualityForm;
import org.navalplanner.business.resources.daos.ICriterionDAO;
import org.navalplanner.business.resources.daos.ICriterionTypeDAO;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
/**
* Implements all the methods needed to search the criterion to filter the
* orders. Provides multiples criterions to filter like {@link Criterion},
* {@link Label}, {@link OrderStatusEnum},{@link ExternalCompany} object , or
* filter by order code or customer reference.
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
@Service
@Scope(BeanDefinition.SCOPE_SINGLETON)
public class MultipleFiltersFinder implements IMultipleFiltersFinder {
@Autowired
private ICriterionTypeDAO criterionTypeDAO;
@Autowired
private ILabelTypeDAO labelTypeDAO;
@Autowired
private IExternalCompanyDAO externalCompanyDAO;
@Autowired
private ICriterionDAO criterionDAO;
@Autowired
private ILabelDAO labelDAO;
@Autowired
private IOrderDAO orderDAO;
private static final Map<CriterionType, List<Criterion>> mapCriterions = new HashMap<CriterionType, List<Criterion>>();
private static final Map<LabelType, List<Label>> mapLabels = new HashMap<LabelType, List<Label>>();
private static final List<ExternalCompany> externalCompanies = new ArrayList<ExternalCompany>();
private static final List<String> customerReferences = new ArrayList<String>();
private static OrderStatusEnum[] ordersStatusEnums;
private static final List<String> ordersCodes = new ArrayList<String>();
private List<FilterPair> listMatching = new ArrayList<FilterPair>();
private final String headers[] = { _("Filter type"), _("Filter pattern") };
protected MultipleFiltersFinder() {
}
@Transactional(readOnly = true)
public void init() {
loadLabels();
loadCriterions();
loadExternalCompanies();
loadOrdersStatusEnums();
loadOrderCodesAndCustomerReferences();
}
private void loadCriterions() {
mapCriterions.clear();
List<CriterionType> criterionTypes = criterionTypeDAO
.getCriterionTypes();
for (CriterionType criterionType : criterionTypes) {
List<Criterion> criterions = new ArrayList<Criterion>(criterionDAO
.findByType(criterionType));
mapCriterions.put(criterionType, criterions);
}
}
private void loadLabels() {
mapLabels.clear();
List<LabelType> labelTypes = labelTypeDAO.getAll();
for (LabelType labelType : labelTypes) {
List<Label> labels = new ArrayList<Label>(labelDAO
.findByType(labelType));
mapLabels.put(labelType, labels);
}
}
private void loadExternalCompanies() {
externalCompanies.clear();
externalCompanies.addAll(externalCompanyDAO
.getExternalCompaniesAreClient());
}
private void loadOrdersStatusEnums() {
ordersStatusEnums = OrderStatusEnum.values();
}
private void loadOrderCodesAndCustomerReferences() {
customerReferences.clear();
ordersCodes.clear();
for (Order order : orderDAO.getOrders()) {
// load customer references
if ((order.getCustomerReference() != null)
&& (!order.getCustomerReference().isEmpty())) {
customerReferences.add(order.getCustomerReference());
}
// load the order codes
ordersCodes.add(order.getCode());
}
}
public List<FilterPair> getMatching(String filter) {
listMatching.clear();
if ((filter != null) && (!filter.isEmpty())) {
filter = filter.toLowerCase();
if (filter.indexOf("rc:") == 0) {
searchInCustomerReferences(filter);
} else if (filter.indexOf("cod:") == 0) {
this.searchInOrderCodes(filter);
} else {
searchInCriterionTypes(filter);
searchInLabelTypes(filter);
searchInExternalCompanies(filter);
searchInOrderStatus(filter);
}
}
return listMatching;
}
private void searchInCriterionTypes(String filter) {
for (CriterionType type : mapCriterions.keySet()) {
if (type.getName().toLowerCase().contains(filter)) {
setFilterPairCriterionType(type);
} else {
searchInCriterions(type, filter);
}
}
}
private void searchInCriterions(CriterionType type, String filter) {
for (Criterion criterion : mapCriterions.get(type)) {
if (criterion.getName().toLowerCase().contains(filter)) {
String pattern = type.getName() + " :: " + criterion.getName();
listMatching.add(new FilterPair(OrderFilterEnum.Criterion,
pattern,
criterion));
}
}
}
private void setFilterPairCriterionType(CriterionType type) {
for (Criterion criterion : mapCriterions.get(type)) {
String pattern = type.getName() + " :: " + criterion.getName();
listMatching.add(new FilterPair(OrderFilterEnum.Criterion, pattern,
criterion));
}
}
private void searchInLabelTypes(String filter) {
for (LabelType type : mapLabels.keySet()) {
if (type.getName().toLowerCase().contains(filter)) {
setFilterPairLabelType(type);
} else {
searchInLabels(type, filter);
}
}
}
private void searchInLabels(LabelType type, String filter) {
for (Label label : mapLabels.get(type)) {
if (label.getName().toLowerCase().contains(filter)) {
String pattern = type.getName() + " :: " + label.getName();
listMatching.add(new FilterPair(OrderFilterEnum.Label, pattern,
label));
}
}
}
private void setFilterPairLabelType(LabelType type) {
for (Label label : mapLabels.get(type)) {
String pattern = type.getName() + " :: " + label.getName();
listMatching.add(new FilterPair(OrderFilterEnum.Label, pattern,
label));
}
}
private void searchInExternalCompanies(String filter){
for(ExternalCompany externalCompany : externalCompanies){
if ((externalCompany.getName().toLowerCase().contains(filter))
|| (externalCompany.getNif().toLowerCase().contains(filter))) {
String pattern = externalCompany.getName() + " :: "
+ externalCompany.getNif();
listMatching.add(new FilterPair(
OrderFilterEnum.ExternalCompany, pattern,
externalCompany));
}
}
}
private void searchInOrderStatus(String filter) {
for (OrderStatusEnum state : ordersStatusEnums) {
if (state.name().toLowerCase().contains(filter)) {
listMatching.add(new FilterPair(OrderFilterEnum.State, state
.name(), state));
}
}
}
private void searchInOrderCodes(String filter) {
if (filter.indexOf("cod:") == 0) {
String codeFilter = filter.replaceFirst("cod:", "");
codeFilter = codeFilter.replace(" ", "");
for (String code : ordersCodes) {
if (code.toLowerCase().equals(codeFilter)) {
listMatching.add(new FilterPair(OrderFilterEnum.Code, code,
code));
return;
}
}
}
}
private void searchInCustomerReferences(String filter) {
if (filter.indexOf("rc:") == 0) {
String referenceFilter = filter.replaceFirst("rc:", "");
referenceFilter = referenceFilter.replace(" ", "");
for (String reference : customerReferences) {
if (reference.toLowerCase().equals(referenceFilter)) {
listMatching.add(new FilterPair(
OrderFilterEnum.CustomerReference,
reference, reference));
return;
}
}
}
}
public String objectToString(Object obj) {
FilterPair filterPair = (FilterPair) obj;
String text = filterPair.getType() + "(" + filterPair.getPattern()
+ "), ";
return text;
}
public boolean isValidFormatText(List filterValues, String value) {
String[] values = value.split(",");
if (values.length != filterValues.size() + 1) {
return false;
}
int i = 0;
for (FilterPair filterPair : (List<FilterPair>) filterValues) {
String filterValue = values[i].replace(" ", "");
String filterPairText = filterPair.getType() + "("
+ filterPair.getPattern() + ")";
filterPairText = filterPairText.replace(" ", "");
if (!filterValue.equals(filterPairText)) {
return false;
}
i++;
}
return true;
}
public String[] getHeaders() {
return headers;
}
public ListitemRenderer getItemRenderer() {
return filterPairRenderer;
}
/**
* Render for {@link QualityForm}
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
private final ListitemRenderer filterPairRenderer = new ListitemRenderer() {
@Override
public void render(Listitem item, Object data) throws Exception {
FilterPair filterPair = (FilterPair) data;
item.setValue(data);
final Listcell labelType = new Listcell();
labelType.setLabel(filterPair.getType().toString());
labelType.setParent(item);
final Listcell labelPattern = new Listcell();
labelPattern.setLabel(filterPair.getPattern());
labelPattern.setParent(item);
}
};
}

View file

@ -0,0 +1,41 @@
/*
* This file is part of ###PROJECT_NAME###
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
package org.navalplanner.web.common.components.finders;
public enum OrderFilterEnum {
Criterion("Criterion"), Label("Label"), ExternalCompany("Customer"), State(
"State"), Code("Code"), CustomerReference("Customer Reference");
private String description;
private OrderFilterEnum(String description) {
this.description = description;
}
public String toString() {
return this.description;
}
}

View file

@ -115,4 +115,6 @@ public interface IOrderModel {
public String gettooltipText(Order order);
List<Order> getFilterOrders(OrderPredicate predicate);
}

View file

@ -42,7 +42,6 @@ import org.navalplanner.business.orders.entities.OrderElement;
import org.navalplanner.business.orders.entities.OrderLine;
import org.navalplanner.business.orders.entities.OrderStatusEnum;
import org.navalplanner.business.templates.entities.OrderTemplate;
import org.navalplanner.business.orders.entities.OrderLineGroup;
import org.navalplanner.business.users.entities.UserRole;
import org.navalplanner.web.common.IMessagesForUser;
import org.navalplanner.web.common.Level;
@ -51,7 +50,9 @@ import org.navalplanner.web.common.OnTabSelection;
import org.navalplanner.web.common.OnlyOneVisible;
import org.navalplanner.web.common.Util;
import org.navalplanner.web.common.OnTabSelection.IOnSelectingTab;
import org.navalplanner.web.common.components.bandboxsearch.BandboxMultipleSearch;
import org.navalplanner.web.common.components.bandboxsearch.BandboxSearch;
import org.navalplanner.web.common.components.finders.FilterPair;
import org.navalplanner.web.orders.assigntemplates.TemplateFinderPopup;
import org.navalplanner.web.orders.assigntemplates.TemplateFinderPopup.IOnResult;
import org.navalplanner.web.orders.labels.AssignedLabelsToOrderElementController;
@ -68,21 +69,27 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Button;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.Comboitem;
import org.zkoss.zul.ComboitemRenderer;
import org.zkoss.zul.Constraint;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Label;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Popup;
import org.zkoss.zul.Row;
import org.zkoss.zul.RowRenderer;
import org.zkoss.zul.SimpleListModel;
import org.zkoss.zul.Tab;
import org.zkoss.zul.Tabbox;
import org.zkoss.zul.Vbox;
import org.zkoss.zul.api.Window;
/**
@ -141,6 +148,7 @@ public class OrderCRUDController extends GenericForwardComposer {
private TemplateFinderPopup templateFinderPopup;
public void createOrderFromTemplate() {
showOrderElementFilter();
Component fromTemplateButton = listWindow
.getFellow("create_from_template_button");
templateFinderPopup.openForOrderCreation(fromTemplateButton,
@ -165,6 +173,20 @@ public class OrderCRUDController extends GenericForwardComposer {
private Tab selectedTab;
private Grid listing;
private Vbox orderFilter;
private Vbox filter;
private Datebox filterStartDate;
private Datebox filterFinishDate;
private BandboxMultipleSearch bdFilters;
private Checkbox checkIncludeOrderElements;
private BandboxSearch bdExternalCompanies;
private OnlyOneVisible cachedOnlyOneVisible;
@ -175,7 +197,6 @@ public class OrderCRUDController extends GenericForwardComposer {
private OrdersRowRenderer ordersRowRenderer = new OrdersRowRenderer();
private Popup popup;
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
@ -186,6 +207,20 @@ public class OrderCRUDController extends GenericForwardComposer {
((Button)listWindow.getFellowIfAny("show_create_form")).setDisabled(false);
((Button)listWindow.getFellowIfAny("create_from_template_button")).setDisabled(false);
}
// Configuration of the order filter
Component filterComponent = Executions.createComponents(
"/orders/_orderFilter.zul", orderFilter,
new HashMap<String, String>());
filterComponent.setVariable("controller", this, true);
filterStartDate = (Datebox) filterComponent
.getFellow("filterStartDate");
filterFinishDate = (Datebox) filterComponent
.getFellow("filterFinishDate");
bdFilters = (BandboxMultipleSearch) filterComponent
.getFellow("bdFilters");
checkIncludeOrderElements = (Checkbox) filterComponent
.getFellow("checkIncludeOrderElements");
}
private void addEditWindowIfNeeded() {
@ -397,9 +432,17 @@ public class OrderCRUDController extends GenericForwardComposer {
}
public void goToList() {
loadComponents();
showWindow(listWindow);
}
private void loadComponents() {
// load the components of the order list
listing = (Grid) listWindow.getFellow("listing");
showOrderFilter();
clearFilterDates();
}
public void reloadHoursGroupOrder() {
assignedCriterionRequirementController
.openWindow(getOrderElementModel());
@ -465,6 +508,7 @@ public class OrderCRUDController extends GenericForwardComposer {
private Runnable onUp;
public void goToEditForm(Order order) {
showOrderElementFilter();
planningControllerEntryPoints.goToOrderDetails(order);
}
@ -503,6 +547,7 @@ public class OrderCRUDController extends GenericForwardComposer {
public void goToCreateForm() {
try {
showOrderElementFilter();
orderModel.prepareForCreate();
showEditWindow(_("Create order"));
orderAuthorizationController.initCreate((Order) orderModel.getOrder());
@ -716,4 +761,90 @@ public class OrderCRUDController extends GenericForwardComposer {
Util.reloadBindings(txtTotalBudget);
}
/**
* Operations to filter the orders by multiple filters
*/
public Constraint checkConstraintFinishDate() {
return new Constraint() {
@Override
public void validate(Component comp, Object value)
throws WrongValueException {
Date finishDate = (Date) value;
if ((finishDate != null)
&& (filterStartDate.getValue() != null)
&& (finishDate.compareTo(filterStartDate.getValue()) < 0)) {
filterFinishDate.setValue(null);
throw new WrongValueException(comp,
_("must be greater than start date"));
}
}
};
}
public Constraint checkConstraintStartDate() {
return new Constraint() {
@Override
public void validate(Component comp, Object value)
throws WrongValueException {
Date startDate = (Date) value;
if ((startDate != null)
&& (filterFinishDate.getValue() != null)
&& (startDate.compareTo(filterFinishDate.getValue()) > 0)) {
filterStartDate.setValue(null);
throw new WrongValueException(comp,
_("must be lower than finish date"));
}
}
};
}
public void onApplyFilter() {
OrderPredicate predicate = createPredicate();
if (predicate != null) {
filterByPredicate(predicate);
} else {
showAllOrders();
}
}
private OrderPredicate createPredicate() {
List<FilterPair> listFilters = (List<FilterPair>) bdFilters
.getSelectedElements();
Date startDate = filterStartDate.getValue();
Date finishDate = filterFinishDate.getValue();
Boolean includeOrderElements = checkIncludeOrderElements.isChecked();
if (listFilters.isEmpty() && startDate == null && finishDate == null) {
return null;
}
return new OrderPredicate(listFilters, startDate, finishDate,
includeOrderElements);
}
private void filterByPredicate(OrderPredicate predicate) {
List<Order> filterOrders = orderModel.getFilterOrders(predicate);
listing.setModel(new SimpleListModel(filterOrders.toArray()));
listing.invalidate();
}
private void clearFilterDates() {
filterStartDate.setValue(null);
filterFinishDate.setValue(null);
}
public void showAllOrders() {
listing.setModel(new SimpleListModel(orderModel.getOrders().toArray()));
listing.invalidate();
}
private void showOrderFilter() {
orderFilter.setVisible(true);
filter.setVisible(false);
}
private void showOrderElementFilter() {
orderFilter.setVisible(false);
filter.setVisible(true);
}
}

View file

@ -41,6 +41,7 @@ import org.navalplanner.business.templates.entities.OrderElementTemplate;
import org.navalplanner.web.common.Util;
import org.navalplanner.web.common.Util.Getter;
import org.navalplanner.web.common.Util.Setter;
import org.navalplanner.web.common.components.bandboxsearch.BandboxMultipleSearch;
import org.navalplanner.web.common.components.bandboxsearch.BandboxSearch;
import org.navalplanner.web.orders.assigntemplates.TemplateFinderPopup;
import org.navalplanner.web.orders.assigntemplates.TemplateFinderPopup.IOnResult;
@ -53,6 +54,7 @@ import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Button;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.Constraint;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.Intbox;
@ -72,8 +74,18 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
private Vbox filter;
private Vbox orderFilter;
private BandboxSearch bdFilter;
private Datebox filterStartDate;
private Datebox filterFinishDate;
private BandboxMultipleSearch bdFilters;
private Checkbox checkIncludeOrderElements;
private OrderElementTreeitemRenderer renderer = new OrderElementTreeitemRenderer();
private final IOrderModel orderModel;
@ -174,6 +186,10 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
// Configuration of the order elements filter
orderFilter.setVisible(false);
filter.setVisible(true);
Component filterComponent = Executions.createComponents(
"/orders/_orderElementTreeFilter.zul",
filter, new HashMap<String, String>());
@ -455,7 +471,7 @@ public class OrderElementTreeController extends TreeController<OrderElement> {
*/
public void clear() {
selectDefaultTab();
// bdFilter.clear();
bdFilter.clear();
predicate = null;
}

View file

@ -149,6 +149,9 @@ public class OrderModel implements IOrderModel {
@Autowired
private IUserDAO userDAO;
private List<Order> orderList = new ArrayList<Order>();
@Override
@Transactional(readOnly = true)
public List<Label> getLabels() {
@ -691,4 +694,21 @@ public class OrderModel implements IOrderModel {
return result.toString();
}
/*
* Operation to filter the order list
*/
@Override
@Transactional(readOnly = true)
public List<Order> getFilterOrders(OrderPredicate predicate) {
List<Order> filterOrderList = new ArrayList<Order>();
for (Order order : orderList) {
orderDAO.reattachUnmodifiedEntity(order);
if (predicate.accepts(order)) {
filterOrderList.add(order);
}
}
return filterOrderList;
}
}

View file

@ -0,0 +1,229 @@
/*
* This file is part of ###PROJECT_NAME###
*
* Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.navalplanner.web.orders;
import java.util.Date;
import java.util.List;
import org.navalplanner.business.externalcompanies.entities.ExternalCompany;
import org.navalplanner.business.labels.entities.Label;
import org.navalplanner.business.orders.entities.Order;
import org.navalplanner.business.orders.entities.OrderElement;
import org.navalplanner.business.orders.entities.OrderStatusEnum;
import org.navalplanner.business.requirements.entities.CriterionRequirement;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.workreports.entities.WorkReport;
import org.navalplanner.business.workreports.entities.WorkReportType;
import org.navalplanner.web.common.components.finders.FilterPair;
/**
* Checks if {@link WorkReportType}, the start date and finish date from
* {@link WorkReport} matches attributes
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
public class OrderPredicate implements IPredicate {
private List<FilterPair> filters;
private Date startDate;
private Date finishDate;
private Boolean includeOrderElements;
public OrderPredicate(List<FilterPair> filters, Date startDate,
Date finishDate, Boolean includeOrderElements) {
this.filters = filters;
this.startDate = startDate;
this.finishDate = finishDate;
this.includeOrderElements = includeOrderElements;
}
@Override
public boolean accepts(Object object) {
final Order order = (Order) object;
return accepts(order);
}
private boolean accepts(Order order) {
if (order == null) {
return false;
}
if (acceptFilters(order) && acceptFiltersDates(order)) {
return true;
}
return false;
}
private boolean acceptFilters(Order order) {
if ((filters == null) || (filters.isEmpty())) {
return true;
}
for (FilterPair filter : filters) {
if (!acceptFilter(filter, order)) {
return false;
}
}
return true;
}
private boolean acceptFilter(FilterPair filter,Order order){
switch (filter.getType()) {
case Criterion:
return acceptCriterion(filter, order);
case Label:
return acceptLabel(filter, order);
case ExternalCompany:
return acceptExternalCompany(filter, order);
case State:
return acceptState(filter, order);
case Code:
return acceptCode(filter, order);
case CustomerReference:
return acceptCustomerReference(filter, order);
}
return false;
}
private boolean acceptCriterion(FilterPair filter, Order order) {
Criterion filterCriterion = (Criterion) filter.getValue();
if (existCriterionInOrderElement(filterCriterion, order)) {
return true;
}
if (includeOrderElements) {
for (OrderElement orderElement : order.getAllOrderElements()) {
if (existCriterionInOrderElement(filterCriterion, orderElement)) {
return true;
}
}
}
return false;
}
private boolean existCriterionInOrderElement(Criterion filterCriterion,
OrderElement order) {
for(CriterionRequirement criterionRequirement : order.getCriterionRequirements()){
if(criterionRequirement.getCriterion().getId().equals(filterCriterion.getId())){
return true;
}
}
return false;
}
private boolean acceptLabel(FilterPair filter,Order order) {
Label filterLabel = (Label) filter.getValue();
if (existLabelInOrderElement(filterLabel, order)) {
return true;
}
if (this.includeOrderElements) {
for (OrderElement orderElement : order.getAllOrderElements()) {
if (existLabelInOrderElement(filterLabel, orderElement)) {
return true;
}
}
}
return false;
}
private boolean existLabelInOrderElement(Label filterLabel,
OrderElement order) {
for(Label label : order.getLabels()){
if(label.getId().equals(filterLabel.getId())){
return true;
}
}
return false;
}
private boolean acceptExternalCompany(FilterPair filter,Order order) {
ExternalCompany filterCustomer = (ExternalCompany) filter.getValue();
if ((order.getCustomer() == null)
|| (order.getCustomer().getId().equals(filterCustomer.getId()))) {
return true;
}
return false;
}
private boolean acceptState(FilterPair filter,Order order) {
OrderStatusEnum filterState = (OrderStatusEnum) filter.getValue();
if ((order.getState() == null)
|| (order.getState().equals(filterState))) {
return true;
}
return false;
}
private boolean acceptCode(FilterPair filter,Order order) {
String filterCode = (String) filter.getValue();
return order.getCode().equals(filterCode);
}
private boolean acceptCustomerReference(FilterPair filter,Order order) {
String filterCustomerReference = (String) filter.getValue();
return order.getCustomerReference().equals(filterCustomerReference);
}
private boolean acceptFiltersDates(Order order) {
// Check if exist work report items into interval between the start date
// and finish date.
if ((isInTheRangeFilterDates(order.getInitDate()) || isInTheRangeFilterDates(order.getDeadline()))
|| ((isInTheRangeWorkReportDates(startDate, order)) || (isInTheRangeWorkReportDates(
finishDate, order)))) {
return true;
}
return false;
}
private boolean isInTheRangeFilterDates(Date date) {
// Check if date is into interval between the startdate and finish date
return (isGreaterToStartDate(date, startDate) && isLowerToFinishDate(
date, finishDate));
}
private boolean isInTheRangeWorkReportDates(Date date,
Order order) {
// Check if date is into interval between the startdate and finish date
return (isGreaterToStartDate(date, order.getInitDate()) && isLowerToFinishDate(
date, order.getDeadline()));
}
private boolean isGreaterToStartDate(Date date, Date startDate) {
if (startDate == null) {
return true;
}
if (date != null && (date.compareTo(startDate) >= 0)) {
return true;
}
return false;
}
private boolean isLowerToFinishDate(Date date, Date finishDate) {
if (finishDate == null) {
return true;
}
if (date != null && (date.compareTo(finishDate) <= 0)) {
return true;
}
return false;
}
}

View file

@ -35,6 +35,12 @@
<macro-uri>/common/components/bandbox_search.zul</macro-uri>
</component>
<component>
<component-name>bandboxMultipleSearch</component-name>
<component-class>org.navalplanner.web.common.components.bandboxsearch.BandboxMultipleSearch</component-class>
<macro-uri>/common/components/bandbox_search.zul</macro-uri>
</component>
<component>
<component-name>newdatasortablecolumn</component-name>
<component-class>org.navalplanner.web.common.components.NewDataSortableColumn</component-class>

View file

@ -0,0 +1,14 @@
<hbox align="center" style="margin-left:240px;">
<!-- Filter by -->
<label>Filter order:</label>
<bandboxMultipleSearch id="bdFilters" widthBandbox="285px" widthListbox="300px"
finder="MultipleFiltersFinder"/>
<label value="${i18n:_('from')}"/>
<datebox id="filterStartDate" constraint = "@{controller.checkConstraintStartDate}"/>
<label value="${i18n:_('to')}"/>
<datebox id="filterFinishDate" constraint = "@{controller.checkConstraintFinishDate}"/>
<label value="${i18n:_('include order elements')}"/>
<checkbox id="checkIncludeOrderElements"/>
<button label="${i18n:_('Filter')}" style="margin-top: -4px"
onClick="controller.onApplyFilter()"/>
</hbox>

View file

@ -27,13 +27,12 @@
<borderlayout sclass="orderslayout" width="auto" apply="${orderController}">
<north height="30px" border="0">
<hbox align="center" id="toolbar">
<templateFinderPopup id="templateFinderPopup" acceptButtonLabel="${i18n:_('Create Order')}" caption="${i18n:_('Choosing Template')}" />
<separator/>
<button label="New order" tooltiptext="${i18n:_('Create new order')}" class="planner-command"/>
<button label="Save" tooltiptext="${i18n:_('Save order')}" class="planner-command" disabled="true"/>
<separator/>
<vbox id="filter" />
</hbox>
<templateFinderPopup id="templateFinderPopup" acceptButtonLabel="${i18n:_('Create Order')}" caption="${i18n:_('Choosing Template')}" />
<button label="New order" tooltiptext="${i18n:_('Create new order')}" class="planner-command"/>
<button label="Save" tooltiptext="${i18n:_('Save order')}" class="planner-command" disabled="true"/>
<vbox id="orderFilter" visible="false"/>
<vbox id="filter" />
</hbox>
</north>
<center border="0" class="orderslayout-area">