com.esofthead.mycollab.module.project.view.milestone.MilestoneRoadmapViewImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.esofthead.mycollab.module.project.view.milestone.MilestoneRoadmapViewImpl.java

Source

/**
 * This file is part of mycollab-web.
 *
 * mycollab-web 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 3 of the License, or
 * (at your option) any later version.
 *
 * mycollab-web 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 mycollab-web.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.esofthead.mycollab.module.project.view.milestone;

import com.esofthead.mycollab.common.i18n.GenericI18Enum;
import com.esofthead.mycollab.configuration.SiteConfiguration;
import com.esofthead.mycollab.configuration.StorageFactory;
import com.esofthead.mycollab.core.arguments.BasicSearchRequest;
import com.esofthead.mycollab.core.arguments.NumberSearchField;
import com.esofthead.mycollab.core.arguments.SearchCriteria;
import com.esofthead.mycollab.core.arguments.SetSearchField;
import com.esofthead.mycollab.core.db.query.LazyValueInjector;
import com.esofthead.mycollab.core.utils.BeanUtility;
import com.esofthead.mycollab.core.utils.StringUtils;
import com.esofthead.mycollab.eventmanager.ApplicationEventListener;
import com.esofthead.mycollab.eventmanager.EventBusFactory;
import com.esofthead.mycollab.module.project.CurrentProjectVariables;
import com.esofthead.mycollab.module.project.ProjectRolePermissionCollections;
import com.esofthead.mycollab.module.project.ProjectTypeConstants;
import com.esofthead.mycollab.module.project.domain.ProjectGenericTask;
import com.esofthead.mycollab.module.project.domain.SimpleMilestone;
import com.esofthead.mycollab.module.project.domain.criteria.MilestoneSearchCriteria;
import com.esofthead.mycollab.module.project.domain.criteria.ProjectGenericTaskSearchCriteria;
import com.esofthead.mycollab.module.project.events.MilestoneEvent;
import com.esofthead.mycollab.module.project.i18n.MilestoneI18nEnum;
import com.esofthead.mycollab.module.project.i18n.OptionI18nEnum;
import com.esofthead.mycollab.module.project.i18n.ProjectI18nEnum;
import com.esofthead.mycollab.module.project.service.MilestoneService;
import com.esofthead.mycollab.module.project.service.ProjectGenericTaskService;
import com.esofthead.mycollab.module.project.ui.ProjectAssetsManager;
import com.esofthead.mycollab.spring.AppContextUtil;
import com.esofthead.mycollab.vaadin.AppContext;
import com.esofthead.mycollab.vaadin.mvp.ViewComponent;
import com.esofthead.mycollab.vaadin.mvp.ViewManager;
import com.esofthead.mycollab.vaadin.mvp.view.AbstractLazyPageView;
import com.esofthead.mycollab.vaadin.ui.ELabel;
import com.esofthead.mycollab.vaadin.web.ui.ToggleButtonGroup;
import com.esofthead.mycollab.vaadin.web.ui.UIConstants;
import com.esofthead.vaadin.floatingcomponent.FloatingComponent;
import com.google.common.eventbus.Subscribe;
import com.hp.gagawa.java.elements.Img;
import com.vaadin.data.Property;
import com.vaadin.server.FontAwesome;
import com.vaadin.shared.ui.MarginInfo;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.*;
import org.vaadin.teemu.VaadinIcons;
import org.vaadin.viritin.layouts.MHorizontalLayout;
import org.vaadin.viritin.layouts.MVerticalLayout;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author MyCollab Ltd
 * @since 5.2.0
 */
@ViewComponent
public class MilestoneRoadmapViewImpl extends AbstractLazyPageView implements MilestoneRoadmapView {
    private Button createBtn;

    private MilestoneService milestoneService = AppContextUtil.getSpringBean(MilestoneService.class);

