Small refactoring

This commit is contained in:
steve 2013-10-24 14:07:12 +08:00
parent 75f3781035
commit 099817e007
31 changed files with 726 additions and 133 deletions

View File

@ -49,12 +49,14 @@ import com.pmease.gitop.web.component.avatar.AvatarImageResourceReference;
import com.pmease.gitop.web.exception.AccessDeniedException;
import com.pmease.gitop.web.page.account.RegisterPage;
import com.pmease.gitop.web.page.account.home.AccountHomePage;
import com.pmease.gitop.web.page.account.setting.members.AccountMembersPage;
import com.pmease.gitop.web.page.account.setting.password.AccountPasswordPage;
import com.pmease.gitop.web.page.account.setting.permission.AccountPermissionPage;
import com.pmease.gitop.web.page.account.setting.permission.AddTeamPage;
import com.pmease.gitop.web.page.account.setting.permission.EditTeamPage;
import com.pmease.gitop.web.page.account.setting.permissions.AccountPermissionsPage;
import com.pmease.gitop.web.page.account.setting.profile.AccountProfilePage;
import com.pmease.gitop.web.page.account.setting.repos.AccountReposPage;
import com.pmease.gitop.web.page.account.setting.teams.AccountTeamsPage;
import com.pmease.gitop.web.page.account.setting.teams.AddTeamPage;
import com.pmease.gitop.web.page.account.setting.teams.EditTeamPage;
import com.pmease.gitop.web.page.error.AccessDeniedPage;
import com.pmease.gitop.web.page.error.InternalErrorPage;
import com.pmease.gitop.web.page.error.PageNotFoundPage;
@ -66,7 +68,7 @@ import com.pmease.gitop.web.page.project.settings.MergeRequestSettingsPage;
import com.pmease.gitop.web.page.project.settings.ProjectAuditLogPage;
import com.pmease.gitop.web.page.project.settings.ProjectHooksPage;
import com.pmease.gitop.web.page.project.settings.ProjectOptionsPage;
import com.pmease.gitop.web.page.project.settings.ProjectPermissionsPage;
import com.pmease.gitop.web.page.project.settings.ProjectPermissionPage;
import com.pmease.gitop.web.page.project.source.ProjectHomePage;
import com.pmease.gitop.web.page.project.source.RepositoryBlobPage;
import com.pmease.gitop.web.page.project.source.RepositoryBranchesPage;
@ -226,7 +228,7 @@ public class GitopWebApp extends AbstractWicketConfig {
mount(new PageParameterAwareMountedMapper("${user}/${project}/settings/hooks", ProjectHooksPage.class));
mount(new PageParameterAwareMountedMapper("${user}/${project}/settings/merge-requests", MergeRequestSettingsPage.class));
mount(new PageParameterAwareMountedMapper("${user}/${project}/settings/audits", ProjectAuditLogPage.class));
mount(new PageParameterAwareMountedMapper("${user}/${project}/settings/permissions", ProjectPermissionsPage.class));
mount(new PageParameterAwareMountedMapper("${user}/${project}/settings/permissions", ProjectPermissionPage.class));
// account dashboard
mount(new MountedMapper("/${user}", AccountHomePage.class) {
@ -245,10 +247,12 @@ public class GitopWebApp extends AbstractWicketConfig {
// account settings
mountPage("settings/profile", AccountProfilePage.class);
mountPage("settings/password", AccountPasswordPage.class);
mountPage("settings/permission", AccountPermissionPage.class);
mountPage("settings/permission", AccountPermissionsPage.class);
mountPage("settings/repos", AccountReposPage.class);
mountPage("teams/add", AddTeamPage.class);
mountPage("teams/edit/${teamId}", EditTeamPage.class);
mountPage("settings/members", AccountMembersPage.class);
mountPage("settings/teams", AccountTeamsPage.class);
mountPage("settings/teams/new", AddTeamPage.class);
mountPage("settings/teams/edit/${teamId}", EditTeamPage.class);
// project related
mountPage("new", CreateProjectPage.class);

View File

@ -45,10 +45,10 @@ ul.piped, ol.piped { margin: 0; padding: 0; }
/* LINKS */
.checkable-link { color: #333; cursor: pointer; }
.checkable-link:hover { text-decoration: none; }
.checkable-link > .icon-checkbox:before { content: "\f096"; width: 16px; }
.checkable-link.checked > .icon-checkbox:before { content: "\f046"; width: 16px; }
.checkable-link.disabled { color: #888; }
em.checkable-link { color: #888 !important; }
.checkable-link .icon-checkbox:before { content: "\f096"; width: 16px; }
.checkable-link.checked .icon-checkbox:before { content: "\f046"; width: 16px; }
.checkable-link.disabled,
.checkable-link > em { color: #999; font-style: normal; cursor: not-allowed;}
/** LIST GROUP */
.list-navs > .list-group-item { border-width: 1px 0; position: relative; }
@ -235,6 +235,44 @@ fieldset[disabled] .btn-gray.active {
border-color: #cccccc;
}
.btn-inverse {
color: #ffffff;
background-color: #34495e;
}
.btn-inverse:hover,
.btn-inverse:focus,
.btn-inverse:active,
.btn-inverse.active,
.open .dropdown-toggle.btn-inverse {
color: #ffffff;
background-color: #415b76;
border-color: #415b76;
}
.btn-inverse:active,
.btn-inverse.active,
.open .dropdown-toggle.btn-inverse {
background: #2c3e50;
}
.btn-inverse.disabled,
.btn-inverse[disabled],
fieldset[disabled] .btn-inverse,
.btn-inverse.disabled:hover,
.btn-inverse[disabled]:hover,
fieldset[disabled] .btn-inverse:hover,
.btn-inverse.disabled:focus,
.btn-inverse[disabled]:focus,
fieldset[disabled] .btn-inverse:focus,
.btn-inverse.disabled:active,
.btn-inverse[disabled]:active,
fieldset[disabled] .btn-inverse:active,
.btn-inverse.disabled.active,
.btn-inverse[disabled].active,
fieldset[disabled] .btn-inverse.active {
background-color: #34495e;
}
.btn-inverse .caret { border-top-color: #fff; }
.btn-radio-group .btn .icon-ok { display: none; }
.btn-radio-group .btn.active { background: #999; color: white; }
.btn-radio-group .btn.active .icon-ok, .btn-radio-group .btn:hover .icon-ok { display: inline-block; }
@ -308,6 +346,8 @@ fieldset[disabled] .btn-gray.active {
.form-horizontal .field-controls { position: relative; min-height: 1px; padding-right: 15px; padding-left: 15px; float: left; }
.form-horizontal .control-label { width: 25%; }
.form-horizontal .field-controls { width: 74.884%; }
.form-horizontal .field-controls .message { margin: 0; padding-top: 7px; }
/**
* AVATAR
*/

View File

@ -1,6 +1,7 @@
/* MISC */
.img-link:hover { text-decoration: none; }
ul.f-dropdown { padding: 0; }
/**
* LAYOUT
@ -58,7 +59,6 @@
.select2-container-multi .select2-choices .select2-search-choice { background: #e5e5e5; }
.select2-container-multi .select2-choices { border-color: #ccc; }
/**
* MAIN
*/
@ -95,10 +95,10 @@
.sidebar .list-navs.first {margin-top: 20px; }
section .head { border-style: solid; border-width: 1px 0; border-color: #ddd; }
section:first-child .head { border-top: none; }
section .head h2, section .head h3 { margin: 0; font-size: 18px; line-height: 24px; color: #888; font-weight: 300; text-transform: uppercase; }
section .padder, section > .body { padding: 0px 20px 20px; margin-bottom: 18px; }
.content section > .head { border-style: solid; border-width: 1px 0; border-color: #ddd; margin-bottom: 0; }
section:first-child > .head { border-top: none; }
section>.head h2, section>.head h3 { margin: 0; font-size: 18px; line-height: 24px; color: #6f6f6f; font-weight: 300; text-transform: uppercase; }
section .padder, section > .body { padding: 20px 20px; }
/** TABLE */
@ -154,7 +154,7 @@ a.permission-link:hover { color: #333; text-decoration: none; }
.user-choice-row p.text-muted { font-size: 0.85em; }
.select2-container.user-choice .select2-choice { height: 34px; line-height: 34px;}
.btn-group-permissions > a { width: 80px; }
.btn-group-permissions > a { width: 120px; }
.link-item a.confirm-link:hover { color: #990000; }

View File

@ -4,8 +4,6 @@ import org.apache.wicket.Component;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.request.resource.JavaScriptResourceReference;
import org.apache.wicket.request.resource.ResourceReference;
import com.google.common.base.Preconditions;
@ -25,12 +23,10 @@ public class FoundationBaseBehavior extends Behavior {
component.add(instance);
}
private final static ResourceReference FOUNDATION_JS = new JavaScriptResourceReference(FoundationBaseBehavior.class, "res/js/foundation.js");
@Override
public void renderHead(final Component component, final IHeaderResponse response) {
super.renderHead(component, response);
response.render(JavaScriptHeaderItem.forReference(FOUNDATION_JS));
response.render(JavaScriptHeaderItem.forReference(FoundationResourceReference.get()));
}
}

View File

@ -0,0 +1,18 @@
package com.pmease.gitop.web.common.component.foundation;
import org.apache.wicket.Component;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
public class FoundationDropDownBehavior extends Behavior {
private static final long serialVersionUID = 1L;
@Override
public void renderHead(final Component component, final IHeaderResponse response) {
super.renderHead(component, response);
response.render(JavaScriptHeaderItem.forReference(FoundationDropDownResourceReference.get()));
}
}

View File

@ -0,0 +1,39 @@
package com.pmease.gitop.web.common.component.foundation;
import org.apache.wicket.markup.head.CssHeaderItem;
import org.apache.wicket.markup.head.HeaderItem;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
import org.apache.wicket.request.resource.CssResourceReference;
import org.apache.wicket.request.resource.JavaScriptResourceReference;
import org.apache.wicket.request.resource.ResourceReference;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
public class FoundationDropDownResourceReference extends JavaScriptResourceReference {
private static final long serialVersionUID = 1L;
private static final ResourceReference CSS = new CssResourceReference(
FoundationDropDownResourceReference.class, "res/css/dropdown.css");
public FoundationDropDownResourceReference() {
super(FoundationDropDownResourceReference.class, "res/js/foundation.dropdown.js");
}
@Override
public Iterable<? extends HeaderItem> getDependencies() {
return Iterables.concat(super.getDependencies(),
ImmutableList.of(
JavaScriptHeaderItem.forReference(FoundationResourceReference.get()),
CssHeaderItem.forReference(CSS),
OnDomReadyHeaderItem.forScript("$(document).foundation()")));
}
private static FoundationDropDownResourceReference instance =
new FoundationDropDownResourceReference();
public static FoundationDropDownResourceReference get() {
return instance;
}
}

View File

@ -0,0 +1,19 @@
package com.pmease.gitop.web.common.component.foundation;
import org.apache.wicket.request.resource.JavaScriptResourceReference;
public class FoundationResourceReference extends JavaScriptResourceReference {
private static final long serialVersionUID = 1L;
public FoundationResourceReference() {
super(FoundationResourceReference.class, "res/js/foundation.js");
}
private static final FoundationResourceReference instance =
new FoundationResourceReference();
public static FoundationResourceReference get() {
return instance;
}
}

View File

@ -0,0 +1,91 @@
/* FOUNDATIOIN DROPDOWN */
@media only screen and (max-width: 767px) {
.f-dropdown {
max-width: 100%;
left: 0; } }
/* Foundation Dropdowns */
.f-dropdown {
position: absolute;
top: -9999px;
list-style: none;
margin-left: 0;
width: 100%;
max-height: none;
height: auto;
background: white;
border: solid 1px #cccccc;
font-size: 16;
z-index: 99;
margin-top: 2px;
max-width: 200px; }
.f-dropdown > *:first-child {
margin-top: 0; }
.f-dropdown > *:last-child {
margin-bottom: 0; }
.f-dropdown:before {
content: "";
display: block;
width: 0;
height: 0;
border: inset 6px;
border-color: transparent transparent white transparent;
border-bottom-style: solid;
position: absolute;
top: -12px;
left: 10px;
z-index: 99; }
.f-dropdown:after {
content: "";
display: block;
width: 0;
height: 0;
border: inset 7px;
border-color: transparent transparent #cccccc transparent;
border-bottom-style: solid;
position: absolute;
top: -14px;
left: 9px;
z-index: 98; }
.f-dropdown.right:before {
left: auto;
right: 10px; }
.f-dropdown.right:after {
left: auto;
right: 9px; }
.f-dropdown li {
font-size: 0.875em;
cursor: pointer;
line-height: 1.125em;
margin: 0; }
.f-dropdown li:hover, .f-dropdown li:focus {
background: #eeeeee; }
.f-dropdown li a {
display: block;
padding: 0.3125em 0.625em;
color: #555555; }
.f-dropdown.content {
position: absolute;
top: -9999px;
list-style: none;
margin-left: 0;
padding: 1.25em;
width: 100%;
height: auto;
max-height: none;
background: white;
border: solid 1px #cccccc;
font-size: 16;
z-index: 99;
max-width: 200px; }
.f-dropdown.content > *:first-child {
margin-top: 0; }
.f-dropdown.content > *:last-child {
margin-bottom: 0; }
.f-dropdown.tiny {
max-width: 200px; }
.f-dropdown.small {
max-width: 300px; }
.f-dropdown.medium {
max-width: 500px; }
.f-dropdown.large {
max-width: 800px; }

View File

@ -16,10 +16,12 @@ import com.pmease.gitop.core.permission.ObjectPermission;
import com.pmease.gitop.web.component.link.UserAvatarLink;
import com.pmease.gitop.web.model.UserModel;
import com.pmease.gitop.web.page.AbstractLayoutPage;
import com.pmease.gitop.web.page.account.setting.members.AccountMembersPage;
import com.pmease.gitop.web.page.account.setting.password.AccountPasswordPage;
import com.pmease.gitop.web.page.account.setting.permission.AccountPermissionPage;
import com.pmease.gitop.web.page.account.setting.permissions.AccountPermissionsPage;
import com.pmease.gitop.web.page.account.setting.profile.AccountProfilePage;
import com.pmease.gitop.web.page.account.setting.repos.AccountReposPage;
import com.pmease.gitop.web.page.account.setting.teams.AccountTeamsPage;
@SuppressWarnings("serial")
public abstract class AccountSettingPage extends AbstractLayoutPage {
@ -28,7 +30,9 @@ public abstract class AccountSettingPage extends AbstractLayoutPage {
PROFILE(AccountProfilePage.class, "Profile"),
PASSWORD(AccountPasswordPage.class, "Change Password"),
REPOS(AccountReposPage.class, "Repositories"),
PERMISSION(AccountPermissionPage.class, "Permissions");
PERMISSIONS(AccountPermissionsPage.class, "Permissions"),
TEAMS(AccountTeamsPage.class, "Teams"),
MEMBERS(AccountMembersPage.class, "Members");
final Class<? extends WebPage> pageClass;
final String name;

View File

@ -0,0 +1,19 @@
<html xmlns:wicket>
<wicket:extend>
<section>
<div class="head">
<h2>Members</h2>
</div>
<div class="body">
<p>Manage your members/collaborators with teams. <a class="btn btn-xs btn-info btn-colorful-text" wicket:id="teamlink">Manage Teams</a></p>
<h3><span wicket:id="num"></span> <small>members total</small></h3>
<hr/>
<div wicket:id="members"></div>
</div>
</section>
<wicket:fragment wicket:id="memberactionfrag">
<a class="img-link remove-link" wicket:id="remove"><i class="icon-remove-sign"></i></a>
</wicket:fragment>
</wicket:extend>
</html>

View File

@ -0,0 +1,110 @@
package com.pmease.gitop.web.page.account.setting.members;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.hibernate.criterion.Restrictions;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.pmease.gitop.core.Gitop;
import com.pmease.gitop.core.manager.MembershipManager;
import com.pmease.gitop.core.model.Membership;
import com.pmease.gitop.core.model.Team;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.web.common.component.vex.AjaxConfirmLink;
import com.pmease.gitop.web.component.members.MemberListView;
import com.pmease.gitop.web.model.UserModel;
import com.pmease.gitop.web.page.account.setting.AccountSettingPage;
import com.pmease.gitop.web.page.account.setting.teams.AccountTeamsPage;
@SuppressWarnings("serial")
public class AccountMembersPage extends AccountSettingPage {
@Override
protected Category getSettingCategory() {
return Category.MEMBERS;
}
@Override
protected String getPageTitle() {
return "Members - " + getAccount();
}
@Override
protected void onPageInitialize() {
super.onPageInitialize();
final IModel<List<User>> model = new LoadableDetachableModel<List<User>>() {
@Override
protected List<User> load() {
User account = getAccount();
Collection<Team> teams = account.getTeams();
Set<User> users = Sets.newHashSet();
for (Team each : teams) {
for (Membership membership : each.getMemberships()) {
users.add(membership.getUser());
}
}
List<User> result = Lists.newArrayList(users);
Collections.sort(result);
return result;
}
};
add(new BookmarkablePageLink<Void>("teamlink", AccountTeamsPage.class));
add(new Label("num", new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
return String.valueOf(model.getObject().size());
}
}).setOutputMarkupId(true));
add(new MemberListView("members", model){
@Override
protected Component createActionsPanel(String id, IModel<User> model) {
Fragment frag = new Fragment(id, "memberactionfrag", AccountMembersPage.this);
User user = model.getObject();
final IModel<User> userModel = new UserModel(user);
frag.add(new AjaxConfirmLink<Void>("remove",
Model.of("<p>Are you sure you want to remove below user? "
+ "Remove this user will remove her/him from <b>all teams</b></p>"
+ "<p>" + user.getName() + " (" + user.getDisplayName() + ")</p>")) {
@Override
public void onClick(AjaxRequestTarget target) {
MembershipManager mm = Gitop.getInstance(MembershipManager.class);
User user = userModel.getObject();
List<Membership> memberships = mm.query(Restrictions.eq("user", user));
for (Membership each : memberships) {
mm.delete(each);
}
target.add(AccountMembersPage.this.get("members"));
target.add(AccountMembersPage.this.get("num"));
}
});
return frag;
}
}.setOutputMarkupId(true));
}
}

View File

@ -1,38 +0,0 @@
<html xmlns:wicket>
<wicket:panel>
<form class="form-inline" wicket:id="infoForm">
<div wicket:id="feedback" class="form-feedback"></div>
<p>Team Name:</p>
<input class="form-control focusable" type="text" placeholder="Team Name" wicket:id="name" />
<div class="btn-group btn-radio-group btn-group-permissions" wicket:id="permissionContainer">
<wicket:container wicket:id="permissions">
<a wicket:id="permission" class="btn btn-default">
<span class="icon-ok"></span>
<span wicket:id="name"></span>
</a>
</wicket:container>
</div>
<button type="submit" class="btn btn-primary btn-colorful-text" wicket:id="submit"><span wicket:id="label"></span></button>
</form>
<wicket:container wicket:id="span">
<hr />
<h4>Members</h4>
<form class="form-inline" wicket:id="membersForm">
<div class="form-feedback" wicket:id="feedback"></div>
<input wicket:id="userchoice" class="team-users-choice" type="hidden" style="width: 420px"></input>
<button type="submit" class="btn btn-success btn-colorful-text" wicket:id="submit"><i class="icon-plus"></i> Add</button>
</form>
<hr/>
<div>
<h4 class="text-muted members-summary"><b wicket:id="total"></b> members total</h4>
<div wicket:id="members"></div>
</div>
</wicket:container>
<wicket:fragment wicket:id="memberactionfrag">
<a class="img-link remove-link" wicket:id="remove"><i class="icon-remove-sign"></i></a>
</wicket:fragment>
</wicket:panel>
</html>

View File

@ -22,8 +22,8 @@
<hr/>
<h4>Teams</h4>
<p class="text-muted">Manage teams and grant the permissions so that all members in the team can have the permissions to access any repositories under this account.</p>
<wicket:container wicket:id="teams"></wicket:container>
<p>Manage teams and grant the permissions so that all members in the team can have the permissions to access any repositories under this account.</p>
<a class="btn btn-info" wicket:id="teamslink">Manage Teams</a>
</div>
</section>
</wicket:extend>

View File

@ -1,10 +1,11 @@
package com.pmease.gitop.web.page.account.setting.permission;
package com.pmease.gitop.web.page.account.setting.permissions;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.AbstractReadOnlyModel;
@ -14,11 +15,11 @@ import com.pmease.gitop.core.Gitop;
import com.pmease.gitop.core.manager.UserManager;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.core.permission.operation.GeneralOperation;
import com.pmease.gitop.web.model.UserModel;
import com.pmease.gitop.web.page.account.setting.AccountSettingPage;
import com.pmease.gitop.web.page.account.setting.teams.AccountTeamsPage;
@SuppressWarnings("serial")
public class AccountPermissionPage extends AccountSettingPage {
public class AccountPermissionsPage extends AccountSettingPage {
@Override
protected String getPageTitle() {
@ -27,7 +28,7 @@ public class AccountPermissionPage extends AccountSettingPage {
@Override
protected Category getSettingCategory() {
return Category.PERMISSION;
return Category.PERMISSIONS;
}
@Override
@ -74,7 +75,7 @@ public class AccountPermissionPage extends AccountSettingPage {
});
add(new TeamsPanel("teams", new UserModel(getAccount())));
add(new BookmarkablePageLink<Void>("teamslink", AccountTeamsPage.class));
}
class PermissionLink extends AjaxLink<Void> {
@ -104,7 +105,7 @@ public class AccountPermissionPage extends AccountSettingPage {
account.setDefaultAuthorizedOperation(permssion);
Gitop.getInstance(UserManager.class).save(account);
target.add(AccountPermissionPage.this.get("loggedInPermissions"));
target.add(AccountPermissionsPage.this.get("loggedInPermissions"));
}
}
}

View File

@ -9,7 +9,7 @@
<div wicket:id="feedback" class="form-feedback"></div>
<div wicket:id="displayName"></div>
<div wicket:id="email"></div>
<div class="submits text-left">
<div class="submits">
<button type="submit" wicket:id="submit" class="btn btn-primary">Update profile</button>
</div>
</form>

View File

@ -0,0 +1,12 @@
<html xmlns:wicket>
<wicket:extend>
<section>
<div class="head">
<h2>Teams</h2>
</div>
<div class="body">
<wicket:container wicket:id="teams"></wicket:container>
</div>
</section>
</wicket:extend>
</html>

View File

@ -0,0 +1,26 @@
package com.pmease.gitop.web.page.account.setting.teams;
import com.pmease.gitop.web.model.UserModel;
import com.pmease.gitop.web.page.account.setting.AccountSettingPage;
public class AccountTeamsPage extends AccountSettingPage {
private static final long serialVersionUID = 1L;
@Override
protected Category getSettingCategory() {
return Category.TEAMS;
}
@Override
protected String getPageTitle() {
return "Teams - " + getAccount();
}
@Override
protected void onPageInitialize() {
super.onPageInitialize();
add(new TeamsPanel("teams", new UserModel(getAccount())));
}
}

View File

@ -1,4 +1,4 @@
package com.pmease.gitop.web.page.account.setting.permission;
package com.pmease.gitop.web.page.account.setting.teams;
import com.pmease.gitop.core.model.Team;

View File

@ -2,7 +2,9 @@
<wicket:extend>
<section>
<div class="head">
<h2 wicket:id="head">Edit Team</h2>
<h2>
<wicket:container wicket:id="head">Edit Team</wicket:container>
</h2>
</div>
<div class="body">
<div wicket:id="editor"></div>

View File

@ -1,4 +1,4 @@
package com.pmease.gitop.web.page.account.setting.permission;
package com.pmease.gitop.web.page.account.setting.teams;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.AbstractReadOnlyModel;
@ -26,7 +26,7 @@ public class EditTeamPage extends AccountSettingPage {
@Override
protected Category getSettingCategory() {
return Category.PERMISSION;
return Category.TEAMS;
}
@Override

View File

@ -0,0 +1,41 @@
<html xmlns:wicket>
<wicket:panel>
<form class="form-inline form-md" wicket:id="infoForm">
<div wicket:id="feedback" class="form-feedback"></div>
<p><b>Team Name <span class="required">*</span></b></p>
<input class="form-control focusable" type="text" placeholder="Team Name" wicket:id="name" />
<button type="submit" class="btn btn-primary" wicket:id="submit"><span wicket:id="label"></span></button>
</form>
<hr />
<p><b>Default Permission:</b></p>
<div class="btn-group btn-radio-group btn-group-permissions" wicket:id="permissionContainer">
<wicket:container wicket:id="permissions">
<a wicket:id="permission" class="btn btn-default">
<span class="icon-ok"></span>
<span wicket:id="name"></span>
</a>
</wicket:container>
</div>
<wicket:container wicket:id="span">
<hr />
<h4>Members</h4>
<form class="form-inline" wicket:id="membersForm">
<div class="form-feedback" wicket:id="feedback"></div>
<input wicket:id="userchoice" class="team-users-choice" type="hidden" style="width: 420px"></input>
<button type="submit" class="btn btn-success btn-colorful-text" wicket:id="submit"><i class="icon-plus"></i> Add</button>
</form>
<hr/>
<div>
<h4 class="text-muted members-summary"><b wicket:id="total"></b> members total</h4>
<div wicket:id="members"></div>
</div>
</wicket:container>
<wicket:fragment wicket:id="memberactionfrag">
<a class="img-link remove-link" wicket:id="remove"><i class="icon-remove-sign"></i></a>
</wicket:fragment>
</wicket:panel>
</html>

View File

@ -1,4 +1,4 @@
package com.pmease.gitop.web.page.account.setting.permission;
package com.pmease.gitop.web.page.account.setting.teams;
import java.util.ArrayList;
import java.util.Collection;
@ -22,6 +22,7 @@ import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.util.WildcardListModel;
import org.apache.wicket.validation.IValidatable;
@ -73,10 +74,10 @@ public class TeamEditor extends Panel {
super.onInitialize();
this.name = getTeam().getName();
this.operation = getTeam().getAuthorizedOperation();
this.currentPermission = getTeam().getAuthorizedOperation();
add(createInfoForm());
add(createPermissionContainer());
membersContainer = new WebMarkupContainer("span") {
@Override
protected void onConfigure() {
@ -159,11 +160,10 @@ public class TeamEditor extends Panel {
}.setOutputMarkupId(true));
}
private GeneralOperation operation;
private GeneralOperation currentPermission;
private String name;
private Form<?> createInfoForm() {
operation = getTeam().getAuthorizedOperation();
Form<?> infoForm = new Form<Void>("infoForm");
add(infoForm);
infoForm.add(new FeedbackPanel("feedback"));
@ -181,26 +181,7 @@ public class TeamEditor extends Panel {
}
}
}).setRequired(true));
WebMarkupContainer permissionContainer = new WebMarkupContainer(
"permissionContainer");
permissionContainer.setOutputMarkupId(true);
infoForm.add(permissionContainer);
permissionContainer.add(new ListView<GeneralOperation>("permissions",
ImmutableList.<GeneralOperation> of(
GeneralOperation.READ,
GeneralOperation.WRITE,
GeneralOperation.ADMIN)) {
@Override
protected void populateItem(ListItem<GeneralOperation> item) {
GeneralOperation permission = item.getModelObject();
AjaxLink<?> link = new PermissionLink("permission", permission);
link.add(new Label("name", permission.toString()));
item.add(link);
}
});
AjaxButton btn = new AjaxButton("submit", infoForm) {
@Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
@ -215,7 +196,7 @@ public class TeamEditor extends Panel {
Preconditions.checkNotNull(owner, "owner");
team.setName(name);
team.setAuthorizedOperation(operation);
team.setAuthorizedOperation(currentPermission);
team.setOwner(owner);
Gitop.getInstance(TeamManager.class).save(team);
@ -241,19 +222,16 @@ public class TeamEditor extends Panel {
return infoForm;
}
class PermissionLink extends AjaxLink<Void> {
final GeneralOperation permission;
PermissionLink(String id, final GeneralOperation permission) {
super(id);
this.permission = permission;
class PermissionLink extends AjaxLink<GeneralOperation> {
PermissionLink(String id, IModel<GeneralOperation> permission) {
super(id, permission);
add(AttributeAppender.append("class",
new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
return Objects.equal(operation, permission) ?
return Objects.equal(currentPermission, getPermission()) ?
"active" : "";
}
}));
@ -261,12 +239,22 @@ public class TeamEditor extends Panel {
@Override
public void onClick(AjaxRequestTarget target) {
if (Objects.equal(operation, permission)) {
if (Objects.equal(currentPermission, getPermission())) {
return;
}
operation = permission;
target.add(TeamEditor.this.get("infoForm").get("permissionContainer"));
currentPermission = getPermission();
Team team = getTeam();
team.setAuthorizedOperation(currentPermission);
if (!team.isNew()) {
Gitop.getInstance(TeamManager.class).save(team);
}
target.add(TeamEditor.this.get("permissionContainer"));
}
GeneralOperation getPermission() {
return (GeneralOperation) getDefaultModelObject();
}
}
@ -320,6 +308,24 @@ public class TeamEditor extends Panel {
return form;
}
private Component createPermissionContainer() {
WebMarkupContainer permissionContainer = new WebMarkupContainer("permissionContainer");
permissionContainer.setOutputMarkupId(true);
permissionContainer.add(new ListView<GeneralOperation>("permissions",
ImmutableList.<GeneralOperation>copyOf(GeneralOperation.values())) {
@Override
protected void populateItem(ListItem<GeneralOperation> item) {
GeneralOperation permission = item.getModelObject();
AjaxLink<?> link = new PermissionLink("permission", Model.of(permission));
link.add(new Label("name", permission.toString()));
item.add(link);
}
});
return permissionContainer;
}
private void onMembersChanged(AjaxRequestTarget target) {
target.add(membersContainer.get("members"));
target.add(membersContainer.get("total"));

View File

@ -1,7 +1,7 @@
<html xmlns:wicket>
<wicket:panel>
<p>
<a class="btn btn-info" wicket:id="addTeam"><i class="icon-plus"></i> Create a team</a>
<a class="btn btn-info btn-colorful-text" wicket:id="addTeam"><i class="icon-plus"></i> Create a team</a>
</p>
<table class="table table-condensed table-hover" wicket:id="teams"></table>

View File

@ -1,4 +1,4 @@
package com.pmease.gitop.web.page.account.setting.permission;
package com.pmease.gitop.web.page.account.setting.teams;
import java.util.List;

View File

@ -21,6 +21,14 @@
<button class="btn btn-default" wicket:id="submit">Submit</button>
</form>
<h3>DropDown</h3>
<a href="#" data-dropdown="drop1" data-options="is_hover:true">Has Dropdown</a>
<ul id="drop1" class="f-dropdown" data-dropdown-content>
<li><a href="#">This is a link</a></li>
<li><a href="#">This is another</a></li>
<li><a href="#">Yet another</a></li>
</ul>
</div>
</wicket:extend>
</html>

View File

@ -1,6 +1,7 @@
package com.pmease.gitop.web.page.home;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.RadioGroup;
import org.apache.wicket.markup.html.list.ListItem;
@ -11,6 +12,7 @@ import org.apache.wicket.model.PropertyModel;
import com.google.common.collect.ImmutableList;
import com.pmease.gitop.web.common.component.dropzone.DropZoneBehavior;
import com.pmease.gitop.web.common.component.foundation.FoundationDropDownBehavior;
import com.pmease.gitop.web.common.component.messenger.Messenger;
import com.pmease.gitop.web.common.component.vex.AjaxConfirmButton;
import com.pmease.gitop.web.common.component.vex.VexLinkBehavior.VexIcon;
@ -37,6 +39,7 @@ public class HomePage extends AbstractLayoutPage {
super.onPageInitialize();
add(new DropZoneBehavior());
add(new FoundationDropDownBehavior());
Form<?> form = new Form<Void>("testForm");
add(form);
@ -80,6 +83,11 @@ public class HomePage extends AbstractLayoutPage {
});
}
@Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
}
VexIcon vexIcon = VexIcon.INFO;
boolean displayed = true;
}

View File

@ -95,7 +95,7 @@ public abstract class AbstractProjectSettingPage extends AbstractProjectPage {
break;
case PERMISSIONS:
pageClass = ProjectPermissionsPage.class;
pageClass = ProjectPermissionPage.class;
break;
default:

View File

@ -1,5 +1,27 @@
<html xmlns:wicket>
<wicket:extend>
<section>
<div class="head">
<h2>Basic Info</h2>
</div>
<div class="body">
<form class="form-md form-horizontal">
<div class="form-group">
<label class="control-label">Location</label>
<div class="field-controls">
<p class="message">/Users/zhenyu/data/gitop/abc.git</p>
</div>
</div>
<div class="form-group">
<label class="control-label">Size</label>
<div class="field-controls">
<p class="message">27M</p>
</div>
</div>
</form>
</div>
</section>
<section>
<div class="head">
<h2>Settings</h2>

View File

@ -0,0 +1,31 @@
<html xmlns:wicket>
<wicket:extend>
<section>
<div class="head"><h2>Project Permissions</h2></div>
<div class="body">
<h4>Anonymous Users</h4>
<p><a class="checkable-link" wicket:id="anonymouslink"><i class="icon-checkbox"></i> Anonymous users can browse and pull this repository.</a></p>
<hr />
<h4>Logged-in Users</h4>
<p>Logged-in users can access this project with permission:</p>
<div class="btn-group btn-group-justified btn-radio-group" wicket:id="loggedInPermissions">
<wicket:container wicket:id="permissions">
<a wicket:id="permission" class="btn">
<span class="icon-ok"></span>
<span wicket:id="name"></span>
</a>
</wicket:container>
</div>
<p></p>
<ul class="text-muted">
<li>Permission granted to logged-in users on account level is <span class="label label-info"><wicket:container wicket:id="userlevelpermission"></wicket:container></span></li>
</ul>
<hr/>
<h4>Teams</h4>
</div>
</section>
</wicket:extend>
</html>

View File

@ -0,0 +1,151 @@
package com.pmease.gitop.web.page.project.settings;
import java.util.List;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.AbstractLink;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.pmease.gitop.core.Gitop;
import com.pmease.gitop.core.manager.ProjectManager;
import com.pmease.gitop.core.model.Project;
import com.pmease.gitop.core.permission.operation.GeneralOperation;
@SuppressWarnings("serial")
public class ProjectPermissionPage extends AbstractProjectSettingPage {
public ProjectPermissionPage(PageParameters params) {
super(params);
}
@Override
protected Category getCategory() {
return Category.PERMISSIONS;
}
@Override
protected void onPageInitialize() {
super.onPageInitialize();
AbstractLink link = new AjaxLink<Void>("anonymouslink") {
@Override
public void onClick(AjaxRequestTarget target) {
Project project = getProject();
project.setPubliclyAccessible(!project.isPubliclyAccessible());
Gitop.getInstance(ProjectManager.class).save(project);
target.add(this);
}
@Override
protected void onConfigure() {
super.onConfigure();
Project project = getProject();
setEnabled(!project.getOwner().isPubliclyAccessible());
}
};
link.setOutputMarkupId(true);
link.add(AttributeAppender.append("class", new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
Project project = getProject();
if (project.isPubliclyAccessible() || project.getOwner().isPubliclyAccessible()) {
return "checked";
} else {
return "";
}
}
}));
add(link);
WebMarkupContainer loggedInPermissions = new WebMarkupContainer("loggedInPermissions");
add(loggedInPermissions);
loggedInPermissions.setOutputMarkupId(true);
add(new Label("userlevelpermission", new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
return getProject().getOwner().getDefaultAuthorizedOperation().name();
}
}));
IModel<List<GeneralOperation>> permissionsModel = new AbstractReadOnlyModel<List<GeneralOperation>>() {
@Override
public List<GeneralOperation> getObject() {
// Project project = getProject();
// List<GeneralOperation> operations = Lists.newArrayList();
// GeneralOperation accountLevel = project.getOwner().getDefaultAuthorizedOperation();
// for (GeneralOperation each : GeneralOperation.values()) {
// if (each.compareTo(accountLevel) >= 0 && !Objects.equal(each, GeneralOperation.ADMIN)) {
// operations.add(each);
// }
// }
//
// return operations;
return ImmutableList.<GeneralOperation>of(GeneralOperation.NO_ACCESS, GeneralOperation.READ, GeneralOperation.WRITE);
}
};
loggedInPermissions.add(new ListView<GeneralOperation>("permissions", permissionsModel) {
@Override
protected void populateItem(ListItem<GeneralOperation> item) {
AjaxLink<?> link = new PermissionLink("permission", item.getModelObject());
item.add(link);
link.add(new Label("name", item.getModelObject().toString()));
}
});
}
private GeneralOperation getLoggedInPermission() {
Project project = getProject();
GeneralOperation op = project.getOwner().getDefaultAuthorizedOperation();
GeneralOperation op2 = project.getDefaultAuthorizedOperation();
return op.compareTo(op2) > 0 ? op : op2;
}
class PermissionLink extends AjaxLink<Void> {
final GeneralOperation permission;
PermissionLink(String id, final GeneralOperation permission) {
super(id);
this.permission = permission;
add(AttributeAppender.append("class", new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
return Objects.equal(getLoggedInPermission(), permission) ?
"btn-default active" : "btn-default";
}
}));
}
@Override
public void onClick(AjaxRequestTarget target) {
Project project = getProject();
project.setDefaultAuthorizedOperation(permission);
Gitop.getInstance(ProjectManager.class).save(project);
target.add(ProjectPermissionPage.this.get("loggedInPermissions"));
}
}
}

View File

@ -1,17 +0,0 @@
package com.pmease.gitop.web.page.project.settings;
import org.apache.wicket.request.mapper.parameter.PageParameters;
@SuppressWarnings("serial")
public class ProjectPermissionsPage extends AbstractProjectSettingPage {
public ProjectPermissionsPage(PageParameters params) {
super(params);
}
@Override
protected Category getCategory() {
return Category.PERMISSIONS;
}
}