]> source.dussan.org Git - gitblit.git/commitdiff
Refactored common code out of My Tickets and Tickets 15/15/3
authorJames Moger <james.moger@gitblit.com>
Thu, 1 May 2014 23:53:53 +0000 (19:53 -0400)
committerJames Moger <james.moger@gitblit.com>
Thu, 1 May 2014 23:53:53 +0000 (19:53 -0400)
17 files changed:
src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
src/main/java/com/gitblit/wicket/SessionlessForm.java
src/main/java/com/gitblit/wicket/TicketsUI.java [new file with mode: 0644]
src/main/java/com/gitblit/wicket/WicketUtils.java
src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html
src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java
src/main/java/com/gitblit/wicket/pages/RepositoryPage.html
src/main/java/com/gitblit/wicket/pages/RepositoryPage.java
src/main/java/com/gitblit/wicket/pages/TicketBasePage.java [deleted file]
src/main/java/com/gitblit/wicket/pages/TicketPage.java
src/main/java/com/gitblit/wicket/pages/TicketsPage.html
src/main/java/com/gitblit/wicket/pages/TicketsPage.java
src/main/java/com/gitblit/wicket/panels/TicketListPanel.html [new file with mode: 0644]
src/main/java/com/gitblit/wicket/panels/TicketListPanel.java [new file with mode: 0644]
src/main/java/com/gitblit/wicket/panels/TicketSearchForm.java [new file with mode: 0644]
src/main/java/com/gitblit/wicket/panels/UserTitlePanel.html [new file with mode: 0644]
src/main/java/com/gitblit/wicket/panels/UserTitlePanel.java [new file with mode: 0644]

index 0c56df5436a49cc2e5df1672b6cca012418c34b3..0ed2ed59cb7b3237af695d2e9d51f3a08b29dc9d 100644 (file)
@@ -672,11 +672,11 @@ gb.ticketIsClosed = This ticket is closed.
 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.myTickets = my tickets
+gb.yourAssignedTickets = assigned to you
 gb.newMilestone = new milestone
 gb.editMilestone = edit milestone
 gb.notifyChangedOpenTickets = send notification for changed open tickets
 gb.overdue = overdue
 gb.openMilestones = open milestones
 gb.closedMilestones = closed milestones
-gb.myTickets = my tickets
-gb.yourAssignedTickets = assigned to you
\ No newline at end of file
index d228a2e12c1f3932e6bab0c5d08e1d1cbc9045e7..6f790717425a88b3cd6658aeccce64e6c60d7c5b 100644 (file)
@@ -22,6 +22,7 @@ import org.apache.wicket.PageParameters;
 import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.MarkupStream;
 import org.apache.wicket.markup.html.form.StatelessForm;
+import org.apache.wicket.protocol.http.RequestUtils;
 import org.apache.wicket.protocol.http.WicketURLDecoder;
 import org.apache.wicket.protocol.http.request.WebRequestCodingStrategy;
 import org.apache.wicket.util.string.AppendingStringBuffer;
@@ -53,9 +54,9 @@ public class SessionlessForm<T> extends StatelessForm<T> {
 
        private static final String HIDDEN_DIV_START = "<div style=\"width:0px;height:0px;position:absolute;left:-100px;top:-100px;overflow:hidden\">";
 
-       private final Class<? extends BasePage> pageClass;
+       protected final Class<? extends BasePage> pageClass;
 
-       private final PageParameters pageParameters;
+       protected final PageParameters pageParameters;
 
        private final Logger log = LoggerFactory.getLogger(SessionlessForm.class);
 
@@ -145,4 +146,14 @@ public class SessionlessForm<T> extends StatelessForm<T> {
                String un = WicketURLDecoder.QUERY_INSTANCE.decode(s);
                return Strings.escapeMarkup(un).toString();
        }
+
+       protected String getAbsoluteUrl() {
+               return getAbsoluteUrl(pageClass, pageParameters);
+       }
+
+       protected String getAbsoluteUrl(Class<? extends BasePage> pageClass, PageParameters pageParameters) {
+               String relativeUrl = urlFor(pageClass, pageParameters).toString();
+               String absoluteUrl = RequestUtils.toAbsolutePath(relativeUrl);
+               return absoluteUrl;
+       }
 }