    private ApplicationEventListener<MilestoneEvent.NewMilestoneAdded> newMilestoneHandler = new ApplicationEventListener<MilestoneEvent.NewMilestoneAdded>() {
        @Override
        @Subscribe
        public void handle(MilestoneEvent.NewMilestoneAdded event) {
            MilestoneRoadmapViewImpl.this.removeAllComponents();
            displayView();
        }
    };

    private MVerticalLayout roadMapView;
    private VerticalLayout filterPanel;
    private ELabel headerText;
    private MilestoneSearchCriteria baseCriteria;

    @Override
    public void attach() {
        EventBusFactory.getInstance().register(newMilestoneHandler);
        super.attach();
    }

    @Override
    public void detach() {
        EventBusFactory.getInstance().unregister(newMilestoneHandler);
        super.detach();
    }

    @Override
    protected void displayView() {
        initUI();
        createBtn.setEnabled(CurrentProjectVariables.canWrite(ProjectRolePermissionCollections.MILESTONES));

        baseCriteria = new MilestoneSearchCriteria();
        baseCriteria.setProjectIds(new SetSearchField<>(CurrentProjectVariables.getProjectId()));
        baseCriteria.setOrderFields(Arrays.asList(new SearchCriteria.OrderField("startdate", SearchCriteria.DESC),
                new SearchCriteria.OrderField("enddate", SearchCriteria.DESC)));
        displayMilestones();

        final MilestoneSearchCriteria tmpCriteria = BeanUtility.deepClone(baseCriteria);
        tmpCriteria.setStatuses(new SetSearchField<>(OptionI18nEnum.MilestoneStatus.Closed.name()));
        int totalCloseCount = milestoneService.getTotalCount(tmpCriteria);
        final CheckBox closeMilestoneSelection = new CheckBox(
                AppContext.getMessage(MilestoneI18nEnum.WIDGET_CLOSED_PHASE_TITLE) + " (" + totalCloseCount + ")",
                true);
        closeMilestoneSelection.setIcon(FontAwesome.MINUS_CIRCLE);
        filterPanel.addComponent(closeMilestoneSelection);

        tmpCriteria.setStatuses(new SetSearchField<>(OptionI18nEnum.MilestoneStatus.InProgress.name()));
        int totalInProgressCount = milestoneService.getTotalCount(tmpCriteria);
        final CheckBox inProgressMilestoneSelection = new CheckBox(
                AppContext.getMessage(MilestoneI18nEnum.WIDGET_INPROGRESS_PHASE_TITLE) + " (" + totalInProgressCount
                        + ")",
                true);
        inProgressMilestoneSelection.setIcon(FontAwesome.SPINNER);
        filterPanel.addComponent(inProgressMilestoneSelection);

        tmpCriteria.setStatuses(new SetSearchField<>(OptionI18nEnum.MilestoneStatus.Future.name()));
        int totalFutureCount = milestoneService.getTotalCount(tmpCriteria);
        final CheckBox futureMilestoneSelection = new CheckBox(
                AppContext.getMessage(MilestoneI18nEnum.WIDGET_FUTURE_PHASE_TITLE) + " (" + totalFutureCount + ")",
                true);

        closeMilestoneSelection.addValueChangeListener(new Property.ValueChangeListener() {
            @Override
            public void valueChange(Property.ValueChangeEvent valueChangeEvent) {
                displayMilestones(tmpCriteria, closeMilestoneSelection.getValue(),
                        inProgressMilestoneSelection.getValue(), futureMilestoneSelection.getValue());
            }
        });
        inProgressMilestoneSelection.addValueChangeListener(new Property.ValueChangeListener() {
            @Override
            public void valueChange(Property.ValueChangeEvent valueChangeEvent) {
                displayMilestones(tmpCriteria, closeMilestoneSelection.getValue(),
                        inProgressMilestoneSelection.getValue(), futureMilestoneSelection.getValue());
            }
        });
        futureMilestoneSelection.addValueChangeListener(new Property.ValueChangeListener() {
            @Override
            public void valueChange(Property.ValueChangeEvent valueChangeEvent) {
                displayMilestones(tmpCriteria, closeMilestoneSelection.getValue(),
                        inProgressMilestoneSelection.getValue(), futureMilestoneSelection.getValue());
            }
        });
        futureMilestoneSelection.setIcon(FontAwesome.CLOCK_O);
        filterPanel.addComponent(futureMilestoneSelection);
    }

