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
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;
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);
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;
+ }
}
--- /dev/null
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.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);
+ }
+ }
+}
\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
<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
+/*
+ * 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);
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,
queryParameters(
null,
milestoneParam,
- openStatii,
+ TicketsUI.openStatii,
null,
null,
true,
} 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
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));
}
};
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(
};
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;
- }
- }
}
<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
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
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));
+++ /dev/null
-/*\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
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
* @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
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
* 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
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
*/\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
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
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
<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
*/\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
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
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
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
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
queryParameters(\r
null,\r
milestoneParam,\r
- openStatii,\r
+ TicketsUI.openStatii,\r
null,\r
null,\r
true,\r
} 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
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
// 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
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
};\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
--- /dev/null
+<!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
--- /dev/null
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.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);
+ }
+}
+
--- /dev/null
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.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));
+ }
+}
--- /dev/null
+<!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
--- /dev/null
+/*\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