From: Zsombor Gegesy Date: Sun, 7 Dec 2014 16:00:58 +0000 (+0100) Subject: Add 'dependency' to the ticket model and to the ui, with editing possibility with... X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=a669af92c30712cb74a659216293f89a58f899df;p=gitblit.git Add 'dependency' to the ticket model and to the ui, with editing possibility with a separate relation editor panel --- diff --git a/src/main/java/com/gitblit/models/TicketModel.java b/src/main/java/com/gitblit/models/TicketModel.java index fd0b09eb..f8813f01 100644 --- a/src/main/java/com/gitblit/models/TicketModel.java +++ b/src/main/java/com/gitblit/models/TicketModel.java @@ -233,6 +233,10 @@ public class TicketModel implements Serializable, Comparable { public List getLabels() { return getList(Field.labels); } + + public List getDependencies() { + return getList(Field.dependency); + } public boolean isResponsible(String username) { return username.equals(responsible); @@ -746,6 +750,26 @@ public class TicketModel implements Serializable, Comparable { fields.put(field, value.toString()); } } + + public void setDeltaField(Field field, List base, List newValues) { + List result = new ArrayList<>(); + for (String oldValue : base) { + if (!newValues.contains(oldValue)) { + result.add("-" + oldValue); + } + } + for (String newValue : newValues) { + if (!base.contains(newValue)) { + result.add("+" + newValue); + } + } + if (result.isEmpty()) { + // no change + remove(field); + } else { + setField(field, join(result, ",")); + } + } public void remove(Field field) { if (fields != null) { @@ -1195,7 +1219,7 @@ public class TicketModel implements Serializable, Comparable { public static enum Field { title, body, responsible, type, status, milestone, mergeSha, mergeTo, - topic, labels, watchers, reviewers, voters, mentions, priority, severity; + topic, labels, watchers, reviewers, voters, mentions, priority, severity, dependency; } public static enum Type { diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 648ac2a5..10bfe009 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -513,6 +513,9 @@ gb.docsWelcome1 = You can use docs to document your repository. gb.docsWelcome2 = Commit a README.md or a HOME.md file to get started. gb.createReadme = create a README gb.responsible = responsible +gb.dependency = dependency +gb.dependencies = dependencies +gb.remove = remove gb.createdThisTicket = created this ticket gb.proposedThisChange = proposed this change gb.uploadedPatchsetN = uploaded patchset {0} @@ -759,4 +762,4 @@ gb.diffCopiedFile = File was copied from {0} gb.diffTruncated = Diff truncated after the above file gb.opacityAdjust = Adjust opacity gb.blinkComparator = Blink comparator -gb.imgdiffSubtract = Subtract (black = identical) \ No newline at end of file +gb.imgdiffSubtract = Subtract (black = identical) diff --git a/src/main/java/com/gitblit/wicket/pages/EditTicketPage.html b/src/main/java/com/gitblit/wicket/pages/EditTicketPage.html index b12d0c77..764adc50 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditTicketPage.html +++ b/src/main/java/com/gitblit/wicket/pages/EditTicketPage.html @@ -43,6 +43,7 @@ + diff --git a/src/main/java/com/gitblit/wicket/pages/EditTicketPage.java b/src/main/java/com/gitblit/wicket/pages/EditTicketPage.java index 192b48ca..61e12878 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditTicketPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditTicketPage.java @@ -30,10 +30,13 @@ import org.apache.wicket.markup.html.form.Button; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.TextField; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.eclipse.jgit.lib.Repository; +import org.jsoup.helper.StringUtil; import com.gitblit.Constants; import com.gitblit.Constants.AccessPermission; @@ -51,7 +54,10 @@ import com.gitblit.tickets.TicketResponsible; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; +import com.gitblit.wicket.panels.LinkPanel; import com.gitblit.wicket.panels.MarkdownTextArea; +import com.gitblit.wicket.panels.SimpleAjaxLink; +import com.gitblit.wicket.panels.TicketRelationEditorPanel; import com.google.common.base.Optional; /** @@ -81,6 +87,8 @@ public class EditTicketPage extends RepositoryPage { private IModel responsibleModel; private IModel milestoneModel; + + private IModel> dependenciesModel; private Label descriptionPreview; @@ -123,6 +131,7 @@ public class EditTicketPage extends RepositoryPage { statusModel = Model.of(ticket.status); priorityModel = Model.of(ticket.priority); severityModel = Model.of(ticket.severity); + dependenciesModel = Model.ofList((List) editable(ticket.getDependencies())); setStatelessHint(false); setOutputMarkupId(true); @@ -141,6 +150,10 @@ public class EditTicketPage extends RepositoryPage { form.add(new TextField("title", titleModel)); form.add(new TextField("topic", topicModel)); + form.setOutputMarkupId(true); + + form.add(new TicketRelationEditorPanel("dependencies", dependenciesModel, getRepositoryModel())); + final IModel markdownPreviewModel = Model.of(ticket.body == null ? "" : ticket.body); descriptionPreview = new Label("descriptionPreview", markdownPreviewModel); descriptionPreview.setEscapeModelStrings(false); @@ -311,6 +324,10 @@ public class EditTicketPage extends RepositoryPage { change.setField(Field.topic, topic); } + List newDependencies = (List) dependenciesModel.getObject(); + + change.setDeltaField(Field.dependency, ticket.getDependencies(), newDependencies); + TicketResponsible responsible = responsibleModel == null ? null : responsibleModel.getObject(); if (responsible != null && !responsible.username.equals(ticket.responsible)) { // responsible change @@ -382,6 +399,11 @@ public class EditTicketPage extends RepositoryPage { form.add(cancel); } + private List editable(List list) { + // need to copy, if it's an Collection.emptyList + return new ArrayList(list); + } + @Override protected String getPageName() { return getString("gb.editTicket"); diff --git a/src/main/java/com/gitblit/wicket/pages/NewTicketPage.html b/src/main/java/com/gitblit/wicket/pages/NewTicketPage.html index 9b5af023..d0b7378d 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewTicketPage.html +++ b/src/main/java/com/gitblit/wicket/pages/NewTicketPage.html @@ -43,6 +43,7 @@ + diff --git a/src/main/java/com/gitblit/wicket/pages/NewTicketPage.java b/src/main/java/com/gitblit/wicket/pages/NewTicketPage.java index 0c52505c..3722be10 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewTicketPage.java +++ b/src/main/java/com/gitblit/wicket/pages/NewTicketPage.java @@ -51,6 +51,7 @@ import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.MarkdownTextArea; +import com.gitblit.wicket.panels.TicketRelationEditorPanel; /** * Page for creating a new ticket. @@ -80,6 +81,8 @@ public class NewTicketPage extends RepositoryPage { private IModel severityModel; + private IModel> dependenciesModel; + public NewTicketPage(PageParameters params) { super(params); @@ -101,6 +104,7 @@ public class NewTicketPage extends RepositoryPage { milestoneModel = Model.of(); severityModel = Model.of(TicketModel.Severity.defaultSeverity); priorityModel = Model.of(TicketModel.Priority.defaultPriority); + dependenciesModel = (IModel) Model.ofList(new ArrayList()); setStatelessHint(false); setOutputMarkupId(true); @@ -122,6 +126,8 @@ public class NewTicketPage extends RepositoryPage { descriptionEditor = new MarkdownTextArea("description", markdownPreviewModel, descriptionPreview); descriptionEditor.setRepository(repositoryName); form.add(descriptionEditor); + + form.add(new TicketRelationEditorPanel("dependencies", dependenciesModel, getRepositoryModel())); if (currentUser.canAdmin(null, getRepositoryModel())) { // responsible @@ -244,6 +250,8 @@ public class NewTicketPage extends RepositoryPage { if (!StringUtils.isEmpty(mergeTo)) { change.setField(Field.mergeTo, mergeTo); } + + change.setDeltaField(Field.dependency, Collections.emptyList(), dependenciesModel.getObject()); TicketModel ticket = app().tickets().createTicket(getRepositoryModel(), 0L, change); if (ticket != null) { diff --git a/src/main/java/com/gitblit/wicket/pages/TicketPage.html b/src/main/java/com/gitblit/wicket/pages/TicketPage.html index 5ae005eb..e3d143db 100644 --- a/src/main/java/com/gitblit/wicket/pages/TicketPage.html +++ b/src/main/java/com/gitblit/wicket/pages/TicketPage.html @@ -72,6 +72,7 @@ [topic] [responsible] [milestone] + [link] 1 vote 1 watch diff --git a/src/main/java/com/gitblit/wicket/pages/TicketPage.java b/src/main/java/com/gitblit/wicket/pages/TicketPage.java index 4890874a..74484b09 100644 --- a/src/main/java/com/gitblit/wicket/pages/TicketPage.java +++ b/src/main/java/com/gitblit/wicket/pages/TicketPage.java @@ -42,6 +42,8 @@ import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.image.ContextImage; import org.apache.wicket.markup.html.link.BookmarkablePageLink; import org.apache.wicket.markup.html.link.ExternalLink; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.markup.repeater.data.DataView; @@ -292,6 +294,18 @@ public class TicketPage extends RepositoryPage { } add(new Label("ticketDescription", desc).setEscapeModelStrings(false)); + /* + * DEPENDENCY + */ + List dependencies = ticket.getDependencies(); + add(new ListView("dependencies", dependencies) { + @Override + protected void populateItem(ListItem item) { + String ticketId= item.getModelObject(); + PageParameters tp = WicketUtils.newObjectParameter(ticket.repository, ticketId); + item.add(new LinkPanel("dependencyLink", "list subject", "#"+ticketId, TicketsPage.class, tp)); + } + }); /* * PARTICIPANTS (DISCUSSION TAB) diff --git a/src/main/java/com/gitblit/wicket/panels/TicketRelationEditorPanel.html b/src/main/java/com/gitblit/wicket/panels/TicketRelationEditorPanel.html new file mode 100644 index 00000000..79c381fb --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/TicketRelationEditorPanel.html @@ -0,0 +1,28 @@ + + + + + + + + + + + [ticket label] + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/TicketRelationEditorPanel.java b/src/main/java/com/gitblit/wicket/panels/TicketRelationEditorPanel.java new file mode 100644 index 00000000..59cc9096 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/TicketRelationEditorPanel.java @@ -0,0 +1,82 @@ +package com.gitblit.wicket.panels; + +import java.util.List; + +import org.apache.wicket.PageParameters; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.form.TextField; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.jsoup.helper.StringUtil; + +import com.gitblit.models.RepositoryModel; +import com.gitblit.wicket.WicketUtils; +import com.gitblit.wicket.pages.TicketsPage; + +public class TicketRelationEditorPanel extends BasePanel { + + private static final long serialVersionUID = 1L; + + private IModel> dependenciesModel; + private IModel addDependencyModel; + + + public TicketRelationEditorPanel(String wicketId, IModel> pdependenciesModel, final RepositoryModel repositoryModel) { + super(wicketId); + this.dependenciesModel = pdependenciesModel; + this.addDependencyModel = Model.of(); + + + add(new ListView("dependencyList", dependenciesModel) { + private static final long serialVersionUID = 1L; + + @Override + protected void populateItem(ListItem item) { + final String ticketId = item.getModelObject(); + + PageParameters tp = WicketUtils.newObjectParameter(repositoryModel.name, ticketId); + item.add(new LinkPanel("dependencyLink", "list subject", "#"+ticketId, TicketsPage.class, tp)); + + item.add(new AjaxButton("removeDependencyLink") { + private static final long serialVersionUID = 1L; + @Override + public void onSubmit(AjaxRequestTarget target, Form form) { + List list = dependenciesModel.getObject(); + list.remove(ticketId); + dependenciesModel.setObject(list); + target.addComponent(form); + } + }); + } + }); + add(new TextField("addDependencyText", addDependencyModel)); + add(new AjaxButton("addDependency") { + private static final long serialVersionUID = 1L; + @Override + protected void onSubmit(AjaxRequestTarget target, Form form) { + String ticketIdStr = addDependencyModel.getObject(); + if (!StringUtil.isBlank(ticketIdStr)) { + try { + long ticketId = Long.parseLong(ticketIdStr); + if (app().tickets().hasTicket(repositoryModel, ticketId)) { + List list = (List) dependenciesModel.getObject(); + list.add(String.valueOf(ticketId)); + addDependencyModel.setObject(""); + } + } catch (NumberFormatException e) { + // TODO : not allowed + + } + } + target.addComponent(form); + } + }); + + + } + +}