    private void displayMilestones(MilestoneSearchCriteria milestoneSearchCriteria, boolean closeSelection,
            boolean inProgressSelection, boolean futureSelection) {
        baseCriteria = milestoneSearchCriteria;
        List<String> statuses = new ArrayList<>();
        if (closeSelection) {
            statuses.add(OptionI18nEnum.MilestoneStatus.Closed.name());
        }
        if (inProgressSelection) {
            statuses.add(OptionI18nEnum.MilestoneStatus.InProgress.name());
        }
        if (futureSelection) {
            statuses.add(OptionI18nEnum.MilestoneStatus.Future.name());
        }
        if (statuses.size() > 0) {
            baseCriteria.setStatuses(new SetSearchField<>(statuses));
            displayMilestones();
        } else {
            roadMapView.removeAllComponents();
        }
    }

    private void displayMilestones() {
        roadMapView.removeAllComponents();
        List<SimpleMilestone> milestones = milestoneService
                .findPagableListByCriteria(new BasicSearchRequest<>(baseCriteria, 0, Integer.MAX_VALUE));
        for (SimpleMilestone milestone : milestones) {
            roadMapView.addComponent(new MilestoneBlock(milestone));
        }

        headerText.setValue(ProjectAssetsManager.getAsset(ProjectTypeConstants.MILESTONE).getHtml() + " Roadmap ("
                + milestones.size() + ")");
    }

    private void initUI() {
        headerText = ELabel.h2("");

        MHorizontalLayout header = new MHorizontalLayout().withStyleName("hdr-view").withFullWidth()
                .withMargin(true).with(headerText, createHeaderRight()).withAlign(headerText, Alignment.MIDDLE_LEFT)
                .expand(headerText);
        this.addComponent(header);
        roadMapView = new MVerticalLayout().withSpacing(false);
        filterPanel = new MVerticalLayout().withWidth("250px").withStyleName("box");
        FloatingComponent floatingComponent = FloatingComponent.floatThis(filterPanel);
        floatingComponent.setContainerId("main-body");
        this.addComponent(
                new MHorizontalLayout().withFullWidth().with(roadMapView, filterPanel).expand(roadMapView));
    }

