summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJames Moger <james.moger@gitblit.com>2014-04-28 11:08:50 -0400
committerJames Moger <james.moger@gitblit.com>2014-05-01 14:31:18 -0400
commit667163976e4e51fc3ebf191525e44d97c8a724dc (patch)
tree1391744c8d316b2acc5c7e6e7760091b4668b816 /src
parent6209dc4fd442887e18e3dd6fe7056f4b842091c2 (diff)
downloadgitblit-667163976e4e51fc3ebf191525e44d97c8a724dc.tar.gz
gitblit-667163976e4e51fc3ebf191525e44d97c8a724dc.zip
Overdue labeling, notify changed tickets control
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/gitblit/tickets/ITicketService.java38
-rw-r--r--src/main/java/com/gitblit/tickets/TicketMilestone.java10
-rw-r--r--src/main/java/com/gitblit/wicket/GitBlitWebApp.properties4
-rw-r--r--src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html3
-rw-r--r--src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java7
-rw-r--r--src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html2
-rw-r--r--src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java11
-rw-r--r--src/main/java/com/gitblit/wicket/pages/TicketsPage.java26
8 files changed, 82 insertions, 19 deletions
diff --git a/src/main/java/com/gitblit/tickets/ITicketService.java b/src/main/java/com/gitblit/tickets/ITicketService.java
index cce805ed..3261ca96 100644
--- a/src/main/java/com/gitblit/tickets/ITicketService.java
+++ b/src/main/java/com/gitblit/tickets/ITicketService.java
@@ -651,11 +651,12 @@ public abstract class ITicketService {
* @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 @@ public abstract class ITicketService {
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 @@ public abstract class ITicketService {
* @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 @@ public abstract class ITicketService {
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);
diff --git a/src/main/java/com/gitblit/tickets/TicketMilestone.java b/src/main/java/com/gitblit/tickets/TicketMilestone.java
index 680615a9..dacedda6 100644
--- a/src/main/java/com/gitblit/tickets/TicketMilestone.java
+++ b/src/main/java/com/gitblit/tickets/TicketMilestone.java
@@ -37,7 +37,15 @@ public class TicketMilestone extends TicketLabel {
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;
}
diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
index ce4c0b22..e66e53a7 100644
--- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
+++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
@@ -673,4 +673,6 @@ gb.mergeToDescription = default integration branch for merging ticket patchsets
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 \ No newline at end of file
+gb.editMilestone = edit milestone
+gb.notifyChangedOpenTickets = send notification for changed open tickets
+gb.overdue = overdue \ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html
index 31f76f1c..0897ebee 100644
--- a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html
+++ b/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>
diff --git a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java
index 967d8f35..b844442a 100644
--- a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java
+++ b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java
@@ -24,7 +24,9 @@ import org.apache.wicket.RestartResponseException;
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 @@ public class EditMilestonePage extends RepositoryPage {
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 class EditMilestonePage extends RepositoryPage {
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
diff --git a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html
index 1b7e11ae..2ba5d5cc 100644
--- a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html
+++ b/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>
diff --git a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java
index d6e34cb0..a9f76d3a 100644
--- a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java
+++ b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java
@@ -22,6 +22,7 @@ import org.apache.wicket.RestartResponseException;
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 @@ public class NewMilestonePage extends RepositoryPage {
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 @@ public class NewMilestonePage extends RepositoryPage {
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 @@ public class NewMilestonePage extends RepositoryPage {
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);
diff --git a/src/main/java/com/gitblit/wicket/pages/TicketsPage.java b/src/main/java/com/gitblit/wicket/pages/TicketsPage.java
index 984b3754..b7e392a2 100644
--- a/src/main/java/com/gitblit/wicket/pages/TicketsPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/TicketsPage.java
@@ -20,6 +20,7 @@ import java.text.MessageFormat;
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 @@ public class TicketsPage extends TicketBasePage {
} 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 @@ public class TicketsPage extends TicketBasePage {
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);