ItEr35S14CUAdministracionMateriaisItEr34S14: Added Materials Category tree box to CustomMenuController

* List material categories
* Add and remove category to category tree
This commit is contained in:
Diego Pino Garcia 2009-11-23 10:47:00 +01:00 committed by Javier Moran Rua
parent 06a5b199a4
commit ca01aa8b9a
8 changed files with 436 additions and 0 deletions

View file

@ -320,4 +320,8 @@ public class MutableTreeModel<T> extends AbstractTreeModel {
}
}
public boolean isEmpty() {
return getChildCount(getRoot()) == 0;
}
}

View file

@ -20,6 +20,8 @@
package org.navalplanner.business.materials.daos;
import java.util.List;
import org.navalplanner.business.common.daos.IGenericDAO;
import org.navalplanner.business.materials.entities.MaterialCategory;
@ -30,4 +32,8 @@ import org.navalplanner.business.materials.entities.MaterialCategory;
*/
public interface IMaterialCategoryDAO extends IGenericDAO<MaterialCategory, Long> {
List<MaterialCategory> getAll();
List<MaterialCategory> getAllRootMaterialCategories();
}

View file

@ -20,6 +20,9 @@
package org.navalplanner.business.materials.daos;
import java.util.List;
import org.hibernate.criterion.Restrictions;
import org.navalplanner.business.common.daos.GenericDAOHibernate;
import org.navalplanner.business.materials.entities.MaterialCategory;
import org.springframework.beans.factory.config.BeanDefinition;
@ -36,4 +39,15 @@ import org.springframework.stereotype.Repository;
public class MaterialCategoryDAO extends GenericDAOHibernate<MaterialCategory, Long> implements
IMaterialCategoryDAO {
@Override
public List<MaterialCategory> getAll() {
return list(MaterialCategory.class);
}
@SuppressWarnings("unchecked")
@Override
public List<MaterialCategory> getAllRootMaterialCategories() {
return getSession().createCriteria(MaterialCategory.class).add(Restrictions.isNull("parent")).list();
}
}

View file

@ -185,6 +185,7 @@ public class CustomMenuController extends Div implements IMenuItemsRegister {
"/resources/criterions/criterions-V2.zul"),
subItem(_("Calendars"), "/calendars/calendars.zul"),
subItem(_("Label types"), "/labels/labelTypes.zul"),
subItem(_("Materials"), "/materials/materials.zul"),
subItem(_("Configuration"), "/common/configuration.zul"));
topItem(_("Quality management"), "/", true);

View file

@ -0,0 +1,40 @@
/*
* 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.materials;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.materials.entities.MaterialCategory;
import org.zkoss.ganttz.util.MutableTreeModel;
/**
*
* @author Diego Pino Garcia <dpino@igalia.com>
*
*/
public interface IMaterialsModel {
void addMaterialCategory(MaterialCategory parent, MaterialCategory child) throws ValidationException;
MutableTreeModel<MaterialCategory> getMaterialCategories();
void removeMaterialCategory(MaterialCategory materialCategory);
}

View file

