ItEr14S11CUConfiguracionDeOrganizacionsDeTraballoConUnidadesTraballoItEr13S13: Added popup for editing TaksWork. Just interface work was done.

This commit is contained in:
Manuel Rego Casasnovas 2009-06-24 10:45:56 +02:00 committed by Javier Moran Rua
parent df70af8fef
commit 7235c2e4a1
6 changed files with 576 additions and 6 deletions

View file

@ -1,5 +1,6 @@
package org.navalplanner.web.common; package org.navalplanner.web.common;
import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Component;
@ -7,7 +8,9 @@ import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.InputEvent; import org.zkoss.zk.ui.event.InputEvent;
import org.zkoss.zkplus.databind.DataBinder; import org.zkoss.zkplus.databind.DataBinder;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.Datebox; import org.zkoss.zul.Datebox;
import org.zkoss.zul.Decimalbox;
import org.zkoss.zul.Intbox; import org.zkoss.zul.Intbox;
import org.zkoss.zul.Textbox; import org.zkoss.zul.Textbox;
@ -204,4 +207,96 @@ public class Util {
return dateBox; return dateBox;
} }
/**
* Binds a {@link Decimalbox} with a {@link Getter}. The {@link Getter} will
* be used to get the value that is going to be showed in the
* {@link Decimalbox}.
*
* @param decimalBox
* The {@link Decimalbox} to be bound
* @param getter
* The {@link Getter} interface that will implement a get method.
* @return The {@link Decimalbox} bound
*/
public static Decimalbox bind(final Decimalbox decimalBox,
final Getter<BigDecimal> getter) {
decimalBox.setValue(getter.get());
decimalBox.setDisabled(true);
return decimalBox;
}
/**
* Binds a {@link Decimalbox} with a {@link Getter}. The {@link Getter} will
* be used to get the value that is going to be showed in the
* {@link Decimalbox}. The {@link Setter} will be used to store the value
* inserted by the user in the {@link Decimalbox}.
*
* @param decimalBox
* The {@link Decimalbox} to be bound
* @param getter
* The {@link Getter} interface that will implement a get method.
* @param setter
* The {@link Setter} interface that will implement a set method.
* @return The {@link Decimalbox} bound
*/
public static Decimalbox bind(final Decimalbox decimalBox,
final Getter<BigDecimal> getter, final Setter<BigDecimal> setter) {
decimalBox.setValue(getter.get());
decimalBox.addEventListener("onChange", new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
setter.set(decimalBox.getValue());
decimalBox.setValue(getter.get());
}
});
return decimalBox;
}
/**
* Binds a {@link Checkbox} with a {@link Getter}. The {@link Getter} will
* be used to get the value that is going to be showed in the
* {@link Checkbox}.
*
* @param decimalBox
* The {@link Checkbox} to be bound
* @param getter
* The {@link Getter} interface that will implement a get method.
* @return The {@link Checkbox} bound
*/
public static Checkbox bind(final Checkbox checkBox,
final Getter<Boolean> getter) {
checkBox.setChecked(getter.get());
checkBox.setDisabled(true);
return checkBox;
}
/**
* Binds a {@link Checkbox} with a {@link Getter}. The {@link Getter} will
* be used to get the value that is going to be showed in the
* {@link Checkbox}. The {@link Setter} will be used to store the value
* inserted by the user in the {@link Checkbox}.
*
* @param decimalBox
* The {@link Checkbox} to be bound
* @param getter
* The {@link Getter} interface that will implement a get method.
* @param setter
* The {@link Setter} interface that will implement a set method.
* @return The {@link Checkbox} bound
*/
public static Checkbox bind(final Checkbox checkBox,
final Getter<Boolean> getter, final Setter<Boolean> setter) {
checkBox.setChecked(getter.get());
checkBox.addEventListener("onChange", new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
setter.set(checkBox.isChecked());
checkBox.setChecked(getter.get());
}
});
return checkBox;
}
} }

View file

