James Moger
2014-04-28 667163976e4e51fc3ebf191525e44d97c8a724dc
Overdue labeling, notify changed tickets control
8 files modified
101 ■■■■ changed files
src/main/java/com/gitblit/tickets/ITicketService.java 38 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/tickets/TicketMilestone.java 10 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/GitBlitWebApp.properties 4 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html 3 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java 7 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java 11 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/TicketsPage.java 26 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/tickets/ITicketService.java
@@ -651,11 +651,12 @@
     * @param oldName
     * @param newName
     * @param createdBy
     * @param send ticket notifications
     * @param notifyOpenTickets
     * @return true if successful
     * @since 1.6.0
     */
    public synchronized boolean renameMilestone(RepositoryModel repository, String oldName, String newName, String createdBy, boolean notify) {
    public synchronized boolean renameMilestone(RepositoryModel repository, String oldName,
            String newName, String createdBy, boolean notifyOpenTickets) {
        if (StringUtils.isEmpty(newName)) {
            throw new IllegalArgumentException("new milestone can not be empty!");
        }
@@ -680,11 +681,11 @@
                Change change = new Change(createdBy);
                change.setField(Field.milestone, newName);
                TicketModel ticket = updateTicket(repository, qr.number, change);
                if (notify && ticket.isOpen()) {
                if (notifyOpenTickets && ticket.isOpen()) {
                    notifier.queueMailing(ticket);
                }
            }
            if (notify) {
            if (notifyOpenTickets) {
                notifier.sendAll();
            }
@@ -709,6 +710,21 @@
     * @since 1.4.0
     */
    public synchronized boolean deleteMilestone(RepositoryModel repository, String milestone, String createdBy) {
        return deleteMilestone(repository, milestone, createdBy, true);
    }
    /**
     * Deletes a milestone.
     *
     * @param repository
     * @param milestone
     * @param createdBy
     * @param notifyOpenTickets
     * @return true if successful
     * @since 1.6.0
     */
    public synchronized boolean deleteMilestone(RepositoryModel repository, String milestone,
            String createdBy, boolean notifyOpenTickets) {
        if (StringUtils.isEmpty(milestone)) {
            throw new IllegalArgumentException("milestone can not be empty!");
        }
@@ -722,14 +738,18 @@
            milestonesCache.remove(repository.name);
            TicketNotifier notifier = createNotifier();
            for (QueryResult qr : tm.tickets) {
                if (qr.isOpen()) {
                    // reset the milestone only for open tickets
                    Change change = new Change(createdBy);
                    change.setField(Field.milestone, "");
                    TicketModel ticket = updateTicket(repository, qr.number, change);
                Change change = new Change(createdBy);
                change.setField(Field.milestone, "");
                TicketModel ticket = updateTicket(repository, qr.number, change);
                if (notifyOpenTickets && ticket.isOpen()) {
                    notifier.queueMailing(ticket);
                }
            }
            if (notifyOpenTickets) {
                notifier.sendAll();
            }
            return true;
        } catch (IOException e) {
            log.error("failed to delete milestone " + milestone + " in " + repository, e);
src/main/java/com/gitblit/tickets/TicketMilestone.java
@@ -37,7 +37,15 @@
        super(name);
        status = Status.Open;
    }
    public boolean isOpen() {
        return status == Status.Open;
    }
    public boolean isOverdue() {
        return due == null ? false : System.currentTimeMillis() > due.getTime();
    }
    public void setDue(Date due) {
        this.due = due;
    }
src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
@@ -673,4 +673,6 @@
gb.anonymousCanNotPropose = Anonymous users can not propose patchsets.
gb.youDoNotHaveClonePermission = You are not permitted to clone this repository.
gb.newMilestone = new milestone
gb.editMilestone = edit milestone
gb.editMilestone = edit milestone
gb.notifyChangedOpenTickets = send notification for changed open tickets
gb.overdue = overdue
src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html
@@ -19,8 +19,9 @@
        <!-- Edit Milestone Table -->
        <table class="ticket">
            <tr><th><wicket:message key="gb.milestone"></wicket:message></th><td class="edit"><input class="input-large" type="text" wicket:id="name" id="name"></input></td></tr>
            <tr><th><wicket:message key="gb.due"></wicket:message></th><td class="edit"><input class="input-large" type="text" wicket:id="due"></input></td></tr>
            <tr><th><wicket:message key="gb.due"></wicket:message></th><td class="edit"><input class="input-large" type="text" wicket:id="due"></input> &nbsp;<span class="help-inline" wicket:id="dueFormat"></span></td></tr>
            <tr><th><wicket:message key="gb.status"></wicket:message><span style="color:red;">*</span></th><td class="edit"><select class="input-large" wicket:id="status"></select></td></tr>
            <tr><th></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="notify" /> &nbsp;<span class="help-inline"><wicket:message key="gb.notifyChangedOpenTickets"></wicket:message></span></label></td></tr>
        </table>
    </div>
    </div>    
src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java
@@ -24,7 +24,9 @@
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.extensions.markup.html.form.DateTextField;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
@@ -102,6 +104,8 @@
        form.add(new TextField<String>("name", nameModel));
        form.add(new DateTextField("due", dueModel, "yyyy-MM-dd"));
        form.add(new Label("dueFormat", "yyyy-MM-dd"));
        form.add(new CheckBox("notify", notificationModel));
        List<Status> statusChoices = Arrays.asList(Status.Open, Status.Closed);
        form.add(new DropDownChoice<TicketModel.Status>("status", statusModel, statusChoices));
@@ -160,8 +164,9 @@
            public void onSubmit() {
                UserModel currentUser = GitBlitWebSession.get().getUser();
                String createdBy = currentUser.username;
                boolean notify = notificationModel.getObject();
                if (app().tickets().deleteMilestone(getRepositoryModel(), oldName, createdBy)) {
                if (app().tickets().deleteMilestone(getRepositoryModel(), oldName, createdBy, notify)) {
                    setResponsePage(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName));
                } else {
                    // TODO error processing
src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html
@@ -19,7 +19,7 @@
        <!-- New Milestone Table -->
        <table class="ticket">
            <tr><th><wicket:message key="gb.milestone"></wicket:message></th><td class="edit"><input class="input-large" type="text" wicket:id="name" id="name"></input></td></tr>
            <tr><th><wicket:message key="gb.due"></wicket:message></th><td class="edit"><input class="input-large" type="text" wicket:id="due"></input></td></tr>
            <tr><th><wicket:message key="gb.due"></wicket:message></th><td class="edit"><input class="input-large" type="text" wicket:id="due"></input> &nbsp;<span class="help-inline" wicket:id="dueFormat"></span></td></tr>
        </table>
    </div>
    </div>    
src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java
@@ -22,6 +22,7 @@
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.extensions.markup.html.form.DateTextField;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
@@ -78,6 +79,7 @@
        form.add(new TextField<String>("name", nameModel));
        form.add(new DateTextField("due", dueModel, "yyyy-MM-dd"));
        form.add(new Label("dueFormat", "yyyy-MM-dd"));
        form.add(new AjaxButton("create") {
@@ -87,6 +89,13 @@
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                String name = nameModel.getObject();
                if (StringUtils.isEmpty(name)) {
                    // invalid name
                    return;
                }
                TicketMilestone milestone = app().tickets().getMilestone(getRepositoryModel(), name);
                if (milestone != null) {
                    // milestone already exists
                    return;
                }
@@ -95,7 +104,7 @@
                UserModel currentUser = GitBlitWebSession.get().getUser();
                String createdBy = currentUser.username;
                TicketMilestone milestone = app().tickets().createMilestone(getRepositoryModel(), name, createdBy);
                milestone = app().tickets().createMilestone(getRepositoryModel(), name, createdBy);
                if (milestone != null) {
                    milestone.due = due;
                    app().tickets().updateMilestone(getRepositoryModel(), milestone, createdBy);
src/main/java/com/gitblit/wicket/pages/TicketsPage.java
@@ -20,6 +20,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
@@ -657,9 +658,20 @@
        } else {
            add(new Label("newMilestone").setVisible(false));
        }
        // milestones list
        List<TicketMilestone> allMilestones = app().tickets().getMilestones(repositoryModel);
        List<TicketMilestone> allMilestones = new ArrayList<TicketMilestone>(app().tickets().getMilestones(repositoryModel));
        Collections.sort(allMilestones, new Comparator<TicketMilestone>() {
            @Override
            public int compare(TicketMilestone o1, TicketMilestone o2) {
                if (o2.isOpen() && !o1.isOpen()) {
                    return 1;
                } else if (o1.isOpen() && !o2.isOpen()) {
                    return -1;
                }
                return o2.due.compareTo(o1.due);
            }
        });
        ListDataProvider<TicketMilestone> allMilestonesDp = new ListDataProvider<TicketMilestone>(allMilestones);
        DataView<TicketMilestone> milestonesList = new DataView<TicketMilestone>("milestoneList", allMilestonesDp) {
            private static final long serialVersionUID = 1L;
@@ -671,15 +683,21 @@
                item.add(new LinkPanel("milestoneName", null, tm.name, TicketsPage.class, params).setRenderBodyOnly(true));
                String css;
                String status = tm.status.name();
                switch (tm.status) {
                case Open:
                    css = "aui-lozenge aui-lozenge-subtle";
                    if (tm.isOverdue()) {
                        css = "aui-lozenge aui-lozenge-subtle aui-lozenge-error";
                        status = "overdue";
                    } else {
                        css = "aui-lozenge aui-lozenge-subtle";
                    }
                    break;
                default:
                    css = "aui-lozenge";
                    break;
                }
                Label stateLabel = new Label("milestoneState", tm.status.name());
                Label stateLabel = new Label("milestoneState", status);
                WicketUtils.setCssClass(stateLabel, css);
                item.add(stateLabel);