@ -0,0 +1,225 @@
/*
* 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.materials;
import static org.navalplanner.web.I18nHelper._;
import java.util.Collection;
import org.apache.commons.logging.LogFactory;
import org.hibernate.validator.InvalidValue;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.materials.entities.Material;
import org.navalplanner.business.materials.entities.MaterialCategory;
import org.navalplanner.web.common.IMessagesForUser;
import org.navalplanner.web.common.Level;
import org.springframework.beans.factory.annotation.Autowired;
import org.zkoss.zk.ui.Component;
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.Events;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Button;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Tree;
import org.zkoss.zul.TreeModel;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treechildren;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.TreeitemRenderer;
import org.zkoss.zul.Treerow;
/**
* Controller for {@link Material} materials
*
* @author Diego Pino García <dpino@igalia.com>
*
*/
public class MaterialsController extends
GenericForwardComposer {
private static final org.apache.commons.logging.Log LOG = LogFactory.getLog(MaterialsController.class);
@Autowired
private IMaterialsModel materialsModel;
private Tree categoriesTree;
private Textbox txtCategory;
private IMessagesForUser messagesForUser;
private Component messagesContainer;
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
comp.setVariable("materialsController", this, true);
}
public TreeModel getMaterialCategories() {
return materialsModel.getMaterialCategories();
}
public MaterialCategoryRenderer getMaterialCategoryRenderer() {
return new MaterialCategoryRenderer();
}
/**
* Render for criterionsTree
*
* I had to implement a renderer for the Tree, for setting open to tree for
* each treeitem while being rendered.
*
* I tried to do this by iterating through the list of items after setting
* model in doAfterCompose, but I got a ConcurrentModificationException. It
* seems that at that point some other component was using the list of item,
* so it was not possible to modify it. There's not other point where to
* initialize components but doAfterCompose.
*
* Finally, I tried this solution and it works.
*
* @author Diego Pino Garcia <dpino@igalia.com>
*
*/
private class MaterialCategoryRenderer implements TreeitemRenderer {
/**
* Copied verbatim from org.zkoss.zul.Tree;
*/
@Override
public void render(Treeitem ti, Object node) throws Exception {
final MaterialCategory materialCategory = (MaterialCategory) node;
Textbox tb = new Textbox(materialCategory.getName());
Treecell tc = new Treecell();
Treerow tr = null;
ti.setValue(node);
if (ti.getTreerow() == null) {
tr = new Treerow();
tr.setParent(ti);
ti.setOpen(true); // Expand node
} else {
tr = ti.getTreerow();
tr.getChildren().clear();
}
tb.setParent(tc);
tc.setParent(tr);
appendDeleteButton(ti);
}
}
private void appendDeleteButton(final Treeitem ti) {
final MaterialCategory materialCategory = (MaterialCategory) ti.getValue();
Button btnDelete = new Button("", "/common/img/ico_borrar1.png");
btnDelete.setHoverImage("/common/img/ico_borrar.png");
btnDelete.setSclass("icono");
btnDelete.setTooltiptext(_("Delete"));
btnDelete.addEventListener(Events.ON_CLICK, new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
confirmRemove(materialCategory);
}
});
btnDelete.setDisabled(hasSubcategoriesOrMaterials(materialCategory));
Treecell tc = new Treecell();
tc.setParent(ti.getTreerow());
btnDelete.setParent(tc);
}
private boolean hasSubcategoriesOrMaterials(MaterialCategory materialCategory) {
return materialCategory.getSubcategories() == null || !materialCategory.getSubcategories().isEmpty();
}
public void confirmRemove(MaterialCategory materialCategory) {
try {
int status = Messagebox.show(_("Confirm deleting {0}. Are you sure?",
materialCategory.getName()), _("Delete"),
Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION);
if (Messagebox.OK == status) {
removeMaterialCategory(materialCategory);
}
} catch (InterruptedException e) {
messagesForUser.showMessage(Level.ERROR, e.getMessage());
LOG.error(_("Error on showing removing element: ", materialCategory.getId()), e);
}
}
private void removeMaterialCategory(MaterialCategory materialCategory) {
materialsModel.removeMaterialCategory(materialCategory);
}
public void addMaterialCategory() {
String categoryName = txtCategory.getValue();
if (categoryName == null || categoryName.isEmpty()) {
throw new WrongValueException(txtCategory, _("cannot be null or empty"));
}
final MaterialCategory category = MaterialCategory.create(_(categoryName));
MaterialCategory parent = null;
final Treeitem treeitem = categoriesTree.getSelectedItem();
if (treeitem != null) {
parent = (MaterialCategory) treeitem.getValue();
}
try {
materialsModel.addMaterialCategory(parent, category);
txtCategory.setValue("");
} catch (ValidationException e) {
for (InvalidValue invalidValue : e.getInvalidValues()) {
Object value = invalidValue.getBean();
if (value instanceof MaterialCategory) {
MaterialCategory materialCategory = (MaterialCategory) value;
Component comp = findInMaterialCategoryTree(materialCategory);
if (comp != null) {
throw new WrongValueException(comp, invalidValue.getMessage());
}
}
}
}
}
private Component findInMaterialCategoryTree(MaterialCategory materialCategory) {
final Treechildren children = categoriesTree.getTreechildren();
for(Treeitem each: (Collection<Treeitem>) children.getItems()) {
final MaterialCategory _materialCategory = (MaterialCategory) each.getValue();
final Textbox textbox = getMaterialCategoryTextbox(each);
// Clear previous errors
textbox.clearErrorMessage();
if (_materialCategory.equals(materialCategory)) {
return textbox;
}
}
return null;
}
private Textbox getMaterialCategoryTextbox(Treeitem treeitem) {
final Treerow tr = treeitem.getTreerow();
final Treecell tc = (Treecell) tr.getChildren().get(0);
return (Textbox) tc.getChildren().get(0);
}
}