@ -129,14 +129,19 @@ public class ProjectWorkCRUDController extends GenericForwardComposer {
messagesForUser = new MessagesForUser(messagesContainer); messagesForUser = new MessagesForUser(messagesContainer);
comp.setVariable("controller", this, true); comp.setVariable("controller", this, true);
getVisibility().showOnly(listWindow); getVisibility().showOnly(listWindow);
setupTaskTreeController(comp, "editWindow");
setupTaskTreeController(comp, "createWindow"); TaskWorkController taskWorkController = new TaskWorkController();
taskWorkController.doAfterCompose(comp.getFellow("editTaskWorkPopup"));
setupTaskTreeController(comp, "editWindow", taskWorkController);
setupTaskTreeController(comp, "createWindow", taskWorkController);
} }
private void setupTaskTreeController(Component comp, String window) private void setupTaskTreeController(Component comp, String window,
TaskWorkController taskWorkController)
throws Exception { throws Exception {
TaskWorksTreeController controller = new TaskWorksTreeController( TaskWorksTreeController controller = new TaskWorksTreeController(
projectWorkModel); projectWorkModel, taskWorkController);
controller controller
.doAfterCompose(comp.getFellow(window).getFellow("tasksTree")); .doAfterCompose(comp.getFellow(window).getFellow("tasksTree"));
} }

View file

