Add a project admin screen to show the projects you own
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
@@ -30,6 +30,8 @@
|
||||
class='com.google.gerrit.server.GroupAdminServiceSrv'/>
|
||||
<servlet path='/rpc/PatchDetailService'
|
||||
class='com.google.gerrit.server.PatchDetailServiceSrv'/>
|
||||
<servlet path='/rpc/ProjectAdminService'
|
||||
class='com.google.gerrit.server.ProjectAdminServiceSrv'/>
|
||||
<servlet path='/rpc/SuggestService'
|
||||
class='com.google.gerrit.server.SuggestServiceSrv'/>
|
||||
<servlet path='/rpc/SystemInfoService'
|
||||
|
@@ -18,6 +18,7 @@ import com.google.gerrit.client.account.AccountSettings;
|
||||
import com.google.gerrit.client.account.NewAgreementScreen;
|
||||
import com.google.gerrit.client.admin.AccountGroupScreen;
|
||||
import com.google.gerrit.client.admin.GroupListScreen;
|
||||
import com.google.gerrit.client.admin.ProjectListScreen;
|
||||
import com.google.gerrit.client.changes.AccountDashboardScreen;
|
||||
import com.google.gerrit.client.changes.ChangeScreen;
|
||||
import com.google.gerrit.client.changes.MineStarredScreen;
|
||||
@@ -29,6 +30,7 @@ import com.google.gerrit.client.reviewdb.Account;
|
||||
import com.google.gerrit.client.reviewdb.AccountGroup;
|
||||
import com.google.gerrit.client.reviewdb.Change;
|
||||
import com.google.gerrit.client.reviewdb.Patch;
|
||||
import com.google.gerrit.client.reviewdb.Project;
|
||||
import com.google.gerrit.client.rpc.RpcUtil;
|
||||
import com.google.gerrit.client.ui.Screen;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
@@ -86,6 +88,10 @@ public class Link implements HistoryListener {
|
||||
return "admin,group," + id.toString();
|
||||
}
|
||||
|
||||
public static String toProjectAdmin(final Project.Id id) {
|
||||
return "admin,project," + id.toString();
|
||||
}
|
||||
|
||||
public void onHistoryChanged(final String token) {
|
||||
Screen s;
|
||||
try {
|
||||
@@ -150,6 +156,10 @@ public class Link implements HistoryListener {
|
||||
if (ADMIN_GROUPS.equals(token)) {
|
||||
return new GroupListScreen();
|
||||
}
|
||||
|
||||
if (ADMIN_PROJECTS.equals(token)) {
|
||||
return new ProjectListScreen();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@@ -37,4 +37,5 @@ public interface AdminConstants extends Constants {
|
||||
String columnGroupDescription();
|
||||
|
||||
String groupListTitle();
|
||||
String projectListTitle();
|
||||
}
|
||||
|
@@ -18,3 +18,4 @@ columnGroupName = Name
|
||||
columnGroupDescription = Description
|
||||
|
||||
groupListTitle = Groups
|
||||
projectListTitle = Projects
|
||||
|
@@ -0,0 +1,39 @@
|
||||
// Copyright 2008 Google Inc.
|
||||
//
|
||||
// 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.google.gerrit.client.admin;
|
||||
|
||||
import com.google.gerrit.client.reviewdb.Project;
|
||||
import com.google.gerrit.client.rpc.SignInRequired;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwtjsonrpc.client.RemoteJsonService;
|
||||
import com.google.gwtjsonrpc.client.VoidResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ProjectAdminService extends RemoteJsonService {
|
||||
@SignInRequired
|
||||
void ownedProjects(AsyncCallback<List<Project>> callback);
|
||||
|
||||
@SignInRequired
|
||||
void projectDetail(Project.Id projectId, AsyncCallback<ProjectDetail> callback);
|
||||
|
||||
@SignInRequired
|
||||
void changeProjectDescription(Project.Id projectId, String description,
|
||||
AsyncCallback<VoidResult> callback);
|
||||
|
||||
@SignInRequired
|
||||
void changeProjectOwner(Project.Id projectId, String newOwnerName,
|
||||
AsyncCallback<VoidResult> callback);
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
// Copyright 2008 Google Inc.
|
||||
//
|
||||
// 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.google.gerrit.client.admin;
|
||||
|
||||
import com.google.gerrit.client.reviewdb.AccountGroup;
|
||||
import com.google.gerrit.client.reviewdb.Project;
|
||||
import com.google.gerrit.client.reviewdb.ReviewDb;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
|
||||
public class ProjectDetail {
|
||||
protected Project project;
|
||||
protected AccountGroup ownerGroup;
|
||||
|
||||
public ProjectDetail() {
|
||||
}
|
||||
|
||||
public void load(final ReviewDb db, final Project g) throws OrmException {
|
||||
project = g;
|
||||
ownerGroup = db.accountGroups().get(project.getOwnerGroupId());
|
||||
}
|
||||
}
|
@@ -0,0 +1,122 @@
|
||||
// Copyright 2008 Google Inc.
|
||||
//
|
||||
// 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.google.gerrit.client.admin;
|
||||
|
||||
import com.google.gerrit.client.Link;
|
||||
import com.google.gerrit.client.reviewdb.Project;
|
||||
import com.google.gerrit.client.rpc.GerritCallback;
|
||||
import com.google.gerrit.client.ui.AccountScreen;
|
||||
import com.google.gerrit.client.ui.FancyFlexTable;
|
||||
import com.google.gwt.user.client.History;
|
||||
import com.google.gwt.user.client.ui.Hyperlink;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.SourcesTableEvents;
|
||||
import com.google.gwt.user.client.ui.TableListener;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ProjectListScreen extends AccountScreen {
|
||||
private ProjectTable projects;
|
||||
|
||||
public ProjectListScreen() {
|
||||
super(Util.C.projectListTitle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getScreenCacheToken() {
|
||||
return getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
if (projects == null) {
|
||||
initUI();
|
||||
}
|
||||
|
||||
Util.PROJECT_SVC.ownedProjects(new GerritCallback<List<Project>>() {
|
||||
public void onSuccess(final List<Project> result) {
|
||||
if (isAttached()) {
|
||||
projects.display(result);
|
||||
projects.finishDisplay(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initUI() {
|
||||
projects = new ProjectTable();
|
||||
projects.setSavePointerId(Link.ADMIN_PROJECTS);
|
||||
add(projects);
|
||||
|
||||
final VerticalPanel fp = new VerticalPanel();
|
||||
fp.setStyleName("gerrit-AddSshKeyPanel");
|
||||
final Label hdr = new Label(Util.C.headingCreateGroup());
|
||||
hdr.setStyleName("gerrit-SmallHeading");
|
||||
fp.add(hdr);
|
||||
}
|
||||
|
||||
private class ProjectTable extends FancyFlexTable<Project> {
|
||||
ProjectTable() {
|
||||
table.setText(0, 1, Util.C.columnGroupName());
|
||||
table.setText(0, 2, Util.C.columnGroupDescription());
|
||||
table.addTableListener(new TableListener() {
|
||||
public void onCellClicked(SourcesTableEvents sender, int row, int cell) {
|
||||
if (cell != 1 && getRowItem(row) != null) {
|
||||
movePointerTo(row);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final FlexCellFormatter fmt = table.getFlexCellFormatter();
|
||||
fmt.addStyleName(0, 1, S_DATA_HEADER);
|
||||
fmt.addStyleName(0, 2, S_DATA_HEADER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getRowItemKey(final Project item) {
|
||||
return item.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onOpenItem(final Project item) {
|
||||
History.newItem(Link.toProjectAdmin(item.getId()));
|
||||
}
|
||||
|
||||
void display(final List<Project> result) {
|
||||
while (1 < table.getRowCount())
|
||||
table.removeRow(table.getRowCount() - 1);
|
||||
|
||||
for (final Project k : result) {
|
||||
final int row = table.getRowCount();
|
||||
table.insertRow(row);
|
||||
populate(row, k);
|
||||
}
|
||||
}
|
||||
|
||||
void populate(final int row, final Project k) {
|
||||
table.setWidget(row, 1, new Hyperlink(k.getName(), Link.toProjectAdmin(k
|
||||
.getId())));
|
||||
table.setText(row, 2, k.getDescription());
|
||||
|
||||
final FlexCellFormatter fmt = table.getFlexCellFormatter();
|
||||
fmt.addStyleName(row, 1, S_DATA_CELL);
|
||||
fmt.addStyleName(row, 2, S_DATA_CELL);
|
||||
|
||||
setRowItem(row, k);
|
||||
}
|
||||
}
|
||||
}
|
@@ -21,9 +21,13 @@ public class Util {
|
||||
public static final AdminConstants C = GWT.create(AdminConstants.class);
|
||||
public static final AdminMessages M = GWT.create(AdminMessages.class);
|
||||
public static final GroupAdminService GROUP_SVC;
|
||||
public static final ProjectAdminService PROJECT_SVC;
|
||||
|
||||
static {
|
||||
GROUP_SVC = GWT.create(GroupAdminService.class);
|
||||
JsonUtil.bind(GROUP_SVC, "rpc/GroupAdminService");
|
||||
|
||||
PROJECT_SVC = GWT.create(ProjectAdminService.class);
|
||||
JsonUtil.bind(PROJECT_SVC, "rpc/ProjectAdminService");
|
||||
}
|
||||
}
|
||||
|
@@ -31,6 +31,9 @@ public interface ProjectAccess extends Access<Project, Project.NameKey> {
|
||||
@Query("ORDER BY name")
|
||||
ResultSet<Project> all() throws OrmException;
|
||||
|
||||
@Query("WHERE ownerGroupId = ?")
|
||||
ResultSet<Project> ownedByGroup(AccountGroup.Id groupId) throws OrmException;
|
||||
|
||||
@Query("WHERE name.name >= ? AND name.name <= ? ORDER BY name LIMIT ?")
|
||||
ResultSet<Project> suggestByName(String nameA, String nameB, int limit)
|
||||
throws OrmException;
|
||||
|
@@ -0,0 +1,151 @@
|
||||
// Copyright 2008 Google Inc.
|
||||
//
|
||||
// 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.google.gerrit.server;
|
||||
|
||||
import com.google.gerrit.client.admin.ProjectAdminService;
|
||||
import com.google.gerrit.client.admin.ProjectDetail;
|
||||
import com.google.gerrit.client.reviewdb.AccountGroup;
|
||||
import com.google.gerrit.client.reviewdb.AccountGroupMember;
|
||||
import com.google.gerrit.client.reviewdb.Project;
|
||||
import com.google.gerrit.client.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.client.rpc.BaseServiceImplementation;
|
||||
import com.google.gerrit.client.rpc.NoSuchEntityException;
|
||||
import com.google.gerrit.client.rpc.RpcUtil;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwtjsonrpc.client.VoidResult;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class ProjectAdminServiceImpl extends BaseServiceImplementation
|
||||
implements ProjectAdminService {
|
||||
private final AccountGroup.Id adminId;
|
||||
|
||||
public ProjectAdminServiceImpl(final GerritServer server) {
|
||||
super(server.getDatabase());
|
||||
adminId = server.getAdminGroupId();
|
||||
}
|
||||
|
||||
public void ownedProjects(final AsyncCallback<List<Project>> callback) {
|
||||
run(callback, new Action<List<Project>>() {
|
||||
public List<Project> run(ReviewDb db) throws OrmException {
|
||||
final List<Project> result;
|
||||
if (amAdmin(db)) {
|
||||
result = db.projects().all().toList();
|
||||
} else {
|
||||
result = myOwnedProjects(db);
|
||||
Collections.sort(result, new Comparator<Project>() {
|
||||
public int compare(final Project a, final Project b) {
|
||||
return a.getName().compareTo(b.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void projectDetail(final Project.Id projectId,
|
||||
final AsyncCallback<ProjectDetail> callback) {
|
||||
run(callback, new Action<ProjectDetail>() {
|
||||
public ProjectDetail run(ReviewDb db) throws OrmException, Failure {
|
||||
assertAmProjectOwner(db, projectId);
|
||||
final Project proj = db.projects().get(projectId);
|
||||
if (proj == null) {
|
||||
throw new Failure(new NoSuchEntityException());
|
||||
}
|
||||
|
||||
final ProjectDetail d = new ProjectDetail();
|
||||
d.load(db, proj);
|
||||
return d;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void changeProjectDescription(final Project.Id projectId,
|
||||
final String description, final AsyncCallback<VoidResult> callback) {
|
||||
run(callback, new Action<VoidResult>() {
|
||||
public VoidResult run(final ReviewDb db) throws OrmException, Failure {
|
||||
assertAmProjectOwner(db, projectId);
|
||||
final Project proj = db.projects().get(projectId);
|
||||
if (proj == null) {
|
||||
throw new Failure(new NoSuchEntityException());
|
||||
}
|
||||
proj.setDescription(description);
|
||||
db.projects().update(Collections.singleton(proj));
|
||||
return VoidResult.INSTANCE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void changeProjectOwner(final Project.Id projectId,
|
||||
final String newOwnerName, final AsyncCallback<VoidResult> callback) {
|
||||
run(callback, new Action<VoidResult>() {
|
||||
public VoidResult run(final ReviewDb db) throws OrmException, Failure {
|
||||
assertAmProjectOwner(db, projectId);
|
||||
final Project project = db.projects().get(projectId);
|
||||
if (project == null) {
|
||||
throw new Failure(new NoSuchEntityException());
|
||||
}
|
||||
|
||||
final AccountGroup owner =
|
||||
db.accountGroups().get(new AccountGroup.NameKey(newOwnerName));
|
||||
if (owner == null) {
|
||||
throw new Failure(new NoSuchEntityException());
|
||||
}
|
||||
|
||||
project.setOwnerGroupId(owner.getId());
|
||||
db.projects().update(Collections.singleton(project));
|
||||
return VoidResult.INSTANCE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean amInGroup(final ReviewDb db,
|
||||
final AccountGroup.Id groupId) throws OrmException {
|
||||
return db.accountGroupMembers().get(
|
||||
new AccountGroupMember.Key(RpcUtil.getAccountId(), groupId)) != null;
|
||||
}
|
||||
|
||||
private boolean amAdmin(final ReviewDb db) throws OrmException {
|
||||
return adminId != null && amInGroup(db, adminId);
|
||||
}
|
||||
|
||||
private void assertAmProjectOwner(final ReviewDb db,
|
||||
final Project.Id projectId) throws OrmException, Failure {
|
||||
final Project project = db.projects().get(projectId);
|
||||
if (project == null) {
|
||||
throw new Failure(new NoSuchEntityException());
|
||||
}
|
||||
if (!amInGroup(db, project.getOwnerGroupId()) && !amAdmin(db)) {
|
||||
throw new Failure(new NoSuchEntityException());
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Project> myOwnedProjects(final ReviewDb db)
|
||||
throws OrmException {
|
||||
final List<Project> own = new ArrayList<Project>();
|
||||
for (final AccountGroupMember m : db.accountGroupMembers().byAccount(
|
||||
RpcUtil.getAccountId()).toList()) {
|
||||
for (final Project g : db.projects().ownedByGroup(m.getAccountGroupId())) {
|
||||
own.add(g);
|
||||
}
|
||||
}
|
||||
return own;
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
// Copyright 2008 Google Inc.
|
||||
//
|
||||
// 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.google.gerrit.server;
|
||||
|
||||
|
||||
/** Publishes {@link ProjectAdminServiceImpl} over JSON. */
|
||||
public class ProjectAdminServiceSrv extends GerritJsonServlet {
|
||||
@Override
|
||||
protected Object createServiceHandle() throws Exception {
|
||||
return new ProjectAdminServiceImpl(GerritServer.getInstance());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user