View file

@ -0,0 +1,92 @@
package org.navalplanner.web.materials;
import static org.navalplanner.web.I18nHelper._;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.Validate;
import org.hibernate.validator.InvalidValue;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.business.materials.daos.IMaterialCategoryDAO;
import org.navalplanner.business.materials.entities.MaterialCategory;
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.ganttz.util.MutableTreeModel;
@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class MaterialsModel implements IMaterialsModel {
@Autowired
IMaterialCategoryDAO categoryDAO;
MutableTreeModel<MaterialCategory> materialCategories = MutableTreeModel.create(MaterialCategory.class);
private void initializeMaterialCategories() {
final List<MaterialCategory> categories = categoryDAO.getAllRootMaterialCategories();
for (MaterialCategory materialCategory: categories) {
materialCategories.addToRoot(materialCategory);
addCategories(materialCategory, materialCategory.getSubcategories());
}
}
private void addCategories(MaterialCategory materialCategory, Set<MaterialCategory> categories) {
for (MaterialCategory category: categories) {
materialCategories.add(materialCategory, category);
final Set<MaterialCategory> subcategories = category.getSubcategories();
if (subcategories != null) {
addCategories(category, subcategories);
}
}
}
@Transactional(readOnly=true)
public MutableTreeModel<MaterialCategory> getMaterialCategories() {
if (materialCategories.isEmpty()) {
initializeMaterialCategories();
}
return materialCategories;
}
@Override
public void addMaterialCategory(MaterialCategory parent, MaterialCategory child) throws ValidationException {
Validate.notNull(child);
final MaterialCategory materialCategory = findMaterialCategory(parent, child);
if (materialCategory != null) {
final InvalidValue invalidValue = new InvalidValue(_("{0} already exists", materialCategory.getName()),
MaterialCategory.class, "name", materialCategory.getName(), materialCategory);
throw new ValidationException(invalidValue);
}
if (parent == null) {
materialCategories.addToRoot(child);
} else {
materialCategories.add(parent, child);
}
}
private MaterialCategory findMaterialCategory(final MaterialCategory parent, final MaterialCategory category) {
for (int i = 0; i < materialCategories.getChildCount(parent); i++) {
final MaterialCategory each = materialCategories.getChild(parent, i);
if (equalsMaterialCategory(each, category)) {
return each;
}
}
return null;
}
private boolean equalsMaterialCategory(MaterialCategory obj1, MaterialCategory obj2) {
return obj1.getName().equals(obj2.getName());
}
@Override
public void removeMaterialCategory(MaterialCategory materialCategory) {
materialCategories.remove(materialCategory);
}
}

View file

@ -0,0 +1,54 @@
<!--
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/>.
-->
<?page id="labelTypesList"?>
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<?init class="org.zkoss.zk.ui.util.Composition" arg0="/common/layout/template.zul"?>
<?link rel="stylesheet" type="text/css" href="/common/css/navalpro_v01.css"?>
<?link rel="stylesheet" type="text/css" href="/common/css/navalpro_zk.css"?>
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<zk>
<window self="@{define(content)}"
apply="org.navalplanner.web.materials.MaterialsController" >
<vbox id="messagesContainer" />
<vbox>
<panel title="${i18n:_('Categories')}" border="normal">
<panelchildren>
<textbox id="txtCategory" style="margin-bottom: 4px;" />
<button label="${i18n:_('Add')}" onClick="materialsController.addMaterialCategory()"/>
<tree id="categoriesTree" width="280px" rows="10"
vflex="true" multiple="true"
model="@{materialsController.materialCategories}"
treeitemRenderer="@{materialsController.materialCategoryRenderer}">
<treecols>
<treecol label="Name" />
<treecol label="" />
</treecols>
</tree>
</panelchildren>
</panel>
</vbox>
</window>
</zk>