/* * HeadsUp Agile * Copyright 2009-2014 Heads Up Development Ltd. * * 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 <http://www.gnu.org/licenses/>. */ package org.headsupdev.agile.app.milestones; import org.apache.wicket.PageParameters; import org.apache.wicket.ResourceReference; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.markup.html.CSSPackageResource; import org.apache.wicket.markup.html.image.Image; import org.apache.wicket.markup.html.link.BookmarkablePageLink; import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.markup.html.link.ResourceLink; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.util.value.ValueMap; import org.headsupdev.agile.api.Manager; import org.headsupdev.agile.api.MenuLink; import org.headsupdev.agile.api.Permission; import org.headsupdev.agile.app.milestones.permission.MilestoneEditPermission; import org.headsupdev.agile.app.milestones.permission.MilestoneViewPermission; import org.headsupdev.agile.storage.Comment; import org.headsupdev.agile.storage.HibernateStorage; import org.headsupdev.agile.storage.StoredProject; import org.headsupdev.agile.storage.dao.MilestonesDAO; import org.headsupdev.agile.storage.issues.Issue; import org.headsupdev.agile.storage.issues.Milestone; import org.headsupdev.agile.web.BookmarkableMenuLink; import org.headsupdev.agile.web.HeadsUpPage; import org.headsupdev.agile.web.MountPoint; import org.headsupdev.agile.web.RenderUtil; import org.headsupdev.agile.web.components.CommentPanel; import org.headsupdev.agile.web.components.issues.IssueFilterPanel; import org.headsupdev.agile.web.components.issues.IssueListPanel; import org.headsupdev.agile.web.dialogs.ConfirmDialog; import org.headsupdev.agile.web.wicket.SortableEntityProvider; import org.hibernate.Criteria; import org.hibernate.Session; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; import java.util.*; /** * Milestone view page * * @author Andrew Williams * @version $Id$ * @since 1.0 */ @MountPoint("view") public class ViewMilestone extends HeadsUpPage { private MilestonesDAO dao = new MilestonesDAO(); private Milestone milestone; private IssueFilterPanel filter; public Permission getRequiredPermission() { return new MilestoneViewPermission(); } public void layout() { super.layout(); add( CSSPackageResource.getHeaderContribution( getClass(), "milestone.css" ) ); String name = getPageParameters().getString( "id" ); milestone = dao.find( name, getProject() ); if ( milestone == null ) { notFoundError(); return; } addLinks( getLinks( milestone ) ); addDetails(); final List<Comment> commentList = new LinkedList<Comment>(); commentList.addAll( milestone.getComments() ); Collections.sort( commentList, new Comparator<Comment>() { public int compare( Comment comment1, Comment comment2 ) { return comment1.getCreated().compareTo( comment2.getCreated() ); } } ); add( new ListView<Comment>( "comments", commentList ) { protected void populateItem( ListItem<Comment> listItem ) { CommentPanel panel = new CommentPanel<Milestone>( "comment", listItem.getModel(), getProject(), commentList, milestone, new MilestoneEditPermission() ) { @Override public void showConfirmDialog( ConfirmDialog dialog, AjaxRequestTarget target ) { showDialog( dialog, target ); } @Override public Link getEditLink() { PageParameters params = new PageParameters(); params.put( "project", getProject() ); params.put( "id", milestone.getName() ); params.put( "commentId", getComment().getId() ); return new BookmarkablePageLink( "editComment", EditComment.class, params ); } }; listItem.add( panel ); } } ); filter = new IssueFilterPanel( "filter", getFilterButton(), getSession().getUser() ) { @Override public void invalidDatePeriod() { warn( "Invalid date period" ); } }; if ( milestone.isCompleted() ) { filter.setStatuses( new boolean[]{false, false, false, false, false, true, true} ); } else { filter.setStatuses( new boolean[]{true, true, true, true, true, false, false} ); } add( filter ); add( new IssueListPanel( "issuelist", getIssuesProvider(), this, true, true, milestone ) ); boolean timeEnabled = Boolean.parseBoolean( milestone.getProject().getConfigurationValue( StoredProject.CONFIGURATION_TIMETRACKING_ENABLED ) ) && milestone.hasValidTimePeriod(); add( new Image( "graph", new ResourceReference( "burndown.png" ), getPageParameters() ).setVisible( timeEnabled ) ); add( new WorkRemainingTable( "table", milestone ).setVisible( timeEnabled ) ); ValueMap params = new ValueMap(); params.put( "project", getProject().getId() ); params.put( "id", milestone.getName() ); params.put( "silent", true ); add( new ResourceLink( "export", new ResourceReference( "export-worked.csv" ), params ).setVisible( timeEnabled ) ); } public Milestone getMilestone() { return milestone; } private SortableEntityProvider<Issue> getIssuesProvider() { return new SortableEntityProvider<Issue>() { @Override protected Criteria createCriteria() { Session session = ( (HibernateStorage) Manager.getStorageInstance() ).getHibernateSession(); Criteria c = session.createCriteria( Issue.class ); c.setResultTransformer( Criteria.DISTINCT_ROOT_ENTITY ); c.add( filter.getStatusCriterion() ); Criterion assignmentRestriction = filter.getAssignmentCriterion(); if ( assignmentRestriction != null ) { c.add( assignmentRestriction ); } c.add( Restrictions.eq( "milestone", milestone ) ); return c; } @Override protected List<Order> getDefaultOrder() { return Arrays.asList( Order.asc( "priority" ), Order.asc( "rank" ), Order.asc( "status" ), Order.asc( "id.id" ) ); } }; } @Override public String getPageTitle() { return "Milestone:" + milestone.getName() + PAGE_TITLE_SEPARATOR + super.getPageTitle(); } protected void addDetails() { add( new MilestonePanel( "milestone", milestone ) ); } public static List<MenuLink> getLinks( Milestone milestone ) { List<MenuLink> links = new LinkedList<MenuLink>(); PageParameters addIssueParams = new PageParameters(); addIssueParams.add( "project", milestone.getProject().getId() ); addIssueParams.add( "milestone", milestone.getName() ); PageParameters pageParams = new PageParameters(); pageParams.add( "project", milestone.getProject().getId() ); pageParams.add( "id", milestone.getName() ); links.add( new BookmarkableMenuLink( RenderUtil.getPageClass( "issues/create" ), addIssueParams, "add issue" ) ); links.add( new BookmarkableMenuLink( RenderUtil.getPageClass( "milestones/edit" ), pageParams, "edit" ) ); if ( milestone.getCompletedDate() == null ) { if ( milestone.getOpenIssues().size() == 0 ) { links.add( new BookmarkableMenuLink( RenderUtil.getPageClass( "milestones/complete" ), pageParams, "complete" ) ); } links.add( new BookmarkableMenuLink( RenderUtil.getPageClass( "milestones/comment" ), pageParams, "comment" ) ); } else { links.add( new BookmarkableMenuLink( RenderUtil.getPageClass( "milestones/reopen" ), pageParams, "reopen" ) ); } return links; } @Override public boolean hasFilter() { return true; } } class IssueComparator implements Comparator<Issue> { public int compare( Issue o1, Issue o2 ) { if ( o1 == null ) { if ( o2 == null ) { return 0; } return -1; } if ( o2 == null ) { return 1; } if ( o1.getPriority() == o2.getPriority() ) { return o1.getStatus() - o2.getStatus(); } return o1.getPriority() - o2.getPriority(); } }