Add WebLink extension point for file history
Change-Id: Ib70f1beeb03dfbf7ebb0ccef0b6f46157b9fac3a
This commit is contained in:
parent
f707c8a98d
commit
21c8686867
@ -32,6 +32,7 @@ public class ProjectAccess {
|
||||
protected LabelTypes labelTypes;
|
||||
protected Map<String, String> capabilities;
|
||||
protected Map<AccountGroup.UUID, GroupInfo> groupInfo;
|
||||
protected List<WebLinkInfoCommon> fileHistoryLinks;
|
||||
|
||||
public ProjectAccess() {
|
||||
}
|
||||
@ -132,4 +133,12 @@ public class ProjectAccess {
|
||||
public void setGroupInfo(Map<AccountGroup.UUID, GroupInfo> m) {
|
||||
groupInfo = m;
|
||||
}
|
||||
|
||||
public void setFileHistoryLinks(List<WebLinkInfoCommon> links) {
|
||||
fileHistoryLinks = links;
|
||||
}
|
||||
|
||||
public List<WebLinkInfoCommon> getFileHistoryLinks() {
|
||||
return fileHistoryLinks;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
// Copyright (C) 2015 The Android Open Source Project
|
||||
//
|
||||
// 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.common.data;
|
||||
|
||||
public class WebLinkInfoCommon {
|
||||
public WebLinkInfoCommon() {}
|
||||
|
||||
public String name;
|
||||
public String imageUrl;
|
||||
public String url;
|
||||
public String target;
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2015 The Android Open Source Project
|
||||
//
|
||||
// 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.extensions.webui;
|
||||
|
||||
import com.google.gerrit.extensions.common.WebLinkInfo;
|
||||
|
||||
public interface FileHistoryWebLink extends WebLink {
|
||||
/**
|
||||
* {@link com.google.gerrit.extensions.common.WebLinkInfo}
|
||||
* describing a link from a file to an external service displaying
|
||||
* a log for that file.
|
||||
*
|
||||
* <p>In order for the web link to be visible
|
||||
* {@link com.google.gerrit.extensions.common.WebLinkInfo#url}
|
||||
* and {@link com.google.gerrit.extensions.common.WebLinkInfo#name}
|
||||
* must be set.<p>
|
||||
*
|
||||
* @param projectName Name of the project
|
||||
* @param revision Name of the revision (e.g. branch or commit ID)
|
||||
* @param fileName Name of the file
|
||||
* @return WebLinkInfo that links to a log for the file in external
|
||||
* service, null if there should be no link.
|
||||
*/
|
||||
WebLinkInfo getFileHistoryWebLink(String projectName, String revision, String fileName);
|
||||
}
|
@ -21,6 +21,7 @@ import com.google.gerrit.client.ui.Hyperlink;
|
||||
import com.google.gerrit.client.ui.ParentProjectBox;
|
||||
import com.google.gerrit.common.data.AccessSection;
|
||||
import com.google.gerrit.common.data.ProjectAccess;
|
||||
import com.google.gerrit.common.data.WebLinkInfoCommon;
|
||||
import com.google.gerrit.reviewdb.client.Branch;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.client.RefNames;
|
||||
@ -40,6 +41,7 @@ import com.google.gwt.user.client.ui.Anchor;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.HTMLPanel;
|
||||
import com.google.gwt.user.client.ui.Image;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -65,7 +67,7 @@ public class ProjectAccessEditor extends Composite implements
|
||||
DivElement history;
|
||||
|
||||
@UiField
|
||||
Anchor gitweb;
|
||||
FlowPanel webLinkPanel;
|
||||
|
||||
@UiField
|
||||
FlowPanel localContainer;
|
||||
@ -120,16 +122,7 @@ public class ProjectAccessEditor extends Composite implements
|
||||
} else {
|
||||
inheritsFrom.getStyle().setDisplay(Display.NONE);
|
||||
}
|
||||
|
||||
GitwebInfo c = Gerrit.info().gitweb();
|
||||
if (value.isConfigVisible() && c != null) {
|
||||
history.getStyle().setDisplay(Display.BLOCK);
|
||||
gitweb.setText(c.getLinkName());
|
||||
gitweb.setHref(c.toFileHistory(new Branch.NameKey(value.getProjectName(),
|
||||
RefNames.REFS_CONFIG), "project.config"));
|
||||
} else {
|
||||
history.getStyle().setDisplay(Display.NONE);
|
||||
}
|
||||
setUpWebLinks();
|
||||
|
||||
addSection.setVisible(editing && (!value.getOwnerOf().isEmpty() || value.canUpload()));
|
||||
}
|
||||
@ -162,6 +155,53 @@ public class ProjectAccessEditor extends Composite implements
|
||||
addSection.setVisible(editing);
|
||||
}
|
||||
|
||||
private void setUpWebLinks() {
|
||||
if (!value.isConfigVisible()) {
|
||||
history.getStyle().setDisplay(Display.NONE);
|
||||
} else {
|
||||
GitwebInfo c = Gerrit.info().gitweb();
|
||||
List<WebLinkInfoCommon> links = value.getFileHistoryLinks();
|
||||
if (c == null && links == null) {
|
||||
history.getStyle().setDisplay(Display.NONE);
|
||||
}
|
||||
if (c != null) {
|
||||
webLinkPanel.add(toAnchor(c.toFileHistory(new Branch.NameKey(value.getProjectName(),
|
||||
RefNames.REFS_CONFIG), "project.config"), c.getLinkName()));
|
||||
}
|
||||
|
||||
if (links != null) {
|
||||
for (WebLinkInfoCommon link : links) {
|
||||
webLinkPanel.add(toAnchor(link));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Anchor toAnchor(String href, String name) {
|
||||
Anchor a = new Anchor();
|
||||
a.setHref(href);
|
||||
a.setText(name);
|
||||
return a;
|
||||
}
|
||||
|
||||
private static Anchor toAnchor(WebLinkInfoCommon info) {
|
||||
Anchor a = new Anchor();
|
||||
a.setHref(info.url);
|
||||
if (info.target != null && !info.target.isEmpty()) {
|
||||
a.setTarget(info.target);
|
||||
}
|
||||
if (info.imageUrl != null && !info.imageUrl.isEmpty()) {
|
||||
Image img = new Image();
|
||||
img.setAltText(info.name);
|
||||
img.setUrl(info.imageUrl);
|
||||
img.setTitle(info.name);
|
||||
a.getElement().appendChild(img.getElement());
|
||||
} else {
|
||||
a.setText("(" + info.name + ")");
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
private class Source extends EditorSource<AccessSectionEditor> {
|
||||
private final FlowPanel container;
|
||||
|
||||
|
@ -39,9 +39,12 @@ limitations under the License.
|
||||
.historyTitle {
|
||||
font-weight: bold;
|
||||
}
|
||||
.gitwebLink {
|
||||
.webLinkPanel a {
|
||||
display: inline;
|
||||
}
|
||||
.webLinkPanel>a {
|
||||
margin-left:2px;
|
||||
}
|
||||
|
||||
.addContainer {
|
||||
margin-top: 5px;
|
||||
@ -62,7 +65,9 @@ limitations under the License.
|
||||
</div>
|
||||
<div ui:field='history' class='{style.history}'>
|
||||
<span class='{style.historyTitle}'><ui:msg>History:</ui:msg></span>
|
||||
<g:Anchor ui:field='gitweb' styleName='{style.gitwebLink}'></g:Anchor>
|
||||
<td>
|
||||
<g:FlowPanel ui:field="webLinkPanel" styleName='{style.webLinkPanel}'/>
|
||||
</td>
|
||||
</div>
|
||||
|
||||
<g:FlowPanel ui:field='localContainer'/>
|
||||
|
@ -15,6 +15,7 @@
|
||||
package com.google.gerrit.httpd.rpc.project;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gerrit.common.data.AccessSection;
|
||||
import com.google.gerrit.common.data.GroupDescription;
|
||||
@ -23,11 +24,13 @@ import com.google.gerrit.common.data.Permission;
|
||||
import com.google.gerrit.common.data.PermissionRule;
|
||||
import com.google.gerrit.common.data.ProjectAccess;
|
||||
import com.google.gerrit.common.data.RefConfigSection;
|
||||
import com.google.gerrit.common.data.WebLinkInfoCommon;
|
||||
import com.google.gerrit.common.errors.NoSuchGroupException;
|
||||
import com.google.gerrit.httpd.rpc.Handler;
|
||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.client.RefNames;
|
||||
import com.google.gerrit.server.WebLinks;
|
||||
import com.google.gerrit.server.account.GroupBackend;
|
||||
import com.google.gerrit.server.account.GroupControl;
|
||||
import com.google.gerrit.server.config.AllProjectsName;
|
||||
@ -64,6 +67,7 @@ class ProjectAccessFactory extends Handler<ProjectAccess> {
|
||||
|
||||
private final Project.NameKey projectName;
|
||||
private ProjectControl pc;
|
||||
private WebLinks webLinks;
|
||||
|
||||
@Inject
|
||||
ProjectAccessFactory(final GroupBackend groupBackend,
|
||||
@ -72,6 +76,7 @@ class ProjectAccessFactory extends Handler<ProjectAccess> {
|
||||
final GroupControl.Factory groupControlFactory,
|
||||
final MetaDataUpdate.Server metaDataUpdateFactory,
|
||||
final AllProjectsName allProjectsName,
|
||||
final WebLinks webLinks,
|
||||
|
||||
@Assisted final Project.NameKey name) {
|
||||
this.groupBackend = groupBackend;
|
||||
@ -80,6 +85,7 @@ class ProjectAccessFactory extends Handler<ProjectAccess> {
|
||||
this.groupControlFactory = groupControlFactory;
|
||||
this.metaDataUpdateFactory = metaDataUpdateFactory;
|
||||
this.allProjectsName = allProjectsName;
|
||||
this.webLinks = webLinks;
|
||||
|
||||
this.projectName = name;
|
||||
}
|
||||
@ -209,9 +215,17 @@ class ProjectAccessFactory extends Handler<ProjectAccess> {
|
||||
detail.setConfigVisible(pc.isOwner() || metaConfigControl.isVisible());
|
||||
detail.setGroupInfo(buildGroupInfo(local));
|
||||
detail.setLabelTypes(pc.getLabelTypes());
|
||||
detail.setFileHistoryLinks(getConfigFileLogLinks(projectName.get()));
|
||||
return detail;
|
||||
}
|
||||
|
||||
private List<WebLinkInfoCommon> getConfigFileLogLinks(String projectName) {
|
||||
FluentIterable<WebLinkInfoCommon> links =
|
||||
webLinks.getFileHistoryLinksCommon(projectName, RefNames.REFS_CONFIG,
|
||||
ProjectConfig.PROJECT_CONFIG);
|
||||
return links.isEmpty() ? null : links.toList();
|
||||
}
|
||||
|
||||
private Map<AccountGroup.UUID, GroupInfo> buildGroupInfo(List<AccessSection> local) {
|
||||
Map<AccountGroup.UUID, GroupInfo> infos = new HashMap<>();
|
||||
for (AccessSection section : local) {
|
||||
|
@ -18,11 +18,13 @@ import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.gerrit.common.data.WebLinkInfoCommon;
|
||||
import com.google.gerrit.extensions.common.DiffWebLinkInfo;
|
||||
import com.google.gerrit.extensions.common.WebLinkInfo;
|
||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||
import com.google.gerrit.extensions.webui.BranchWebLink;
|
||||
import com.google.gerrit.extensions.webui.DiffWebLink;
|
||||
import com.google.gerrit.extensions.webui.FileHistoryWebLink;
|
||||
import com.google.gerrit.extensions.webui.FileWebLink;
|
||||
import com.google.gerrit.extensions.webui.PatchSetWebLink;
|
||||
import com.google.gerrit.extensions.webui.ProjectWebLink;
|
||||
@ -53,9 +55,26 @@ public class WebLinks {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
private static final Predicate<WebLinkInfoCommon> INVALID_WEBLINK_COMMON =
|
||||
new Predicate<WebLinkInfoCommon>() {
|
||||
|
||||
@Override
|
||||
public boolean apply(WebLinkInfoCommon link) {
|
||||
if (link == null) {
|
||||
return false;
|
||||
} else if (Strings.isNullOrEmpty(link.name)
|
||||
|| Strings.isNullOrEmpty(link.url)) {
|
||||
log.warn(String.format("%s is missing name and/or url", link
|
||||
.getClass().getName()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private final DynamicSet<PatchSetWebLink> patchSetLinks;
|
||||
private final DynamicSet<FileWebLink> fileLinks;
|
||||
private final DynamicSet<FileHistoryWebLink> fileHistoryLinks;
|
||||
private final DynamicSet<DiffWebLink> diffLinks;
|
||||
private final DynamicSet<ProjectWebLink> projectLinks;
|
||||
private final DynamicSet<BranchWebLink> branchLinks;
|
||||
@ -63,11 +82,14 @@ public class WebLinks {
|
||||
@Inject
|
||||
public WebLinks(DynamicSet<PatchSetWebLink> patchSetLinks,
|
||||
DynamicSet<FileWebLink> fileLinks,
|
||||
DynamicSet<FileHistoryWebLink> fileLogLinks,
|
||||
DynamicSet<DiffWebLink> diffLinks,
|
||||
DynamicSet<ProjectWebLink> projectLinks,
|
||||
DynamicSet<BranchWebLink> branchLinks) {
|
||||
DynamicSet<BranchWebLink> branchLinks
|
||||
) {
|
||||
this.patchSetLinks = patchSetLinks;
|
||||
this.fileLinks = fileLinks;
|
||||
this.fileHistoryLinks = fileLogLinks;
|
||||
this.diffLinks = diffLinks;
|
||||
this.projectLinks = projectLinks;
|
||||
this.branchLinks = branchLinks;
|
||||
@ -108,6 +130,46 @@ public class WebLinks {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param project Project name.
|
||||
* @param revision SHA1 of revision.
|
||||
* @param file File name.
|
||||
* @return Links for file history
|
||||
*/
|
||||
public FluentIterable<WebLinkInfo> getFileHistoryLinks(final String project,
|
||||
final String revision, final String file) {
|
||||
return filterLinks(fileHistoryLinks, new Function<WebLink, WebLinkInfo>() {
|
||||
|
||||
@Override
|
||||
public WebLinkInfo apply(WebLink webLink) {
|
||||
return ((FileHistoryWebLink) webLink).getFileHistoryWebLink(project,
|
||||
revision, file);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public FluentIterable<WebLinkInfoCommon> getFileHistoryLinksCommon(
|
||||
final String project, final String revision, final String file) {
|
||||
return FluentIterable
|
||||
.from(fileHistoryLinks)
|
||||
.transform(new Function<WebLink, WebLinkInfoCommon>() {
|
||||
@Override
|
||||
public WebLinkInfoCommon apply(WebLink webLink) {
|
||||
WebLinkInfo info =
|
||||
((FileHistoryWebLink) webLink).getFileHistoryWebLink(project,
|
||||
revision, file);
|
||||
WebLinkInfoCommon commonInfo = new WebLinkInfoCommon();
|
||||
commonInfo.name = info.name;
|
||||
commonInfo.imageUrl = info.imageUrl;
|
||||
commonInfo.url = info.url;
|
||||
commonInfo.target = info.target;
|
||||
return commonInfo;
|
||||
}
|
||||
})
|
||||
.filter(INVALID_WEBLINK_COMMON);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param project Project name.
|
||||
|
@ -37,6 +37,7 @@ import com.google.gerrit.extensions.registration.DynamicSet;
|
||||
import com.google.gerrit.extensions.systemstatus.MessageOfTheDay;
|
||||
import com.google.gerrit.extensions.webui.BranchWebLink;
|
||||
import com.google.gerrit.extensions.webui.DiffWebLink;
|
||||
import com.google.gerrit.extensions.webui.FileHistoryWebLink;
|
||||
import com.google.gerrit.extensions.webui.FileWebLink;
|
||||
import com.google.gerrit.extensions.webui.PatchSetWebLink;
|
||||
import com.google.gerrit.extensions.webui.ProjectWebLink;
|
||||
@ -285,6 +286,7 @@ public class GerritGlobalModule extends FactoryModule {
|
||||
DynamicMap.mapOf(binder(), ProjectConfigEntry.class);
|
||||
DynamicSet.setOf(binder(), PatchSetWebLink.class);
|
||||
DynamicSet.setOf(binder(), FileWebLink.class);
|
||||
DynamicSet.setOf(binder(), FileHistoryWebLink.class);
|
||||
DynamicSet.setOf(binder(), DiffWebLink.class);
|
||||
DynamicSet.setOf(binder(), ProjectWebLink.class);
|
||||
DynamicSet.setOf(binder(), BranchWebLink.class);
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit ac84984d90e09be358754e707a192ddce2ea6d63
|
||||
Subproject commit 730613516a733fa33f684cbe03fe22ecf811216e
|
Loading…
Reference in New Issue
Block a user