Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tickets updated with priority and severity #220

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
120 changes: 119 additions & 1 deletion src/main/java/com/gitblit/models/TicketModel.java
Expand Up @@ -91,6 +91,10 @@ public class TicketModel implements Serializable, Comparable<TicketModel> {

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
Expand Down Expand Up @@ -141,6 +145,8 @@ public TicketModel() {
changes = new ArrayList<Change>();
status = Status.New;
type = Type.defaultType;
priority = Priority.defaultPriority;
severity = Severity.defaultSeverity;
}

public boolean isOpen() {
Expand Down Expand Up @@ -517,6 +523,12 @@ public void applyChange(Change change) {
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;
Expand Down Expand Up @@ -1183,7 +1195,7 @@ public static Score fromScore(int score) {

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 {
Expand Down Expand Up @@ -1310,4 +1322,110 @@ public static PatchsetType fromObject(Object o) {
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;
}
}
}
4 changes: 4 additions & 0 deletions src/main/java/com/gitblit/tickets/QueryResult.java
Expand Up @@ -24,6 +24,8 @@
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;

/**
Expand Down Expand Up @@ -62,6 +64,8 @@ public class QueryResult implements Serializable {
public int commentsCount;
public int votesCount;
public int approvalsCount;
public Priority priority;
public Severity severity;

public int docId;
public int totalResults;
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/com/gitblit/tickets/TicketIndexer.java
Expand Up @@ -103,7 +103,10 @@ public static enum Lucene {
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;

Expand Down Expand Up @@ -519,6 +522,8 @@ private Document ticketToDoc(TicketModel ticket) {
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()) {
Expand Down Expand Up @@ -600,6 +605,8 @@ private QueryResult docToQueryResult(Document doc) throws ParseException {
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
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
Expand Up @@ -742,4 +742,10 @@ gb.sshKeyCommentDescription = Enter an optional comment. If blank, the comment w
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
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
47 changes: 40 additions & 7 deletions src/main/java/com/gitblit/wicket/TicketsUI.java
Expand Up @@ -21,6 +21,8 @@
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;
Expand All @@ -36,7 +38,7 @@ public class TicketsUI {
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);
}
Expand All @@ -48,28 +50,59 @@ public static Label getStateIcon(String wicketId, Type type, Status state) {
}
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();
}
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/com/gitblit/wicket/WicketUtils.java
Expand Up @@ -29,12 +29,14 @@
import org.apache.wicket.Component;
import org.apache.wicket.PageParameters;
import org.apache.wicket.Request;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.behavior.HeaderContributor;
import org.apache.wicket.behavior.SimpleAttributeModifier;
import org.apache.wicket.markup.html.IHeaderContributor;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.image.ContextImage;
import org.apache.wicket.model.Model;
import org.apache.wicket.protocol.http.WebRequest;
import org.apache.wicket.resource.ContextRelativeResource;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
Expand All @@ -56,6 +58,10 @@ public static void setCssClass(Component container, String value) {
container.add(new SimpleAttributeModifier("class", value));
}

public static void addCssClass(Component container, String value) {
container.add(new AttributeAppender("class", new Model<String>(value), " "));
}

public static void setCssStyle(Component container, String value) {
container.add(new SimpleAttributeModifier("style", value));
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/gitblit/wicket/pages/EditTicketPage.html
Expand Up @@ -41,6 +41,8 @@
<tr wicket:id="status"></tr>
<tr wicket:id="responsible"></tr>
<tr wicket:id="milestone"></tr>
<tr><th><wicket:message key="gb.priority"></wicket:message></th><td class="edit"><select class="input-large" wicket:id="priority"></select></td></tr>
<tr><th><wicket:message key="gb.severity"></wicket:message></th><td class="edit"><select class="input-large" wicket:id="severity"></select></td></tr>
<tr wicket:id="mergeto"></tr>
</table>
</div>
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/com/gitblit/wicket/pages/EditTicketPage.java
Expand Up @@ -83,6 +83,10 @@ public class EditTicketPage extends RepositoryPage {
private IModel<TicketMilestone> milestoneModel;

private Label descriptionPreview;

private IModel<TicketModel.Priority> priorityModel;

private IModel<TicketModel.Severity> severityModel;

public EditTicketPage(PageParameters params) {
super(params);
Expand Down Expand Up @@ -117,6 +121,8 @@ public EditTicketPage(PageParameters params) {
milestoneModel = Model.of();
mergeToModel = Model.of(ticket.mergeTo == null ? getRepositoryModel().mergeTo : ticket.mergeTo);
statusModel = Model.of(ticket.status);
priorityModel = Model.of(ticket.priority);
severityModel = Model.of(ticket.severity);

setStatelessHint(false);
setOutputMarkupId(true);
Expand Down Expand Up @@ -219,6 +225,14 @@ public EditTicketPage(PageParameters params) {
milestone.add(new DropDownChoice<TicketMilestone>("milestone", milestoneModel, milestones));
form.add(milestone.setVisible(!milestones.isEmpty()));

// priority
List<TicketModel.Priority> priorityChoices = Arrays.asList(TicketModel.Priority.choices());
form.add(new DropDownChoice<TicketModel.Priority>("priority", priorityModel, priorityChoices));

// severity
List<TicketModel.Severity> severityChoices = Arrays.asList(TicketModel.Severity.choices());
form.add(new DropDownChoice<TicketModel.Severity>("severity", severityModel, severityChoices));

// mergeTo (integration branch)
List<String> branches = new ArrayList<String>();
for (String branch : getRepositoryModel().getLocalBranches()) {
Expand Down Expand Up @@ -315,7 +329,19 @@ protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
change.setField(Field.milestone, milestone.name);
}
}

TicketModel.Priority priority = priorityModel.getObject();
if (!ticket.priority.equals(priority))
{
change.setField(Field.priority, priority);
}

TicketModel.Severity severity = severityModel.getObject();
if (!ticket.severity.equals(severity))
{
change.setField(Field.severity, severity);
}

String mergeTo = mergeToModel.getObject();
if ((StringUtils.isEmpty(ticket.mergeTo) && !StringUtils.isEmpty(mergeTo))
|| (!StringUtils.isEmpty(mergeTo) && !mergeTo.equals(ticket.mergeTo))) {
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java
Expand Up @@ -230,6 +230,10 @@ public void populateItem(final Item<Status> item) {
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) {
Expand Down