]> source.dussan.org Git - gitblit.git/commitdiff
Add 'dependency' to the ticket model and to the ui, with editing possibility with...
authorZsombor Gegesy <gzsombor@gmail.com>
Sun, 7 Dec 2014 16:00:58 +0000 (17:00 +0100)
committerZsombor Gegesy <gzsombor@gmail.com>
Mon, 8 Dec 2014 18:51:48 +0000 (19:51 +0100)
src/main/java/com/gitblit/models/TicketModel.java
src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
src/main/java/com/gitblit/wicket/pages/EditTicketPage.html
src/main/java/com/gitblit/wicket/pages/EditTicketPage.java
src/main/java/com/gitblit/wicket/pages/NewTicketPage.html
src/main/java/com/gitblit/wicket/pages/NewTicketPage.java
src/main/java/com/gitblit/wicket/pages/TicketPage.html
src/main/java/com/gitblit/wicket/pages/TicketPage.java
src/main/java/com/gitblit/wicket/panels/TicketRelationEditorPanel.html [new file with mode: 0644]
src/main/java/com/gitblit/wicket/panels/TicketRelationEditorPanel.java [new file with mode: 0644]

index fd0b09eb9323abd2022ed83e315a9ad77ad18d99..f8813f01ce60ad39b88d03e41b9cf2371a73a9bc 100644 (file)
@@ -233,6 +233,10 @@ public class TicketModel implements Serializable, Comparable<TicketModel> {
        public List<String> getLabels() {
                return getList(Field.labels);
        }
+       
+       public List<String> getDependencies() {
+               return getList(Field.dependency);
+       }
 
        public boolean isResponsible(String username) {
                return username.equals(responsible);
@@ -746,6 +750,26 @@ public class TicketModel implements Serializable, Comparable<TicketModel> {
                                fields.put(field, value.toString());
                        }
                }
+               
+               public void setDeltaField(Field field, List<String> base, List<String> newValues) {
+                       List<String> 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<TicketModel> {
 
        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 {
index 648ac2a54b51c210635bd0c465aac5cc22020f51..10bfe009534b755dbc358386452553e5f5cf2d0f 100644 (file)
@@ -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)
index b12d0c7734396643472dc4047f4e040a7648dc54..764adc50d59a5074e318aeb4a9076c26fbb2923e 100644 (file)
@@ -43,6 +43,7 @@
             <tr wicket:id="priority"></tr>\r
                        <tr wicket:id="responsible"></tr>\r
                        <tr wicket:id="milestone"></tr>\r
+                       <span wicket:id="dependencies"></span>\r
                        <tr wicket:id="mergeto"></tr>\r
                </table>\r
        </div>\r
index 192b48caac3faf7ea9b32445cf61eccb44a5515c..61e12878b1d4eb3905e115564be878e669f5df86 100644 (file)
@@ -30,10 +30,13 @@ import org.apache.wicket.markup.html.form.Button;
 import org.apache.wicket.markup.html.form.DropDownChoice;\r
 import org.apache.wicket.markup.html.form.Form;\r
 import org.apache.wicket.markup.html.form.TextField;\r
+import org.apache.wicket.markup.html.list.ListItem;\r
+import org.apache.wicket.markup.html.list.ListView;\r
 import org.apache.wicket.markup.html.panel.Fragment;\r
 import org.apache.wicket.model.IModel;\r
 import org.apache.wicket.model.Model;\r
 import org.eclipse.jgit.lib.Repository;\r
+import org.jsoup.helper.StringUtil;\r
 \r
 import com.gitblit.Constants;\r
 import com.gitblit.Constants.AccessPermission;\r
@@ -51,7 +54,10 @@ import com.gitblit.tickets.TicketResponsible;
 import com.gitblit.utils.StringUtils;\r
 import com.gitblit.wicket.GitBlitWebSession;\r
 import com.gitblit.wicket.WicketUtils;\r
+import com.gitblit.wicket.panels.LinkPanel;\r
 import com.gitblit.wicket.panels.MarkdownTextArea;\r
+import com.gitblit.wicket.panels.SimpleAjaxLink;\r
+import com.gitblit.wicket.panels.TicketRelationEditorPanel;\r
 import com.google.common.base.Optional;\r
 \r
 /**\r
@@ -81,6 +87,8 @@ public class EditTicketPage extends RepositoryPage {
        private IModel<TicketResponsible> responsibleModel;\r
 \r
        private IModel<TicketMilestone> milestoneModel;\r
+       \r
+       private IModel<List<String>> dependenciesModel;\r
 \r
        private Label descriptionPreview;\r
 \r
@@ -123,6 +131,7 @@ public class EditTicketPage extends RepositoryPage {
                statusModel = Model.of(ticket.status);\r
                priorityModel = Model.of(ticket.priority);\r
                severityModel = Model.of(ticket.severity);\r
+               dependenciesModel = Model.ofList((List) editable(ticket.getDependencies()));\r
 \r
                setStatelessHint(false);\r
                setOutputMarkupId(true);\r
@@ -141,6 +150,10 @@ public class EditTicketPage extends RepositoryPage {
                form.add(new TextField<String>("title", titleModel));\r
                form.add(new TextField<String>("topic", topicModel));\r
 \r
+               form.setOutputMarkupId(true);\r
+\r
+               form.add(new TicketRelationEditorPanel("dependencies", dependenciesModel, getRepositoryModel()));\r
+\r
                final IModel<String> markdownPreviewModel = Model.of(ticket.body == null ? "" : ticket.body);\r
                descriptionPreview = new Label("descriptionPreview", markdownPreviewModel);\r
                descriptionPreview.setEscapeModelStrings(false);\r
@@ -311,6 +324,10 @@ public class EditTicketPage extends RepositoryPage {
                                        change.setField(Field.topic, topic);\r
                                }\r
 \r
+                               List<String> newDependencies = (List<String>) dependenciesModel.getObject();\r
+                               \r
+                               change.setDeltaField(Field.dependency, ticket.getDependencies(), newDependencies);\r
+                               \r
                                TicketResponsible responsible = responsibleModel == null ? null : responsibleModel.getObject();\r
                                if (responsible != null && !responsible.username.equals(ticket.responsible)) {\r
                                        // responsible change\r
@@ -382,6 +399,11 @@ public class EditTicketPage extends RepositoryPage {
                form.add(cancel);\r
        }\r
 \r
+       private List<String> editable(List<String> list) {\r
+               // need to copy, if it's an Collection.emptyList \r
+               return new ArrayList<String>(list);\r
+       }\r
+\r
        @Override\r
        protected String getPageName() {\r
                return getString("gb.editTicket");\r
index 9b5af023843ef8e044ddb4a2adcb5171ed5b2096..d0b7378d923e9a02d76cdcb1b2f73dc14b54b27c 100644 (file)
@@ -43,6 +43,7 @@
             <tr wicket:id="priority"></tr>\r
                        <tr wicket:id="responsible"></tr>\r
                        <tr wicket:id="milestone"></tr>\r
+                       <span wicket:id="dependencies"></span>\r
                        <tr wicket:id="mergeto"></tr>\r
                </table>\r
        </div>\r
index 0c52505c6c9d1130c77e40bcdecaed032508d80d..3722be10342a5b0007d972a9596c556589d42933 100644 (file)
@@ -51,6 +51,7 @@ import com.gitblit.utils.StringUtils;
 import com.gitblit.wicket.GitBlitWebSession;\r
 import com.gitblit.wicket.WicketUtils;\r
 import com.gitblit.wicket.panels.MarkdownTextArea;\r
+import com.gitblit.wicket.panels.TicketRelationEditorPanel;\r
 \r
 /**\r
  * Page for creating a new ticket.\r
@@ -80,6 +81,8 @@ public class NewTicketPage extends RepositoryPage {
 \r
        private IModel<TicketModel.Severity> severityModel;\r
 \r
+       private IModel<List<String>> dependenciesModel;\r
+\r
        public NewTicketPage(PageParameters params) {\r
                super(params);\r
 \r
@@ -101,6 +104,7 @@ public class NewTicketPage extends RepositoryPage {
                milestoneModel = Model.of();\r
                severityModel = Model.of(TicketModel.Severity.defaultSeverity);\r
                priorityModel = Model.of(TicketModel.Priority.defaultPriority);\r
+               dependenciesModel = (IModel) Model.ofList(new ArrayList<String>());\r
 \r
                setStatelessHint(false);\r
                setOutputMarkupId(true);\r
@@ -122,6 +126,8 @@ public class NewTicketPage extends RepositoryPage {
                descriptionEditor = new MarkdownTextArea("description", markdownPreviewModel, descriptionPreview);\r
                descriptionEditor.setRepository(repositoryName);\r
                form.add(descriptionEditor);\r
+               \r
+               form.add(new TicketRelationEditorPanel("dependencies", dependenciesModel, getRepositoryModel()));\r
 \r
                if (currentUser.canAdmin(null, getRepositoryModel())) {\r
                        // responsible\r
@@ -244,6 +250,8 @@ public class NewTicketPage extends RepositoryPage {
                                if (!StringUtils.isEmpty(mergeTo)) {\r
                                        change.setField(Field.mergeTo, mergeTo);\r
                                }\r
+                               \r
+                               change.setDeltaField(Field.dependency, Collections.<String>emptyList(), dependenciesModel.getObject());\r
 \r
                                TicketModel ticket = app().tickets().createTicket(getRepositoryModel(), 0L, change);\r
                                if (ticket != null) {\r
index 5ae005ebbfec3d8ef707834a89da75d41f4f5298..e3d143dbe46a0920ca48c1492b5c7073a573152c 100644 (file)
@@ -72,6 +72,7 @@
                                                <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
+                                               <tr><th><wicket:message key="gb.dependencies"></wicket:message></th><td><span wicket:id="dependencies"><a wicket:id="dependencyLink">[link]</a></span></td></tr>\r
                                                <tr><th><wicket:message key="gb.votes"></wicket:message></th><td><span wicket:id="votes" class="badge">1</span> <a style="padding-left:5px" wicket:id="voteLink" href="#">vote</a></td></tr>\r
                                                <tr><th><wicket:message key="gb.watchers"></wicket:message></th><td><span wicket:id="watchers" class="badge">1</span> <a style="padding-left:5px" wicket:id="watchLink" href="#">watch</a></td></tr>\r
                                                <tr><th><wicket:message key="gb.export"></wicket:message></th><td><a rel="nofollow" target="_blank" wicket:id="exportJson"></a></td></tr>\r
index 4890874ac050c270640799f65fbf43c7208c2120..74484b09869b08b0ee24a77d4022c920777ceaa6 100644 (file)
@@ -42,6 +42,8 @@ import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.image.ContextImage;\r
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;\r
 import org.apache.wicket.markup.html.link.ExternalLink;\r
+import org.apache.wicket.markup.html.list.ListItem;\r
+import org.apache.wicket.markup.html.list.ListView;\r
 import org.apache.wicket.markup.html.panel.Fragment;\r
 import org.apache.wicket.markup.repeater.Item;\r
 import org.apache.wicket.markup.repeater.data.DataView;\r
@@ -292,6 +294,18 @@ public class TicketPage extends RepositoryPage {
                }\r
                add(new Label("ticketDescription", desc).setEscapeModelStrings(false));\r
 \r
+               /*\r
+                * DEPENDENCY\r
+                */\r
+               List<String> dependencies = ticket.getDependencies();\r
+               add(new ListView<String>("dependencies", dependencies) {\r
+                       @Override\r
+                       protected void populateItem(ListItem<String> item) {\r
+                               String ticketId= item.getModelObject();\r
+                               PageParameters tp = WicketUtils.newObjectParameter(ticket.repository, ticketId);\r
+                               item.add(new LinkPanel("dependencyLink", "list subject", "#"+ticketId, TicketsPage.class, tp));\r
+                       }\r
+               });\r
 \r
                /*\r
                 * PARTICIPANTS (DISCUSSION TAB)\r
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 (file)
index 0000000..79c381f
--- /dev/null
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"  
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"  
+      xml:lang="en"  
+      lang="en"> 
+
+<body>
+<wicket:panel>
+
+       <span wicket:id="dependencyList">
+               <tr>
+                       <th><wicket:message key="gb.dependency"></wicket:message></th>
+                       <td class="edit">
+                               <span wicket:id="dependencyLink" >[ticket label]</span>
+                               <button type="submit" class="btn" wicket:id="removeDependencyLink"><wicket:message key="gb.remove"/></button>
+                       </td>
+               </tr>
+       </span>
+       <th><wicket:message key="gb.dependency"></wicket:message></th>
+       <td class="edit">
+               <input class="input-large" type="text" wicket:id="addDependencyText"></input>
+               <button class="btn btn-appmenu" wicket:id="addDependency"><wicket:message key="gb.add"/></button>
+       </td>
+
+
+</wicket:panel>
+</body>
+</html>
\ 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 (file)
index 0000000..59cc909
--- /dev/null
@@ -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<List<String>> dependenciesModel;
+       private IModel<String> addDependencyModel;
+
+       
+       public TicketRelationEditorPanel(String wicketId, IModel<List<String>> pdependenciesModel, final RepositoryModel repositoryModel) {
+               super(wicketId);
+               this.dependenciesModel = pdependenciesModel;
+               this.addDependencyModel = Model.of();
+               
+               
+               add(new ListView<String>("dependencyList", dependenciesModel) {
+                       private static final long serialVersionUID = 1L;
+
+                       @Override
+                       protected void populateItem(ListItem<String> 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<String> list = dependenciesModel.getObject();
+                                               list.remove(ticketId);
+                                               dependenciesModel.setObject(list);
+                                               target.addComponent(form);
+                                       }
+                               });
+                       }
+               });
+               add(new TextField<String>("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<String> list = (List<String>) dependenciesModel.getObject();
+                                                       list.add(String.valueOf(ticketId));
+                                                       addDependencyModel.setObject("");
+                                               }
+                                       } catch (NumberFormatException e) {
+                                               // TODO : not allowed
+                                               
+                                       }
+                               }
+                               target.addComponent(form);
+                       }
+               });
+               
+               
+       }
+
+}