diff --git a/src/main/java/com/gitblit/wicket/TicketsUI.java b/src/main/java/com/gitblit/wicket/TicketsUI.java
new file mode 100644 (file)
index 0000000..a243a7b
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * 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.wicket;
+
+import java.io.Serializable;
+import java.text.MessageFormat;
+
+import org.apache.wicket.markup.html.basic.Label;
+
+import com.gitblit.models.TicketModel;
+import com.gitblit.models.TicketModel.Status;
+import com.gitblit.models.TicketModel.Type;
+import com.gitblit.utils.StringUtils;
+
+/**
+ * Common tickets ui methods and classes.
+ *
+ * @author James Moger
+ *
+ */
+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);
+       }
+
+       public static Label getStateIcon(String wicketId, Type type, Status state) {
+               Label label = new Label(wicketId);
+               if (type == null) {
+                       type = Type.defaultType;
+               }
+               switch (type) {
+               case Proposal:
+                       WicketUtils.setCssClass(label, "fa fa-code-fork");
+                       break;
+               case Bug:
+                       WicketUtils.setCssClass(label, "fa fa-bug");
+                       break;
+               case Enhancement:
+                       WicketUtils.setCssClass(label, "fa fa-magic");
+                       break;
+               case Question:
+                       WicketUtils.setCssClass(label, "fa fa-question");
+                       break;
+               default:
+                       // standard ticket
+                       WicketUtils.setCssClass(label, "fa fa-ticket");
+               }
+               WicketUtils.setHtmlTooltip(label, getTypeState(type, state));
+               return label;
+       }
+
+       public static String getTypeState(Type type, Status state) {
+               return state.toString() + " " + type.toString();
+       }
+
+       public static String getLozengeClass(Status status, boolean subtle) {
+               if (status == null) {
+                       status = Status.New;
+               }
+               String css = "";
+               switch (status) {
+               case Declined:
+               case Duplicate:
+               case Invalid:
+               case Wontfix:
+               case Abandoned:
+                       css = "aui-lozenge-error";
+                       break;
+               case Fixed:
+               case Merged:
+               case Resolved:
+                       css = "aui-lozenge-success";
+                       break;
+               case New:
+                       css = "aui-lozenge-complete";
+                       break;
+               case On_Hold:
+                       css = "aui-lozenge-current";
+                       break;
+               default:
+                       css = "";
+                       break;
+               }
+
+               return "aui-lozenge" + (subtle ? " aui-lozenge-subtle": "") + (css.isEmpty() ? "" : " ") + css;
+       }
+
+       public static String getStatusClass(Status status) {
+               String css = "";
+               switch (status) {
+               case Declined:
+               case Duplicate:
+               case Invalid:
+               case Wontfix:
+               case Abandoned:
+                       css = "resolution-error";
+                       break;
+               case Fixed:
+               case Merged:
+               case Resolved:
+                       css = "resolution-success";
+                       break;
+               case New:
+                       css = "resolution-complete";
+                       break;
+               case On_Hold:
+                       css = "resolution-current";
+                       break;
+               default:
+                       css = "";
+                       break;
+               }
+
+               return "resolution" + (css.isEmpty() ? "" : " ") + css;
+       }
+
+       public static class TicketSort implements Serializable {
+
+               private static final long serialVersionUID = 1L;
+
+               public final String name;
+               public final String sortBy;
+               public final boolean desc;
+
+               public TicketSort(String name, String sortBy, boolean desc) {
+                       this.name = name;
+                       this.sortBy = sortBy;
+                       this.desc = desc;
+               }
+       }
+
+       public static class Indicator implements Serializable {
+
+               private static final long serialVersionUID = 1L;
+
+               public final String css;
+               public final int count;
+               public final String tooltip;
+
+               public Indicator(String css, String tooltip) {
+                       this.css = css;
+                       this.tooltip = tooltip;
+                       this.count = 0;
+               }
+
+               public Indicator(String css, int count, String pattern) {
+                       this.css = css;
+                       this.count = count;
+                       this.tooltip = StringUtils.isEmpty(pattern) ? "" : MessageFormat.format(pattern, count);
+               }
+
+               public String getTooltip() {
+                       return tooltip;
+               }
+       }
+
+       public static class TicketQuery implements Serializable, Comparable<TicketQuery> {
+
+               private static final long serialVersionUID = 1L;
+
+               public final String name;
+               public final String query;
+               public String color;
+
+               public TicketQuery(String name, String query) {
+                       this.name = name;
+                       this.query = query;
+               }
+
+               public TicketQuery color(String value) {
+                       this.color = value;
+                       return this;
+               }
+
+               @Override
+               public boolean equals(Object o) {
+                       if (o instanceof TicketQuery) {
+                               return ((TicketQuery) o).query.equals(query);
+                       }
+                       return false;
+               }
+
+               @Override
+               public int hashCode() {
+                       return query.hashCode();
+               }
+
+               @Override
+               public int compareTo(TicketQuery o) {
+                       return query.compareTo(o.query);
+               }
+       }
+}
index 2a34ca8041131b27ad6abd0a824704f7a1202cee..10b214687eab465669ccabb9a22a74d2cdbfc5a0 100644 (file)
@@ -300,7 +300,9 @@ public class WicketUtils {
 \r
        public static PageParameters newRepositoryParameter(String repositoryName) {\r
                Map<String, String> parameterMap = new HashMap<String, String>();\r
-               parameterMap.put("r", repositoryName);\r
+               if (!StringUtils.isEmpty(repositoryName)) {\r
+                       parameterMap.put("r", repositoryName);\r
+               }\r
                return new PageParameters(parameterMap);\r
        }\r
 \r
index f4e62b4ea97fd466117a919b49a0ba3d76ae40ee..b0bc19493e98e7c1538b2cb37ae6520ead4325fd 100644 (file)
@@ -7,19 +7,12 @@
 <body>
        <wicket:extend>
                <div class="container">
-               
                        <div class="row" style="padding-top:15px;min-height:500px;" >
                                <div class="tab-pane active" id="tickets">
                                        <!-- query controls -->
                                        <div class="span3">
                                                <div class="hidden-phone">
-                                                       <div>
-                                                               <div style="display:inline-block;vertical-align:top;padding: 0px 2px 2px;"><img wicket:id="userGravatar"></img></div>
-                                                               <div style="display:inline-block;">
-                                                                       <div style="font-size:1.5em;" wicket:id="userDisplayName"></div>
-                                                                       <div style="color:#888;font-size:1.2em;padding-top:4px;"><wicket:message key="gb.myTickets"></wicket:message></div>
-                                                               </div>
-                                                       </div>
+                                                       <div wicket:id="userTitlePanel"></div>
                                                        
                                                        <!-- search tickets form -->
                                                        <form class="form-search" style="margin: 10px 0px;" wicket:id="ticketSearchForm">
                                                                </div>
                                                        </div>
                                                </div>
-                                               <table class="table tickets">   
-                                                       <tbody>
-                                                               <tr wicket:id="row">
-                                                                       <td class="ticket-list-icon">
-                                                                               <i wicket:id="state"></i>
-                                                                       </td>
-                                                               <td>
-                                                                       <span wicket:id="title">[title]</span> <span wicket:id="labels" style="font-weight: normal;color:white;"><span class="label" wicket:id="label"></span></span>
-                                                                       <div class="ticket-list-details">
-                                                                               <span style="padding-right: 10px;" class="hidden-phone">
-                                                                                       <wicket:message key="gb.createdBy"></wicket:message>
-                                                                                       <span style="padding: 0px 2px" wicket:id="createdBy">[createdBy]</span> <span class="date" wicket:id="createDate">[create date]</span>
-                                                                               </span>
-                                                                               <span wicket:id="indicators" style="white-space:nowrap;"><i wicket:id="icon"></i> <span style="padding-right:10px;" wicket:id="count"></span></span>
-                                                                       </div>
-                                                                       <div class="hidden-phone" wicket:id="updated"></div>
-                                                                       <div class="ticket-list-details" wicket:id="repositoryLink">[repository link]</div>
-                                                               </td>
-                                                               <td class="ticket-list-state">
-                                                                               <span class="badge badge-info" wicket:id="votes"></span>
-                                                               </td>
-                                                               <td class="hidden-phone ticket-list-state">
-                                                                               <i wicket:message="title:gb.watching" style="color:#888;" class="fa fa-eye" wicket:id="watching"></i>
-                                                               </td>
-                                                               <td class="ticket-list-state">
-                                                                               <div wicket:id="status"></div>
-                                                               </td>
-                                                               <td class="indicators">
-                                                                       <div>                                                           
-                                                                               <b>#<span wicket:id="id">[id]</span></b>
-                                                                       </div>
-                                                                       <div wicket:id="responsible"></div>
-                                                               </td>
-                                                               </tr>
-                                               </tbody>
-                                               </table>                                                
+                                               
+                                               <div wicket:id="ticketList"></div>                                      
                                        </div>
                                </div>
                        </div>
                </div>
-               
-<wicket:fragment wicket:id="updatedFragment">
-       <div class="ticket-list-details">
-               <wicket:message key="gb.updatedBy"></wicket:message>
-               <span style="padding: 0px 2px" wicket:id="updatedBy">[updatedBy]</span> <span class="date" wicket:id="updateDate">[update date]</span>
-       </div>
-</wicket:fragment>
-               
+                               
 </wicket:extend>
 </body>
 </html>
\ No newline at end of file
index e26885808f8c61f64ecda36fcb80f6c87c5b7a9c..c207d561a2a299738b870faeedbcf0154009d020 100644 (file)
@@ -1,72 +1,74 @@
+/*
+ * 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.wicket.pages;
 
-import java.io.Serializable;
-import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
 import org.apache.wicket.PageParameters;
-import org.apache.wicket.behavior.SimpleAttributeModifier;
 import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.TextField;
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;
-import org.apache.wicket.markup.html.panel.Fragment;
 import org.apache.wicket.markup.repeater.Item;
 import org.apache.wicket.markup.repeater.data.DataView;
 import org.apache.wicket.markup.repeater.data.ListDataProvider;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.request.target.basic.RedirectRequestTarget;
-import org.eclipse.jgit.lib.Repository;
 
-import com.gitblit.Constants;
 import com.gitblit.Keys;
-import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.TicketModel;
 import com.gitblit.models.TicketModel.Status;
-import com.gitblit.models.TicketModel.Type;
 import com.gitblit.models.UserModel;
-import com.gitblit.tickets.ITicketService;
 import com.gitblit.tickets.QueryBuilder;
 import com.gitblit.tickets.QueryResult;
 import com.gitblit.tickets.TicketIndexer.Lucene;
-import com.gitblit.tickets.TicketLabel;
 import com.gitblit.utils.ArrayUtils;
-import com.gitblit.utils.BugtraqProcessor;
 import com.gitblit.utils.StringUtils;
-import com.gitblit.wicket.GitBlitWebApp;
 import com.gitblit.wicket.GitBlitWebSession;
-import com.gitblit.wicket.SessionlessForm;
+import com.gitblit.wicket.TicketsUI;
+import com.gitblit.wicket.TicketsUI.TicketSort;
 import com.gitblit.wicket.WicketUtils;
-import com.gitblit.wicket.panels.GravatarImage;
 import com.gitblit.wicket.panels.LinkPanel;
-
+import com.gitblit.wicket.panels.TicketListPanel;
+import com.gitblit.wicket.panels.TicketSearchForm;
+import com.gitblit.wicket.panels.UserTitlePanel;
+
+/**
+ * My Tickets page
+ *
+ * @author Christian Buisson
+ * @author James Moger
+ */
 public class MyTicketsPage extends RootPage {
 
-       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 MyTicketsPage()
-       {
+       public MyTicketsPage() {
                this(null);
        }
 
-       public MyTicketsPage(PageParameters params)
-       {
+       public MyTicketsPage(PageParameters params)     {
                super(params);
                setupPage("", getString("gb.myTickets"));
 
                UserModel currentUser = GitBlitWebSession.get().getUser();
-               if (currentUser == null) {
+               if (currentUser == null || UserModel.ANONYMOUS.equals(currentUser)) {
                        setRedirect(true);
                        setResponsePage(getApplication().getHomePage());
                        return;
                }
 
                final String username = currentUser.getName();
-               final String[] statiiParam = (params == null) ? openStatii : params.getStringArray(Lucene.status.name());
+               final String[] statiiParam = (params == null) ? TicketsUI.openStatii : params.getStringArray(Lucene.status.name());
                final String assignedToParam = (params == null) ? "" : params.getString(Lucene.responsible.name(), null);
                final String milestoneParam = (params == null) ? "" : params.getString(Lucene.milestone.name(), null);
                final String queryParam = (params == null || StringUtils.isEmpty(params.getString("q", null))) ? "watchedby:" + username : params.getString("q", null);
@@ -74,13 +76,11 @@ public class MyTicketsPage extends RootPage {
                final String sortBy = (params == null) ? "" : Lucene.fromString(params.getString("sort", Lucene.created.name())).name();
                final boolean desc = (params == null) ? true : !"asc".equals(params.getString("direction", "desc"));
 
-               add(new GravatarImage("userGravatar", currentUser, "gravatar", 36, false));
-               add(new Label("userDisplayName", currentUser.getDisplayName()));
+               // add the user title panel
+               add(new UserTitlePanel("userTitlePanel", currentUser, getString("gb.myTickets")));
 
                // add search form
-               TicketSearchForm searchForm = new TicketSearchForm("ticketSearchForm", searchParam);
-               add(searchForm);
-               searchForm.setTranslatedAttributes();
+               add(new TicketSearchForm("ticketSearchForm", null, searchParam, getClass(), params));
 
                // standard queries
                add(new BookmarkablePageLink<Void>("changesQuery", MyTicketsPage.class,
@@ -137,7 +137,7 @@ public class MyTicketsPage extends RootPage {
                                queryParameters(
                                                null,
                                                milestoneParam,
-                                               openStatii,
+                                               TicketsUI.openStatii,
                                                null,
                                                null,
                                                true,
@@ -188,8 +188,8 @@ public class MyTicketsPage extends RootPage {
                } else {
                        add(new Label("selectedStatii", StringUtils.flattenStrings(Arrays.asList(statiiParam), ",")));
                }
-               add(new BookmarkablePageLink<Void>("openTickets", MyTicketsPage.class, queryParameters(queryParam, milestoneParam, openStatii, assignedToParam, sortBy, desc, 1)));
-               add(new BookmarkablePageLink<Void>("closedTickets", MyTicketsPage.class, queryParameters(queryParam, milestoneParam, closedStatii, assignedToParam, sortBy, desc, 1)));
+               add(new BookmarkablePageLink<Void>("openTickets", MyTicketsPage.class, queryParameters(queryParam, milestoneParam, TicketsUI.openStatii, assignedToParam, sortBy, desc, 1)));
+               add(new BookmarkablePageLink<Void>("closedTickets", MyTicketsPage.class, queryParameters(queryParam, milestoneParam, TicketsUI.closedStatii, assignedToParam, sortBy, desc, 1)));
                add(new BookmarkablePageLink<Void>("allTickets", MyTicketsPage.class, queryParameters(queryParam, milestoneParam, null, assignedToParam, sortBy, desc, 1)));
 
                // by status
@@ -203,7 +203,7 @@ public class MyTicketsPage extends RootPage {
                        public void populateItem(final Item<Status> item) {
                                final Status status = item.getModelObject();
                                PageParameters p = queryParameters(queryParam, milestoneParam, new String [] { status.name().toLowerCase() }, assignedToParam, sortBy, desc, 1);
-                               String css = getStatusClass(status);
+                               String css = TicketsUI.getStatusClass(status);
                                item.add(new LinkPanel("statusLink", css, status.toString(), MyTicketsPage.class, p).setRenderBodyOnly(true));
                        }
                };
@@ -284,342 +284,18 @@ public class MyTicketsPage extends RootPage {
                int page = (params != null) ? Math.max(1, WicketUtils.getPage(params)) : 1;
                int pageSize = app().settings().getInteger(Keys.tickets.perPage, 25);
 
-               ITicketService tickets = GitBlitWebApp.get().tickets();
                List<QueryResult> results;
-               if(StringUtils.isEmpty(searchParam))
-               {
-                       results = tickets.queryFor(luceneQuery, page, pageSize, sortBy, desc);
-               }
-               else
-               {
-                       results = tickets.searchFor(null, searchParam, page, pageSize);
+               if(StringUtils.isEmpty(searchParam)) {
+                       results = app().tickets().queryFor(luceneQuery, page, pageSize, sortBy, desc);
+               } else {
+                       results = app().tickets().searchFor(null, searchParam, page, pageSize);
                }
+
                int totalResults = results.size() == 0 ? 0 : results.get(0).totalResults;
                buildPager(queryParam, milestoneParam, statiiParam, assignedToParam, sortBy, desc, page, pageSize, results.size(), totalResults);
 
                final boolean showSwatch = app().settings().getBoolean(Keys.web.repositoryListSwatches, true);
-               final ListDataProvider<QueryResult> dp = new ListDataProvider<QueryResult>(results);
-
-               DataView<QueryResult> dataView = new DataView<QueryResult>("row", dp) {
-                       private static final long serialVersionUID = 1L;
-
-                       @Override
-                       protected void populateItem(Item<QueryResult> item) {
-                               final QueryResult ticket = item.getModelObject();
-                               final RepositoryModel repository = app().repositories().getRepositoryModel(ticket.repository);
-
-                               if (showSwatch) {
-                                       // set repository color
-                                       String color = StringUtils.getColor(StringUtils.stripDotGit(repository.name));
-                                       WicketUtils.setCssStyle(item, MessageFormat.format("border-left: 2px solid {0};", color));
-                               }
-
-                               PageParameters rp = WicketUtils.newRepositoryParameter(ticket.repository);
-                               PageParameters tp = WicketUtils.newObjectParameter(ticket.repository, "" + ticket.number);
-                               item.add(new LinkPanel("repositoryLink", null, StringUtils.stripDotGit(ticket.repository), SummaryPage.class, rp));
-
-                               item.add(getStateIcon("state", ticket.type, ticket.status));
-                               item.add(new Label("id", "" + ticket.number));
-                               UserModel creator = app().users().getUserModel(ticket.createdBy);
-                               if (creator != null) {
-                                       item.add(new LinkPanel("createdBy", null, creator.getDisplayName(),
-                                               UserPage.class, WicketUtils.newUsernameParameter(ticket.createdBy)));
-                               } else {
-                                       item.add(new Label("createdBy", ticket.createdBy));
-                               }
-                               item.add(WicketUtils.createDateLabel("createDate", ticket.createdAt, GitBlitWebSession
-                                               .get().getTimezone(), getTimeUtils(), false));
-
-                               if (ticket.updatedAt == null) {
-                                       item.add(new Label("updated").setVisible(false));
-                               } else {
-                                       Fragment updated = new Fragment("updated", "updatedFragment", this);
-                                       UserModel updater = app().users().getUserModel(ticket.updatedBy);
-                                       if (updater != null) {
-                                               updated.add(new LinkPanel("updatedBy", null, updater.getDisplayName(),
-                                                               UserPage.class, WicketUtils.newUsernameParameter(ticket.updatedBy)));
-                                       } else {
-                                               updated.add(new Label("updatedBy", ticket.updatedBy));
-                                       }
-                                       updated.add(WicketUtils.createDateLabel("updateDate", ticket.updatedAt, GitBlitWebSession
-                                                       .get().getTimezone(), getTimeUtils(), false));
-                                       item.add(updated);
-                               }
-
-                               item.add(new LinkPanel("title", "list subject", StringUtils.trimString(
-                                               ticket.title, Constants.LEN_SHORTLOG), TicketsPage.class, tp));
-
-                               ListDataProvider<String> labelsProvider = new ListDataProvider<String>(ticket.getLabels());
-                               DataView<String> labelsView = new DataView<String>("labels", labelsProvider) {
-                                       private static final long serialVersionUID = 1L;
-
-                                       @Override
-                                       public void populateItem(final Item<String> labelItem) {
-                                               BugtraqProcessor btp  = new BugtraqProcessor(app().settings());
-                                               Repository db = app().repositories().getRepository(repository.name);
-                                               String content = btp.processPlainCommitMessage(db, repository.name, labelItem.getModelObject());
-                                               db.close();
-                                               Label label = new Label("label", content);
-                                               label.setEscapeModelStrings(false);
-                                               TicketLabel tLabel = app().tickets().getLabel(repository, labelItem.getModelObject());
-                                               String background = MessageFormat.format("background-color:{0};", tLabel.color);
-                                               label.add(new SimpleAttributeModifier("style", background));
-                                               labelItem.add(label);
-                                       }
-                               };
-                               item.add(labelsView);
-
-                               if (StringUtils.isEmpty(ticket.responsible)) {
-                                       item.add(new Label("responsible").setVisible(false));
-                               } else {
-                                       UserModel responsible = app().users().getUserModel(ticket.responsible);
-                                       if (responsible == null) {
-                                               responsible = new UserModel(ticket.responsible);
-                                       }
-                                       GravatarImage avatar = new GravatarImage("responsible", responsible.getDisplayName(),
-                                                       responsible.emailAddress, null, 16, true);
-                                       avatar.setTooltip(getString("gb.responsible") + ": " + responsible.getDisplayName());
-                                       item.add(avatar);
-                               }
-
-                               // votes indicator
-                               Label v = new Label("votes", "" + ticket.votesCount);
-                               WicketUtils.setHtmlTooltip(v, getString("gb.votes"));
-                               item.add(v.setVisible(ticket.votesCount > 0));
-
-                               // watching indicator
-                               item.add(new Label("watching").setVisible(ticket.isWatching(GitBlitWebSession.get().getUsername())));
-
-                               // status indicator
-                               String css = getLozengeClass(ticket.status, true);
-                               Label l = new Label("status", ticket.status.toString());
-                               WicketUtils.setCssClass(l, css);
-                               item.add(l);
-
-                               // add the ticket indicators/icons
-                               List<Indicator> indicators = new ArrayList<Indicator>();
-
-                               // comments
-                               if (ticket.commentsCount > 0) {
-                                       int count = ticket.commentsCount;
-                                       String pattern = "gb.nComments";
-                                       if (count == 1) {
-                                               pattern = "gb.oneComment";
-                                       }
-                                       indicators.add(new Indicator("fa fa-comment", count, pattern));
-                               }
-
-                               // participants
-                               if (!ArrayUtils.isEmpty(ticket.participants)) {
-                                       int count = ticket.participants.size();
-                                       if (count > 1) {
-                                               String pattern = "gb.nParticipants";
-                                               indicators.add(new Indicator("fa fa-user", count, pattern));
-                                       }
-                               }
-
-                               // attachments
-                               if (!ArrayUtils.isEmpty(ticket.attachments)) {
-                                       int count = ticket.attachments.size();
-                                       String pattern = "gb.nAttachments";
-                                       if (count == 1) {
-                                               pattern = "gb.oneAttachment";
-                                       }
-                                       indicators.add(new Indicator("fa fa-file", count, pattern));
-                               }
-
-                               // patchset revisions
-                               if (ticket.patchset != null) {
-                                       int count = ticket.patchset.commits;
-                                       String pattern = "gb.nCommits";
-                                       if (count == 1) {
-                                               pattern = "gb.oneCommit";
-                                       }
-                                       indicators.add(new Indicator("fa fa-code", count, pattern));
-                               }
-
-                               // milestone
-                               if (!StringUtils.isEmpty(ticket.milestone)) {
-                                       indicators.add(new Indicator("fa fa-bullseye", ticket.milestone));
-                               }
-
-                               ListDataProvider<Indicator> indicatorsDp = new ListDataProvider<Indicator>(indicators);
-                               DataView<Indicator> indicatorsView = new DataView<Indicator>("indicators", indicatorsDp) {
-                                       private static final long serialVersionUID = 1L;
-
-                                       @Override
-                                       public void populateItem(final Item<Indicator> item) {
-                                               Indicator indicator = item.getModelObject();
-                                               String tooltip = indicator.getTooltip();
-
-                                               Label icon = new Label("icon");
-                                               WicketUtils.setCssClass(icon, indicator.css);
-                                               item.add(icon);
-
-                                               if (indicator.count > 0) {
-                                                       Label count = new Label("count", "" + indicator.count);
-                                                       item.add(count.setVisible(!StringUtils.isEmpty(tooltip)));
-                                               } else {
-                                                       item.add(new Label("count").setVisible(false));
-                                               }
-
-                                               WicketUtils.setHtmlTooltip(item, tooltip);
-                                       }
-                               };
-                               item.add(indicatorsView);
-                       }
-               };
-
-               add(dataView);
-       }
-
-       protected Label getStateIcon(String wicketId, TicketModel ticket) {
-               return getStateIcon(wicketId, ticket.type, ticket.status);
-       }
-
-       protected Label getStateIcon(String wicketId, Type type, Status state) {
-               Label label = new Label(wicketId);
-               if (type == null) {
-                       type = Type.defaultType;
-               }
-               switch (type) {
-               case Proposal:
-                       WicketUtils.setCssClass(label, "fa fa-code-fork");
-                       break;
-               case Bug:
-                       WicketUtils.setCssClass(label, "fa fa-bug");
-                       break;
-               case Enhancement:
-                       WicketUtils.setCssClass(label, "fa fa-magic");
-                       break;
-               case Question:
-                       WicketUtils.setCssClass(label, "fa fa-question");
-                       break;
-               default:
-                       // standard ticket
-                       WicketUtils.setCssClass(label, "fa fa-ticket");
-               }
-               WicketUtils.setHtmlTooltip(label, getTypeState(type, state));
-               return label;
-       }
-
-       protected String getTypeState(Type type, Status state) {
-               return state.toString() + " " + type.toString();
-       }
-
-       protected String getLozengeClass(Status status, boolean subtle) {
-               if (status == null) {
-                       status = Status.New;
-               }
-               String css = "";
-               switch (status) {
-               case Declined:
-               case Duplicate:
-               case Invalid:
-               case Wontfix:
-               case Abandoned:
-                       css = "aui-lozenge-error";
-                       break;
-               case Fixed:
-               case Merged:
-               case Resolved:
-                       css = "aui-lozenge-success";
-                       break;
-               case New:
-                       css = "aui-lozenge-complete";
-                       break;
-               case On_Hold:
-                       css = "aui-lozenge-current";
-                       break;
-               default:
-                       css = "";
-                       break;
-               }
-
-               return "aui-lozenge" + (subtle ? " aui-lozenge-subtle": "") + (css.isEmpty() ? "" : " ") + css;
-       }
-
-       protected String getStatusClass(Status status) {
-               String css = "";
-               switch (status) {
-               case Declined:
-               case Duplicate:
-               case Invalid:
-               case Wontfix:
-               case Abandoned:
-                       css = "resolution-error";
-                       break;
-               case Fixed:
-               case Merged:
-               case Resolved:
-                       css = "resolution-success";
-                       break;
-               case New:
-                       css = "resolution-complete";
-                       break;
-               case On_Hold:
-                       css = "resolution-current";
-                       break;
-               default:
-                       css = "";
-                       break;
-               }
-
-               return "resolution" + (css.isEmpty() ? "" : " ") + css;
-       }
-
-       private class TicketSort implements Serializable {
-
-               private static final long serialVersionUID = 1L;
-
-               final String name;
-               final String sortBy;
-               final boolean desc;
-
-               TicketSort(String name, String sortBy, boolean desc) {
-                       this.name = name;
-                       this.sortBy = sortBy;
-                       this.desc = desc;
-               }
-       }
-
-       private class TicketSearchForm extends SessionlessForm<Void> implements Serializable {
-               private static final long serialVersionUID = 1L;
-
-               private final IModel<String> searchBoxModel;;
-
-               public TicketSearchForm(String id, String text) {
-                       super(id, MyTicketsPage.this.getClass(), MyTicketsPage.this.getPageParameters());
-
-                       this.searchBoxModel = new Model<String>(text == null ? "" : text);
-
-                       TextField<String> searchBox = new TextField<String>("ticketSearchBox", searchBoxModel);
-                       add(searchBox);
-               }
-
-               void setTranslatedAttributes() {
-                       WicketUtils.setHtmlTooltip(get("ticketSearchBox"),
-                                       MessageFormat.format(getString("gb.searchTicketsTooltip"), ""));
-                       WicketUtils.setInputPlaceholder(get("ticketSearchBox"), getString("gb.searchTickets"));
-               }
-
-               @Override
-               public void onSubmit() {
-                       String searchString = searchBoxModel.getObject();
-                       if (StringUtils.isEmpty(searchString)) {
-                               // redirect to self to avoid wicket page update bug
-                               String absoluteUrl = getCanonicalUrl();
-                               getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
-                               return;
-                       }
-
-                       // use an absolute url to workaround Wicket-Tomcat problems with
-                       // mounted url parameters (issue-111)
-                       PageParameters params = WicketUtils.newRepositoryParameter("");
-                       params.add("s", searchString);
-                       String absoluteUrl = getCanonicalUrl(MyTicketsPage.class, params);
-                       getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
-               }
+               add(new TicketListPanel("ticketList", results, showSwatch, true));
        }
 
        protected PageParameters queryParameters(
@@ -713,29 +389,4 @@ public class MyTicketsPage extends RootPage {
                };
                add(pagesView);
        }
-
-       private class Indicator implements Serializable {
-
-               private static final long serialVersionUID = 1L;
-
-               final String css;
-               final int count;
-               final String tooltip;
-
-               Indicator(String css, String tooltip) {
-                       this.css = css;
-                       this.tooltip = tooltip;
-                       this.count = 0;
-               }
-
-               Indicator(String css, int count, String pattern) {
-                       this.css = css;
-                       this.count = count;
-                       this.tooltip = StringUtils.isEmpty(pattern) ? "" : MessageFormat.format(getString(pattern), count);
-               }
-
-               String getTooltip() {
-                       return tooltip;
-               }
-       }
 }
index cb4f1b6738ef0033c2692e052e85fa55d137cc9c..22544bc8ef69e3704563c3aff01e94c4161cf41e 100644 (file)
@@ -17,7 +17,7 @@
                                                                <form class="form-search" style="margin: 0px;" wicket:id="searchForm">\r
                                                                        <div class="input-append">\r
                                                                                <select class="span2" style="border-radius: 4px;" wicket:id="searchType"/>\r
-                                                                               <input type="text" class="search-query" style="width: 170px;border-radius: 14px 0 0 14px; padding-left: 14px;" id="searchBox" wicket:id="searchBox" value=""/>\r
+                                                                               <input type="text" class="input-medium search-query" style="border-radius: 14px 0 0 14px; padding-left: 14px;" id="searchBox" wicket:id="searchBox" value=""/>\r
                                                                                <button class="btn" style="border-radius: 0 14px 14px 0px;margin-left:-5px;" type="submit"><i class="icon-search"></i></button>\r
                                                                        </div>\r
                                                                </form>\r
index 2b97bc1657cc9f6fb494268644221c48536181ad..5ea99fd8f9d2b61781621af2d86b7f2ec3f32027 100644 (file)
@@ -69,6 +69,7 @@ import com.gitblit.wicket.GitBlitWebSession;
 import com.gitblit.wicket.PageRegistration;\r
 import com.gitblit.wicket.PageRegistration.OtherPageLink;\r
 import com.gitblit.wicket.SessionlessForm;\r
+import com.gitblit.wicket.TicketsUI;\r
 import com.gitblit.wicket.WicketUtils;\r
 import com.gitblit.wicket.panels.LinkPanel;\r
 import com.gitblit.wicket.panels.NavigationPanel;\r
@@ -204,7 +205,7 @@ public abstract class RepositoryPage extends RootPage {
                pages.put("tree", new PageRegistration("gb.tree", TreePage.class, params));\r
                if (app().tickets().isReady() && (app().tickets().isAcceptingNewTickets(getRepositoryModel()) || app().tickets().hasTickets(getRepositoryModel()))) {\r
                        PageParameters tParams = new PageParameters(params);\r
-                       for (String state : TicketsPage.openStatii) {\r
+                       for (String state : TicketsUI.openStatii) {\r
                                tParams.add(Lucene.status.name(), state);\r
                        }\r
                        pages.put("tickets", new PageRegistration("gb.tickets", TicketsPage.class, tParams));
diff --git a/src/main/java/com/gitblit/wicket/pages/TicketBasePage.java b/src/main/java/com/gitblit/wicket/pages/TicketBasePage.java
deleted file mode 100644 (file)
index 60fa638..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*\r
- * Copyright 2013 gitblit.com.\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package com.gitblit.wicket.pages;\r
-\r
-import org.apache.wicket.PageParameters;\r
-import org.apache.wicket.markup.html.basic.Label;\r
-\r
-import com.gitblit.models.TicketModel;\r
-import com.gitblit.models.TicketModel.Status;\r
-import com.gitblit.models.TicketModel.Type;\r
-import com.gitblit.wicket.WicketUtils;\r
-\r
-public abstract class TicketBasePage extends RepositoryPage {\r
-\r
-       public TicketBasePage(PageParameters params) {\r
-               super(params);\r
-       }\r
-\r
-       protected Label getStateIcon(String wicketId, TicketModel ticket) {\r
-               return getStateIcon(wicketId, ticket.type, ticket.status);\r
-       }\r
-\r
-       protected Label getStateIcon(String wicketId, Type type, Status state) {\r
-               Label label = new Label(wicketId);\r
-               if (type == null) {\r
-                       type = Type.defaultType;\r
-               }\r
-               switch (type) {\r
-               case Proposal:\r
-                       WicketUtils.setCssClass(label, "fa fa-code-fork");\r
-                       break;\r
-               case Bug:\r
-                       WicketUtils.setCssClass(label, "fa fa-bug");\r
-                       break;\r
-               case Enhancement:\r
-                       WicketUtils.setCssClass(label, "fa fa-magic");\r
-                       break;\r
-               case Question:\r
-                       WicketUtils.setCssClass(label, "fa fa-question");\r
-                       break;\r
-               default:\r
-                       // standard ticket\r
-                       WicketUtils.setCssClass(label, "fa fa-ticket");\r
-               }\r
-               WicketUtils.setHtmlTooltip(label, getTypeState(type, state));\r
-               return label;\r
-       }\r
-\r
-       protected String getTypeState(Type type, Status state) {\r
-               return state.toString() + " " + type.toString();\r
-       }\r
-\r
-       protected String getLozengeClass(Status status, boolean subtle) {\r
-               if (status == null) {\r
-                       status = Status.New;\r
-               }\r
-               String css = "";\r
-               switch (status) {\r
-               case Declined:\r
-               case Duplicate:\r
-               case Invalid:\r
-               case Wontfix:\r
-               case Abandoned:\r
-                       css = "aui-lozenge-error";\r
-                       break;\r
-               case Fixed:\r
-               case Merged:\r
-               case Resolved:\r
-                       css = "aui-lozenge-success";\r
-                       break;\r
-               case New:\r
-                       css = "aui-lozenge-complete";\r
-                       break;\r
-               case On_Hold:\r
-                       css = "aui-lozenge-current";\r
-                       break;\r
-               default:\r
-                       css = "";\r
-                       break;\r
-               }\r
-\r
-               return "aui-lozenge" + (subtle ? " aui-lozenge-subtle": "") + (css.isEmpty() ? "" : " ") + css;\r
-       }\r
-\r
-       protected String getStatusClass(Status status) {\r
-               String css = "";\r
-               switch (status) {\r
-               case Declined:\r
-               case Duplicate:\r
-               case Invalid:\r
-               case Wontfix:\r
-               case Abandoned:\r
-                       css = "resolution-error";\r
-                       break;\r
-               case Fixed:\r
-               case Merged:\r
-               case Resolved:\r
-                       css = "resolution-success";\r
-                       break;\r
-               case New:\r
-                       css = "resolution-complete";\r
-                       break;\r
-               case On_Hold:\r
-                       css = "resolution-current";\r
-                       break;\r
-               default:\r
-                       css = "";\r
-                       break;\r
-               }\r
-\r
-               return "resolution" + (css.isEmpty() ? "" : " ") + css;\r
-       }\r
-}\r
index 659acad06e406a5aafdfb8ea4cdddd11e10a9ee0..c066f24dd6153166b3960b6ffa4fb9b3806c20ed 100644 (file)
@@ -86,6 +86,7 @@ import com.gitblit.utils.MarkdownUtils;
 import com.gitblit.utils.StringUtils;\r
 import com.gitblit.utils.TimeUtils;\r
 import com.gitblit.wicket.GitBlitWebSession;\r
+import com.gitblit.wicket.TicketsUI;\r
 import com.gitblit.wicket.WicketUtils;\r
 import com.gitblit.wicket.panels.BasePanel.JavascriptTextPrompt;\r
 import com.gitblit.wicket.panels.CommentPanel;\r
@@ -102,7 +103,7 @@ import com.gitblit.wicket.panels.SimpleAjaxLink;
  * @author James Moger\r
  *\r
  */\r
-public class TicketPage extends TicketBasePage {\r
+public class TicketPage extends RepositoryPage {\r
 \r
        static final String NIL = "<nil>";\r
 \r
@@ -154,7 +155,7 @@ public class TicketPage extends TicketBasePage {
                String href = urlFor(TicketsPage.class, params).toString();\r
                add(new ExternalLink("ticketNumber", href, "#" + ticket.number));\r
                Label headerStatus = new Label("headerStatus", ticket.status.toString());\r
-               WicketUtils.setCssClass(headerStatus, getLozengeClass(ticket.status, false));\r
+               WicketUtils.setCssClass(headerStatus, TicketsUI.getLozengeClass(ticket.status, false));\r
                add(headerStatus);\r
                add(new Label("ticketTitle", ticket.title));\r
                if (currentPatchset == null) {\r
@@ -317,10 +318,10 @@ public class TicketPage extends TicketBasePage {
                 * LARGE STATUS INDICATOR WITH ICON (DISCUSSION TAB->SIDE BAR)\r
                 */\r
                Fragment ticketStatus = new Fragment("ticketStatus", "ticketStatusFragment", this);\r
-               Label ticketIcon = getStateIcon("ticketIcon", ticket);\r
+               Label ticketIcon = TicketsUI.getStateIcon("ticketIcon", ticket);\r
                ticketStatus.add(ticketIcon);\r
                ticketStatus.add(new Label("ticketStatus", ticket.status.toString()));\r
-               WicketUtils.setCssClass(ticketStatus, getLozengeClass(ticket.status, false));\r
+               WicketUtils.setCssClass(ticketStatus, TicketsUI.getLozengeClass(ticket.status, false));\r
                add(ticketStatus);\r
 \r
 \r
@@ -370,7 +371,7 @@ public class TicketPage extends TicketBasePage {
                                                                setResponsePage(TicketsPage.class, getPageParameters());\r
                                                        }\r
                                                };\r
-                                               String css = getStatusClass(item.getModel().getObject());\r
+                                               String css = TicketsUI.getStatusClass(item.getModel().getObject());\r
                                                WicketUtils.setCssClass(link, css);\r
                                                item.add(link);\r
                                        }\r
@@ -665,7 +666,7 @@ public class TicketPage extends TicketBasePage {
                                                 */\r
                                                Fragment frag = new Fragment("entry", "statusFragment", this);\r
                                                Label status = new Label("statusChange", entry.getStatus().toString());\r
-                                               String css = getLozengeClass(entry.getStatus(), false);\r
+                                               String css = TicketsUI.getLozengeClass(entry.getStatus(), false);\r
                                                WicketUtils.setCssClass(status, css);\r
                                                for (IBehavior b : status.getBehaviors()) {\r
                                                        if (b instanceof SimpleAttributeModifier) {\r
@@ -936,7 +937,7 @@ public class TicketPage extends TicketBasePage {
                                                        case status:\r
                                                                // special handling for status\r
                                                                Status status = event.getStatus();\r
-                                                               String css = getLozengeClass(status, true);\r
+                                                               String css = TicketsUI.getLozengeClass(status, true);\r
                                                                value = String.format("<span class=\"%1$s\">%2$s</span>", css, status.toString());\r
                                                                break;\r
                                                        default:\r
@@ -1525,14 +1526,14 @@ public class TicketPage extends TicketBasePage {
                switch (type) {\r
                        case Rebase:\r
                        case Rebase_Squash:\r
-                               typeCss = getLozengeClass(Status.Declined, false);\r
+                               typeCss = TicketsUI.getLozengeClass(Status.Declined, false);\r
                                break;\r
                        case Squash:\r
                        case Amend:\r
-                               typeCss = getLozengeClass(Status.On_Hold, false);\r
+                               typeCss = TicketsUI.getLozengeClass(Status.On_Hold, false);\r
                                break;\r
                        case Proposal:\r
-                               typeCss = getLozengeClass(Status.New, false);\r
+                               typeCss = TicketsUI.getLozengeClass(Status.New, false);\r
                                break;\r
                        case FastForward:\r
                        default:\r
index a40d31264b5e1b48e5a165c12f5a76cb42c3cd7b..40060f36605617adf795d2b4db772ce5e6e86d34 100644 (file)
@@ -11,7 +11,7 @@
        <div class="hidden-phone pull-right">\r
                <form class="form-search" style="margin: 0px;" wicket:id="ticketSearchForm">\r
                        <div class="input-append">\r
-                               <input type="text" class="search-query" style="width: 170px;border-radius: 14px 0 0 14px; padding-left: 14px;" id="ticketSearchBox" wicket:id="ticketSearchBox" value=""/>\r
+                               <input type="text" class="input-medium search-query" style="border-radius: 14px 0 0 14px; padding-left: 14px;" id="ticketSearchBox" wicket:id="ticketSearchBox" value=""/>\r
                                <button class="btn" style="border-radius: 0 14px 14px 0px;margin-left:-5px;" type="submit"><i class="icon-search"></i></button>\r
                        </div>\r
                </form>\r
                                </div>\r
                        </div>\r
                \r
-               \r
-                       <table class="table tickets">                   \r
-                       <tbody>\r
-                       <tr wicket:id="ticket">\r
-                               <td class="ticket-list-icon">\r
-                                       <i wicket:id="state"></i>\r
-                               </td>\r
-                       <td>\r
-                               <span wicket:id="title">[title]</span> <span wicket:id="labels" style="font-weight: normal;color:white;"><span class="label" wicket:id="label"></span></span>\r
-                               <div class="ticket-list-details">\r
-                                       <span style="padding-right: 10px;" class="hidden-phone">\r
-                                               <wicket:message key="gb.createdBy"></wicket:message>\r
-                                               <span style="padding: 0px 2px" wicket:id="createdBy">[createdBy]</span> <span class="date" wicket:id="createDate">[create date]</span>\r
-                                       </span>\r
-                                       <span wicket:id="indicators" style="white-space:nowrap;"><i wicket:id="icon"></i> <span style="padding-right:10px;" wicket:id="count"></span></span>\r
-                               </div>\r
-                               <div class="hidden-phone" wicket:id="updated"></div>\r
-                       </td>\r
-                       <td class="ticket-list-state">\r
-                                       <span class="badge badge-info" wicket:id="votes"></span>\r
-                       </td>\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-state">\r
-                                       <div wicket:id="status"></div>\r
-                       </td>\r
-                       <td class="indicators">\r
-                               <div>                                                           \r
-                                       <b>#<span wicket:id="id">[id]</span></b>\r
-                               </div>\r
-                               <div wicket:id="responsible"></div>\r
-                       </td>\r
-                       </tr>\r
-               </tbody>\r
-                       </table>\r
+                       <div wicket:id="ticketList"></div>\r
                \r
                        <div class="btn-group pull-right">\r
                                        <div class="pagination pagination-right pagination-small">\r
        </ul>\r
 </wicket:fragment>\r
 \r
-<wicket:fragment wicket:id="updatedFragment">\r
-       <div class="ticket-list-details">\r
-               <wicket:message key="gb.updatedBy"></wicket:message>\r
-               <span style="padding: 0px 2px" wicket:id="updatedBy">[updatedBy]</span> <span class="date" wicket:id="updateDate">[update date]</span>\r
-       </div>\r
-</wicket:fragment>\r
-\r
 </wicket:extend>\r
 </body>\r
 </html>
\ No newline at end of file
index 5973d4736a6418a34f37123bebccb148ed815c7c..d88ccb6b406a1ce9f7bc5967816543442cd98ef6 100644 (file)
@@ -15,7 +15,6 @@
  */\r
 package com.gitblit.wicket.pages;\r
 \r
-import java.io.Serializable;\r
 import java.text.MessageFormat;\r
 import java.util.ArrayList;\r
 import java.util.Arrays;\r
@@ -29,17 +28,12 @@ import org.apache.wicket.Component;
 import org.apache.wicket.PageParameters;\r
 import org.apache.wicket.behavior.SimpleAttributeModifier;\r
 import org.apache.wicket.markup.html.basic.Label;\r
-import org.apache.wicket.markup.html.form.TextField;\r
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;\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
 import org.apache.wicket.markup.repeater.data.ListDataProvider;\r
-import org.apache.wicket.model.IModel;\r
-import org.apache.wicket.model.Model;\r
-import org.apache.wicket.request.target.basic.RedirectRequestTarget;\r
 \r
-import com.gitblit.Constants;\r
 import com.gitblit.Constants.AccessPermission;\r
 import com.gitblit.Keys;\r
 import com.gitblit.models.RegistrantAccessPermission;\r
@@ -56,19 +50,18 @@ import com.gitblit.tickets.TicketResponsible;
 import com.gitblit.utils.ArrayUtils;\r
 import com.gitblit.utils.StringUtils;\r
 import com.gitblit.wicket.GitBlitWebSession;\r
-import com.gitblit.wicket.SessionlessForm;\r
+import com.gitblit.wicket.TicketsUI;\r
+import com.gitblit.wicket.TicketsUI.TicketQuery;\r
+import com.gitblit.wicket.TicketsUI.TicketSort;\r
 import com.gitblit.wicket.WicketUtils;\r
-import com.gitblit.wicket.panels.GravatarImage;\r
 import com.gitblit.wicket.panels.LinkPanel;\r
+import com.gitblit.wicket.panels.TicketListPanel;\r
+import com.gitblit.wicket.panels.TicketSearchForm;\r
 \r
-public class TicketsPage extends TicketBasePage {\r
+public class TicketsPage extends RepositoryPage {\r
 \r
        final TicketResponsible any;\r
 \r
-       public static final String [] openStatii = new String [] { Status.New.name().toLowerCase(), Status.Open.name().toLowerCase() };\r
-\r
-       public static final String [] closedStatii = new String [] { "!" + Status.New.name().toLowerCase(), "!" + Status.Open.name().toLowerCase() };\r
-\r
        public TicketsPage(PageParameters params) {\r
                super(params);\r
 \r
@@ -102,11 +95,8 @@ public class TicketsPage extends TicketBasePage {
                final String sortBy = Lucene.fromString(params.getString("sort", Lucene.created.name())).name();\r
                final boolean desc = !"asc".equals(params.getString("direction", "desc"));\r
 \r
-\r
                // add search form\r
-               TicketSearchForm searchForm = new TicketSearchForm("ticketSearchForm", repositoryName, searchParam);\r
-               add(searchForm);\r
-               searchForm.setTranslatedAttributes();\r
+               add(new TicketSearchForm("ticketSearchForm", repositoryName, searchParam, getClass(), params));\r
 \r
                final String activeQuery;\r
                if (!StringUtils.isEmpty(searchParam)) {\r
@@ -192,12 +182,12 @@ public class TicketsPage extends TicketBasePage {
                        milestonePanel.add(new LinkPanel("openTickets", null,\r
                                        MessageFormat.format(getString("gb.nOpenTickets"), currentMilestone.getOpenTickets()),\r
                                        TicketsPage.class,\r
-                                       queryParameters(null, currentMilestone.name, openStatii, null, sortBy, desc, 1)));\r
+                                       queryParameters(null, currentMilestone.name, TicketsUI.openStatii, null, sortBy, desc, 1)));\r
 \r
                        milestonePanel.add(new LinkPanel("closedTickets", null,\r
                                        MessageFormat.format(getString("gb.nClosedTickets"), currentMilestone.getClosedTickets()),\r
                                        TicketsPage.class,\r
-                                       queryParameters(null, currentMilestone.name, closedStatii, null, sortBy, desc, 1)));\r
+                                       queryParameters(null, currentMilestone.name, TicketsUI.closedStatii, null, sortBy, desc, 1)));\r
 \r
                        milestonePanel.add(new Label("totalTickets", MessageFormat.format(getString("gb.nTotalTickets"), currentMilestone.getTotalTickets())));\r
                        add(milestonePanel);\r
@@ -287,7 +277,7 @@ public class TicketsPage extends TicketBasePage {
                                queryParameters(\r
                                                null,\r
                                                milestoneParam,\r
-                                               openStatii,\r
+                                               TicketsUI.openStatii,\r
                                                null,\r
                                                null,\r
                                                true,\r
@@ -397,8 +387,8 @@ public class TicketsPage extends TicketBasePage {
                } else {\r
                        add(new Label("selectedStatii", StringUtils.flattenStrings(Arrays.asList(statiiParam), ",")));\r
                }\r
-               add(new BookmarkablePageLink<Void>("openTickets", TicketsPage.class, queryParameters(queryParam, milestoneParam, openStatii, assignedToParam, sortBy, desc, 1)));\r
-               add(new BookmarkablePageLink<Void>("closedTickets", TicketsPage.class, queryParameters(queryParam, milestoneParam, closedStatii, assignedToParam, sortBy, desc, 1)));\r
+               add(new BookmarkablePageLink<Void>("openTickets", TicketsPage.class, queryParameters(queryParam, milestoneParam, TicketsUI.openStatii, assignedToParam, sortBy, desc, 1)));\r
+               add(new BookmarkablePageLink<Void>("closedTickets", TicketsPage.class, queryParameters(queryParam, milestoneParam, TicketsUI.closedStatii, assignedToParam, sortBy, desc, 1)));\r
                add(new BookmarkablePageLink<Void>("allTickets", TicketsPage.class, queryParameters(queryParam, milestoneParam, null, assignedToParam, sortBy, desc, 1)));\r
 \r
                // by status\r
@@ -412,7 +402,7 @@ public class TicketsPage extends TicketBasePage {
                        public void populateItem(final Item<Status> item) {\r
                                final Status status = item.getModelObject();\r
                                PageParameters p = queryParameters(queryParam, milestoneParam, new String [] { status.name().toLowerCase() }, assignedToParam, sortBy, desc, 1);\r
-                               String css = getStatusClass(status);\r
+                               String css = TicketsUI.getStatusClass(status);\r
                                item.add(new LinkPanel("statusLink", css, status.toString(), TicketsPage.class, p).setRenderBodyOnly(true));\r
                        }\r
                };\r
@@ -491,162 +481,7 @@ public class TicketsPage extends TicketBasePage {
                // paging links\r
                buildPager(queryParam, milestoneParam, statiiParam, assignedToParam, sortBy, desc, page, pageSize, results.size(), totalResults);\r
 \r
-               ListDataProvider<QueryResult> resultsDataProvider = new ListDataProvider<QueryResult>(results);\r
-               DataView<QueryResult> ticketsView = new DataView<QueryResult>("ticket", resultsDataProvider) {\r
-                       private static final long serialVersionUID = 1L;\r
-\r
-                       @Override\r
-                       public void populateItem(final Item<QueryResult> item) {\r
-                               final QueryResult ticket = item.getModelObject();\r
-                               item.add(getStateIcon("state", ticket.type, ticket.status));\r
-                               item.add(new Label("id", "" + ticket.number));\r
-                               UserModel creator = app().users().getUserModel(ticket.createdBy);\r
-                               if (creator != null) {\r
-                                       item.add(new LinkPanel("createdBy", null, creator.getDisplayName(),\r
-                                               UserPage.class, WicketUtils.newUsernameParameter(ticket.createdBy)));\r
-                               } else {\r
-                                       item.add(new Label("createdBy", ticket.createdBy));\r
-                               }\r
-                               item.add(WicketUtils.createDateLabel("createDate", ticket.createdAt, GitBlitWebSession\r
-                                               .get().getTimezone(), getTimeUtils(), false));\r
-\r
-                               if (ticket.updatedAt == null) {\r
-                                       item.add(new Label("updated").setVisible(false));\r
-                               } else {\r
-                                       Fragment updated = new Fragment("updated", "updatedFragment", this);\r
-                                       UserModel updater = app().users().getUserModel(ticket.updatedBy);\r
-                                       if (updater != null) {\r
-                                               updated.add(new LinkPanel("updatedBy", null, updater.getDisplayName(),\r
-                                                               UserPage.class, WicketUtils.newUsernameParameter(ticket.updatedBy)));\r
-                                       } else {\r
-                                               updated.add(new Label("updatedBy", ticket.updatedBy));\r
-                                       }\r
-                                       updated.add(WicketUtils.createDateLabel("updateDate", ticket.updatedAt, GitBlitWebSession\r
-                                                       .get().getTimezone(), getTimeUtils(), false));\r
-                                       item.add(updated);\r
-                               }\r
-\r
-                               item.add(new LinkPanel("title", "list subject", StringUtils.trimString(\r
-                                               ticket.title, Constants.LEN_SHORTLOG), TicketsPage.class, newTicketParameter(ticket)));\r
-\r
-                               ListDataProvider<String> labelsProvider = new ListDataProvider<String>(ticket.getLabels());\r
-                               DataView<String> labelsView = new DataView<String>("labels", labelsProvider) {\r
-                                       private static final long serialVersionUID = 1L;\r
-\r
-                                       @Override\r
-                                       public void populateItem(final Item<String> labelItem) {\r
-                                               String content = bugtraqProcessor().processPlainCommitMessage(getRepository(), repositoryName, labelItem.getModelObject());\r
-                                               Label label = new Label("label", content);\r
-                                               label.setEscapeModelStrings(false);\r
-                                               TicketLabel tLabel = app().tickets().getLabel(getRepositoryModel(), labelItem.getModelObject());\r
-                                               String background = MessageFormat.format("background-color:{0};", tLabel.color);\r
-                                               label.add(new SimpleAttributeModifier("style", background));\r
-                                               labelItem.add(label);\r
-                                       }\r
-                               };\r
-                               item.add(labelsView);\r
-\r
-                               if (StringUtils.isEmpty(ticket.responsible)) {\r
-                                       item.add(new Label("responsible").setVisible(false));\r
-                               } else {\r
-                                       UserModel responsible = app().users().getUserModel(ticket.responsible);\r
-                                       if (responsible == null) {\r
-                                               responsible = new UserModel(ticket.responsible);\r
-                                       }\r
-                                       GravatarImage avatar = new GravatarImage("responsible", responsible.getDisplayName(),\r
-                                                       responsible.emailAddress, null, 16, true);\r
-                                       avatar.setTooltip(getString("gb.responsible") + ": " + responsible.getDisplayName());\r
-                                       item.add(avatar);\r
-                               }\r
-\r
-                               // votes indicator\r
-                               Label v = new Label("votes", "" + ticket.votesCount);\r
-                               WicketUtils.setHtmlTooltip(v, getString("gb.votes"));\r
-                               item.add(v.setVisible(ticket.votesCount > 0));\r
-\r
-                               // watching indicator\r
-                               item.add(new Label("watching").setVisible(ticket.isWatching(GitBlitWebSession.get().getUsername())));\r
-\r
-                               // status indicator\r
-                               String css = getLozengeClass(ticket.status, true);\r
-                               Label l = new Label("status", ticket.status.toString());\r
-                               WicketUtils.setCssClass(l, css);\r
-                               item.add(l);\r
-\r
-                               // add the ticket indicators/icons\r
-                               List<Indicator> indicators = new ArrayList<Indicator>();\r
-\r
-                               // comments\r
-                               if (ticket.commentsCount > 0) {\r
-                                       int count = ticket.commentsCount;\r
-                                       String pattern = "gb.nComments";\r
-                                       if (count == 1) {\r
-                                               pattern = "gb.oneComment";\r
-                                       }\r
-                                       indicators.add(new Indicator("fa fa-comment", count, pattern));\r
-                               }\r
-\r
-                               // participants\r
-                               if (!ArrayUtils.isEmpty(ticket.participants)) {\r
-                                       int count = ticket.participants.size();\r
-                                       if (count > 1) {\r
-                                               String pattern = "gb.nParticipants";\r
-                                               indicators.add(new Indicator("fa fa-user", count, pattern));\r
-                                       }\r
-                               }\r
-\r
-                               // attachments\r
-                               if (!ArrayUtils.isEmpty(ticket.attachments)) {\r
-                                       int count = ticket.attachments.size();\r
-                                       String pattern = "gb.nAttachments";\r
-                                       if (count == 1) {\r
-                                               pattern = "gb.oneAttachment";\r
-                                       }\r
-                                       indicators.add(new Indicator("fa fa-file", count, pattern));\r
-                               }\r
-\r
-                               // patchset revisions\r
-                               if (ticket.patchset != null) {\r
-                                       int count = ticket.patchset.commits;\r
-                                       String pattern = "gb.nCommits";\r
-                                       if (count == 1) {\r
-                                               pattern = "gb.oneCommit";\r
-                                       }\r
-                                       indicators.add(new Indicator("fa fa-code", count, pattern));\r
-                               }\r
-\r
-                               // milestone\r
-                               if (!StringUtils.isEmpty(ticket.milestone)) {\r
-                                       indicators.add(new Indicator("fa fa-bullseye", ticket.milestone));\r
-                               }\r
-\r
-                               ListDataProvider<Indicator> indicatorsDp = new ListDataProvider<Indicator>(indicators);\r
-                               DataView<Indicator> indicatorsView = new DataView<Indicator>("indicators", indicatorsDp) {\r
-                                       private static final long serialVersionUID = 1L;\r
-\r
-                                       @Override\r
-                                       public void populateItem(final Item<Indicator> item) {\r
-                                               Indicator indicator = item.getModelObject();\r
-                                               String tooltip = indicator.getTooltip();\r
-\r
-                                               Label icon = new Label("icon");\r
-                                               WicketUtils.setCssClass(icon, indicator.css);\r
-                                               item.add(icon);\r
-\r
-                                               if (indicator.count > 0) {\r
-                                                       Label count = new Label("count", "" + indicator.count);\r
-                                                       item.add(count.setVisible(!StringUtils.isEmpty(tooltip)));\r
-                                               } else {\r
-                                                       item.add(new Label("count").setVisible(false));\r
-                                               }\r
-\r
-                                               WicketUtils.setHtmlTooltip(item, tooltip);\r
-                                       }\r
-                               };\r
-                               item.add(indicatorsView);\r
-                       }\r
-               };\r
-               add(ticketsView);\r
+               add(new TicketListPanel("ticketList", results, false, false));\r
 \r
                // new milestone link\r
                RepositoryModel repositoryModel = getRepositoryModel();\r
@@ -747,12 +582,12 @@ public class TicketsPage extends TicketBasePage {
                                        milestonePanel.add(new LinkPanel("openTickets", null,\r
                                                        MessageFormat.format(getString("gb.nOpenTickets"), m.getOpenTickets()),\r
                                                        TicketsPage.class,\r
-                                                       queryParameters(null, tm.name, openStatii, null, null, true, 1)));\r
+                                                       queryParameters(null, tm.name, TicketsUI.openStatii, null, null, true, 1)));\r
 \r
                                        milestonePanel.add(new LinkPanel("closedTickets", null,\r
                                                        MessageFormat.format(getString("gb.nClosedTickets"), m.getClosedTickets()),\r
                                                        TicketsPage.class,\r
-                                                       queryParameters(null, tm.name, closedStatii, null, null, true, 1)));\r
+                                                       queryParameters(null, tm.name, TicketsUI.closedStatii, null, null, true, 1)));\r
 \r
                                        milestonePanel.add(new Label("totalTickets", MessageFormat.format(getString("gb.nTotalTickets"), m.getTotalTickets())));\r
                                        entryPanel.add(milestonePanel);\r
@@ -864,123 +699,4 @@ public class TicketsPage extends TicketBasePage {
                };\r
                add(pagesView);\r
        }\r
-\r
-       private class Indicator implements Serializable {\r
-\r
-               private static final long serialVersionUID = 1L;\r
-\r
-               final String css;\r
-               final int count;\r
-               final String tooltip;\r
-\r
-               Indicator(String css, String tooltip) {\r
-                       this.css = css;\r
-                       this.tooltip = tooltip;\r
-                       this.count = 0;\r
-               }\r
-\r
-               Indicator(String css, int count, String pattern) {\r
-                       this.css = css;\r
-                       this.count = count;\r
-                       this.tooltip = StringUtils.isEmpty(pattern) ? "" : MessageFormat.format(getString(pattern), count);\r
-               }\r
-\r
-               String getTooltip() {\r
-                       return tooltip;\r
-               }\r
-       }\r
-\r
-       private class TicketQuery implements Serializable, Comparable<TicketQuery> {\r
-\r
-               private static final long serialVersionUID = 1L;\r
-\r
-               final String name;\r
-               final String query;\r
-               String color;\r
-\r
-               TicketQuery(String name, String query) {\r
-                       this.name = name;\r
-                       this.query = query;\r
-               }\r
-\r
-               TicketQuery color(String value) {\r
-                       this.color = value;\r
-                       return this;\r
-               }\r
-\r
-               @Override\r
-               public boolean equals(Object o) {\r
-                       if (o instanceof TicketQuery) {\r
-                               return ((TicketQuery) o).query.equals(query);\r
-                       }\r
-                       return false;\r
-               }\r
-\r
-               @Override\r
-               public int hashCode() {\r
-                       return query.hashCode();\r
-               }\r
-\r
-               @Override\r
-               public int compareTo(TicketQuery o) {\r
-                       return query.compareTo(o.query);\r
-               }\r
-       }\r
-\r
-       private class TicketSort implements Serializable {\r
-\r
-               private static final long serialVersionUID = 1L;\r
-\r
-               final String name;\r
-               final String sortBy;\r
-               final boolean desc;\r
-\r
-               TicketSort(String name, String sortBy, boolean desc) {\r
-                       this.name = name;\r
-                       this.sortBy = sortBy;\r
-                       this.desc = desc;\r
-               }\r
-       }\r
-\r
-       private class TicketSearchForm extends SessionlessForm<Void> implements Serializable {\r
-               private static final long serialVersionUID = 1L;\r
-\r
-               private final String repositoryName;\r
-\r
-               private final IModel<String> searchBoxModel;;\r
-\r
-               public TicketSearchForm(String id, String repositoryName, String text) {\r
-                       super(id, TicketsPage.this.getClass(), TicketsPage.this.getPageParameters());\r
-\r
-                       this.repositoryName = repositoryName;\r
-                       this.searchBoxModel = new Model<String>(text == null ? "" : text);\r
-\r
-                       TextField<String> searchBox = new TextField<String>("ticketSearchBox", searchBoxModel);\r
-                       add(searchBox);\r
-               }\r
-\r
-               void setTranslatedAttributes() {\r
-                       WicketUtils.setHtmlTooltip(get("ticketSearchBox"),\r
-                                       MessageFormat.format(getString("gb.searchTicketsTooltip"), repositoryName));\r
-                       WicketUtils.setInputPlaceholder(get("ticketSearchBox"), getString("gb.searchTickets"));\r
-               }\r
-\r
-               @Override\r
-               public void onSubmit() {\r
-                       String searchString = searchBoxModel.getObject();\r
-                       if (StringUtils.isEmpty(searchString)) {\r
-                               // redirect to self to avoid wicket page update bug\r
-                               String absoluteUrl = getCanonicalUrl();\r
-                               getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));\r
-                               return;\r
-                       }\r
-\r
-                       // use an absolute url to workaround Wicket-Tomcat problems with\r
-                       // mounted url parameters (issue-111)\r
-                       PageParameters params = WicketUtils.newRepositoryParameter(repositoryName);\r
-                       params.add("s", searchString);\r
-                       String absoluteUrl = getCanonicalUrl(TicketsPage.class, params);\r
-                       getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));\r
-               }\r
-       }\r
 }\r
diff --git a/src/main/java/com/gitblit/wicket/panels/TicketListPanel.html b/src/main/java/com/gitblit/wicket/panels/TicketListPanel.html
new file mode 100644 (file)
index 0000000..6e6d209
--- /dev/null
@@ -0,0 +1,55 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml"  \r
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"  \r
+      xml:lang="en"  \r
+      lang="en"> \r
+\r
+<body>\r
+<wicket:panel>\r
+<table class="table tickets">  \r
+       <tbody>\r
+               <tr wicket:id="row">\r
+                       <td class="ticket-list-icon">\r
+                               <i wicket:id="state"></i>\r
+                       </td>\r
+               <td>\r
+                       <span wicket:id="title">[title]</span> <span wicket:id="labels" style="font-weight: normal;color:white;"><span class="label" wicket:id="label"></span></span>\r
+                       <div class="ticket-list-details">\r
+                               <span style="padding-right: 10px;" class="hidden-phone">\r
+                                       <wicket:message key="gb.createdBy"></wicket:message>\r
+                                       <span style="padding: 0px 2px" wicket:id="createdBy">[createdBy]</span> <span class="date" wicket:id="createDate">[create date]</span>\r
+                               </span>\r
+                               <span wicket:id="indicators" style="white-space:nowrap;"><i wicket:id="icon"></i> <span style="padding-right:10px;" wicket:id="count"></span></span>\r
+                       </div>\r
+                       <div class="hidden-phone" wicket:id="updated"></div>\r
+                       <div class="ticket-list-details"><span class="activitySwatch" wicket:id="repositoryLink">[repository link]</span></div>\r
+               </td>\r
+               <td class="ticket-list-state">\r
+                               <span class="badge badge-info" wicket:id="votes"></span>\r
+               </td>\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-state">\r
+                               <div wicket:id="status"></div>\r
+               </td>\r
+               <td class="indicators">\r
+                       <div>                                                           \r
+                                       <b>#<span wicket:id="id">[id]</span></b>\r
+                               </div>\r
+                       <div wicket:id="responsible"></div>\r
+               </td>\r
+               </tr>\r
+    </tbody>\r
+</table>\r
+\r
+<wicket:fragment wicket:id="updatedFragment">\r
+       <div class="ticket-list-details">\r
+               <wicket:message key="gb.updatedBy"></wicket:message>\r
+               <span style="padding: 0px 2px" wicket:id="updatedBy">[updatedBy]</span> <span class="date" wicket:id="updateDate">[update date]</span>\r
+       </div>\r
+</wicket:fragment>\r
+\r
+</wicket:panel>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/panels/TicketListPanel.java b/src/main/java/com/gitblit/wicket/panels/TicketListPanel.java
new file mode 100644 (file)
index 0000000..fc0431f
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * 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.wicket.panels;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.behavior.SimpleAttributeModifier;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.data.DataView;
+import org.apache.wicket.markup.repeater.data.ListDataProvider;
+import org.eclipse.jgit.lib.Repository;
+
+import com.gitblit.Constants;
+import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.UserModel;
+import com.gitblit.tickets.QueryResult;
+import com.gitblit.tickets.TicketLabel;
+import com.gitblit.utils.ArrayUtils;
+import com.gitblit.utils.BugtraqProcessor;
+import com.gitblit.utils.StringUtils;
+import com.gitblit.wicket.GitBlitWebSession;
+import com.gitblit.wicket.TicketsUI;
+import com.gitblit.wicket.TicketsUI.Indicator;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.pages.SummaryPage;
+import com.gitblit.wicket.pages.TicketsPage;
+import com.gitblit.wicket.pages.UserPage;
+
+/**
+ *
+ * The ticket list panel lists tickets in a table.
+ *
+ * @author James Moger
+ *
+ */
+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);
+
+               final ListDataProvider<QueryResult> dp = new ListDataProvider<QueryResult>(list);
+               DataView<QueryResult> dataView = new DataView<QueryResult>("row", dp) {
+                       private static final long serialVersionUID = 1L;
+
+                       @Override
+                       protected void populateItem(Item<QueryResult> item) {
+                               final QueryResult ticket = item.getModelObject();
+                               final RepositoryModel repository = app().repositories().getRepositoryModel(ticket.repository);
+
+                               if (showSwatch) {
+                                       // set repository color
+                                       String color = StringUtils.getColor(StringUtils.stripDotGit(repository.name));
+                                       WicketUtils.setCssStyle(item, MessageFormat.format("border-left: 2px solid {0};", color));
+                               }
+
+                               PageParameters rp = WicketUtils.newRepositoryParameter(ticket.repository);
+                               PageParameters tp = WicketUtils.newObjectParameter(ticket.repository, "" + ticket.number);
+
+                               if (showRepository) {
+                                       String name = StringUtils.stripDotGit(ticket.repository);
+                                       LinkPanel link = new LinkPanel("repositoryLink", null, name, SummaryPage.class, rp);
+                                       WicketUtils.setCssBackground(link, name);
+                                       item.add(link);
+                               } else {
+                                       item.add(new Label("repositoryLink").setVisible(false));
+                               }
+
+                               item.add(TicketsUI.getStateIcon("state", ticket.type, ticket.status));
+                               item.add(new Label("id", "" + ticket.number));
+                               UserModel creator = app().users().getUserModel(ticket.createdBy);
+                               if (creator != null) {
+                                       item.add(new LinkPanel("createdBy", null, creator.getDisplayName(),
+                                                       UserPage.class, WicketUtils.newUsernameParameter(ticket.createdBy)));
+                               } else {
+                                       item.add(new Label("createdBy", ticket.createdBy));
+                               }
+                               item.add(WicketUtils.createDateLabel("createDate", ticket.createdAt, GitBlitWebSession
+                                               .get().getTimezone(), getTimeUtils(), false));
+
+                               if (ticket.updatedAt == null) {
+                                       item.add(new Label("updated").setVisible(false));
+                               } else {
+                                       Fragment updated = new Fragment("updated", "updatedFragment", this);
+                                       UserModel updater = app().users().getUserModel(ticket.updatedBy);
+                                       if (updater != null) {
+                                               updated.add(new LinkPanel("updatedBy", null, updater.getDisplayName(),
+                                                               UserPage.class, WicketUtils.newUsernameParameter(ticket.updatedBy)));
+                                       } else {
+                                               updated.add(new Label("updatedBy", ticket.updatedBy));
+                                       }
+                                       updated.add(WicketUtils.createDateLabel("updateDate", ticket.updatedAt, GitBlitWebSession
+                                                       .get().getTimezone(), getTimeUtils(), false));
+                                       item.add(updated);
+                               }
+
+                               item.add(new LinkPanel("title", "list subject", StringUtils.trimString(
+                                               ticket.title, Constants.LEN_SHORTLOG), TicketsPage.class, tp));
+
+                               ListDataProvider<String> labelsProvider = new ListDataProvider<String>(ticket.getLabels());
+                               DataView<String> labelsView = new DataView<String>("labels", labelsProvider) {
+                                       private static final long serialVersionUID = 1L;
+
+                                       @Override
+                                       public void populateItem(final Item<String> labelItem) {
+                                               BugtraqProcessor btp  = new BugtraqProcessor(app().settings());
+                                               Repository db = app().repositories().getRepository(repository.name);
+                                               String content = btp.processPlainCommitMessage(db, repository.name, labelItem.getModelObject());
+                                               db.close();
+                                               Label label = new Label("label", content);
+                                               label.setEscapeModelStrings(false);
+                                               TicketLabel tLabel = app().tickets().getLabel(repository, labelItem.getModelObject());
+                                               String background = MessageFormat.format("background-color:{0};", tLabel.color);
+                                               label.add(new SimpleAttributeModifier("style", background));
+                                               labelItem.add(label);
+                                       }
+                               };
+                               item.add(labelsView);
+
+                               if (StringUtils.isEmpty(ticket.responsible)) {
+                                       item.add(new Label("responsible").setVisible(false));
+                               } else {
+                                       UserModel responsible = app().users().getUserModel(ticket.responsible);
+                                       if (responsible == null) {
+                                               responsible = new UserModel(ticket.responsible);
+                                       }
+                                       GravatarImage avatar = new GravatarImage("responsible", responsible.getDisplayName(),
+                                                       responsible.emailAddress, null, 16, true);
+                                       avatar.setTooltip(getString("gb.responsible") + ": " + responsible.getDisplayName());
+                                       item.add(avatar);
+                               }
+
+                               // votes indicator
+                               Label v = new Label("votes", "" + ticket.votesCount);
+                               WicketUtils.setHtmlTooltip(v, getString("gb.votes"));
+                               item.add(v.setVisible(ticket.votesCount > 0));
+
+                               // watching indicator
+                               item.add(new Label("watching").setVisible(ticket.isWatching(GitBlitWebSession.get().getUsername())));
+
+                               // status indicator
+                               String css = TicketsUI.getLozengeClass(ticket.status, true);
+                               Label l = new Label("status", ticket.status.toString());
+                               WicketUtils.setCssClass(l, css);
+                               item.add(l);
+
+                               // add the ticket indicators/icons
+                               List<Indicator> indicators = new ArrayList<Indicator>();
+
+                               // comments
+                               if (ticket.commentsCount > 0) {
+                                       int count = ticket.commentsCount;
+                                       String pattern = getString("gb.nComments");
+                                       if (count == 1) {
+                                               pattern = getString("gb.oneComment");
+                                       }
+                                       indicators.add(new Indicator("fa fa-comment", count, pattern));
+                               }
+
+                               // participants
+                               if (!ArrayUtils.isEmpty(ticket.participants)) {
+                                       int count = ticket.participants.size();
+                                       if (count > 1) {
+                                               String pattern = getString("gb.nParticipants");
+                                               indicators.add(new Indicator("fa fa-user", count, pattern));
+                                       }
+                               }
+
+                               // attachments
+                               if (!ArrayUtils.isEmpty(ticket.attachments)) {
+                                       int count = ticket.attachments.size();
+                                       String pattern = getString("gb.nAttachments");
+                                       if (count == 1) {
+                                               pattern = getString("gb.oneAttachment");
+                                       }
+                                       indicators.add(new Indicator("fa fa-file", count, pattern));
+                               }
+
+                               // patchset revisions
+                               if (ticket.patchset != null) {
+                                       int count = ticket.patchset.commits;
+                                       String pattern = getString("gb.nCommits");
+                                       if (count == 1) {
+                                               pattern = getString("gb.oneCommit");
+                                       }
+                                       indicators.add(new Indicator("fa fa-code", count, pattern));
+                               }
+
+                               // milestone
+                               if (!StringUtils.isEmpty(ticket.milestone)) {
+                                       indicators.add(new Indicator("fa fa-bullseye", ticket.milestone));
+                               }
+
+                               ListDataProvider<Indicator> indicatorsDp = new ListDataProvider<Indicator>(indicators);
+                               DataView<Indicator> indicatorsView = new DataView<Indicator>("indicators", indicatorsDp) {
+                                       private static final long serialVersionUID = 1L;
+
+                                       @Override
+                                       public void populateItem(final Item<Indicator> item) {
+                                               Indicator indicator = item.getModelObject();
+                                               String tooltip = indicator.getTooltip();
+
+                                               Label icon = new Label("icon");
+                                               WicketUtils.setCssClass(icon, indicator.css);
+                                               item.add(icon);
+
+                                               if (indicator.count > 0) {
+                                                       Label count = new Label("count", "" + indicator.count);
+                                                       item.add(count.setVisible(!StringUtils.isEmpty(tooltip)));
+                                               } else {
+                                                       item.add(new Label("count").setVisible(false));
+                                               }
+
+                                               WicketUtils.setHtmlTooltip(item, tooltip);
+                                       }
+                               };
+                               item.add(indicatorsView);
+                       }
+               };
+
+               add(dataView);
+       }
+}
+
diff --git a/src/main/java/com/gitblit/wicket/panels/TicketSearchForm.java b/src/main/java/com/gitblit/wicket/panels/TicketSearchForm.java
new file mode 100644 (file)
index 0000000..21bf1ba
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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.wicket.panels;
+
+import java.io.Serializable;
+import java.text.MessageFormat;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.request.target.basic.RedirectRequestTarget;
+
+import com.gitblit.utils.StringUtils;
+import com.gitblit.wicket.SessionlessForm;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.pages.BasePage;
+
+public class TicketSearchForm extends SessionlessForm<Void> implements Serializable {
+
+       private static final long serialVersionUID = 1L;
+
+       private final String repositoryName;
+
+       private final IModel<String> searchBoxModel;
+
+       public TicketSearchForm(String id, String repositoryName, String text,
+                       Class<? extends BasePage> pageClass, PageParameters params) {
+
+               super(id, pageClass, params);
+
+               this.repositoryName = repositoryName;
+               this.searchBoxModel = new Model<String>(text == null ? "" : text);
+
+               TextField<String> searchBox = new TextField<String>("ticketSearchBox", searchBoxModel);
+               add(searchBox);
+       }
+
+       @Override
+       protected
+       void onInitialize() {
+               super.onInitialize();
+               WicketUtils.setHtmlTooltip(get("ticketSearchBox"),
+                               MessageFormat.format(getString("gb.searchTicketsTooltip"), ""));
+               WicketUtils.setInputPlaceholder(get("ticketSearchBox"), getString("gb.searchTickets"));
+       }
+
+       @Override
+       public void onSubmit() {
+               String searchString = searchBoxModel.getObject();
+               if (StringUtils.isEmpty(searchString)) {
+                       // redirect to self to avoid wicket page update bug
+                       String absoluteUrl = getAbsoluteUrl();
+                       getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
+                       return;
+               }
+
+               // use an absolute url to workaround Wicket-Tomcat problems with
+               // mounted url parameters (issue-111)
+               PageParameters params = WicketUtils.newRepositoryParameter(repositoryName);
+               params.add("s", searchString);
+               String absoluteUrl = getAbsoluteUrl(pageClass, params);
+               getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
+       }
+}
diff --git a/src/main/java/com/gitblit/wicket/panels/UserTitlePanel.html b/src/main/java/com/gitblit/wicket/panels/UserTitlePanel.html
new file mode 100644 (file)
index 0000000..432c880
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml"  \r
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"  \r
+      xml:lang="en"  \r
+      lang="en"> \r
+\r
+<body>\r
+<wicket:panel>\r
+<div style="display:inline-block;vertical-align:top;padding: 0px 2px 2px;"><img wicket:id="userGravatar"></img></div>\r
+       <div style="display:inline-block;">\r
+       <div style="font-size:1.5em;" wicket:id="userDisplayName"></div>\r
+       <div style="color:#888;font-size:1.2em;padding-top:4px;"><span wicket:id="userTitle"></span></div>\r
+</div>\r
+</wicket:panel>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/panels/UserTitlePanel.java b/src/main/java/com/gitblit/wicket/panels/UserTitlePanel.java
new file mode 100644 (file)
index 0000000..2bf5ee7
--- /dev/null
@@ -0,0 +1,32 @@
+/*\r
+ * Copyright 2014 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.wicket.panels;\r
+\r
+import org.apache.wicket.markup.html.basic.Label;\r
+\r
+import com.gitblit.models.UserModel;\r
+\r
+public class UserTitlePanel extends BasePanel {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       public UserTitlePanel(String wicketId, UserModel user, String title) {\r
+               super(wicketId);\r
+               add(new GravatarImage("userGravatar", user, "gravatar", 36, false));\r
+               add(new Label("userDisplayName", user.getDisplayName()));\r
+               add(new Label("userTitle", title));\r
+       }\r
+}\r