Merge branch 'master' into new-buttons-1-dashboard

This commit is contained in:
Jan Faracik 2022-07-13 00:02:33 +01:00 committed by GitHub
commit 1fa24ea550
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 782 additions and 2419 deletions

View File

@ -25,8 +25,18 @@
package hudson.model;
import hudson.Extension;
import hudson.Util;
import java.io.IOException;
import jenkins.model.Jenkins;
import jenkins.model.ModelObjectWithContextMenu;
import org.apache.commons.jelly.JellyException;
import org.jenkinsci.Symbol;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerFallback;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
/**
* Adds the "Manage Jenkins" link to the top page.
@ -34,7 +44,7 @@ import org.jenkinsci.Symbol;
* @author Kohsuke Kawaguchi
*/
@Extension(ordinal = 100) @Symbol("manageJenkins")
public class ManageJenkinsAction implements RootAction {
public class ManageJenkinsAction implements RootAction, StaplerFallback, ModelObjectWithContextMenu {
@Override
public String getIconFileName() {
if (Jenkins.get().hasAnyPermission(Jenkins.MANAGE, Jenkins.SYSTEM_READ))
@ -52,4 +62,29 @@ public class ManageJenkinsAction implements RootAction {
public String getUrlName() {
return "/manage";
}
@Override
public Object getStaplerFallback() {
return Jenkins.get();
}
@Override
public ContextMenu doContextMenu(StaplerRequest request, StaplerResponse response) throws JellyException, IOException {
return new ContextMenu().from(this, request, response, "index");
}
/**
* Workaround to ensuring that links in context menus resolve correctly in the submenu of the top-level 'Dashboard'
* menu.
*/
@Restricted(NoExternalUse.class)
public void addContextMenuItem(ContextMenu menu, String url, String icon, String iconXml, String text, boolean post, boolean requiresConfirmation) {
if (Stapler.getCurrentRequest().findAncestorObject(this.getClass()) != null || !Util.isSafeToRedirectTo(url)) {
// Default behavior if the URL is absolute or scheme-relative, or the current object is an ancestor (i.e. would resolve correctly)
menu.add(url, icon, iconXml, text, post, requiresConfirmation);
return;
}
// If neither is the case, rewrite the relative URL to point to inside the /manage/ URL space
menu.add("manage/" + url, icon, iconXml, text, post, requiresConfirmation);
}
}

View File

@ -115,6 +115,7 @@ import hudson.model.Label;
import hudson.model.ListView;
import hudson.model.LoadBalancer;
import hudson.model.LoadStatistics;
import hudson.model.ManageJenkinsAction;
import hudson.model.ManagementLink;
import hudson.model.Messages;
import hudson.model.ModifiableViewGroup;
@ -4415,7 +4416,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
for (MenuItem i : menu.items) {
if (i.url.equals(request.getContextPath() + "/manage")) {
// add "Manage Jenkins" subitems
i.subMenu = new ContextMenu().from(this, request, response, "manage");
i.subMenu = new ContextMenu().from(ExtensionList.lookupSingleton(ManageJenkinsAction.class), request, response, "index");
}
}
return menu;

View File

@ -595,6 +595,8 @@ public class IconSet {
translations.put("icon-text", "symbol-details");
translations.put("icon-up", "symbol-arrow-up");
translations.put("icon-user", "symbol-people");
translations.put("icon-undo", "symbol-undo");
translations.put("icon-redo", "symbol-redo");
ICON_TO_SYMBOL_TRANSLATIONS = translations;
}

View File

@ -30,7 +30,7 @@ l.side_panel {
l.task(icon:"icon-up icon-md", href:rootURL+'/', title:_("Back to Dashboard"))
l.task(icon:"symbol-settings", href:"${rootURL}/manage", title:_("Manage Jenkins"))
if (!app.updateCenter.jobs.isEmpty()) {
l.task(icon: "symbol-download", href:"${rootURL}/updateCenter/", title:_("Update Center"))
l.task(icon: "symbol-download", href:"../updateCenter/", title:_("Update Center"))
}
}
}

View File

@ -31,5 +31,12 @@ THE SOFTWARE.
<l:task contextMenu="false" href="${buildUrl.baseUrl}/" icon="symbol-details" title="${%Status}"/>
<l:task href="${buildUrl.baseUrl}/changes" icon="symbol-changes" title="${%Changes}"/>
<p:console-link/>
<l:task href="${buildUrl.baseUrl}/configure" icon="symbol-settings" title="${h.hasPermission(it,it.UPDATE)?'%Edit Build Information':'%View Build Information'}"/>
<j:choose>
<j:when test="${h.hasPermission(it,it.UPDATE)}">
<l:task icon="symbol-edit-note" href="${buildUrl.baseUrl}/configure" title="${%Edit Build Information}"/>
</j:when>
<j:otherwise>
<l:task icon="symbol-view" href="${buildUrl.baseUrl}/configure" title="${%View Build Information}"/>
</j:otherwise>
</j:choose>
</j:jelly>

View File

@ -34,7 +34,7 @@ THE SOFTWARE.
<l:task href="${rootURL}/" icon="icon-up icon-md" title="${%Back to Dashboard}"/>
<l:task href="${rootURL}/manage" icon="symbol-settings" permissions="${app.MANAGE_AND_SYSTEM_READ}" title="${%Manage Jenkins}"/>
<l:task href="new" icon="symbol-add" permission="${createPermission}" title="${%New Node}"/>
<l:task href="${rootURL}/configureClouds" icon="symbol-cloud" permission="${app.SYSTEM_READ}"
<l:task href="../configureClouds" icon="symbol-cloud" permission="${app.SYSTEM_READ}"
title="${app.hasPermission(app.ADMINISTER) ? '%Configure Clouds' : '%View Clouds'}"/>
<l:task href="configure" icon="symbol-settings" permissions="${app.MANAGE_AND_SYSTEM_READ}" title="${%Node Monitoring}"/>
</l:tasks>

View File

@ -31,7 +31,7 @@ THE SOFTWARE.
<l:app-bar title="${%Manage Jenkins}" />
<j:if test="${taskTags==null}">
<st:include page="sidepanel.jelly" />
<st:include page="sidepanel.jelly" it="${app}" />
</j:if>
<l:main-panel>
@ -39,10 +39,10 @@ THE SOFTWARE.
<j:forEach var="am" items="${app.activeAdministrativeMonitors}">
<st:include page="message.jelly" it="${am}" />
</j:forEach>
<st:include page="downgrade.jelly" />
<st:include page="downgrade.jelly" it="${app}" />
</section>
<j:forEach var="category" items="${it.categorizedManagementLinks.entrySet()}">
<j:forEach var="category" items="${app.categorizedManagementLinks.entrySet()}">
<section class="jenkins-section jenkins-section--bottom-padding">
<h2 class="jenkins-section__title">${category.key.label}</h2>
${taskTags!=null and attrs.contextMenu!='false' ? taskTags.addHeader(category.key.label) : null}
@ -55,7 +55,7 @@ THE SOFTWARE.
<j:set var="iconXml">
<l:icon src="${m.iconFileName}" />
</j:set>
${taskTags!=null and attrs.contextMenu!='false' ? taskTags.add(m.urlName, iconSrc, iconXml, m.displayName, m.requiresPOST, m.requiresConfirmation) : null}
${taskTags!=null and attrs.contextMenu!='false' ? it.addContextMenuItem(taskTags, m.urlName, iconSrc, iconXml, m.displayName, m.requiresPOST, m.requiresConfirmation) : null}
<j:choose>
<j:when test="${m.requiresConfirmation}">
<l:confirmationLink href="${m.urlName}" post="${m.requiresPOST}" message="${%are.you.sure(m.displayName)}">

View File

@ -32,7 +32,7 @@ THE SOFTWARE.
<l:tasks>
<l:task href="${rootURL}/" icon="icon-up icon-md" title="${%Back to Dashboard}"/>
<l:task href="${rootURL}/manage" icon="symbol-settings" title="${%Manage Jenkins}"/>
<l:task href="${rootURL}/pluginManager/" icon="icon-plugin icon-lg" title="${%Manage Plugins}"/>
<l:task href="../pluginManager/" icon="icon-plugin icon-lg" title="${%Manage Plugins}"/>
</l:tasks>
</l:side-panel>
</j:jelly>

View File

@ -13,7 +13,7 @@ l.layout(norefresh:true, permission:app.SYSTEM_READ, title:my.displayName) {
l.side_panel {
l.tasks {
l.task(icon:"icon-up icon-md", href:rootURL+'/', title:_("Back to Dashboard"))
l.task(icon:"symbol-settings", href:"${rootURL}/computer/", title:_("Manage Nodes"))
l.task(icon:"symbol-settings", href: "../computer/", title:_("Manage Nodes"))
}
}
l.app_bar(title: my.displayName)

View File

@ -26,9 +26,10 @@ THE SOFTWARE.
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
<l:layout title="${it.displayName} ${%Load Statistics}">
<st:include page="sidepanel.jelly" />
<l:breadcrumb title="${%Load Statistics}"/>
<l:main-panel>
<j:set var="prefix" value="overallLoad" />
<st:include page="main.jelly" from="${it.overallLoad}" />
</l:main-panel>
</l:layout>
</j:jelly>
</j:jelly>

View File

@ -29,6 +29,7 @@ THE SOFTWARE.
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<l:layout permissions="${app.MANAGE_AND_SYSTEM_READ}" title="${%System Information}">
<st:include page="sidepanel.jelly" />
<l:breadcrumb title="${%System Information}"/>
<l:main-panel>
<l:hasPermission permission="${app.SYSTEM_READ}">
<div class="jenkins-app-bar">

View File

@ -30,6 +30,7 @@ THE SOFTWARE.
<l:layout permission="${h.ADMINISTER}" title="${%Script Console}">
<st:include page="sidepanel.jelly" />
<l:breadcrumb title="${%Script Console}"/>
<l:main-panel>
<h1>${%Script Console}</h1>

View File

@ -73,7 +73,7 @@ THE SOFTWARE.
</issueManagement>
<properties>
<revision>2.359</revision>
<revision>2.360</revision>
<changelist>-SNAPSHOT</changelist>
<!-- *.html files are in UTF-8, and *.properties are in iso-8859-1, so this configuration is actually incorrect,

View File

@ -90,7 +90,7 @@ THE SOFTWARE.
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jenkins-test-harness</artifactId>
<version>1797.v711534844e8a_</version>
<version>1802.v9de0d87365d2</version>
<scope>test</scope>
<exclusions>
<exclusion>

View File

@ -86,7 +86,7 @@ public class Jenkins64991Test {
final Page redirectedPage = HtmlFormUtil.submit(loginPage.getFormByName("login"));
assertTrue(redirectedPage.isHtmlPage());
assertEquals(j.getURL() + "manage", redirectedPage.getUrl().toExternalForm());
assertEquals(j.getURL() + "manage/", redirectedPage.getUrl().toExternalForm());
assertThat(redirectedPage.getWebResponse().getContentAsString(), containsStringIgnoringCase(Messages.GlobalSecurityConfiguration_DisplayName()));
}

View File

@ -11,9 +11,7 @@ import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
@ -498,8 +496,6 @@ public class DoActionFilterTest extends StaplerAbstractTest {
public void doWithResponseImpl(ResponseImpl response) { replyOk(); }
public void doWithRequestAndResponse(RequestAndResponse requestAndResponse) { replyOk(); }
// special case to keep Groovy parameter name, but does not seem to indicate it's automatically a web method
@CapturedParameterNames("req")
public void doAnnotatedResponseSuccess(Object req) { replyOk(); }
@ -509,21 +505,6 @@ public class DoActionFilterTest extends StaplerAbstractTest {
// public void doAnnotatedJsonOutputFilter() { replyOk(); }
}
public abstract static class RequestAndResponse implements StaplerRequest, StaplerResponse {
@Override
public CollectionAndEnumeration getHeaderNames() {
return null;
}
@Override
public CollectionAndEnumeration getHeaders(String name) {
return null;
}
public abstract static class CollectionAndEnumeration implements Collection, Enumeration {
}
}
@Test
public void testNotOkSpecialCases_withServletRequest() throws Exception {
assertNotReachable("testNewRulesNotOkSpecialCases/withServletRequest/");
@ -548,12 +529,6 @@ public class DoActionFilterTest extends StaplerAbstractTest {
assertDoActionRequestWasBlockedAndResetFlag();
}
@Test
public void testNotOkSpecialCases_withRequestAndResponse() throws Exception {
assertNotReachable("testNewRulesNotOkSpecialCases/withRequestAndResponse/");
assertDoActionRequestWasBlockedAndResetFlag();
}
@Test
public void testNotOkSpecialCases_annotatedResponseSuccess() throws Exception {
assertNotReachable("testNewRulesNotOkSpecialCases/annotatedResponseSuccess/");

View File

@ -26,12 +26,10 @@
"@jenkins-cd/js-test": "^1.2.3",
"autoprefixer": "^10.4.7",
"clean-webpack-plugin": "^4.0.0",
"copy-webpack-plugin": "^6.4.1",
"css-loader": "^5.2.7",
"css-minimizer-webpack-plugin": "^1.0.0",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.7.1",
"css-minimizer-webpack-plugin": "^4.0.0",
"eslint": "^8.19.0",
"eslint-plugin-only-warn": "^1.0.3",
"file-loader": "^6.2.0",
"handlebars": "^3.0.8",
"handlebars-loader": "^1.7.2",
"jest": "^26.0.1",
@ -39,16 +37,16 @@
"jest-junit": "^14.0.0",
"jest-standard-reporter": "^2.0.0",
"less": "^4.1.3",
"less-loader": "^7.3.0",
"mini-css-extract-plugin": "^1.6.2",
"less-loader": "^11.0.0",
"mini-css-extract-plugin": "^2.6.1",
"postcss": "^8.4.14",
"postcss-loader": "^4.3.0",
"style-loader": "^2.0.0",
"postcss-loader": "^7.0.1",
"style-loader": "^3.3.1",
"stylelint": "^14.9.1",
"stylelint-config-standard": "^26.0.0",
"webpack": "^4.46.0",
"webpack": "^5.73.0",
"webpack-cli": "^4.10.0",
"webpack-fix-style-only-entries": "^0.5.0"
"webpack-remove-empty-scripts": "^0.8.1"
},
"dependencies": {
"@babel/preset-env": "^7.18.6",
@ -56,7 +54,7 @@
"bootstrap": "3.4.1",
"jenkins-js-modules": "^1.5.0",
"jquery": "3.6.0",
"lodash": "^4.17.20",
"lodash": "^4.17.21",
"postcss-less": "^6.0.0",
"sortablejs": "^1.15.0",
"window-handle": "^1.0.0"

View File

@ -1131,7 +1131,7 @@ td.progress-bar-done {
}
td.progress-bar-left {
background-color: #ebecf0;
background-color: #bababa;
}
table.progress-bar.red {

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512">
<title>edit-note</title>
<path d="M384 224v184a40 40 0 01-40 40H104a40 40 0 01-40-40V168a40 40 0 0140-40h167.48" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/>
<path d="M459.94 53.25a16.06 16.06 0 00-23.22-.56L424.35 65a8 8 0 000 11.31l11.34 11.32a8 8 0 0011.34 0l12.06-12c6.1-6.09 6.67-16.01.85-22.38zM399.34 90L218.82 270.2a9 9 0 00-2.31 3.93L208.16 299a3.91 3.91 0 004.86 4.86l24.85-8.35a9 9 0 003.93-2.31L422 112.66a9 9 0 000-12.66l-9.95-10a9 9 0 00-12.71 0z" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 632 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><title>Arrow Redo</title><path d="M448 256L272 88v96C103.57 184 64 304.77 64 424c48.61-62.24 91.6-96 208-96v96z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/></svg>

After

Width:  |  Height:  |  Size: 274 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><title>Arrow Undo</title><path d="M240 424v-96c116.4 0 159.39 33.76 208 96 0-119.23-39.57-240-208-240V88L64 256z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/></svg>

After

Width:  |  Height:  |  Size: 275 B

View File

@ -2,8 +2,8 @@
const path = require('path');
const MiniCSSExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const RemoveEmptyScriptsPlugin = require('webpack-remove-empty-scripts');
const CopyPlugin = require('copy-webpack-plugin');
const { CleanWebpackPlugin: CleanPlugin } = require('clean-webpack-plugin');
@ -42,7 +42,7 @@ module.exports = (env, argv) => ({
},
devtool: argv.mode === 'production' ? 'source-map' : 'inline-cheap-module-source-map',
plugins: [
new FixStyleOnlyEntriesPlugin(),
new RemoveEmptyScriptsPlugin({}),
new MiniCSSExtractPlugin({
filename: "[name].css",
}),
@ -77,14 +77,12 @@ module.exports = (env, argv) => ({
loader: 'css-loader',
options: {
sourceMap: true,
url: (url, resourcePath) => {
// ignore the URLS on the base styles as they are picked
// from the src/main/webapp/images dir
if (resourcePath.includes('styles.less')) {
return false;
// ignore the URLS on the base styles as they are picked
// from the src/main/webapp/images dir
url: {
filter: (url, resourcePath) => {
return !resourcePath.includes('styles.less');
}
return true;
}
}
},
@ -104,15 +102,10 @@ module.exports = (env, argv) => ({
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}
]
type: "asset/resource",
generator: {
filename: 'fonts/[name].[ext]',
},
},
{
test: /\.hbs$/,

File diff suppressed because it is too large Load Diff