未验证 提交 6de7e5fc 编写于 作者: T Tim Jacomb 提交者: GitHub

Merge pull request #4546 from daniel-beck/new-manage-layout

Manage Jenkins with flow layout and categories
......@@ -46,4 +46,10 @@ public class AboutJenkins extends ManagementLink {
public Permission getRequiredPermission() {
return Jenkins.SYSTEM_READ;
}
@Nonnull
@Override
public Category getCategory() {
return Category.STATUS;
}
}
......@@ -440,6 +440,12 @@ public class OldDataMonitor extends AdministrativeMonitor {
@Extension @Symbol("oldData")
public static class ManagementLinkImpl extends ManagementLink {
@Nonnull
@Override
public Category getCategory() {
return Category.TROUBLESHOOTING;
}
@Override
public String getIconFileName() {
return "document.png";
......
......@@ -53,6 +53,7 @@ import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.types.FileSet;
import org.kohsuke.stapler.interceptor.RequirePOST;
import javax.annotation.Nonnull;
import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
......@@ -100,6 +101,13 @@ public class WindowsInstallerLink extends ManagementLink {
return Messages.WindowsInstallerLink_Description();
}
@Nonnull
@Override
public Category getCategory() {
return Category.CONFIGURATION;
}
/**
* Is the installation successful?
*/
......
......@@ -31,6 +31,12 @@ import hudson.security.Permission;
import jenkins.model.Jenkins;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jvnet.localizer.Localizable;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.interceptor.RequirePOST;
import javax.annotation.CheckForNull;
......@@ -131,4 +137,58 @@ public abstract class ManagementLink implements ExtensionPoint, Action {
public boolean getRequiresPOST() {
return false;
}
/**
* Name of the category for this management link. Exists so that plugins with core dependency pre-dating the version
* when this was introduced can define a category. Plugins with newer core dependency override {@link #getCategory()} instead.
*
* @return name of the desired category, one of the enum values of {@link Category}, e.g. {@code STATUS}.
* @since TODO
*/
@Restricted(NoExternalUse.class) // TODO I don't think this works
protected @Nonnull String getCategoryName() {
return "UNCATEGORIZED";
}
/**
* Category for management link, uses {@code String} so it can be done with core dependency pre-dating the version this feature was added.
*
* @return An enum value of {@link Category}.
* @since TODO
*/
public @Nonnull Category getCategory() {
try {
return Category.valueOf(getCategoryName());
} catch (RuntimeException e) {
LOGGER.log(Level.WARNING, "invalid category {0} for class {1}", new Object[]{getCategoryName() , this.getClass().getName()});
return Category.UNCATEGORIZED;
}
}
/**
* Categories supported by this version of core.
*
* @since TODO
*/
public enum Category {
CONFIGURATION(Messages._ManagementLink_Category_CONFIGURATION()),
SECURITY(Messages._ManagementLink_Category_SECURITY()),
STATUS(Messages._ManagementLink_Category_STATUS()),
TROUBLESHOOTING(Messages._ManagementLink_Category_TROUBLESHOOTING()),
TOOLS(Messages._ManagementLink_Category_TOOLS()),
MISC(Messages._ManagementLink_Category_MISC()),
UNCATEGORIZED(Messages._ManagementLink_Category_UNCATEGORIZED());
private Localizable label;
Category(Localizable label) {
this.label = label;
}
public @Nonnull String getLabel() {
return label.toString();
}
}
private static final Logger LOGGER = Logger.getLogger(ManagementLink.class.getName());
}
......@@ -41,6 +41,7 @@ import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import javax.servlet.ServletException;
import jenkins.model.GlobalConfigurationCategory;
......@@ -93,6 +94,12 @@ public class GlobalSecurityConfiguration extends ManagementLink implements Descr
return Jenkins.get().isDisableRememberMe();
}
@Nonnull
@Override
public Category getCategory() {
return Category.SECURITY;
}
@POST
public synchronized void doConfigure(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException {
// for compatibility reasons, the actual value is stored in Jenkins
......
......@@ -771,6 +771,12 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
public String getDescription() {
return Messages.HudsonPrivateSecurityRealm_ManageUserLinks_Description();
}
@Nonnull
@Override
public Category getCategory() {
return Category.SECURITY;
}
}
/**
......
......@@ -62,4 +62,10 @@ public class CliLink extends ManagementLink {
public String getUrlName() {
return "cli";
}
@Nonnull
@Override
public Category getCategory() {
return Category.TOOLS;
}
}
......@@ -62,4 +62,10 @@ public class ConfigureLink extends ManagementLink {
public String getUrlName() {
return "configure";
}
@Nonnull
@Override
public Category getCategory() {
return Category.CONFIGURATION;
}
}
......@@ -30,6 +30,8 @@ import hudson.security.Permission;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import javax.annotation.Nonnull;
/**
* @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
*/
......@@ -59,4 +61,10 @@ public class ConsoleLink extends ManagementLink {
public Permission getRequiredPermission() {
return Jenkins.ADMINISTER;
}
@Nonnull
@Override
public Category getCategory() {
return Category.TOOLS;
}
}
......@@ -27,7 +27,6 @@ package jenkins.management;
import hudson.Extension;
import hudson.model.ManagementLink;
import hudson.security.Permission;
import jenkins.management.Messages;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
......@@ -63,4 +62,10 @@ public class NodesLink extends ManagementLink {
public String getUrlName() {
return "computer";
}
@Nonnull
@Override
public Category getCategory() {
return Category.CONFIGURATION;
}
}
......@@ -28,6 +28,8 @@ import hudson.Extension;
import hudson.model.ManagementLink;
import org.jenkinsci.Symbol;
import javax.annotation.Nonnull;
/**
* @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
*/
......@@ -52,4 +54,10 @@ public class PluginsLink extends ManagementLink {
public String getUrlName() {
return "pluginManager";
}
@Nonnull
@Override
public Category getCategory() {
return Category.CONFIGURATION;
}
}
......@@ -28,6 +28,8 @@ import hudson.Extension;
import hudson.model.ManagementLink;
import org.jenkinsci.Symbol;
import javax.annotation.Nonnull;
/**
* @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
*/
......@@ -61,4 +63,10 @@ public class ReloadLink extends ManagementLink {
public boolean getRequiresPOST() {
return true;
}
@Nonnull
@Override
public Category getCategory() {
return Category.TOOLS;
}
}
......@@ -29,6 +29,8 @@ import hudson.model.ManagementLink;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import javax.annotation.Nonnull;
/**
* @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
*/
......@@ -58,4 +60,10 @@ public class ShutdownLink extends ManagementLink {
public boolean getRequiresPOST() {
return true;
}
@Nonnull
@Override
public Category getCategory() {
return Category.TOOLS;
}
}
......@@ -62,4 +62,10 @@ public class StatisticsLink extends ManagementLink {
public String getUrlName() {
return "load-statistics";
}
@Nonnull
@Override
public Category getCategory() {
return Category.STATUS;
}
}
......@@ -31,8 +31,6 @@ import javax.annotation.Nonnull;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import javax.annotation.CheckForNull;
/**
* @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
*/
......@@ -63,4 +61,10 @@ public class SystemInfoLink extends ManagementLink {
public String getUrlName() {
return "systemInfo";
}
@Nonnull
@Override
public Category getCategory() {
return Category.STATUS;
}
}
......@@ -28,6 +28,8 @@ import hudson.Extension;
import hudson.model.ManagementLink;
import org.jenkinsci.Symbol;
import javax.annotation.Nonnull;
/**
* @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
*/
......@@ -52,4 +54,10 @@ public class SystemLogLink extends ManagementLink {
public String getUrlName() {
return "log";
}
@Nonnull
@Override
public Category getCategory() {
return Category.STATUS;
}
}
......@@ -4737,6 +4737,22 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
public List<ManagementLink> getManagementLinks() {
return ManagementLink.all();
}
// for Jelly
@Restricted(NoExternalUse.class)
public Map<ManagementLink.Category, List<ManagementLink>> getCategorizedManagementLinks() {
Map<ManagementLink.Category, List<ManagementLink>> byCategory = new TreeMap<>();
for (ManagementLink link : ManagementLink.all()) {
if (link.getIconFileName() == null) {
continue;
}
if (!Jenkins.get().hasPermission(link.getRequiredPermission())) {
continue;
}
byCategory.computeIfAbsent(link.getCategory(), c -> new ArrayList<>()).add(link);
}
return byCategory;
}
/**
* If set, a currently active setup wizard - e.g. installation
......
......@@ -39,6 +39,7 @@ import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.verb.POST;
import javax.annotation.Nonnull;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.logging.Level;
......@@ -73,6 +74,12 @@ public class GlobalToolConfiguration extends ManagementLink {
return Jenkins.ADMINISTER;
}
@Nonnull
@Override
public Category getCategory() {
return Category.CONFIGURATION;
}
@POST
public synchronized void doConfigure(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException {
boolean result = configure(req, req.getSubmittedForm());
......
......@@ -404,3 +404,11 @@ User.IllegalFullname="{0}" is prohibited as a full name for security reasons.
TimeZoneProperty.DisplayName=User Defined Time Zone
TimeZoneProperty.DisplayDefaultTimeZone=Default
ManagementLink.Category.CONFIGURATION=System Configuration
ManagementLink.Category.SECURITY=Security
ManagementLink.Category.STATUS=Status Information
ManagementLink.Category.TROUBLESHOOTING=Troubleshooting
ManagementLink.Category.TOOLS=Tools and Actions
ManagementLink.Category.MISC=Other
ManagementLink.Category.UNCATEGORIZED=Uncategorized
......@@ -46,11 +46,13 @@ THE SOFTWARE.
<st:include page="downgrade.jelly" />
</div>
<j:forEach var="m" items="${it.managementLinks}">
<l:hasPermission permission="${m.requiredPermission}">
<j:forEach var="category" items="${it.categorizedManagementLinks.entrySet()}">
<h2>${category.key.label}</h2>
<div class="manage-page__row">
<j:forEach var="m" items="${category.value}">
<j:set var="icon" value="${m.iconClassName != null ? m.iconClassName : m.iconFileName}" />
<j:if test="${icon!=null}">
<div class="manage-option">
<div class="manage-option manage-page__column">
<j:set var="iconUrl" value="${icon.startsWith('/') ? resURL+icon : imagesURL + '/48x48/' + icon}" />
<j:set var="alt" value="${icon.replaceAll('\\d*\\.[^.]+$', '')}"/>
${taskTags!=null and attrs.contextMenu!='false' ? taskTags.add(m.urlName, iconUrl, m.displayName, m.requiresPOST, m.requiresConfirmation) : null}
......@@ -88,7 +90,8 @@ THE SOFTWARE.
</j:choose>
</div>
</j:if>
</l:hasPermission>
</j:forEach>
</div>
</j:forEach>
</l:main-panel>
......
......@@ -55,7 +55,7 @@ public class ManagementLinkTest {
for (int i=0; ; i++) {
HtmlPage page = wc.goTo("manage");
List<?> anchors = DomNodeUtil.selectNodes(page, "//div[@class='manage-option']/a[not(@onclick)]");
List<?> anchors = DomNodeUtil.selectNodes(page, "//div[contains(@class,'manage-option')]/a[not(@onclick)]");
assertTrue(anchors.size()>=8);
if (i==anchors.size()) return; // done
......
......@@ -24,3 +24,5 @@ html {
// Keep page header code in this bundle to avoid loading multiple files
// that are always needed
@import './modules/page-header.less';
@import './modules/manage-jenkins.less';
.manage-page__row {
display: block;
display: flex;
flex-wrap: wrap;
}
.manage-page__column {
width: 100%;
}
@media screen and (min-width: 992px) {
.manage-page__column {
width: 50%;
}
}
@media screen and (min-width: 1200px) {
.manage-page__column {
width: 33.333%;
}
}
@media screen and (min-width: 1800px) {
.manage-page__column {
width: 25%;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册