From ce048e750f7ae986dddfc8ab9b57750114d2b7b9 Mon Sep 17 00:00:00 2001 From: James Moger Date: Fri, 25 Apr 2014 23:52:30 -0400 Subject: Create and update milestone pages with rename support --- .../java/com/gitblit/tickets/ITicketService.java | 31 +++- src/main/java/com/gitblit/tickets/TicketLabel.java | 7 +- .../java/com/gitblit/tickets/TicketMilestone.java | 4 + .../java/com/gitblit/wicket/GitBlitWebApp.java | 4 + .../com/gitblit/wicket/GitBlitWebApp.properties | 4 +- .../gitblit/wicket/pages/EditMilestonePage.html | 38 +++++ .../gitblit/wicket/pages/EditMilestonePage.java | 166 +++++++++++++++++++++ .../com/gitblit/wicket/pages/NewMilestonePage.html | 37 +++++ .../com/gitblit/wicket/pages/NewMilestonePage.java | 123 +++++++++++++++ .../java/com/gitblit/wicket/pages/TicketsPage.html | 5 +- .../java/com/gitblit/wicket/pages/TicketsPage.java | 21 ++- 11 files changed, 430 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html create mode 100644 src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java create mode 100644 src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html create mode 100644 src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java (limited to 'src') diff --git a/src/main/java/com/gitblit/tickets/ITicketService.java b/src/main/java/com/gitblit/tickets/ITicketService.java index c2f3283e..e1a377a6 100644 --- a/src/main/java/com/gitblit/tickets/ITicketService.java +++ b/src/main/java/com/gitblit/tickets/ITicketService.java @@ -49,6 +49,7 @@ import com.gitblit.models.TicketModel.Field; import com.gitblit.models.TicketModel.Patchset; import com.gitblit.models.TicketModel.Status; import com.gitblit.tickets.TicketIndexer.Lucene; +import com.gitblit.utils.DeepCopier; import com.gitblit.utils.DiffUtils; import com.gitblit.utils.DiffUtils.DiffStat; import com.gitblit.utils.StringUtils; @@ -556,9 +557,10 @@ public abstract class ITicketService { public TicketMilestone getMilestone(RepositoryModel repository, String milestone) { for (TicketMilestone ms : getMilestones(repository)) { if (ms.name.equalsIgnoreCase(milestone)) { + TicketMilestone tm = DeepCopier.copy(ms); String q = QueryBuilder.q(Lucene.rid.matches(repository.getRID())).and(Lucene.milestone.matches(milestone)).build(); - ms.tickets = indexer.queryFor(q, 1, 0, Lucene.number.name(), true); - return ms; + tm.tickets = indexer.queryFor(q, 1, 0, Lucene.number.name(), true); + return tm; } } return null; @@ -639,6 +641,21 @@ public abstract class ITicketService { * @since 1.4.0 */ public synchronized boolean renameMilestone(RepositoryModel repository, String oldName, String newName, String createdBy) { + return renameMilestone(repository, oldName, newName, createdBy, true); + } + + /** + * Renames a milestone. + * + * @param repository + * @param oldName + * @param newName + * @param createdBy + * @param send ticket notifications + * @return true if successful + * @since 1.6.0 + */ + public synchronized boolean renameMilestone(RepositoryModel repository, String oldName, String newName, String createdBy, boolean notify) { if (StringUtils.isEmpty(newName)) { throw new IllegalArgumentException("new milestone can not be empty!"); } @@ -651,7 +668,7 @@ public abstract class ITicketService { config.setString(MILESTONE, newName, STATUS, milestone.status.name()); config.setString(MILESTONE, newName, COLOR, milestone.color); if (milestone.due != null) { - config.setString(MILESTONE, milestone.name, DUE, + config.setString(MILESTONE, newName, DUE, new SimpleDateFormat(DUE_DATE_PATTERN).format(milestone.due)); } config.save(); @@ -663,9 +680,13 @@ public abstract class ITicketService { Change change = new Change(createdBy); change.setField(Field.milestone, newName); TicketModel ticket = updateTicket(repository, qr.number, change); - notifier.queueMailing(ticket); + if (notify && ticket.isOpen()) { + notifier.queueMailing(ticket); + } + } + if (notify) { + notifier.sendAll(); } - notifier.sendAll(); return true; } catch (IOException e) { diff --git a/src/main/java/com/gitblit/tickets/TicketLabel.java b/src/main/java/com/gitblit/tickets/TicketLabel.java index 686ce88b..a7f0ebec 100644 --- a/src/main/java/com/gitblit/tickets/TicketLabel.java +++ b/src/main/java/com/gitblit/tickets/TicketLabel.java @@ -30,14 +30,17 @@ public class TicketLabel implements Serializable { private static final long serialVersionUID = 1L; - public final String name; + public String name; public String color; public List tickets; - public TicketLabel(String name) { + setName(name); + } + + public void setName(String name) { this.name = name; this.color = StringUtils.getColor(name); } diff --git a/src/main/java/com/gitblit/tickets/TicketMilestone.java b/src/main/java/com/gitblit/tickets/TicketMilestone.java index c6b4fcca..680615a9 100644 --- a/src/main/java/com/gitblit/tickets/TicketMilestone.java +++ b/src/main/java/com/gitblit/tickets/TicketMilestone.java @@ -37,6 +37,10 @@ public class TicketMilestone extends TicketLabel { super(name); status = Status.Open; } + + public void setDue(Date due) { + this.due = due; + } public int getProgress() { int total = getTotalTickets(); diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java index c4fdeda5..d4c1bc40 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java @@ -51,6 +51,7 @@ import com.gitblit.wicket.pages.CommitPage; import com.gitblit.wicket.pages.ComparePage; import com.gitblit.wicket.pages.DocPage; import com.gitblit.wicket.pages.DocsPage; +import com.gitblit.wicket.pages.EditMilestonePage; import com.gitblit.wicket.pages.EditTicketPage; import com.gitblit.wicket.pages.ExportTicketPage; import com.gitblit.wicket.pages.FederationRegistrationPage; @@ -63,6 +64,7 @@ import com.gitblit.wicket.pages.LogoutPage; import com.gitblit.wicket.pages.LuceneSearchPage; import com.gitblit.wicket.pages.MetricsPage; import com.gitblit.wicket.pages.MyDashboardPage; +import com.gitblit.wicket.pages.NewMilestonePage; import com.gitblit.wicket.pages.NewTicketPage; import com.gitblit.wicket.pages.OverviewPage; import com.gitblit.wicket.pages.PatchPage; @@ -187,6 +189,8 @@ public class GitBlitWebApp extends WebApplication { mount("/tickets/new", NewTicketPage.class, "r"); mount("/tickets/edit", EditTicketPage.class, "r", "h"); mount("/tickets/export", ExportTicketPage.class, "r", "h"); + mount("/milestones/new", NewMilestonePage.class, "r"); + mount("/milestones/edit", EditMilestonePage.class, "r", "h"); // setup the markup document urls mount("/docs", DocsPage.class, "r"); diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index aeb2d9ef..ce4c0b22 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -671,4 +671,6 @@ gb.serverDoesNotAcceptPatchsets = This server does not accept patchsets. 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. \ No newline at end of file +gb.youDoNotHaveClonePermission = You are not permitted to clone this repository. +gb.newMilestone = new milestone +gb.editMilestone = edit milestone \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html new file mode 100644 index 00000000..66b47848 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html @@ -0,0 +1,38 @@ + + + + + + +
+ +
+ +
+ +
+
+
+ + + + + +
*
+
+
+ +
+
+
 
+
+
+
+
+ + +
+ \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java new file mode 100644 index 00000000..44077884 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java @@ -0,0 +1,166 @@ +/* + * 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.util.Arrays; +import java.util.Date; +import java.util.List; + +import org.apache.wicket.PageParameters; +import org.apache.wicket.RestartResponseException; +import org.apache.wicket.extensions.markup.html.form.DateTextField; +import org.apache.wicket.markup.html.form.Button; +import org.apache.wicket.markup.html.form.DropDownChoice; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.form.TextField; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.parboiled.common.StringUtils; + +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.TicketModel; +import com.gitblit.models.TicketModel.Status; +import com.gitblit.models.UserModel; +import com.gitblit.tickets.TicketMilestone; +import com.gitblit.wicket.GitBlitWebSession; +import com.gitblit.wicket.WicketUtils; + +/** + * Page for creating a new milestone. + * + * @author James Moger + * + */ +public class EditMilestonePage extends RepositoryPage { + + private final String oldName; + + private IModel nameModel; + + private IModel dueModel; + + private IModel statusModel; + + private IModel notificationModel; + + public EditMilestonePage(PageParameters params) { + super(params); + + RepositoryModel model = getRepositoryModel(); + if (!app().tickets().isAcceptingTicketUpdates(model)) { + // ticket service is read-only + throw new RestartResponseException(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)); + } + + UserModel currentUser = GitBlitWebSession.get().getUser(); + if (currentUser == null) { + currentUser = UserModel.ANONYMOUS; + } + + if (!currentUser.isAuthenticated || !currentUser.canAdmin(model)) { + // administration prohibited + throw new RestartResponseException(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)); + } + + oldName = WicketUtils.getObject(params); + if (StringUtils.isEmpty(oldName)) { + // milestone not specified + throw new RestartResponseException(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)); + } + + TicketMilestone tm = app().tickets().getMilestone(getRepositoryModel(), oldName); + if (tm == null) { + // milestone does not exist + throw new RestartResponseException(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)); + } + + setStatelessHint(false); + setOutputMarkupId(true); + + Form form = new Form("editForm") { + + private static final long serialVersionUID = 1L; + + @Override + protected void onSubmit() { + + String name = nameModel.getObject(); + if (StringUtils.isEmpty(name)) { + return; + } + + Date due = dueModel.getObject(); + Status status = statusModel.getObject(); + boolean rename = !name.equals(oldName); + boolean notify = notificationModel.getObject(); + + UserModel currentUser = GitBlitWebSession.get().getUser(); + String createdBy = currentUser.username; + + TicketMilestone tm = app().tickets().getMilestone(getRepositoryModel(), oldName); + tm.setName(name); + tm.setDue(due); + tm.status = status; + + boolean success = true; + if (rename) { + success = app().tickets().renameMilestone(getRepositoryModel(), oldName, name, createdBy, notify); + } + + if (success && app().tickets().updateMilestone(getRepositoryModel(), tm, createdBy)) { + setResponsePage(TicketsPage.class, WicketUtils.newRepositoryParameter(getRepositoryModel().name)); + } else { + // TODO error + } + } + }; + add(form); + + nameModel = Model.of(tm.name); + dueModel = Model.of(tm.due); + statusModel = Model.of(tm.status); + notificationModel = Model.of(true); + + form.add(new TextField("name", nameModel)); + form.add(new DateTextField("due", dueModel, "yyyy-MM-dd")); + + List statusChoices = Arrays.asList(Status.Open, Status.Closed); + form.add(new DropDownChoice("status", statusModel, statusChoices)); + + form.add(new Button("save")); + Button cancel = new Button("cancel") { + private static final long serialVersionUID = 1L; + + @Override + public void onSubmit() { + setResponsePage(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)); + } + }; + cancel.setDefaultFormProcessing(false); + form.add(cancel); + + } + + @Override + protected String getPageName() { + return getString("gb.editMilestone"); + } + + @Override + protected Class getRepoNavPageClass() { + return TicketsPage.class; + } +} diff --git a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html new file mode 100644 index 00000000..1b7e11ae --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html @@ -0,0 +1,37 @@ + + + + + + +
+ +
+ +
+ +
+
+
+ + + + +
+
+
+ +
+
+
 
+
+
+
+
+ + +
+ \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java new file mode 100644 index 00000000..2c95f018 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java @@ -0,0 +1,123 @@ +/* + * 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.util.Date; + +import org.apache.wicket.PageParameters; +import org.apache.wicket.RestartResponseException; +import org.apache.wicket.extensions.markup.html.form.DateTextField; +import org.apache.wicket.markup.html.form.Button; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.form.TextField; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; + +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.UserModel; +import com.gitblit.tickets.TicketMilestone; +import com.gitblit.wicket.GitBlitWebSession; +import com.gitblit.wicket.WicketUtils; + +/** + * Page for creating a new milestone. + * + * @author James Moger + * + */ +public class NewMilestonePage extends RepositoryPage { + + private IModel nameModel; + + private IModel dueModel; + + public NewMilestonePage(PageParameters params) { + super(params); + + RepositoryModel model = getRepositoryModel(); + if (!app().tickets().isAcceptingTicketUpdates(model)) { + // ticket service is read-only + throw new RestartResponseException(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)); + } + + UserModel currentUser = GitBlitWebSession.get().getUser(); + if (currentUser == null) { + currentUser = UserModel.ANONYMOUS; + } + + if (!currentUser.isAuthenticated || !currentUser.canAdmin(model)) { + // administration prohibited + throw new RestartResponseException(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)); + } + + setStatelessHint(false); + setOutputMarkupId(true); + + Form form = new Form("editForm") { + + private static final long serialVersionUID = 1L; + + @Override + protected void onSubmit() { + + String name = nameModel.getObject(); + Date due = dueModel.getObject(); + + UserModel currentUser = GitBlitWebSession.get().getUser(); + String createdBy = currentUser.username; + + TicketMilestone milestone = app().tickets().createMilestone(getRepositoryModel(), name, createdBy); + if (milestone != null) { + milestone.due = due; + app().tickets().updateMilestone(getRepositoryModel(), milestone, createdBy); + throw new RestartResponseException(TicketsPage.class, WicketUtils.newRepositoryParameter(getRepositoryModel().name)); + } else { + // TODO error + } + } + }; + add(form); + + nameModel = Model.of(""); + dueModel = Model.of(new Date()); + + form.add(new TextField("name", nameModel)); + form.add(new DateTextField("due", dueModel, "yyyy-MM-dd")); + + form.add(new Button("create")); + Button cancel = new Button("cancel") { + private static final long serialVersionUID = 1L; + + @Override + public void onSubmit() { + setResponsePage(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)); + } + }; + cancel.setDefaultFormProcessing(false); + form.add(cancel); + + } + + @Override + protected String getPageName() { + return getString("gb.newMilestone"); + } + + @Override + protected Class getRepoNavPageClass() { + return TicketsPage.class; + } +} diff --git a/src/main/java/com/gitblit/wicket/pages/TicketsPage.html b/src/main/java/com/gitblit/wicket/pages/TicketsPage.html index 7d13852b..e144bea1 100644 --- a/src/main/java/com/gitblit/wicket/pages/TicketsPage.html +++ b/src/main/java/com/gitblit/wicket/pages/TicketsPage.html @@ -138,10 +138,13 @@
+
+ +

- +
diff --git a/src/main/java/com/gitblit/wicket/pages/TicketsPage.java b/src/main/java/com/gitblit/wicket/pages/TicketsPage.java index ca509e28..984b3754 100644 --- a/src/main/java/com/gitblit/wicket/pages/TicketsPage.java +++ b/src/main/java/com/gitblit/wicket/pages/TicketsPage.java @@ -42,6 +42,7 @@ import com.gitblit.Constants; import com.gitblit.Constants.AccessPermission; import com.gitblit.Keys; import com.gitblit.models.RegistrantAccessPermission; +import com.gitblit.models.RepositoryModel; import com.gitblit.models.TicketModel; import com.gitblit.models.TicketModel.Status; import com.gitblit.models.UserModel; @@ -646,7 +647,19 @@ public class TicketsPage extends TicketBasePage { }; add(ticketsView); - List allMilestones = app().tickets().getMilestones(getRepositoryModel()); + // new milestone link + RepositoryModel repositoryModel = getRepositoryModel(); + final boolean acceptingUpdates = app().tickets().isAcceptingTicketUpdates(repositoryModel) + && user != null && user.canAdmin(getRepositoryModel()); + if (acceptingUpdates) { + add(new LinkPanel("newMilestone", null, getString("gb.newMilestone"), + NewMilestonePage.class, WicketUtils.newRepositoryParameter(repositoryName))); + } else { + add(new Label("newMilestone").setVisible(false)); + } + + // milestones list + List allMilestones = app().tickets().getMilestones(repositoryModel); ListDataProvider allMilestonesDp = new ListDataProvider(allMilestones); DataView milestonesList = new DataView("milestoneList", allMilestonesDp) { private static final long serialVersionUID = 1L; @@ -675,6 +688,12 @@ public class TicketsPage extends TicketBasePage { } else { item.add(WicketUtils.createDatestampLabel("milestoneDue", tm.due, getTimeZone(), getTimeUtils())); } + if (acceptingUpdates) { + item.add(new LinkPanel("editMilestone", null, getString("gb.edit"), EditMilestonePage.class, + WicketUtils.newObjectParameter(repositoryName, tm.name))); + } else { + item.add(new Label("editMilestone").setVisible(false)); + } } }; add(milestonesList); -- cgit v1.2.3 From 01995873731e7efa517ca66246547b3084f8d529 Mon Sep 17 00:00:00 2001 From: James Moger Date: Sat, 26 Apr 2014 13:51:39 -0400 Subject: Allow milestone deletion within the edit milestone page --- .../java/com/gitblit/tickets/ITicketService.java | 11 +++++- src/main/java/com/gitblit/tickets/QueryResult.java | 8 ++++ .../gitblit/wicket/pages/EditMilestonePage.html | 2 +- .../gitblit/wicket/pages/EditMilestonePage.java | 45 +++++++++++++++------- .../com/gitblit/wicket/pages/NewMilestonePage.java | 18 ++++++--- 5 files changed, 62 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/tickets/ITicketService.java b/src/main/java/com/gitblit/tickets/ITicketService.java index e1a377a6..cce805ed 100644 --- a/src/main/java/com/gitblit/tickets/ITicketService.java +++ b/src/main/java/com/gitblit/tickets/ITicketService.java @@ -643,7 +643,7 @@ public abstract class ITicketService { public synchronized boolean renameMilestone(RepositoryModel repository, String oldName, String newName, String createdBy) { return renameMilestone(repository, oldName, newName, createdBy, true); } - + /** * Renames a milestone. * @@ -714,6 +714,7 @@ public abstract class ITicketService { } Repository db = null; try { + TicketMilestone tm = getMilestone(repository, milestone); db = repositoryManager.getRepository(repository.name); StoredConfig config = db.getConfig(); config.unsetSection(MILESTONE, milestone); @@ -721,6 +722,14 @@ public abstract class ITicketService { milestonesCache.remove(repository.name); + for (QueryResult qr : tm.tickets) { + if (qr.isOpen()) { + // reset the milestone only for open tickets + Change change = new Change(createdBy); + change.setField(Field.milestone, ""); + TicketModel ticket = updateTicket(repository, qr.number, change); + } + } return true; } catch (IOException e) { log.error("failed to delete milestone " + milestone + " in " + repository, e); diff --git a/src/main/java/com/gitblit/tickets/QueryResult.java b/src/main/java/com/gitblit/tickets/QueryResult.java index 9f5d3a55..7a2b1abe 100644 --- a/src/main/java/com/gitblit/tickets/QueryResult.java +++ b/src/main/java/com/gitblit/tickets/QueryResult.java @@ -74,6 +74,14 @@ public class QueryResult implements Serializable { return type != null && Type.Proposal == type; } + public boolean isOpen() { + return !status.isClosed(); + } + + public boolean isClosed() { + return status.isClosed(); + } + public boolean isMerged() { return Status.Merged == status && !StringUtils.isEmpty(mergeSha); } diff --git a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html index 66b47848..31f76f1c 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html +++ b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html @@ -27,7 +27,7 @@
-
 
+
   
diff --git a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java index 44077884..b92ba8ba 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java @@ -28,13 +28,13 @@ import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; -import org.parboiled.common.StringUtils; import com.gitblit.models.RepositoryModel; import com.gitblit.models.TicketModel; import com.gitblit.models.TicketModel.Status; import com.gitblit.models.UserModel; import com.gitblit.tickets.TicketMilestone; +import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; @@ -47,13 +47,13 @@ import com.gitblit.wicket.WicketUtils; public class EditMilestonePage extends RepositoryPage { private final String oldName; - + private IModel nameModel; private IModel dueModel; - + private IModel statusModel; - + private IModel notificationModel; public EditMilestonePage(PageParameters params) { @@ -64,7 +64,7 @@ public class EditMilestonePage extends RepositoryPage { // ticket service is read-only throw new RestartResponseException(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)); } - + UserModel currentUser = GitBlitWebSession.get().getUser(); if (currentUser == null) { currentUser = UserModel.ANONYMOUS; @@ -74,13 +74,13 @@ public class EditMilestonePage extends RepositoryPage { // administration prohibited throw new RestartResponseException(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)); } - + oldName = WicketUtils.getObject(params); if (StringUtils.isEmpty(oldName)) { // milestone not specified throw new RestartResponseException(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)); } - + TicketMilestone tm = app().tickets().getMilestone(getRepositoryModel(), oldName); if (tm == null) { // milestone does not exist @@ -96,30 +96,30 @@ public class EditMilestonePage extends RepositoryPage { @Override protected void onSubmit() { - + String name = nameModel.getObject(); if (StringUtils.isEmpty(name)) { return; } - + Date due = dueModel.getObject(); Status status = statusModel.getObject(); boolean rename = !name.equals(oldName); boolean notify = notificationModel.getObject(); - + UserModel currentUser = GitBlitWebSession.get().getUser(); String createdBy = currentUser.username; - + TicketMilestone tm = app().tickets().getMilestone(getRepositoryModel(), oldName); tm.setName(name); tm.setDue(due); tm.status = status; - + boolean success = true; if (rename) { success = app().tickets().renameMilestone(getRepositoryModel(), oldName, name, createdBy, notify); } - + if (success && app().tickets().updateMilestone(getRepositoryModel(), tm, createdBy)) { setResponsePage(TicketsPage.class, WicketUtils.newRepositoryParameter(getRepositoryModel().name)); } else { @@ -133,7 +133,7 @@ public class EditMilestonePage extends RepositoryPage { dueModel = Model.of(tm.due); statusModel = Model.of(tm.status); notificationModel = Model.of(true); - + form.add(new TextField("name", nameModel)); form.add(new DateTextField("due", dueModel, "yyyy-MM-dd")); @@ -152,6 +152,23 @@ public class EditMilestonePage extends RepositoryPage { cancel.setDefaultFormProcessing(false); form.add(cancel); + Button delete = new Button("delete") { + private static final long serialVersionUID = 1L; + + @Override + public void onSubmit() { + UserModel currentUser = GitBlitWebSession.get().getUser(); + String createdBy = currentUser.username; + + if (app().tickets().deleteMilestone(getRepositoryModel(), oldName, createdBy)) { + setResponsePage(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)); + } else { + // TODO error processing + } + } + }; + delete.setDefaultFormProcessing(false); + form.add(delete); } @Override diff --git a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java index 2c95f018..4c393786 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java +++ b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java @@ -29,6 +29,8 @@ import org.apache.wicket.model.Model; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; import com.gitblit.tickets.TicketMilestone; +import com.gitblit.utils.StringUtils; +import com.gitblit.utils.TimeUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; @@ -43,7 +45,7 @@ public class NewMilestonePage extends RepositoryPage { private IModel nameModel; private IModel dueModel; - + public NewMilestonePage(PageParameters params) { super(params); @@ -52,7 +54,7 @@ public class NewMilestonePage extends RepositoryPage { // ticket service is read-only throw new RestartResponseException(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)); } - + UserModel currentUser = GitBlitWebSession.get().getUser(); if (currentUser == null) { currentUser = UserModel.ANONYMOUS; @@ -72,13 +74,17 @@ public class NewMilestonePage extends RepositoryPage { @Override protected void onSubmit() { - + String name = nameModel.getObject(); + if (StringUtils.isEmpty(name)) { + return; + } + Date due = dueModel.getObject(); UserModel currentUser = GitBlitWebSession.get().getUser(); String createdBy = currentUser.username; - + TicketMilestone milestone = app().tickets().createMilestone(getRepositoryModel(), name, createdBy); if (milestone != null) { milestone.due = due; @@ -92,8 +98,8 @@ public class NewMilestonePage extends RepositoryPage { add(form); nameModel = Model.of(""); - dueModel = Model.of(new Date()); - + dueModel = Model.of(new Date(System.currentTimeMillis() + TimeUtils.ONEDAY)); + form.add(new TextField("name", nameModel)); form.add(new DateTextField("due", dueModel, "yyyy-MM-dd")); -- cgit v1.2.3 From 6209dc4fd442887e18e3dd6fe7056f4b842091c2 Mon Sep 17 00:00:00 2001 From: James Moger Date: Sun, 27 Apr 2014 19:49:33 -0400 Subject: Use ajax buttons in the New|Edit Milestone pages --- .../gitblit/wicket/pages/EditMilestonePage.java | 37 +++++++++++----------- .../com/gitblit/wicket/pages/NewMilestonePage.java | 26 ++++++++------- 2 files changed, 33 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java index b92ba8ba..967d8f35 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java @@ -21,6 +21,8 @@ import java.util.List; import org.apache.wicket.PageParameters; import org.apache.wicket.RestartResponseException; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; import org.apache.wicket.extensions.markup.html.form.DateTextField; import org.apache.wicket.markup.html.form.Button; import org.apache.wicket.markup.html.form.DropDownChoice; @@ -90,13 +92,26 @@ public class EditMilestonePage extends RepositoryPage { setStatelessHint(false); setOutputMarkupId(true); - Form form = new Form("editForm") { + Form form = new Form("editForm"); + add(form); + + nameModel = Model.of(tm.name); + dueModel = Model.of(tm.due); + statusModel = Model.of(tm.status); + notificationModel = Model.of(true); + + form.add(new TextField("name", nameModel)); + form.add(new DateTextField("due", dueModel, "yyyy-MM-dd")); + + List statusChoices = Arrays.asList(Status.Open, Status.Closed); + form.add(new DropDownChoice("status", statusModel, statusChoices)); + + form.add(new AjaxButton("save") { private static final long serialVersionUID = 1L; @Override - protected void onSubmit() { - + protected void onSubmit(AjaxRequestTarget target, Form form) { String name = nameModel.getObject(); if (StringUtils.isEmpty(name)) { return; @@ -126,21 +141,7 @@ public class EditMilestonePage extends RepositoryPage { // TODO error } } - }; - add(form); - - nameModel = Model.of(tm.name); - dueModel = Model.of(tm.due); - statusModel = Model.of(tm.status); - notificationModel = Model.of(true); - - form.add(new TextField("name", nameModel)); - form.add(new DateTextField("due", dueModel, "yyyy-MM-dd")); - - List statusChoices = Arrays.asList(Status.Open, Status.Closed); - form.add(new DropDownChoice("status", statusModel, statusChoices)); - - form.add(new Button("save")); + }); Button cancel = new Button("cancel") { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java index 4c393786..d6e34cb0 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java +++ b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java @@ -19,6 +19,8 @@ import java.util.Date; import org.apache.wicket.PageParameters; import org.apache.wicket.RestartResponseException; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; import org.apache.wicket.extensions.markup.html.form.DateTextField; import org.apache.wicket.markup.html.form.Button; import org.apache.wicket.markup.html.form.Form; @@ -68,13 +70,21 @@ public class NewMilestonePage extends RepositoryPage { setStatelessHint(false); setOutputMarkupId(true); - Form form = new Form("editForm") { + Form form = new Form("editForm"); + add(form); + + nameModel = Model.of(""); + dueModel = Model.of(new Date(System.currentTimeMillis() + TimeUtils.ONEDAY)); + + form.add(new TextField("name", nameModel)); + form.add(new DateTextField("due", dueModel, "yyyy-MM-dd")); + + form.add(new AjaxButton("create") { private static final long serialVersionUID = 1L; @Override - protected void onSubmit() { - + protected void onSubmit(AjaxRequestTarget target, Form form) { String name = nameModel.getObject(); if (StringUtils.isEmpty(name)) { return; @@ -94,16 +104,8 @@ public class NewMilestonePage extends RepositoryPage { // TODO error } } - }; - add(form); - - nameModel = Model.of(""); - dueModel = Model.of(new Date(System.currentTimeMillis() + TimeUtils.ONEDAY)); - - form.add(new TextField("name", nameModel)); - form.add(new DateTextField("due", dueModel, "yyyy-MM-dd")); + }); - form.add(new Button("create")); Button cancel = new Button("cancel") { private static final long serialVersionUID = 1L; -- cgit v1.2.3 From 667163976e4e51fc3ebf191525e44d97c8a724dc Mon Sep 17 00:00:00 2001 From: James Moger Date: Mon, 28 Apr 2014 11:08:50 -0400 Subject: Overdue labeling, notify changed tickets control --- .../java/com/gitblit/tickets/ITicketService.java | 38 +++++++++++++++++----- .../java/com/gitblit/tickets/TicketMilestone.java | 10 +++++- .../com/gitblit/wicket/GitBlitWebApp.properties | 4 ++- .../gitblit/wicket/pages/EditMilestonePage.html | 3 +- .../gitblit/wicket/pages/EditMilestonePage.java | 7 +++- .../com/gitblit/wicket/pages/NewMilestonePage.html | 2 +- .../com/gitblit/wicket/pages/NewMilestonePage.java | 11 ++++++- .../java/com/gitblit/wicket/pages/TicketsPage.java | 26 ++++++++++++--- 8 files changed, 82 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/tickets/ITicketService.java b/src/main/java/com/gitblit/tickets/ITicketService.java index cce805ed..3261ca96 100644 --- a/src/main/java/com/gitblit/tickets/ITicketService.java +++ b/src/main/java/com/gitblit/tickets/ITicketService.java @@ -651,11 +651,12 @@ public abstract class ITicketService { * @param oldName * @param newName * @param createdBy - * @param send ticket notifications + * @param notifyOpenTickets * @return true if successful * @since 1.6.0 */ - public synchronized boolean renameMilestone(RepositoryModel repository, String oldName, String newName, String createdBy, boolean notify) { + public synchronized boolean renameMilestone(RepositoryModel repository, String oldName, + String newName, String createdBy, boolean notifyOpenTickets) { if (StringUtils.isEmpty(newName)) { throw new IllegalArgumentException("new milestone can not be empty!"); } @@ -680,11 +681,11 @@ public abstract class ITicketService { Change change = new Change(createdBy); change.setField(Field.milestone, newName); TicketModel ticket = updateTicket(repository, qr.number, change); - if (notify && ticket.isOpen()) { + if (notifyOpenTickets && ticket.isOpen()) { notifier.queueMailing(ticket); } } - if (notify) { + if (notifyOpenTickets) { notifier.sendAll(); } @@ -709,6 +710,21 @@ public abstract class ITicketService { * @since 1.4.0 */ public synchronized boolean deleteMilestone(RepositoryModel repository, String milestone, String createdBy) { + return deleteMilestone(repository, milestone, createdBy, true); + } + + /** + * Deletes a milestone. + * + * @param repository + * @param milestone + * @param createdBy + * @param notifyOpenTickets + * @return true if successful + * @since 1.6.0 + */ + public synchronized boolean deleteMilestone(RepositoryModel repository, String milestone, + String createdBy, boolean notifyOpenTickets) { if (StringUtils.isEmpty(milestone)) { throw new IllegalArgumentException("milestone can not be empty!"); } @@ -722,14 +738,18 @@ public abstract class ITicketService { milestonesCache.remove(repository.name); + TicketNotifier notifier = createNotifier(); for (QueryResult qr : tm.tickets) { - if (qr.isOpen()) { - // reset the milestone only for open tickets - Change change = new Change(createdBy); - change.setField(Field.milestone, ""); - TicketModel ticket = updateTicket(repository, qr.number, change); + Change change = new Change(createdBy); + change.setField(Field.milestone, ""); + TicketModel ticket = updateTicket(repository, qr.number, change); + if (notifyOpenTickets && ticket.isOpen()) { + notifier.queueMailing(ticket); } } + if (notifyOpenTickets) { + notifier.sendAll(); + } return true; } catch (IOException e) { log.error("failed to delete milestone " + milestone + " in " + repository, e); diff --git a/src/main/java/com/gitblit/tickets/TicketMilestone.java b/src/main/java/com/gitblit/tickets/TicketMilestone.java index 680615a9..dacedda6 100644 --- a/src/main/java/com/gitblit/tickets/TicketMilestone.java +++ b/src/main/java/com/gitblit/tickets/TicketMilestone.java @@ -37,7 +37,15 @@ public class TicketMilestone extends TicketLabel { super(name); status = Status.Open; } - + + public boolean isOpen() { + return status == Status.Open; + } + + public boolean isOverdue() { + return due == null ? false : System.currentTimeMillis() > due.getTime(); + } + public void setDue(Date due) { this.due = due; } diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index ce4c0b22..e66e53a7 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -673,4 +673,6 @@ 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.newMilestone = new milestone -gb.editMilestone = edit milestone \ No newline at end of file +gb.editMilestone = edit milestone +gb.notifyChangedOpenTickets = send notification for changed open tickets +gb.overdue = overdue \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html index 31f76f1c..0897ebee 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html +++ b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html @@ -19,8 +19,9 @@ - + +
 
*
diff --git a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java index 967d8f35..b844442a 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java @@ -24,7 +24,9 @@ import org.apache.wicket.RestartResponseException; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.form.AjaxButton; import org.apache.wicket.extensions.markup.html.form.DateTextField; +import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Button; +import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.TextField; @@ -102,6 +104,8 @@ public class EditMilestonePage extends RepositoryPage { form.add(new TextField("name", nameModel)); form.add(new DateTextField("due", dueModel, "yyyy-MM-dd")); + form.add(new Label("dueFormat", "yyyy-MM-dd")); + form.add(new CheckBox("notify", notificationModel)); List statusChoices = Arrays.asList(Status.Open, Status.Closed); form.add(new DropDownChoice("status", statusModel, statusChoices)); @@ -160,8 +164,9 @@ public class EditMilestonePage extends RepositoryPage { public void onSubmit() { UserModel currentUser = GitBlitWebSession.get().getUser(); String createdBy = currentUser.username; + boolean notify = notificationModel.getObject(); - if (app().tickets().deleteMilestone(getRepositoryModel(), oldName, createdBy)) { + if (app().tickets().deleteMilestone(getRepositoryModel(), oldName, createdBy, notify)) { setResponsePage(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)); } else { // TODO error processing diff --git a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html index 1b7e11ae..2ba5d5cc 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html +++ b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html @@ -19,7 +19,7 @@ - +
 
diff --git a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java index d6e34cb0..a9f76d3a 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java +++ b/src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java @@ -22,6 +22,7 @@ import org.apache.wicket.RestartResponseException; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.form.AjaxButton; import org.apache.wicket.extensions.markup.html.form.DateTextField; +import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Button; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.TextField; @@ -78,6 +79,7 @@ public class NewMilestonePage extends RepositoryPage { form.add(new TextField("name", nameModel)); form.add(new DateTextField("due", dueModel, "yyyy-MM-dd")); + form.add(new Label("dueFormat", "yyyy-MM-dd")); form.add(new AjaxButton("create") { @@ -87,6 +89,13 @@ public class NewMilestonePage extends RepositoryPage { protected void onSubmit(AjaxRequestTarget target, Form form) { String name = nameModel.getObject(); if (StringUtils.isEmpty(name)) { + // invalid name + return; + } + + TicketMilestone milestone = app().tickets().getMilestone(getRepositoryModel(), name); + if (milestone != null) { + // milestone already exists return; } @@ -95,7 +104,7 @@ public class NewMilestonePage extends RepositoryPage { UserModel currentUser = GitBlitWebSession.get().getUser(); String createdBy = currentUser.username; - TicketMilestone milestone = app().tickets().createMilestone(getRepositoryModel(), name, createdBy); + milestone = app().tickets().createMilestone(getRepositoryModel(), name, createdBy); if (milestone != null) { milestone.due = due; app().tickets().updateMilestone(getRepositoryModel(), milestone, createdBy); diff --git a/src/main/java/com/gitblit/wicket/pages/TicketsPage.java b/src/main/java/com/gitblit/wicket/pages/TicketsPage.java index 984b3754..b7e392a2 100644 --- a/src/main/java/com/gitblit/wicket/pages/TicketsPage.java +++ b/src/main/java/com/gitblit/wicket/pages/TicketsPage.java @@ -20,6 +20,7 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Set; import java.util.TreeSet; @@ -657,9 +658,20 @@ public class TicketsPage extends TicketBasePage { } else { add(new Label("newMilestone").setVisible(false)); } - + // milestones list - List allMilestones = app().tickets().getMilestones(repositoryModel); + List allMilestones = new ArrayList(app().tickets().getMilestones(repositoryModel)); + Collections.sort(allMilestones, new Comparator() { + @Override + public int compare(TicketMilestone o1, TicketMilestone o2) { + if (o2.isOpen() && !o1.isOpen()) { + return 1; + } else if (o1.isOpen() && !o2.isOpen()) { + return -1; + } + return o2.due.compareTo(o1.due); + } + }); ListDataProvider allMilestonesDp = new ListDataProvider(allMilestones); DataView milestonesList = new DataView("milestoneList", allMilestonesDp) { private static final long serialVersionUID = 1L; @@ -671,15 +683,21 @@ public class TicketsPage extends TicketBasePage { item.add(new LinkPanel("milestoneName", null, tm.name, TicketsPage.class, params).setRenderBodyOnly(true)); String css; + String status = tm.status.name(); switch (tm.status) { case Open: - css = "aui-lozenge aui-lozenge-subtle"; + if (tm.isOverdue()) { + css = "aui-lozenge aui-lozenge-subtle aui-lozenge-error"; + status = "overdue"; + } else { + css = "aui-lozenge aui-lozenge-subtle"; + } break; default: css = "aui-lozenge"; break; } - Label stateLabel = new Label("milestoneState", tm.status.name()); + Label stateLabel = new Label("milestoneState", status); WicketUtils.setCssClass(stateLabel, css); item.add(stateLabel); -- cgit v1.2.3 From 8d2caa7e81fcd995f0a5c07fa4454ae2f8e86e6e Mon Sep 17 00:00:00 2001 From: James Moger Date: Wed, 30 Apr 2014 17:15:31 -0400 Subject: Show open milestone progress and change milestones list layout --- .../com/gitblit/wicket/GitBlitWebApp.properties | 4 +- .../java/com/gitblit/wicket/pages/TicketsPage.html | 40 ++++++++++- .../java/com/gitblit/wicket/pages/TicketsPage.java | 81 +++++++++++++++++----- 3 files changed, 104 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index e66e53a7..1394890f 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -675,4 +675,6 @@ gb.youDoNotHaveClonePermission = You are not permitted to clone this repository. gb.newMilestone = new milestone gb.editMilestone = edit milestone gb.notifyChangedOpenTickets = send notification for changed open tickets -gb.overdue = overdue \ No newline at end of file +gb.overdue = overdue +gb.openMilestones = open milestones +gb.closedMilestones = closed milestones \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/TicketsPage.html b/src/main/java/com/gitblit/wicket/pages/TicketsPage.html index e144bea1..a40d3126 100644 --- a/src/main/java/com/gitblit/wicket/pages/TicketsPage.html +++ b/src/main/java/com/gitblit/wicket/pages/TicketsPage.html @@ -141,15 +141,49 @@
+ +
+

+

+
+
+
+
+
+
+
-
-

- +

+

+
+
+
+
+
+ +

+ +
+
+ + +
+
+
+
+
+ , + , + +
+
+
+ diff --git a/src/main/java/com/gitblit/wicket/pages/TicketsPage.java b/src/main/java/com/gitblit/wicket/pages/TicketsPage.java index b7e392a2..5973d473 100644 --- a/src/main/java/com/gitblit/wicket/pages/TicketsPage.java +++ b/src/main/java/com/gitblit/wicket/pages/TicketsPage.java @@ -660,27 +660,49 @@ public class TicketsPage extends TicketBasePage { } // milestones list - List allMilestones = new ArrayList(app().tickets().getMilestones(repositoryModel)); - Collections.sort(allMilestones, new Comparator() { + List openMilestones = new ArrayList(); + List closedMilestones = new ArrayList(); + for (TicketMilestone milestone : app().tickets().getMilestones(repositoryModel)) { + if (milestone.isOpen()) { + openMilestones.add(milestone); + } else { + closedMilestones.add(milestone); + } + } + Collections.sort(openMilestones, new Comparator() { + @Override + public int compare(TicketMilestone o1, TicketMilestone o2) { + return o2.due.compareTo(o1.due); + } + }); + + Collections.sort(closedMilestones, new Comparator() { @Override public int compare(TicketMilestone o1, TicketMilestone o2) { - if (o2.isOpen() && !o1.isOpen()) { - return 1; - } else if (o1.isOpen() && !o2.isOpen()) { - return -1; - } return o2.due.compareTo(o1.due); } }); - ListDataProvider allMilestonesDp = new ListDataProvider(allMilestones); - DataView milestonesList = new DataView("milestoneList", allMilestonesDp) { + + DataView openMilestonesList = milestoneList("openMilestonesList", openMilestones, acceptingUpdates); + add(openMilestonesList); + + DataView closedMilestonesList = milestoneList("closedMilestonesList", closedMilestones, acceptingUpdates); + add(closedMilestonesList); + } + + protected DataView milestoneList(String wicketId, List milestones, final boolean acceptingUpdates) { + ListDataProvider milestonesDp = new ListDataProvider(milestones); + DataView milestonesList = new DataView(wicketId, milestonesDp) { private static final long serialVersionUID = 1L; @Override public void populateItem(final Item item) { + Fragment entryPanel = new Fragment("entryPanel", "milestoneListFragment", this); + item.add(entryPanel); + final TicketMilestone tm = item.getModelObject(); - PageParameters params = queryParameters(null, tm.name, null, null, null, desc, 1); - item.add(new LinkPanel("milestoneName", null, tm.name, TicketsPage.class, params).setRenderBodyOnly(true)); + PageParameters params = queryParameters(null, tm.name, null, null, null, true, 1); + entryPanel.add(new LinkPanel("milestoneName", null, tm.name, TicketsPage.class, params).setRenderBodyOnly(true)); String css; String status = tm.status.name(); @@ -699,22 +721,47 @@ public class TicketsPage extends TicketBasePage { } Label stateLabel = new Label("milestoneState", status); WicketUtils.setCssClass(stateLabel, css); - item.add(stateLabel); + entryPanel.add(stateLabel); if (tm.due == null) { - item.add(new Label("milestoneDue", getString("gb.notSpecified"))); + entryPanel.add(new Label("milestoneDue", getString("gb.notSpecified"))); } else { - item.add(WicketUtils.createDatestampLabel("milestoneDue", tm.due, getTimeZone(), getTimeUtils())); + entryPanel.add(WicketUtils.createDatestampLabel("milestoneDue", tm.due, getTimeZone(), getTimeUtils())); } if (acceptingUpdates) { - item.add(new LinkPanel("editMilestone", null, getString("gb.edit"), EditMilestonePage.class, + entryPanel.add(new LinkPanel("editMilestone", null, getString("gb.edit"), EditMilestonePage.class, WicketUtils.newObjectParameter(repositoryName, tm.name))); } else { - item.add(new Label("editMilestone").setVisible(false)); + entryPanel.add(new Label("editMilestone").setVisible(false)); + } + + if (tm.isOpen()) { + // re-load milestone with query results + TicketMilestone m = app().tickets().getMilestone(getRepositoryModel(), tm.name); + + Fragment milestonePanel = new Fragment("milestonePanel", "openMilestoneFragment", this); + Label label = new Label("progress"); + WicketUtils.setCssStyle(label, "width:" + tm.getProgress() + "%;"); + milestonePanel.add(label); + + milestonePanel.add(new LinkPanel("openTickets", null, + MessageFormat.format(getString("gb.nOpenTickets"), m.getOpenTickets()), + TicketsPage.class, + queryParameters(null, tm.name, openStatii, null, null, true, 1))); + + milestonePanel.add(new LinkPanel("closedTickets", null, + MessageFormat.format(getString("gb.nClosedTickets"), m.getClosedTickets()), + TicketsPage.class, + queryParameters(null, tm.name, closedStatii, null, null, true, 1))); + + milestonePanel.add(new Label("totalTickets", MessageFormat.format(getString("gb.nTotalTickets"), m.getTotalTickets()))); + entryPanel.add(milestonePanel); + } else { + entryPanel.add(new Label("milestonePanel").setVisible(false)); } } }; - add(milestonesList); + return milestonesList; } protected PageParameters queryParameters( -- cgit v1.2.3 From 3380373c3123f875f50e48b0290c84dfae0519e4 Mon Sep 17 00:00:00 2001 From: BUISSON Christian Date: Tue, 15 Apr 2014 15:21:33 +0200 Subject: First Step in My Tickets --- .../com/gitblit/tickets/FileTicketService.java | 116 +++++++++++-------- .../java/com/gitblit/tickets/ITicketService.java | 11 +- .../java/com/gitblit/wicket/GitBlitWebApp.java | 2 + .../com/gitblit/wicket/GitBlitWebApp.properties | 3 +- .../com/gitblit/wicket/GitBlitWebApp_fr.properties | 1 + .../com/gitblit/wicket/pages/MyTicketsPage.html | 50 ++++++++ .../com/gitblit/wicket/pages/MyTicketsPage.java | 128 +++++++++++++++++++++ .../java/com/gitblit/wicket/pages/RootPage.java | 1 + 8 files changed, 262 insertions(+), 50 deletions(-) create mode 100644 src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html create mode 100644 src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java (limited to 'src') diff --git a/src/main/java/com/gitblit/tickets/FileTicketService.java b/src/main/java/com/gitblit/tickets/FileTicketService.java index 4386020f..ea5d065f 100644 --- a/src/main/java/com/gitblit/tickets/FileTicketService.java +++ b/src/main/java/com/gitblit/tickets/FileTicketService.java @@ -207,62 +207,82 @@ public class FileTicketService extends ITicketService { @Override public List getTickets(RepositoryModel repository, TicketFilter filter) { List list = new ArrayList(); - - Repository db = repositoryManager.getRepository(repository.name); - try { - // Collect the set of all json files - File dir = new File(db.getDirectory(), TICKETS_PATH); - List journals = findAll(dir, JOURNAL); - - // Deserialize each ticket and optionally filter out unwanted tickets - for (File journal : journals) { - String json = null; - try { - json = new String(FileUtils.readContent(journal), Constants.ENCODING); - } catch (Exception e) { - log.error(null, e); - } - if (StringUtils.isEmpty(json)) { - // journal was touched but no changes were written - continue; - } - try { - // Reconstruct ticketId from the path - // id/26/326/journal.json - String path = FileUtils.getRelativePath(dir, journal); - String tid = path.split("/")[1]; - long ticketId = Long.parseLong(tid); - List changes = TicketSerializer.deserializeJournal(json); - if (ArrayUtils.isEmpty(changes)) { - log.warn("Empty journal for {}:{}", repository, journal); + List databases = new ArrayList(); + List models = new ArrayList(); + + if(repository == null) + { + List allRepo = repositoryManager.getRepositoryList(); + for(int i = 0; i < allRepo.size(); i++) + { + databases.add(repositoryManager.getRepository(allRepo.get(i))); + models.add(repositoryManager.getRepositoryModel(allRepo.get(i))); + } + } + else + { + databases.add(repositoryManager.getRepository(repository.name)); + models.add(repository); + } + + for(int i = 0; i < databases.size(); i++) + { + Repository db = databases.get(i); + try { + // Collect the set of all json files + File dir = new File(db.getDirectory(), TICKETS_PATH); + List journals = findAll(dir, JOURNAL); + + // Deserialize each ticket and optionally filter out unwanted tickets + for (File journal : journals) { + String json = null; + try { + json = new String(FileUtils.readContent(journal), Constants.ENCODING); + } catch (Exception e) { + log.error(null, e); + } + if (StringUtils.isEmpty(json)) { + // journal was touched but no changes were written continue; } - TicketModel ticket = TicketModel.buildTicket(changes); - ticket.project = repository.projectPath; - ticket.repository = repository.name; - ticket.number = ticketId; - - // add the ticket, conditionally, to the list - if (filter == null) { - list.add(ticket); - } else { - if (filter.accept(ticket)) { + try { + // Reconstruct ticketId from the path + // id/26/326/journal.json + String path = FileUtils.getRelativePath(dir, journal); + String tid = path.split("/")[1]; + long ticketId = Long.parseLong(tid); + List changes = TicketSerializer.deserializeJournal(json); + if (ArrayUtils.isEmpty(changes)) { + log.warn("Empty journal for {}:{}", models.get(i), journal); + continue; + } + TicketModel ticket = TicketModel.buildTicket(changes); + ticket.project = models.get(i).projectPath; + ticket.repository = models.get(i).name; + ticket.number = ticketId; + + // add the ticket, conditionally, to the list + if (filter == null) { list.add(ticket); + } else { + if (filter.accept(ticket)) { + list.add(ticket); + } } + } catch (Exception e) { + log.error("failed to deserialize {}/{}\n{}", + new Object [] { models.get(i), journal, e.getMessage()}); + log.error(null, e); } - } catch (Exception e) { - log.error("failed to deserialize {}/{}\n{}", - new Object [] { repository, journal, e.getMessage()}); - log.error(null, e); } + } finally { + db.close(); } - - // sort the tickets by creation - Collections.sort(list); - return list; - } finally { - db.close(); } + + // sort the tickets by creation + Collections.sort(list); + return list; } private List findAll(File dir, String filename) { diff --git a/src/main/java/com/gitblit/tickets/ITicketService.java b/src/main/java/com/gitblit/tickets/ITicketService.java index 3261ca96..e7b4c71d 100644 --- a/src/main/java/com/gitblit/tickets/ITicketService.java +++ b/src/main/java/com/gitblit/tickets/ITicketService.java @@ -779,12 +779,21 @@ public abstract class ITicketService { * @since 1.4.0 */ public abstract boolean hasTicket(RepositoryModel repository, long ticketId); + + /** + * Returns all tickets. This is not a Lucene search! + * + * @return all tickets + */ + public List getTickets() { + return getTickets(null, null); + } /** * Returns all tickets. This is not a Lucene search! * * @param repository - * @return all tickets + * @return all tickets of a given repository * @since 1.4.0 */ public List getTickets(RepositoryModel repository) { diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java index d4c1bc40..9f002d2b 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java @@ -81,6 +81,7 @@ import com.gitblit.wicket.pages.TicketsPage; import com.gitblit.wicket.pages.TreePage; import com.gitblit.wicket.pages.UserPage; import com.gitblit.wicket.pages.UsersPage; +import com.gitblit.wicket.pages.MyTicketsPage; public class GitBlitWebApp extends WebApplication { @@ -191,6 +192,7 @@ public class GitBlitWebApp extends WebApplication { mount("/tickets/export", ExportTicketPage.class, "r", "h"); mount("/milestones/new", NewMilestonePage.class, "r"); mount("/milestones/edit", EditMilestonePage.class, "r", "h"); + mount("/mytickets", MyTicketsPage.class, "r", "h"); // setup the markup document urls mount("/docs", DocsPage.class, "r"); diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 1394890f..030c5ebe 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -677,4 +677,5 @@ gb.editMilestone = edit milestone gb.notifyChangedOpenTickets = send notification for changed open tickets gb.overdue = overdue gb.openMilestones = open milestones -gb.closedMilestones = closed milestones \ No newline at end of file +gb.closedMilestones = closed milestones +gb.mytickets = my tickets \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_fr.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_fr.properties index 8a725cf4..75a3ab7a 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_fr.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_fr.properties @@ -670,3 +670,4 @@ gb.repositoryDoesNotAcceptPatchsets = Ce d gb.serverDoesNotAcceptPatchsets = Ce serveur n'accepte pas de patchsets. gb.ticketIsClosed = Ce ticket est clos. gb.mergeToDescription = default integration branch for merging ticket patchsets +gb.mytickets = mes tickets diff --git a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html new file mode 100644 index 00000000..bbb2b96b --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html @@ -0,0 +1,50 @@ + + + + + +
+ Responsible Tickets + + + + + + +
+ + + Author Tickets + + + + + + +
+ + + Voted Tickets + + + + + + +
+ + + Watched Tickets + + + + + + +
+ + + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java new file mode 100644 index 00000000..509b00ca --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java @@ -0,0 +1,128 @@ +package com.gitblit.wicket.pages; + +import java.util.ArrayList; +import java.util.List; + +import com.gitblit.models.UserModel; +import com.gitblit.models.TicketModel; +import com.gitblit.tickets.ITicketService; +import com.gitblit.wicket.GitBlitWebApp; +import com.gitblit.wicket.GitBlitWebSession; +import com.gitblit.wicket.panels.LinkPanel; + +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; +import org.apache.wicket.PageParameters; + +public class MyTicketsPage extends RootPage { + + public MyTicketsPage(PageParameters params) + { + this(); + } + + public MyTicketsPage() + { + super(); + setupPage("", ""); + + UserModel currentUser = GitBlitWebSession.get().getUser(); + if (currentUser == null) { + currentUser = UserModel.ANONYMOUS; + } + String username = currentUser.getName(); + + ITicketService tickets = GitBlitWebApp.get().tickets(); + List returnedTickets = tickets.getTickets(null); + + List responsibleTickets = new ArrayList(); + List authorTickets = new ArrayList(); + List votedTickets = new ArrayList(); + List watchedTickets = new ArrayList(); + for(int i = 0; i < returnedTickets.size(); i++) + { + TicketModel ticket = returnedTickets.get(i); + if(ticket.isOpen()) + { + if(ticket.isResponsible(username)) + { + responsibleTickets.add(ticket); + } + if(ticket.isAuthor(username)) + { + authorTickets.add(ticket); + } + if(ticket.isVoter(username)) + { + votedTickets.add(ticket); + } + if(ticket.isWatching(username)) + { + watchedTickets.add(ticket); + } + } + } + + ListView responsibleView = new ListView("responsibleTickets", responsibleTickets) + { + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(final ListItem item) + { + final TicketModel ticket = item.getModelObject(); + String ticketUrl = app().tickets().getTicketUrl(ticket); + item.add(new LinkPanel("ticketName", "", ticket.title, ticketUrl)); + item.add(new Label("ticketDescription", ticket.body)); + } + }; + + ListView authorView = new ListView("authorTickets", authorTickets) + { + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(final ListItem item) + { + final TicketModel ticket = item.getModelObject(); + String ticketUrl = app().tickets().getTicketUrl(ticket); + item.add(new LinkPanel("ticketName", "", ticket.title, ticketUrl)); + item.add(new Label("ticketDescription", ticket.body)); + } + }; + + ListView votedView = new ListView("votedTickets", votedTickets) + { + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(final ListItem item) + { + final TicketModel ticket = item.getModelObject(); + String ticketUrl = app().tickets().getTicketUrl(ticket); + item.add(new LinkPanel("ticketName", "", ticket.title, ticketUrl)); + item.add(new Label("ticketDescription", ticket.body)); + } + }; + + ListView watchedView = new ListView("watchedTickets", watchedTickets) + { + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(final ListItem item) + { + final TicketModel ticket = item.getModelObject(); + String ticketUrl = app().tickets().getTicketUrl(ticket); + item.add(new LinkPanel("ticketName", "", ticket.title, ticketUrl)); + item.add(new Label("ticketDescription", ticket.body)); + } + }; + + add(responsibleView); + add(authorView); + add(votedView); + add(watchedView); + } +} diff --git a/src/main/java/com/gitblit/wicket/pages/RootPage.java b/src/main/java/com/gitblit/wicket/pages/RootPage.java index 5ccc3a4c..ec413b19 100644 --- a/src/main/java/com/gitblit/wicket/pages/RootPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RootPage.java @@ -173,6 +173,7 @@ public abstract class RootPage extends BasePage { pages.add(new PageRegistration("gb.repositories", RepositoriesPage.class, getRootPageParameters())); pages.add(new PageRegistration("gb.activity", ActivityPage.class, getRootPageParameters())); + pages.add(new PageRegistration("gb.mytickets", MyTicketsPage.class, getRootPageParameters())); if (app().settings().getBoolean(Keys.web.allowLuceneIndexing, true)) { pages.add(new PageRegistration("gb.search", LuceneSearchPage.class)); } -- cgit v1.2.3 From 47bfbe3b1da6629655f49b32b917dccb21b83809 Mon Sep 17 00:00:00 2001 From: BUISSON Christian Date: Tue, 15 Apr 2014 15:45:34 +0200 Subject: Deactivate the navbar button for My Tickets (until it is finalized). --- src/main/java/com/gitblit/wicket/pages/RootPage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/RootPage.java b/src/main/java/com/gitblit/wicket/pages/RootPage.java index ec413b19..f43dc45e 100644 --- a/src/main/java/com/gitblit/wicket/pages/RootPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RootPage.java @@ -173,7 +173,7 @@ public abstract class RootPage extends BasePage { pages.add(new PageRegistration("gb.repositories", RepositoriesPage.class, getRootPageParameters())); pages.add(new PageRegistration("gb.activity", ActivityPage.class, getRootPageParameters())); - pages.add(new PageRegistration("gb.mytickets", MyTicketsPage.class, getRootPageParameters())); + //pages.add(new PageRegistration("gb.mytickets", MyTicketsPage.class, getRootPageParameters())); if (app().settings().getBoolean(Keys.web.allowLuceneIndexing, true)) { pages.add(new PageRegistration("gb.search", LuceneSearchPage.class)); } -- cgit v1.2.3 From 556a5853fb7145adc20b2e718eca2e921f3d7399 Mon Sep 17 00:00:00 2001 From: BUISSON Christian Date: Wed, 16 Apr 2014 16:10:51 +0200 Subject: Ajout du nom du repository sur la page "MyTickets". --- .../com/gitblit/wicket/pages/MyTicketsPage.html | 86 ++++++++++++---------- .../com/gitblit/wicket/pages/MyTicketsPage.java | 8 ++ 2 files changed, 55 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html index bbb2b96b..5222c35c 100644 --- a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html +++ b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html @@ -6,45 +6,53 @@ - - Responsible Tickets - - - - - - -
- - - Author Tickets - - - - - - -
- - - Voted Tickets - - - - - - -
- - - Watched Tickets - - - - - - -
+
+
[my tickets message]
+ + + Responsible Tickets + + + + + + + +
+ + + Author Tickets + + + + + + + +
+ + + Voted Tickets + + + + + + + +
+ + + Watched Tickets + + + + + + + +
+
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java index 509b00ca..6e656ae4 100644 --- a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java +++ b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java @@ -3,6 +3,7 @@ package com.gitblit.wicket.pages; import java.util.ArrayList; import java.util.List; +import com.gitblit.Keys; import com.gitblit.models.UserModel; import com.gitblit.models.TicketModel; import com.gitblit.tickets.ITicketService; @@ -33,6 +34,9 @@ public class MyTicketsPage extends RootPage { } String username = currentUser.getName(); + String message = "Welcome on GitBlit"; + this.add(new Label("myTicketsMessage", message)); + ITicketService tickets = GitBlitWebApp.get().tickets(); List returnedTickets = tickets.getTickets(null); @@ -73,6 +77,7 @@ public class MyTicketsPage extends RootPage { { final TicketModel ticket = item.getModelObject(); String ticketUrl = app().tickets().getTicketUrl(ticket); + item.add(new Label("repositoryName", ticket.repository)); item.add(new LinkPanel("ticketName", "", ticket.title, ticketUrl)); item.add(new Label("ticketDescription", ticket.body)); } @@ -87,6 +92,7 @@ public class MyTicketsPage extends RootPage { { final TicketModel ticket = item.getModelObject(); String ticketUrl = app().tickets().getTicketUrl(ticket); + item.add(new Label("repositoryName", ticket.repository)); item.add(new LinkPanel("ticketName", "", ticket.title, ticketUrl)); item.add(new Label("ticketDescription", ticket.body)); } @@ -101,6 +107,7 @@ public class MyTicketsPage extends RootPage { { final TicketModel ticket = item.getModelObject(); String ticketUrl = app().tickets().getTicketUrl(ticket); + item.add(new Label("repositoryName", ticket.repository)); item.add(new LinkPanel("ticketName", "", ticket.title, ticketUrl)); item.add(new Label("ticketDescription", ticket.body)); } @@ -115,6 +122,7 @@ public class MyTicketsPage extends RootPage { { final TicketModel ticket = item.getModelObject(); String ticketUrl = app().tickets().getTicketUrl(ticket); + item.add(new Label("repositoryName", ticket.repository)); item.add(new LinkPanel("ticketName", "", ticket.title, ticketUrl)); item.add(new Label("ticketDescription", ticket.body)); } -- cgit v1.2.3 From 7d19224c99f118351ad15a77942762e74940536f Mon Sep 17 00:00:00 2001 From: Hybris95 Date: Wed, 16 Apr 2014 16:42:18 +0200 Subject: Implementation of the getTickets capability of recovering all tickets from a nullable RepositoryModel --- .../com/gitblit/tickets/BranchTicketService.java | 114 ++++++++++++--------- .../com/gitblit/tickets/FileTicketService.java | 9 +- .../com/gitblit/tickets/RedisTicketService.java | 85 +++++++++------ 3 files changed, 124 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/tickets/BranchTicketService.java b/src/main/java/com/gitblit/tickets/BranchTicketService.java index 284b1be1..7d6926df 100644 --- a/src/main/java/com/gitblit/tickets/BranchTicketService.java +++ b/src/main/java/com/gitblit/tickets/BranchTicketService.java @@ -436,64 +436,84 @@ public class BranchTicketService extends ITicketService implements RefsChangedLi @Override public List getTickets(RepositoryModel repository, TicketFilter filter) { List list = new ArrayList(); - - Repository db = repositoryManager.getRepository(repository.name); - try { - RefModel ticketsBranch = getTicketsBranch(db); - if (ticketsBranch == null) { - return list; + List databases = new ArrayList(); + List models = new ArrayList(); + + if(repository == null) + { + List allRepo = repositoryManager.getRepositoryList(); + for(int i = 0; i < allRepo.size(); i++) + { + databases.add(repositoryManager.getRepository(allRepo.get(i))); + models.add(repositoryManager.getRepositoryModel(allRepo.get(i))); } + } + else + { + databases.add(repositoryManager.getRepository(repository.name)); + models.add(repository); + } - // Collect the set of all json files - List paths = JGitUtils.getDocuments(db, Arrays.asList("json"), BRANCH); - - // Deserialize each ticket and optionally filter out unwanted tickets - for (PathModel path : paths) { - String name = path.name.substring(path.name.lastIndexOf('/') + 1); - if (!JOURNAL.equals(name)) { - continue; - } - String json = readTicketsFile(db, path.path); - if (StringUtils.isEmpty(json)) { - // journal was touched but no changes were written - continue; + for(int i = 0; i < databases.size(); i++) + { + Repository db = databases.get(i); + try { + RefModel ticketsBranch = getTicketsBranch(db); + if (ticketsBranch == null) { + return list; } - try { - // Reconstruct ticketId from the path - // id/26/326/journal.json - String tid = path.path.split("/")[2]; - long ticketId = Long.parseLong(tid); - List changes = TicketSerializer.deserializeJournal(json); - if (ArrayUtils.isEmpty(changes)) { - log.warn("Empty journal for {}:{}", repository, path.path); + + // Collect the set of all json files + List paths = JGitUtils.getDocuments(db, Arrays.asList("json"), BRANCH); + + // Deserialize each ticket and optionally filter out unwanted tickets + for (PathModel path : paths) { + String name = path.name.substring(path.name.lastIndexOf('/') + 1); + if (!JOURNAL.equals(name)) { + continue; + } + String json = readTicketsFile(db, path.path); + if (StringUtils.isEmpty(json)) { + // journal was touched but no changes were written continue; } - TicketModel ticket = TicketModel.buildTicket(changes); - ticket.project = repository.projectPath; - ticket.repository = repository.name; - ticket.number = ticketId; - - // add the ticket, conditionally, to the list - if (filter == null) { - list.add(ticket); - } else { - if (filter.accept(ticket)) { + try { + // Reconstruct ticketId from the path + // id/26/326/journal.json + String tid = path.path.split("/")[2]; + long ticketId = Long.parseLong(tid); + List changes = TicketSerializer.deserializeJournal(json); + if (ArrayUtils.isEmpty(changes)) { + log.warn("Empty journal for {}:{}", models.get(i), path.path); + continue; + } + TicketModel ticket = TicketModel.buildTicket(changes); + ticket.project = models.get(i).projectPath; + ticket.repository = models.get(i).name; + ticket.number = ticketId; + + // add the ticket, conditionally, to the list + if (filter == null) { list.add(ticket); + } else { + if (filter.accept(ticket)) { + list.add(ticket); + } } + } catch (Exception e) { + log.error("failed to deserialize {}/{}\n{}", + new Object [] { repository, path.path, e.getMessage()}); + log.error(null, e); } - } catch (Exception e) { - log.error("failed to deserialize {}/{}\n{}", - new Object [] { repository, path.path, e.getMessage()}); - log.error(null, e); } + } finally { + db.close(); } - - // sort the tickets by creation - Collections.sort(list); - return list; - } finally { - db.close(); } + + // sort the tickets by creation + Collections.sort(list); + return list; } /** diff --git a/src/main/java/com/gitblit/tickets/FileTicketService.java b/src/main/java/com/gitblit/tickets/FileTicketService.java index ea5d065f..7fd9675f 100644 --- a/src/main/java/com/gitblit/tickets/FileTicketService.java +++ b/src/main/java/com/gitblit/tickets/FileTicketService.java @@ -228,6 +228,7 @@ public class FileTicketService extends ITicketService { for(int i = 0; i < databases.size(); i++) { Repository db = databases.get(i); + RepositoryModel model = models.get(i); try { // Collect the set of all json files File dir = new File(db.getDirectory(), TICKETS_PATH); @@ -253,12 +254,12 @@ public class FileTicketService extends ITicketService { long ticketId = Long.parseLong(tid); List changes = TicketSerializer.deserializeJournal(json); if (ArrayUtils.isEmpty(changes)) { - log.warn("Empty journal for {}:{}", models.get(i), journal); + log.warn("Empty journal for {}:{}", model, journal); continue; } TicketModel ticket = TicketModel.buildTicket(changes); - ticket.project = models.get(i).projectPath; - ticket.repository = models.get(i).name; + ticket.project = model.projectPath; + ticket.repository = model.name; ticket.number = ticketId; // add the ticket, conditionally, to the list @@ -271,7 +272,7 @@ public class FileTicketService extends ITicketService { } } catch (Exception e) { log.error("failed to deserialize {}/{}\n{}", - new Object [] { models.get(i), journal, e.getMessage()}); + new Object [] { model, journal, e.getMessage()}); log.error(null, e); } } diff --git a/src/main/java/com/gitblit/tickets/RedisTicketService.java b/src/main/java/com/gitblit/tickets/RedisTicketService.java index 2c5b181f..48256b2b 100644 --- a/src/main/java/com/gitblit/tickets/RedisTicketService.java +++ b/src/main/java/com/gitblit/tickets/RedisTicketService.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.Set; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.eclipse.jgit.lib.Repository; import redis.clients.jedis.Client; import redis.clients.jedis.Jedis; @@ -228,47 +229,65 @@ public class RedisTicketService extends ITicketService { public List getTickets(RepositoryModel repository, TicketFilter filter) { Jedis jedis = pool.getResource(); List list = new ArrayList(); + List models = new ArrayList(); + + if(repository == null) + { + List allRepo = repositoryManager.getRepositoryList(); + for(int i = 0; i < allRepo.size(); i++) + { + models.add(repositoryManager.getRepositoryModel(allRepo.get(i))); + } + } + else + { + models.add(repository); + } + if (jedis == null) { return list; } - try { - // Deserialize each journal, build the ticket, and optionally filter - Set keys = jedis.keys(key(repository, KeyType.journal, "*")); - for (String key : keys) { - // {repo}:journal:{id} - String id = key.split(":")[2]; - long ticketId = Long.parseLong(id); - List changes = getJournal(jedis, repository, ticketId); - if (ArrayUtils.isEmpty(changes)) { - log.warn("Empty journal for {}:{}", repository, ticketId); - continue; - } - TicketModel ticket = TicketModel.buildTicket(changes); - ticket.project = repository.projectPath; - ticket.repository = repository.name; - ticket.number = ticketId; - - // add the ticket, conditionally, to the list - if (filter == null) { - list.add(ticket); - } else { - if (filter.accept(ticket)) { + for(int i = 0; i < models.size(); i++) + { + RepositoryModel model = models.get(i); + try { + // Deserialize each journal, build the ticket, and optionally filter + Set keys = jedis.keys(key(model, KeyType.journal, "*")); + for (String key : keys) { + // {repo}:journal:{id} + String id = key.split(":")[2]; + long ticketId = Long.parseLong(id); + List changes = getJournal(jedis, model, ticketId); + if (ArrayUtils.isEmpty(changes)) { + log.warn("Empty journal for {}:{}", model, ticketId); + continue; + } + TicketModel ticket = TicketModel.buildTicket(changes); + ticket.project = model.projectPath; + ticket.repository = model.name; + ticket.number = ticketId; + + // add the ticket, conditionally, to the list + if (filter == null) { list.add(ticket); + } else { + if (filter.accept(ticket)) { + list.add(ticket); + } } } - } - - // sort the tickets by creation - Collections.sort(list); - } catch (JedisException e) { - log.error("failed to retrieve tickets from Redis @ " + getUrl(), e); - pool.returnBrokenResource(jedis); - jedis = null; - } finally { - if (jedis != null) { - pool.returnResource(jedis); + } catch (JedisException e) { + log.error("failed to retrieve tickets from Redis @ " + getUrl(), e); + pool.returnBrokenResource(jedis); + jedis = null; + } finally { + if (jedis != null) { + pool.returnResource(jedis); + } } } + // sort the tickets by creation + Collections.sort(list); return list; } -- cgit v1.2.3 From 75796a0e2798e256a94f725961c9676746fc107a Mon Sep 17 00:00:00 2001 From: Hybris95 Date: Thu, 17 Apr 2014 15:44:16 +0200 Subject: Added git stylesheets to MyTickets. Added links to Repositories containing the tickets. --- .../com/gitblit/wicket/pages/MyTicketsPage.html | 69 +++++------ .../com/gitblit/wicket/pages/MyTicketsPage.java | 137 +++++++++------------ src/main/resources/gitblit.css | 48 ++++++++ 3 files changed, 135 insertions(+), 119 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html index 5222c35c..5d11fbbb 100644 --- a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html +++ b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html @@ -9,49 +9,36 @@
[my tickets message]
- - Responsible Tickets +
+ - - - - - - -
- - - Author Tickets - - - - - - - -
- - - Voted Tickets - - - - - - - -
- - - Watched Tickets - - - - - - - + + + +
+ + + + + + Repository + + Ticket + Description + Responsible + + + + + + + [repository name] + + [ticket name] + [ticket description] + [ticket responsible] +
diff --git a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java index 6e656ae4..6cd80a3f 100644 --- a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java +++ b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java @@ -1,19 +1,28 @@ package com.gitblit.wicket.pages; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; -import com.gitblit.Keys; +import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; import com.gitblit.models.TicketModel; import com.gitblit.tickets.ITicketService; import com.gitblit.wicket.GitBlitWebApp; import com.gitblit.wicket.GitBlitWebSession; +import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.LinkPanel; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; +import org.apache.wicket.markup.html.panel.Fragment; +import org.apache.wicket.markup.repeater.Item; +import org.apache.wicket.markup.repeater.data.DataView; +import org.apache.wicket.markup.repeater.data.IDataProvider; +import org.apache.wicket.markup.repeater.data.ListDataProvider; +import org.apache.wicket.model.IModel; +import org.apache.wicket.Component; import org.apache.wicket.PageParameters; public class MyTicketsPage extends RootPage { @@ -34,103 +43,75 @@ public class MyTicketsPage extends RootPage { } String username = currentUser.getName(); + // TODO - Recover the Welcome message String message = "Welcome on GitBlit"; - this.add(new Label("myTicketsMessage", message)); + this.add(new Label("myTicketsMessage", message)); + + Fragment fragment = new Fragment("headerContent", "ticketsHeader", this); + add(fragment); ITicketService tickets = GitBlitWebApp.get().tickets(); List returnedTickets = tickets.getTickets(null); + List yourTickets = new ArrayList(); - List responsibleTickets = new ArrayList(); - List authorTickets = new ArrayList(); - List votedTickets = new ArrayList(); - List watchedTickets = new ArrayList(); for(int i = 0; i < returnedTickets.size(); i++) { TicketModel ticket = returnedTickets.get(i); if(ticket.isOpen()) { - if(ticket.isResponsible(username)) - { - responsibleTickets.add(ticket); - } - if(ticket.isAuthor(username)) - { - authorTickets.add(ticket); - } - if(ticket.isVoter(username)) + if(ticket.isResponsible(username) || ticket.isAuthor(username) + || ticket.isVoter(username) || ticket.isWatching(username)) { - votedTickets.add(ticket); - } - if(ticket.isWatching(username)) - { - watchedTickets.add(ticket); + yourTickets.add(ticket); } } } - ListView responsibleView = new ListView("responsibleTickets", responsibleTickets) - { - private static final long serialVersionUID = 1L; - - @Override - public void populateItem(final ListItem item) - { - final TicketModel ticket = item.getModelObject(); - String ticketUrl = app().tickets().getTicketUrl(ticket); - item.add(new Label("repositoryName", ticket.repository)); - item.add(new LinkPanel("ticketName", "", ticket.title, ticketUrl)); - item.add(new Label("ticketDescription", ticket.body)); - } - }; + final ListDataProvider dp = new ListDataProvider(yourTickets); - ListView authorView = new ListView("authorTickets", authorTickets) - { + DataView dataView = new DataView("row", dp) { private static final long serialVersionUID = 1L; - - @Override - public void populateItem(final ListItem item) - { - final TicketModel ticket = item.getModelObject(); - String ticketUrl = app().tickets().getTicketUrl(ticket); - item.add(new Label("repositoryName", ticket.repository)); - item.add(new LinkPanel("ticketName", "", ticket.title, ticketUrl)); - item.add(new Label("ticketDescription", ticket.body)); - } - }; - - ListView votedView = new ListView("votedTickets", votedTickets) - { - private static final long serialVersionUID = 1L; - - @Override - public void populateItem(final ListItem item) - { - final TicketModel ticket = item.getModelObject(); - String ticketUrl = app().tickets().getTicketUrl(ticket); - item.add(new Label("repositoryName", ticket.repository)); - item.add(new LinkPanel("ticketName", "", ticket.title, ticketUrl)); - item.add(new Label("ticketDescription", ticket.body)); - } - }; - - ListView watchedView = new ListView("watchedTickets", watchedTickets) - { - private static final long serialVersionUID = 1L; - + @Override - public void populateItem(final ListItem item) - { - final TicketModel ticket = item.getModelObject(); - String ticketUrl = app().tickets().getTicketUrl(ticket); - item.add(new Label("repositoryName", ticket.repository)); - item.add(new LinkPanel("ticketName", "", ticket.title, ticketUrl)); - item.add(new Label("ticketDescription", ticket.body)); + protected void populateItem(Item item) { + TicketModel ticketModel = item.getModelObject(); + RepositoryModel repository = app().repositories().getRepositoryModel(ticketModel.repository); + + Fragment row = new Fragment("rowContent", "ticketRow", this); + item.add(row); + + Component swatch; + if(repository.isBare) + { + swatch = new Label("repositorySwatch", " ").setEscapeModelStrings(false); + } + else + { + swatch = new Label("repositorySwatch", "!"); + WicketUtils.setHtmlTooltip(swatch, getString("gb.workingCopyWarning")); + } + WicketUtils.setCssBackground(swatch, repository.toString()); + row.add(swatch); + + PageParameters pp = WicketUtils.newRepositoryParameter(repository.name); + Class linkPage; + if (repository.hasCommits) { + // repository has content + linkPage = SummaryPage.class; + } else { + // new/empty repository OR proposed repository + linkPage = EmptyRepositoryPage.class; + } + + String ticketUrl = app().tickets().getTicketUrl(ticketModel); + + row.add(new LinkPanel("repositoryName", "list", repository.name, linkPage, pp)); + row.add(new LinkPanel("ticketName", "list", ticketModel.title, ticketUrl)); + row.add(new LinkPanel("ticketDescription", "list", ticketModel.body, ticketUrl)); + row.add(new Label("ticketResponsible", ticketModel.responsible)); } }; - add(responsibleView); - add(authorView); - add(votedView); - add(watchedView); + add(dataView); } } diff --git a/src/main/resources/gitblit.css b/src/main/resources/gitblit.css index 748a3198..ea663a66 100644 --- a/src/main/resources/gitblit.css +++ b/src/main/resources/gitblit.css @@ -1599,6 +1599,54 @@ table.repositories tr.group td a { color: black; } +table.tickets { + border:1px solid #ddd; + border-spacing: 0px; + width: 100%; +} + +table.tickets th { + padding: 4px; + border:0; +} + +table.tickets th.right { + border-right: 1px solid #ddd; +} + +table.tickets td { + padding: 2px; + border-left: 0; +} + +table.tickets td.rightAlign { + text-align: right; + border-right: 1px solid #ddd; +} + +table.tickets td.icon img { + vertical-align: top; +} + +table.tickets tr.group { + background-color: #ccc; + border-left: 1px solid #ccc; + border-right: 1px solid #ccc; +} + +table.tickets tr.group td { + font-weight: bold; + color: black; + background-color: #ddd; + padding-left: 5px; + border-top: 1px solid #aaa; + border-bottom: 1px solid #aaa; +} + +table.tickets tr.group td a { + color: black; +} + table.palette { border:0; width: 0 !important; } table.palette td.header { font-weight: bold; -- cgit v1.2.3 From f3b1e099e6ae252f1f1296ce5415b85fef6361cf Mon Sep 17 00:00:00 2001 From: Hybris95 Date: Fri, 18 Apr 2014 10:53:24 +0200 Subject: Added back the "my tickets" button in the navbar. --- src/main/java/com/gitblit/wicket/pages/RootPage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/RootPage.java b/src/main/java/com/gitblit/wicket/pages/RootPage.java index f43dc45e..ec413b19 100644 --- a/src/main/java/com/gitblit/wicket/pages/RootPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RootPage.java @@ -173,7 +173,7 @@ public abstract class RootPage extends BasePage { pages.add(new PageRegistration("gb.repositories", RepositoriesPage.class, getRootPageParameters())); pages.add(new PageRegistration("gb.activity", ActivityPage.class, getRootPageParameters())); - //pages.add(new PageRegistration("gb.mytickets", MyTicketsPage.class, getRootPageParameters())); + pages.add(new PageRegistration("gb.mytickets", MyTicketsPage.class, getRootPageParameters())); if (app().settings().getBoolean(Keys.web.allowLuceneIndexing, true)) { pages.add(new PageRegistration("gb.search", LuceneSearchPage.class)); } -- cgit v1.2.3 From e1fa9b763cadcdc44943f805aba83698acafa613 Mon Sep 17 00:00:00 2001 From: James Moger Date: Mon, 21 Apr 2014 21:55:48 -0400 Subject: Revisions demonstrating the direction I'd like this to go --- .../com/gitblit/wicket/pages/MyTicketsPage.html | 55 +++-- .../com/gitblit/wicket/pages/MyTicketsPage.java | 227 ++++++++++++++------- 2 files changed, 180 insertions(+), 102 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html index 5d11fbbb..063e7511 100644 --- a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html +++ b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html @@ -7,38 +7,35 @@
-
[my tickets message]
- - + + + + + + + + - - - - + + + + + + + +
+ + Repository + TicketStatusResponsible
+ + [repository name] + + [ticket icon] + [ticket title] + (#[ticket number]) + [ticket responsible]
- - - - - - Repository - - Ticket - Description - Responsible - - - - - - - [repository name] - - [ticket name] - [ticket description] - [ticket responsible] -
diff --git a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java index 6cd80a3f..2c57a051 100644 --- a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java +++ b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java @@ -1,41 +1,41 @@ package com.gitblit.wicket.pages; -import java.util.ArrayList; -import java.util.Iterator; import java.util.List; +import org.apache.wicket.Component; +import org.apache.wicket.PageParameters; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.repeater.Item; +import org.apache.wicket.markup.repeater.data.DataView; +import org.apache.wicket.markup.repeater.data.ListDataProvider; + import com.gitblit.models.RepositoryModel; -import com.gitblit.models.UserModel; import com.gitblit.models.TicketModel; +import com.gitblit.models.UserModel; +import com.gitblit.models.TicketModel.Status; +import com.gitblit.models.TicketModel.Type; import com.gitblit.tickets.ITicketService; +import com.gitblit.tickets.QueryBuilder; +import com.gitblit.tickets.QueryResult; +import com.gitblit.tickets.TicketIndexer.Lucene; +import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebApp; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; +import com.gitblit.wicket.panels.GravatarImage; import com.gitblit.wicket.panels.LinkPanel; -import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.html.list.ListItem; -import org.apache.wicket.markup.html.list.ListView; -import org.apache.wicket.markup.html.panel.Fragment; -import org.apache.wicket.markup.repeater.Item; -import org.apache.wicket.markup.repeater.data.DataView; -import org.apache.wicket.markup.repeater.data.IDataProvider; -import org.apache.wicket.markup.repeater.data.ListDataProvider; -import org.apache.wicket.model.IModel; -import org.apache.wicket.Component; -import org.apache.wicket.PageParameters; - public class MyTicketsPage extends RootPage { - public MyTicketsPage(PageParameters params) + public MyTicketsPage() { - this(); + this(null); } - public MyTicketsPage() + public MyTicketsPage(PageParameters params) { super(); - setupPage("", ""); + setupPage("", getString("gb.mytickets")); UserModel currentUser = GitBlitWebSession.get().getUser(); if (currentUser == null) { @@ -43,75 +43,156 @@ public class MyTicketsPage extends RootPage { } String username = currentUser.getName(); - // TODO - Recover the Welcome message - String message = "Welcome on GitBlit"; - this.add(new Label("myTicketsMessage", message)); - - Fragment fragment = new Fragment("headerContent", "ticketsHeader", this); - add(fragment); + QueryBuilder qb = QueryBuilder + .q(Lucene.createdby.matches(username)) + .or(Lucene.responsible.matches(username)) + .or(Lucene.watchedby.matches(username)); ITicketService tickets = GitBlitWebApp.get().tickets(); - List returnedTickets = tickets.getTickets(null); - List yourTickets = new ArrayList(); - - for(int i = 0; i < returnedTickets.size(); i++) - { - TicketModel ticket = returnedTickets.get(i); - if(ticket.isOpen()) - { - if(ticket.isResponsible(username) || ticket.isAuthor(username) - || ticket.isVoter(username) || ticket.isWatching(username)) - { - yourTickets.add(ticket); - } - } - } + List results = tickets.queryFor(qb.build(), 0, 0, Lucene.updated.name(), true); - final ListDataProvider dp = new ListDataProvider(yourTickets); + final ListDataProvider dp = new ListDataProvider(results); - DataView dataView = new DataView("row", dp) { + DataView dataView = new DataView("row", dp) { private static final long serialVersionUID = 1L; @Override - protected void populateItem(Item item) { - TicketModel ticketModel = item.getModelObject(); - RepositoryModel repository = app().repositories().getRepositoryModel(ticketModel.repository); - - Fragment row = new Fragment("rowContent", "ticketRow", this); - item.add(row); + protected void populateItem(Item item) { + QueryResult ticket = item.getModelObject(); + RepositoryModel repository = app().repositories().getRepositoryModel(ticket.repository); - Component swatch; - if(repository.isBare) - { - swatch = new Label("repositorySwatch", " ").setEscapeModelStrings(false); - } - else - { - swatch = new Label("repositorySwatch", "!"); - WicketUtils.setHtmlTooltip(swatch, getString("gb.workingCopyWarning")); - } + Component swatch = new Label("repositorySwatch", " ").setEscapeModelStrings(false); WicketUtils.setCssBackground(swatch, repository.toString()); - row.add(swatch); + item.add(swatch); - PageParameters pp = WicketUtils.newRepositoryParameter(repository.name); - Class linkPage; - if (repository.hasCommits) { - // repository has content - linkPage = SummaryPage.class; - } else { - // new/empty repository OR proposed repository - linkPage = EmptyRepositoryPage.class; - } + PageParameters rp = WicketUtils.newRepositoryParameter(ticket.repository); + PageParameters tp = WicketUtils.newObjectParameter(ticket.repository, "" + ticket.number); + item.add(new LinkPanel("repositoryName", "list", StringUtils.stripDotGit(ticket.repository), SummaryPage.class, rp)); - String ticketUrl = app().tickets().getTicketUrl(ticketModel); + item.add(getStateIcon("ticketIcon", ticket.type, ticket.status)); + item.add(new Label("ticketNumber", "" + ticket.number)); + item.add(new LinkPanel("ticketTitle", "list", ticket.title, TicketsPage.class, tp)); + + // votes indicator + Label v = new Label("ticketVotes", "" + ticket.votesCount); + WicketUtils.setHtmlTooltip(v, getString("gb.votes")); + item.add(v.setVisible(ticket.votesCount > 0)); + + Label ticketStatus = new Label("ticketStatus", ticket.status.toString()); + String statusClass = getStatusClass(ticket.status); + WicketUtils.setCssClass(ticketStatus, statusClass); + item.add(ticketStatus); - row.add(new LinkPanel("repositoryName", "list", repository.name, linkPage, pp)); - row.add(new LinkPanel("ticketName", "list", ticketModel.title, ticketUrl)); - row.add(new LinkPanel("ticketDescription", "list", ticketModel.body, ticketUrl)); - row.add(new Label("ticketResponsible", ticketModel.responsible)); + UserModel responsible = app().users().getUserModel(ticket.responsible); + if (responsible == null) { + if (ticket.responsible == null) { + item.add(new Label("ticketResponsibleImg").setVisible(false)); + } else { + item.add(new GravatarImage("ticketResponsibleImg", ticket.responsible, ticket.responsible, null, 16, true)); + } + item.add(new Label("ticketResponsible", ticket.responsible)); + } else { + item.add(new GravatarImage("ticketResponsibleImg", responsible, null, 16, true)); + item.add(new LinkPanel("ticketResponsible", null, responsible.getDisplayName(), UserPage.class, WicketUtils.newUsernameParameter(ticket.responsible))); + } } }; 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; + } } -- cgit v1.2.3 From 4640f1b689684b805f08a5a937e91dfc65ae977f Mon Sep 17 00:00:00 2001 From: Hybris95 Date: Tue, 22 Apr 2014 12:23:03 +0200 Subject: Now only shows the "my tickets" button in the navbar if you are connected. Redirects to the main page if you try going on "/mytickets" when not connected (or if you disconnect while being on "/mytickets"). --- .../java/com/gitblit/wicket/pages/MyTicketsPage.java | 6 ++++-- src/main/java/com/gitblit/wicket/pages/RootPage.java | 17 +++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java index 2c57a051..9be3b125 100644 --- a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java +++ b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java @@ -34,12 +34,14 @@ public class MyTicketsPage extends RootPage { public MyTicketsPage(PageParameters params) { - super(); + super(params); setupPage("", getString("gb.mytickets")); UserModel currentUser = GitBlitWebSession.get().getUser(); if (currentUser == null) { - currentUser = UserModel.ANONYMOUS; + setRedirect(true); + setResponsePage(getApplication().getHomePage()); + return; } String username = currentUser.getName(); diff --git a/src/main/java/com/gitblit/wicket/pages/RootPage.java b/src/main/java/com/gitblit/wicket/pages/RootPage.java index ec413b19..a4d2353d 100644 --- a/src/main/java/com/gitblit/wicket/pages/RootPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RootPage.java @@ -134,6 +134,8 @@ public abstract class RootPage extends BasePage { boolean authenticateView = app().settings().getBoolean(Keys.web.authenticateViewPages, false); boolean authenticateAdmin = app().settings().getBoolean(Keys.web.authenticateAdminPages, true); boolean allowAdmin = app().settings().getBoolean(Keys.web.allowAdministration, true); + boolean allowLucene = app().settings().getBoolean(Keys.web.allowLuceneIndexing, true); + boolean isLoggedIn = GitBlitWebSession.get().isLoggedIn(); if (authenticateAdmin) { showAdmin = allowAdmin && GitBlitWebSession.get().canAdmin(); @@ -151,7 +153,7 @@ public abstract class RootPage extends BasePage { } if (authenticateView || authenticateAdmin) { - if (GitBlitWebSession.get().isLoggedIn()) { + if (isLoggedIn) { UserMenu userFragment = new UserMenu("userPanel", "userMenuFragment", RootPage.this); add(userFragment); } else { @@ -167,14 +169,17 @@ public abstract class RootPage extends BasePage { // navigation links List pages = new ArrayList(); - if (!authenticateView || (authenticateView && GitBlitWebSession.get().isLoggedIn())) { - pages.add(new PageRegistration(GitBlitWebSession.get().isLoggedIn() ? "gb.myDashboard" : "gb.dashboard", MyDashboardPage.class, + if (!authenticateView || (authenticateView && isLoggedIn)) { + pages.add(new PageRegistration(isLoggedIn ? "gb.myDashboard" : "gb.dashboard", MyDashboardPage.class, getRootPageParameters())); pages.add(new PageRegistration("gb.repositories", RepositoriesPage.class, getRootPageParameters())); pages.add(new PageRegistration("gb.activity", ActivityPage.class, getRootPageParameters())); - pages.add(new PageRegistration("gb.mytickets", MyTicketsPage.class, getRootPageParameters())); - if (app().settings().getBoolean(Keys.web.allowLuceneIndexing, true)) { + if(isLoggedIn) + { + pages.add(new PageRegistration("gb.mytickets", MyTicketsPage.class, getRootPageParameters())); + } + if (allowLucene) { pages.add(new PageRegistration("gb.search", LuceneSearchPage.class)); } if (showAdmin) { @@ -184,7 +189,7 @@ public abstract class RootPage extends BasePage { pages.add(new PageRegistration("gb.federation", FederationPage.class)); } - if (!authenticateView || (authenticateView && GitBlitWebSession.get().isLoggedIn())) { + if (!authenticateView || (authenticateView && isLoggedIn)) { addDropDownMenus(pages); } } -- cgit v1.2.3 From e7f65dfe56b5b6325a7d7b42f877ae8d63fa4f71 Mon Sep 17 00:00:00 2001 From: Hybris95 Date: Tue, 22 Apr 2014 16:21:35 +0200 Subject: Advanced "my tickets" page. Using filters and search. --- .../com/gitblit/wicket/pages/MyTicketsPage.html | 117 +++++-- .../com/gitblit/wicket/pages/MyTicketsPage.java | 370 ++++++++++++++++++++- 2 files changed, 452 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html index 063e7511..459d2551 100644 --- a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html +++ b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html @@ -7,35 +7,94 @@
- - - - - - - - - - - - - - - - - - -
- - Repository - TicketStatusResponsible
- - [repository name] - - [ticket icon] - [ticket title] - (#[ticket number]) - [ticket responsible]
+ + +
+ +
+ + +
+
+
+ +
+
+ +
+
+ + +
+
+
+ : + +
+ +
+ : + +
+ +
+ +
+
+ + + + + + + + + + +
+ + [repository name] + + [ticket icon] + [ticket title] + (#[ticket number]) + [ticket responsible]
+
+
+
+
diff --git a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java index 9be3b125..01a30181 100644 --- a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java +++ b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java @@ -1,14 +1,24 @@ 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.Component; import org.apache.wicket.PageParameters; 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.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 com.gitblit.Keys; import com.gitblit.models.RepositoryModel; import com.gitblit.models.TicketModel; import com.gitblit.models.UserModel; @@ -18,14 +28,20 @@ import com.gitblit.tickets.ITicketService; import com.gitblit.tickets.QueryBuilder; import com.gitblit.tickets.QueryResult; import com.gitblit.tickets.TicketIndexer.Lucene; +import com.gitblit.utils.ArrayUtils; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebApp; import com.gitblit.wicket.GitBlitWebSession; +import com.gitblit.wicket.SessionlessForm; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.GravatarImage; import com.gitblit.wicket.panels.LinkPanel; 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() { @@ -43,15 +59,205 @@ public class MyTicketsPage extends RootPage { setResponsePage(getApplication().getHomePage()); return; } - String username = currentUser.getName(); - QueryBuilder qb = QueryBuilder - .q(Lucene.createdby.matches(username)) - .or(Lucene.responsible.matches(username)) - .or(Lucene.watchedby.matches(username)); + final String username = currentUser.getName(); + final String[] statiiParam = (params == null) ? new String[0] : 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 searchParam = (params == null) ? "" : params.getString("s", 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 search form + TicketSearchForm searchForm = new TicketSearchForm("ticketSearchForm", searchParam); + add(searchForm); + searchForm.setTranslatedAttributes(); + + // standard queries + add(new BookmarkablePageLink("changesQuery", MyTicketsPage.class, + queryParameters( + Lucene.type.matches(TicketModel.Type.Proposal.name()), + milestoneParam, + statiiParam, + assignedToParam, + sortBy, + desc, + 1))); + + add(new BookmarkablePageLink("bugsQuery", MyTicketsPage.class, + queryParameters( + Lucene.type.matches(TicketModel.Type.Bug.name()), + milestoneParam, + statiiParam, + assignedToParam, + sortBy, + desc, + 1))); + + add(new BookmarkablePageLink("enhancementsQuery", MyTicketsPage.class, + queryParameters( + Lucene.type.matches(TicketModel.Type.Enhancement.name()), + milestoneParam, + statiiParam, + assignedToParam, + sortBy, + desc, + 1))); + + add(new BookmarkablePageLink("tasksQuery", MyTicketsPage.class, + queryParameters( + Lucene.type.matches(TicketModel.Type.Task.name()), + milestoneParam, + statiiParam, + assignedToParam, + sortBy, + desc, + 1))); + + add(new BookmarkablePageLink("questionsQuery", MyTicketsPage.class, + queryParameters( + Lucene.type.matches(TicketModel.Type.Question.name()), + milestoneParam, + statiiParam, + assignedToParam, + sortBy, + desc, + 1))); + + add(new BookmarkablePageLink("resetQuery", MyTicketsPage.class, + queryParameters( + null, + milestoneParam, + openStatii, + null, + null, + true, + 1))); + + add(new Label("userDivider")); + add(new BookmarkablePageLink("createdQuery", MyTicketsPage.class, + queryParameters( + Lucene.createdby.matches(username), + milestoneParam, + statiiParam, + assignedToParam, + sortBy, + desc, + 1))); + + add(new BookmarkablePageLink("watchedQuery", MyTicketsPage.class, + queryParameters( + Lucene.watchedby.matches(username), + milestoneParam, + statiiParam, + assignedToParam, + sortBy, + desc, + 1))); + add(new BookmarkablePageLink("mentionsQuery", MyTicketsPage.class, + queryParameters( + Lucene.mentions.matches(username), + milestoneParam, + statiiParam, + assignedToParam, + sortBy, + desc, + 1))); + + // states + if (ArrayUtils.isEmpty(statiiParam)) { + add(new Label("selectedStatii", getString("gb.all"))); + } else { + add(new Label("selectedStatii", StringUtils.flattenStrings(Arrays.asList(statiiParam), ","))); + } + add(new BookmarkablePageLink("openTickets", MyTicketsPage.class, queryParameters(queryParam, milestoneParam, openStatii, assignedToParam, sortBy, desc, 1))); + add(new BookmarkablePageLink("closedTickets", MyTicketsPage.class, queryParameters(queryParam, milestoneParam, closedStatii, assignedToParam, sortBy, desc, 1))); + add(new BookmarkablePageLink("allTickets", MyTicketsPage.class, queryParameters(queryParam, milestoneParam, null, assignedToParam, sortBy, desc, 1))); + + // by status + List statii = new ArrayList(Arrays.asList(Status.values())); + statii.remove(Status.Closed); + ListDataProvider resolutionsDp = new ListDataProvider(statii); + DataView statiiLinks = new DataView("statii", resolutionsDp) { + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(final Item item) { + final Status status = item.getModelObject(); + PageParameters p = queryParameters(queryParam, milestoneParam, new String [] { status.name().toLowerCase() }, assignedToParam, sortBy, desc, 1); + String css = getStatusClass(status); + item.add(new LinkPanel("statusLink", css, status.toString(), MyTicketsPage.class, p).setRenderBodyOnly(true)); + } + }; + add(statiiLinks); + + List sortChoices = new ArrayList(); + sortChoices.add(new TicketSort(getString("gb.sortNewest"), Lucene.created.name(), true)); + sortChoices.add(new TicketSort(getString("gb.sortOldest"), Lucene.created.name(), false)); + sortChoices.add(new TicketSort(getString("gb.sortMostRecentlyUpdated"), Lucene.updated.name(), true)); + sortChoices.add(new TicketSort(getString("gb.sortLeastRecentlyUpdated"), Lucene.updated.name(), false)); + sortChoices.add(new TicketSort(getString("gb.sortMostComments"), Lucene.comments.name(), true)); + sortChoices.add(new TicketSort(getString("gb.sortLeastComments"), Lucene.comments.name(), false)); + sortChoices.add(new TicketSort(getString("gb.sortMostPatchsetRevisions"), Lucene.patchsets.name(), true)); + sortChoices.add(new TicketSort(getString("gb.sortLeastPatchsetRevisions"), Lucene.patchsets.name(), false)); + sortChoices.add(new TicketSort(getString("gb.sortMostVotes"), Lucene.votes.name(), true)); + sortChoices.add(new TicketSort(getString("gb.sortLeastVotes"), Lucene.votes.name(), false)); + + TicketSort currentSort = sortChoices.get(0); + for (TicketSort ts : sortChoices) { + if (ts.sortBy.equals(sortBy) && desc == ts.desc) { + currentSort = ts; + break; + } + } + add(new Label("currentSort", currentSort.name)); + + ListDataProvider sortChoicesDp = new ListDataProvider(sortChoices); + DataView sortMenu = new DataView("sort", sortChoicesDp) { + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(final Item item) { + final TicketSort ts = item.getModelObject(); + PageParameters params = queryParameters(queryParam, milestoneParam, statiiParam, assignedToParam, ts.sortBy, ts.desc, 1); + item.add(new LinkPanel("sortLink", null, ts.name, MyTicketsPage.class, params).setRenderBodyOnly(true)); + } + }; + add(sortMenu); + + // Build Query here + QueryBuilder qb = new QueryBuilder(queryParam); + if (!qb.containsField(Lucene.responsible.name())) { + // specify the responsible + qb.and(Lucene.responsible.matches(assignedToParam)); + } + if (!qb.containsField(Lucene.milestone.name())) { + // specify the milestone + qb.and(Lucene.milestone.matches(milestoneParam)); + } + if (!qb.containsField(Lucene.status.name()) && !ArrayUtils.isEmpty(statiiParam)) { + // specify the states + boolean not = false; + QueryBuilder q = new QueryBuilder(); + for (String state : statiiParam) { + if (state.charAt(0) == '!') { + not = true; + q.and(Lucene.status.doesNotMatch(state.substring(1))); + } else { + q.or(Lucene.status.matches(state)); + } + } + if (not) { + qb.and(q.toString()); + } else { + qb.and(q.toSubquery().toString()); + } + } + final String luceneQuery = qb.build(); ITicketService tickets = GitBlitWebApp.get().tickets(); - List results = tickets.queryFor(qb.build(), 0, 0, Lucene.updated.name(), true); + List results = tickets.queryFor(luceneQuery, 0, 0, Lucene.updated.name(), true); final ListDataProvider dp = new ListDataProvider(results); @@ -100,6 +306,12 @@ public class MyTicketsPage extends RootPage { } }; + // paging links + int page = (params != null) ? Math.max(1, WicketUtils.getPage(params)) : 1; + int pageSize = app().settings().getInteger(Keys.tickets.perPage, 25); + int totalResults = results.size() == 0 ? 0 : results.get(0).totalResults; + buildPager(queryParam, milestoneParam, statiiParam, assignedToParam, sortBy, desc, page, pageSize, results.size(), totalResults); + add(dataView); } @@ -197,4 +409,150 @@ public class MyTicketsPage extends RootPage { 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 implements Serializable { + private static final long serialVersionUID = 1L; + + private final IModel searchBoxModel;; + + public TicketSearchForm(String id, String text) { + super(id, MyTicketsPage.this.getClass(), MyTicketsPage.this.getPageParameters()); + + this.searchBoxModel = new Model(text == null ? "" : text); + + TextField searchBox = new TextField("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)); + } + } + + protected PageParameters queryParameters( + String query, + String milestone, + String[] states, + String assignedTo, + String sort, + boolean descending, + int page) { + + PageParameters params = WicketUtils.newRepositoryParameter(""); + if (!StringUtils.isEmpty(query)) { + params.add("q", query); + } + if (!StringUtils.isEmpty(milestone)) { + params.add(Lucene.milestone.name(), milestone); + } + if (!ArrayUtils.isEmpty(states)) { + for (String state : states) { + params.add(Lucene.status.name(), state); + } + } + if (!StringUtils.isEmpty(assignedTo)) { + params.add(Lucene.responsible.name(), assignedTo); + } + if (!StringUtils.isEmpty(sort)) { + params.add("sort", sort); + } + if (!descending) { + params.add("direction", "asc"); + } + if (page > 1) { + params.add("pg", "" + page); + } + return params; + } + + protected void buildPager( + final String query, + final String milestone, + final String [] states, + final String assignedTo, + final String sort, + final boolean desc, + final int page, + int pageSize, + int count, + int total) { + + boolean showNav = total > (2 * pageSize); + boolean allowPrev = page > 1; + boolean allowNext = (pageSize * (page - 1) + count) < total; + add(new BookmarkablePageLink("prevLink", TicketsPage.class, queryParameters(query, milestone, states, assignedTo, sort, desc, page - 1)).setEnabled(allowPrev).setVisible(showNav)); + add(new BookmarkablePageLink("nextLink", TicketsPage.class, queryParameters(query, milestone, states, assignedTo, sort, desc, page + 1)).setEnabled(allowNext).setVisible(showNav)); + + if (total <= pageSize) { + add(new Label("pageLink").setVisible(false)); + return; + } + + // determine page numbers to display + int pages = count == 0 ? 0 : ((total / pageSize) + (total % pageSize == 0 ? 0 : 1)); + // preferred number of pagelinks + int segments = 5; + if (pages < segments) { + // not enough data for preferred number of page links + segments = pages; + } + int minpage = Math.min(Math.max(1, page - 2), pages - (segments - 1)); + int maxpage = Math.min(pages, minpage + (segments - 1)); + List sequence = new ArrayList(); + for (int i = minpage; i <= maxpage; i++) { + sequence.add(i); + } + + ListDataProvider pagesDp = new ListDataProvider(sequence); + DataView pagesView = new DataView("pageLink", pagesDp) { + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(final Item item) { + final Integer i = item.getModelObject(); + LinkPanel link = new LinkPanel("page", null, "" + i, TicketsPage.class, queryParameters(query, milestone, states, assignedTo, sort, desc, i)); + link.setRenderBodyOnly(true); + if (i == page) { + WicketUtils.setCssClass(item, "active"); + } + item.add(link); + } + }; + add(pagesView); + } } -- cgit v1.2.3 From 3f5b8f5d9203aa7ffb7fbe9cdbaf9dba3da6cae6 Mon Sep 17 00:00:00 2001 From: Hybris95 Date: Tue, 22 Apr 2014 17:10:33 +0200 Subject: Fixes sort, page building and search functions on "my tickets" page. --- .../com/gitblit/wicket/pages/MyTicketsPage.java | 30 ++++++++++++++-------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java index 01a30181..32cdaec3 100644 --- a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java +++ b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java @@ -61,7 +61,7 @@ public class MyTicketsPage extends RootPage { } final String username = currentUser.getName(); - final String[] statiiParam = (params == null) ? new String[0] : params.getStringArray(Lucene.status.name()); + final String[] statiiParam = (params == null) ? 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); @@ -256,8 +256,22 @@ public class MyTicketsPage extends RootPage { } final String luceneQuery = qb.build(); + // paging links + 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 results = tickets.queryFor(luceneQuery, 0, 0, Lucene.updated.name(), true); + List results; + if(StringUtils.isEmpty(searchParam)) + { + results = tickets.queryFor(luceneQuery, page, pageSize, sortBy, desc); + } + else + { + results = 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 ListDataProvider dp = new ListDataProvider(results); @@ -306,12 +320,6 @@ public class MyTicketsPage extends RootPage { } }; - // paging links - int page = (params != null) ? Math.max(1, WicketUtils.getPage(params)) : 1; - int pageSize = app().settings().getInteger(Keys.tickets.perPage, 25); - int totalResults = results.size() == 0 ? 0 : results.get(0).totalResults; - buildPager(queryParam, milestoneParam, statiiParam, assignedToParam, sortBy, desc, page, pageSize, results.size(), totalResults); - add(dataView); } @@ -515,8 +523,8 @@ public class MyTicketsPage extends RootPage { boolean showNav = total > (2 * pageSize); boolean allowPrev = page > 1; boolean allowNext = (pageSize * (page - 1) + count) < total; - add(new BookmarkablePageLink("prevLink", TicketsPage.class, queryParameters(query, milestone, states, assignedTo, sort, desc, page - 1)).setEnabled(allowPrev).setVisible(showNav)); - add(new BookmarkablePageLink("nextLink", TicketsPage.class, queryParameters(query, milestone, states, assignedTo, sort, desc, page + 1)).setEnabled(allowNext).setVisible(showNav)); + add(new BookmarkablePageLink("prevLink", MyTicketsPage.class, queryParameters(query, milestone, states, assignedTo, sort, desc, page - 1)).setEnabled(allowPrev).setVisible(showNav)); + add(new BookmarkablePageLink("nextLink", MyTicketsPage.class, queryParameters(query, milestone, states, assignedTo, sort, desc, page + 1)).setEnabled(allowNext).setVisible(showNav)); if (total <= pageSize) { add(new Label("pageLink").setVisible(false)); @@ -545,7 +553,7 @@ public class MyTicketsPage extends RootPage { @Override public void populateItem(final Item item) { final Integer i = item.getModelObject(); - LinkPanel link = new LinkPanel("page", null, "" + i, TicketsPage.class, queryParameters(query, milestone, states, assignedTo, sort, desc, i)); + LinkPanel link = new LinkPanel("page", null, "" + i, MyTicketsPage.class, queryParameters(query, milestone, states, assignedTo, sort, desc, i)); link.setRenderBodyOnly(true); if (i == page) { WicketUtils.setCssClass(item, "active"); -- cgit v1.2.3 From 6f9908aa9ebcdfbb32e8305b157be177071abe56 Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 24 Apr 2014 14:05:36 -0400 Subject: Do not display My Tickets link if ticket service is not ready --- src/main/java/com/gitblit/wicket/pages/RootPage.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/RootPage.java b/src/main/java/com/gitblit/wicket/pages/RootPage.java index a4d2353d..fb68208f 100644 --- a/src/main/java/com/gitblit/wicket/pages/RootPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RootPage.java @@ -172,13 +172,12 @@ public abstract class RootPage extends BasePage { if (!authenticateView || (authenticateView && isLoggedIn)) { pages.add(new PageRegistration(isLoggedIn ? "gb.myDashboard" : "gb.dashboard", MyDashboardPage.class, getRootPageParameters())); + if (isLoggedIn && app().tickets().isReady()) { + pages.add(new PageRegistration("gb.mytickets", MyTicketsPage.class)); + } pages.add(new PageRegistration("gb.repositories", RepositoriesPage.class, getRootPageParameters())); pages.add(new PageRegistration("gb.activity", ActivityPage.class, getRootPageParameters())); - if(isLoggedIn) - { - pages.add(new PageRegistration("gb.mytickets", MyTicketsPage.class, getRootPageParameters())); - } if (allowLucene) { pages.add(new PageRegistration("gb.search", LuceneSearchPage.class)); } -- cgit v1.2.3 From b3f70e7ed4b4c59fc578f529411f41e3fd6b192f Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 24 Apr 2014 14:06:36 -0400 Subject: Improve generated Lucene query to only show relevant My Tickets results --- .../com/gitblit/wicket/pages/MyTicketsPage.java | 67 ++++++++++++---------- 1 file changed, 37 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java index 32cdaec3..083526b6 100644 --- a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java +++ b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.java @@ -21,9 +21,9 @@ import org.apache.wicket.request.target.basic.RedirectRequestTarget; import com.gitblit.Keys; import com.gitblit.models.RepositoryModel; import com.gitblit.models.TicketModel; -import com.gitblit.models.UserModel; 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; @@ -42,24 +42,24 @@ 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() { - this(null); + this(null); } - + public MyTicketsPage(PageParameters params) { super(params); setupPage("", getString("gb.mytickets")); - + UserModel currentUser = GitBlitWebSession.get().getUser(); if (currentUser == null) { setRedirect(true); setResponsePage(getApplication().getHomePage()); return; } - + final String username = currentUser.getName(); final String[] statiiParam = (params == null) ? openStatii : params.getStringArray(Lucene.status.name()); final String assignedToParam = (params == null) ? "" : params.getString(Lucene.responsible.name(), null); @@ -68,12 +68,12 @@ public class MyTicketsPage extends RootPage { final String searchParam = (params == null) ? "" : params.getString("s", 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 search form TicketSearchForm searchForm = new TicketSearchForm("ticketSearchForm", searchParam); add(searchForm); searchForm.setTranslatedAttributes(); - + // standard queries add(new BookmarkablePageLink("changesQuery", MyTicketsPage.class, queryParameters( @@ -164,7 +164,7 @@ public class MyTicketsPage extends RootPage { sortBy, desc, 1))); - + // states if (ArrayUtils.isEmpty(statiiParam)) { add(new Label("selectedStatii", getString("gb.all"))); @@ -174,7 +174,7 @@ public class MyTicketsPage extends RootPage { add(new BookmarkablePageLink("openTickets", MyTicketsPage.class, queryParameters(queryParam, milestoneParam, openStatii, assignedToParam, sortBy, desc, 1))); add(new BookmarkablePageLink("closedTickets", MyTicketsPage.class, queryParameters(queryParam, milestoneParam, closedStatii, assignedToParam, sortBy, desc, 1))); add(new BookmarkablePageLink("allTickets", MyTicketsPage.class, queryParameters(queryParam, milestoneParam, null, assignedToParam, sortBy, desc, 1))); - + // by status List statii = new ArrayList(Arrays.asList(Status.values())); statii.remove(Status.Closed); @@ -225,17 +225,9 @@ public class MyTicketsPage extends RootPage { } }; add(sortMenu); - + // Build Query here QueryBuilder qb = new QueryBuilder(queryParam); - if (!qb.containsField(Lucene.responsible.name())) { - // specify the responsible - qb.and(Lucene.responsible.matches(assignedToParam)); - } - if (!qb.containsField(Lucene.milestone.name())) { - // specify the milestone - qb.and(Lucene.milestone.matches(milestoneParam)); - } if (!qb.containsField(Lucene.status.name()) && !ArrayUtils.isEmpty(statiiParam)) { // specify the states boolean not = false; @@ -254,12 +246,27 @@ public class MyTicketsPage extends RootPage { qb.and(q.toSubquery().toString()); } } - final String luceneQuery = qb.build(); - + + final String luceneQuery; + if (qb.containsField(Lucene.createdby.name()) + || qb.containsField(Lucene.responsible.name()) + || qb.containsField(Lucene.watchedby.name())) { + // focused "my tickets" query + luceneQuery = qb.build(); + } else { + // general "my tickets" query + QueryBuilder myQuery = new QueryBuilder(); + myQuery.or(Lucene.createdby.matches(username)); + myQuery.or(Lucene.responsible.matches(username)); + myQuery.or(Lucene.watchedby.matches(username)); + myQuery.and(qb.toSubquery().toString()); + luceneQuery = myQuery.build(); + } + // paging links 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 results; if(StringUtils.isEmpty(searchParam)) @@ -272,9 +279,9 @@ public class MyTicketsPage extends RootPage { } int totalResults = results.size() == 0 ? 0 : results.get(0).totalResults; buildPager(queryParam, milestoneParam, statiiParam, assignedToParam, sortBy, desc, page, pageSize, results.size(), totalResults); - + final ListDataProvider dp = new ListDataProvider(results); - + DataView dataView = new DataView("row", dp) { private static final long serialVersionUID = 1L; @@ -282,15 +289,15 @@ public class MyTicketsPage extends RootPage { protected void populateItem(Item item) { QueryResult ticket = item.getModelObject(); RepositoryModel repository = app().repositories().getRepositoryModel(ticket.repository); - + Component swatch = new Label("repositorySwatch", " ").setEscapeModelStrings(false); WicketUtils.setCssBackground(swatch, repository.toString()); item.add(swatch); - + PageParameters rp = WicketUtils.newRepositoryParameter(ticket.repository); PageParameters tp = WicketUtils.newObjectParameter(ticket.repository, "" + ticket.number); item.add(new LinkPanel("repositoryName", "list", StringUtils.stripDotGit(ticket.repository), SummaryPage.class, rp)); - + item.add(getStateIcon("ticketIcon", ticket.type, ticket.status)); item.add(new Label("ticketNumber", "" + ticket.number)); item.add(new LinkPanel("ticketTitle", "list", ticket.title, TicketsPage.class, tp)); @@ -304,7 +311,7 @@ public class MyTicketsPage extends RootPage { String statusClass = getStatusClass(ticket.status); WicketUtils.setCssClass(ticketStatus, statusClass); item.add(ticketStatus); - + UserModel responsible = app().users().getUserModel(ticket.responsible); if (responsible == null) { if (ticket.responsible == null) { @@ -319,10 +326,10 @@ public class MyTicketsPage extends RootPage { } } }; - + add(dataView); } - + protected Label getStateIcon(String wicketId, TicketModel ticket) { return getStateIcon(wicketId, ticket.type, ticket.status); } -- cgit v1.2.3 From 4062e46eb07c4202d8872ecc02eb246304dda01e Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 24 Apr 2014 15:16:51 -0400 Subject: Revise My Tickets layout and styling --- .../com/gitblit/wicket/pages/MyTicketsPage.html | 183 ++++++++++-------- .../com/gitblit/wicket/pages/MyTicketsPage.java | 209 ++++++++++++++++++--- src/main/resources/gitblit.css | 48 ----- 3 files changed, 290 insertions(+), 150 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html index 459d2551..9ecc4b6e 100644 --- a/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html +++ b/src/main/java/com/gitblit/wicket/pages/MyTicketsPage.html @@ -8,94 +8,123 @@
- -
- @@ -41,9 +40,6 @@ This is what you should download if you want to go from zero to Git in less than ### WAR: For Your Servlet Container *Gitblit WAR* is what you should download if you already have a servlet container available that you wish to use. Jetty 6/7/8 and Tomcat 6/7 are known to work. Generally, any Servlet 2.5 or Servlet 3.0 container should work. -### Express: For the Cloud -*Gitblit Express* is a prepared distribution for [RedHat's OpenShift][rhcloud] cloud service. - ### You decide how to use Gitblit Gitblit can be used as a dumb repository viewer with no administrative controls or user accounts. @@ -81,4 +77,3 @@ Gitblit requires a Java 7 Runtime Environment (JRE) or a Java 7 Development Kit [jgit]: http://eclipse.org/jgit "Eclipse JGit Site" [git]: http://git-scm.com "Official Git Site" -[rhcloud]: https://openshift.redhat.com/app "RedHat OpenShift" diff --git a/src/site/upgrade_express.mkd b/src/site/upgrade_express.mkd deleted file mode 100644 index 9e1eed9d..00000000 --- a/src/site/upgrade_express.mkd +++ /dev/null @@ -1,23 +0,0 @@ -## Upgrading Gitblit Express - -1. Make a backup copy of */deployments/ROOT.war/WEB-INF/web.xml* -2. Delete your */deployments/ROOT.war* and then copy the new */deployments/ROOT.war* from the archive. -3. Diff your backup copy of web.xml with the pristine one you copied as part of */deployments/ROOT.war* and apply any necessary changes. - -These steps are necessary to ensure that you end up using the specified libraries and resources for the new version. Otherwise you could end up with a hybrid filesystem that would make it difficult to troubleshoot. It is important to note that the web.xml file contains both your default settings AND application configuration. Not updating the web.xml is just a likely to create problems as making a hybrid filesystem. - -### 1.3.1 web.xml - -- Changed *WicketFilter* to *GitblitWicketFilter* to handle optional, smart cache-control updates (issue-274) - -### 1.3.0 web.xml - -- Added LogoServlet -- Added SparkleShareInviteServlet -- Added EnforceAuthenticationFilter -- Moved GitServlet - -### 1.4.0 web.xml - -- Changed baseFolder from a context-parameter to a JNDI env-entry -- Added pt servlet \ No newline at end of file -- cgit v1.2.3 From b5e11d843b83261376552dd6fc26d346c82402a4 Mon Sep 17 00:00:00 2001 From: James Moger Date: Fri, 23 May 2014 11:39:06 -0400 Subject: Do not directly link to the EmptyRepositoryPage --- .../java/com/gitblit/wicket/panels/RepositoriesPanel.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java index d8e23bea..dd208e23 100644 --- a/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java @@ -52,7 +52,6 @@ import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.pages.BasePage; import com.gitblit.wicket.pages.EditRepositoryPage; -import com.gitblit.wicket.pages.EmptyRepositoryPage; import com.gitblit.wicket.pages.ProjectPage; import com.gitblit.wicket.pages.RepositoriesPage; import com.gitblit.wicket.pages.SummaryPage; @@ -204,15 +203,7 @@ public class RepositoriesPanel extends BasePanel { swatch.setVisible(showSwatch); if (linksActive) { - Class linkPage; - if (entry.hasCommits) { - // repository has content - linkPage = SummaryPage.class; - } else { - // new/empty repository OR proposed repository - linkPage = EmptyRepositoryPage.class; - } - + Class linkPage = SummaryPage.class; PageParameters pp = WicketUtils.newRepositoryParameter(entry.name); row.add(new LinkPanel("repositoryName", "list", repoName, linkPage, pp)); row.add(new LinkPanel("repositoryDescription", "list", entry.description, -- cgit v1.2.3 From fb9cd5968346045e1129406ca54639075316a396 Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 29 May 2014 12:40:35 -0400 Subject: Add setting to control thread pool size for default work queue --- releases.moxie | 2 ++ src/main/distrib/data/gitblit.properties | 6 ++++++ src/main/java/com/gitblit/manager/ServicesManager.java | 3 ++- 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/releases.moxie b/releases.moxie index 34f855bc..4332238d 100644 --- a/releases.moxie +++ b/releases.moxie @@ -38,6 +38,7 @@ r24: { - Add setting to allow STARTTLS without requiring SMTPS (pr-183) - Added an extension point for monitoring onStartup and onShutdown (ticket-79) - Tag server-side merges when incremental push tags are enabled (issue-432, ticket-85) + - Add setting to control default thread pool size for miscellaneous background tasks (ticket-92) dependencyChanges: - Update to javax.mail 1.5.1 (issue-417, ticket-58) contributors: @@ -53,6 +54,7 @@ r24: { settings: - { name: 'web.allowDeletingNonEmptyRepositories', defaultValue: 'true' } - { name: 'mail.starttls', defaultValue: 'false' } + - { name: 'execution.defaultThreadPoolSize', defaultValue: '1' } } # diff --git a/src/main/distrib/data/gitblit.properties b/src/main/distrib/data/gitblit.properties index 7d74c281..b27395c3 100644 --- a/src/main/distrib/data/gitblit.properties +++ b/src/main/distrib/data/gitblit.properties @@ -613,6 +613,12 @@ plugins.folder = ${baseFolder}/plugins # SINCE 1.5.0 plugins.registry = http://plugins.gitblit.com/plugins.json +# Number of threads used to handle miscellaneous tasks in the background. +# +# SINCE 1.6.0 +# RESTART REQUIRED +execution.defaultThreadPoolSize = 1 + # # Groovy Integration # diff --git a/src/main/java/com/gitblit/manager/ServicesManager.java b/src/main/java/com/gitblit/manager/ServicesManager.java index b1c97ba4..755d8bac 100644 --- a/src/main/java/com/gitblit/manager/ServicesManager.java +++ b/src/main/java/com/gitblit/manager/ServicesManager.java @@ -80,8 +80,9 @@ public class ServicesManager implements IManager { public ServicesManager(IGitblit gitblit) { this.settings = gitblit.getSettings(); this.gitblit = gitblit; + int defaultThreadPoolSize = settings.getInteger(Keys.execution.defaultThreadPoolSize, 1); this.idGenerator = new IdGenerator(); - this.workQueue = new WorkQueue(idGenerator, 1); + this.workQueue = new WorkQueue(idGenerator, defaultThreadPoolSize); } @Override -- cgit v1.2.3 From 9eff8aa74221277d878c174840e4cefdc9e954d8 Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 29 May 2014 17:14:58 -0400 Subject: Clarify server.threadPoolSize documentation --- src/main/distrib/data/gitblit.properties | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/main/distrib/data/gitblit.properties b/src/main/distrib/data/gitblit.properties index b27395c3..6f55a3eb 100644 --- a/src/main/distrib/data/gitblit.properties +++ b/src/main/distrib/data/gitblit.properties @@ -1795,7 +1795,8 @@ realm.ldap.removeDeletedUsers = true realm.redmine.url = http://example.com/redmine # -# Server Settings +# Gitblit GO Server Settings +# The following settings only affect the integrated GO variant. # # The temporary folder to decompress the embedded gitblit webapp. @@ -1805,7 +1806,9 @@ realm.redmine.url = http://example.com/redmine # BASEFOLDER server.tempFolder = ${baseFolder}/temp -# Specify the maximum number of concurrent http/https worker threads to allow. +# Specify the maximum number of concurrent http/https Jetty worker +# threads to allow. This setting does not affect other threaded +# daemons and components of Gitblit. # # SINCE 1.3.0 # RESTART REQUIRED -- cgit v1.2.3 From 0047fbba99b804d268a66ed7504a568596de6168 Mon Sep 17 00:00:00 2001 From: James Moger Date: Tue, 27 May 2014 18:13:30 -0400 Subject: Simplified repository creation with a NewRepositoryPage --- .gitmodules | 3 + build.xml | 6 + releases.moxie | 2 + src/main/distrib/data/gitblit.properties | 5 + src/main/distrib/data/gitignore | 1 + src/main/java/com/gitblit/Constants.java | 8 + .../java/com/gitblit/servlet/GitblitContext.java | 16 + .../java/com/gitblit/wicket/GitBlitWebApp.java | 10 + .../com/gitblit/wicket/GitBlitWebApp.properties | 17 +- .../gitblit/wicket/pages/EditRepositoryPage.java | 16 +- .../gitblit/wicket/pages/NewRepositoryPage.html | 98 ++++ .../gitblit/wicket/pages/NewRepositoryPage.java | 493 +++++++++++++++++++++ .../java/com/gitblit/wicket/pages/RootPage.java | 2 +- .../java/com/gitblit/wicket/pages/UserPage.java | 4 +- .../wicket/panels/FilterableRepositoryList.java | 3 +- .../gitblit/wicket/panels/RepositoriesPanel.java | 5 +- 16 files changed, 674 insertions(+), 15 deletions(-) create mode 100644 .gitmodules create mode 160000 src/main/distrib/data/gitignore create mode 100644 src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html create mode 100644 src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java (limited to 'src') diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..01eaa2c8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/main/distrib/data/gitignore"] + path = src/main/distrib/data/gitignore + url = https://github.com/github/gitignore.git diff --git a/build.xml b/build.xml index f45c4ca9..be6f1dd2 100644 --- a/build.xml +++ b/build.xml @@ -919,6 +919,12 @@ + + + + + + diff --git a/releases.moxie b/releases.moxie index 4332238d..5aa207fa 100644 --- a/releases.moxie +++ b/releases.moxie @@ -36,6 +36,7 @@ r24: { - Add FORK_REPOSITORY RPC request type (issue-371, pr-161, ticket-65) - Add object type (ot) parameter for RSS queries to retrieve tag details (pr-165, ticket-66) - Add setting to allow STARTTLS without requiring SMTPS (pr-183) + - Simplified repository creation, offer simple README generation, and insertion of a pre-defined .gitignore file (ticket-76) - Added an extension point for monitoring onStartup and onShutdown (ticket-79) - Tag server-side merges when incremental push tags are enabled (issue-432, ticket-85) - Add setting to control default thread pool size for miscellaneous background tasks (ticket-92) @@ -55,6 +56,7 @@ r24: { - { name: 'web.allowDeletingNonEmptyRepositories', defaultValue: 'true' } - { name: 'mail.starttls', defaultValue: 'false' } - { name: 'execution.defaultThreadPoolSize', defaultValue: '1' } + - { name: 'git.gitignoreFolder', defaultValue: '${baseFolder}/gitignore' } } # diff --git a/src/main/distrib/data/gitblit.properties b/src/main/distrib/data/gitblit.properties index 6f55a3eb..d5623cd5 100644 --- a/src/main/distrib/data/gitblit.properties +++ b/src/main/distrib/data/gitblit.properties @@ -271,6 +271,11 @@ git.defaultIncrementalPushTagPrefix = r # SINCE 1.4.0 git.createRepositoriesShared = false +# Directory for gitignore templates used during repository creation. +# +# SINCE 1.6.0 +git.gitignoreFolder = ${baseFolder}/gitignore + # Enable JGit-based garbage collection. (!!EXPERIMENTAL!!) # # USE AT YOUR OWN RISK! diff --git a/src/main/distrib/data/gitignore b/src/main/distrib/data/gitignore new file mode 160000 index 00000000..097db81c --- /dev/null +++ b/src/main/distrib/data/gitignore @@ -0,0 +1 @@ +Subproject commit 097db81c08b138dea7cb031eb18eeb16afe44bdf diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java index 95eb944a..3e307537 100644 --- a/src/main/java/com/gitblit/Constants.java +++ b/src/main/java/com/gitblit/Constants.java @@ -122,6 +122,14 @@ public class Constants { public static final String R_TICKETS_PATCHSETS = "refs/tickets/"; + public static final String R_MASTER = "refs/heads/master"; + + public static final String MASTER = "master"; + + public static final String R_DEVELOP = "refs/heads/develop"; + + public static final String DEVELOP = "develop"; + public static String getVersion() { String v = Constants.class.getPackage().getImplementationVersion(); if (v == null) { diff --git a/src/main/java/com/gitblit/servlet/GitblitContext.java b/src/main/java/com/gitblit/servlet/GitblitContext.java index 110e553c..50f22d5a 100644 --- a/src/main/java/com/gitblit/servlet/GitblitContext.java +++ b/src/main/java/com/gitblit/servlet/GitblitContext.java @@ -372,6 +372,22 @@ public class GitblitContext extends DaggerContext { } } + // Copy the included gitignore files to the configured gitignore folder + String gitignorePath = webxmlSettings.getString(Keys.git.gitignoreFolder, "gitignore"); + File localGitignores = com.gitblit.utils.FileUtils.resolveParameter(Constants.baseFolder$, base, gitignorePath); + if (!localGitignores.exists()) { + File warGitignores = new File(contextFolder, "/WEB-INF/data/gitignore"); + if (!warGitignores.equals(localGitignores)) { + try { + com.gitblit.utils.FileUtils.copy(localGitignores, warGitignores.listFiles()); + } catch (IOException e) { + logger.error(MessageFormat.format( + "Failed to copy included .gitignore files from {0} to {1}", + warGitignores, localGitignores)); + } + } + } + // merge the WebXmlSettings into the runtime settings (for backwards-compatibilty) runtimeSettings.merge(webxmlSettings); diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java index 7291d039..f63ff3d9 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java @@ -57,6 +57,7 @@ import com.gitblit.wicket.pages.ComparePage; import com.gitblit.wicket.pages.DocPage; import com.gitblit.wicket.pages.DocsPage; import com.gitblit.wicket.pages.EditMilestonePage; +import com.gitblit.wicket.pages.EditRepositoryPage; import com.gitblit.wicket.pages.EditTicketPage; import com.gitblit.wicket.pages.ExportTicketPage; import com.gitblit.wicket.pages.FederationRegistrationPage; @@ -71,6 +72,7 @@ import com.gitblit.wicket.pages.MetricsPage; import com.gitblit.wicket.pages.MyDashboardPage; import com.gitblit.wicket.pages.MyTicketsPage; import com.gitblit.wicket.pages.NewMilestonePage; +import com.gitblit.wicket.pages.NewRepositoryPage; import com.gitblit.wicket.pages.NewTicketPage; import com.gitblit.wicket.pages.OverviewPage; import com.gitblit.wicket.pages.PatchPage; @@ -92,6 +94,8 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { private final Class homePageClass = MyDashboardPage.class; + private final Class newRepositoryPageClass = NewRepositoryPage.class; + private final Map cacheablePages = new HashMap(); private final IStoredSettings settings; @@ -207,6 +211,8 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { mount("/proposal", ReviewProposalPage.class, "t"); mount("/registration", FederationRegistrationPage.class, "u", "n"); + mount("/new", NewRepositoryPage.class); + mount("/edit", EditRepositoryPage.class, "r"); mount("/activity", ActivityPage.class, "r", "h"); mount("/lucene", LuceneSearchPage.class); mount("/project", ProjectPage.class, "p"); @@ -262,6 +268,10 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { return homePageClass; } + public Class getNewRepositoryPage() { + return newRepositoryPageClass; + } + /* (non-Javadoc) * @see com.gitblit.wicket.Webapp#isCacheablePage(java.lang.String) */ diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 12430ade..ac589558 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -685,4 +685,19 @@ gb.closedMilestones = closed milestones gb.administration = administration gb.plugins = plugins gb.extensions = extensions - +gb.anonymous = Anonymous +gb.anonymousRepoDescription = Anyone can see, clone, and push to this repository. +gb.public = Public +gb.publicRepoDescription = Anyone can see and clone this repository. You choose who can push. +gb.protected = Protected +gb.protectedRepoDescription = Anyone can see this repository. You choose who can clone and push. +gb.private = Private +gb.privateRepoDescription = You choose who can see, clone, and push to this repository. +gb.initialCommit = Initial Commit +gb.initialCommitDescription = This will allow you to git clone this repository immediately. Skip this step if you have already run git init locally. +gb.initWithReadme = Include a README +gb.initWithReadmeDescription = This will generate a simple README document for your repository. +gb.initWithGitignore = Include a .gitignore file +gb.initWithGitignoreDescription = This will insert a config file that instructs your Git clients to ignore files or directories that match defined patterns. +gb.initWithGitflow = Include a .gitflow file +gb.initWithGitflowDescription = This will generate a config file which guides Git clients in setting up Gitflow branches. \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java index 412c0ecc..c18cd514 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java @@ -429,11 +429,7 @@ public class EditRepositoryPage extends RootSubPage { return; } setRedirect(false); - if (isCreate) { - setResponsePage(RepositoriesPage.class); - } else { - setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryModel.name)); - } + setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryModel.name)); } }; @@ -632,7 +628,15 @@ public class EditRepositoryPage extends RootSubPage { if (canDelete) { if (app().repositories().deleteRepositoryModel(latestModel)) { info(MessageFormat.format(getString("gb.repositoryDeleted"), latestModel)); - setResponsePage(RepositoriesPage.class); + if (latestModel.isPersonalRepository()) { + // redirect to user's profile page + String prefix = app().settings().getString(Keys.git.userRepositoryPrefix, "~"); + String username = latestModel.projectPath.substring(prefix.length()); + setResponsePage(UserPage.class, WicketUtils.newUsernameParameter(username)); + } else { + // redirect to server repositories page + setResponsePage(RepositoriesPage.class); + } } else { error(MessageFormat.format(getString("gb.repositoryDeleteFailed"), latestModel)); } diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html new file mode 100644 index 00000000..e9f12027 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html @@ -0,0 +1,98 @@ + + + + + +
+
+
+ + + + + + + + + + + + + + +
/  
+ +
+
+ +
+ +
+ + +
+
+ + +
+
+
+ +
+
+
+ +
+ +

+
+

+
+ +
+
+ +
+
+
+

+
+
+ +
+ +
+ +
+
+ +

+
+
+ +
+
+ +
+
+
+

+

+
+
+ + + + + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java new file mode 100644 index 00000000..b0cc3e95 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java @@ -0,0 +1,493 @@ +/* + * 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.File; +import java.io.IOException; +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.behavior.SimpleAttributeModifier; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.Button; +import org.apache.wicket.markup.html.form.CheckBox; +import org.apache.wicket.markup.html.form.DropDownChoice; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.form.Radio; +import org.apache.wicket.markup.html.form.RadioGroup; +import org.apache.wicket.markup.html.form.TextField; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; +import org.apache.wicket.model.CompoundPropertyModel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.eclipse.jgit.dircache.DirCache; +import org.eclipse.jgit.dircache.DirCacheBuilder; +import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.lib.CommitBuilder; +import org.eclipse.jgit.lib.Config; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectInserter; +import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.lib.RefUpdate; +import org.eclipse.jgit.lib.RefUpdate.Result; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; + +import com.gitblit.Constants; +import com.gitblit.Constants.AccessRestrictionType; +import com.gitblit.Constants.AuthorizationControl; +import com.gitblit.GitBlitException; +import com.gitblit.Keys; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.UserModel; +import com.gitblit.utils.ArrayUtils; +import com.gitblit.utils.FileUtils; +import com.gitblit.utils.StringUtils; +import com.gitblit.wicket.GitBlitWebSession; +import com.gitblit.wicket.WicketUtils; + +public class NewRepositoryPage extends RootSubPage { + + private final RepositoryModel repositoryModel; + private RadioGroup permissionGroup; + private IModel addReadmeModel; + private Model gitignoreModel; + private IModel addGitflowModel; + private IModel addGitignoreModel; + + public NewRepositoryPage() { + // create constructor + super(); + repositoryModel = new RepositoryModel(); + + setupPage(getString("gb.newRepository"), ""); + + setStatelessHint(false); + setOutputMarkupId(true); + } + + @Override + protected boolean requiresPageMap() { + return true; + } + + @Override + protected Class getRootNavPageClass() { + return RepositoriesPage.class; + } + + @Override + protected void onInitialize() { + super.onInitialize(); + + CompoundPropertyModel rModel = new CompoundPropertyModel<>(repositoryModel); + Form form = new Form("editForm", rModel) { + + private static final long serialVersionUID = 1L; + + @Override + protected void onSubmit() { + + // confirm a repository name was entered + if (StringUtils.isEmpty(repositoryModel.name)) { + error(getString("gb.pleaseSetRepositoryName")); + return; + } + + String project = repositoryModel.projectPath; + String fullName = (project + "/" + repositoryModel.name).trim(); + fullName = fullName.replace('\\', '/'); + fullName = fullName.replace("//", "/"); + if (fullName.charAt(0) == '/') { + fullName = fullName.substring(1); + } + if (fullName.endsWith("/")) { + fullName = fullName.substring(0, fullName.length() - 1); + } + + try { + if (fullName.contains("../")) { + error(getString("gb.illegalRelativeSlash")); + return; + } + if (fullName.contains("/../")) { + error(getString("gb.illegalRelativeSlash")); + return; + } + + // confirm valid characters in repository name + Character c = StringUtils.findInvalidCharacter(fullName); + if (c != null) { + error(MessageFormat.format(getString("gb.illegalCharacterRepositoryName"), + c)); + return; + } + + repositoryModel.name = fullName; + repositoryModel.projectPath = null; + + Permission permisison = permissionGroup.getModelObject(); + repositoryModel.accessRestriction = permisison.type; + repositoryModel.authorizationControl = AuthorizationControl.NAMED; + + repositoryModel.owners = new ArrayList(); + repositoryModel.owners.add(GitBlitWebSession.get().getUsername()); + + // setup branch defaults + boolean useGitFlow = addGitflowModel.getObject(); + + repositoryModel.HEAD = Constants.R_MASTER; + repositoryModel.mergeTo = Constants.MASTER; + if (useGitFlow) { + // tickets normally merge to develop unless they are hotfixes + repositoryModel.mergeTo = Constants.DEVELOP; + } + + repositoryModel.allowForks = app().settings().getBoolean(Keys.web.allowForking, true); + + // optionally generate an initial commit + boolean addReadme = addReadmeModel.getObject(); + String gitignore = null; + boolean addGitignore = addGitignoreModel.getObject(); + if (addGitignore) { + gitignore = gitignoreModel.getObject(); + if (StringUtils.isEmpty(gitignore)) { + throw new GitBlitException("Please select a .gitignore file"); + } + } + + // init the repository + app().gitblit().updateRepositoryModel(repositoryModel.name, repositoryModel, true); + + // optionally create an initial commit + initialCommit(repositoryModel, addReadme, gitignore, useGitFlow); + + } catch (GitBlitException e) { + error(e.getMessage()); + + // restore project and name fields on error condition + repositoryModel.projectPath = StringUtils.getFirstPathElement(fullName); + if (!StringUtils.isEmpty(repositoryModel.projectPath)) { + repositoryModel.name = fullName.substring(repositoryModel.projectPath.length() + 1); + } + return; + } + setRedirect(true); + setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(fullName)); + } + }; + + GitBlitWebSession session = GitBlitWebSession.get(); + UserModel user = session.getUser(); + + // build project list for repository destination + String defaultProject = null; + List projects = new ArrayList(); + + if (user.canAdmin()) { + String main = app().settings().getString(Keys.web.repositoryRootGroupName, "main"); + projects.add(main); + defaultProject = main; + } + + if (user.canCreate()) { + projects.add(user.getPersonalPath()); + if (defaultProject == null) { + // only prefer personal namespace if default is not already set + defaultProject = user.getPersonalPath(); + } + } + + repositoryModel.projectPath = defaultProject; + + // do not let the browser pre-populate these fields + form.add(new SimpleAttributeModifier("autocomplete", "off")); + + form.add(new DropDownChoice("projectPath", projects)); + form.add(new TextField("name")); + form.add(new TextField("description")); + + Permission anonymousPermission = new Permission(getString("gb.anonymous"), getString("gb.anonymousRepoDescription"), "blank.png", AccessRestrictionType.NONE); + Permission publicPermission = new Permission(getString("gb.public"), getString("gb.publicRepoDescription"), "lock_go_16x16.png", AccessRestrictionType.PUSH); + Permission protectedPermission = new Permission(getString("gb.protected"), getString("gb.protectedRepoDescription"), "lock_pull_16x16.png", AccessRestrictionType.CLONE); + Permission privatePermission = new Permission(getString("gb.private"), getString("gb.privateRepoDescription"), "shield_16x16.png", AccessRestrictionType.VIEW); + + List permissions = new ArrayList(); + if (app().settings().getBoolean(Keys.git.allowAnonymousPushes, false)) { + permissions.add(anonymousPermission); + } + permissions.add(publicPermission); + permissions.add(protectedPermission); + permissions.add(privatePermission); + + // determine default permission selection + AccessRestrictionType defaultRestriction = AccessRestrictionType.fromName( + app().settings().getString(Keys.git.defaultAccessRestriction, AccessRestrictionType.PUSH.name())); + if (AccessRestrictionType.NONE == defaultRestriction) { + defaultRestriction = AccessRestrictionType.PUSH; + } + + Permission defaultPermission = publicPermission; + for (Permission permission : permissions) { + if (permission.type == defaultRestriction) { + defaultPermission = permission; + } + } + + permissionGroup = new RadioGroup<>("permissionsGroup", new Model(defaultPermission)); + form.add(permissionGroup); + + ListView permissionsList = new ListView("permissions", permissions) { + + private static final long serialVersionUID = 1L; + + @Override + protected void populateItem(ListItem item) { + Permission p = item.getModelObject(); + item.add(new Radio("radio", item.getModel())); + item.add(WicketUtils.newImage("image", p.image)); + item.add(new Label("name", p.name)); + item.add(new Label("description", p.description)); + } + }; + permissionGroup.add(permissionsList); + + // + // initial commit options + // + + // add README + addReadmeModel = Model.of(false); + form.add(new CheckBox("addReadme", addReadmeModel)); + + // add .gitignore + File gitignoreDir = app().runtime().getFileOrFolder(Keys.git.gitignoreFolder, "${baseFolder}/gitignore"); + File [] files = gitignoreDir.listFiles(); + if (files == null) { + files = new File[0]; + } + List gitignores = new ArrayList(); + for (File file : files) { + if (file.isFile() && file.getName().endsWith(".gitignore")) { + gitignores.add(StringUtils.stripFileExtension(file.getName())); + } + } + Collections.sort(gitignores); + gitignoreModel = Model.of(""); + final DropDownChoice gitignoreChoice = new DropDownChoice("gitignore", gitignoreModel, gitignores); + gitignoreChoice.setOutputMarkupId(true); + form.add(gitignoreChoice.setEnabled(false)); + + addGitignoreModel = Model.of(false); + final CheckBox gitignoreCheckbox = new CheckBox("addGitignore", addGitignoreModel); + form.add(gitignoreCheckbox); + + gitignoreCheckbox.add(new AjaxFormComponentUpdatingBehavior("onchange") { + + private static final long serialVersionUID = 1L; + + @Override + protected void onUpdate(AjaxRequestTarget target) { + gitignoreChoice.setEnabled(addGitignoreModel.getObject()); + target.addComponent(gitignoreChoice); + } + }); + + // TODO add .gitflow + addGitflowModel = Model.of(false); + form.add(new CheckBox("addGitflow", addGitflowModel)); + + form.add(new Button("create")); + + add(form); + } + + /** + * Prepare the initial commit for the repository. + * + * @param repository + * @param addReadme + * @param gitignore + * @param addGitFlow + * @return true if an initial commit was created + */ + protected boolean initialCommit(RepositoryModel repository, boolean addReadme, String gitignore, + boolean addGitFlow) { + boolean initialCommit = addReadme || !StringUtils.isEmpty(gitignore) || addGitFlow; + if (!initialCommit) { + return false; + } + + // build an initial commit + boolean success = false; + Repository db = app().repositories().getRepository(repositoryModel.name); + ObjectInserter odi = db.newObjectInserter(); + try { + + UserModel user = GitBlitWebSession.get().getUser(); + PersonIdent author = new PersonIdent(user.getDisplayName(), user.emailAddress); + + DirCache newIndex = DirCache.newInCore(); + DirCacheBuilder indexBuilder = newIndex.builder(); + + if (addReadme) { + // insert a README + String title = StringUtils.stripDotGit(StringUtils.getLastPathElement(repositoryModel.name)); + String description = repositoryModel.description == null ? "" : repositoryModel.description; + String readme = String.format("## %s\n\n%s\n\n", title, description); + byte [] bytes = readme.getBytes(Constants.ENCODING); + + DirCacheEntry entry = new DirCacheEntry("README.md"); + entry.setLength(bytes.length); + entry.setLastModified(System.currentTimeMillis()); + entry.setFileMode(FileMode.REGULAR_FILE); + entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes)); + + indexBuilder.add(entry); + } + + if (!StringUtils.isEmpty(gitignore)) { + // insert a .gitignore file + File dir = app().runtime().getFileOrFolder(Keys.git.gitignoreFolder, "${baseFolder}/gitignore"); + File file = new File(dir, gitignore + ".gitignore"); + if (file.exists() && file.length() > 0) { + byte [] bytes = FileUtils.readContent(file); + if (!ArrayUtils.isEmpty(bytes)) { + DirCacheEntry entry = new DirCacheEntry(".gitignore"); + entry.setLength(bytes.length); + entry.setLastModified(System.currentTimeMillis()); + entry.setFileMode(FileMode.REGULAR_FILE); + entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes)); + + indexBuilder.add(entry); + } + } + } + + if (addGitFlow) { + // insert a .gitflow file + Config config = new Config(); + config.setString("gitflow", null, "masterBranch", Constants.MASTER); + config.setString("gitflow", null, "developBranch", Constants.DEVELOP); + config.setString("gitflow", null, "featureBranchPrefix", "feature/"); + config.setString("gitflow", null, "releaseBranchPrefix", "release/"); + config.setString("gitflow", null, "hotfixBranchPrefix", "hotfix/"); + config.setString("gitflow", null, "supportBranchPrefix", "support/"); + config.setString("gitflow", null, "versionTagPrefix", ""); + + byte [] bytes = config.toText().getBytes(Constants.ENCODING); + + DirCacheEntry entry = new DirCacheEntry(".gitflow"); + entry.setLength(bytes.length); + entry.setLastModified(System.currentTimeMillis()); + entry.setFileMode(FileMode.REGULAR_FILE); + entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes)); + + indexBuilder.add(entry); + } + + indexBuilder.finish(); + + if (newIndex.getEntryCount() == 0) { + // nothing to commit + return false; + } + + ObjectId treeId = newIndex.writeTree(odi); + + // Create a commit object + CommitBuilder commit = new CommitBuilder(); + commit.setAuthor(author); + commit.setCommitter(author); + commit.setEncoding(Constants.ENCODING); + commit.setMessage("Initial commit"); + commit.setTreeId(treeId); + + // Insert the commit into the repository + ObjectId commitId = odi.insert(commit); + odi.flush(); + + // set the branch refs + RevWalk revWalk = new RevWalk(db); + try { + // set the master branch + RevCommit revCommit = revWalk.parseCommit(commitId); + RefUpdate masterRef = db.updateRef(Constants.R_MASTER); + masterRef.setNewObjectId(commitId); + masterRef.setRefLogMessage("commit: " + revCommit.getShortMessage(), false); + Result masterRC = masterRef.update(); + switch (masterRC) { + case NEW: + success = true; + break; + default: + success = false; + } + + if (addGitFlow) { + // set the develop branch for git-flow + RefUpdate developRef = db.updateRef(Constants.R_DEVELOP); + developRef.setNewObjectId(commitId); + developRef.setRefLogMessage("commit: " + revCommit.getShortMessage(), false); + Result developRC = developRef.update(); + switch (developRC) { + case NEW: + success = true; + break; + default: + success = false; + } + } + } finally { + revWalk.release(); + } + } catch (UnsupportedEncodingException e) { + logger().error(null, e); + } catch (IOException e) { + logger().error(null, e); + } finally { + odi.release(); + db.close(); + } + return success; + } + + private static class Permission implements Serializable { + + private static final long serialVersionUID = 1L; + + final String name; + final String description; + final String image; + final AccessRestrictionType type; + + Permission(String name, String description, String img, AccessRestrictionType type) { + this.name = name; + this.description = description; + this.image = img; + this.type = type; + } + } +} diff --git a/src/main/java/com/gitblit/wicket/pages/RootPage.java b/src/main/java/com/gitblit/wicket/pages/RootPage.java index a2f3a497..b1c3639d 100644 --- a/src/main/java/com/gitblit/wicket/pages/RootPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RootPage.java @@ -607,7 +607,7 @@ public abstract class RootPage extends BasePage { List standardItems = new ArrayList(); standardItems.add(new MenuDivider()); if (user.canAdmin() || user.canCreate()) { - standardItems.add(new PageLinkMenuItem("gb.newRepository", EditRepositoryPage.class)); + standardItems.add(new PageLinkMenuItem("gb.newRepository", app().getNewRepositoryPage())); } standardItems.add(new PageLinkMenuItem("gb.myProfile", UserPage.class, WicketUtils.newUsernameParameter(user.username))); diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index 6cb791eb..29b49b33 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -30,8 +30,8 @@ import org.eclipse.jgit.lib.PersonIdent; import com.gitblit.Keys; import com.gitblit.models.Menu.ParameterMenuItem; -import com.gitblit.models.NavLink.DropDownPageMenuNavLink; import com.gitblit.models.NavLink; +import com.gitblit.models.NavLink.DropDownPageMenuNavLink; import com.gitblit.models.ProjectModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; @@ -95,7 +95,7 @@ public class UserPage extends RootPage { UserModel sessionUser = GitBlitWebSession.get().getUser(); if (sessionUser != null && user.canCreate() && sessionUser.equals(user)) { // user can create personal repositories - add(new BookmarkablePageLink("newRepository", EditRepositoryPage.class)); + add(new BookmarkablePageLink("newRepository", app().getNewRepositoryPage())); } else { add(new Label("newRepository").setVisible(false)); } diff --git a/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java b/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java index 45b0bab1..4433b043 100644 --- a/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java +++ b/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java @@ -33,7 +33,6 @@ import com.gitblit.utils.StringUtils; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.freemarker.FreemarkerPanel; import com.gitblit.wicket.ng.NgController; -import com.gitblit.wicket.pages.EditRepositoryPage; /** * A client-side filterable rich repository list which uses Freemarker, Wicket, @@ -98,7 +97,7 @@ public class FilterableRepositoryList extends BasePanel { } if (allowCreate) { - panel.add(new LinkPanel(ngList + "Button", "btn btn-mini", getString("gb.newRepository"), EditRepositoryPage.class)); + panel.add(new LinkPanel(ngList + "Button", "btn btn-mini", getString("gb.newRepository"), app().getNewRepositoryPage())); } else { panel.add(new Label(ngList + "Button").setVisible(false)); } diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java index dd208e23..8573e1a6 100644 --- a/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java @@ -51,7 +51,6 @@ import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.pages.BasePage; -import com.gitblit.wicket.pages.EditRepositoryPage; import com.gitblit.wicket.pages.ProjectPage; import com.gitblit.wicket.pages.RepositoriesPage; import com.gitblit.wicket.pages.SummaryPage; @@ -87,12 +86,12 @@ public class RepositoriesPanel extends BasePanel { setResponsePage(RepositoriesPage.class); } }.setVisible(app().settings().getBoolean(Keys.git.cacheRepositoryList, true))); - managementLinks.add(new BookmarkablePageLink("newRepository", EditRepositoryPage.class)); + managementLinks.add(new BookmarkablePageLink("newRepository", app().getNewRepositoryPage())); add(managementLinks); } else if (showManagement && user != null && user.canCreate()) { // user can create personal repositories managementLinks = new Fragment("managementPanel", "personalLinks", this); - managementLinks.add(new BookmarkablePageLink("newRepository", EditRepositoryPage.class)); + managementLinks.add(new BookmarkablePageLink("newRepository", app().getNewRepositoryPage())); add(managementLinks); } else { // user has no management permissions -- cgit v1.2.3 From 8845b9aff37ee1cdc538ed4247933f7e3c06a49e Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 29 May 2014 21:19:59 -0400 Subject: Inlcude authorization control and revise the string resources --- .../com/gitblit/wicket/GitBlitWebApp.properties | 14 +++--- .../gitblit/wicket/pages/NewRepositoryPage.java | 53 ++++++++++++++++++---- 2 files changed, 52 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index ac589558..3fd5a3ac 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -685,12 +685,14 @@ gb.closedMilestones = closed milestones gb.administration = administration gb.plugins = plugins gb.extensions = extensions -gb.anonymous = Anonymous -gb.anonymousRepoDescription = Anyone can see, clone, and push to this repository. -gb.public = Public -gb.publicRepoDescription = Anyone can see and clone this repository. You choose who can push. -gb.protected = Protected -gb.protectedRepoDescription = Anyone can see this repository. You choose who can clone and push. +gb.anonymousPush = Anonymous Pushes +gb.anonymousPushDescription = Anyone can see, clone, and push to this repository. +gb.pushRestrictedAuthenticated = Restrict Pushes (Authenticated) +gb.pushRestrictedAuthenticatedDescription = Anyone can see and clone this repository. All authenticated users can push. +gb.pushRestrictedNamed = Restrict Pushes (Named) +gb.pushRestrictedNamedDescription = Anyone can see and clone this repository. You choose who can push. +gb.cloneRestricted = Restrict Clones & Pushes +gb.cloneRestrictedDescription = Anyone can see this repository. You choose who can clone and push. gb.private = Private gb.privateRepoDescription = You choose who can see, clone, and push to this repository. gb.initialCommit = Initial Commit diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java index b0cc3e95..a423ae62 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java @@ -148,9 +148,9 @@ public class NewRepositoryPage extends RootSubPage { repositoryModel.name = fullName; repositoryModel.projectPath = null; - Permission permisison = permissionGroup.getModelObject(); - repositoryModel.accessRestriction = permisison.type; - repositoryModel.authorizationControl = AuthorizationControl.NAMED; + Permission permission = permissionGroup.getModelObject(); + repositoryModel.authorizationControl = permission.control; + repositoryModel.accessRestriction = permission.type; repositoryModel.owners = new ArrayList(); repositoryModel.owners.add(GitBlitWebSession.get().getUsername()); @@ -229,15 +229,41 @@ public class NewRepositoryPage extends RootSubPage { form.add(new TextField("name")); form.add(new TextField("description")); - Permission anonymousPermission = new Permission(getString("gb.anonymous"), getString("gb.anonymousRepoDescription"), "blank.png", AccessRestrictionType.NONE); - Permission publicPermission = new Permission(getString("gb.public"), getString("gb.publicRepoDescription"), "lock_go_16x16.png", AccessRestrictionType.PUSH); - Permission protectedPermission = new Permission(getString("gb.protected"), getString("gb.protectedRepoDescription"), "lock_pull_16x16.png", AccessRestrictionType.CLONE); - Permission privatePermission = new Permission(getString("gb.private"), getString("gb.privateRepoDescription"), "shield_16x16.png", AccessRestrictionType.VIEW); + Permission anonymousPermission = new Permission(getString("gb.anonymousPush"), + getString("gb.anonymousPushDescription"), + "blank.png", + AuthorizationControl.AUTHENTICATED, + AccessRestrictionType.NONE); + + Permission authenticatedPermission = new Permission(getString("gb.pushRestrictedAuthenticated"), + getString("gb.pushRestrictedAuthenticatedDescription"), + "lock_go_16x16.png", + AuthorizationControl.AUTHENTICATED, + AccessRestrictionType.PUSH); + + Permission publicPermission = new Permission(getString("gb.pushRestrictedNamed"), + getString("gb.pushRestrictedNamedDescription"), + "lock_go_16x16.png", + AuthorizationControl.NAMED, + AccessRestrictionType.PUSH); + + Permission protectedPermission = new Permission(getString("gb.cloneRestricted"), + getString("gb.cloneRestrictedDescription"), + "lock_pull_16x16.png", + AuthorizationControl.NAMED, + AccessRestrictionType.CLONE); + + Permission privatePermission = new Permission(getString("gb.private"), + getString("gb.privateRepoDescription"), + "shield_16x16.png", + AuthorizationControl.NAMED, + AccessRestrictionType.VIEW); List permissions = new ArrayList(); if (app().settings().getBoolean(Keys.git.allowAnonymousPushes, false)) { permissions.add(anonymousPermission); } + permissions.add(authenticatedPermission); permissions.add(publicPermission); permissions.add(protectedPermission); permissions.add(privatePermission); @@ -248,10 +274,17 @@ public class NewRepositoryPage extends RootSubPage { if (AccessRestrictionType.NONE == defaultRestriction) { defaultRestriction = AccessRestrictionType.PUSH; } + AuthorizationControl defaultControl = AuthorizationControl.fromName( + app().settings().getString(Keys.git.defaultAuthorizationControl, AuthorizationControl.NAMED.name())); + + if (AuthorizationControl.AUTHENTICATED == defaultControl) { + defaultRestriction = AccessRestrictionType.PUSH; + } Permission defaultPermission = publicPermission; for (Permission permission : permissions) { - if (permission.type == defaultRestriction) { + if (permission.type == defaultRestriction + && permission.control == defaultControl) { defaultPermission = permission; } } @@ -481,12 +514,14 @@ public class NewRepositoryPage extends RootSubPage { final String name; final String description; final String image; + final AuthorizationControl control; final AccessRestrictionType type; - Permission(String name, String description, String img, AccessRestrictionType type) { + Permission(String name, String description, String img, AuthorizationControl control, AccessRestrictionType type) { this.name = name; this.description = description; this.image = img; + this.control = control; this.type = type; } } -- cgit v1.2.3 From 2c50880dbd5de292e37d2533fccfcb62f6be9f95 Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 29 May 2014 21:47:56 -0400 Subject: Extract authorization/access selection panel to re-usable class --- .../gitblit/wicket/pages/NewRepositoryPage.html | 13 +- .../gitblit/wicket/pages/NewRepositoryPage.java | 101 +----------- .../wicket/panels/RepositoryPermissionPanel.html | 25 +++ .../wicket/panels/RepositoryPermissionPanel.java | 171 +++++++++++++++++++++ 4 files changed, 205 insertions(+), 105 deletions(-) create mode 100644 src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.html create mode 100644 src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.java (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html index e9f12027..c59f29c8 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html @@ -32,18 +32,7 @@
- -
-
- - -
-
-
- -
-
-
+
diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java index a423ae62..cd0cef61 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java @@ -17,7 +17,6 @@ package com.gitblit.wicket.pages; import java.io.File; import java.io.IOException; -import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.text.MessageFormat; import java.util.ArrayList; @@ -27,16 +26,11 @@ import java.util.List; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.behavior.SimpleAttributeModifier; -import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Button; import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.Form; -import org.apache.wicket.markup.html.form.Radio; -import org.apache.wicket.markup.html.form.RadioGroup; import org.apache.wicket.markup.html.form.TextField; -import org.apache.wicket.markup.html.list.ListItem; -import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.CompoundPropertyModel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; @@ -67,15 +61,16 @@ import com.gitblit.utils.FileUtils; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; +import com.gitblit.wicket.panels.RepositoryPermissionPanel; public class NewRepositoryPage extends RootSubPage { private final RepositoryModel repositoryModel; - private RadioGroup permissionGroup; private IModel addReadmeModel; private Model gitignoreModel; private IModel addGitflowModel; private IModel addGitignoreModel; + private RepositoryPermissionPanel permissionPanel; public NewRepositoryPage() { // create constructor @@ -148,9 +143,7 @@ public class NewRepositoryPage extends RootSubPage { repositoryModel.name = fullName; repositoryModel.projectPath = null; - Permission permission = permissionGroup.getModelObject(); - repositoryModel.authorizationControl = permission.control; - repositoryModel.accessRestriction = permission.type; + permissionPanel.setPermission(repositoryModel); repositoryModel.owners = new ArrayList(); repositoryModel.owners.add(GitBlitWebSession.get().getUsername()); @@ -229,46 +222,7 @@ public class NewRepositoryPage extends RootSubPage { form.add(new TextField("name")); form.add(new TextField("description")); - Permission anonymousPermission = new Permission(getString("gb.anonymousPush"), - getString("gb.anonymousPushDescription"), - "blank.png", - AuthorizationControl.AUTHENTICATED, - AccessRestrictionType.NONE); - - Permission authenticatedPermission = new Permission(getString("gb.pushRestrictedAuthenticated"), - getString("gb.pushRestrictedAuthenticatedDescription"), - "lock_go_16x16.png", - AuthorizationControl.AUTHENTICATED, - AccessRestrictionType.PUSH); - - Permission publicPermission = new Permission(getString("gb.pushRestrictedNamed"), - getString("gb.pushRestrictedNamedDescription"), - "lock_go_16x16.png", - AuthorizationControl.NAMED, - AccessRestrictionType.PUSH); - - Permission protectedPermission = new Permission(getString("gb.cloneRestricted"), - getString("gb.cloneRestrictedDescription"), - "lock_pull_16x16.png", - AuthorizationControl.NAMED, - AccessRestrictionType.CLONE); - - Permission privatePermission = new Permission(getString("gb.private"), - getString("gb.privateRepoDescription"), - "shield_16x16.png", - AuthorizationControl.NAMED, - AccessRestrictionType.VIEW); - - List permissions = new ArrayList(); - if (app().settings().getBoolean(Keys.git.allowAnonymousPushes, false)) { - permissions.add(anonymousPermission); - } - permissions.add(authenticatedPermission); - permissions.add(publicPermission); - permissions.add(protectedPermission); - permissions.add(privatePermission); - - // determine default permission selection + // prepare the default access controls AccessRestrictionType defaultRestriction = AccessRestrictionType.fromName( app().settings().getString(Keys.git.defaultAccessRestriction, AccessRestrictionType.PUSH.name())); if (AccessRestrictionType.NONE == defaultRestriction) { @@ -281,31 +235,11 @@ public class NewRepositoryPage extends RootSubPage { defaultRestriction = AccessRestrictionType.PUSH; } - Permission defaultPermission = publicPermission; - for (Permission permission : permissions) { - if (permission.type == defaultRestriction - && permission.control == defaultControl) { - defaultPermission = permission; - } - } - - permissionGroup = new RadioGroup<>("permissionsGroup", new Model(defaultPermission)); - form.add(permissionGroup); + repositoryModel.authorizationControl = defaultControl; + repositoryModel.accessRestriction = defaultRestriction; - ListView permissionsList = new ListView("permissions", permissions) { - - private static final long serialVersionUID = 1L; - - @Override - protected void populateItem(ListItem item) { - Permission p = item.getModelObject(); - item.add(new Radio("radio", item.getModel())); - item.add(WicketUtils.newImage("image", p.image)); - item.add(new Label("name", p.name)); - item.add(new Label("description", p.description)); - } - }; - permissionGroup.add(permissionsList); + permissionPanel = new RepositoryPermissionPanel("permissionPanel", repositoryModel); + form.add(permissionPanel); // // initial commit options @@ -506,23 +440,4 @@ public class NewRepositoryPage extends RootSubPage { } return success; } - - private static class Permission implements Serializable { - - private static final long serialVersionUID = 1L; - - final String name; - final String description; - final String image; - final AuthorizationControl control; - final AccessRestrictionType type; - - Permission(String name, String description, String img, AuthorizationControl control, AccessRestrictionType type) { - this.name = name; - this.description = description; - this.image = img; - this.control = control; - this.type = type; - } - } } diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.html b/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.html new file mode 100644 index 00000000..6a4d5cef --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.html @@ -0,0 +1,25 @@ + + + + + + + +
+
+ + +
+
+
+ +
+
+
+ +
+ + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.java new file mode 100644 index 00000000..7c416b1b --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.java @@ -0,0 +1,171 @@ +/* + * 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.util.ArrayList; +import java.util.List; + +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.Radio; +import org.apache.wicket.markup.html.form.RadioGroup; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; +import org.apache.wicket.model.Model; + +import com.gitblit.Constants.AccessRestrictionType; +import com.gitblit.Constants.AuthorizationControl; +import com.gitblit.Keys; +import com.gitblit.models.RepositoryModel; +import com.gitblit.wicket.WicketUtils; + +/** + * A radio group panel of the 5 available authorization/access restriction combinations. + * + * @author James Moger + * + */ +public class RepositoryPermissionPanel extends BasePanel { + + private static final long serialVersionUID = 1L; + + private final RepositoryModel repository; + + private RadioGroup permissionGroup; + + public RepositoryPermissionPanel(String wicketId, RepositoryModel repository) { + super(wicketId); + this.repository = repository; + } + + @Override + protected void onInitialize() { + super.onInitialize(); + + Permission anonymousPermission = new Permission(getString("gb.anonymousPush"), + getString("gb.anonymousPushDescription"), + "blank.png", + AuthorizationControl.AUTHENTICATED, + AccessRestrictionType.NONE); + + Permission authenticatedPermission = new Permission(getString("gb.pushRestrictedAuthenticated"), + getString("gb.pushRestrictedAuthenticatedDescription"), + "lock_go_16x16.png", + AuthorizationControl.AUTHENTICATED, + AccessRestrictionType.PUSH); + + Permission publicPermission = new Permission(getString("gb.pushRestrictedNamed"), + getString("gb.pushRestrictedNamedDescription"), + "lock_go_16x16.png", + AuthorizationControl.NAMED, + AccessRestrictionType.PUSH); + + Permission protectedPermission = new Permission(getString("gb.cloneRestricted"), + getString("gb.cloneRestrictedDescription"), + "lock_pull_16x16.png", + AuthorizationControl.NAMED, + AccessRestrictionType.CLONE); + + Permission privatePermission = new Permission(getString("gb.private"), + getString("gb.privateRepoDescription"), + "shield_16x16.png", + AuthorizationControl.NAMED, + AccessRestrictionType.VIEW); + + List permissions = new ArrayList(); + if (app().settings().getBoolean(Keys.git.allowAnonymousPushes, false)) { + permissions.add(anonymousPermission); + } + permissions.add(authenticatedPermission); + permissions.add(publicPermission); + permissions.add(protectedPermission); + permissions.add(privatePermission); + + AccessRestrictionType defaultRestriction = repository.accessRestriction; + if (defaultRestriction == null) { + defaultRestriction = AccessRestrictionType.fromName(app().settings().getString(Keys.git.defaultAccessRestriction, + AccessRestrictionType.PUSH.name())); + } + + AuthorizationControl defaultControl = repository.authorizationControl; + if (defaultControl == null) { + defaultControl = AuthorizationControl.fromName(app().settings().getString(Keys.git.defaultAuthorizationControl, + AuthorizationControl.NAMED.name())); + } + + Permission defaultPermission = publicPermission; + for (Permission permission : permissions) { + if (permission.type == defaultRestriction && permission.control == defaultControl) { + defaultPermission = permission; + } + } + + permissionGroup = new RadioGroup<>("permissionsGroup", new Model(defaultPermission)); + ListView permissionsList = new ListView("permissions", permissions) { + + private static final long serialVersionUID = 1L; + + @Override + protected void populateItem(ListItem item) { + Permission p = item.getModelObject(); + item.add(new Radio("radio", item.getModel())); + item.add(WicketUtils.newImage("image", p.image)); + item.add(new Label("name", p.name)); + item.add(new Label("description", p.description)); + } + }; + permissionGroup.add(permissionsList); + + setOutputMarkupId(true); + + add(permissionGroup); + } + + public void setPermission(RepositoryModel repository) { + Permission permission = permissionGroup.getModelObject(); + repository.authorizationControl = permission.control; + repository.accessRestriction = permission.type; + } + + @Override + protected boolean getStatelessHint() { + return false; + } + + private static class Permission implements Serializable { + + private static final long serialVersionUID = 1L; + + final String name; + final String description; + final String image; + final AuthorizationControl control; + final AccessRestrictionType type; + + Permission(String name, String description, String img, AuthorizationControl control, AccessRestrictionType type) { + this.name = name; + this.description = description; + this.image = img; + this.control = control; + this.type = type; + } + + @Override + public String toString() { + return name; + } + } +} -- cgit v1.2.3 From a3456e22504a0a054312989fd52a21e4d193baf7 Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 29 May 2014 22:29:51 -0400 Subject: Extract repository name panel for re-use --- .../com/gitblit/wicket/GitBlitWebApp.properties | 1 + .../gitblit/wicket/pages/NewRepositoryPage.html | 17 +-- .../gitblit/wicket/pages/NewRepositoryPage.java | 79 ++---------- .../gitblit/wicket/panels/RepositoryNamePanel.html | 27 ++++ .../gitblit/wicket/panels/RepositoryNamePanel.java | 139 +++++++++++++++++++++ .../wicket/panels/RepositoryPermissionPanel.java | 2 +- 6 files changed, 179 insertions(+), 86 deletions(-) create mode 100644 src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html create mode 100644 src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 3fd5a3ac..d90158d4 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -685,6 +685,7 @@ gb.closedMilestones = closed milestones gb.administration = administration gb.plugins = plugins gb.extensions = extensions +gb.pleaseSelectProject = Please select the project! gb.anonymousPush = Anonymous Pushes gb.anonymousPushDescription = Anyone can see, clone, and push to this repository. gb.pushRestrictedAuthenticated = Restrict Pushes (Authenticated) diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html index c59f29c8..05f56012 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html @@ -10,20 +10,7 @@
- - - - - - - - - - - - - -
/  
+

@@ -32,7 +19,7 @@
- +

diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java index cd0cef61..e2e5d4bc 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java @@ -18,7 +18,6 @@ package com.gitblit.wicket.pages; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; -import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -61,6 +60,7 @@ import com.gitblit.utils.FileUtils; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; +import com.gitblit.wicket.panels.RepositoryNamePanel; import com.gitblit.wicket.panels.RepositoryPermissionPanel; public class NewRepositoryPage extends RootSubPage { @@ -71,6 +71,7 @@ public class NewRepositoryPage extends RootSubPage { private IModel addGitflowModel; private IModel addGitignoreModel; private RepositoryPermissionPanel permissionPanel; + private RepositoryNamePanel namePanel; public NewRepositoryPage() { // create constructor @@ -104,46 +105,11 @@ public class NewRepositoryPage extends RootSubPage { @Override protected void onSubmit() { - - // confirm a repository name was entered - if (StringUtils.isEmpty(repositoryModel.name)) { - error(getString("gb.pleaseSetRepositoryName")); - return; - } - - String project = repositoryModel.projectPath; - String fullName = (project + "/" + repositoryModel.name).trim(); - fullName = fullName.replace('\\', '/'); - fullName = fullName.replace("//", "/"); - if (fullName.charAt(0) == '/') { - fullName = fullName.substring(1); - } - if (fullName.endsWith("/")) { - fullName = fullName.substring(0, fullName.length() - 1); - } - try { - if (fullName.contains("../")) { - error(getString("gb.illegalRelativeSlash")); + if (!namePanel.updateModel(repositoryModel)) { return; } - if (fullName.contains("/../")) { - error(getString("gb.illegalRelativeSlash")); - return; - } - - // confirm valid characters in repository name - Character c = StringUtils.findInvalidCharacter(fullName); - if (c != null) { - error(MessageFormat.format(getString("gb.illegalCharacterRepositoryName"), - c)); - return; - } - - repositoryModel.name = fullName; - repositoryModel.projectPath = null; - - permissionPanel.setPermission(repositoryModel); + permissionPanel.updateModel(repositoryModel); repositoryModel.owners = new ArrayList(); repositoryModel.owners.add(GitBlitWebSession.get().getUsername()); @@ -179,47 +145,20 @@ public class NewRepositoryPage extends RootSubPage { } catch (GitBlitException e) { error(e.getMessage()); - - // restore project and name fields on error condition - repositoryModel.projectPath = StringUtils.getFirstPathElement(fullName); - if (!StringUtils.isEmpty(repositoryModel.projectPath)) { - repositoryModel.name = fullName.substring(repositoryModel.projectPath.length() + 1); - } + namePanel.resetModel(repositoryModel); return; } setRedirect(true); - setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(fullName)); + setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryModel.name)); } }; - GitBlitWebSession session = GitBlitWebSession.get(); - UserModel user = session.getUser(); - - // build project list for repository destination - String defaultProject = null; - List projects = new ArrayList(); - - if (user.canAdmin()) { - String main = app().settings().getString(Keys.web.repositoryRootGroupName, "main"); - projects.add(main); - defaultProject = main; - } - - if (user.canCreate()) { - projects.add(user.getPersonalPath()); - if (defaultProject == null) { - // only prefer personal namespace if default is not already set - defaultProject = user.getPersonalPath(); - } - } - - repositoryModel.projectPath = defaultProject; - // do not let the browser pre-populate these fields form.add(new SimpleAttributeModifier("autocomplete", "off")); - form.add(new DropDownChoice("projectPath", projects)); - form.add(new TextField("name")); + namePanel = new RepositoryNamePanel("namePanel", repositoryModel); + form.add(namePanel); + form.add(new TextField("description")); // prepare the default access controls diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html new file mode 100644 index 00000000..f3a0738e --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + +
/  
+ +
+ + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java new file mode 100644 index 00000000..7b20adec --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java @@ -0,0 +1,139 @@ +/* + * 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.markup.html.form.DropDownChoice; +import org.apache.wicket.markup.html.form.TextField; + +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.UserModel; +import com.gitblit.utils.StringUtils; +import com.gitblit.wicket.GitBlitWebSession; + +/** + * A radio group panel of the 5 available authorization/access restriction combinations. + * + * @author James Moger + * + */ +public class RepositoryNamePanel extends BasePanel { + + private static final long serialVersionUID = 1L; + + private final RepositoryModel repository; + + private String fullName; + + public RepositoryNamePanel(String wicketId, RepositoryModel repository) { + super(wicketId); + this.repository = repository; + } + + @Override + protected void onInitialize() { + super.onInitialize(); + + GitBlitWebSession session = GitBlitWebSession.get(); + UserModel user = session.getUser(); + + // build project list for repository destination + String defaultProject = null; + List projects = new ArrayList(); + + if (user.canAdmin()) { + projects.add("/"); + defaultProject = "/"; + } + + if (user.canCreate()) { + String p = user.getPersonalPath() + "/"; + projects.add(p); + if (defaultProject == null) { + // only prefer personal namespace if default is not already set + defaultProject = p; + } + } + + repository.projectPath = defaultProject; + + add(new DropDownChoice("projectPath", projects)); + add(new TextField("name")); + } + + public boolean updateModel(RepositoryModel repositoryModel) { + // confirm a project was selected + if (StringUtils.isEmpty(repositoryModel.projectPath)) { + error(getString("gb.pleaseSelectProject")); + return false; + } + + // confirm a repository name was entered + if (StringUtils.isEmpty(repositoryModel.name)) { + error(getString("gb.pleaseSetRepositoryName")); + return false; + } + + String project = repositoryModel.projectPath; + + fullName = (project + repositoryModel.name).trim(); + fullName = fullName.replace('\\', '/'); + fullName = fullName.replace("//", "/"); + if (fullName.charAt(0) == '/') { + fullName = fullName.substring(1); + } + if (fullName.endsWith("/")) { + fullName = fullName.substring(0, fullName.length() - 1); + } + + if (fullName.contains("../")) { + error(getString("gb.illegalRelativeSlash")); + return false; + } + if (fullName.contains("/../")) { + error(getString("gb.illegalRelativeSlash")); + return false; + } + + // confirm valid characters in repository name + Character c = StringUtils.findInvalidCharacter(fullName); + if (c != null) { + error(MessageFormat.format(getString("gb.illegalCharacterRepositoryName"), c)); + return false; + } + + repositoryModel.name = fullName; + repositoryModel.projectPath = null; + + return true; + } + + public void resetModel(RepositoryModel repositoryModel) { + // restore project and name fields on error condition + repositoryModel.projectPath = StringUtils.getFirstPathElement(fullName) + "/"; + if (repositoryModel.projectPath.length() > 1) { + repositoryModel.name = fullName.substring(repositoryModel.projectPath.length()); + } + } + + @Override + protected boolean getStatelessHint() { + return false; + } +} diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.java index 7c416b1b..ed3f1fed 100644 --- a/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.java @@ -134,7 +134,7 @@ public class RepositoryPermissionPanel extends BasePanel { add(permissionGroup); } - public void setPermission(RepositoryModel repository) { + public void updateModel(RepositoryModel repository) { Permission permission = permissionGroup.getModelObject(); repository.authorizationControl = permission.control; repository.accessRestriction = permission.type; -- cgit v1.2.3 From 5779988cf3a1d737322b2b6a1d568da8713509e7 Mon Sep 17 00:00:00 2001 From: James Moger Date: Fri, 30 May 2014 10:05:06 -0400 Subject: Use RepositoryNamePanel in EditRepositoryPage, rename AccessPolicyPanel --- .../com/gitblit/wicket/GitBlitWebApp.properties | 22 +-- .../gitblit/wicket/pages/EditRepositoryPage.html | 4 +- .../gitblit/wicket/pages/EditRepositoryPage.java | 63 ++------ .../gitblit/wicket/pages/NewRepositoryPage.html | 5 - .../gitblit/wicket/pages/NewRepositoryPage.java | 9 +- .../gitblit/wicket/panels/AccessPolicyPanel.html | 28 ++++ .../gitblit/wicket/panels/AccessPolicyPanel.java | 171 +++++++++++++++++++++ .../gitblit/wicket/panels/RepositoryNamePanel.html | 7 +- .../gitblit/wicket/panels/RepositoryNamePanel.java | 83 +++++++--- .../wicket/panels/RepositoryPermissionPanel.html | 25 --- .../wicket/panels/RepositoryPermissionPanel.java | 171 --------------------- 11 files changed, 290 insertions(+), 298 deletions(-) create mode 100644 src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html create mode 100644 src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java delete mode 100644 src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.html delete mode 100644 src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.java (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index d90158d4..d2d1454e 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -686,16 +686,18 @@ gb.administration = administration gb.plugins = plugins gb.extensions = extensions gb.pleaseSelectProject = Please select the project! -gb.anonymousPush = Anonymous Pushes -gb.anonymousPushDescription = Anyone can see, clone, and push to this repository. -gb.pushRestrictedAuthenticated = Restrict Pushes (Authenticated) -gb.pushRestrictedAuthenticatedDescription = Anyone can see and clone this repository. All authenticated users can push. -gb.pushRestrictedNamed = Restrict Pushes (Named) -gb.pushRestrictedNamedDescription = Anyone can see and clone this repository. You choose who can push. -gb.cloneRestricted = Restrict Clones & Pushes -gb.cloneRestrictedDescription = Anyone can see this repository. You choose who can clone and push. -gb.private = Private -gb.privateRepoDescription = You choose who can see, clone, and push to this repository. +gb.accessPolicy = Access Policy +gb.accessPolicyDescription = Choose an access policy to control visibility, cloning, and pushing to this repository. +gb.anonymousPolicy = Anonymous View, Clone, & Push +gb.anonymousPolicyDescription = Anyone can see, clone, and push to this repository. +gb.authenticatedPushPolicy = Restrict Push (Authenticated) +gb.authenticatedPushPolicyDescription = Anyone can see and clone this repository. All authenticated users have RW+ push permission. +gb.namedPushPolicy = Restrict Push (Named) +gb.namedPushPolicyDescription = Anyone can see and clone this repository. You choose who can push. +gb.clonePolicy = Restrict Clone & Push +gb.clonePolicyDescription = Anyone can see this repository. You choose who can clone and push. +gb.viewPolicy = Restrict View, Clone, & Push +gb.viewPolicyDescription = You choose who can see, clone, and push to this repository. gb.initialCommit = Initial Commit gb.initialCommitDescription = This will allow you to git clone this repository immediately. Skip this step if you have already run git init locally. gb.initWithReadme = Include a README diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html index b7a1976f..ccb60a5c 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html @@ -24,10 +24,10 @@
+
+ - - diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java index c18cd514..4759fd0d 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java @@ -72,11 +72,14 @@ import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.BasePanel.JavascriptEventConfirmation; import com.gitblit.wicket.panels.BulletListPanel; import com.gitblit.wicket.panels.RegistrantPermissionsPanel; +import com.gitblit.wicket.panels.RepositoryNamePanel; public class EditRepositoryPage extends RootSubPage { private final boolean isCreate; + RepositoryNamePanel namePanel; + private boolean isAdmin; RepositoryModel repositoryModel; @@ -263,60 +266,9 @@ public class EditRepositoryPage extends RootSubPage { @Override protected void onSubmit() { try { - // confirm a repository name was entered - if (repositoryModel.name == null && StringUtils.isEmpty(repositoryModel.name)) { - error(getString("gb.pleaseSetRepositoryName")); - return; - } - - // ensure name is trimmed - repositoryModel.name = repositoryModel.name.trim(); - - // automatically convert backslashes to forward slashes - repositoryModel.name = repositoryModel.name.replace('\\', '/'); - // Automatically replace // with / - repositoryModel.name = repositoryModel.name.replace("//", "/"); - - // prohibit folder paths - if (repositoryModel.name.startsWith("/")) { - error(getString("gb.illegalLeadingSlash")); - return; - } - if (repositoryModel.name.startsWith("../")) { - error(getString("gb.illegalRelativeSlash")); - return; - } - if (repositoryModel.name.contains("/../")) { - error(getString("gb.illegalRelativeSlash")); + if (!namePanel.updateModel(repositoryModel)) { return; } - if (repositoryModel.name.endsWith("/")) { - repositoryModel.name = repositoryModel.name.substring(0, repositoryModel.name.length() - 1); - } - - // confirm valid characters in repository name - Character c = StringUtils.findInvalidCharacter(repositoryModel.name); - if (c != null) { - error(MessageFormat.format(getString("gb.illegalCharacterRepositoryName"), - c)); - return; - } - - if (user.canCreate() && !user.canAdmin() && allowEditName) { - // ensure repository name begins with the user's path - if (!repositoryModel.name.startsWith(user.getPersonalPath())) { - error(MessageFormat.format(getString("gb.illegalPersonalRepositoryLocation"), - user.getPersonalPath())); - return; - } - - if (repositoryModel.name.equals(user.getPersonalPath())) { - // reset path prefix and show error - repositoryModel.name = user.getPersonalPath() + "/"; - error(getString("gb.pleaseSetRepositoryName")); - return; - } - } // confirm access restriction selection if (repositoryModel.accessRestriction == null) { @@ -426,6 +378,7 @@ public class EditRepositoryPage extends RootSubPage { } } catch (GitBlitException e) { error(e.getMessage()); + namePanel.resetModel(repositoryModel); return; } setRedirect(false); @@ -437,8 +390,10 @@ public class EditRepositoryPage extends RootSubPage { form.add(new SimpleAttributeModifier("autocomplete", "off")); // field names reflective match RepositoryModel fields - form.add(new TextField("name").setEnabled(allowEditName)); - form.add(new TextField("description")); + namePanel = new RepositoryNamePanel("namePanel", repositoryModel); + namePanel.setEditable(allowEditName); + form.add(namePanel); + form.add(ownersPalette); form.add(new CheckBox("allowForks").setEnabled(app().settings().getBoolean(Keys.web.allowForking, true))); DropDownChoice accessRestriction = new DropDownChoice("accessRestriction", diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html index 05f56012..8e4e74ac 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html @@ -12,11 +12,6 @@
-
-
- -
-
diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java index e2e5d4bc..0adb1ddd 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java @@ -29,7 +29,6 @@ import org.apache.wicket.markup.html.form.Button; import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.Form; -import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.model.CompoundPropertyModel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; @@ -61,7 +60,7 @@ import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.RepositoryNamePanel; -import com.gitblit.wicket.panels.RepositoryPermissionPanel; +import com.gitblit.wicket.panels.AccessPolicyPanel; public class NewRepositoryPage extends RootSubPage { @@ -70,7 +69,7 @@ public class NewRepositoryPage extends RootSubPage { private Model gitignoreModel; private IModel addGitflowModel; private IModel addGitignoreModel; - private RepositoryPermissionPanel permissionPanel; + private AccessPolicyPanel permissionPanel; private RepositoryNamePanel namePanel; public NewRepositoryPage() { @@ -159,8 +158,6 @@ public class NewRepositoryPage extends RootSubPage { namePanel = new RepositoryNamePanel("namePanel", repositoryModel); form.add(namePanel); - form.add(new TextField("description")); - // prepare the default access controls AccessRestrictionType defaultRestriction = AccessRestrictionType.fromName( app().settings().getString(Keys.git.defaultAccessRestriction, AccessRestrictionType.PUSH.name())); @@ -177,7 +174,7 @@ public class NewRepositoryPage extends RootSubPage { repositoryModel.authorizationControl = defaultControl; repositoryModel.accessRestriction = defaultRestriction; - permissionPanel = new RepositoryPermissionPanel("permissionPanel", repositoryModel); + permissionPanel = new AccessPolicyPanel("permissionPanel", repositoryModel); form.add(permissionPanel); // diff --git a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html new file mode 100644 index 00000000..38fa7f6a --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html @@ -0,0 +1,28 @@ + + + + + + +

+

+ + +
+
+ + +
+
+
+ +
+
+
+ +
+ + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java new file mode 100644 index 00000000..a115e251 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java @@ -0,0 +1,171 @@ +/* + * 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.util.ArrayList; +import java.util.List; + +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.Radio; +import org.apache.wicket.markup.html.form.RadioGroup; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; +import org.apache.wicket.model.Model; + +import com.gitblit.Constants.AccessRestrictionType; +import com.gitblit.Constants.AuthorizationControl; +import com.gitblit.Keys; +import com.gitblit.models.RepositoryModel; +import com.gitblit.wicket.WicketUtils; + +/** + * A radio group panel of the 5 available authorization/access restriction combinations. + * + * @author James Moger + * + */ +public class AccessPolicyPanel extends BasePanel { + + private static final long serialVersionUID = 1L; + + private final RepositoryModel repository; + + private RadioGroup policiesGroup; + + public AccessPolicyPanel(String wicketId, RepositoryModel repository) { + super(wicketId); + this.repository = repository; + } + + @Override + protected void onInitialize() { + super.onInitialize(); + + AccessPolicy anonymousPolicy = new AccessPolicy(getString("gb.anonymousPolicy"), + getString("gb.anonymousPolicyDescription"), + "blank.png", + AuthorizationControl.AUTHENTICATED, + AccessRestrictionType.NONE); + + AccessPolicy authenticatedPushPolicy = new AccessPolicy(getString("gb.authenticatedPushPolicy"), + getString("gb.authenticatedPushPolicyDescription"), + "lock_go_16x16.png", + AuthorizationControl.AUTHENTICATED, + AccessRestrictionType.PUSH); + + AccessPolicy namedPushPolicy = new AccessPolicy(getString("gb.namedPushPolicy"), + getString("gb.namedPushPolicyDescription"), + "lock_go_16x16.png", + AuthorizationControl.NAMED, + AccessRestrictionType.PUSH); + + AccessPolicy clonePolicy = new AccessPolicy(getString("gb.clonePolicy"), + getString("gb.clonePolicyDescription"), + "lock_pull_16x16.png", + AuthorizationControl.NAMED, + AccessRestrictionType.CLONE); + + AccessPolicy viewPolicy = new AccessPolicy(getString("gb.viewPolicy"), + getString("gb.viewPolicyDescription"), + "shield_16x16.png", + AuthorizationControl.NAMED, + AccessRestrictionType.VIEW); + + List policies = new ArrayList(); + if (app().settings().getBoolean(Keys.git.allowAnonymousPushes, false)) { + policies.add(anonymousPolicy); + } + policies.add(authenticatedPushPolicy); + policies.add(namedPushPolicy); + policies.add(clonePolicy); + policies.add(viewPolicy); + + AccessRestrictionType defaultRestriction = repository.accessRestriction; + if (defaultRestriction == null) { + defaultRestriction = AccessRestrictionType.fromName(app().settings().getString(Keys.git.defaultAccessRestriction, + AccessRestrictionType.PUSH.name())); + } + + AuthorizationControl defaultControl = repository.authorizationControl; + if (defaultControl == null) { + defaultControl = AuthorizationControl.fromName(app().settings().getString(Keys.git.defaultAuthorizationControl, + AuthorizationControl.NAMED.name())); + } + + AccessPolicy defaultPolicy = namedPushPolicy; + for (AccessPolicy policy : policies) { + if (policy.type == defaultRestriction && policy.control == defaultControl) { + defaultPolicy = policy; + } + } + + policiesGroup = new RadioGroup<>("policiesGroup", new Model(defaultPolicy)); + ListView policiesList = new ListView("policies", policies) { + + private static final long serialVersionUID = 1L; + + @Override + protected void populateItem(ListItem item) { + AccessPolicy p = item.getModelObject(); + item.add(new Radio("radio", item.getModel())); + item.add(WicketUtils.newImage("image", p.image)); + item.add(new Label("name", p.name)); + item.add(new Label("description", p.description)); + } + }; + policiesGroup.add(policiesList); + + setOutputMarkupId(true); + + add(policiesGroup); + } + + public void updateModel(RepositoryModel repository) { + AccessPolicy policy = policiesGroup.getModelObject(); + repository.authorizationControl = policy.control; + repository.accessRestriction = policy.type; + } + + @Override + protected boolean getStatelessHint() { + return false; + } + + private static class AccessPolicy implements Serializable { + + private static final long serialVersionUID = 1L; + + final String name; + final String description; + final String image; + final AuthorizationControl control; + final AccessRestrictionType type; + + AccessPolicy(String name, String description, String img, AuthorizationControl control, AccessRestrictionType type) { + this.name = name; + this.description = description; + this.image = img; + this.control = control; + this.type = type; + } + + @Override + public String toString() { + return name; + } + } +} diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html index f3a0738e..3c651620 100644 --- a/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html +++ b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html @@ -11,16 +11,19 @@
- -
 

/  
+ +
+
+ +
diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java index 7b20adec..358ff59b 100644 --- a/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java +++ b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java @@ -17,18 +17,20 @@ package com.gitblit.wicket.panels; import java.text.MessageFormat; import java.util.ArrayList; -import java.util.List; +import java.util.Set; +import java.util.TreeSet; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.TextField; +import com.gitblit.models.ProjectModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; /** - * A radio group panel of the 5 available authorization/access restriction combinations. + * A panel for naming a repository, specifying it's project, and entering a description. * * @author James Moger * @@ -37,44 +39,79 @@ public class RepositoryNamePanel extends BasePanel { private static final long serialVersionUID = 1L; - private final RepositoryModel repository; - private String fullName; + private DropDownChoice projectChoice; + + private TextField nameField; + public RepositoryNamePanel(String wicketId, RepositoryModel repository) { super(wicketId); - this.repository = repository; - } - - @Override - protected void onInitialize() { - super.onInitialize(); GitBlitWebSession session = GitBlitWebSession.get(); UserModel user = session.getUser(); - // build project list for repository destination + // build project set for repository destination String defaultProject = null; - List projects = new ArrayList(); + Set projectNames = new TreeSet(); + + // add the registered/known projects + for (ProjectModel project : app().projects().getProjectModels(user, false)) { + // TODO issue-351: user.canAdmin(project) + if (user.canAdmin()) { + if (project.isRoot) { + projectNames.add("/"); + } else { + projectNames.add(project.name + "/"); + } + } + } - if (user.canAdmin()) { - projects.add("/"); - defaultProject = "/"; + // add the user's personal project namespace + if (user.canAdmin() || user.canCreate()) { + projectNames.add(user.getPersonalPath() + "/"); } - if (user.canCreate()) { - String p = user.getPersonalPath() + "/"; - projects.add(p); - if (defaultProject == null) { - // only prefer personal namespace if default is not already set - defaultProject = p; + if (!StringUtils.isEmpty(repository.name)) { + // editing a repository name + // set the defaultProject to the current repository project + defaultProject = repository.projectPath; + if (StringUtils.isEmpty(defaultProject)) { + defaultProject = "/"; + } else { + defaultProject += "/"; + } + + projectNames.add(defaultProject); + } + + // if default project is not already set, set preference based on the user permissions + if (defaultProject == null) { + if (user.canAdmin()) { + defaultProject = "/"; + } else if (user.canCreate()) { + defaultProject = user.getPersonalPath() + "/"; } } + // update the model which is reflectively mapped to the Wicket fields by name repository.projectPath = defaultProject; + if (repository.projectPath.length() > 1 && !StringUtils.isEmpty(repository.name)) { + repository.name = repository.name.substring(repository.projectPath.length()); + } + projectChoice = new DropDownChoice("projectPath", new ArrayList(projectNames)); + nameField = new TextField("name"); + + // only enable project selection if we actually have multiple choices + add(projectChoice.setEnabled(projectNames.size() > 1)); + add(nameField); + add(new TextField("description")); + } - add(new DropDownChoice("projectPath", projects)); - add(new TextField("name")); + public void setEditable(boolean editable) { + // only enable project selection if we actually have multiple choices + projectChoice.setEnabled(projectChoice.getChoices().size() > 1 && editable); + nameField.setEnabled(editable); } public boolean updateModel(RepositoryModel repositoryModel) { diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.html b/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.html deleted file mode 100644 index 6a4d5cef..00000000 --- a/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - -
-
- - -
-
-
- -
-
-
- -
- - \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.java deleted file mode 100644 index ed3f1fed..00000000 --- a/src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 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.util.ArrayList; -import java.util.List; - -import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.html.form.Radio; -import org.apache.wicket.markup.html.form.RadioGroup; -import org.apache.wicket.markup.html.list.ListItem; -import org.apache.wicket.markup.html.list.ListView; -import org.apache.wicket.model.Model; - -import com.gitblit.Constants.AccessRestrictionType; -import com.gitblit.Constants.AuthorizationControl; -import com.gitblit.Keys; -import com.gitblit.models.RepositoryModel; -import com.gitblit.wicket.WicketUtils; - -/** - * A radio group panel of the 5 available authorization/access restriction combinations. - * - * @author James Moger - * - */ -public class RepositoryPermissionPanel extends BasePanel { - - private static final long serialVersionUID = 1L; - - private final RepositoryModel repository; - - private RadioGroup permissionGroup; - - public RepositoryPermissionPanel(String wicketId, RepositoryModel repository) { - super(wicketId); - this.repository = repository; - } - - @Override - protected void onInitialize() { - super.onInitialize(); - - Permission anonymousPermission = new Permission(getString("gb.anonymousPush"), - getString("gb.anonymousPushDescription"), - "blank.png", - AuthorizationControl.AUTHENTICATED, - AccessRestrictionType.NONE); - - Permission authenticatedPermission = new Permission(getString("gb.pushRestrictedAuthenticated"), - getString("gb.pushRestrictedAuthenticatedDescription"), - "lock_go_16x16.png", - AuthorizationControl.AUTHENTICATED, - AccessRestrictionType.PUSH); - - Permission publicPermission = new Permission(getString("gb.pushRestrictedNamed"), - getString("gb.pushRestrictedNamedDescription"), - "lock_go_16x16.png", - AuthorizationControl.NAMED, - AccessRestrictionType.PUSH); - - Permission protectedPermission = new Permission(getString("gb.cloneRestricted"), - getString("gb.cloneRestrictedDescription"), - "lock_pull_16x16.png", - AuthorizationControl.NAMED, - AccessRestrictionType.CLONE); - - Permission privatePermission = new Permission(getString("gb.private"), - getString("gb.privateRepoDescription"), - "shield_16x16.png", - AuthorizationControl.NAMED, - AccessRestrictionType.VIEW); - - List permissions = new ArrayList(); - if (app().settings().getBoolean(Keys.git.allowAnonymousPushes, false)) { - permissions.add(anonymousPermission); - } - permissions.add(authenticatedPermission); - permissions.add(publicPermission); - permissions.add(protectedPermission); - permissions.add(privatePermission); - - AccessRestrictionType defaultRestriction = repository.accessRestriction; - if (defaultRestriction == null) { - defaultRestriction = AccessRestrictionType.fromName(app().settings().getString(Keys.git.defaultAccessRestriction, - AccessRestrictionType.PUSH.name())); - } - - AuthorizationControl defaultControl = repository.authorizationControl; - if (defaultControl == null) { - defaultControl = AuthorizationControl.fromName(app().settings().getString(Keys.git.defaultAuthorizationControl, - AuthorizationControl.NAMED.name())); - } - - Permission defaultPermission = publicPermission; - for (Permission permission : permissions) { - if (permission.type == defaultRestriction && permission.control == defaultControl) { - defaultPermission = permission; - } - } - - permissionGroup = new RadioGroup<>("permissionsGroup", new Model(defaultPermission)); - ListView permissionsList = new ListView("permissions", permissions) { - - private static final long serialVersionUID = 1L; - - @Override - protected void populateItem(ListItem item) { - Permission p = item.getModelObject(); - item.add(new Radio("radio", item.getModel())); - item.add(WicketUtils.newImage("image", p.image)); - item.add(new Label("name", p.name)); - item.add(new Label("description", p.description)); - } - }; - permissionGroup.add(permissionsList); - - setOutputMarkupId(true); - - add(permissionGroup); - } - - public void updateModel(RepositoryModel repository) { - Permission permission = permissionGroup.getModelObject(); - repository.authorizationControl = permission.control; - repository.accessRestriction = permission.type; - } - - @Override - protected boolean getStatelessHint() { - return false; - } - - private static class Permission implements Serializable { - - private static final long serialVersionUID = 1L; - - final String name; - final String description; - final String image; - final AuthorizationControl control; - final AccessRestrictionType type; - - Permission(String name, String description, String img, AuthorizationControl control, AccessRestrictionType type) { - this.name = name; - this.description = description; - this.image = img; - this.control = control; - this.type = type; - } - - @Override - public String toString() { - return name; - } - } -} -- cgit v1.2.3 From 6a437ec4a6853bdd15f7c33f7fbafdd247a3790c Mon Sep 17 00:00:00 2001 From: James Moger Date: Sat, 31 May 2014 10:23:56 -0400 Subject: Use AccessPolicyPanel in EditRepositoryPage --- .../com/gitblit/wicket/GitBlitWebApp.properties | 4 +- .../gitblit/wicket/pages/EditRepositoryPage.html | 4 +- .../gitblit/wicket/pages/EditRepositoryPage.java | 91 +++------------------- .../gitblit/wicket/pages/NewRepositoryPage.html | 6 +- .../gitblit/wicket/pages/NewRepositoryPage.java | 10 +-- .../gitblit/wicket/panels/AccessPolicyPanel.java | 17 +++- 6 files changed, 33 insertions(+), 99 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index d2d1454e..13abcc06 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -687,7 +687,7 @@ gb.plugins = plugins gb.extensions = extensions gb.pleaseSelectProject = Please select the project! gb.accessPolicy = Access Policy -gb.accessPolicyDescription = Choose an access policy to control visibility, cloning, and pushing to this repository. +gb.accessPolicyDescription = Choose an access policy to control repository visibility and git permissions. gb.anonymousPolicy = Anonymous View, Clone, & Push gb.anonymousPolicyDescription = Anyone can see, clone, and push to this repository. gb.authenticatedPushPolicy = Restrict Push (Authenticated) @@ -704,5 +704,3 @@ gb.initWithReadme = Include a README gb.initWithReadmeDescription = This will generate a simple README document for your repository. gb.initWithGitignore = Include a .gitignore file gb.initWithGitignoreDescription = This will insert a config file that instructs your Git clients to ignore files or directories that match defined patterns. -gb.initWithGitflow = Include a .gitflow file -gb.initWithGitflowDescription = This will generate a config file which guides Git clients in setting up Gitflow branches. \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html index ccb60a5c..ab448038 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html @@ -58,9 +58,7 @@
-   diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java index 4759fd0d..e86bd1ee 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java @@ -29,7 +29,6 @@ import java.util.Set; import org.apache.wicket.PageParameters; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior; -import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.behavior.SimpleAttributeModifier; import org.apache.wicket.extensions.markup.html.form.palette.Palette; import org.apache.wicket.markup.html.WebMarkupContainer; @@ -40,7 +39,6 @@ import org.apache.wicket.markup.html.form.ChoiceRenderer; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.IChoiceRenderer; -import org.apache.wicket.markup.html.form.RadioChoice; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.markup.html.list.ListItem; @@ -69,6 +67,7 @@ import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.StringChoiceRenderer; import com.gitblit.wicket.WicketUtils; +import com.gitblit.wicket.panels.AccessPolicyPanel; import com.gitblit.wicket.panels.BasePanel.JavascriptEventConfirmation; import com.gitblit.wicket.panels.BulletListPanel; import com.gitblit.wicket.panels.RegistrantPermissionsPanel; @@ -80,6 +79,8 @@ public class EditRepositoryPage extends RootSubPage { RepositoryNamePanel namePanel; + AccessPolicyPanel accessPolicyPanel; + private boolean isAdmin; RepositoryModel repositoryModel; @@ -396,9 +397,6 @@ public class EditRepositoryPage extends RootSubPage { form.add(ownersPalette); form.add(new CheckBox("allowForks").setEnabled(app().settings().getBoolean(Keys.web.allowForking, true))); - DropDownChoice accessRestriction = new DropDownChoice("accessRestriction", - AccessRestrictionType.choices(app().settings().getBoolean(Keys.git.allowAnonymousPushes, false)), new AccessRestrictionRenderer()); - form.add(accessRestriction); form.add(new CheckBox("isFrozen")); // TODO enable origin definition form.add(new TextField("origin").setEnabled(false/* isCreate */)); @@ -456,11 +454,6 @@ public class EditRepositoryPage extends RootSubPage { form.add(new TextField("mailingLists", mailingLists)); form.add(indexedBranchesPalette); - List acList = Arrays.asList(AuthorizationControl.values()); - final RadioChoice authorizationControl = new RadioChoice( - "authorizationControl", acList, new AuthorizationControlRenderer()); - form.add(authorizationControl); - final CheckBox verifyCommitter = new CheckBox("verifyCommitter"); verifyCommitter.setOutputMarkupId(true); form.add(verifyCommitter); @@ -484,12 +477,10 @@ public class EditRepositoryPage extends RootSubPage { // anonymous everything, disable all controls usersPalette.setEnabled(false); teamsPalette.setEnabled(false); - authorizationControl.setEnabled(false); verifyCommitter.setEnabled(false); } else { // authenticated something // enable authorization controls - authorizationControl.setEnabled(true); verifyCommitter.setEnabled(true); boolean allowFineGrainedControls = repositoryModel.authorizationControl.equals(AuthorizationControl.NAMED); @@ -497,15 +488,15 @@ public class EditRepositoryPage extends RootSubPage { teamsPalette.setEnabled(allowFineGrainedControls); } - accessRestriction.add(new AjaxFormComponentUpdatingBehavior("onchange") { + AjaxFormChoiceComponentUpdatingBehavior callback = new AjaxFormChoiceComponentUpdatingBehavior() { private static final long serialVersionUID = 1L; @Override protected void onUpdate(AjaxRequestTarget target) { - // enable/disable permissions panel based on access restriction + accessPolicyPanel.updateModel(repositoryModel); + boolean allowAuthorizationControl = repositoryModel.accessRestriction.exceeds(AccessRestrictionType.NONE); - authorizationControl.setEnabled(allowAuthorizationControl); verifyCommitter.setEnabled(allowAuthorizationControl); boolean allowFineGrainedControls = allowAuthorizationControl && repositoryModel.authorizationControl.equals(AuthorizationControl.NAMED); @@ -516,36 +507,14 @@ public class EditRepositoryPage extends RootSubPage { repositoryModel.authorizationControl = AuthorizationControl.NAMED; } - target.addComponent(authorizationControl); target.addComponent(verifyCommitter); target.addComponent(usersPalette); target.addComponent(teamsPalette); } - }); - - authorizationControl.add(new AjaxFormChoiceComponentUpdatingBehavior() { - - private static final long serialVersionUID = 1L; - - @Override - protected void onUpdate(AjaxRequestTarget target) { - // enable/disable permissions panel based on access restriction - boolean allowAuthorizationControl = repositoryModel.accessRestriction.exceeds(AccessRestrictionType.NONE); - authorizationControl.setEnabled(allowAuthorizationControl); - - boolean allowFineGrainedControls = allowAuthorizationControl && repositoryModel.authorizationControl.equals(AuthorizationControl.NAMED); - usersPalette.setEnabled(allowFineGrainedControls); - teamsPalette.setEnabled(allowFineGrainedControls); + }; - if (allowFineGrainedControls) { - repositoryModel.authorizationControl = AuthorizationControl.NAMED; - } - - target.addComponent(authorizationControl); - target.addComponent(usersPalette); - target.addComponent(teamsPalette); - } - }); + accessPolicyPanel = new AccessPolicyPanel("accessPolicyPanel", repositoryModel, callback); + form.add(accessPolicyPanel); List renderers = Arrays.asList(CommitMessageRenderer.values()); DropDownChoice messageRendererChoice = new DropDownChoice("commitMessageRenderer", renderers); @@ -656,27 +625,6 @@ public class EditRepositoryPage extends RootSubPage { } } - private class AccessRestrictionRenderer implements IChoiceRenderer { - - private static final long serialVersionUID = 1L; - - private final Map map; - - public AccessRestrictionRenderer() { - map = getAccessRestrictions(); - } - - @Override - public String getDisplayValue(AccessRestrictionType type) { - return map.get(type); - } - - @Override - public String getIdValue(AccessRestrictionType type, int index) { - return Integer.toString(index); - } - } - private class FederationTypeRenderer implements IChoiceRenderer { private static final long serialVersionUID = 1L; @@ -698,27 +646,6 @@ public class EditRepositoryPage extends RootSubPage { } } - private class AuthorizationControlRenderer implements IChoiceRenderer { - - private static final long serialVersionUID = 1L; - - private final Map map; - - public AuthorizationControlRenderer() { - map = getAuthorizationControls(); - } - - @Override - public String getDisplayValue(AuthorizationControl type) { - return map.get(type); - } - - @Override - public String getIdValue(AuthorizationControl type, int index) { - return Integer.toString(index); - } - } - private class GCPeriodRenderer implements IChoiceRenderer { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html index 8e4e74ac..df55381a 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html @@ -14,7 +14,7 @@
-
+

@@ -39,8 +39,8 @@
- -

+ Include a .gitflow file +

This will generate a config file which guides Git clients in setting up Gitflow branches.

diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java index 0adb1ddd..d5ae3440 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java @@ -59,8 +59,8 @@ import com.gitblit.utils.FileUtils; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; -import com.gitblit.wicket.panels.RepositoryNamePanel; import com.gitblit.wicket.panels.AccessPolicyPanel; +import com.gitblit.wicket.panels.RepositoryNamePanel; public class NewRepositoryPage extends RootSubPage { @@ -69,7 +69,7 @@ public class NewRepositoryPage extends RootSubPage { private Model gitignoreModel; private IModel addGitflowModel; private IModel addGitignoreModel; - private AccessPolicyPanel permissionPanel; + private AccessPolicyPanel accessPolicyPanel; private RepositoryNamePanel namePanel; public NewRepositoryPage() { @@ -108,7 +108,7 @@ public class NewRepositoryPage extends RootSubPage { if (!namePanel.updateModel(repositoryModel)) { return; } - permissionPanel.updateModel(repositoryModel); + accessPolicyPanel.updateModel(repositoryModel); repositoryModel.owners = new ArrayList(); repositoryModel.owners.add(GitBlitWebSession.get().getUsername()); @@ -174,8 +174,8 @@ public class NewRepositoryPage extends RootSubPage { repositoryModel.authorizationControl = defaultControl; repositoryModel.accessRestriction = defaultRestriction; - permissionPanel = new AccessPolicyPanel("permissionPanel", repositoryModel); - form.add(permissionPanel); + accessPolicyPanel = new AccessPolicyPanel("accessPolicyPanel", repositoryModel); + form.add(accessPolicyPanel); // // initial commit options diff --git a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java index a115e251..057b96f4 100644 --- a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java @@ -19,6 +19,7 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Radio; import org.apache.wicket.markup.html.form.RadioGroup; @@ -44,11 +45,18 @@ public class AccessPolicyPanel extends BasePanel { private final RepositoryModel repository; + private final AjaxFormChoiceComponentUpdatingBehavior callback; + private RadioGroup policiesGroup; public AccessPolicyPanel(String wicketId, RepositoryModel repository) { + this(wicketId, repository, null); + } + + public AccessPolicyPanel(String wicketId, RepositoryModel repository, AjaxFormChoiceComponentUpdatingBehavior callback) { super(wicketId); this.repository = repository; + this.callback = callback; } @Override @@ -128,10 +136,13 @@ public class AccessPolicyPanel extends BasePanel { } }; policiesGroup.add(policiesList); + if (callback != null) { + policiesGroup.add(callback); + policiesGroup.setOutputMarkupId(true); + } + add(policiesGroup); setOutputMarkupId(true); - - add(policiesGroup); } public void updateModel(RepositoryModel repository) { @@ -145,7 +156,7 @@ public class AccessPolicyPanel extends BasePanel { return false; } - private static class AccessPolicy implements Serializable { + public static class AccessPolicy implements Serializable { private static final long serialVersionUID = 1L; -- cgit v1.2.3 From 85b5d72949ead641ba697543324ff5d236e23fd1 Mon Sep 17 00:00:00 2001 From: James Moger Date: Tue, 3 Jun 2014 00:16:38 -0400 Subject: Overhaul EditRepositoryPage for layout and usability --- .../com/gitblit/wicket/GitBlitWebApp.properties | 24 +- .../gitblit/wicket/pages/EditRepositoryPage.html | 242 ++++++++++++----- .../gitblit/wicket/pages/EditRepositoryPage.java | 288 ++++++++++++++++----- .../gitblit/wicket/panels/AccessPolicyPanel.html | 35 ++- .../gitblit/wicket/panels/AccessPolicyPanel.java | 20 ++ .../gitblit/wicket/panels/RepositoryNamePanel.html | 2 +- 6 files changed, 470 insertions(+), 141 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 13abcc06..bd5d89e0 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -133,7 +133,7 @@ gb.sendProposal = propose gb.status = status gb.origin = origin gb.headRef = default branch (HEAD) -gb.headRefDescription = change the ref that HEAD links to. e.g. refs/heads/master +gb.headRefDescription = The default branch that will be cloned and displayed on the Summary page. gb.federationStrategy = federation strategy gb.federationRegistration = federation registration gb.federationResults = federation pull results @@ -223,8 +223,8 @@ gb.queryResults = results {0} - {1} ({2} hits) gb.noHits = no hits gb.authored = authored gb.committed = committed -gb.indexedBranches = indexed branches -gb.indexedBranchesDescription = select the branches to include in your Lucene index +gb.indexedBranches = Indexed Branches +gb.indexedBranchesDescription = Select the branches to be indexed by Lucene gb.noIndexedRepositoriesWarning = none of your repositories are configured for Lucene indexing gb.undefinedQueryWarning = query is undefined! gb.noSelectedRepositoriesWarning = please select one or more repositories! @@ -704,3 +704,21 @@ gb.initWithReadme = Include a README gb.initWithReadmeDescription = This will generate a simple README document for your repository. gb.initWithGitignore = Include a .gitignore file gb.initWithGitignoreDescription = This will insert a config file that instructs your Git clients to ignore files or directories that match defined patterns. +gb.receive = receive +gb.permissions = permissions +gb.ownersDescription = Owners can manage all repository settings but they are not allowed to rename a repository unless it is their personal repository. +gb.userPermissionsDescription = You can specify individual user permissions. These settings will override team or regex permissions. +gb.teamPermissionsDescription = You can specify individual team permissions. These settings will override regex permissions. +gb.ticketSettings = Ticket Settings +gb.receiveSettings = Receive Settings +gb.receiveSettingsDescription = The receive settings control pushes to the repository. +gb.preReceiveDescription = Pre-receive hooks are executed after commits are received but BEFORE the refs are updated.

This is the appropriate hook for rejecting a push.

+gb.postReceiveDescription = Post-receive hooks are executed after commits are received but AFTER the refs are updated.

This is the appropriate hook for notifications, build triggers, etc.

+gb.federationStrategyDescription = Control if and how to federate this repository with another Gitblit. +gb.federationSetsDescription = This repository will be included in the selected federation sets. +gb.miscellaneous = miscellaneous +gb.originDescription = The url from which this repository was cloned. +gb.gc = GC +gb.garbageCollection = Garbage Collection +gb.garbageCollectionDescription = The garbage collector will pack loose objects pushed from clients and will remove unreferenced objects from the repository. +gb.commitMessageRendererDescription = Commit messages can be displayed as plaintext or as rendered markup. \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html index ab448038..b5f9528f 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html @@ -9,14 +9,17 @@
-
+
@@ -24,97 +27,200 @@
-
+ +
+ +
+ +
- - - - - - - - - - - - - - - - - - - - - - - -

 



+ +

+

+
+ +
+ +

+

+
+ +
+ +

+

+
+ +
+ + +
+

+

+ +
+ +
+
+
+ +
+ +

+

+ - - - - - - - - - - - + + + +




-
- -
+
+ +

+

+ - - + + + +
+ +
+
+ +

+

+ + + + +
+
+ +
+ + +
+ +

+

+ +
+ +
+
+
+
+ +
+ + +
+

+

+ +
+ +
+ +
+ +

+

+ +
- -
- - - - -
-
- - - -

 

+ +
+ +

+

+ +
+
-
-
-
-
+ + +
-
-
-
   
+
+
+ +
+ +
+
+
+
+
+
+
+ +
+ +
   
+ +
+
+ + +
+
+ +
+ +
+
+ + +
+
+ +
+ + +
+
+ \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java index e86bd1ee..16dac895 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java @@ -43,9 +43,11 @@ import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; +import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.model.CompoundPropertyModel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; +import org.apache.wicket.model.PropertyModel; import org.apache.wicket.model.util.CollectionModel; import org.apache.wicket.model.util.ListModel; import org.eclipse.jgit.lib.Repository; @@ -200,7 +202,7 @@ public class EditRepositoryPage extends RootSubPage { } } final Palette ownersPalette = new Palette("owners", new ListModel(owners), new CollectionModel( - persons), new ChoiceRenderer(null, "userId"), 12, true); + persons), new ChoiceRenderer(null, "userId"), 12, false); // indexed local branches palette List allLocalBranches = new ArrayList(); @@ -387,21 +389,7 @@ public class EditRepositoryPage extends RootSubPage { } }; - // do not let the browser pre-populate these fields - form.add(new SimpleAttributeModifier("autocomplete", "off")); - - // field names reflective match RepositoryModel fields - namePanel = new RepositoryNamePanel("namePanel", repositoryModel); - namePanel.setEditable(allowEditName); - form.add(namePanel); - - form.add(ownersPalette); - form.add(new CheckBox("allowForks").setEnabled(app().settings().getBoolean(Keys.web.allowForking, true))); - form.add(new CheckBox("isFrozen")); - // TODO enable origin definition - form.add(new TextField("origin").setEnabled(false/* isCreate */)); - - // allow relinking HEAD to a branch or tag other than master on edit repository + // Determine available refs & branches List availableRefs = new ArrayList(); List availableBranches = new ArrayList(); if (!ArrayUtils.isEmpty(repositoryModel.availableRefs)) { @@ -414,53 +402,79 @@ public class EditRepositoryPage extends RootSubPage { } } } - form.add(new DropDownChoice("HEAD", availableRefs).setEnabled(availableRefs.size() > 0)); - boolean gcEnabled = app().settings().getBoolean(Keys.git.enableGarbageCollection, false); - int defaultGcPeriod = app().settings().getInteger(Keys.git.defaultGarbageCollectionPeriod, 7); - if (repositoryModel.gcPeriod == 0) { - repositoryModel.gcPeriod = defaultGcPeriod; - } - List gcPeriods = Arrays.asList(1, 2, 3, 4, 5, 7, 10, 14 ); - form.add(new DropDownChoice("gcPeriod", gcPeriods, new GCPeriodRenderer()).setEnabled(gcEnabled)); - form.add(new TextField("gcThreshold").setEnabled(gcEnabled)); + // do not let the browser pre-populate these fields + form.add(new SimpleAttributeModifier("autocomplete", "off")); - // federation strategies - remove ORIGIN choice if this repository has - // no origin. - List federationStrategies = new ArrayList( - Arrays.asList(FederationStrategy.values())); - if (StringUtils.isEmpty(repositoryModel.origin)) { - federationStrategies.remove(FederationStrategy.FEDERATE_ORIGIN); - } - form.add(new DropDownChoice("federationStrategy", federationStrategies, - new FederationTypeRenderer())); - form.add(new CheckBox("acceptNewPatchsets")); - form.add(new CheckBox("acceptNewTickets")); - form.add(new CheckBox("requireApproval")); - form.add(new DropDownChoice("mergeTo", availableBranches).setEnabled(availableBranches.size() > 0)); - form.add(new CheckBox("useIncrementalPushTags")); - form.add(new CheckBox("showRemoteBranches")); - form.add(new CheckBox("skipSizeCalculation")); - form.add(new CheckBox("skipSummaryMetrics")); - List maxActivityCommits = Arrays.asList(-1, 0, 25, 50, 75, 100, 150, 200, 250, 500); - form.add(new DropDownChoice("maxActivityCommits", maxActivityCommits, new MaxActivityCommitsRenderer())); - metricAuthorExclusions = new Model(ArrayUtils.isEmpty(repositoryModel.metricAuthorExclusions) ? "" - : StringUtils.flattenStrings(repositoryModel.metricAuthorExclusions, " ")); - form.add(new TextField("metricAuthorExclusions", metricAuthorExclusions)); + // + // + // GENERAL + // + namePanel = new RepositoryNamePanel("namePanel", repositoryModel); + namePanel.setEditable(allowEditName); + form.add(namePanel); - mailingLists = new Model(ArrayUtils.isEmpty(repositoryModel.mailingLists) ? "" - : StringUtils.flattenStrings(repositoryModel.mailingLists, " ")); - form.add(new TextField("mailingLists", mailingLists)); - form.add(indexedBranchesPalette); + // XXX AccessPolicyPanel is defined later. + + form.add(newChoice("head", + getString("gb.headRef"), + getString("gb.headRefDescription"), + new PropertyModel(repositoryModel, "HEAD"), + availableRefs)); - final CheckBox verifyCommitter = new CheckBox("verifyCommitter"); - verifyCommitter.setOutputMarkupId(true); - form.add(verifyCommitter); + // + // PERMISSIONS + // + form.add(ownersPalette); form.add(usersPalette); form.add(teamsPalette); - form.add(federationSetsPalette); + + // + // TICKETS + // + form.add(newCheckbox("acceptNewPatchsets", + getString("gb.acceptNewPatchsets"), + getString("gb.acceptNewPatchsetsDescription"), + new PropertyModel(repositoryModel, "acceptNewPatchsets"))); + + form.add(newCheckbox("acceptNewTickets", + getString("gb.acceptNewTickets"), + getString("gb.acceptNewTicketsDescription"), + new PropertyModel(repositoryModel, "acceptNewPatchsets"))); + + form.add(newCheckbox("requireApproval", + getString("gb.requireApproval"), + getString("gb.requireApprovalDescription"), + new PropertyModel(repositoryModel, "requireApproval"))); + + form.add(newChoice("mergeTo", + getString("gb.mergeTo"), + getString("gb.mergeToDescription"), + new PropertyModel(repositoryModel, "mergeTo"), + availableBranches)); + + // + // RECEIVE + // + form.add(newCheckbox("isFrozen", + getString("gb.isFrozen"), + getString("gb.isFrozenDescription"), + new PropertyModel(repositoryModel, "isFrozen"))); + + form.add(newCheckbox("incrementalPushTags", + getString("gb.enableIncrementalPushTags"), + getString("gb.useIncrementalPushTagsDescription"), + new PropertyModel(repositoryModel, "useIncrementalPushTags"))); + + final CheckBox verifyCommitter = new CheckBox("checkbox", new PropertyModel(repositoryModel, "verifyCommitter")); + verifyCommitter.setOutputMarkupId(true); + form.add(newCheckbox("verifyCommitter", + getString("gb.verifyCommitter"), + getString("gb.verifyCommitterDescription"), + verifyCommitter)); + form.add(preReceivePalette); form.add(new BulletListPanel("inheritedPreReceive", getString("gb.inherited"), app().repositories() .getPreReceiveScriptsInherited(repositoryModel))); @@ -472,6 +486,116 @@ public class EditRepositoryPage extends RootSubPage { customFieldsSection.add(customFieldsListView); form.add(customFieldsSection.setVisible(!app().settings().getString(Keys.groovy.customFields, "").isEmpty())); + // + // FEDERATION + // + List federationStrategies = new ArrayList( + Arrays.asList(FederationStrategy.values())); + // federation strategies - remove ORIGIN choice if this repository has no origin. + if (StringUtils.isEmpty(repositoryModel.origin)) { + federationStrategies.remove(FederationStrategy.FEDERATE_ORIGIN); + } + + form.add(newChoice("federationStrategy", + getString("gb.federationStrategy"), + getString("gb.federationStrategyDescription"), + new DropDownChoice( + "choice", + new PropertyModel(repositoryModel, "federationStrategy"), + federationStrategies, + new FederationTypeRenderer()))); + + form.add(federationSetsPalette); + + // + // SEARCH + // + form.add(indexedBranchesPalette); + + // + // GARBAGE COLLECTION + // + boolean gcEnabled = app().settings().getBoolean(Keys.git.enableGarbageCollection, false); + int defaultGcPeriod = app().settings().getInteger(Keys.git.defaultGarbageCollectionPeriod, 7); + if (repositoryModel.gcPeriod == 0) { + repositoryModel.gcPeriod = defaultGcPeriod; + } + List gcPeriods = Arrays.asList(1, 2, 3, 4, 5, 7, 10, 14 ); + form.add(newChoice("gcPeriod", + getString("gb.gcPeriod"), + getString("gb.gcPeriodDescription"), + new DropDownChoice("choice", + new PropertyModel(repositoryModel, "gcPeriod"), + gcPeriods, + new GCPeriodRenderer())).setEnabled(gcEnabled)); + + form.add(newTextfield("gcThreshold", + getString("gb.gcThreshold"), + getString("gb.gcThresholdDescription"), + "span1", + new PropertyModel(repositoryModel, "gcThreshold")).setEnabled(gcEnabled)); + + // + // MISCELLANEOUS + // + + form.add(newTextfield("origin", + getString("gb.origin"), + getString("gb.originDescription"), + "span6", + new PropertyModel(repositoryModel, "origin")).setEnabled(false)); + + form.add(newCheckbox("showRemoteBranches", + getString("gb.showRemoteBranches"), + getString("gb.showRemoteBranchesDescription"), + new PropertyModel(repositoryModel, "showRemoteBranches"))); + + form.add(newCheckbox("skipSizeCalculation", + getString("gb.skipSizeCalculation"), + getString("gb.skipSizeCalculationDescription"), + new PropertyModel(repositoryModel, "skipSizeCalculation"))); + + form.add(newCheckbox("skipSummaryMetrics", + getString("gb.skipSummaryMetrics"), + getString("gb.skipSummaryMetricsDescription"), + new PropertyModel(repositoryModel, "skipSummaryMetrics"))); + + List maxActivityCommits = Arrays.asList(-1, 0, 25, 50, 75, 100, 150, 200, 250, 500); + form.add(newChoice("maxActivityCommits", + getString("gb.maxActivityCommits"), + getString("gb.maxActivityCommitsDescription"), + new DropDownChoice("choice", + new PropertyModel(repositoryModel, "maxActivityCommits"), + maxActivityCommits, + new MaxActivityCommitsRenderer()))); + + List renderers = Arrays.asList(CommitMessageRenderer.values()); + form.add(newChoice("commitMessageRenderer", + getString("gb.commitMessageRenderer"), + getString("gb.commitMessageRendererDescription"), + new DropDownChoice("choice", + new PropertyModel(repositoryModel, "commitMessageRenderer"), + renderers))); + + metricAuthorExclusions = new Model(ArrayUtils.isEmpty(repositoryModel.metricAuthorExclusions) ? "" + : StringUtils.flattenStrings(repositoryModel.metricAuthorExclusions, " ")); + + form.add(newTextfield("metricAuthorExclusions", + getString("gb.metricAuthorExclusions"), + getString("gb.metricAuthorExclusions"), + "span6", + metricAuthorExclusions)); + + mailingLists = new Model(ArrayUtils.isEmpty(repositoryModel.mailingLists) ? "" + : StringUtils.flattenStrings(repositoryModel.mailingLists, " ")); + + form.add(newTextfield("mailingLists", + getString("gb.mailingLists"), + getString("gb.mailingLists"), + "span6", + mailingLists)); + + // initial enable/disable of permission controls if (repositoryModel.accessRestriction.equals(AccessRestrictionType.NONE)) { // anonymous everything, disable all controls @@ -488,6 +612,9 @@ public class EditRepositoryPage extends RootSubPage { teamsPalette.setEnabled(allowFineGrainedControls); } + // + // ACCESS POLICY PANEL (GENERAL) + // AjaxFormChoiceComponentUpdatingBehavior callback = new AjaxFormChoiceComponentUpdatingBehavior() { private static final long serialVersionUID = 1L; @@ -516,10 +643,10 @@ public class EditRepositoryPage extends RootSubPage { accessPolicyPanel = new AccessPolicyPanel("accessPolicyPanel", repositoryModel, callback); form.add(accessPolicyPanel); - List renderers = Arrays.asList(CommitMessageRenderer.values()); - DropDownChoice messageRendererChoice = new DropDownChoice("commitMessageRenderer", renderers); - form.add(messageRendererChoice); + // + // FORM CONTROLS + // form.add(new Button("save")); Button cancel = new Button("cancel") { private static final long serialVersionUID = 1L; @@ -625,6 +752,51 @@ public class EditRepositoryPage extends RootSubPage { } } + private Fragment newCheckbox(String wicketId, String title, String description, IModel model) { + Fragment fragment = new Fragment(wicketId, "checkboxOption", this); + fragment.add(new Label("name", title)); + fragment.add(new Label("description", description)); + fragment.add(new CheckBox("checkbox", model)); + return fragment; + } + + private Fragment newCheckbox(String wicketId, String title, String description, CheckBox checkbox) { + Fragment fragment = new Fragment(wicketId, "checkboxOption", this); + fragment.add(new Label("name", title)); + fragment.add(new Label("description", description)); + fragment.add(checkbox); + return fragment; + } + + private Fragment newChoice(String wicketId, String title, String description, IModel model, List choices) { + Fragment fragment = new Fragment(wicketId, "choiceOption", this); + fragment.add(new Label("name", title)); + fragment.add(new Label("description", description)); + fragment.add(new DropDownChoice<>("choice", model, choices).setEnabled(choices.size() > 0)); + return fragment; + } + + private Fragment newChoice(String wicketId, String title, String description, DropDownChoice choice) { + Fragment fragment = new Fragment(wicketId, "choiceOption", this); + fragment.add(new Label("name", title)); + fragment.add(new Label("description", description)); + fragment.add(choice.setEnabled(choice.getChoices().size() > 0)); + return fragment; + } + + private Fragment newTextfield(String wicketId, String title, String description, String css, IModel model) { + Fragment fragment = new Fragment(wicketId, "textfieldOption", this); + fragment.add(new Label("name", title)); + fragment.add(new Label("description", description)); + TextField tf = new TextField("text", model); + if (!StringUtils.isEmpty(css)) { + WicketUtils.setCssClass(tf, css); + } + fragment.add(tf); + return fragment; + } + + private class FederationTypeRenderer implements IChoiceRenderer { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html index 38fa7f6a..965c4d51 100644 --- a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html +++ b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html @@ -10,19 +10,32 @@

- -
-
- - -
-
-
- -
+
+
+
+ +
- +
+
+ +
+
+
+ +
+
+ + +
+
+ +
+ +
+
+ \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java index 057b96f4..7aa801f4 100644 --- a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java @@ -21,10 +21,13 @@ import java.util.List; import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior; import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.Radio; import org.apache.wicket.markup.html.form.RadioGroup; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; +import org.apache.wicket.markup.html.panel.Fragment; +import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import com.gitblit.Constants.AccessRestrictionType; @@ -49,6 +52,8 @@ public class AccessPolicyPanel extends BasePanel { private RadioGroup policiesGroup; + private IModel allowForks; + public AccessPolicyPanel(String wicketId, RepositoryModel repository) { this(wicketId, repository, null); } @@ -142,13 +147,28 @@ public class AccessPolicyPanel extends BasePanel { } add(policiesGroup); + allowForks = Model.of(true); + add(newCheckbox("allowForks", + getString("gb.allowForks"), + getString("gb.allowForksDescription"), + allowForks).setEnabled(app().settings().getBoolean(Keys.web.allowForking, true))); + setOutputMarkupId(true); } + private Fragment newCheckbox(String wicketId, String title, String description, IModel model) { + Fragment fragment = new Fragment(wicketId, "checkboxOption", this); + fragment.add(new Label("name", title)); + fragment.add(new Label("description", description)); + fragment.add(new CheckBox("checkbox", model)); + return fragment; + } + public void updateModel(RepositoryModel repository) { AccessPolicy policy = policiesGroup.getModelObject(); repository.authorizationControl = policy.control; repository.accessRestriction = policy.type; + repository.allowForks = allowForks.getObject(); } @Override diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html index 3c651620..6fb6e45c 100644 --- a/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html +++ b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html @@ -15,7 +15,7 @@   +   -- cgit v1.2.3 From 2cf367f1970133303c872e969861be6147196fef Mon Sep 17 00:00:00 2001 From: James Moger Date: Tue, 3 Jun 2014 09:13:58 -0400 Subject: Extract re-usable checkbox, choice, and text option panels --- .../gitblit/wicket/pages/EditRepositoryPage.html | 33 -------- .../gitblit/wicket/pages/EditRepositoryPage.java | 90 ++++++---------------- .../gitblit/wicket/panels/AccessPolicyPanel.html | 9 --- .../gitblit/wicket/panels/AccessPolicyPanel.java | 12 +-- .../com/gitblit/wicket/panels/CheckboxOption.html | 17 ++++ .../com/gitblit/wicket/panels/CheckboxOption.java | 53 +++++++++++++ .../com/gitblit/wicket/panels/ChoiceOption.html | 19 +++++ .../com/gitblit/wicket/panels/ChoiceOption.java | 51 ++++++++++++ .../wicket/panels/RegistrantPermissionsPanel.html | 2 +- .../java/com/gitblit/wicket/panels/TextOption.html | 20 +++++ .../java/com/gitblit/wicket/panels/TextOption.java | 53 +++++++++++++ 11 files changed, 239 insertions(+), 120 deletions(-) create mode 100644 src/main/java/com/gitblit/wicket/panels/CheckboxOption.html create mode 100644 src/main/java/com/gitblit/wicket/panels/CheckboxOption.java create mode 100644 src/main/java/com/gitblit/wicket/panels/ChoiceOption.html create mode 100644 src/main/java/com/gitblit/wicket/panels/ChoiceOption.java create mode 100644 src/main/java/com/gitblit/wicket/panels/TextOption.html create mode 100644 src/main/java/com/gitblit/wicket/panels/TextOption.java (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html index b5f9528f..1e683b4f 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html @@ -189,38 +189,5 @@ - -
-
- -
- -
-
- - -
-
- -
- - -
-
- \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java index 16dac895..f891595c 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java @@ -43,7 +43,6 @@ import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; -import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.model.CompoundPropertyModel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; @@ -72,8 +71,11 @@ import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.AccessPolicyPanel; import com.gitblit.wicket.panels.BasePanel.JavascriptEventConfirmation; import com.gitblit.wicket.panels.BulletListPanel; +import com.gitblit.wicket.panels.CheckboxOption; +import com.gitblit.wicket.panels.ChoiceOption; import com.gitblit.wicket.panels.RegistrantPermissionsPanel; import com.gitblit.wicket.panels.RepositoryNamePanel; +import com.gitblit.wicket.panels.TextOption; public class EditRepositoryPage extends RootSubPage { @@ -417,7 +419,7 @@ public class EditRepositoryPage extends RootSubPage { // XXX AccessPolicyPanel is defined later. - form.add(newChoice("head", + form.add(new ChoiceOption("head", getString("gb.headRef"), getString("gb.headRefDescription"), new PropertyModel(repositoryModel, "HEAD"), @@ -434,22 +436,22 @@ public class EditRepositoryPage extends RootSubPage { // // TICKETS // - form.add(newCheckbox("acceptNewPatchsets", + form.add(new CheckboxOption("acceptNewPatchsets", getString("gb.acceptNewPatchsets"), getString("gb.acceptNewPatchsetsDescription"), new PropertyModel(repositoryModel, "acceptNewPatchsets"))); - form.add(newCheckbox("acceptNewTickets", + form.add(new CheckboxOption("acceptNewTickets", getString("gb.acceptNewTickets"), getString("gb.acceptNewTicketsDescription"), new PropertyModel(repositoryModel, "acceptNewPatchsets"))); - form.add(newCheckbox("requireApproval", + form.add(new CheckboxOption("requireApproval", getString("gb.requireApproval"), getString("gb.requireApprovalDescription"), new PropertyModel(repositoryModel, "requireApproval"))); - form.add(newChoice("mergeTo", + form.add(new ChoiceOption("mergeTo", getString("gb.mergeTo"), getString("gb.mergeToDescription"), new PropertyModel(repositoryModel, "mergeTo"), @@ -458,22 +460,22 @@ public class EditRepositoryPage extends RootSubPage { // // RECEIVE // - form.add(newCheckbox("isFrozen", + form.add(new CheckboxOption("isFrozen", getString("gb.isFrozen"), getString("gb.isFrozenDescription"), new PropertyModel(repositoryModel, "isFrozen"))); - form.add(newCheckbox("incrementalPushTags", + form.add(new CheckboxOption("incrementalPushTags", getString("gb.enableIncrementalPushTags"), getString("gb.useIncrementalPushTagsDescription"), new PropertyModel(repositoryModel, "useIncrementalPushTags"))); final CheckBox verifyCommitter = new CheckBox("checkbox", new PropertyModel(repositoryModel, "verifyCommitter")); verifyCommitter.setOutputMarkupId(true); - form.add(newCheckbox("verifyCommitter", + form.add(new CheckboxOption("verifyCommitter", getString("gb.verifyCommitter"), - getString("gb.verifyCommitterDescription"), - verifyCommitter)); + getString("gb.verifyCommitterDescription") + "
" + getString("gb.verifyCommitterNote"), + verifyCommitter).setIsHtmlDescription(true)); form.add(preReceivePalette); form.add(new BulletListPanel("inheritedPreReceive", getString("gb.inherited"), app().repositories() @@ -496,7 +498,7 @@ public class EditRepositoryPage extends RootSubPage { federationStrategies.remove(FederationStrategy.FEDERATE_ORIGIN); } - form.add(newChoice("federationStrategy", + form.add(new ChoiceOption("federationStrategy", getString("gb.federationStrategy"), getString("gb.federationStrategyDescription"), new DropDownChoice( @@ -521,7 +523,7 @@ public class EditRepositoryPage extends RootSubPage { repositoryModel.gcPeriod = defaultGcPeriod; } List gcPeriods = Arrays.asList(1, 2, 3, 4, 5, 7, 10, 14 ); - form.add(newChoice("gcPeriod", + form.add(new ChoiceOption("gcPeriod", getString("gb.gcPeriod"), getString("gb.gcPeriodDescription"), new DropDownChoice("choice", @@ -529,7 +531,7 @@ public class EditRepositoryPage extends RootSubPage { gcPeriods, new GCPeriodRenderer())).setEnabled(gcEnabled)); - form.add(newTextfield("gcThreshold", + form.add(new TextOption("gcThreshold", getString("gb.gcThreshold"), getString("gb.gcThresholdDescription"), "span1", @@ -539,29 +541,29 @@ public class EditRepositoryPage extends RootSubPage { // MISCELLANEOUS // - form.add(newTextfield("origin", + form.add(new TextOption("origin", getString("gb.origin"), getString("gb.originDescription"), "span6", new PropertyModel(repositoryModel, "origin")).setEnabled(false)); - form.add(newCheckbox("showRemoteBranches", + form.add(new CheckboxOption("showRemoteBranches", getString("gb.showRemoteBranches"), getString("gb.showRemoteBranchesDescription"), new PropertyModel(repositoryModel, "showRemoteBranches"))); - form.add(newCheckbox("skipSizeCalculation", + form.add(new CheckboxOption("skipSizeCalculation", getString("gb.skipSizeCalculation"), getString("gb.skipSizeCalculationDescription"), new PropertyModel(repositoryModel, "skipSizeCalculation"))); - form.add(newCheckbox("skipSummaryMetrics", + form.add(new CheckboxOption("skipSummaryMetrics", getString("gb.skipSummaryMetrics"), getString("gb.skipSummaryMetricsDescription"), new PropertyModel(repositoryModel, "skipSummaryMetrics"))); List maxActivityCommits = Arrays.asList(-1, 0, 25, 50, 75, 100, 150, 200, 250, 500); - form.add(newChoice("maxActivityCommits", + form.add(new ChoiceOption("maxActivityCommits", getString("gb.maxActivityCommits"), getString("gb.maxActivityCommitsDescription"), new DropDownChoice("choice", @@ -570,7 +572,7 @@ public class EditRepositoryPage extends RootSubPage { new MaxActivityCommitsRenderer()))); List renderers = Arrays.asList(CommitMessageRenderer.values()); - form.add(newChoice("commitMessageRenderer", + form.add(new ChoiceOption("commitMessageRenderer", getString("gb.commitMessageRenderer"), getString("gb.commitMessageRendererDescription"), new DropDownChoice("choice", @@ -580,7 +582,7 @@ public class EditRepositoryPage extends RootSubPage { metricAuthorExclusions = new Model(ArrayUtils.isEmpty(repositoryModel.metricAuthorExclusions) ? "" : StringUtils.flattenStrings(repositoryModel.metricAuthorExclusions, " ")); - form.add(newTextfield("metricAuthorExclusions", + form.add(new TextOption("metricAuthorExclusions", getString("gb.metricAuthorExclusions"), getString("gb.metricAuthorExclusions"), "span6", @@ -589,7 +591,7 @@ public class EditRepositoryPage extends RootSubPage { mailingLists = new Model(ArrayUtils.isEmpty(repositoryModel.mailingLists) ? "" : StringUtils.flattenStrings(repositoryModel.mailingLists, " ")); - form.add(newTextfield("mailingLists", + form.add(new TextOption("mailingLists", getString("gb.mailingLists"), getString("gb.mailingLists"), "span6", @@ -752,50 +754,6 @@ public class EditRepositoryPage extends RootSubPage { } } - private Fragment newCheckbox(String wicketId, String title, String description, IModel model) { - Fragment fragment = new Fragment(wicketId, "checkboxOption", this); - fragment.add(new Label("name", title)); - fragment.add(new Label("description", description)); - fragment.add(new CheckBox("checkbox", model)); - return fragment; - } - - private Fragment newCheckbox(String wicketId, String title, String description, CheckBox checkbox) { - Fragment fragment = new Fragment(wicketId, "checkboxOption", this); - fragment.add(new Label("name", title)); - fragment.add(new Label("description", description)); - fragment.add(checkbox); - return fragment; - } - - private Fragment newChoice(String wicketId, String title, String description, IModel model, List choices) { - Fragment fragment = new Fragment(wicketId, "choiceOption", this); - fragment.add(new Label("name", title)); - fragment.add(new Label("description", description)); - fragment.add(new DropDownChoice<>("choice", model, choices).setEnabled(choices.size() > 0)); - return fragment; - } - - private Fragment newChoice(String wicketId, String title, String description, DropDownChoice choice) { - Fragment fragment = new Fragment(wicketId, "choiceOption", this); - fragment.add(new Label("name", title)); - fragment.add(new Label("description", description)); - fragment.add(choice.setEnabled(choice.getChoices().size() > 0)); - return fragment; - } - - private Fragment newTextfield(String wicketId, String title, String description, String css, IModel model) { - Fragment fragment = new Fragment(wicketId, "textfieldOption", this); - fragment.add(new Label("name", title)); - fragment.add(new Label("description", description)); - TextField tf = new TextField("text", model); - if (!StringUtils.isEmpty(css)) { - WicketUtils.setCssClass(tf, css); - } - fragment.add(tf); - return fragment; - } - private class FederationTypeRenderer implements IChoiceRenderer { diff --git a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html index 965c4d51..d3c29ba7 100644 --- a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html +++ b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html @@ -27,15 +27,6 @@
- -
-
- -
- -
-
- \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java index 7aa801f4..4f234263 100644 --- a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java @@ -21,12 +21,10 @@ import java.util.List; import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior; import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.Radio; import org.apache.wicket.markup.html.form.RadioGroup; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; -import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; @@ -148,7 +146,7 @@ public class AccessPolicyPanel extends BasePanel { add(policiesGroup); allowForks = Model.of(true); - add(newCheckbox("allowForks", + add(new CheckboxOption("allowForks", getString("gb.allowForks"), getString("gb.allowForksDescription"), allowForks).setEnabled(app().settings().getBoolean(Keys.web.allowForking, true))); @@ -156,14 +154,6 @@ public class AccessPolicyPanel extends BasePanel { setOutputMarkupId(true); } - private Fragment newCheckbox(String wicketId, String title, String description, IModel model) { - Fragment fragment = new Fragment(wicketId, "checkboxOption", this); - fragment.add(new Label("name", title)); - fragment.add(new Label("description", description)); - fragment.add(new CheckBox("checkbox", model)); - return fragment; - } - public void updateModel(RepositoryModel repository) { AccessPolicy policy = policiesGroup.getModelObject(); repository.authorizationControl = policy.control; diff --git a/src/main/java/com/gitblit/wicket/panels/CheckboxOption.html b/src/main/java/com/gitblit/wicket/panels/CheckboxOption.html new file mode 100644 index 00000000..6684fe92 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/CheckboxOption.html @@ -0,0 +1,17 @@ + + + + + +
+
+ +
+ +
+
+ + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/CheckboxOption.java b/src/main/java/com/gitblit/wicket/panels/CheckboxOption.java new file mode 100644 index 00000000..086d8ef2 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/CheckboxOption.java @@ -0,0 +1,53 @@ +/* + * 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 org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.CheckBox; +import org.apache.wicket.model.IModel; + +/** + * A re-usable checkbox option panel. + * + * [x] title + * description + * + * @author James Moger + * + */ +public class CheckboxOption extends BasePanel { + + private static final long serialVersionUID = 1L; + + public CheckboxOption(String wicketId, String title, String description, IModel model) { + super(wicketId); + add(new Label("name", title)); + add(new Label("description", description)); + add(new CheckBox("checkbox", model)); + } + + public CheckboxOption(String wicketId, String title, String description, CheckBox checkbox) { + super(wicketId); + add(new Label("name", title)); + add(new Label("description", description)); + add(checkbox.setMarkupId("checkbox")); + } + + public CheckboxOption setIsHtmlDescription(boolean val) { + ((Label) get("description")).setEscapeModelStrings(!val); + return this; + } +} diff --git a/src/main/java/com/gitblit/wicket/panels/ChoiceOption.html b/src/main/java/com/gitblit/wicket/panels/ChoiceOption.html new file mode 100644 index 00000000..8c34c819 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/ChoiceOption.html @@ -0,0 +1,19 @@ + + + + + +
+
+ +
+
diff --git a/src/main/java/com/gitblit/wicket/panels/TextOption.html b/src/main/java/com/gitblit/wicket/panels/TextOption.html new file mode 100644 index 00000000..ff2da78e --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/TextOption.html @@ -0,0 +1,20 @@ + + + + + +
+
+ +
+ + +
+
+ + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/TextOption.java b/src/main/java/com/gitblit/wicket/panels/TextOption.java new file mode 100644 index 00000000..dcd465fb --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/TextOption.java @@ -0,0 +1,53 @@ +/* + * 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 org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.TextField; +import org.apache.wicket.model.IModel; + +import com.gitblit.utils.StringUtils; +import com.gitblit.wicket.WicketUtils; + +/** + * A re-usable textfield option panel. + * + * title + * description + * [textfield] + * + * @author James Moger + * + */ +public class TextOption extends BasePanel { + + private static final long serialVersionUID = 1L; + + public TextOption(String wicketId, String title, String description, IModel model) { + this(wicketId, title, description, null, model); + } + + public TextOption(String wicketId, String title, String description, String css, IModel model) { + super(wicketId); + add(new Label("name", title)); + add(new Label("description", description)); + TextField tf = new TextField("text", model); + if (!StringUtils.isEmpty(css)) { + WicketUtils.setCssClass(tf, css); + } + add(tf); + } +} -- cgit v1.2.3 From 7b8654dec60d378059bd9d765abcfd597b80ab5f Mon Sep 17 00:00:00 2001 From: James Moger Date: Tue, 3 Jun 2014 09:21:57 -0400 Subject: Use alignment from option panels un AccessPolicyPanel --- src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html index d3c29ba7..a2d76b7e 100644 --- a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html +++ b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html @@ -12,14 +12,10 @@
-
- - -
-
-
- +
+
+
-- cgit v1.2.3 From 6cc8ec025ad26f1451f0947fa4ad79bb2f9c292a Mon Sep 17 00:00:00 2001 From: James Moger Date: Tue, 3 Jun 2014 09:24:39 -0400 Subject: Hide empty option descriptions --- src/main/java/com/gitblit/wicket/panels/CheckboxOption.java | 5 +++-- src/main/java/com/gitblit/wicket/panels/ChoiceOption.java | 5 +++-- src/main/java/com/gitblit/wicket/panels/TextOption.java | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/panels/CheckboxOption.java b/src/main/java/com/gitblit/wicket/panels/CheckboxOption.java index 086d8ef2..08eeaa24 100644 --- a/src/main/java/com/gitblit/wicket/panels/CheckboxOption.java +++ b/src/main/java/com/gitblit/wicket/panels/CheckboxOption.java @@ -18,6 +18,7 @@ package com.gitblit.wicket.panels; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.model.IModel; +import org.parboiled.common.StringUtils; /** * A re-usable checkbox option panel. @@ -35,14 +36,14 @@ public class CheckboxOption extends BasePanel { public CheckboxOption(String wicketId, String title, String description, IModel model) { super(wicketId); add(new Label("name", title)); - add(new Label("description", description)); + add(new Label("description", description).setVisible(!StringUtils.isEmpty(description))); add(new CheckBox("checkbox", model)); } public CheckboxOption(String wicketId, String title, String description, CheckBox checkbox) { super(wicketId); add(new Label("name", title)); - add(new Label("description", description)); + add(new Label("description", description).setVisible(!StringUtils.isEmpty(description))); add(checkbox.setMarkupId("checkbox")); } diff --git a/src/main/java/com/gitblit/wicket/panels/ChoiceOption.java b/src/main/java/com/gitblit/wicket/panels/ChoiceOption.java index cc084a7b..9c25b70a 100644 --- a/src/main/java/com/gitblit/wicket/panels/ChoiceOption.java +++ b/src/main/java/com/gitblit/wicket/panels/ChoiceOption.java @@ -20,6 +20,7 @@ import java.util.List; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.model.IModel; +import org.parboiled.common.StringUtils; /** * A re-usable choice option panel. @@ -38,14 +39,14 @@ public class ChoiceOption extends BasePanel { public ChoiceOption(String wicketId, String title, String description, IModel model, List choices) { super(wicketId); add(new Label("name", title)); - add(new Label("description", description)); + add(new Label("description", description).setVisible(!StringUtils.isEmpty(description))); add(new DropDownChoice<>("choice", model, choices).setEnabled(choices.size() > 0)); } public ChoiceOption(String wicketId, String title, String description, DropDownChoice choice) { super(wicketId); add(new Label("name", title)); - add(new Label("description", description)); + add(new Label("description", description).setVisible(!StringUtils.isEmpty(description))); add(choice.setMarkupId("choice").setEnabled(choice.getChoices().size() > 0)); } } diff --git a/src/main/java/com/gitblit/wicket/panels/TextOption.java b/src/main/java/com/gitblit/wicket/panels/TextOption.java index dcd465fb..22370f3c 100644 --- a/src/main/java/com/gitblit/wicket/panels/TextOption.java +++ b/src/main/java/com/gitblit/wicket/panels/TextOption.java @@ -43,7 +43,7 @@ public class TextOption extends BasePanel { public TextOption(String wicketId, String title, String description, String css, IModel model) { super(wicketId); add(new Label("name", title)); - add(new Label("description", description)); + add(new Label("description", description).setVisible(!StringUtils.isEmpty(description))); TextField tf = new TextField("text", model); if (!StringUtils.isEmpty(css)) { WicketUtils.setCssClass(tf, css); -- cgit v1.2.3 From ba516f6c6aaabf7935ef42292f446bf375bf542b Mon Sep 17 00:00:00 2001 From: James Moger Date: Tue, 3 Jun 2014 09:56:50 -0400 Subject: Extract re-usable conditional choice option panel --- .../gitblit/wicket/pages/NewRepositoryPage.html | 36 ++-------- .../gitblit/wicket/pages/NewRepositoryPage.java | 44 ++++++------ .../wicket/panels/ConditionalChoiceOption.html | 19 ++++++ .../wicket/panels/ConditionalChoiceOption.java | 78 ++++++++++++++++++++++ 4 files changed, 120 insertions(+), 57 deletions(-) create mode 100644 src/main/java/com/gitblit/wicket/panels/ConditionalChoiceOption.html create mode 100644 src/main/java/com/gitblit/wicket/panels/ConditionalChoiceOption.java (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html index df55381a..115b8c10 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html @@ -19,41 +19,13 @@

-
-

-
+

-
-
- -
-
-
-

-
-
+
-
- -
- -
-
- Include a .gitflow file -

This will generate a config file which guides Git clients in setting up Gitflow branches.

-
-
+
-
-
- -
-
-
-

-

+

+
+
+ +
+ + + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/BooleanOption.java b/src/main/java/com/gitblit/wicket/panels/BooleanOption.java new file mode 100644 index 00000000..4a9299ce --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/BooleanOption.java @@ -0,0 +1,54 @@ +/* + * 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 org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.CheckBox; +import org.apache.wicket.model.IModel; +import org.parboiled.common.StringUtils; + +/** + * A re-usable checkbox option panel. + * + * [x] title + * description + * + * @author James Moger + * + */ +public class BooleanOption extends BasePanel { + + private static final long serialVersionUID = 1L; + + public BooleanOption(String wicketId, String title, String description, IModel model) { + super(wicketId); + add(new Label("name", title)); + add(new Label("description", description).setVisible(!StringUtils.isEmpty(description))); + add(new CheckBox("checkbox", model)); + } + + public BooleanOption(String wicketId, String title, String description, CheckBox checkbox) { + super(wicketId); + add(new Label("name", title)); + add(new Label("description", description).setVisible(!StringUtils.isEmpty(description))); + add(checkbox.setMarkupId("checkbox")); + } + + public BooleanOption setIsHtmlDescription(boolean val) { + ((Label) get("description")).setEscapeModelStrings(!val); + return this; + } +} diff --git a/src/main/java/com/gitblit/wicket/panels/CheckboxOption.html b/src/main/java/com/gitblit/wicket/panels/CheckboxOption.html deleted file mode 100644 index 6684fe92..00000000 --- a/src/main/java/com/gitblit/wicket/panels/CheckboxOption.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - -
-
- -
- -
-
- - \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/CheckboxOption.java b/src/main/java/com/gitblit/wicket/panels/CheckboxOption.java deleted file mode 100644 index 08eeaa24..00000000 --- a/src/main/java/com/gitblit/wicket/panels/CheckboxOption.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.html.form.CheckBox; -import org.apache.wicket.model.IModel; -import org.parboiled.common.StringUtils; - -/** - * A re-usable checkbox option panel. - * - * [x] title - * description - * - * @author James Moger - * - */ -public class CheckboxOption extends BasePanel { - - private static final long serialVersionUID = 1L; - - public CheckboxOption(String wicketId, String title, String description, IModel model) { - super(wicketId); - add(new Label("name", title)); - add(new Label("description", description).setVisible(!StringUtils.isEmpty(description))); - add(new CheckBox("checkbox", model)); - } - - public CheckboxOption(String wicketId, String title, String description, CheckBox checkbox) { - super(wicketId); - add(new Label("name", title)); - add(new Label("description", description).setVisible(!StringUtils.isEmpty(description))); - add(checkbox.setMarkupId("checkbox")); - } - - public CheckboxOption setIsHtmlDescription(boolean val) { - ((Label) get("description")).setEscapeModelStrings(!val); - return this; - } -} diff --git a/src/main/java/com/gitblit/wicket/panels/ConditionalChoiceOption.html b/src/main/java/com/gitblit/wicket/panels/ConditionalChoiceOption.html deleted file mode 100644 index fb360d12..00000000 --- a/src/main/java/com/gitblit/wicket/panels/ConditionalChoiceOption.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - -
-
- -
-
-- cgit v1.2.3 From c9921bd3b0b7bf90b6e5e2a52141c3fdf0f31f89 Mon Sep 17 00:00:00 2001 From: James Moger Date: Wed, 4 Jun 2014 17:04:17 -0400 Subject: Revise the user profile page and add a preferences form --- .../com/gitblit/wicket/GitBlitWebApp.properties | 9 +- .../java/com/gitblit/wicket/pages/UserPage.html | 51 ++++--- .../java/com/gitblit/wicket/pages/UserPage.java | 153 +++++++++++++++++++-- .../gitblit/wicket/panels/AccessPolicyPanel.html | 2 +- .../gitblit/wicket/panels/BooleanChoiceOption.html | 2 +- .../com/gitblit/wicket/panels/BooleanOption.html | 2 +- .../com/gitblit/wicket/panels/ChoiceOption.html | 2 +- .../java/com/gitblit/wicket/panels/TextOption.html | 2 +- 8 files changed, 185 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index d6fd57e9..81171799 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -722,4 +722,11 @@ gb.originDescription = The url from which this repository was cloned. gb.gc = GC gb.garbageCollection = Garbage Collection gb.garbageCollectionDescription = The garbage collector will pack loose objects pushed from clients and will remove unreferenced objects from the repository. -gb.commitMessageRendererDescription = Commit messages can be displayed as plaintext or as rendered markup. \ No newline at end of file +gb.commitMessageRendererDescription = Commit messages can be displayed as plaintext or as rendered markup. +gb.preferences = preferences +gb.accountPreferences = Account Preferences +gb.accountPreferencesDescription = Specify your account preferences +gb.languagePreference = Language Preference +gb.languagePreferenceDescription = Select your preferred translation for the Gitblit UI +gb.displayNameDescription = The preferred name for display +gb.emailAddressDescription = The primary email address for receiving notifications \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.html b/src/main/java/com/gitblit/wicket/pages/UserPage.html index 7aaded7a..09267873 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.html +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.html @@ -7,27 +7,19 @@
-
-
-
-
-

-
-
-
+
+
+
- -
- -
+
+ +
+
+
@@ -41,11 +33,36 @@
+ + +
+
+ + +
  • +
    + + +
    +

    +

    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index 29b49b33..baad4a06 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -15,19 +15,27 @@ */ package com.gitblit.wicket.pages; +import java.io.Serializable; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Locale; import org.apache.wicket.PageParameters; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.html.link.BookmarkablePageLink; +import org.apache.wicket.markup.html.form.Form; +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.PersonIdent; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import com.gitblit.GitBlitException; import com.gitblit.Keys; import com.gitblit.models.Menu.ParameterMenuItem; import com.gitblit.models.NavLink; @@ -40,9 +48,10 @@ import com.gitblit.wicket.GitBlitWebApp; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.GitblitRedirectException; import com.gitblit.wicket.WicketUtils; -import com.gitblit.wicket.panels.GravatarImage; -import com.gitblit.wicket.panels.LinkPanel; +import com.gitblit.wicket.panels.ChoiceOption; import com.gitblit.wicket.panels.ProjectRepositoryPanel; +import com.gitblit.wicket.panels.TextOption; +import com.gitblit.wicket.panels.UserTitlePanel; public class UserPage extends RootPage { @@ -83,21 +92,18 @@ public class UserPage extends RootPage { user = new UserModel(userName); } - add(new Label("userDisplayName", user.getDisplayName())); - add(new Label("userUsername", user.username)); - LinkPanel email = new LinkPanel("userEmail", null, user.emailAddress, "mailto:#"); - email.setRenderBodyOnly(true); - add(email.setVisible(app().settings().getBoolean(Keys.web.showEmailAddresses, true) && !StringUtils.isEmpty(user.emailAddress))); - PersonIdent person = new PersonIdent(user.getDisplayName(), user.emailAddress == null ? user.getDisplayName() : user.emailAddress); - add(new GravatarImage("gravatar", person, 210)); + add(new UserTitlePanel("userTitlePanel", user, user.username)); UserModel sessionUser = GitBlitWebSession.get().getUser(); - if (sessionUser != null && user.canCreate() && sessionUser.equals(user)) { - // user can create personal repositories - add(new BookmarkablePageLink("newRepository", app().getNewRepositoryPage())); + boolean isMyProfile = sessionUser != null && sessionUser.equals(user); + + if (isMyProfile) { + addPreferences(user); } else { - add(new Label("newRepository").setVisible(false)); + // visiting user + add(new Label("preferencesLink").setVisible(false)); + add(new Label("preferencesTab").setVisible(false)); } List repositories = getRepositories(params); @@ -145,4 +151,121 @@ public class UserPage extends RootPage { navLinks.add(menu); } + + private void addPreferences(UserModel user) { + // add preferences + Form prefs = new Form("prefsForm"); + + List languages = Arrays.asList( + new Language("English","en"), + new Language("Español", "es"), + new Language("Français", "fr"), + new Language("日本語", "ja"), + new Language("한국ë§", "ko"), + new Language("Nederlands", "nl"), + new Language("Norsk", "no"), + new Language("JÄ™zyk Polski", "pl"), + new Language("Português", "pt_BR"), + new Language("中文", "zh_CN")); + + String lc = user.getPreferences().locale; + if (StringUtils.isEmpty(lc)) { + // user has not specified language preference + // try server default preference + lc = app().settings().getString(Keys.web.forceDefaultLocale, null); + if (StringUtils.isEmpty(lc)) { + // server default language is not configured + // try browser preference + Locale sessionLocale = GitBlitWebSession.get().getLocale(); + if (sessionLocale != null) { + lc = sessionLocale.getLanguage() + "_" + sessionLocale.getCountry(); + } + } + } + Language preferredLanguage = null; + if (!StringUtils.isEmpty(lc)) { + for (Language language : languages) { + if (language.code.equals(lc)) { + // language_COUNTRY match + preferredLanguage = language; + } else if (preferredLanguage != null && lc.startsWith(language.code)) { + // language match, but not COUNTRY match + preferredLanguage = language; + } + } + } + + final IModel displayName = Model.of(user.getDisplayName()); + final IModel emailAddress = Model.of(user.emailAddress == null ? "" : user.emailAddress); + final IModel language = Model.of(preferredLanguage); + + prefs.add(new TextOption("displayName", + getString("gb.displayName"), + getString("gb.displayNameDescription"), + displayName).setVisible(app().authentication().supportsDisplayNameChanges(user))); + + prefs.add(new TextOption("emailAddress", + getString("gb.emailAddress"), + getString("gb.emailAddressDescription"), + emailAddress).setVisible(app().authentication().supportsEmailAddressChanges(user))); + + prefs.add(new ChoiceOption("language", + getString("gb.languagePreference"), + getString("gb.languagePreferenceDescription"), + language, + languages)); + + prefs.add(new AjaxButton("save") { + + private static final long serialVersionUID = 1L; + + @Override + protected void onSubmit(AjaxRequestTarget target, Form form) { + + UserModel user = GitBlitWebSession.get().getUser(); + + user.displayName = displayName.getObject(); + user.emailAddress = emailAddress.getObject(); + + Language lang = language.getObject(); + if (lang != null) { + user.getPreferences().locale = lang.code; + } + + try { + app().gitblit().reviseUser(user.username, user); + + setRedirect(true); + setResponsePage(UserPage.class, WicketUtils.newUsernameParameter(user.username)); + } catch (GitBlitException e) { + // logger.error("Failed to update user " + user.username, e); + // error(getString("gb.failedToUpdateUser"), false); + } + } + }); + + // add the preferences tab + add(new Fragment("preferencesLink", "preferencesLinkFragment", this).setRenderBodyOnly(true)); + Fragment fragment = new Fragment("preferencesTab", "preferencesTabFragment", this); + fragment.add(prefs); + add(fragment.setRenderBodyOnly(true)); + } + + private class Language implements Serializable { + + private static final long serialVersionUID = 1L; + + final String name; + final String code; + + public Language(String name, String code) { + this.name = name; + this.code = code; + } + + @Override + public String toString() { + return name + " (" + code +")"; + } + } } diff --git a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html index 87a02068..07050192 100644 --- a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html +++ b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html @@ -13,7 +13,7 @@
    - +
    diff --git a/src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.html b/src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.html index fb360d12..b1ced8da 100644 --- a/src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.html +++ b/src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.html @@ -8,7 +8,7 @@
    - +
    diff --git a/src/main/java/com/gitblit/wicket/panels/ChoiceOption.html b/src/main/java/com/gitblit/wicket/panels/ChoiceOption.html index 8c34c819..e9e48874 100644 --- a/src/main/java/com/gitblit/wicket/panels/ChoiceOption.html +++ b/src/main/java/com/gitblit/wicket/panels/ChoiceOption.html @@ -7,7 +7,7 @@
    -
    +
    @@ -47,6 +51,10 @@
  • + +
  • +
    +

    @@ -63,6 +71,12 @@
    + +
    +
    +
    +
    + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index baad4a06..4a955c7c 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -50,6 +50,7 @@ import com.gitblit.wicket.GitblitRedirectException; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.ChoiceOption; import com.gitblit.wicket.panels.ProjectRepositoryPanel; +import com.gitblit.wicket.panels.SshKeysPanel; import com.gitblit.wicket.panels.TextOption; import com.gitblit.wicket.panels.UserTitlePanel; @@ -100,10 +101,22 @@ public class UserPage extends RootPage { if (isMyProfile) { addPreferences(user); + + if (app().gitblit().isServingSSH()) { + // show the SSH key management tab + addSshKeys(user); + } else { + // SSH daemon is disabled, hide keys tab + add(new Label("sshKeysLink").setVisible(false)); + add(new Label("sshKeysTab").setVisible(false)); + } } else { // visiting user add(new Label("preferencesLink").setVisible(false)); add(new Label("preferencesTab").setVisible(false)); + + add(new Label("sshKeysLink").setVisible(false)); + add(new Label("sshKeysTab").setVisible(false)); } List repositories = getRepositories(params); @@ -251,6 +264,15 @@ public class UserPage extends RootPage { add(fragment.setRenderBodyOnly(true)); } + private void addSshKeys(final UserModel user) { + Fragment keysTab = new Fragment("sshKeysTab", "sshKeysTabFragment", this); + keysTab.add(new SshKeysPanel("sshKeysPanel", user, getClass(), getPageParameters())); + + // add the SSH keys tab + add(new Fragment("sshKeysLink", "sshKeysLinkFragment", this).setRenderBodyOnly(true)); + add(keysTab.setRenderBodyOnly(true)); + } + private class Language implements Serializable { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.html b/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.html new file mode 100644 index 00000000..d67b704a --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.html @@ -0,0 +1,46 @@ + + + + + +

    +

    +
    + +
    +
    + +
    +
    +
    +
    
    +		
    + +
    +
    +
    +
    + +
    + +
    + +
    +
    + +
    +
    +

    +
    +
    +
    + +
    +
    +
    +
    + + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java b/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java new file mode 100644 index 00000000..03cb93ca --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java @@ -0,0 +1,161 @@ +/* + * 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.util.Arrays; +import java.util.List; + +import org.apache.wicket.PageParameters; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.link.Link; +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 com.gitblit.Constants.AccessPermission; +import com.gitblit.models.UserModel; +import com.gitblit.transport.ssh.SshKey; +import com.gitblit.utils.StringUtils; +import com.gitblit.wicket.GitBlitWebSession; + + +/** + * A panel that enumerates and manages SSH public keys. + * + * @author James Moger + * + */ +public class SshKeysPanel extends BasePanel { + + private static final long serialVersionUID = 1L; + + private final UserModel user; + + private final Class pageClass; + + private final PageParameters params; + + public SshKeysPanel(String wicketId, UserModel user, Class pageClass, PageParameters params) { + super(wicketId); + + this.user = user; + this.pageClass = pageClass; + this.params = params; + } + + @Override + protected void onInitialize() { + super.onInitialize(); + List keys = app().keys().getKeys(user.username); + + final ListDataProvider dp = new ListDataProvider(keys); + DataView keysView = new DataView("keys", dp) { + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(final Item item) { + final SshKey key = item.getModelObject(); + item.add(new Label("comment", key.getComment())); + item.add(new Label("fingerprint", key.getFingerprint())); + item.add(new Label("permission", key.getPermission().toString())); + item.add(new Label("algorithm", key.getAlgorithm())); + + Link delete = new Link("delete") { + + private static final long serialVersionUID = 1L; + + @Override + public void onClick() { + if (app().keys().removeKey(user.username, key)) { + setRedirect(true); + setResponsePage(pageClass, params); + } + } + }; + item.add(delete); + } + }; + add(keysView); + + Form addKeyForm = new Form("addKeyForm"); + + final IModel keyData = Model.of(""); + addKeyForm.add(new TextAreaOption("addKeyData", + getString("gb.key"), + null, + "span5", + keyData)); + + final IModel keyPermission = Model.of(AccessPermission.PUSH); + addKeyForm.add(new ChoiceOption("addKeyPermission", + getString("gb.permission"), + getString("gb.sshKeyPermissionDescription"), + keyPermission, + Arrays.asList(AccessPermission.SSHPERMISSIONS))); + + final IModel keyComment = Model.of(""); + addKeyForm.add(new TextOption("addKeyComment", + getString("gb.comment"), + getString("gb.sshKeyCommentDescription"), + "span5", + keyComment)); + + addKeyForm.add(new AjaxButton("addKeyButton") { + + private static final long serialVersionUID = 1L; + + @Override + protected void onSubmit(AjaxRequestTarget target, Form form) { + + UserModel user = GitBlitWebSession.get().getUser(); + String data = keyData.getObject(); + if (StringUtils.isEmpty(data)) { + // do not submit empty key + return; + } + + SshKey key = new SshKey(data); + try { + key.getPublicKey(); + } catch (Exception e) { + // failed to parse the key + return; + } + + AccessPermission permission = keyPermission.getObject(); + key.setPermission(permission); + + String comment = keyComment.getObject(); + if (!StringUtils.isEmpty(comment)) { + key.setComment(comment); + } + + if (app().keys().addKey(user.username, key)) { + setRedirect(true); + setResponsePage(pageClass, params); + } + } + }); + + add(addKeyForm); + } +} diff --git a/src/main/java/com/gitblit/wicket/panels/TextAreaOption.html b/src/main/java/com/gitblit/wicket/panels/TextAreaOption.html new file mode 100644 index 00000000..bb7dc7c6 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/TextAreaOption.html @@ -0,0 +1,20 @@ + + + + + +
    +
    + +
    + + +
    +
    + + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/TextAreaOption.java b/src/main/java/com/gitblit/wicket/panels/TextAreaOption.java new file mode 100644 index 00000000..d2c74a06 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/TextAreaOption.java @@ -0,0 +1,54 @@ +/* + * 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 org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.TextArea; +import org.apache.wicket.model.IModel; + +import com.gitblit.utils.StringUtils; +import com.gitblit.wicket.WicketUtils; + +/** + * A re-usable textarea option panel. + * + * title + * description + * [text + * area] + * + * @author James Moger + * + */ +public class TextAreaOption extends BasePanel { + + private static final long serialVersionUID = 1L; + + public TextAreaOption(String wicketId, String title, String description, IModel model) { + this(wicketId, title, description, null, model); + } + + public TextAreaOption(String wicketId, String title, String description, String css, IModel model) { + super(wicketId); + add(new Label("name", title)); + add(new Label("description", description).setVisible(!StringUtils.isEmpty(description))); + TextArea tf = new TextArea("text", model); + if (!StringUtils.isEmpty(css)) { + WicketUtils.setCssClass(tf, css); + } + add(tf); + } +} diff --git a/src/test/java/com/gitblit/tests/mock/MockRuntimeManager.java b/src/test/java/com/gitblit/tests/mock/MockRuntimeManager.java index 6e56a873..54be539f 100644 --- a/src/test/java/com/gitblit/tests/mock/MockRuntimeManager.java +++ b/src/test/java/com/gitblit/tests/mock/MockRuntimeManager.java @@ -81,6 +81,21 @@ public class MockRuntimeManager implements IRuntimeManager { return true; } + @Override + public boolean isServingHTTP() { + return true; + } + + @Override + public boolean isServingGIT() { + return true; + } + + @Override + public boolean isServingSSH() { + return true; + } + @Override public boolean isDebugMode() { return true; -- cgit v1.2.3 From 6537deb8b76b7a4725c40a174a7c440385f88e51 Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 5 Jun 2014 10:20:59 -0400 Subject: Revise language/locale preference handling --- src/main/java/com/gitblit/ConfigUserService.java | 9 +++++--- .../java/com/gitblit/models/UserPreferences.java | 6 ++++- .../com/gitblit/wicket/GitBlitWebApp.properties | 2 +- .../java/com/gitblit/wicket/pages/UserPage.java | 26 ++++++++++++++-------- 4 files changed, 29 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/ConfigUserService.java b/src/main/java/com/gitblit/ConfigUserService.java index 9b4dd7f1..b5dfde3b 100644 --- a/src/main/java/com/gitblit/ConfigUserService.java +++ b/src/main/java/com/gitblit/ConfigUserService.java @@ -707,8 +707,9 @@ public class ConfigUserService implements IUserService { config.setBoolean(USER, model.username, DISABLED, true); } if (model.getPreferences() != null) { - if (!StringUtils.isEmpty(model.getPreferences().locale)) { - config.setString(USER, model.username, LOCALE, model.getPreferences().locale); + if (model.getPreferences().getLocale() != null) { + String val = model.getPreferences().getLocale().getLanguage() + "_" + model.getPreferences().getLocale().getCountry(); + config.setString(USER, model.username, LOCALE, val); } } @@ -880,11 +881,13 @@ public class ConfigUserService implements IUserService { user.stateProvince = config.getString(USER, username, STATEPROVINCE); user.countryCode = config.getString(USER, username, COUNTRYCODE); user.cookie = config.getString(USER, username, COOKIE); - user.getPreferences().locale = config.getString(USER, username, LOCALE); if (StringUtils.isEmpty(user.cookie) && !StringUtils.isEmpty(user.password)) { user.cookie = StringUtils.getSHA1(user.username + user.password); } + // preferences + user.getPreferences().setLocale(config.getString(USER, username, LOCALE)); + // user roles Set roles = new HashSet(Arrays.asList(config.getStringList( USER, username, ROLE))); diff --git a/src/main/java/com/gitblit/models/UserPreferences.java b/src/main/java/com/gitblit/models/UserPreferences.java index 44e44933..61db353c 100644 --- a/src/main/java/com/gitblit/models/UserPreferences.java +++ b/src/main/java/com/gitblit/models/UserPreferences.java @@ -37,7 +37,7 @@ public class UserPreferences implements Serializable { public final String username; - public String locale; + private String locale; private final Map repositoryPreferences = new TreeMap(); @@ -58,6 +58,10 @@ public class UserPreferences implements Serializable { return new Locale(locale); } + public void setLocale(String locale) { + this.locale = locale; + } + public UserRepositoryPreferences getRepositoryPreferences(String repositoryName) { String key = repositoryName.toLowerCase(); if (!repositoryPreferences.containsKey(key)) { diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 7dc0f9b6..90d30f29 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -727,7 +727,7 @@ gb.preferences = preferences gb.accountPreferences = Account Preferences gb.accountPreferencesDescription = Specify your account preferences gb.languagePreference = Language Preference -gb.languagePreferenceDescription = Select your preferred translation for the Gitblit UI +gb.languagePreferenceDescription = Select your preferred translation for Gitblit gb.displayNameDescription = The preferred name for display gb.emailAddressDescription = The primary email address for receiving notifications gb.sshKeys = SSH Keys diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index 4a955c7c..94048963 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -181,28 +181,36 @@ public class UserPage extends RootPage { new Language("Português", "pt_BR"), new Language("中文", "zh_CN")); - String lc = user.getPreferences().locale; - if (StringUtils.isEmpty(lc)) { + Locale locale = user.getPreferences().getLocale(); + if (locale == null) { // user has not specified language preference // try server default preference - lc = app().settings().getString(Keys.web.forceDefaultLocale, null); + String lc = app().settings().getString(Keys.web.forceDefaultLocale, null); if (StringUtils.isEmpty(lc)) { // server default language is not configured // try browser preference Locale sessionLocale = GitBlitWebSession.get().getLocale(); if (sessionLocale != null) { - lc = sessionLocale.getLanguage() + "_" + sessionLocale.getCountry(); + locale = sessionLocale; } + } else { + } } + Language preferredLanguage = null; - if (!StringUtils.isEmpty(lc)) { + if (locale != null) { + String localeCode = locale.getLanguage(); + if (!StringUtils.isEmpty(locale.getCountry())) { + localeCode += "_" + locale.getCountry(); + } + for (Language language : languages) { - if (language.code.equals(lc)) { + if (language.code.equals(localeCode)) { // language_COUNTRY match preferredLanguage = language; - } else if (preferredLanguage != null && lc.startsWith(language.code)) { - // language match, but not COUNTRY match + } else if (preferredLanguage != null && language.code.startsWith(locale.getLanguage())) { + // language match preferredLanguage = language; } } @@ -242,7 +250,7 @@ public class UserPage extends RootPage { Language lang = language.getObject(); if (lang != null) { - user.getPreferences().locale = lang.code; + user.getPreferences().setLocale(lang.code); } try { -- cgit v1.2.3 From 74221eb302e782ef23777d5c3f0a649ceb321c1e Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 5 Jun 2014 10:23:58 -0400 Subject: Add method to INotificationManager to return email service status --- src/main/java/com/gitblit/FederationClient.java | 5 +++++ src/main/java/com/gitblit/manager/GitblitManager.java | 5 +++++ src/main/java/com/gitblit/manager/INotificationManager.java | 8 ++++++++ src/main/java/com/gitblit/manager/NotificationManager.java | 5 +++++ 4 files changed, 23 insertions(+) (limited to 'src') diff --git a/src/main/java/com/gitblit/FederationClient.java b/src/main/java/com/gitblit/FederationClient.java index c3dcd9da..cd06c3cb 100644 --- a/src/main/java/com/gitblit/FederationClient.java +++ b/src/main/java/com/gitblit/FederationClient.java @@ -165,6 +165,11 @@ public class FederationClient { return this; } + @Override + public boolean isSendingMail() { + return false; + } + @Override public void sendMailToAdministrators(String subject, String message) { } diff --git a/src/main/java/com/gitblit/manager/GitblitManager.java b/src/main/java/com/gitblit/manager/GitblitManager.java index ef2433dd..98ad33e7 100644 --- a/src/main/java/com/gitblit/manager/GitblitManager.java +++ b/src/main/java/com/gitblit/manager/GitblitManager.java @@ -660,6 +660,11 @@ public class GitblitManager implements IGitblit { * NOTIFICATION MANAGER */ + @Override + public boolean isSendingMail() { + return notificationManager.isSendingMail(); + } + @Override public void sendMailToAdministrators(String subject, String message) { notificationManager.sendMailToAdministrators(subject, message); diff --git a/src/main/java/com/gitblit/manager/INotificationManager.java b/src/main/java/com/gitblit/manager/INotificationManager.java index 231cf43a..64fc01e8 100644 --- a/src/main/java/com/gitblit/manager/INotificationManager.java +++ b/src/main/java/com/gitblit/manager/INotificationManager.java @@ -21,6 +21,14 @@ import com.gitblit.models.Mailing; public interface INotificationManager extends IManager { + /** + * Returns true if the email service is configured and ready to send notifications. + * + * @return true if the email service is operational + * @since 1.6.0 + */ + boolean isSendingMail(); + /** * Notify the administrators by email. * diff --git a/src/main/java/com/gitblit/manager/NotificationManager.java b/src/main/java/com/gitblit/manager/NotificationManager.java index ba63cfc1..69a611bb 100644 --- a/src/main/java/com/gitblit/manager/NotificationManager.java +++ b/src/main/java/com/gitblit/manager/NotificationManager.java @@ -71,6 +71,11 @@ public class NotificationManager implements INotificationManager { return this; } + @Override + public boolean isSendingMail() { + return mailService.isReady(); + } + /** * Notify the administrators by email. * -- cgit v1.2.3 From afbaebde11093fae8b420aaaf71dcd56d8c0f9fd Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 5 Jun 2014 10:24:39 -0400 Subject: Add "email me on my ticket changes" preference --- src/main/java/com/gitblit/ConfigUserService.java | 4 ++++ src/main/java/com/gitblit/models/UserPreferences.java | 13 +++++++++++++ src/main/java/com/gitblit/tickets/TicketNotifier.java | 11 +++++++++-- src/main/java/com/gitblit/wicket/GitBlitWebApp.properties | 2 ++ src/main/java/com/gitblit/wicket/pages/UserPage.html | 3 ++- src/main/java/com/gitblit/wicket/pages/UserPage.java | 9 +++++++++ 6 files changed, 39 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/ConfigUserService.java b/src/main/java/com/gitblit/ConfigUserService.java index b5dfde3b..9759eff7 100644 --- a/src/main/java/com/gitblit/ConfigUserService.java +++ b/src/main/java/com/gitblit/ConfigUserService.java @@ -96,6 +96,8 @@ public class ConfigUserService implements IUserService { private static final String LOCALE = "locale"; + private static final String EMAILONMYTICKETCHANGES = "emailMeOnMyTicketChanges"; + private static final String ACCOUNTTYPE = "accountType"; private static final String DISABLED = "disabled"; @@ -711,6 +713,7 @@ public class ConfigUserService implements IUserService { String val = model.getPreferences().getLocale().getLanguage() + "_" + model.getPreferences().getLocale().getCountry(); config.setString(USER, model.username, LOCALE, val); } + config.setBoolean(USER, model.username, EMAILONMYTICKETCHANGES, model.getPreferences().isEmailMeOnMyTicketChanges()); } // user roles @@ -887,6 +890,7 @@ public class ConfigUserService implements IUserService { // preferences user.getPreferences().setLocale(config.getString(USER, username, LOCALE)); + user.getPreferences().setEmailMeOnMyTicketChanges(config.getBoolean(USER, username, EMAILONMYTICKETCHANGES, true)); // user roles Set roles = new HashSet(Arrays.asList(config.getStringList( diff --git a/src/main/java/com/gitblit/models/UserPreferences.java b/src/main/java/com/gitblit/models/UserPreferences.java index 61db353c..c95b0da5 100644 --- a/src/main/java/com/gitblit/models/UserPreferences.java +++ b/src/main/java/com/gitblit/models/UserPreferences.java @@ -39,6 +39,8 @@ public class UserPreferences implements Serializable { private String locale; + private Boolean emailMeOnMyTicketChanges; + private final Map repositoryPreferences = new TreeMap(); public UserPreferences(String username) { @@ -100,4 +102,15 @@ public class UserPreferences implements Serializable { Collections.sort(list); return list; } + + public boolean isEmailMeOnMyTicketChanges() { + if (emailMeOnMyTicketChanges == null) { + return true; + } + return emailMeOnMyTicketChanges; + } + + public void setEmailMeOnMyTicketChanges(boolean value) { + this.emailMeOnMyTicketChanges = value; + } } diff --git a/src/main/java/com/gitblit/tickets/TicketNotifier.java b/src/main/java/com/gitblit/tickets/TicketNotifier.java index 9a5e4e1d..07371b1b 100644 --- a/src/main/java/com/gitblit/tickets/TicketNotifier.java +++ b/src/main/java/com/gitblit/tickets/TicketNotifier.java @@ -545,7 +545,6 @@ public class TicketNotifier { } } } - mailing.setRecipients(toAddresses); // // CC recipients @@ -554,7 +553,7 @@ public class TicketNotifier { // repository owners if (!ArrayUtils.isEmpty(repository.owners)) { - tos.addAll(repository.owners); + ccs.addAll(repository.owners); } // cc users mentioned in last comment @@ -595,6 +594,14 @@ public class TicketNotifier { } ccAddresses.addAll(settings.getStrings(Keys.mail.mailingLists)); + // respect the author's email preference + UserModel lastAuthor = userManager.getUserModel(lastChange.author); + if (!lastAuthor.getPreferences().isEmailMeOnMyTicketChanges()) { + toAddresses.remove(lastAuthor.emailAddress); + ccAddresses.remove(lastAuthor.emailAddress); + } + + mailing.setRecipients(toAddresses); mailing.setCCs(ccAddresses); } diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 90d30f29..c80d45ce 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -728,6 +728,8 @@ gb.accountPreferences = Account Preferences gb.accountPreferencesDescription = Specify your account preferences gb.languagePreference = Language Preference gb.languagePreferenceDescription = Select your preferred translation for Gitblit +gb.emailMeOnMyTicketChanges = Email me on my ticket changes +gb.emailMeOnMyTicketChangesDescription = Send me an email notification for changes that I make to a ticket gb.displayNameDescription = The preferred name for display gb.emailAddressDescription = The primary email address for receiving notifications gb.sshKeys = SSH Keys diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.html b/src/main/java/com/gitblit/wicket/pages/UserPage.html index d71cb2b5..017fcb1f 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.html +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.html @@ -64,7 +64,8 @@
    -
    +
    +
    diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index 94048963..505f55d9 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -48,6 +48,7 @@ import com.gitblit.wicket.GitBlitWebApp; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.GitblitRedirectException; import com.gitblit.wicket.WicketUtils; +import com.gitblit.wicket.panels.BooleanOption; import com.gitblit.wicket.panels.ChoiceOption; import com.gitblit.wicket.panels.ProjectRepositoryPanel; import com.gitblit.wicket.panels.SshKeysPanel; @@ -219,6 +220,7 @@ public class UserPage extends RootPage { final IModel displayName = Model.of(user.getDisplayName()); final IModel emailAddress = Model.of(user.emailAddress == null ? "" : user.emailAddress); final IModel language = Model.of(preferredLanguage); + final IModel emailMeOnMyTicketChanges = Model.of(user.getPreferences().isEmailMeOnMyTicketChanges()); prefs.add(new TextOption("displayName", getString("gb.displayName"), @@ -236,6 +238,11 @@ public class UserPage extends RootPage { language, languages)); + prefs.add(new BooleanOption("emailMeOnMyTicketChanges", + getString("gb.emailMeOnMyTicketChanges"), + getString("gb.emailMeOnMyTicketChangesDescription"), + emailMeOnMyTicketChanges).setVisible(app().notifier().isSendingMail())); + prefs.add(new AjaxButton("save") { private static final long serialVersionUID = 1L; @@ -253,6 +260,8 @@ public class UserPage extends RootPage { user.getPreferences().setLocale(lang.code); } + user.getPreferences().setEmailMeOnMyTicketChanges(emailMeOnMyTicketChanges.getObject()); + try { app().gitblit().reviseUser(user.username, user); -- cgit v1.2.3 From b0658eedf4bc1590cd5003d17d9c71dd47b3c70c Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 5 Jun 2014 11:22:44 -0400 Subject: Use AJAX to manage the SSH keys panel --- .../java/com/gitblit/wicket/pages/UserPage.java | 2 +- .../com/gitblit/wicket/panels/SshKeysPanel.java | 46 +++++++++++++--------- 2 files changed, 28 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index 505f55d9..00a36272 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -283,7 +283,7 @@ public class UserPage extends RootPage { private void addSshKeys(final UserModel user) { Fragment keysTab = new Fragment("sshKeysTab", "sshKeysTabFragment", this); - keysTab.add(new SshKeysPanel("sshKeysPanel", user, getClass(), getPageParameters())); + keysTab.add(new SshKeysPanel("sshKeysPanel", user)); // add the SSH keys tab add(new Fragment("sshKeysLink", "sshKeysLinkFragment", this).setRenderBodyOnly(true)); diff --git a/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java b/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java index 03cb93ca..15ebd67b 100644 --- a/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java @@ -15,16 +15,15 @@ */ package com.gitblit.wicket.panels; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.apache.wicket.PageParameters; import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.ajax.markup.html.form.AjaxButton; -import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Form; -import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.markup.repeater.data.DataView; import org.apache.wicket.markup.repeater.data.ListDataProvider; @@ -39,7 +38,7 @@ import com.gitblit.wicket.GitBlitWebSession; /** - * A panel that enumerates and manages SSH public keys. + * A panel that enumerates and manages SSH public keys using AJAX. * * @author James Moger * @@ -50,25 +49,21 @@ public class SshKeysPanel extends BasePanel { private final UserModel user; - private final Class pageClass; - - private final PageParameters params; - - public SshKeysPanel(String wicketId, UserModel user, Class pageClass, PageParameters params) { + public SshKeysPanel(String wicketId, UserModel user) { super(wicketId); this.user = user; - this.pageClass = pageClass; - this.params = params; } @Override protected void onInitialize() { super.onInitialize(); - List keys = app().keys().getKeys(user.username); + setOutputMarkupId(true); + + final List keys = new ArrayList(app().keys().getKeys(user.username)); final ListDataProvider dp = new ListDataProvider(keys); - DataView keysView = new DataView("keys", dp) { + final DataView keysView = new DataView("keys", dp) { private static final long serialVersionUID = 1L; @Override @@ -79,15 +74,19 @@ public class SshKeysPanel extends BasePanel { item.add(new Label("permission", key.getPermission().toString())); item.add(new Label("algorithm", key.getAlgorithm())); - Link delete = new Link("delete") { + AjaxLink delete = new AjaxLink("delete") { private static final long serialVersionUID = 1L; @Override - public void onClick() { + public void onClick(AjaxRequestTarget target) { if (app().keys().removeKey(user.username, key)) { - setRedirect(true); - setResponsePage(pageClass, params); + // reset the keys list + keys.clear(); + keys.addAll(app().keys().getKeys(user.username)); + + // update the panel + target.addComponent(SshKeysPanel.this); } } }; @@ -150,8 +149,17 @@ public class SshKeysPanel extends BasePanel { } if (app().keys().addKey(user.username, key)) { - setRedirect(true); - setResponsePage(pageClass, params); + // reset add key fields + keyData.setObject(""); + keyPermission.setObject(AccessPermission.PUSH); + keyComment.setObject(""); + + // reset the keys list + keys.clear(); + keys.addAll(app().keys().getKeys(user.username)); + + // update the panel + target.addComponent(SshKeysPanel.this); } } }); -- cgit v1.2.3 From bfce9f59fca542d7b96b88d67494336b0c50b045 Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 5 Jun 2014 12:19:07 -0400 Subject: Add setting to control inclusion of personal repositories in the main list --- releases.moxie | 3 +++ src/main/distrib/data/gitblit.properties | 5 +++++ .../java/com/gitblit/wicket/pages/RepositoriesPage.java | 13 ++++++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/releases.moxie b/releases.moxie index c7299a7e..fc139b77 100644 --- a/releases.moxie +++ b/releases.moxie @@ -29,6 +29,7 @@ r24: { - Overhaul the EmptyRepositoryPage (ticket-73) - Overhauled the edit repository page (ticket-76) - Process bugtraq links in the ticket description and comments (ticket-78) + - Exclude personal repositories from the repositories list, by default (issue-419, ticket-95) additions: - Add My Tickets page (issue-215, ticket-15) - Added CRUD functionality for Ticket Milestones (ticket-17) @@ -55,8 +56,10 @@ r24: { - Marcus Hunger - Matthias Cullmann - Emmeran Seehuber + - Sascha Vogt settings: - { name: 'web.allowDeletingNonEmptyRepositories', defaultValue: 'true' } + - { name: 'web.includePersonalRepositories', defaultValue: 'false' } - { name: 'mail.starttls', defaultValue: 'false' } - { name: 'execution.defaultThreadPoolSize', defaultValue: '1' } - { name: 'git.gitignoreFolder', defaultValue: '${baseFolder}/gitignore' } diff --git a/src/main/distrib/data/gitblit.properties b/src/main/distrib/data/gitblit.properties index d5623cd5..65fe41e5 100644 --- a/src/main/distrib/data/gitblit.properties +++ b/src/main/distrib/data/gitblit.properties @@ -782,6 +782,11 @@ web.allowCookieAuthentication = true # SINCE 1.6.0 web.allowDeletingNonEmptyRepositories = true +# Setting to include personal repositories in the main repositories list. +# +# SINCE 1.6.0 +web.includePersonalRepositories = false + # Config file for storing project metadata # # SINCE 1.2.0 diff --git a/src/main/java/com/gitblit/wicket/pages/RepositoriesPage.java b/src/main/java/com/gitblit/wicket/pages/RepositoriesPage.java index a0b15a83..660b4ed1 100644 --- a/src/main/java/com/gitblit/wicket/pages/RepositoriesPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RepositoriesPage.java @@ -21,6 +21,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.text.MessageFormat; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import org.apache.wicket.Component; @@ -30,8 +31,8 @@ import org.eclipse.jgit.lib.Constants; import com.gitblit.Keys; import com.gitblit.models.Menu.ParameterMenuItem; -import com.gitblit.models.NavLink.DropDownPageMenuNavLink; import com.gitblit.models.NavLink; +import com.gitblit.models.NavLink.DropDownPageMenuNavLink; import com.gitblit.models.RepositoryModel; import com.gitblit.utils.MarkdownUtils; import com.gitblit.utils.StringUtils; @@ -79,7 +80,17 @@ public class RepositoriesPage extends RootPage { .setEscapeModelStrings(false).setVisible(message.length() > 0); add(repositoriesMessage); + // conditionally include personal repositories in this page List repositories = getRepositories(params); + if (!app().settings().getBoolean(Keys.web.includePersonalRepositories, true)) { + Iterator itr = repositories.iterator(); + while (itr.hasNext()) { + RepositoryModel rm = itr.next(); + if (rm.isPersonalRepository()) { + itr.remove(); + } + } + } RepositoriesPanel repositoriesPanel = new RepositoriesPanel("repositoriesPanel", showAdmin, true, repositories, true, getAccessRestrictions()); -- cgit v1.2.3 From 1b04d7730f56a08c935974504b2d849d01870c02 Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 5 Jun 2014 14:14:54 -0400 Subject: Add clone transport user preference --- releases.moxie | 1 + src/main/java/com/gitblit/ConfigUserService.java | 9 +++++++++ src/main/java/com/gitblit/GitBlit.java | 19 +++++++++++++++++++ .../java/com/gitblit/models/UserPreferences.java | 11 +++++++++++ .../com/gitblit/wicket/GitBlitWebApp.properties | 4 +++- .../java/com/gitblit/wicket/pages/UserPage.html | 1 + .../java/com/gitblit/wicket/pages/UserPage.java | 21 +++++++++++++++++++++ 7 files changed, 65 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/releases.moxie b/releases.moxie index fc139b77..c1e11d98 100644 --- a/releases.moxie +++ b/releases.moxie @@ -43,6 +43,7 @@ r24: { - Simplified repository creation, offer simple README generation, and insertion of a pre-defined .gitignore file (ticket-76) - Added an extension point for monitoring onStartup and onShutdown (ticket-79) - Tag server-side merges when incremental push tags are enabled (issue-432, ticket-85) + - Add a user preference for the clone transport (ticket-90) - Add setting to control default thread pool size for miscellaneous background tasks (ticket-92) dependencyChanges: - Update to javax.mail 1.5.1 (issue-417, ticket-58) diff --git a/src/main/java/com/gitblit/ConfigUserService.java b/src/main/java/com/gitblit/ConfigUserService.java index 9759eff7..0c5b2a58 100644 --- a/src/main/java/com/gitblit/ConfigUserService.java +++ b/src/main/java/com/gitblit/ConfigUserService.java @@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory; import com.gitblit.Constants.AccessPermission; import com.gitblit.Constants.AccountType; +import com.gitblit.Constants.Transport; import com.gitblit.manager.IRuntimeManager; import com.gitblit.models.TeamModel; import com.gitblit.models.UserModel; @@ -98,6 +99,8 @@ public class ConfigUserService implements IUserService { private static final String EMAILONMYTICKETCHANGES = "emailMeOnMyTicketChanges"; + private static final String TRANSPORT = "transport"; + private static final String ACCOUNTTYPE = "accountType"; private static final String DISABLED = "disabled"; @@ -713,7 +716,12 @@ public class ConfigUserService implements IUserService { String val = model.getPreferences().getLocale().getLanguage() + "_" + model.getPreferences().getLocale().getCountry(); config.setString(USER, model.username, LOCALE, val); } + config.setBoolean(USER, model.username, EMAILONMYTICKETCHANGES, model.getPreferences().isEmailMeOnMyTicketChanges()); + + if (model.getPreferences().getTransport() != null) { + config.setString(USER, model.username, TRANSPORT, model.getPreferences().getTransport().name()); + } } // user roles @@ -891,6 +899,7 @@ public class ConfigUserService implements IUserService { // preferences user.getPreferences().setLocale(config.getString(USER, username, LOCALE)); user.getPreferences().setEmailMeOnMyTicketChanges(config.getBoolean(USER, username, EMAILONMYTICKETCHANGES, true)); + user.getPreferences().setTransport(Transport.fromString(config.getString(USER, username, TRANSPORT))); // user roles Set roles = new HashSet(Arrays.asList(config.getStringList( diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java index 81793850..f9d9be9f 100644 --- a/src/main/java/com/gitblit/GitBlit.java +++ b/src/main/java/com/gitblit/GitBlit.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Set; @@ -264,6 +265,24 @@ public class GitBlit extends GitblitManager { } }); + // consider the user's transport preference + RepositoryUrl preferredUrl = null; + Transport preferredTransport = user.getPreferences().getTransport(); + if (preferredTransport != null) { + Iterator itr = list.iterator(); + while (itr.hasNext()) { + RepositoryUrl url = itr.next(); + if (url.transport.equals(preferredTransport)) { + itr.remove(); + preferredUrl = url; + break; + } + } + } + if (preferredUrl != null) { + list.add(0, preferredUrl); + } + return list; } diff --git a/src/main/java/com/gitblit/models/UserPreferences.java b/src/main/java/com/gitblit/models/UserPreferences.java index c95b0da5..90c034fc 100644 --- a/src/main/java/com/gitblit/models/UserPreferences.java +++ b/src/main/java/com/gitblit/models/UserPreferences.java @@ -23,6 +23,7 @@ import java.util.Locale; import java.util.Map; import java.util.TreeMap; +import com.gitblit.Constants.Transport; import com.gitblit.utils.StringUtils; /** @@ -41,6 +42,8 @@ public class UserPreferences implements Serializable { private Boolean emailMeOnMyTicketChanges; + private Transport transport; + private final Map repositoryPreferences = new TreeMap(); public UserPreferences(String username) { @@ -113,4 +116,12 @@ public class UserPreferences implements Serializable { public void setEmailMeOnMyTicketChanges(boolean value) { this.emailMeOnMyTicketChanges = value; } + + public Transport getTransport() { + return transport; + } + + public void setTransport(Transport transport) { + this.transport = transport; + } } diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index c80d45ce..eb92e2d2 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -739,4 +739,6 @@ gb.key = Key gb.comment = Comment gb.sshKeyCommentDescription = Enter an optional comment. If blank, the comment will be extracted from the key data. gb.permission = Permission -gb.sshKeyPermissionDescription = Specify the access permission for the SSH key \ No newline at end of file +gb.sshKeyPermissionDescription = Specify the access permission for the SSH key +gb.transportPreference = Transport Preference +gb.transportPreferenceDescription = Set the transport that you prefer to use for cloning \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.html b/src/main/java/com/gitblit/wicket/pages/UserPage.html index 017fcb1f..8dccfee7 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.html +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.html @@ -66,6 +66,7 @@
    +
    diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index 00a36272..306eea65 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -35,6 +35,7 @@ import org.apache.wicket.markup.repeater.data.ListDataProvider; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; +import com.gitblit.Constants.Transport; import com.gitblit.GitBlitException; import com.gitblit.Keys; import com.gitblit.models.Menu.ParameterMenuItem; @@ -221,6 +222,7 @@ public class UserPage extends RootPage { final IModel emailAddress = Model.of(user.emailAddress == null ? "" : user.emailAddress); final IModel language = Model.of(preferredLanguage); final IModel emailMeOnMyTicketChanges = Model.of(user.getPreferences().isEmailMeOnMyTicketChanges()); + final IModel transport = Model.of(user.getPreferences().getTransport()); prefs.add(new TextOption("displayName", getString("gb.displayName"), @@ -243,6 +245,24 @@ public class UserPage extends RootPage { getString("gb.emailMeOnMyTicketChangesDescription"), emailMeOnMyTicketChanges).setVisible(app().notifier().isSendingMail())); + List availableTransports = new ArrayList<>(); + if (app().gitblit().isServingSSH()) { + availableTransports.add(Transport.SSH); + } + if (app().gitblit().isServingHTTP()) { + availableTransports.add(Transport.HTTPS); + availableTransports.add(Transport.HTTP); + } + if (app().gitblit().isServingGIT()) { + availableTransports.add(Transport.GIT); + } + + prefs.add(new ChoiceOption("transport", + getString("gb.transportPreference"), + getString("gb.transportPreferenceDescription"), + transport, + availableTransports)); + prefs.add(new AjaxButton("save") { private static final long serialVersionUID = 1L; @@ -261,6 +281,7 @@ public class UserPage extends RootPage { } user.getPreferences().setEmailMeOnMyTicketChanges(emailMeOnMyTicketChanges.getObject()); + user.getPreferences().setTransport(transport.getObject()); try { app().gitblit().reviseUser(user.username, user); -- cgit v1.2.3 From f9e51c9454c89a8587bb122183c7658b94606d42 Mon Sep 17 00:00:00 2001 From: James Moger Date: Mon, 9 Jun 2014 09:10:13 -0400 Subject: Use separate project and name field models in the RepositoryNamePanel --- .../gitblit/wicket/pages/EditRepositoryPage.java | 3 +- .../gitblit/wicket/pages/NewRepositoryPage.java | 3 +- .../gitblit/wicket/panels/RepositoryNamePanel.java | 73 ++++++++++------------ 3 files changed, 36 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java index a0e6e7ba..a1c37385 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java @@ -70,8 +70,8 @@ import com.gitblit.wicket.StringChoiceRenderer; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.AccessPolicyPanel; import com.gitblit.wicket.panels.BasePanel.JavascriptEventConfirmation; -import com.gitblit.wicket.panels.BulletListPanel; import com.gitblit.wicket.panels.BooleanOption; +import com.gitblit.wicket.panels.BulletListPanel; import com.gitblit.wicket.panels.ChoiceOption; import com.gitblit.wicket.panels.RegistrantPermissionsPanel; import com.gitblit.wicket.panels.RepositoryNamePanel; @@ -383,7 +383,6 @@ public class EditRepositoryPage extends RootSubPage { } } catch (GitBlitException e) { error(e.getMessage()); - namePanel.resetModel(repositoryModel); return; } setRedirect(false); diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java index b8752e33..46877168 100644 --- a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java @@ -56,8 +56,8 @@ import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.AccessPolicyPanel; -import com.gitblit.wicket.panels.BooleanOption; import com.gitblit.wicket.panels.BooleanChoiceOption; +import com.gitblit.wicket.panels.BooleanOption; import com.gitblit.wicket.panels.RepositoryNamePanel; public class NewRepositoryPage extends RootSubPage { @@ -142,7 +142,6 @@ public class NewRepositoryPage extends RootSubPage { } catch (GitBlitException e) { error(e.getMessage()); - namePanel.resetModel(repositoryModel); return; } setRedirect(true); diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java index 358ff59b..d3e493ed 100644 --- a/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java +++ b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java @@ -22,6 +22,8 @@ import java.util.TreeSet; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.TextField; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; import com.gitblit.models.ProjectModel; import com.gitblit.models.RepositoryModel; @@ -41,7 +43,11 @@ public class RepositoryNamePanel extends BasePanel { private String fullName; - private DropDownChoice projectChoice; + private final IModel projectPath; + + private DropDownChoice pathChoice; + + private final IModel repoName; private TextField nameField; @@ -52,84 +58,82 @@ public class RepositoryNamePanel extends BasePanel { UserModel user = session.getUser(); // build project set for repository destination - String defaultProject = null; - Set projectNames = new TreeSet(); + String defaultPath = null; + String defaultName = null; + Set pathNames = new TreeSet(); // add the registered/known projects for (ProjectModel project : app().projects().getProjectModels(user, false)) { // TODO issue-351: user.canAdmin(project) if (user.canAdmin()) { if (project.isRoot) { - projectNames.add("/"); + pathNames.add("/"); } else { - projectNames.add(project.name + "/"); + pathNames.add(project.name + "/"); } } } // add the user's personal project namespace if (user.canAdmin() || user.canCreate()) { - projectNames.add(user.getPersonalPath() + "/"); + pathNames.add(user.getPersonalPath() + "/"); } if (!StringUtils.isEmpty(repository.name)) { // editing a repository name // set the defaultProject to the current repository project - defaultProject = repository.projectPath; - if (StringUtils.isEmpty(defaultProject)) { - defaultProject = "/"; + if (StringUtils.isEmpty(repository.projectPath)) { + defaultPath = "/"; } else { - defaultProject += "/"; + defaultPath = repository.projectPath + "/"; } - - projectNames.add(defaultProject); + defaultName = repository.name.substring(defaultPath.length()); + pathNames.add(defaultPath); } // if default project is not already set, set preference based on the user permissions - if (defaultProject == null) { + if (defaultPath == null) { if (user.canAdmin()) { - defaultProject = "/"; + defaultPath = "/"; } else if (user.canCreate()) { - defaultProject = user.getPersonalPath() + "/"; + defaultPath = user.getPersonalPath() + "/"; } } - // update the model which is reflectively mapped to the Wicket fields by name - repository.projectPath = defaultProject; - if (repository.projectPath.length() > 1 && !StringUtils.isEmpty(repository.name)) { - repository.name = repository.name.substring(repository.projectPath.length()); - } - projectChoice = new DropDownChoice("projectPath", new ArrayList(projectNames)); - nameField = new TextField("name"); + projectPath = Model.of(defaultPath); + pathChoice = new DropDownChoice("projectPath", projectPath, new ArrayList(pathNames)); + repoName = Model.of(defaultName); + nameField = new TextField("name", repoName); // only enable project selection if we actually have multiple choices - add(projectChoice.setEnabled(projectNames.size() > 1)); + add(pathChoice.setEnabled(pathNames.size() > 1)); add(nameField); add(new TextField("description")); } public void setEditable(boolean editable) { // only enable project selection if we actually have multiple choices - projectChoice.setEnabled(projectChoice.getChoices().size() > 1 && editable); + pathChoice.setEnabled(pathChoice.getChoices().size() > 1 && editable); nameField.setEnabled(editable); } public boolean updateModel(RepositoryModel repositoryModel) { - // confirm a project was selected - if (StringUtils.isEmpty(repositoryModel.projectPath)) { + // confirm a project path was selected + if (StringUtils.isEmpty(projectPath.getObject())) { error(getString("gb.pleaseSelectProject")); return false; } // confirm a repository name was entered - if (StringUtils.isEmpty(repositoryModel.name)) { + if (StringUtils.isEmpty(repoName.getObject())) { error(getString("gb.pleaseSetRepositoryName")); return false; } - String project = repositoryModel.projectPath; + String project = projectPath.getObject(); + String name = repoName.getObject(); - fullName = (project + repositoryModel.name).trim(); + fullName = (project + name).trim(); fullName = fullName.replace('\\', '/'); fullName = fullName.replace("//", "/"); if (fullName.charAt(0) == '/') { @@ -156,21 +160,12 @@ public class RepositoryNamePanel extends BasePanel { } repositoryModel.name = fullName; - repositoryModel.projectPath = null; return true; } - public void resetModel(RepositoryModel repositoryModel) { - // restore project and name fields on error condition - repositoryModel.projectPath = StringUtils.getFirstPathElement(fullName) + "/"; - if (repositoryModel.projectPath.length() > 1) { - repositoryModel.name = fullName.substring(repositoryModel.projectPath.length()); - } - } - @Override protected boolean getStatelessHint() { return false; } -} +} \ No newline at end of file -- cgit v1.2.3 From 7e6932b27785d8dd9309c9a4d7a5fa9824c6b9cf Mon Sep 17 00:00:00 2001 From: James Moger Date: Mon, 9 Jun 2014 11:28:08 -0400 Subject: Fix locale preference storing --- src/main/java/com/gitblit/ConfigUserService.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/ConfigUserService.java b/src/main/java/com/gitblit/ConfigUserService.java index 0c5b2a58..d7d6c14f 100644 --- a/src/main/java/com/gitblit/ConfigUserService.java +++ b/src/main/java/com/gitblit/ConfigUserService.java @@ -24,6 +24,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -712,8 +713,14 @@ public class ConfigUserService implements IUserService { config.setBoolean(USER, model.username, DISABLED, true); } if (model.getPreferences() != null) { - if (model.getPreferences().getLocale() != null) { - String val = model.getPreferences().getLocale().getLanguage() + "_" + model.getPreferences().getLocale().getCountry(); + Locale locale = model.getPreferences().getLocale(); + if (locale != null) { + String val; + if (StringUtils.isEmpty(locale.getCountry())) { + val = locale.getLanguage(); + } else { + val = locale.getLanguage() + "_" + locale.getCountry(); + } config.setString(USER, model.username, LOCALE, val); } -- cgit v1.2.3 From e0331746c1aee48a18ae2954770ca481d49eaf36 Mon Sep 17 00:00:00 2001 From: James Moger Date: Mon, 9 Jun 2014 11:33:42 -0400 Subject: Link to open tickets view for open milestones from ticket page --- src/main/java/com/gitblit/wicket/pages/TicketPage.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/main/java/com/gitblit/wicket/pages/TicketPage.java b/src/main/java/com/gitblit/wicket/pages/TicketPage.java index f7e4ada5..f5f63d23 100644 --- a/src/main/java/com/gitblit/wicket/pages/TicketPage.java +++ b/src/main/java/com/gitblit/wicket/pages/TicketPage.java @@ -250,8 +250,12 @@ public class TicketPage extends RepositoryPage { } else { // link to milestone query TicketMilestone milestone = app().tickets().getMilestone(repository, ticket.milestone); - PageParameters milestoneParameters = new PageParameters(); - milestoneParameters.put("r", repositoryName); + PageParameters milestoneParameters; + if (milestone.isOpen()) { + milestoneParameters = WicketUtils.newOpenTicketsParameter(repositoryName); + } else { + milestoneParameters = WicketUtils.newRepositoryParameter(repositoryName); + } milestoneParameters.put(Lucene.milestone.name(), ticket.milestone); int progress = 0; int open = 0; -- cgit v1.2.3 From dcd6541d4e7a159e7478962121fbfd0782568af0 Mon Sep 17 00:00:00 2001 From: James Moger Date: Mon, 9 Jun 2014 12:36:09 -0400 Subject: Switch to basic ant copy filter for web.xml --- build.xml | 22 ++++++++++++++++++---- src/main/java/WEB-INF/web.xml | 6 +----- 2 files changed, 19 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/build.xml b/build.xml index be6f1dd2..035f1896 100644 --- a/build.xml +++ b/build.xml @@ -174,8 +174,19 @@ + + + + + + + + + + + @@ -240,10 +251,13 @@ - - - - + + + + + + + diff --git a/src/main/java/WEB-INF/web.xml b/src/main/java/WEB-INF/web.xml index 3a6c4490..13f612e4 100644 --- a/src/main/java/WEB-INF/web.xml +++ b/src/main/java/WEB-INF/web.xml @@ -30,12 +30,8 @@ - - Gitblit - @gb.version@ - + Gitblit - @gb.version@ - -