@ -0,0 +1,373 @@
package org.navalplanner.web.workorders;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.navalplanner.business.workorders.entities.ActivityWork;
import org.navalplanner.business.workorders.entities.ProjectWork;
import org.navalplanner.business.workorders.entities.TaskWork;
import org.navalplanner.business.workorders.entities.TaskWorkContainer;
import org.navalplanner.business.workorders.entities.TaskWorkLeaf;
import org.navalplanner.business.workorders.entities.ActivityWork.HoursPolicies;
import org.navalplanner.web.common.Util;
import org.zkoss.zk.ui.Component;
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.Checkbox;
import org.zkoss.zul.Decimalbox;
import org.zkoss.zul.Intbox;
import org.zkoss.zul.Label;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.Popup;
import org.zkoss.zul.Textbox;
/**
* Controller for {@link TaskWork} view of {@link ProjectWork} entities <br />
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
*/
public class TaskWorkController extends GenericForwardComposer {
/**
* {@link TaskWork} that is managed
*/
private TaskWork taskWork;
/**
* {@link Popup} where {@link TaskWork} edition form is showed
*/
private Popup popup;
/**
* Model of the {@link ActivityWork} list
*/
private List<ActivityWork> activityWorksModel;
/**
* {@link Listitem} for every {@link ActivityWork}
*/
private AcitivyWorkListitemRender renderer = new AcitivyWorkListitemRender();
/**
* {@link Listbox} where {@link ActivityWork} are shown
*/
private Listbox activityWorksListbox;
public TaskWork getTaskWork() {
return taskWork;
}
public List<ActivityWork> getActivityWorksModel() {
return activityWorksModel;
}
public AcitivyWorkListitemRender getRenderer() {
return renderer;
}
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
comp.setVariable("taskWorkController", this, true);
popup = (Popup) comp;
}
/**
* Open the popup to edit a {@link TaskWork}. If it's a
* {@link TaskWorkContainer} less fields will be enabled.
*
* @param taskWork
* The {@link TaskWork} to be edited
*/
public void openPopup(TaskWork taskWork) {
this.taskWork = taskWork;
this.activityWorksModel = taskWork.getActivities();
// If is a container
if (taskWork instanceof TaskWorkContainer) {
// Disable fields just used in the TaskWorkLeaf
((Textbox) popup.getFellow("totalHours")).setDisabled(true);
// Hide not needed buttons
popup.getFellow("manageCriterions").setVisible(false);
popup.getFellow("addActivityWork").setVisible(false);
popup.getFellow("deleteActivityWork").setVisible(false);
} else {
// Enable fields just used in the TaskWorkLeaf
((Textbox) popup.getFellow("totalHours")).setDisabled(false);
// Show needed buttons
popup.getFellow("manageCriterions").setVisible(true);
popup.getFellow("addActivityWork").setVisible(true);
popup.getFellow("deleteActivityWork").setVisible(true);
}
fillFixedHoursCheckbox(taskWork);
Util.reloadBindings(popup);
popup.open(popup.getParent(), "start-after");
}
/**
* Private method that just fills the Div with id "fixedHoursCheckbox" in
* the .zul.
*
* If the parameter is a {@link TaskWorkLeaf} the method adds the needed
* checkbox.
*
* @param taskWork
* {@link TaskWork} that is been rendered
*/
private void fillFixedHoursCheckbox(final TaskWork taskWork) {
// Get the Div with id "fixedHoursCheckbox"
Component fixedHoursCheckbox = popup.getFellow("fixedHoursCheckbox");
// Empty the content of the Div
// Making a copy to avoid a ConcurrentModificationException
List<Component> children = new ArrayList<Component>(fixedHoursCheckbox
.getChildren());
for (Component component : children) {
fixedHoursCheckbox.removeChild(component);
}
// If is a leaf
if (taskWork instanceof TaskWorkLeaf) {
// Add specific fields
fixedHoursCheckbox.appendChild(Util.bind(new Checkbox(),
new Util.Getter<Boolean>() {
@Override
public Boolean get() {
return ((TaskWorkLeaf) taskWork).isFixedHours();
}
}, new Util.Setter<Boolean>() {
@Override
public void set(Boolean value) {
((TaskWorkLeaf) taskWork).setFixedHours(value);
}
}));
fixedHoursCheckbox.appendChild(new Label("Fixed hours"));
}
}
/**
* Just close the {@link Popup}
*/
public void cancel() {
popup.close();
}
/**
* Just close the {@link Popup} and refresh parent status. Save actions are
* managed by "save-when" at .zul file.
*/
public void save() {
popup.close();
Util.reloadBindings(popup.getParent());
}
/**
* Adds a new {@link ActivityWork} to the current {@link TaskWork}
*
* The {@link TaskWork} should be a {@link TaskWorkLeaf}
*/
public void addActivityWork() {
ActivityWork activity = new ActivityWork();
((TaskWorkLeaf) taskWork).addActivity(activity);
this.activityWorksModel = taskWork.getActivities();
Util.reloadBindings(popup);
}
/**
* Deletes the selected {@link ActivityWork} for the current
* {@link TaskWork}
*
* The {@link TaskWork} should be a {@link TaskWorkLeaf}
*/
public void deleteActivityWorks() {
Set<Listitem> selectedItems = activityWorksListbox.getSelectedItems();
for (Listitem item : selectedItems) {
((TaskWorkLeaf) taskWork).deleteActivity((ActivityWork) item
.getValue());
}
this.activityWorksModel = taskWork.getActivities();
Util.reloadBindings(popup);
}
/**
* Represents every {@link AcitivyWork} with an edition form if needed
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
*/
public class AcitivyWorkListitemRender implements ListitemRenderer {
@Override
public void render(Listitem item, Object data) throws Exception {
final ActivityWork activity = (ActivityWork) data;
item.setValue(activity);
Listcell cellWorkingHours = new Listcell();
cellWorkingHours.setParent(item);
Listcell cellPercentage = new Listcell();
cellPercentage.setParent(item);
Listcell cellHoursPolicy = new Listcell();
cellHoursPolicy.setParent(item);
// Generate hours policy Listbox
final Listbox hoursPolicyListBox = new Listbox();
hoursPolicyListBox.setRows(1);
hoursPolicyListBox.setMold("select");
for (HoursPolicies hourPolicy : HoursPolicies.values()) {
Listitem listitem = new Listitem();
listitem.setValue(hourPolicy);
listitem.setLabel(hourPolicy.toString());
listitem.setParent(hoursPolicyListBox);
}
// If is a container
if (taskWork instanceof TaskWorkContainer) {
// Just getters are needed
// Working hours
cellWorkingHours.appendChild(Util.bind(new Intbox(),
new Util.Getter<Integer>() {
@Override
public Integer get() {
return activity.getWorkingHours();
}
}));
// Percentage
cellPercentage.appendChild(Util.bind(new Decimalbox(),
new Util.Getter<BigDecimal>() {
@Override
public BigDecimal get() {
return activity.getPercentage();
}
}));
// Hours policy
hoursPolicyListBox.setSelectedIndex(activity.getHoursPolicy()
.ordinal());
hoursPolicyListBox.setDisabled(true);
cellHoursPolicy.appendChild(hoursPolicyListBox);
} else { // If is a leaf
final Intbox workingHours = Util.bind(new Intbox(),
new Util.Getter<Integer>() {
@Override
public Integer get() {
return activity.getWorkingHours();
}
}, new Util.Setter<Integer>() {
@Override
public void set(Integer value) {
activity.setWorkingHours(value);
}
});
final Decimalbox percentage = Util.bind(new Decimalbox(),
new Util.Getter<BigDecimal>() {
@Override
public BigDecimal get() {
return activity.getPercentage();
}
}, new Util.Setter<BigDecimal>() {
@Override
public void set(BigDecimal value) {
activity.setPercentage(value);
}
});
// Hours policy
hoursPolicyListBox.setSelectedIndex(activity.getHoursPolicy()
.ordinal());
hoursPolicyListBox.addEventListener(Events.ON_SELECT,
new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
HoursPolicies policy = (HoursPolicies) hoursPolicyListBox
.getSelectedItem().getValue();
activity.setHoursPolicy(policy);
// Disable components depending on the policy
disableComponents(workingHours, percentage,
policy);
}
});
// Disable components depending on the policy
disableComponents(workingHours, percentage,
(HoursPolicies) hoursPolicyListBox.getSelectedItem()
.getValue());
cellWorkingHours.appendChild(workingHours);
cellPercentage.appendChild(percentage);
cellHoursPolicy.appendChild(hoursPolicyListBox);
}
}
/**
* Disable workingHours and percentage components depending on the
* policy selected by the user.
*
* @param workingHours
* An {@link Intbox} for the workingHours
* @param percentage
* A {@link Decimalbox} for the percentage
* @param policy
* A {@link HoursPolicies} value
*/
public void disableComponents(Intbox workingHours,
Decimalbox percentage, HoursPolicies policy) {
switch (policy) {
case FIXED_PERCENTAGE:
// Working hours not editable
workingHours.setDisabled(true);
// Percentage editable
percentage.setDisabled(false);
break;
case NO_FIXED:
case FIXED_HOURS:
default:
// Working hours editable
workingHours.setDisabled(false);
// Percentage not editable
percentage.setDisabled(true);
break;
}
}
}
}