    private HorizontalLayout createHeaderRight() {
        MHorizontalLayout layout = new MHorizontalLayout();

        createBtn = new Button(AppContext.getMessage(MilestoneI18nEnum.NEW), new Button.ClickListener() {
            private static final long serialVersionUID = 1L;

            @Override
            public void buttonClick(final Button.ClickEvent event) {
                SimpleMilestone milestone = new SimpleMilestone();
                milestone.setSaccountid(AppContext.getAccountId());
                milestone.setProjectid(CurrentProjectVariables.getProjectId());
                UI.getCurrent().addWindow(new MilestoneAddWindow(milestone));
            }
        });
        createBtn.setIcon(FontAwesome.PLUS);
        createBtn.setStyleName(UIConstants.BUTTON_ACTION);
        createBtn.setEnabled(CurrentProjectVariables.canWrite(ProjectRolePermissionCollections.MILESTONES));
        layout.with(createBtn);

        Button printBtn = new Button("", new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent clickEvent) {
                UI.getCurrent().addWindow(new MilestoneCustomizeReportOutputWindow(new LazyValueInjector() {
                    @Override
                    protected Object doEval() {
                        return baseCriteria;
                    }
                }));
            }
        });
        printBtn.setIcon(FontAwesome.PRINT);
        printBtn.addStyleName(UIConstants.BUTTON_OPTION);
        printBtn.setDescription(AppContext.getMessage(GenericI18Enum.ACTION_EXPORT));
        layout.addComponent(printBtn);

        Button kanbanBtn = new Button("Board", new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent clickEvent) {
                EventBusFactory.getInstance()
                        .post(new MilestoneEvent.GotoList(MilestoneRoadmapViewImpl.this, null));
            }
        });
        kanbanBtn.setDescription("Board View");
        kanbanBtn.setIcon(FontAwesome.TH);

        Button roadmapBtn = new Button("List");
        roadmapBtn.setDescription("Roadmap");
        roadmapBtn.setIcon(VaadinIcons.CUBE);

        ToggleButtonGroup viewButtons = new ToggleButtonGroup();
        viewButtons.addButton(roadmapBtn);
        viewButtons.addButton(kanbanBtn);
        viewButtons.withDefaultButton(roadmapBtn);
        layout.with(viewButtons);

        return layout;
    }

    private static class MilestoneBlock extends MVerticalLayout {
        private boolean showIssues = false;

        MilestoneBlock(final SimpleMilestone milestone) {
            this.setMargin(new MarginInfo(true, false, true, false));
            this.setStyleName("roadmap-block");

            ELabel statusLbl = new ELabel(
                    AppContext.getMessage(OptionI18nEnum.MilestoneStatus.class, milestone.getStatus()))
                            .withStyleName(UIConstants.FIELD_NOTE).withWidthUndefined();
            ToggleMilestoneSummaryField toggleMilestoneSummaryField = new ToggleMilestoneSummaryField(milestone);
            MHorizontalLayout headerLayout = new MHorizontalLayout(statusLbl, toggleMilestoneSummaryField)
                    .expand(toggleMilestoneSummaryField).withFullWidth();
            this.with(headerLayout);

            CssLayout metaBlock = new CssLayout();
            MilestonePopupFieldFactory popupFieldFactory = ViewManager
                    .getCacheComponent(MilestonePopupFieldFactory.class);
            metaBlock.addComponent(popupFieldFactory.createMilestoneAssigneePopupField(milestone, true));
            metaBlock.addComponent(popupFieldFactory.createStartDatePopupField(milestone));
            metaBlock.addComponent(popupFieldFactory.createEndDatePopupField(milestone));
            if (!SiteConfiguration.isCommunityEdition()) {
                metaBlock.addComponent(popupFieldFactory.createBillableHoursPopupField(milestone));
                metaBlock.addComponent(popupFieldFactory.createNonBillableHoursPopupField(milestone));
            }

            this.add(metaBlock);

            if (StringUtils.isNotBlank(milestone.getDescription())) {
                ELabel descriptionLbl = new ELabel(StringUtils.formatRichText(milestone.getDescription()),
                        ContentMode.HTML);
                this.addComponent(descriptionLbl);
            }

            MHorizontalLayout progressLayout = new MHorizontalLayout();
            progressLayout.setDefaultComponentAlignment(Alignment.MIDDLE_LEFT);
            int openAssignments = milestone.getNumOpenBugs() + milestone.getNumOpenTasks();
            int totalAssignments = milestone.getNumBugs() + milestone.getNumTasks();
            ELabel progressInfoLbl;
            if (totalAssignments > 0) {
                progressInfoLbl = new ELabel(AppContext.getMessage(ProjectI18nEnum.OPT_PROJECT_ASSIGNMENT,
                        (totalAssignments - openAssignments), totalAssignments,
                        (totalAssignments - openAssignments) * 100 / totalAssignments))
                                .withStyleName(UIConstants.META_INFO);
            } else {
                progressInfoLbl = new ELabel(AppContext.getMessage(ProjectI18nEnum.OPT_NO_ASSIGNMENT))
                        .withStyleName(UIConstants.META_INFO);
            }

            final MVerticalLayout issueLayout = new MVerticalLayout()
                    .withMargin(new MarginInfo(false, true, false, true));
            issueLayout.setVisible(false);

            progressLayout.with(progressInfoLbl);

            if (totalAssignments > 0) {
                final Button viewIssuesBtn = new Button(
                        AppContext.getMessage(ProjectI18nEnum.ACTION_VIEW_ASSIGNMENTS));
                Button.ClickListener viewIssuesListener = new Button.ClickListener() {
                    @Override
                    public void buttonClick(Button.ClickEvent clickEvent) {
                        showIssues = !showIssues;
                        if (showIssues) {
                            issueLayout.setVisible(true);
                            viewIssuesBtn
                                    .setCaption(AppContext.getMessage(ProjectI18nEnum.ACTION_HIDE_ASSIGNMENTS));
                            ProjectGenericTaskSearchCriteria searchCriteria = new ProjectGenericTaskSearchCriteria();
                            searchCriteria
                                    .setProjectIds(new SetSearchField<>(CurrentProjectVariables.getProjectId()));
                            searchCriteria.setTypes(
                                    new SetSearchField<>(ProjectTypeConstants.BUG, ProjectTypeConstants.TASK));
                            searchCriteria.setMilestoneId(new NumberSearchField(milestone.getId()));
                            ProjectGenericTaskService genericTaskService = AppContextUtil
                                    .getSpringBean(ProjectGenericTaskService.class);
                            List<ProjectGenericTask> genericTasks = genericTaskService.findPagableListByCriteria(
                                    new BasicSearchRequest<>(searchCriteria, 0, Integer.MAX_VALUE));
                            for (ProjectGenericTask genericTask : genericTasks) {
                                ToggleGenericTaskSummaryField toggleGenericTaskSummaryField = new ToggleGenericTaskSummaryField(
                                        genericTask);
                                MHorizontalLayout rowComp = new MHorizontalLayout();
                                rowComp.setDefaultComponentAlignment(Alignment.TOP_LEFT);
                                rowComp.with(
                                        new ELabel(ProjectAssetsManager.getAsset(genericTask.getType()).getHtml(),
                                                ContentMode.HTML).withWidthUndefined());
                                String status = "";
                                if (genericTask.isBug()) {
                                    status = AppContext.getMessage(OptionI18nEnum.BugStatus.class,
                                            genericTask.getStatus());
                                } else if (genericTask.isMilestone()) {
                                    status = AppContext.getMessage(OptionI18nEnum.MilestoneStatus.class,
                                            genericTask.getStatus());
                                } else if (genericTask.isRisk()) {
                                    status = AppContext.getMessage(
                                            com.esofthead.mycollab.common.i18n.OptionI18nEnum.StatusI18nEnum.class,
                                            genericTask.getStatus());
                                } else if (genericTask.isTask()) {
                                    status = AppContext.getMessage(
                                            com.esofthead.mycollab.common.i18n.OptionI18nEnum.StatusI18nEnum.class,
                                            genericTask.getStatus());
                                }
                                rowComp.with(new ELabel(status).withStyleName(UIConstants.FIELD_NOTE)
                                        .withWidthUndefined());
                                String avatarLink = StorageFactory.getInstance()
                                        .getAvatarPath(genericTask.getAssignUserAvatarId(), 16);
                                Img img = new Img(genericTask.getAssignUserFullName(), avatarLink)
                                        .setTitle(genericTask.getAssignUserFullName());
                                rowComp.with(new ELabel(img.write(), ContentMode.HTML).withWidthUndefined());

                                rowComp.with(toggleGenericTaskSummaryField).expand(toggleGenericTaskSummaryField);
                                issueLayout.addComponent(rowComp);

                            }
                        } else {
                            viewIssuesBtn
                                    .setCaption(AppContext.getMessage(ProjectI18nEnum.ACTION_VIEW_ASSIGNMENTS));
                            issueLayout.removeAllComponents();
                            issueLayout.setVisible(false);
                        }
                    }
                };
                viewIssuesBtn.addClickListener(viewIssuesListener);
                viewIssuesBtn.addStyleName(UIConstants.BUTTON_LINK);
                progressLayout.with(viewIssuesBtn);
            }

            this.with(progressLayout, issueLayout);
        }
    }
}