+ Severity indicated via new character indicator and color of ticket icon on ticket list
+ Priority indicated via new priority icon and color on ticket list
+ Indexed as integers to provide sorting and maintain language neutral
index
+ Colours and indicator text controlled through CSS classes priority-<x> & severity-<x>
+ UITicketTest created to generate tickets of all types to ease debugging
public Integer deletions;
+ public Priority priority;
+
+ public Severity severity;
+
/**
* Builds an effective ticket from the collection of changes. A change may
* Add or Subtract information from a ticket, but the collection of changes
changes = new ArrayList<Change>();
status = Status.New;
type = Type.defaultType;
+ priority = Priority.defaultPriority;
+ severity = Severity.defaultSeverity;
}
public boolean isOpen() {
case mergeSha:
mergeSha = toString(value);
break;
+ case priority:
+ priority = TicketModel.Priority.fromObject(value, priority);
+ break;
+ case severity:
+ severity = TicketModel.Severity.fromObject(value, severity);
+ break;
default:
// unknown
break;
public static enum Field {
title, body, responsible, type, status, milestone, mergeSha, mergeTo,
- topic, labels, watchers, reviewers, voters, mentions;
+ topic, labels, watchers, reviewers, voters, mentions, priority, severity;
}
public static enum Type {
return null;
}
}
+
+ public static enum Priority {
+ Low(-1), Normal(0), High(1), Urgent(2);
+
+ public static Priority defaultPriority = Normal;
+
+ final int value;
+
+ Priority(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public static Priority [] choices() {
+ return new Priority [] { Urgent, High, Normal, Low };
+ }
+
+ @Override
+ public String toString() {
+ return name().toLowerCase().replace('_', ' ');
+ }
+
+ public static Priority fromObject(Object o, Priority defaultPriority) {
+ if (o instanceof Priority) {
+ // cast and return
+ return (Priority) o;
+ } else if (o instanceof String) {
+ // find by name
+ for (Priority priority : values()) {
+ String str = o.toString();
+ if (priority.name().equalsIgnoreCase(str)
+ || priority.toString().equalsIgnoreCase(str)) {
+ return priority;
+ }
+ }
+ } else if (o instanceof Number) {
+
+ switch (((Number) o).intValue()) {
+ case -1: return Priority.Low;
+ case 0: return Priority.Normal;
+ case 1: return Priority.High;
+ case 2: return Priority.Urgent;
+ default: return Priority.Normal;
+ }
+ }
+
+ return defaultPriority;
+ }
+ }
+
+ public static enum Severity {
+ Unrated(-1), Negligible(1), Minor(2), Serious(3), Critical(4), Catastrophic(5);
+
+ public static Severity defaultSeverity = Unrated;
+
+ final int value;
+
+ Severity(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public static Severity [] choices() {
+ return new Severity [] { Unrated, Negligible, Minor, Serious, Critical, Catastrophic };
+ }
+
+ @Override
+ public String toString() {
+ return name().toLowerCase().replace('_', ' ');
+ }
+
+ public static Severity fromObject(Object o, Severity defaultSeverity) {
+ if (o instanceof Severity) {
+ // cast and return
+ return (Severity) o;
+ } else if (o instanceof String) {
+ // find by name
+ for (Severity severity : values()) {
+ String str = o.toString();
+ if (severity.name().equalsIgnoreCase(str)
+ || severity.toString().equalsIgnoreCase(str)) {
+ return severity;
+ }
+ }
+ } else if (o instanceof Number) {
+
+ switch (((Number) o).intValue()) {
+ case -1: return Severity.Unrated;
+ case 1: return Severity.Negligible;
+ case 2: return Severity.Minor;
+ case 3: return Severity.Serious;
+ case 4: return Severity.Critical;
+ case 5: return Severity.Catastrophic;
+ default: return Severity.Unrated;
+ }
+ }
+
+ return defaultSeverity;
+ }
+ }
}
import com.gitblit.models.TicketModel.Patchset;
import com.gitblit.models.TicketModel.Status;
import com.gitblit.models.TicketModel.Type;
+import com.gitblit.models.TicketModel.Priority;
+import com.gitblit.models.TicketModel.Severity;
import com.gitblit.utils.StringUtils;
/**
public int commentsCount;
public int votesCount;
public int approvalsCount;
+ public Priority priority;
+ public Severity severity;
public int docId;
public int totalResults;
mergesha(Type.STRING),
mergeto(Type.STRING),
patchsets(Type.INT),
- votes(Type.INT);
+ votes(Type.INT),
+ //NOTE: Indexing on the underlying value to allow flexibility on naming
+ priority(Type.INT),
+ severity(Type.INT);
final Type fieldType;
toDocField(doc, Lucene.watchedby, StringUtils.flattenStrings(ticket.getWatchers(), ";").toLowerCase());
toDocField(doc, Lucene.mentions, StringUtils.flattenStrings(ticket.getMentions(), ";").toLowerCase());
toDocField(doc, Lucene.votes, ticket.getVoters().size());
+ toDocField(doc, Lucene.priority, ticket.priority.getValue());
+ toDocField(doc, Lucene.severity, ticket.severity.getValue());
List<String> attachments = new ArrayList<String>();
for (Attachment attachment : ticket.getAttachments()) {
result.participants = unpackStrings(doc, Lucene.participants);
result.watchedby = unpackStrings(doc, Lucene.watchedby);
result.mentions = unpackStrings(doc, Lucene.mentions);
+ result.priority = TicketModel.Priority.fromObject(unpackInt(doc, Lucene.priority), TicketModel.Priority.defaultPriority);
+ result.severity = TicketModel.Severity.fromObject(unpackInt(doc, Lucene.severity), TicketModel.Severity.defaultSeverity);
if (!StringUtils.isEmpty(doc.get(Lucene.patchset.name()))) {
// unpack most recent patchset
gb.permission = Permission
gb.sshKeyPermissionDescription = Specify the access permission for the SSH key
gb.transportPreference = Transport Preference
-gb.transportPreferenceDescription = Set the transport that you prefer to use for cloning
\ No newline at end of file
+gb.transportPreferenceDescription = Set the transport that you prefer to use for cloning
+gb.priority = priority
+gb.severity = severity
+gb.sortHighestPriority = highest priority
+gb.sortLowestPriority = lowest priority
+gb.sortHighestSeverity = highest severity
+gb.sortLowestSeverity = lowest severity
import org.apache.wicket.markup.html.basic.Label;
import com.gitblit.models.TicketModel;
+import com.gitblit.models.TicketModel.Priority;
+import com.gitblit.models.TicketModel.Severity;
import com.gitblit.models.TicketModel.Status;
import com.gitblit.models.TicketModel.Type;
import com.gitblit.utils.StringUtils;
public static final String [] openStatii = new String [] { Status.New.name().toLowerCase(), Status.Open.name().toLowerCase() };
public static final String [] closedStatii = new String [] { "!" + Status.New.name().toLowerCase(), "!" + Status.Open.name().toLowerCase() };
-
+
public static Label getStateIcon(String wicketId, TicketModel ticket) {
return getStateIcon(wicketId, ticket.type, ticket.status);
}
}
switch (type) {
case Proposal:
- WicketUtils.setCssClass(label, "fa fa-code-fork");
+ WicketUtils.setCssClass(label, "fa fa-code-fork fa-fw");
break;
case Bug:
- WicketUtils.setCssClass(label, "fa fa-bug");
+ WicketUtils.setCssClass(label, "fa fa-bug fa-fw");
break;
case Enhancement:
- WicketUtils.setCssClass(label, "fa fa-magic");
+ WicketUtils.setCssClass(label, "fa fa-magic fa-fw");
break;
case Question:
- WicketUtils.setCssClass(label, "fa fa-question");
+ WicketUtils.setCssClass(label, "fa fa-question fa-fw");
break;
case Maintenance:
- WicketUtils.setCssClass(label, "fa fa-cogs");
+ WicketUtils.setCssClass(label, "fa fa-cogs fa-fw");
break;
default:
// standard ticket
- WicketUtils.setCssClass(label, "fa fa-ticket");
+ WicketUtils.setCssClass(label, "fa fa-ticket fa-fw");
}
WicketUtils.setHtmlTooltip(label, getTypeState(type, state));
+
+ return label;
+ }
+
+ public static Label getPriorityIcon(String wicketId, Priority priority) {
+ Label label = new Label(wicketId);
+ if (priority == null) {
+ priority = Priority.defaultPriority;
+ }
+ switch (priority) {
+ case Urgent:
+ WicketUtils.setCssClass(label, "fa fa-step-forward fa-rotate-270");
+ break;
+ case High:
+ WicketUtils.setCssClass(label, "fa fa-caret-up fa-lg");
+ break;
+ case Low:
+ WicketUtils.setCssClass(label, "fa fa-caret-down fa-lg");
+ break;
+ default:
+ }
+ WicketUtils.setHtmlTooltip(label, priority.toString());
+
return label;
}
+
+ public static String getPriorityClass(Priority priority) {
+ return String.format("priority-%s", priority);
+ }
+ public static String getSeverityClass(Severity severity) {
+ return String.format("severity-%s", severity);
+ }
+
public static String getTypeState(Type type, Status state) {
return state.toString() + " " + type.toString();
}
import org.apache.wicket.Component;\r
import org.apache.wicket.PageParameters;\r
import org.apache.wicket.Request;\r
+import org.apache.wicket.behavior.AttributeAppender;\r
import org.apache.wicket.behavior.HeaderContributor;\r
import org.apache.wicket.behavior.SimpleAttributeModifier;\r
import org.apache.wicket.markup.html.IHeaderContributor;\r
import org.apache.wicket.markup.html.IHeaderResponse;\r
import org.apache.wicket.markup.html.basic.Label;\r
import org.apache.wicket.markup.html.image.ContextImage;\r
+import org.apache.wicket.model.Model;\r
import org.apache.wicket.protocol.http.WebRequest;\r
import org.apache.wicket.resource.ContextRelativeResource;\r
import org.eclipse.jgit.diff.DiffEntry.ChangeType;\r
container.add(new SimpleAttributeModifier("class", value));\r
}\r
\r
+ public static void addCssClass(Component container, String value) {\r
+ container.add(new AttributeAppender("class", new Model<String>(value), " "));\r
+ }\r
+ \r
public static void setCssStyle(Component container, String value) {\r
container.add(new SimpleAttributeModifier("style", value));\r
}\r
<tr wicket:id="status"></tr>\r
<tr wicket:id="responsible"></tr>\r
<tr wicket:id="milestone"></tr>\r
+ <tr><th><wicket:message key="gb.priority"></wicket:message></th><td class="edit"><select class="input-large" wicket:id="priority"></select></td></tr>\r
+ <tr><th><wicket:message key="gb.severity"></wicket:message></th><td class="edit"><select class="input-large" wicket:id="severity"></select></td></tr>\r
<tr wicket:id="mergeto"></tr>\r
</table>\r
</div>\r
private IModel<TicketMilestone> milestoneModel;\r
\r
private Label descriptionPreview;\r
+ \r
+ private IModel<TicketModel.Priority> priorityModel;\r
+ \r
+ private IModel<TicketModel.Severity> severityModel;\r
\r
public EditTicketPage(PageParameters params) {\r
super(params);\r
milestoneModel = Model.of();\r
mergeToModel = Model.of(ticket.mergeTo == null ? getRepositoryModel().mergeTo : ticket.mergeTo);\r
statusModel = Model.of(ticket.status);\r
+ priorityModel = Model.of(ticket.priority);\r
+ severityModel = Model.of(ticket.severity);\r
\r
setStatelessHint(false);\r
setOutputMarkupId(true);\r
milestone.add(new DropDownChoice<TicketMilestone>("milestone", milestoneModel, milestones));\r
form.add(milestone.setVisible(!milestones.isEmpty()));\r
\r
+ // priority\r
+ List<TicketModel.Priority> priorityChoices = Arrays.asList(TicketModel.Priority.choices());\r
+ form.add(new DropDownChoice<TicketModel.Priority>("priority", priorityModel, priorityChoices));\r
+ \r
+ // severity\r
+ List<TicketModel.Severity> severityChoices = Arrays.asList(TicketModel.Severity.choices());\r
+ form.add(new DropDownChoice<TicketModel.Severity>("severity", severityModel, severityChoices));\r
+ \r
// mergeTo (integration branch)\r
List<String> branches = new ArrayList<String>();\r
for (String branch : getRepositoryModel().getLocalBranches()) {\r
change.setField(Field.milestone, milestone.name);\r
}\r
}\r
+ \r
+ TicketModel.Priority priority = priorityModel.getObject();\r
+ if (!ticket.priority.equals(priority))\r
+ {\r
+ change.setField(Field.priority, priority);\r
+ }\r
\r
+ TicketModel.Severity severity = severityModel.getObject();\r
+ if (!ticket.severity.equals(severity))\r
+ {\r
+ change.setField(Field.severity, severity);\r
+ }\r
+ \r
String mergeTo = mergeToModel.getObject();\r
if ((StringUtils.isEmpty(ticket.mergeTo) && !StringUtils.isEmpty(mergeTo))\r
|| (!StringUtils.isEmpty(mergeTo) && !mergeTo.equals(ticket.mergeTo))) {\r
sortChoices.add(new TicketSort(getString("gb.sortLeastPatchsetRevisions"), Lucene.patchsets.name(), false));
sortChoices.add(new TicketSort(getString("gb.sortMostVotes"), Lucene.votes.name(), true));
sortChoices.add(new TicketSort(getString("gb.sortLeastVotes"), Lucene.votes.name(), false));
+ sortChoices.add(new TicketSort(getString("gb.sortHighestPriority"), Lucene.priority.name(), true));
+ sortChoices.add(new TicketSort(getString("gb.sortLowestPriority"), Lucene.priority.name(), false));
+ sortChoices.add(new TicketSort(getString("gb.sortHighestSeverity"), Lucene.severity.name(), true));
+ sortChoices.add(new TicketSort(getString("gb.sortLowestSeverity"), Lucene.severity.name(), false));
TicketSort currentSort = sortChoices.get(0);
for (TicketSort ts : sortChoices) {
<tr><th><wicket:message key="gb.type"></wicket:message><span style="color:red;">*</span></th><td class="edit"><select class="input-large" wicket:id="type"></select></td></tr>\r
<tr wicket:id="responsible"></tr>\r
<tr wicket:id="milestone"></tr>\r
+ <tr><th><wicket:message key="gb.priority"></wicket:message></th><td class="edit"><select class="input-large" wicket:id="priority"></select></td></tr>\r
+ <tr><th><wicket:message key="gb.severity"></wicket:message></th><td class="edit"><select class="input-large" wicket:id="severity"></select></td></tr>\r
<tr wicket:id="mergeto"></tr>\r
</table>\r
</div>\r
private IModel<TicketMilestone> milestoneModel;\r
\r
private Label descriptionPreview;\r
+ \r
+ private IModel<TicketModel.Priority> priorityModel;\r
+ \r
+ private IModel<TicketModel.Severity> severityModel;\r
\r
public NewTicketPage(PageParameters params) {\r
super(params);\r
mergeToModel = Model.of(Repository.shortenRefName(getRepositoryModel().mergeTo));\r
responsibleModel = Model.of();\r
milestoneModel = Model.of();\r
+ severityModel = Model.of(TicketModel.Severity.defaultSeverity);\r
+ priorityModel = Model.of(TicketModel.Priority.defaultPriority);\r
\r
setStatelessHint(false);\r
setOutputMarkupId(true);\r
milestone.add(new DropDownChoice<TicketMilestone>("milestone", milestoneModel, milestones));\r
form.add(milestone.setVisible(!milestones.isEmpty()));\r
\r
+ // priority\r
+ form.add(new DropDownChoice<TicketModel.Priority>("priority", priorityModel, Arrays.asList(TicketModel.Priority.choices())));\r
+ \r
+ //severity\r
+ form.add(new DropDownChoice<TicketModel.Severity>("severity", severityModel, Arrays.asList(TicketModel.Severity.choices())));\r
+ \r
// integration branch\r
List<String> branches = new ArrayList<String>();\r
for (String branch : getRepositoryModel().getLocalBranches()) {\r
if (milestone != null) {\r
change.setField(Field.milestone, milestone.name);\r
}\r
+ \r
+ // severity\r
+ TicketModel.Severity severity = TicketModel.Severity.defaultSeverity;\r
+ if (severityModel.getObject() != null) {\r
+ severity = severityModel.getObject();\r
+ }\r
+ change.setField(Field.severity, severity);\r
+ \r
+ // priority\r
+ TicketModel.Priority priority = TicketModel.Priority.defaultPriority;\r
+ if (priorityModel.getObject() != null) {\r
+ priority = priorityModel.getObject();\r
+ }\r
+ change.setField(Field.priority, priority);\r
\r
// integration branch\r
String mergeTo = mergeToModel.getObject();\r
<div style="border: 1px solid #ccc;padding: 10px;margin: 5px 0px;">\r
<table class="summary" style="width: 100%">\r
<tr><th><wicket:message key="gb.type"></wicket:message></th><td><span wicket:id="ticketType">[type]</span></td></tr>\r
+ <tr><th><wicket:message key="gb.priority"></wicket:message></th><td><span wicket:id="priority">[priority]</span></td></tr>\r
+ <tr><th><wicket:message key="gb.severity"></wicket:message></th><td><span wicket:id="severity">[severity]</span></td></tr>\r
<tr><th><wicket:message key="gb.topic"></wicket:message></th><td><span wicket:id="ticketTopic">[topic]</span></td></tr>\r
<tr><th><wicket:message key="gb.responsible"></wicket:message></th><td><span wicket:id="responsible">[responsible]</span></td></tr>\r
<tr><th><wicket:message key="gb.milestone"></wicket:message></th><td><span wicket:id="milestone">[milestone]</span></td></tr>\r
* TICKET METADATA\r
*/\r
add(new Label("ticketType", ticket.type.toString()));\r
+ \r
+ add(new Label("priority", ticket.priority.toString()));\r
+ add(new Label("severity", ticket.severity.toString()));\r
+ \r
if (StringUtils.isEmpty(ticket.topic)) {\r
add(new Label("ticketTopic").setVisible(false));\r
} else {\r
String safeTopic = app().xssFilter().relaxed(topic);\r
add(new Label("ticketTopic", safeTopic).setEscapeModelStrings(false));\r
}\r
+ \r
+ \r
\r
\r
/*\r
sortChoices.add(new TicketSort(getString("gb.sortLeastPatchsetRevisions"), Lucene.patchsets.name(), false));\r
sortChoices.add(new TicketSort(getString("gb.sortMostVotes"), Lucene.votes.name(), true));\r
sortChoices.add(new TicketSort(getString("gb.sortLeastVotes"), Lucene.votes.name(), false));\r
-\r
+ sortChoices.add(new TicketSort(getString("gb.sortHighestPriority"), Lucene.priority.name(), true));\r
+ sortChoices.add(new TicketSort(getString("gb.sortLowestPriority"), Lucene.priority.name(), false));\r
+ sortChoices.add(new TicketSort(getString("gb.sortHighestSeverity"), Lucene.severity.name(), true));\r
+ sortChoices.add(new TicketSort(getString("gb.sortLowestSeverity"), Lucene.severity.name(), false));\r
+ \r
TicketSort currentSort = sortChoices.get(0);\r
for (TicketSort ts : sortChoices) {\r
if (ts.sortBy.equals(sortBy) && desc == ts.desc) {\r
<td class="hidden-phone ticket-list-state">\r
<i wicket:message="title:gb.watching" style="color:#888;" class="fa fa-eye" wicket:id="watching"></i>\r
</td>\r
+ <td class="ticket-list-priority">\r
+ <div wicket:id="priority"></div>\r
+ </td>\r
<td class="ticket-list-state">\r
<div wicket:id="status"></div>\r
</td>\r
public class TicketListPanel extends BasePanel {
private static final long serialVersionUID = 1L;
-
+
public TicketListPanel(String wicketId, List<QueryResult> list, final boolean showSwatch, final boolean showRepository) {
super(wicketId);
item.add(new Label("ticketsLink").setVisible(false));
}
- item.add(TicketsUI.getStateIcon("state", ticket.type, ticket.status));
+ Label icon = TicketsUI.getStateIcon("state", ticket.type, ticket.status);
+ WicketUtils.addCssClass(icon, TicketsUI.getSeverityClass(ticket.severity));
+ item.add(icon);
+
item.add(new Label("id", "" + ticket.number));
UserModel creator = app().users().getUserModel(ticket.createdBy);
if (creator != null) {
// watching indicator
item.add(new Label("watching").setVisible(ticket.isWatching(GitBlitWebSession.get().getUsername())));
+ // priority indicator
+ Label priorityIcon = TicketsUI.getPriorityIcon("priority", ticket.priority);
+ WicketUtils.addCssClass(priorityIcon, TicketsUI.getPriorityClass(ticket.priority));
+ item.add(priorityIcon.setVisible(true));
+
// status indicator
String css = TicketsUI.getLozengeClass(ticket.status, true);
Label l = new Label("status", ticket.status.toString());
td.ticket-list-state {
vertical-align: middle;
+}\r
+\r
+td.ticket-list-priority {\r
+ vertical-align: middle;\r
}
.ticket-list-details {
background-color: #fff;
border-color: #ece7e2;
color: #815b3a;
-}
\ No newline at end of file
+}\r
+.severity-catastrophic {\r
+ color:#CC79A7;\r
+}\r
+.severity-catastrophic:after {\r
+ font-family: Helvetica,arial,freesans,clean,sans-serif ;\r
+ content: "Ca";\r
+ font-weight:900;\r
+ font-size:.6em; \r
+ font-variant:small-caps;\r
+ display:flex;\r
+}\r
+.severity-critical {\r
+ color:#D55E00;\r
+}\r
+.severity-critical:after {\r
+ font-family: Helvetica,arial,freesans,clean,sans-serif ;\r
+ content: "c";\r
+ font-weight:900;\r
+ font-size:.6em; \r
+ font-variant:small-caps;\r
+ display:flex;\r
+}\r
+.severity-serious {\r
+ color:#E69F00;\r
+}\r
+.severity-serious:after {\r
+ font-family: Helvetica,arial,freesans,clean,sans-serif ;\r
+ content: "s";\r
+ font-weight:900;\r
+ font-size:.6em; \r
+ font-variant:small-caps;\r
+ display:flex;\r
+}\r
+.severity-minor {\r
+ color:#0072B2;\r
+}\r
+.severity-minor:after {\r
+ font-family: Helvetica,arial,freesans,clean,sans-serif ;\r
+ content: "m";\r
+ font-weight:900;\r
+ font-size:.6em; \r
+ font-variant:small-caps;\r
+ display:flex;\r
+}\r
+.severity-negligible {\r
+ color:#009E73;\r
+}\r
+.severity-negligible:after {\r
+ font-family: Helvetica,arial,freesans,clean,sans-serif ;\r
+ content: "n";\r
+ font-weight:900;\r
+ font-size:.6em; \r
+ font-variant:small-caps;\r
+ display:flex;\r
+}\r
+.severity-unrated {\r
+}\r
+.priority-urgent {\r
+ color:#CC79A7;\r
+}\r
+.priority-high {\r
+ color:#D55E00;\r
+}\r
+.priority-normal {\r
+}\r
+.priority-low {\r
+ color:#0072B2;\r
+}\r
FanoutServiceTest.class, Issue0259Test.class, Issue0271Test.class, HtpasswdAuthenticationTest.class,\r
ModelUtilsTest.class, JnaUtilsTest.class, LdapSyncServiceTest.class, FileTicketServiceTest.class,
BranchTicketServiceTest.class, RedisTicketServiceTest.class, AuthenticationManagerTest.class,\r
- SshKeysDispatcherTest.class })
+ SshKeysDispatcherTest.class, UITicketTest.class })
public class GitBlitSuite {\r
\r
public static final File BASEFOLDER = new File("data");\r
assertTrue("failed to delete label " + label.name, service.deleteLabel(getRepository(), label.name, "lucifer"));\r
}\r
}\r
-\r
-\r
-\r
+ \r
+ @Test\r
+ public void testPriorityAndSeverity() throws Exception {\r
+ // C1: create and insert a ticket\r
+ Change c1 = newChange("testPriorityAndSeverity() " + Long.toHexString(System.currentTimeMillis()));\r
+ TicketModel ticket = service.createTicket(getRepository(), c1);\r
+ assertTrue(ticket.number > 0);\r
+ assertEquals(TicketModel.Priority.Normal, ticket.priority);\r
+ assertEquals(TicketModel.Severity.Unrated, ticket.severity);\r
+ \r
+ TicketModel constructed = service.getTicket(getRepository(), ticket.number);\r
+ compare(ticket, constructed);\r
+ \r
+ // C2: Change Priority max\r
+ Change c2 = new Change("C2");\r
+ c2.setField(Field.priority, TicketModel.Priority.Urgent);\r
+ constructed = service.updateTicket(getRepository(), ticket.number, c2);\r
+ assertNotNull(constructed);\r
+ assertEquals(2, constructed.changes.size());\r
+ assertEquals(TicketModel.Priority.Urgent, constructed.priority);\r
+ assertEquals(TicketModel.Severity.Unrated, constructed.severity);\r
+ \r
+ // C3: Change Severity max\r
+ Change c3 = new Change("C3");\r
+ c3.setField(Field.severity, TicketModel.Severity.Catastrophic);\r
+ constructed = service.updateTicket(getRepository(), ticket.number, c3);\r
+ assertNotNull(constructed);\r
+ assertEquals(3, constructed.changes.size());\r
+ assertEquals(TicketModel.Priority.Urgent, constructed.priority);\r
+ assertEquals(TicketModel.Severity.Catastrophic, constructed.severity);\r
+ \r
+ // C4: Change Priority min\r
+ Change c4 = new Change("C3");\r
+ c4.setField(Field.priority, TicketModel.Priority.Low);\r
+ constructed = service.updateTicket(getRepository(), ticket.number, c4);\r
+ assertNotNull(constructed);\r
+ assertEquals(4, constructed.changes.size());\r
+ assertEquals(TicketModel.Priority.Low, constructed.priority);\r
+ assertEquals(TicketModel.Severity.Catastrophic, constructed.severity);\r
+ }\r
+ \r
private Change newChange(String summary) {\r
Change change = new Change("C1");\r
change.setField(Field.title, summary);\r
--- /dev/null
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.tests;
+
+import java.io.File;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.io.FileUtils;
+import org.bouncycastle.util.Arrays;
+import org.eclipse.jgit.lib.Repository;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.gitblit.IStoredSettings;
+import com.gitblit.Keys;
+import com.gitblit.manager.INotificationManager;
+import com.gitblit.manager.IPluginManager;
+import com.gitblit.manager.IRepositoryManager;
+import com.gitblit.manager.IRuntimeManager;
+import com.gitblit.manager.IUserManager;
+import com.gitblit.manager.NotificationManager;
+import com.gitblit.manager.PluginManager;
+import com.gitblit.manager.RepositoryManager;
+import com.gitblit.manager.RuntimeManager;
+import com.gitblit.manager.UserManager;
+import com.gitblit.models.Mailing;
+import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.TicketModel;
+import com.gitblit.models.TicketModel.Attachment;
+import com.gitblit.models.TicketModel.Change;
+import com.gitblit.models.TicketModel.Field;
+import com.gitblit.models.TicketModel.Patchset;
+import com.gitblit.models.TicketModel.Priority;
+import com.gitblit.models.TicketModel.Severity;
+import com.gitblit.models.TicketModel.Status;
+import com.gitblit.models.TicketModel.Type;
+import com.gitblit.tests.mock.MemorySettings;
+import com.gitblit.tickets.ITicketService;
+import com.gitblit.tickets.ITicketService.TicketFilter;
+import com.gitblit.tickets.QueryResult;
+import com.gitblit.tickets.TicketIndexer.Lucene;
+import com.gitblit.tickets.BranchTicketService;
+import com.gitblit.tickets.TicketLabel;
+import com.gitblit.tickets.TicketMilestone;
+import com.gitblit.tickets.TicketNotifier;
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.utils.XssFilter;
+import com.gitblit.utils.XssFilter.AllowXssFilter;
+
+/**
+ * Generates the range of tickets to ease testing of the look and feel of tickets
+ */
+public class UITicketTest extends GitblitUnitTest {
+
+ private ITicketService service;
+ final String repoName = "UITicketTest.git";
+ final RepositoryModel repo = new RepositoryModel(repoName, null, null, null);
+
+ protected ITicketService getService(boolean deleteAll) throws Exception {
+
+ IStoredSettings settings = getSettings(deleteAll);
+ XssFilter xssFilter = new AllowXssFilter();
+ IRuntimeManager runtimeManager = new RuntimeManager(settings, xssFilter).start();
+ IPluginManager pluginManager = new PluginManager(runtimeManager).start();
+ INotificationManager notificationManager = new NotificationManager(settings).start();
+ IUserManager userManager = new UserManager(runtimeManager, pluginManager).start();
+ IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, pluginManager, userManager).start();
+
+ BranchTicketService service = new BranchTicketService(
+ runtimeManager,
+ pluginManager,
+ notificationManager,
+ userManager,
+ repositoryManager).start();
+
+ if (deleteAll) {
+ service.deleteAll(repo);
+ }
+ return service;
+ }
+
+ protected IStoredSettings getSettings(boolean deleteAll) throws Exception {
+ File dir = new File(GitBlitSuite.REPOSITORIES, repoName);
+ if (deleteAll) {
+ FileUtils.deleteDirectory(dir);
+ JGitUtils.createRepository(GitBlitSuite.REPOSITORIES, repoName).close();
+ }
+
+ File luceneDir = new File(dir, "tickets/lucene");
+ luceneDir.mkdirs();
+
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put(Keys.git.repositoriesFolder, GitBlitSuite.REPOSITORIES.getAbsolutePath());
+ map.put(Keys.tickets.indexFolder, luceneDir.getAbsolutePath());
+
+ IStoredSettings settings = new MemorySettings(map);
+ return settings;
+ }
+
+ @Before
+ public void setup() throws Exception {
+ service = getService(true);
+ }
+
+ @After
+ public void cleanup() {
+ service.stop();
+ }
+
+ @Test
+ public void UITicketOptions() throws Exception {
+
+ for (TicketModel.Type t : TicketModel.Type.values())
+ {
+ for (TicketModel.Priority p : TicketModel.Priority.values())
+ {
+ for (TicketModel.Severity s : TicketModel.Severity.values())
+ {
+ assertNotNull(service.createTicket(repo, newChange(t, p, s)));
+ }
+ }
+ }
+ }
+
+ private Change newChange(Type type, Priority priority, Severity severity) {
+ Change change = new Change("JUnit");
+ change.setField(Field.title, String.format("Type: %s | Priority: %s | Severity: %s", type, priority, severity));
+ change.setField(Field.type, type);
+ change.setField(Field.severity, severity);
+ change.setField(Field.priority, priority);
+ return change;
+ }
+
+}
\ No newline at end of file