View file

@ -14,7 +14,9 @@ import org.navalplanner.business.workorders.entities.TaskWorkLeaf;
import org.navalplanner.web.common.Util; import org.navalplanner.web.common.Util;
import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.DropEvent; import org.zkoss.zk.ui.event.DropEvent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.util.GenericForwardComposer; import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Datebox; import org.zkoss.zul.Datebox;
import org.zkoss.zul.Intbox; import org.zkoss.zul.Intbox;
@ -27,8 +29,10 @@ import org.zkoss.zul.Treerow;
import org.zkoss.zul.api.Tree; import org.zkoss.zul.api.Tree;
/** /**
* Controller for {@link WorkOrganization} view of WorkOrder entitites <br /> * Controller for {@link WorkOrganization} view of WorkOrder entities <br />
*
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com> * @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
* @author Manuel Rego Casasnovas <mrego@igalia.com>
*/ */
public class TaskWorksTreeController extends GenericForwardComposer { public class TaskWorksTreeController extends GenericForwardComposer {
@ -40,12 +44,16 @@ public class TaskWorksTreeController extends GenericForwardComposer {
private final IProjectWorkModel projectWorkModel; private final IProjectWorkModel projectWorkModel;
private final TaskWorkController taskWorkController;
public TaskWorkTreeitemRenderer getRenderer() { public TaskWorkTreeitemRenderer getRenderer() {
return renderer; return renderer;
} }
public TaskWorksTreeController(IProjectWorkModel projectWorkModel) { public TaskWorksTreeController(IProjectWorkModel projectWorkModel,
TaskWorkController taskWorkController) {
this.projectWorkModel = projectWorkModel; this.projectWorkModel = projectWorkModel;
this.taskWorkController = taskWorkController;
} }
public void indent() { public void indent() {
@ -279,6 +287,7 @@ public class TaskWorksTreeController extends GenericForwardComposer {
taskWork.setEndDate(value); taskWork.setEndDate(value);
} }
})); }));
Treerow tr = null; Treerow tr = null;
/* /*
* Since only one treerow is allowed, if treerow is not null, append * Since only one treerow is allowed, if treerow is not null, append
@ -313,6 +322,15 @@ public class TaskWorksTreeController extends GenericForwardComposer {
} }
}); });
tr.addEventListener(Events.ON_DOUBLE_CLICK, new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
taskWorkController.openPopup(taskWork);
}
});
} }
private String pathAsString(int[] path) { private String pathAsString(int[] path) {
@ -326,4 +344,5 @@ public class TaskWorksTreeController extends GenericForwardComposer {
return result.toString(); return result.toString();
} }
} }
} }

View file

@ -0,0 +1,75 @@
<popup id="${arg.top_id}">
<vbox>
<label value="${arg.title}" />
<hbox>
<label value="Task Name" />
<textbox id="name"
value="@{taskWorkController.taskWork.name,
save-when='saveButton.onClick'}" />
</hbox>
<hbox>
<label value="Init Date" />
<datebox id="initDate"
value="@{taskWorkController.taskWork.initDate,
save-when='saveButton.onClick'}" />
<checkbox id="mandatoryInit"
checked="@{taskWorkController.taskWork.mandatoryInit},
save-when='saveButton.onClick'" />
<label value="Mandatory" />
</hbox>
<hbox>
<label value="End Date" />
<datebox id="endDate"
value="@{taskWorkController.taskWork.endDate,
save-when='saveButton.onClick'}" />
<checkbox id="mandatoryEnd"
checked="@{taskWorkController.taskWork.mandatoryEnd,
save-when='saveButton.onClick'}" />
<label value="Mandatory" />
</hbox>
<hbox>
<label value="Total hours" />
<textbox id="totalHours"
value="@{taskWorkController.taskWork.workHours}" />
<div id="fixedHoursCheckbox" />
</hbox>
<listbox id="activityWorksListbox" multiple="true"
model="@{taskWorkController.activityWorksModel}"
itemRenderer="@{taskWorkController.renderer}">
<listhead sizable="true">
<listheader label="Hours" />
<listheader label="%" />
<listheader label="Fixed" />
</listhead>
</listbox>
<hbox>
<button id="addActivityWork" label="Add activity work"
onClick="taskWorkController.addActivityWork();" />
<button id="deleteActivityWork" label="Delete activity work"
onClick="taskWorkController.deleteActivityWorks();" />
<button id="manageCriterions" label="Manage criterions" />
</hbox>
<textbox id="description" rows="4"
value="@{taskWorkController.taskWork.description,
save-when='saveButton.onClick'}" />
<hbox>
<button onClick="taskWorkController.cancel();"
label="${arg.cancel_button_label}" />
<button id="saveButton"
onClick="taskWorkController.save();"
label="${arg.save_button_label}" />
</hbox>
</vbox>
</popup>

View file

@ -7,6 +7,7 @@
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?> <?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<?component name="list" inline="true" macroURI="_list.zul"?> <?component name="list" inline="true" macroURI="_list.zul"?>
<?component name="edition" inline="true" macroURI="_edition.zul"?> <?component name="edition" inline="true" macroURI="_edition.zul"?>
<?component name="taskWorkPopup" inline="true" macroURI="_editTaskWork.zul"?>
<zk > <zk >
<window self="@{define(content)}" <window self="@{define(content)}"
apply="org.navalplanner.web.workorders.ProjectWorkCRUDController"> apply="org.navalplanner.web.workorders.ProjectWorkCRUDController">
@ -16,6 +17,8 @@
save_button_label="Save" cancel_button_label="Cancel" /> save_button_label="Save" cancel_button_label="Cancel" />
<edition top_id="editWindow" title="Edit Personal Data" <edition top_id="editWindow" title="Edit Personal Data"
save_button_label="Save" cancel_button_label="Cancel" /> save_button_label="Save" cancel_button_label="Cancel" />
<taskWorkPopup top_id="editTaskWorkPopup" title="Edit Task Work"
save_button_label="Save" cancel_button_label="Cancel" />
<window visible="@{controller.confirmingRemove}" <window visible="@{controller.confirmingRemove}"
id="confirmRemove" title="Confirmación" width="500px" id="confirmRemove" title="Confirmación" width="500px"
position="center"> position="center">