/* /* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package net.rrm.ehour.ui.report.panel.criteria; import com.google.common.collect.Lists; import com.googlecode.wicket.jquery.ui.form.datepicker.DatePicker; import net.rrm.ehour.config.EhourConfig; import net.rrm.ehour.domain.*; import net.rrm.ehour.report.criteria.ReportCriteria; import net.rrm.ehour.report.criteria.ReportCriteriaUpdateType; import net.rrm.ehour.report.criteria.Sort; import net.rrm.ehour.report.criteria.UserSelectedCriteria; import net.rrm.ehour.report.service.ReportCriteriaService; import net.rrm.ehour.ui.common.border.GreyBlueRoundedBorder; import net.rrm.ehour.ui.common.border.GreySquaredRoundedBorder; import net.rrm.ehour.ui.common.component.PlaceholderPanel; import net.rrm.ehour.ui.common.decorator.LoadingSpinnerDecorator; import net.rrm.ehour.ui.common.event.AjaxEvent; import net.rrm.ehour.ui.common.event.EventPublisher; import net.rrm.ehour.ui.common.panel.AbstractAjaxPanel; import net.rrm.ehour.ui.common.panel.datepicker.LocalizedDatePicker; import net.rrm.ehour.ui.common.renderers.DomainObjectChoiceRenderer; import net.rrm.ehour.ui.common.session.EhourWebSession; import net.rrm.ehour.ui.common.util.WebGeo; import net.rrm.ehour.ui.common.wicket.Container; import net.rrm.ehour.ui.report.panel.criteria.quick.*; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.attributes.AjaxRequestAttributes; import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.ajax.markup.html.form.AjaxButton; import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox; import org.apache.wicket.event.Broadcast; import org.apache.wicket.event.IEvent; import org.apache.wicket.markup.head.IHeaderResponse; import org.apache.wicket.markup.head.JavaScriptReferenceHeaderItem; import org.apache.wicket.markup.head.OnDomReadyHeaderItem; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.IChoiceRenderer; import org.apache.wicket.markup.html.form.ListMultipleChoice; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.model.IModel; import org.apache.wicket.model.PropertyModel; import org.apache.wicket.model.ResourceModel; import org.apache.wicket.request.resource.JavaScriptResourceReference; import org.apache.wicket.spring.injection.annot.SpringBean; import org.apache.wicket.util.string.AppendingStringBuffer; import java.util.*; import static net.rrm.ehour.report.criteria.UserSelectedCriteria.ReportType; import static net.rrm.ehour.ui.report.panel.criteria.quick.QuickPeriod.QuickType.*; /** * Base report criteria panel which adds the quick date selections */ public class ReportCriteriaPanel extends AbstractAjaxPanel<ReportCriteriaBackingBean> { private static final long serialVersionUID = 161160822264046559L; private static final int MAX_CRITERIA_ROW = 6; private static final JavaScriptResourceReference CRITERIA_JS = new JavaScriptResourceReference(ReportCriteriaPanel.class, "report_criteria.js"); private static final String ID_USERDEPT_PLACEHOLDER = "userDepartmentPlaceholder"; public static final int AMOUNT_OF_QUICKWEEKS = 8; public static final int AMOUNT_OF_QUICKMONTHS = 6; public static final int AMOUNT_OF_QUICKQUARTERS = 3; private static final String CUSTOMER_FILTER_INPUT_ID = "#customerFilterInput"; private static final String PROJECT_FILTER_INPUT_ID = "#projectFilterInput"; private static final String DEPARTMENT_FILTER_INPUT_ID = "#departmentFilterInput"; private static final String USER_FILTER_INPUT_ID = "#userFilterInput"; private static final int MONTHS_PER_QUARTER = 3; @SpringBean private ReportCriteriaService reportCriteriaService; private DatePicker startDatePicker; private DatePicker endDatePicker; private ListMultipleChoice<Project> projects; private ListMultipleChoice<Customer> customers; private ListMultipleChoice<User> users; private List<WebMarkupContainer> quickSelections; private ListMultipleChoice<UserDepartment> departments; private WebMarkupContainer lockedDateSelection; public ReportCriteriaPanel(String id, IModel<ReportCriteriaBackingBean> model) { super(id, model); GreySquaredRoundedBorder greyBorder = new GreySquaredRoundedBorder("border", WebGeo.W_FULL); add(greyBorder); setOutputMarkupId(true); Form<ReportCriteriaBackingBean> form = new Form<>("criteriaForm"); form.setOutputMarkupId(true); greyBorder.add(form); addDates(form, model); GreyBlueRoundedBorder blueBorder = new GreyBlueRoundedBorder("customerProjectsBorder"); form.add(blueBorder); ReportCriteriaBackingBean criteriaBackingBean = model.getObject(); addCustomerSelection(criteriaBackingBean, blueBorder); addProjectSelection(criteriaBackingBean, blueBorder); UserSelectedCriteria userSelectedCriteria = criteriaBackingBean.getReportCriteria().getUserSelectedCriteria(); boolean showDepartmentAndOtherUsers = userSelectedCriteria.isForGlobalReport() || userSelectedCriteria.isForPm(); form.add(showDepartmentAndOtherUsers ? addDepartmentsAndUsers(criteriaBackingBean, ID_USERDEPT_PLACEHOLDER) : new PlaceholderPanel(ID_USERDEPT_PLACEHOLDER)); addSubmitButtons(form); form.add(addReportTypeSelection("reportRole", userSelectedCriteria)); } private WebMarkupContainer addReportTypeSelection(String id, final UserSelectedCriteria criteria) { List<ReportType> types = determineReportRoleTypes(); if (types.size() > 1) { final DropDownChoice<ReportType> choice = new DropDownChoice<>(id, new PropertyModel<ReportType>(criteria, "selectedReportType"), types, new IChoiceRenderer<ReportType>() { @Override public Object getDisplayValue(ReportType object) { switch (object) { case REPORT: return new ResourceModel("report.useRole.global").wrapOnAssignment(ReportCriteriaPanel.this).getObject(); case PM: return new ResourceModel("report.useRole.pm").wrapOnAssignment(ReportCriteriaPanel.this).getObject(); default: return new ResourceModel("report.useRole.single").wrapOnAssignment(ReportCriteriaPanel.this).getObject(); } } @Override public String getIdValue(ReportType object, int index) { return Integer.toString(index); } }); choice.add(new AjaxFormComponentUpdatingBehavior("onchange") { @Override protected void onUpdate(AjaxRequestTarget target) { ReportType type = choice.getModelObject(); User user = EhourWebSession.getUser(); switch (type) { case REPORT: criteria.setReportTypeToGlobal(); break; case PM: criteria.setReportTypeToPM(user); break; case INDIVIDUAL_USER: default: criteria.setReportTypeToIndividualUser(user); break; } send(getPage(), Broadcast.EXACT, new ReportTypeChangeEvent(target, type)); } }); return choice; } else { WebMarkupContainer container = new WebMarkupContainer(id); container.setVisible(false); return container; } } public static class ReportTypeChangeEvent { public final AjaxRequestTarget target; public final ReportType reportType; public ReportTypeChangeEvent(AjaxRequestTarget target, ReportType reportType) { this.target = target; this.reportType = reportType; } } private List<ReportType> determineReportRoleTypes() { List<ReportType> types = Lists.newArrayList(); EhourWebSession session = getEhourWebSession(); if (session.isReporter()) { types.add(ReportType.REPORT); } if (session.isProjectManager()) { types.add(ReportType.PM); } types.add(ReportType.INDIVIDUAL_USER); return types; } private void addCustomerSelection(final ReportCriteriaBackingBean bean, WebMarkupContainer parent) { customers = new ListMultipleChoice<>("reportCriteria.userSelectedCriteria.customers", new PropertyModel<Collection<Customer>>(bean, "reportCriteria.userSelectedCriteria.customers"), new PropertyModel<List<Customer>>(bean, "reportCriteria.availableCriteria.customers"), new DomainObjectChoiceRenderer<Customer>()); customers.setMarkupId("customerSelect"); customers.setMaxRows(MAX_CRITERIA_ROW); customers.setOutputMarkupId(true); customers.add(new AjaxFormComponentUpdatingBehavior("change") { private static final long serialVersionUID = -5588313671121851508L; protected void onUpdate(AjaxRequestTarget target) { // show only projects for selected customers List<Customer> preCustomers = Lists.newArrayList(bean.getReportCriteria().getAvailableCriteria().getCustomers()); updateReportCriteria(ReportCriteriaUpdateType.UPDATE_CUSTOMERS_AND_PROJECTS); List<Customer> postCustomers = bean.getReportCriteria().getAvailableCriteria().getCustomers(); if (!preCustomers.containsAll(postCustomers)) { updateCustomers(target); } updateProjects(target); } }); parent.add(customers); final AjaxCheckBox deactivateBox = new AjaxCheckBox("reportCriteria.userSelectedCriteria.onlyActiveCustomers") { @Override protected void onUpdate(AjaxRequestTarget target) { updateCustomersAndProjects(target); } }; deactivateBox.setOutputMarkupId(true); parent.add(deactivateBox); final DropDownChoice<Sort> customerSort = createCustomerSort(); parent.add(customerSort); parent.add(new AjaxLink<Void>("clearCustomer") { @Override public void onClick(AjaxRequestTarget target) { bean.getReportCriteria().getUserSelectedCriteria().resetCustomerSelection(); updateReportCriteria(ReportCriteriaUpdateType.UPDATE_CUSTOMERS_AND_PROJECTS); updateCustomers(target); updateProjects(target); target.appendJavaScript(getCustomerFilterClearScript()); target.add(customerSort); target.add(deactivateBox); } }); } private DropDownChoice<Sort> createCustomerSort() { DropDownChoice<Sort> customerSort = new DropDownChoice<>("customerSort", new PropertyModel<Sort>(getPanelModelObject(), "reportCriteria.userSelectedCriteria.customerSort"), Arrays.asList(Sort.NAME, Sort.CODE), new SortRenderer()); customerSort.add(new AjaxFormComponentUpdatingBehavior("change") { @Override protected void onUpdate(AjaxRequestTarget target) { ReportCriteria reportCriteria = getPanelModelObject().getReportCriteria(); reportCriteria.updateCustomerSort(); target.add(customers); applyClientSideCustomerFilter(target); } }); customerSort.setOutputMarkupId(true); return customerSort; } private void addProjectSelection(final ReportCriteriaBackingBean bean, WebMarkupContainer parent) { projects = new ListMultipleChoice<>("reportCriteria.userSelectedCriteria.projects", new PropertyModel<List<Project>>(bean, "reportCriteria.availableCriteria.projects"), new DomainObjectChoiceRenderer<Project>()); projects.setMaxRows(MAX_CRITERIA_ROW); projects.setOutputMarkupId(true); projects.setMarkupId("projectSelect"); projects.add(new AjaxFormComponentUpdatingBehavior("change") { @Override protected void onUpdate(AjaxRequestTarget target) { } }); parent.add(projects); final AjaxCheckBox onlyActiveCheckbox = new AjaxCheckBox("reportCriteria.userSelectedCriteria.onlyActiveProjects") { @Override protected void onUpdate(AjaxRequestTarget target) { updateReportCriteria(ReportCriteriaUpdateType.UPDATE_CUSTOMERS_AND_PROJECTS); updateCustomers(target); updateProjects(target); } }; onlyActiveCheckbox.setOutputMarkupId(true); parent.add(onlyActiveCheckbox); final AjaxCheckBox billableCheckbox = new AjaxCheckBox("reportCriteria.userSelectedCriteria.onlyBillableProjects", new PropertyModel<Boolean>(ReportCriteriaPanel.this.getDefaultModel(), "reportCriteria.userSelectedCriteria.onlyBillableProjects")) { @Override protected void onUpdate(AjaxRequestTarget target) { updateReportCriteria(ReportCriteriaUpdateType.UPDATE_CUSTOMERS_AND_PROJECTS); updateProjects(target); } }; billableCheckbox.setMarkupId("reportCriteria.userSelectedCriteria.onlyBillableProjects"); billableCheckbox.setOutputMarkupId(true); parent.add(billableCheckbox); final DropDownChoice<Sort> projectSort = createProjectSort(); parent.add(projectSort); parent.add(new AjaxLink<Void>("clearProject") { @Override public void onClick(AjaxRequestTarget target) { bean.getReportCriteria().getUserSelectedCriteria().resetProjectSelection(); updateReportCriteria(ReportCriteriaUpdateType.UPDATE_CUSTOMERS_AND_PROJECTS); updateCustomers(target); updateProjects(target); target.appendJavaScript(getProjectFilterClearScript()); target.add(projectSort); target.add(billableCheckbox); target.add(onlyActiveCheckbox); } }); } private DropDownChoice<Sort> createProjectSort() { DropDownChoice<Sort> projectSort = new DropDownChoice<>("projectSort", new PropertyModel<Sort>(getPanelModelObject(), "reportCriteria.userSelectedCriteria.projectSort"), Arrays.asList(Sort.NAME, Sort.CODE), new SortRenderer()); projectSort.add(new AjaxFormComponentUpdatingBehavior("change") { @Override protected void onUpdate(AjaxRequestTarget target) { ReportCriteria reportCriteria = getPanelModelObject().getReportCriteria(); reportCriteria.updateProjectSort(); target.add(projects); applyClientSideProjectFilter(target); } }); projectSort.setOutputMarkupId(true); return projectSort; } private void updateCustomersAndProjects(AjaxRequestTarget target) { updateReportCriteria(ReportCriteriaUpdateType.UPDATE_CUSTOMERS_AND_PROJECTS); updateProjects(target); updateCustomers(target); } private void updateProjects(AjaxRequestTarget target) { target.add(projects); applyClientSideProjectFilter(target); } private void applyClientSideProjectFilter(AjaxRequestTarget target) { target.appendJavaScript(getProjectFilterRegistrationScript()); } private void updateCustomers(AjaxRequestTarget target) { target.add(customers); applyClientSideCustomerFilter(target); } private void applyClientSideCustomerFilter(AjaxRequestTarget target) { target.appendJavaScript(getCustomerFilterRegistrationScript()); } private void addUserSelection(final ReportCriteriaBackingBean bean, WebMarkupContainer parent) { users = new ListMultipleChoice<>("reportCriteria.userSelectedCriteria.users", new PropertyModel<List<User>>(getDefaultModel(), "reportCriteria.availableCriteria.users"), new DomainObjectChoiceRenderer<User>()); users.setMarkupId("userSelect"); users.setOutputMarkupId(true); users.setMaxRows(MAX_CRITERIA_ROW); parent.add(users); // hide active checkbox final AjaxCheckBox deactivateBox = new AjaxCheckBox("reportCriteria.userSelectedCriteria.onlyActiveUsers") { private static final long serialVersionUID = 2585047163449150793L; @Override protected void onUpdate(AjaxRequestTarget target) { updateReportCriteria(ReportCriteriaUpdateType.UPDATE_USERS_AND_DEPTS); target.add(users); // reapply the filter to the possible new contents of the dropdowns target.appendJavaScript(getUserFilterRegistrationScript()); } }; parent.add(deactivateBox); Label filterToggleText = new Label("onlyActiveUsersLabel", new ResourceModel("report.onlyActiveUsers")); parent.add(filterToggleText); parent.add(new AjaxLink<Void>("clearUser") { @Override public void onClick(AjaxRequestTarget target) { bean.getReportCriteria().getUserSelectedCriteria().resetUserSelection(); updateReportCriteria(ReportCriteriaUpdateType.UPDATE_USERS_AND_DEPTS); updateUsers(target); updateDepartments(target); target.appendJavaScript(getUserFilterClearScript()); } }); } private void updateDepartments(AjaxRequestTarget target) { target.add(departments); applyClientSideDepartmentFilter(target); } private void applyClientSideDepartmentFilter(AjaxRequestTarget target) { target.appendJavaScript(getDepartmentFilterRegistrationScript()); } private void updateUsers(AjaxRequestTarget target) { target.add(users); applyClientSideUserFilter(target); } private void applyClientSideUserFilter(AjaxRequestTarget target) { target.appendJavaScript(getUserFilterRegistrationScript()); } private Fragment addDepartmentsAndUsers(ReportCriteriaBackingBean bean, String id) { Fragment fragment = new Fragment(id, "userDepartmentCriteria", this); GreyBlueRoundedBorder blueBorder = new GreyBlueRoundedBorder("deptUserBorder"); fragment.add(blueBorder); addUserDepartmentSelection(bean, blueBorder); addUserSelection(bean, blueBorder); return fragment; } private void addUserDepartmentSelection(final ReportCriteriaBackingBean bean, WebMarkupContainer parent) { departments = new ListMultipleChoice<>("reportCriteria.userSelectedCriteria.userDepartments", new PropertyModel<List<UserDepartment>>(getDefaultModel(), "reportCriteria.availableCriteria.userDepartments"), new DomainObjectChoiceRenderer<UserDepartment>()); departments.setMarkupId("departmentSelect"); departments.setMaxRows(MAX_CRITERIA_ROW); departments.setOutputMarkupId(true); // update projects when customer(s) selected departments.add(new AjaxFormComponentUpdatingBehavior("change") { private static final long serialVersionUID = 1L; protected void onUpdate(AjaxRequestTarget target) { // show only projects for selected customers updateReportCriteria(ReportCriteriaUpdateType.UPDATE_USERS_AND_DEPTS); target.add(users); } }); parent.add(departments); parent.add(new AjaxLink<Void>("clearDepartment") { @Override public void onClick(AjaxRequestTarget target) { bean.getReportCriteria().getUserSelectedCriteria().resetUserDepartmentSelection(); updateReportCriteria(ReportCriteriaUpdateType.UPDATE_USERS_AND_DEPTS); updateUsers(target); updateDepartments(target); target.appendJavaScript(getDepartmentFilterClearScript()); } }); } private void updateReportCriteria(ReportCriteriaUpdateType updateType) { ReportCriteriaBackingBean backingBean = getPanelModelObject(); ReportCriteria reportCriteria = reportCriteriaService.syncUserReportCriteria(backingBean.getReportCriteria(), updateType); backingBean.getReportCriteria().setAvailableCriteria(reportCriteria.getAvailableCriteria()); } @SuppressWarnings("serial") private void addSubmitButtons(Form<ReportCriteriaBackingBean> form) { // Submit AjaxButton submitButton = new AjaxButton("createReport", form) { @Override protected final void onSubmit(AjaxRequestTarget target, Form<?> form) { EventPublisher.publishAjaxEvent(this, new AjaxEvent(ReportCriteriaAjaxEventType.CRITERIA_UPDATED)); } @Override protected void updateAjaxAttributes(AjaxRequestAttributes attributes) { super.updateAjaxAttributes(attributes); attributes.getAjaxCallListeners().add(new LoadingSpinnerDecorator()); } @Override protected void onError(AjaxRequestTarget target, Form<?> form) { target.add(form); } }; // default submit form.add(submitButton); // reset button AjaxButton resetButton = new AjaxButton("resetCriteria") { @Override protected final void onSubmit(AjaxRequestTarget target, Form<?> form) { EventPublisher.publishAjaxEvent(this, new AjaxEvent(ReportCriteriaAjaxEventType.CRITERIA_RESET)); } @Override protected void onError(AjaxRequestTarget target, Form<?> form) { onSubmit(target, form); } }; resetButton.setDefaultFormProcessing(false); form.add(resetButton); } private void addDates(Form<ReportCriteriaBackingBean> form, IModel<ReportCriteriaBackingBean> model) { startDatePicker = createDatePicker("reportCriteria.userSelectedCriteria.reportRange.dateStart", new PropertyModel<Date>(model, "reportCriteria.userSelectedCriteria.reportRange.dateStart")); form.add(startDatePicker); endDatePicker = createDatePicker("reportCriteria.userSelectedCriteria.reportRange.dateEnd", new PropertyModel<Date>(model, "reportCriteria.userSelectedCriteria.reportRange.dateEnd")); form.add(endDatePicker); quickSelections = new ArrayList<>(); quickSelections.add(createQuickWeek()); quickSelections.add(createQuickMonth()); quickSelections.add(createQuickQuarter()); for (WebMarkupContainer cont : quickSelections) { cont.setOutputMarkupId(true); form.add(cont); } lockedDateSelection = createLockedPeriodRangeDropdown("lockedDate"); form.add(lockedDateSelection); } private WebMarkupContainer createLockedPeriodRangeDropdown(String id) { ReportCriteriaBackingBean panelModelObject = getPanelModelObject(); List<TimesheetLock> locks = panelModelObject.getReportCriteria().getAvailableCriteria().getTimesheetLocks(); if (locks == null || locks.isEmpty()) { Container placeholder = new Container(id); placeholder.setVisible(false); return placeholder; } DateDropDownChoice<TimesheetLock> lockedDateDropDown = new DateDropDownChoice<>(id, new PropertyModel<TimesheetLock>(getPanelModel(), "reportForLock"), locks, new IChoiceRenderer<TimesheetLock>() { @Override public Object getDisplayValue(TimesheetLock object) { return object.getName(); } @Override public String getIdValue(TimesheetLock object, int index) { return Integer.toString(index); } } ); lockedDateDropDown.setOutputMarkupId(true); return lockedDateDropDown; } private DatePicker createDatePicker(String id, IModel<Date> model) { DatePicker datePicker = new LocalizedDatePicker(id, model); datePicker.setOutputMarkupId(true); datePicker.add(new AjaxFormComponentUpdatingBehavior("onchange") { private static final long serialVersionUID = -5588313671121851508L; @Override protected void onUpdate(AjaxRequestTarget target) { ReportCriteriaBackingBean backingBean = ReportCriteriaPanel.this.getPanelModelObject(); backingBean.resetQuickSelections(); for (WebMarkupContainer cont : quickSelections) { target.add(cont); } } }); return datePicker; } private WebMarkupContainer createQuickWeek() { List<QuickWeek> weeks = new ArrayList<>(); Calendar currentDate = new GregorianCalendar(); int currentWeek = -AMOUNT_OF_QUICKWEEKS; EhourConfig config = EhourWebSession.getEhourConfig(); currentDate.setFirstDayOfWeek(config.getFirstDayOfWeek()); currentDate.set(Calendar.DAY_OF_WEEK, config.getFirstDayOfWeek()); currentDate.add(Calendar.WEEK_OF_YEAR, -1); //previous weeks.add(QuickWeek.shortcut(currentDate, config, QuickPeriod.QuickType.SHORTCUT_PREV)); currentDate.add(Calendar.WEEK_OF_YEAR, 1); //current weeks.add(QuickWeek.shortcut(currentDate, config, QuickPeriod.QuickType.SHORTCUT_CURRENT)); currentDate.add(Calendar.WEEK_OF_YEAR, 1); //next weeks.add(QuickWeek.shortcut(currentDate, config, QuickPeriod.QuickType.SHORTCUT_NEXT)); currentDate.add(Calendar.WEEK_OF_YEAR, -1); //previous currentDate.add(Calendar.WEEK_OF_YEAR, currentWeek); weeks.add(QuickWeek.divider()); for (; currentWeek < AMOUNT_OF_QUICKWEEKS; currentWeek++) { weeks.add(QuickWeek.instance(currentDate, config)); currentDate.add(Calendar.WEEK_OF_YEAR, 1); } return createQuickDateDropDown("quickWeek", weeks, new QuickWeekRenderer()); } private WebMarkupContainer createQuickMonth() { List<QuickMonth> months = new ArrayList<>(); Calendar currentDate = new GregorianCalendar(); currentDate.set(Calendar.DAY_OF_MONTH, 1); currentDate.add(Calendar.MONTH, -1); //previous months.add(QuickMonth.shortcut(currentDate, SHORTCUT_PREV)); currentDate.add(Calendar.MONTH, 1); //current months.add(QuickMonth.shortcut(currentDate, SHORTCUT_CURRENT)); currentDate.add(Calendar.MONTH, 1); //next months.add(QuickMonth.shortcut(currentDate, SHORTCUT_NEXT)); months.add(QuickMonth.divider()); currentDate.add(Calendar.MONTH, -1); //previous int currentMonth = -AMOUNT_OF_QUICKMONTHS; currentDate.add(Calendar.MONTH, currentMonth); for (; currentMonth < AMOUNT_OF_QUICKMONTHS; currentMonth++) { months.add(QuickMonth.instance(currentDate)); currentDate.add(Calendar.MONTH, 1); } return createQuickDateDropDown("quickMonth", months, new QuickMonthRenderer()); } private WebMarkupContainer createQuickQuarter() { List<QuickQuarter> quarters = new ArrayList<>(); Calendar currentDate = new GregorianCalendar(); int currentQuarter = -AMOUNT_OF_QUICKQUARTERS; int quarter = currentDate.get(Calendar.MONTH) / MONTHS_PER_QUARTER; currentDate.set(Calendar.MONTH, quarter * MONTHS_PER_QUARTER); // abuse rounding off currentDate.set(Calendar.DAY_OF_MONTH, 1); currentDate.add(Calendar.MONTH, -MONTHS_PER_QUARTER); quarters.add(QuickQuarter.shortcut(currentDate, SHORTCUT_PREV)); currentDate.add(Calendar.MONTH, MONTHS_PER_QUARTER); quarters.add(QuickQuarter.shortcut(currentDate, SHORTCUT_CURRENT)); currentDate.add(Calendar.MONTH, MONTHS_PER_QUARTER); quarters.add(QuickQuarter.shortcut(currentDate, SHORTCUT_NEXT)); //reset currentDate.add(Calendar.MONTH, -MONTHS_PER_QUARTER); currentDate.add(Calendar.MONTH, currentQuarter * MONTHS_PER_QUARTER); quarters.add(QuickQuarter.divider()); for (; currentQuarter < AMOUNT_OF_QUICKQUARTERS; currentQuarter++) { quarters.add(QuickQuarter.instance(currentDate)); currentDate.add(Calendar.MONTH, MONTHS_PER_QUARTER); } return createQuickDateDropDown("quickQuarter", quarters, new QuickQuarterRenderer()); } private <T extends QuickPeriod> DateDropDownChoice<T> createQuickDateDropDown(String id, List<T> options, IChoiceRenderer<T> renderer) { return new DateDropDownChoice<T>(id, options, renderer) { @Override protected void setOptionAttributes(AppendingStringBuffer buffer, T choice, int index, String selected) { super.setOptionAttributes(buffer, choice, index, selected); if (choice.isDivider()) { buffer.append(" disabled"); } } }; } @Override public void onEvent(IEvent<?> event) { Object payload = event.getPayload(); if (payload instanceof DateDropDownChoice.DateChangedPayload) { updateDates(((DateDropDownChoice.DateChangedPayload) payload).getTarget()); } } private void updateDates(AjaxRequestTarget target) { target.add(startDatePicker); target.add(endDatePicker); if (lockedDateSelection.isVisibleInHierarchy()) { target.add(lockedDateSelection); } for (WebMarkupContainer quickSelection : quickSelections) { target.add(quickSelection); } } @Override public void renderHead(IHeaderResponse response) { response.render(JavaScriptReferenceHeaderItem.forReference(CRITERIA_JS)); response.render(OnDomReadyHeaderItem.forScript(getCustomerFilterRegistrationScript())); response.render(OnDomReadyHeaderItem.forScript(getProjectFilterRegistrationScript())); response.render(OnDomReadyHeaderItem.forScript(getDepartmentFilterRegistrationScript())); response.render(OnDomReadyHeaderItem.forScript(getUserFilterRegistrationScript())); } private String getCustomerFilterRegistrationScript() { return String.format("initFilter('#customerSelect', '%s')", CUSTOMER_FILTER_INPUT_ID); } private String getProjectFilterRegistrationScript() { return String.format("initFilter('#projectSelect', '%s')", PROJECT_FILTER_INPUT_ID); } private CharSequence getDepartmentFilterRegistrationScript() { return String.format("initFilter('#departmentSelect', '%s')", DEPARTMENT_FILTER_INPUT_ID); } private CharSequence getUserFilterRegistrationScript() { return String.format("initFilter('#userSelect', '%s')", USER_FILTER_INPUT_ID); } private String getCustomerFilterClearScript() { return getFilterClearScript(CUSTOMER_FILTER_INPUT_ID); } private String getProjectFilterClearScript() { return getFilterClearScript(PROJECT_FILTER_INPUT_ID); } private String getDepartmentFilterClearScript() { return getFilterClearScript(DEPARTMENT_FILTER_INPUT_ID); } private String getUserFilterClearScript() { return getFilterClearScript(USER_FILTER_INPUT_ID); } private String getFilterClearScript(String inputId) { return String.format("clearFilter('%s');", inputId); } }