/* * 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.timesheet.panel; import net.rrm.ehour.config.EhourConfig; import net.rrm.ehour.domain.Project; import net.rrm.ehour.timesheet.dto.UserProjectStatus; import net.rrm.ehour.ui.common.border.CustomTitledGreyRoundedBorder; import net.rrm.ehour.ui.common.component.CurrencyLabel; import net.rrm.ehour.ui.common.model.DateModel; import net.rrm.ehour.ui.common.model.MessageResourceModel; import net.rrm.ehour.ui.common.panel.AbstractBasePanel; import net.rrm.ehour.ui.common.util.HtmlUtil; import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.Model; import org.apache.wicket.model.ResourceModel; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.List; /** * Panel showing overview */ public class ProjectOverviewPanel extends AbstractBasePanel<Void> { private static final long serialVersionUID = -5935376941518756941L; private static final String ID_GREY_BORDER = "greyBorder"; private static final String ID_TABLE_DATA = "projectStatus"; private static final String ID_SUMMARY_ROW = "summaryRow"; private static final String ID_FOLD_LINK = "foldLink"; private static final String ID_FOLD_IMG = "foldImg"; public ProjectOverviewPanel(String id, Calendar overviewFor, Collection<UserProjectStatus> projectStatusses) { super(id); this.setOutputMarkupId(true); // this should be easier.. Label label = new Label("title", new MessageResourceModel("projectoverview.aggregatedPerMonth", this, new DateModel(overviewFor, getConfig(), DateModel.DATESTYLE_MONTHONLY))); CustomTitledGreyRoundedBorder greyBorder = new CustomTitledGreyRoundedBorder(ID_GREY_BORDER, label); addGrandTotals(greyBorder, projectStatusses, getConfig()); addColumnLabels(greyBorder); addTableData(greyBorder, projectStatusses); add(greyBorder); } private void addGrandTotals(WebMarkupContainer container, Collection<UserProjectStatus> projectStatusSet, EhourConfig config) { float totalHours = 0; float totalTurnover = 0; Label turnOverLabel; if (projectStatusSet != null) { for (UserProjectStatus status : projectStatusSet) { totalHours += (status.getHours() != null) ? status.getHours().floatValue() : 0; totalTurnover += (status.getTurnOver() != null) ? status.getTurnOver().floatValue() : 0; } } container.add(new Label("grandTotalHours", new Model<>(totalHours))); turnOverLabel = new CurrencyLabel("grandTotalTurnover", new Model<>(totalTurnover)); turnOverLabel.setVisible(config.isShowTurnover()); turnOverLabel.setEscapeModelStrings(false); container.add(turnOverLabel); turnOverLabel = HtmlUtil.getNbspLabel("grandRate"); turnOverLabel.setVisible(config.isShowTurnover()); turnOverLabel.setEscapeModelStrings(false); container.add(turnOverLabel); Label projectLabel = HtmlUtil.getNbspLabel("grandProject"); Label customerLabel = HtmlUtil.getNbspLabel("grandCustomer"); if (!config.isShowTurnover()) { customerLabel.add(AttributeModifier.replace("style", "width: 30%")); projectLabel.add(AttributeModifier.replace("style", "width: 35%")); } container.add(customerLabel); container.add(projectLabel); } private void addColumnLabels(WebMarkupContainer container) { Label projectLabel = new Label("projectLabel", new ResourceModel("overview.project")); setProjectLabelWidth(projectLabel); container.add(projectLabel); Label customerLabel = new Label("customerLabel", new ResourceModel("overview.customer")); setCustomerLabelWidth(customerLabel); container.add(customerLabel); Label rateLabel = new Label("rateLabel", new ResourceModel("overview.rate")); setRateWidthOrHide(rateLabel); container.add(rateLabel); Label turnOverLabel = new Label("turnoverLabel", new ResourceModel("overview.turnover")); setTurnoverWidthOrHide(turnOverLabel); container.add(turnOverLabel); } @SuppressWarnings("serial") private void addTableData(WebMarkupContainer container, Collection<UserProjectStatus> projectStatusSet) { List<UserProjectStatus> statusses = projectStatusSet == null ? new ArrayList<UserProjectStatus>() : new ArrayList<>(projectStatusSet); // table data should reflect the path to the listView ListView<UserProjectStatus> view = new ListView<UserProjectStatus>(ID_TABLE_DATA, statusses) { public void populateItem(final ListItem<UserProjectStatus> item) { UserProjectStatus projectStatus = item.getModelObject(); WebMarkupContainer projectNameContainer = new WebMarkupContainer("projectNameContainer"); item.add(projectNameContainer); setProjectLabelWidth(projectNameContainer); Project project = projectStatus.getProjectAssignment().getProject(); Label projectLabel = new Label("projectName", project.getName()); projectLabel.setMarkupId(String.format("prjN%d", project.getProjectId())); projectLabel.setOutputMarkupId(true); projectNameContainer.add(projectLabel); String name = project.getCustomer().getName(); Label customerLabel = new Label("customerName", name); createTitle(customerLabel, name); setCustomerLabelWidth(customerLabel); item.add(customerLabel); String projectCode = project.getProjectCode(); Label projectCodeLabel = new Label("projectCode", projectCode); createTitle(customerLabel, projectCode); projectCodeLabel.setMarkupId(String.format("prjC%d", project.getProjectId())); projectCodeLabel.setOutputMarkupId(true); item.add(projectCodeLabel); Float hourlyRate = projectStatus.getProjectAssignment().getHourlyRate(); Label rateLabel = hourlyRate != null ? new CurrencyLabel("rate", hourlyRate) : new Label("rate", "--"); rateLabel.setEscapeModelStrings(false); setRateWidthOrHide(rateLabel); item.add(rateLabel); Number hours = projectStatus.getHours(); item.add(new Label("monthHours", new Model<>(hours != null ? hours.floatValue() : 0f))); boolean billable = project.isBillable(); Label turnOverLabel = billable ? new CurrencyLabel("turnover", projectStatus.getTurnOver().floatValue()) : new Label("turnover", "--"); setTurnoverWidthOrHide(turnOverLabel); item.add(turnOverLabel); // SummaryRow Component projectSummaryRow = createProjectSummaryRow(ID_SUMMARY_ROW, projectStatus); item.add(projectSummaryRow); item.add(createFoldLink(projectSummaryRow)); } }; container.add(view); } private void createTitle(Label label, String title) { label.add(AttributeModifier.append("title", title)); } /** * Create fold link (also contains the creation of the summary row) */ @SuppressWarnings("serial") private Component createFoldLink(final Component original) { AjaxLink<String> foldLink = new AjaxLink<String>(ID_FOLD_LINK) { @Override public void onClick(AjaxRequestTarget target) { boolean isVisible = original.isVisible(); original.setVisible(!isVisible); target.add(original); WebMarkupContainer img = createFoldImage(!isVisible); this.get(ID_FOLD_IMG).replaceWith(img); target.add(img); } }; final WebMarkupContainer originalImage = createFoldImage(false); foldLink.add(originalImage); return foldLink; } private WebMarkupContainer createFoldImage(boolean up) { WebMarkupContainer foldImg = new WebMarkupContainer("foldImg"); foldImg.add(AttributeModifier.replace("class", up ? "fa fa-angle-up" : "fa fa-angle-down")); foldImg.setOutputMarkupId(true); return foldImg; } private Component createProjectSummaryRow(String id, UserProjectStatus projectStatus) { // SummaryRow placeholder WebMarkupContainer container = new WebMarkupContainer(id); container.setOutputMarkupId(true); container.setOutputMarkupPlaceholderTag(true); container.setVisible(false); // valid from until label DateModel startDate = new DateModel(projectStatus.getProjectAssignment().getDateStart(), getConfig()); DateModel endDate = new DateModel(projectStatus.getProjectAssignment().getDateEnd(), getConfig()); Label validityLabel = new Label("overview.validity", new MessageResourceModel("overview.validity", this, startDate, endDate)); validityLabel.setEscapeModelStrings(false); container.add(validityLabel); WebMarkupContainer cont = new WebMarkupContainer("remainingHoursLabel"); // only shown for allotted types cont.setVisible(projectStatus.getProjectAssignment().getAssignmentType().isAllottedType()); Number bookedHours = projectStatus.getTotalBookedHours(); float totalBookedHours = (bookedHours != null) ? projectStatus.getTotalBookedHours().floatValue() : 0; cont.add(new Label("overview.totalbooked", new MessageResourceModel("overview.totalbooked", this, totalBookedHours))); Label remainingLabel = new Label("overview.remainingfixed", new MessageResourceModel("overview.remainingfixed", this, projectStatus.getFixedHoursRemaining())); remainingLabel.setVisible(projectStatus.getProjectAssignment().getAssignmentType().isAllottedType()); cont.add(remainingLabel); Label remainingFlexLabel = new Label("overview.remainingflex", new MessageResourceModel("overview.remainingflex", this, projectStatus.getFlexHoursRemaining())); // only shown for flex allotted types remainingFlexLabel.setVisible(projectStatus.getProjectAssignment().getAssignmentType().isFlexAllottedType()); cont.add(remainingFlexLabel); container.add(cont); return container; } private void setCustomerLabelWidth(Label label) { if (!isTurnOverVisible()) { label.add(AttributeModifier.replace("style", "width: 30%;")); } } private void setProjectLabelWidth(Component label) { if (!isTurnOverVisible()) { label.add(AttributeModifier.replace("style", "width: 35%;")); } } private void setRateWidthOrHide(Label label) { label.setVisible(isTurnOverVisible()); } private void setTurnoverWidthOrHide(Label label) { label.setVisible(isTurnOverVisible()); } private boolean isTurnOverVisible() { return getConfig().isShowTurnover(); } }