From 19da03932c8bb35afebaf4ff7f3e75932a35399c Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Wed, 2 Jun 2010 17:32:28 +0200 Subject: [PATCH] ItEr59S08CUAsignacionRecursosLimitantesItEr58S10: Refactor manual allocation window, set as an independent window --- .../LimitingResourcesController.java | 372 ++-------------- .../ManualAllocationController.java | 418 ++++++++++++++++++ .../limitingResourcesLayout.zul | 69 +-- .../limitingresources/manualAllocation.zul | 63 +++ 4 files changed, 513 insertions(+), 409 deletions(-) create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/ManualAllocationController.java create mode 100644 navalplanner-webapp/src/main/webapp/limitingresources/manualAllocation.zul diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java index 343f7c517..d3c11f544 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/LimitingResourcesController.java @@ -26,20 +26,14 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; -import org.joda.time.LocalDate; import org.navalplanner.business.orders.entities.Order; -import org.navalplanner.business.planner.entities.DateAndHour; import org.navalplanner.business.planner.entities.GenericResourceAllocation; -import org.navalplanner.business.planner.entities.LimitingResourceAllocator; import org.navalplanner.business.planner.entities.LimitingResourceQueueElement; -import org.navalplanner.business.planner.entities.LimitingResourceQueueElementGap; import org.navalplanner.business.planner.entities.ResourceAllocation; import org.navalplanner.business.planner.entities.SpecificResourceAllocation; import org.navalplanner.business.planner.entities.Task; @@ -57,30 +51,18 @@ import org.zkoss.ganttz.resourceload.IFilterChangedListener; import org.zkoss.ganttz.timetracker.TimeTracker; import org.zkoss.ganttz.timetracker.zoom.SeveralModificators; import org.zkoss.ganttz.timetracker.zoom.ZoomLevel; -import org.zkoss.zk.ui.SuspendNotAllowedException; -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.event.SelectEvent; -import org.zkoss.zk.ui.util.Clients; -import org.zkoss.zk.ui.util.Composer; +import org.zkoss.zk.ui.util.GenericForwardComposer; import org.zkoss.zul.Button; import org.zkoss.zul.Checkbox; -import org.zkoss.zul.Datebox; import org.zkoss.zul.Grid; import org.zkoss.zul.Hbox; 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.Messagebox; -import org.zkoss.zul.Radio; -import org.zkoss.zul.Radiogroup; import org.zkoss.zul.Row; import org.zkoss.zul.RowRenderer; -import org.zkoss.zul.SimpleListModel; import org.zkoss.zul.Window; /** @@ -89,7 +71,7 @@ import org.zkoss.zul.Window; */ @Component @Scope(BeanDefinition.SCOPE_PROTOTYPE) -public class LimitingResourcesController implements Composer { +public class LimitingResourcesController extends GenericForwardComposer { @Autowired private ILimitingResourceQueueModel limitingResourceQueueModel; @@ -108,20 +90,10 @@ public class LimitingResourcesController implements Composer { private Window manualAllocationWindow; - private Radiogroup radioAllocationDate; - - private Datebox startAllocationDate; - - private Map endAllocationDates = new HashMap(); - private final LimitingResourceQueueElementsRenderer limitingResourceQueueElementsRenderer = new LimitingResourceQueueElementsRenderer(); - private final QueueRenderer queueRenderer = new QueueRenderer(); - - private final CandidateGapRenderer candidateGapRenderer = new CandidateGapRenderer(); - - private transient IFilterChangedListener filterChangedListener; + private transient IFilterChangedListener filterChangedListener; public LimitingResourcesController() { } @@ -143,10 +115,6 @@ public class LimitingResourcesController implements Composer { reload(filterByResources); } - private Listbox listAssignableQueues; - - private Listbox listCandidateGaps; - private void reload(boolean filterByResources) { try { @@ -171,11 +139,8 @@ public class LimitingResourcesController implements Composer { gridUnassignedLimitingResourceQueueElements = (Grid) limitingResourcesPanel .getFellowIfAny("gridUnassignedLimitingResourceQueueElements"); - manualAllocationWindow = (Window) limitingResourcesPanel.getFellowIfAny("manualAllocationWindow"); - listAssignableQueues = (Listbox) manualAllocationWindow.getFellowIfAny("listAssignableQueues"); - listCandidateGaps = (Listbox) manualAllocationWindow.getFellowIfAny("listCandidateGaps"); - radioAllocationDate = (Radiogroup) manualAllocationWindow.getFellowIfAny("radioAllocationDate"); - startAllocationDate = (Datebox) manualAllocationWindow.getFellowIfAny("startAllocationDate"); + + initManualAllocationWindow(); addCommands(limitingResourcesPanel); } catch (IllegalArgumentException e) { @@ -189,6 +154,18 @@ public class LimitingResourcesController implements Composer { } } + private void initManualAllocationWindow() { + manualAllocationWindow = (Window) limitingResourcesPanel.getFellowIfAny("manualAllocationWindow"); + ManualAllocationController manualAllocationController = (ManualAllocationController) manualAllocationWindow + .getVariable("manualAllocationController", true); + manualAllocationController.setLimitingResourcesController(this); + manualAllocationController.setLimitingResourcesPanel(limitingResourcesPanel); + } + + public ILimitingResourceQueueModel getLimitingResourceQueueModel() { + return limitingResourceQueueModel; + } + private void addListeners() { filterChangedListener = new IFilterChangedListener() { @@ -451,20 +428,6 @@ public class LimitingResourcesController implements Composer { } - private void showManualAllocationWindow(LimitingResourceQueueElement element) { - try { - setAssignableQueues(element); - limitingResourceQueueModel.init(element); - manualAllocationWindow.doModal(); - } catch (SuspendNotAllowedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - public List getLimitingResourceQueues() { return limitingResourceQueueModel.getLimitingResourceQueues(); } @@ -474,299 +437,18 @@ public class LimitingResourcesController implements Composer { Util.reloadBindings(gridUnassignedLimitingResourceQueueElements); } - private void feedValidGaps(LimitingResourceQueueElement element, LimitingResourceQueue queue) { - feedValidGapsSince(element, queue, getStartDayBecauseOfGantt(element)); - } - - private DateAndHour getStartDayBecauseOfGantt(LimitingResourceQueueElement element) { - return new DateAndHour(new LocalDate(element.getEarlierStartDateBecauseOfGantt()), 0); - } - - private void feedValidGapsSince(LimitingResourceQueueElement element, LimitingResourceQueue queue, DateAndHour since) { - List gaps = LimitingResourceAllocator.getValidGapsForElementSince(element, queue, since); - endAllocationDates = calculateEndAllocationDates(element.getResourceAllocation(), queue.getResource(), gaps); - listCandidateGaps.setModel(new SimpleListModel(gaps)); - if (!gaps.isEmpty()) { - listCandidateGaps.setSelectedIndex(0); - setStartAllocationDate(gaps.get(0).getStartTime()); - startAllocationDate.setDisabled(true); - disable(radioAllocationDate, false); - } else { - disable(radioAllocationDate, true); - } - radioAllocationDate.setSelectedIndex(0); - } - - private void setStartAllocationDate(DateAndHour time) { - final Date date = (time != null) ? toDate(time.getDate()) : null; - startAllocationDate.setValue(date); - } - - private Map calculateEndAllocationDates( - ResourceAllocation resourceAllocation, Resource resource, - List gaps) { - - Map result = new HashMap(); - for (LimitingResourceQueueElementGap each: gaps) { - result.put(each, calculateEndAllocationDate(resourceAllocation, resource, each)); - } - return result; - } - - private DateAndHour calculateEndAllocationDate( - ResourceAllocation resourceAllocation, Resource resource, - LimitingResourceQueueElementGap gap) { - - if (gap.getEndTime() != null) { - return LimitingResourceAllocator.startTimeToAllocateStartingFromEnd(resourceAllocation, resource, gap); - } - return null; - } - - public void selectRadioAllocationDate(Event event) { - Radiogroup radiogroup = (Radiogroup) event.getTarget().getParent(); - startAllocationDate.setDisabled(radiogroup.getSelectedIndex() != 2); - } - - private void disable(Radiogroup radiogroup, boolean disabled) { - for (Object obj: radiogroup.getChildren()) { - final Radio each = (Radio) obj; - each.setDisabled(disabled); - } - } - - public CandidateGapRenderer getCandidateGapRenderer() { - return candidateGapRenderer; - } - - private class CandidateGapRenderer implements ListitemRenderer { - - @Override - public void render(Listitem item, Object data) throws Exception { - LimitingResourceQueueElementGap gap = (LimitingResourceQueueElementGap) data; - - item.setValue(gap); - item.appendChild(cell(gap.getStartTime())); - item.appendChild(cell(gap.getEndTime())); - } - - public Listcell cell(DateAndHour time) { - return new Listcell(formatTime(time)); - } - - private String formatTime(DateAndHour time) { - return time == null ? _("END") : time.getDate().toString("dd/MM/yyyy") + " - " + time.getHour(); - } - - } - - private void setAssignableQueues(final LimitingResourceQueueElement element) { - List queues = limitingResourceQueueModel.getAssignableQueues(element); - listAssignableQueues.setModel(new SimpleListModel(queues)); - listAssignableQueues.addEventListener(Events.ON_SELECT, new EventListener() { - - @Override - public void onEvent(Event event) throws Exception { - SelectEvent se = (SelectEvent) event; - - LimitingResourceQueue queue = getSelectedQueue(se); - if (queue != null) { - feedValidGaps(element, queue); - } - } - - public LimitingResourceQueue getSelectedQueue(SelectEvent se) { - final Listitem item = (Listitem) se.getSelectedItems().iterator().next(); - return (LimitingResourceQueue) item.getValue(); - } - - }); - listAssignableQueues.setSelectedIndex(0); - feedValidGaps(element, queues.get(0)); - } - - private LimitingResourceQueue getSelectedQueue() { - LimitingResourceQueue result = null; - - final Listitem item = listAssignableQueues.getSelectedItem(); - if (item != null) { - result = (LimitingResourceQueue) item.getValue(); - } - return result; - } - - public ListitemRenderer getQueueRenderer() { - return queueRenderer; - } - - private class QueueRenderer implements ListitemRenderer { - - @Override - public void render(Listitem item, Object data) throws Exception { - final LimitingResourceQueue queue = (LimitingResourceQueue) data; - item.setValue(queue); - item.appendChild(cell(queue)); - } - - private Listcell cell(LimitingResourceQueue queue) { - Listcell result = new Listcell(); - result.setLabel(queue.getResource().getName()); - return result; - } - - } - - public void accept(Event e) { - final LimitingResourceQueue queue = getSelectedQueue(); - final DateAndHour time = getSelectedAllocationTime(); - Validate.notNull(time); - limitingResourceQueueModel - .assignEditingLimitingResourceQueueElementToQueueAt(queue, time); - Util.reloadBindings(gridUnassignedLimitingResourceQueueElements); - - LimitingResourceQueueElement element = limitingResourceQueueModel - .getLimitingResourceQueueElement(); - limitingResourcesPanel.appendQueueElementToQueue(element); - closeManualAllocationWindow(e); - } - - private DateAndHour getSelectedAllocationTime() { - final LimitingResourceQueueElementGap selectedGap = getSelectedGap(); - int index = radioAllocationDate.getSelectedIndex(); - - // Earliest date - if (index == 0) { - return getEarliestTime(selectedGap); - // Latest date - } else if (index == 1) { - return getLatestTime(selectedGap); - // Select start date - } else if (index == 2) { - LocalDate selectedDay = new LocalDate(startAllocationDate.getValue()); - DateAndHour allocationTime = getValidDayInGap(selectedDay, getSelectedGap()); - if (allocationTime == null) { - throw new WrongValueException(startAllocationDate, _("Day is not valid within selected gap")); - } - return allocationTime; - } - return null; - } - - private DateAndHour getEarliestTime(LimitingResourceQueueElementGap gap) { - Validate.notNull(gap); - return gap.getStartTime(); - } - - private DateAndHour getLatestTime(LimitingResourceQueueElementGap gap) { - Validate.notNull(gap); - LimitingResourceQueueElement element = limitingResourceQueueModel.getLimitingResourceQueueElement(); - LimitingResourceQueue queue = getSelectedQueue(); - return LimitingResourceAllocator.startTimeToAllocateStartingFromEnd( - element.getResourceAllocation(), queue.getResource(), gap); - } - - private LimitingResourceQueueElementGap getSelectedGap() { - Listitem item = listCandidateGaps.getSelectedItem(); - if (item != null) { - return (LimitingResourceQueueElementGap) item.getValue(); - } - return null; - } - - /** - * Checks if date is a valid day within gap. A day is valid within a gap if - * it is included between gap.startTime and the last day from which is - * possible to start doing an allocation (endAllocationDate) - * - * If date is valid, returns DateAndHour in gap associated with that date - * - * @param date - * @param gap - * @return - */ - private DateAndHour getValidDayInGap(LocalDate date, LimitingResourceQueueElementGap gap) { - final DateAndHour endAllocationDate = endAllocationDates.get(gap); - final LocalDate start = gap.getStartTime().getDate(); - final LocalDate end = endAllocationDate != null ? endAllocationDate.getDate() : null; - - if (start.equals(date)) { - return gap.getStartTime(); - } - if (end != null && end.equals(date)) { - return endAllocationDate; - } - if ((start.compareTo(date) <= 0 - && (end == null || end.compareTo(date) >= 0))) { - return new DateAndHour(date, 0); - } - - return null; - } - - public void cancel() { - manualAllocationWindow.setVisible(false); - } - - public void closeManualAllocationWindow(Event e) { - manualAllocationWindow.setVisible(false); - e.stopPropagation(); - } - - public void setStartAllocationDate(Event event) { - setStartAllocationDate(getSelectedGap().getStartTime()); - } - - public void highlightCalendar(Event event) { - Datebox datebox = (Datebox) event.getTarget(); - if (datebox.getValue() == null) { - final LocalDate startDate = getSelectedGap().getStartTime().getDate(); - datebox.setValue(toDate(startDate)); - } - highlightDaysInGap(datebox.getUuid(), getSelectedGap()); - } - - private Date toDate(LocalDate date) { - return date.toDateTimeAtStartOfDay().toDate(); - } - - public void highlightDaysInGap(String uuid, LimitingResourceQueueElementGap gap) { - final LocalDate start = gap.getStartTime().getDate(); - final LocalDate end = getEndAllocationDate(gap); - - final String jsCall = "highlightDaysInInterval('" - + uuid + "', '" - + jsonInterval(formatDate(start), formatDate(end)) + "', '" - + jsonHighlightColor() + "');"; - Clients.evalJavaScript(jsCall); - } - - private LocalDate getEndAllocationDate(LimitingResourceQueueElementGap gap) { - final DateAndHour endTime = endAllocationDates.get(gap); - return endTime != null ? endTime.getDate() : null; - } - - public String formatDate(LocalDate date) { - return (date != null) ? date.toString() : null; - } - - private String jsonInterval(String start, String end) { - StringBuilder result = new StringBuilder(); - - result.append("{\"start\": \"" + start + "\", "); - if (end != null) { - result.append("\"end\": \"" + end + "\""); - } - result.append("}"); - - return result.toString(); - } - - private String jsonHighlightColor() { - return "{\"color\": \"blue\", \"bgcolor\": \"white\"}"; - } - public void moveTask(LimitingResourceQueueElement element) { showManualAllocationWindow(element); } + private void showManualAllocationWindow(LimitingResourceQueueElement element) { + ManualAllocationController manualAllocationController = (ManualAllocationController) manualAllocationWindow + .getVariable("manualAllocationController", true); + manualAllocationController.show(element); + } + + public void reloadUnassignedLimitingResourceQueueElements() { + Util.reloadBindings(gridUnassignedLimitingResourceQueueElements); + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/ManualAllocationController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/ManualAllocationController.java new file mode 100644 index 000000000..290dec1b3 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/limitingresources/ManualAllocationController.java @@ -0,0 +1,418 @@ +/* + * This file is part of NavalPlan + * + * 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 . + */ + +package org.navalplanner.web.limitingresources; + +import static org.navalplanner.web.I18nHelper._; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.Validate; +import org.joda.time.LocalDate; +import org.navalplanner.business.planner.entities.DateAndHour; +import org.navalplanner.business.planner.entities.LimitingResourceAllocator; +import org.navalplanner.business.planner.entities.LimitingResourceQueueElement; +import org.navalplanner.business.planner.entities.LimitingResourceQueueElementGap; +import org.navalplanner.business.planner.entities.ResourceAllocation; +import org.navalplanner.business.resources.entities.LimitingResourceQueue; +import org.navalplanner.business.resources.entities.Resource; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; +import org.zkoss.zk.ui.SuspendNotAllowedException; +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.event.SelectEvent; +import org.zkoss.zk.ui.util.Clients; +import org.zkoss.zk.ui.util.GenericForwardComposer; +import org.zkoss.zul.Datebox; +import org.zkoss.zul.Listbox; +import org.zkoss.zul.Listcell; +import org.zkoss.zul.Listitem; +import org.zkoss.zul.ListitemRenderer; +import org.zkoss.zul.Radio; +import org.zkoss.zul.Radiogroup; +import org.zkoss.zul.SimpleListModel; +import org.zkoss.zul.Window; + +/** + * Controller for manual allocation of queue elements + * + * @author Diego Pino García + */ +@Component +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +public class ManualAllocationController extends GenericForwardComposer { + + private LimitingResourcesController limitingResourcesController; + + private LimitingResourcesPanel limitingResourcesPanel; + + private Radiogroup radioAllocationDate; + + private Datebox startAllocationDate; + + private Listbox listAssignableQueues; + + private Listbox listCandidateGaps; + + private Map endAllocationDates = new HashMap(); + + private final QueueRenderer queueRenderer = new QueueRenderer(); + + private final CandidateGapRenderer candidateGapRenderer = new CandidateGapRenderer(); + + public ManualAllocationController() { + + } + + @Override + public void doAfterCompose(org.zkoss.zk.ui.Component comp) throws Exception { + this.self = comp; + self.setVariable("manualAllocationController", this, true); + listAssignableQueues = (Listbox) self.getFellowIfAny("listAssignableQueues"); + listCandidateGaps = (Listbox) self.getFellowIfAny("listCandidateGaps"); + radioAllocationDate = (Radiogroup) self.getFellowIfAny("radioAllocationDate"); + startAllocationDate = (Datebox) self.getFellowIfAny("startAllocationDate"); + } + + public void setLimitingResourcesPanel(LimitingResourcesPanel limitingResourcesPanel) { + this.limitingResourcesPanel = limitingResourcesPanel; + } + + public void setLimitingResourcesController(LimitingResourcesController limitingResourcesController) { + this.limitingResourcesController = limitingResourcesController; + } + + public ILimitingResourceQueueModel getLimitingResourceQueueModel() { + return limitingResourcesController.getLimitingResourceQueueModel(); + } + + private void feedValidGaps(LimitingResourceQueueElement element, LimitingResourceQueue queue) { + feedValidGapsSince(element, queue, getStartDayBecauseOfGantt(element)); + } + + private DateAndHour getStartDayBecauseOfGantt(LimitingResourceQueueElement element) { + return new DateAndHour(new LocalDate(element.getEarlierStartDateBecauseOfGantt()), 0); + } + + private void feedValidGapsSince(LimitingResourceQueueElement element, LimitingResourceQueue queue, DateAndHour since) { + List gaps = LimitingResourceAllocator.getValidGapsForElementSince(element, queue, since); + endAllocationDates = calculateEndAllocationDates(element.getResourceAllocation(), queue.getResource(), gaps); + listCandidateGaps.setModel(new SimpleListModel(gaps)); + if (!gaps.isEmpty()) { + listCandidateGaps.setSelectedIndex(0); + setStartAllocationDate(gaps.get(0).getStartTime()); + startAllocationDate.setDisabled(true); + disable(radioAllocationDate, false); + } else { + disable(radioAllocationDate, true); + } + radioAllocationDate.setSelectedIndex(0); + } + + private void setStartAllocationDate(DateAndHour time) { + final Date date = (time != null) ? toDate(time.getDate()) : null; + startAllocationDate.setValue(date); + } + + private Map calculateEndAllocationDates( + ResourceAllocation resourceAllocation, Resource resource, + List gaps) { + + Map result = new HashMap(); + for (LimitingResourceQueueElementGap each: gaps) { + result.put(each, calculateEndAllocationDate(resourceAllocation, resource, each)); + } + return result; + } + + private DateAndHour calculateEndAllocationDate( + ResourceAllocation resourceAllocation, Resource resource, + LimitingResourceQueueElementGap gap) { + + if (gap.getEndTime() != null) { + return LimitingResourceAllocator.startTimeToAllocateStartingFromEnd(resourceAllocation, resource, gap); + } + return null; + } + + public void selectRadioAllocationDate(Event event) { + Radiogroup radiogroup = (Radiogroup) event.getTarget().getParent(); + startAllocationDate.setDisabled(radiogroup.getSelectedIndex() != 2); + } + + private void disable(Radiogroup radiogroup, boolean disabled) { + for (Object obj: radiogroup.getChildren()) { + final Radio each = (Radio) obj; + each.setDisabled(disabled); + } + } + + private void setAssignableQueues(final LimitingResourceQueueElement element) { + List queues = getLimitingResourceQueueModel().getAssignableQueues(element); + listAssignableQueues.setModel(new SimpleListModel(queues)); + listAssignableQueues.addEventListener(Events.ON_SELECT, new EventListener() { + + @Override + public void onEvent(Event event) throws Exception { + SelectEvent se = (SelectEvent) event; + + LimitingResourceQueue queue = getSelectedQueue(se); + if (queue != null) { + feedValidGaps(element, queue); + } + } + + public LimitingResourceQueue getSelectedQueue(SelectEvent se) { + final Listitem item = (Listitem) se.getSelectedItems().iterator().next(); + return (LimitingResourceQueue) item.getValue(); + } + + }); + listAssignableQueues.setSelectedIndex(0); + feedValidGaps(element, queues.get(0)); + } + + private LimitingResourceQueue getSelectedQueue() { + LimitingResourceQueue result = null; + + final Listitem item = listAssignableQueues.getSelectedItem(); + if (item != null) { + result = (LimitingResourceQueue) item.getValue(); + } + return result; + } + + public void accept(Event e) { + final LimitingResourceQueue queue = getSelectedQueue(); + final DateAndHour time = getSelectedAllocationTime(); + Validate.notNull(time); + getLimitingResourceQueueModel() + .assignEditingLimitingResourceQueueElementToQueueAt(queue, time); + limitingResourcesController.reloadUnassignedLimitingResourceQueueElements(); + + LimitingResourceQueueElement element = getLimitingResourceQueueModel() + .getLimitingResourceQueueElement(); + limitingResourcesPanel.appendQueueElementToQueue(element); + closeManualAllocationWindow(e); + } + + private DateAndHour getSelectedAllocationTime() { + final LimitingResourceQueueElementGap selectedGap = getSelectedGap(); + int index = radioAllocationDate.getSelectedIndex(); + + // Earliest date + if (index == 0) { + return getEarliestTime(selectedGap); + // Latest date + } else if (index == 1) { + return getLatestTime(selectedGap); + // Select start date + } else if (index == 2) { + LocalDate selectedDay = new LocalDate(startAllocationDate.getValue()); + DateAndHour allocationTime = getValidDayInGap(selectedDay, getSelectedGap()); + if (allocationTime == null) { + throw new WrongValueException(startAllocationDate, _("Day is not valid within selected gap")); + } + return allocationTime; + } + return null; + } + + private DateAndHour getEarliestTime(LimitingResourceQueueElementGap gap) { + Validate.notNull(gap); + return gap.getStartTime(); + } + + private DateAndHour getLatestTime(LimitingResourceQueueElementGap gap) { + Validate.notNull(gap); + LimitingResourceQueueElement element = getLimitingResourceQueueModel().getLimitingResourceQueueElement(); + LimitingResourceQueue queue = getSelectedQueue(); + return LimitingResourceAllocator.startTimeToAllocateStartingFromEnd( + element.getResourceAllocation(), queue.getResource(), gap); + } + + private LimitingResourceQueueElementGap getSelectedGap() { + Listitem item = listCandidateGaps.getSelectedItem(); + if (item != null) { + return (LimitingResourceQueueElementGap) item.getValue(); + } + return null; + } + + /** + * Checks if date is a valid day within gap. A day is valid within a gap if + * it is included between gap.startTime and the last day from which is + * possible to start doing an allocation (endAllocationDate) + * + * If date is valid, returns DateAndHour in gap associated with that date + * + * @param date + * @param gap + * @return + */ + private DateAndHour getValidDayInGap(LocalDate date, LimitingResourceQueueElementGap gap) { + final DateAndHour endAllocationDate = endAllocationDates.get(gap); + final LocalDate start = gap.getStartTime().getDate(); + final LocalDate end = endAllocationDate != null ? endAllocationDate.getDate() : null; + + if (start.equals(date)) { + return gap.getStartTime(); + } + if (end != null && end.equals(date)) { + return endAllocationDate; + } + if ((start.compareTo(date) <= 0 + && (end == null || end.compareTo(date) >= 0))) { + return new DateAndHour(date, 0); + } + + return null; + } + + public void cancel() { + self.setVisible(false); + } + + public void closeManualAllocationWindow(Event e) { + self.setVisible(false); + e.stopPropagation(); + } + + public void setStartAllocationDate(Event event) { + setStartAllocationDate(getSelectedGap().getStartTime()); + } + + public void highlightCalendar(Event event) { + Datebox datebox = (Datebox) event.getTarget(); + if (datebox.getValue() == null) { + final LocalDate startDate = getSelectedGap().getStartTime().getDate(); + datebox.setValue(toDate(startDate)); + } + highlightDaysInGap(datebox.getUuid(), getSelectedGap()); + } + + private Date toDate(LocalDate date) { + return date.toDateTimeAtStartOfDay().toDate(); + } + + public void highlightDaysInGap(String uuid, LimitingResourceQueueElementGap gap) { + final LocalDate start = gap.getStartTime().getDate(); + final LocalDate end = getEndAllocationDate(gap); + + final String jsCall = "highlightDaysInInterval('" + + uuid + "', '" + + jsonInterval(formatDate(start), formatDate(end)) + "', '" + + jsonHighlightColor() + "');"; + Clients.evalJavaScript(jsCall); + } + + private LocalDate getEndAllocationDate(LimitingResourceQueueElementGap gap) { + final DateAndHour endTime = endAllocationDates.get(gap); + return endTime != null ? endTime.getDate() : null; + } + + public String formatDate(LocalDate date) { + return (date != null) ? date.toString() : null; + } + + private String jsonInterval(String start, String end) { + StringBuilder result = new StringBuilder(); + + result.append("{\"start\": \"" + start + "\", "); + if (end != null) { + result.append("\"end\": \"" + end + "\""); + } + result.append("}"); + + return result.toString(); + } + + private String jsonHighlightColor() { + return "{\"color\": \"blue\", \"bgcolor\": \"white\"}"; + } + + public CandidateGapRenderer getCandidateGapRenderer() { + return candidateGapRenderer; + } + + private class CandidateGapRenderer implements ListitemRenderer { + + @Override + public void render(Listitem item, Object data) throws Exception { + LimitingResourceQueueElementGap gap = (LimitingResourceQueueElementGap) data; + + item.setValue(gap); + item.appendChild(cell(gap.getStartTime())); + item.appendChild(cell(gap.getEndTime())); + } + + public Listcell cell(DateAndHour time) { + return new Listcell(formatTime(time)); + } + + private String formatTime(DateAndHour time) { + return time == null ? _("END") : time.getDate().toString("dd/MM/yyyy") + " - " + time.getHour(); + } + + } + + public void show(LimitingResourceQueueElement element) { + try { + setAssignableQueues(element); + getLimitingResourceQueueModel().init(element); + ((Window) self).doModal(); + } catch (SuspendNotAllowedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public ListitemRenderer getQueueRenderer() { + return queueRenderer; + } + + private class QueueRenderer implements ListitemRenderer { + + @Override + public void render(Listitem item, Object data) throws Exception { + final LimitingResourceQueue queue = (LimitingResourceQueue) data; + item.setValue(queue); + item.appendChild(cell(queue)); + } + + private Listcell cell(LimitingResourceQueue queue) { + Listcell result = new Listcell(); + result.setLabel(queue.getResource().getName()); + return result; + } + + } + +} diff --git a/navalplanner-webapp/src/main/webapp/limitingresources/limitingResourcesLayout.zul b/navalplanner-webapp/src/main/webapp/limitingresources/limitingResourcesLayout.zul index c8c9a0316..e20b6abce 100644 --- a/navalplanner-webapp/src/main/webapp/limitingresources/limitingResourcesLayout.zul +++ b/navalplanner-webapp/src/main/webapp/limitingresources/limitingResourcesLayout.zul @@ -20,6 +20,10 @@ + + @@ -108,69 +112,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -