From dcbcf8148d9022d5427e1ac37b3f92bdf18dda27 Mon Sep 17 00:00:00 2001
From: Jan Faracik <43062514+janfaracik@users.noreply.github.com>
Date: Wed, 15 Jul 2026 08:33:36 +0100
Subject: [PATCH 1/7] Show a notification on Manage Jenkins page save
---
core/src/main/java/hudson/Functions.java | 6 +++
.../security/GlobalSecurityConfiguration.java | 2 +-
core/src/main/java/hudson/util/FormApply.java | 52 +++++++++++++++++++
.../main/java/jenkins/agents/CloudSet.java | 2 +-
.../AppearanceGlobalConfiguration.java | 2 +-
core/src/main/java/jenkins/model/Jenkins.java | 2 +-
.../tools/GlobalToolConfiguration.java | 2 +-
.../main/resources/lib/layout/layout.jelly | 5 +-
src/main/js/app.js | 14 +++++
.../java/jenkins/bugs/Jenkins64991Test.java | 2 +-
10 files changed, 82 insertions(+), 7 deletions(-)
diff --git a/core/src/main/java/hudson/Functions.java b/core/src/main/java/hudson/Functions.java
index 391ed0389ea7..08c1cce3c327 100644
--- a/core/src/main/java/hudson/Functions.java
+++ b/core/src/main/java/hudson/Functions.java
@@ -86,6 +86,7 @@
import hudson.tasks.Publisher;
import hudson.tasks.UserAvatarResolver;
import hudson.util.Area;
+import hudson.util.FormApply;
import hudson.util.FormValidation.CheckMethod;
import hudson.util.HudsonIsLoading;
import hudson.util.HudsonIsRestarting;
@@ -217,6 +218,11 @@ public class Functions {
public Functions() {
}
+ @Restricted(NoExternalUse.class)
+ public @CheckForNull FormApply.Notification getFormApplyNotification() {
+ return FormApply.getAndClearNotification(Stapler.getCurrentRequest2());
+ }
+
/**
* Generates an unique ID.
*/
diff --git a/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java b/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java
index ae90b0428c7b..d1fd4bdcca6d 100644
--- a/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java
+++ b/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java
@@ -108,7 +108,7 @@ public synchronized void doConfigure(StaplerRequest2 req, StaplerResponse2 rsp)
boolean result = configure(req, json);
LOGGER.log(Level.FINE, "security saved: " + result);
Jenkins.get().save();
- FormApply.success(req.getContextPath() + "/manage").generateResponse(req, rsp, null);
+ FormApply.success(req.getContextPath() + "/manage/" + getUrlName()).generateResponse(req, rsp, null);
} catch (JSONException x) {
LOGGER.warning(() -> "Bad JSON:\n" + json.toString(2));
throw x;
diff --git a/core/src/main/java/hudson/util/FormApply.java b/core/src/main/java/hudson/util/FormApply.java
index 3d5f458ec126..ed6d63931288 100644
--- a/core/src/main/java/hudson/util/FormApply.java
+++ b/core/src/main/java/hudson/util/FormApply.java
@@ -24,8 +24,10 @@
package hudson.util;
+import edu.umd.cs.findbugs.annotations.CheckForNull;
import hudson.Functions;
import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpSession;
import java.io.IOException;
import jenkins.model.Jenkins;
import org.kohsuke.stapler.HttpResponses.HttpResponseException;
@@ -40,6 +42,9 @@
* @since 1.453
*/
public class FormApply {
+ private static final String NOTIFICATION_MESSAGE_SESSION_ATTRIBUTE = FormApply.class.getName() + ".notificationMessage";
+ private static final String NOTIFICATION_TYPE_SESSION_ATTRIBUTE = FormApply.class.getName() + ".notificationType";
+
/**
* Generates the response for the form submission in such a way that it handles the "apply" button
* correctly.
@@ -56,6 +61,7 @@ public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object n
showNotification(Messages.HttpResponses_Saved(), NotificationType.SUCCESS)
.generateResponse(req, rsp, node);
} else {
+ setNotificationInSession(req, Messages.HttpResponses_Saved(), NotificationType.SUCCESS);
rsp.sendRedirect(destination);
}
}
@@ -127,6 +133,52 @@ public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object n
};
}
+ private static void setNotificationInSession(StaplerRequest2 req, String message, NotificationType notificationType) {
+ HttpSession session = req.getSession();
+ session.setAttribute(NOTIFICATION_MESSAGE_SESSION_ATTRIBUTE, message);
+ session.setAttribute(NOTIFICATION_TYPE_SESSION_ATTRIBUTE, notificationType.name());
+ }
+
+ public static @CheckForNull Notification getAndClearNotification(StaplerRequest2 req) {
+ HttpSession session = req.getSession(false);
+ if (session == null) {
+ return null;
+ }
+
+ String message = (String) session.getAttribute(NOTIFICATION_MESSAGE_SESSION_ATTRIBUTE);
+ String notificationType = (String) session.getAttribute(NOTIFICATION_TYPE_SESSION_ATTRIBUTE);
+ session.removeAttribute(NOTIFICATION_MESSAGE_SESSION_ATTRIBUTE);
+ session.removeAttribute(NOTIFICATION_TYPE_SESSION_ATTRIBUTE);
+
+ if (message == null || notificationType == null) {
+ return null;
+ }
+
+ try {
+ return new Notification(message, NotificationType.valueOf(notificationType));
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+
+ public static final class Notification {
+ private final String message;
+ private final NotificationType notificationType;
+
+ private Notification(String message, NotificationType notificationType) {
+ this.message = message;
+ this.notificationType = notificationType;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public NotificationType getNotificationType() {
+ return notificationType;
+ }
+ }
+
/**
* Corresponds to types declared in index.js
diff --git a/core/src/main/java/jenkins/agents/CloudSet.java b/core/src/main/java/jenkins/agents/CloudSet.java
index cbd5cc975d89..d458d7ac549c 100644
--- a/core/src/main/java/jenkins/agents/CloudSet.java
+++ b/core/src/main/java/jenkins/agents/CloudSet.java
@@ -285,7 +285,7 @@ public void doReorder(StaplerRequest2 req, StaplerResponse2 rsp) throws IOExcept
var clouds = new ArrayList<>(Jenkins.get().clouds);
clouds.sort(Comparator.comparingInt(c -> getIndexOf(namesList, c)));
Jenkins.get().clouds.replaceBy(clouds);
- FormApply.success(req.getContextPath() + "/manage").generateResponse(req, rsp, null);
+ FormApply.success(req.getContextPath() + "/manage/" + getUrlName()).generateResponse(req, rsp, null);
}
private static int getIndexOf(List namesList, Cloud cloud) {
diff --git a/core/src/main/java/jenkins/appearance/AppearanceGlobalConfiguration.java b/core/src/main/java/jenkins/appearance/AppearanceGlobalConfiguration.java
index 1208043b60cd..33d764d0cc04 100644
--- a/core/src/main/java/jenkins/appearance/AppearanceGlobalConfiguration.java
+++ b/core/src/main/java/jenkins/appearance/AppearanceGlobalConfiguration.java
@@ -101,7 +101,7 @@ public Category getCategory() {
public synchronized void doConfigure(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException, ServletException, Descriptor.FormException {
boolean result = configure(req, req.getSubmittedForm());
LOGGER.log(Level.FINE, "appearance saved: " + result);
- FormApply.success(req.getContextPath() + "/manage").generateResponse(req, rsp, null);
+ FormApply.success(req.getContextPath() + "/manage/" + getUrlName()).generateResponse(req, rsp, null);
}
private boolean configure(StaplerRequest2 req, JSONObject json) throws Descriptor.FormException, IOException {
diff --git a/core/src/main/java/jenkins/model/Jenkins.java b/core/src/main/java/jenkins/model/Jenkins.java
index 7cfac6f3b3c6..f4c009f9e397 100644
--- a/core/src/main/java/jenkins/model/Jenkins.java
+++ b/core/src/main/java/jenkins/model/Jenkins.java
@@ -4045,7 +4045,7 @@ public synchronized void doConfigSubmit(StaplerRequest2 req, StaplerResponse2 rs
save();
updateComputers(this);
if (result)
- FormApply.success(req.getContextPath() + '/').generateResponse(req, rsp, null);
+ FormApply.success(req.getContextPath() + "/manage/configure").generateResponse(req, rsp, null);
else
FormApply.success("configure").generateResponse(req, rsp, null); // back to config
diff --git a/core/src/main/java/jenkins/tools/GlobalToolConfiguration.java b/core/src/main/java/jenkins/tools/GlobalToolConfiguration.java
index 47208f942958..d00906363b09 100644
--- a/core/src/main/java/jenkins/tools/GlobalToolConfiguration.java
+++ b/core/src/main/java/jenkins/tools/GlobalToolConfiguration.java
@@ -84,7 +84,7 @@ public Category getCategory() {
public synchronized void doConfigure(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException, ServletException, Descriptor.FormException {
boolean result = configure(req, req.getSubmittedForm());
LOGGER.log(Level.FINE, "tools saved: " + result);
- FormApply.success(req.getContextPath() + "/manage").generateResponse(req, rsp, null);
+ FormApply.success(req.getContextPath() + "/manage/" + getUrlName()).generateResponse(req, rsp, null);
}
private boolean configure(StaplerRequest2 req, JSONObject json) throws Descriptor.FormException, IOException {
diff --git a/core/src/main/resources/lib/layout/layout.jelly b/core/src/main/resources/lib/layout/layout.jelly
index 0e2dac0f47e8..399aade7341e 100644
--- a/core/src/main/resources/lib/layout/layout.jelly
+++ b/core/src/main/resources/lib/layout/layout.jelly
@@ -91,6 +91,7 @@ THE SOFTWARE.
+
${h.advertiseHeaders(response2)}
@@ -155,7 +156,9 @@ THE SOFTWARE.
+ data-search-help-url="${%searchBox.url}"
+ data-notification-message="${formApplyNotification.message}"
+ data-notification-type="${formApplyNotification.notificationType}">
diff --git a/src/main/js/app.js b/src/main/js/app.js
index c21991f6e826..819374500744 100644
--- a/src/main/js/app.js
+++ b/src/main/js/app.js
@@ -9,11 +9,25 @@ import ConfirmationLink from "@/components/confirmation-link";
import Dialogs from "@/components/dialogs";
import Defer from "@/components/defer";
+function showPageLoadNotification() {
+ const { notificationMessage, notificationType } = document.body.dataset;
+ if (!notificationMessage) {
+ return;
+ }
+
+ const options =
+ (notificationType && window.notificationBar[notificationType]) || undefined;
+ window.notificationBar.show(notificationMessage, options);
+ delete document.body.dataset.notificationMessage;
+ delete document.body.dataset.notificationType;
+}
+
AppBar.init();
Dropdowns.init();
CommandPalette.init();
Defer.init();
Notifications.init();
+showPageLoadNotification();
SearchBar.init();
Tooltips.init();
StopButtonLink.init();
diff --git a/test/src/test/java/jenkins/bugs/Jenkins64991Test.java b/test/src/test/java/jenkins/bugs/Jenkins64991Test.java
index 7ff236736224..1a4bd4a457e7 100644
--- a/test/src/test/java/jenkins/bugs/Jenkins64991Test.java
+++ b/test/src/test/java/jenkins/bugs/Jenkins64991Test.java
@@ -85,7 +85,7 @@ void test403Redirect() throws Exception {
final Page redirectedPage = HtmlFormUtil.submit(loginPage.getFormByName("login"));
assertTrue(redirectedPage.isHtmlPage());
- assertEquals(j.getURL() + "manage/", redirectedPage.getUrl().toExternalForm());
+ assertEquals(j.getURL() + "manage/configure", redirectedPage.getUrl().toExternalForm());
assertThat(redirectedPage.getWebResponse().getContentAsString(), containsStringIgnoringCase(Messages.GlobalSecurityConfiguration_DisplayName()));
}
From 96869ff90bae38790470325c021fa39d2b667fec Mon Sep 17 00:00:00 2001
From: Jan Faracik <43062514+janfaracik@users.noreply.github.com>
Date: Thu, 16 Jul 2026 08:03:04 +0100
Subject: [PATCH 2/7] Update Jenkins64991Test.java
---
test/src/test/java/jenkins/bugs/Jenkins64991Test.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/src/test/java/jenkins/bugs/Jenkins64991Test.java b/test/src/test/java/jenkins/bugs/Jenkins64991Test.java
index 1a4bd4a457e7..7ff236736224 100644
--- a/test/src/test/java/jenkins/bugs/Jenkins64991Test.java
+++ b/test/src/test/java/jenkins/bugs/Jenkins64991Test.java
@@ -85,7 +85,7 @@ void test403Redirect() throws Exception {
final Page redirectedPage = HtmlFormUtil.submit(loginPage.getFormByName("login"));
assertTrue(redirectedPage.isHtmlPage());
- assertEquals(j.getURL() + "manage/configure", redirectedPage.getUrl().toExternalForm());
+ assertEquals(j.getURL() + "manage/", redirectedPage.getUrl().toExternalForm());
assertThat(redirectedPage.getWebResponse().getContentAsString(), containsStringIgnoringCase(Messages.GlobalSecurityConfiguration_DisplayName()));
}
From 1d4e92619e44538601f5dde3858e33d9c2501960 Mon Sep 17 00:00:00 2001
From: Jan Faracik <43062514+janfaracik@users.noreply.github.com>
Date: Thu, 16 Jul 2026 08:06:05 +0100
Subject: [PATCH 3/7] Update CspHeaderDeciderTest.java
---
.../java/jenkins/security/csp/impl/CspHeaderDeciderTest.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/src/test/java/jenkins/security/csp/impl/CspHeaderDeciderTest.java b/test/src/test/java/jenkins/security/csp/impl/CspHeaderDeciderTest.java
index 67e41556506d..65da3adfa05c 100644
--- a/test/src/test/java/jenkins/security/csp/impl/CspHeaderDeciderTest.java
+++ b/test/src/test/java/jenkins/security/csp/impl/CspHeaderDeciderTest.java
@@ -234,7 +234,7 @@ public void testFallbackAdminMonitorAndSetup(JenkinsRule j) throws IOException,
final Page afterSavingPage = HtmlFormUtil.submit(setupPage.getFormByName("config"), setupPage.getFormByName("config").getButtonByName("Submit"));
assertThat(afterSavingPage, instanceOf(HtmlPage.class));
- assertThat(afterSavingPage.getUrl().getPath(), is(j.contextPath + "/manage/"));
+ assertThat(afterSavingPage.getUrl().getPath(), is(j.contextPath + "/manage/configureSecurity/"));
assertThat(afterSavingPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy"), not(nullValue()));
assertThat(afterSavingPage.getWebResponse().getResponseHeaderValue("Content-Security-Policy-Report-Only"), nullValue());
From c085134b8fa8c266bfadc862bfe32adf976b8b79 Mon Sep 17 00:00:00 2001
From: Jan Faracik <43062514+janfaracik@users.noreply.github.com>
Date: Thu, 16 Jul 2026 08:10:04 +0100
Subject: [PATCH 4/7] Tidy up
---
src/main/js/app.js | 14 --------------
src/main/js/components/notifications/index.js | 15 +++++++++++++++
2 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/src/main/js/app.js b/src/main/js/app.js
index 819374500744..c21991f6e826 100644
--- a/src/main/js/app.js
+++ b/src/main/js/app.js
@@ -9,25 +9,11 @@ import ConfirmationLink from "@/components/confirmation-link";
import Dialogs from "@/components/dialogs";
import Defer from "@/components/defer";
-function showPageLoadNotification() {
- const { notificationMessage, notificationType } = document.body.dataset;
- if (!notificationMessage) {
- return;
- }
-
- const options =
- (notificationType && window.notificationBar[notificationType]) || undefined;
- window.notificationBar.show(notificationMessage, options);
- delete document.body.dataset.notificationMessage;
- delete document.body.dataset.notificationType;
-}
-
AppBar.init();
Dropdowns.init();
CommandPalette.init();
Defer.init();
Notifications.init();
-showPageLoadNotification();
SearchBar.init();
Tooltips.init();
StopButtonLink.init();
diff --git a/src/main/js/components/notifications/index.js b/src/main/js/components/notifications/index.js
index 39bbfe5d95cc..2762920614f1 100644
--- a/src/main/js/components/notifications/index.js
+++ b/src/main/js/components/notifications/index.js
@@ -73,6 +73,21 @@ function init() {
}
},
};
+
+ tryShowPageLoadNotification();
+}
+
+function tryShowPageLoadNotification() {
+ const { notificationMessage, notificationType } = document.body.dataset;
+ if (!notificationMessage) {
+ return;
+ }
+
+ const options =
+ (notificationType && window.notificationBar[notificationType]) || undefined;
+ window.notificationBar.show(notificationMessage, options);
+ delete document.body.dataset.notificationMessage;
+ delete document.body.dataset.notificationType;
}
export default { init };
From 4d9179e00f7bc1be1dddadcfaaa799d309a00a03 Mon Sep 17 00:00:00 2001
From: Jan Faracik <43062514+janfaracik@users.noreply.github.com>
Date: Thu, 16 Jul 2026 08:13:26 +0100
Subject: [PATCH 5/7] Tidy up
---
core/src/main/java/hudson/util/FormApply.java | 6 +-----
src/main/js/components/notifications/index.js | 10 +++++-----
2 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/core/src/main/java/hudson/util/FormApply.java b/core/src/main/java/hudson/util/FormApply.java
index ed6d63931288..7be1337e9004 100644
--- a/core/src/main/java/hudson/util/FormApply.java
+++ b/core/src/main/java/hudson/util/FormApply.java
@@ -154,11 +154,7 @@ private static void setNotificationInSession(StaplerRequest2 req, String message
return null;
}
- try {
- return new Notification(message, NotificationType.valueOf(notificationType));
- } catch (IllegalArgumentException e) {
- return null;
- }
+ return new Notification(message, NotificationType.valueOf(notificationType));
}
public static final class Notification {
diff --git a/src/main/js/components/notifications/index.js b/src/main/js/components/notifications/index.js
index 2762920614f1..adfc3476f0dd 100644
--- a/src/main/js/components/notifications/index.js
+++ b/src/main/js/components/notifications/index.js
@@ -79,15 +79,15 @@ function init() {
function tryShowPageLoadNotification() {
const { notificationMessage, notificationType } = document.body.dataset;
+
if (!notificationMessage) {
return;
}
- const options =
- (notificationType && window.notificationBar[notificationType]) || undefined;
- window.notificationBar.show(notificationMessage, options);
- delete document.body.dataset.notificationMessage;
- delete document.body.dataset.notificationType;
+ window.notificationBar.show(
+ notificationMessage,
+ window.notificationBar[notificationType],
+ );
}
export default { init };
From e5d79952b2611bc098805e0c7a7b1e2b026c03b9 Mon Sep 17 00:00:00 2001
From: Jan Faracik <43062514+janfaracik@users.noreply.github.com>
Date: Thu, 16 Jul 2026 08:14:48 +0100
Subject: [PATCH 6/7] Update FormApply.java
---
core/src/main/java/hudson/util/FormApply.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/core/src/main/java/hudson/util/FormApply.java b/core/src/main/java/hudson/util/FormApply.java
index 7be1337e9004..ee7ebbd67424 100644
--- a/core/src/main/java/hudson/util/FormApply.java
+++ b/core/src/main/java/hudson/util/FormApply.java
@@ -175,7 +175,6 @@ public NotificationType getNotificationType() {
}
}
-
/**
* Corresponds to types declared in index.js
*/
From 4869792c753266b708305fab8a2019c1e88222a3 Mon Sep 17 00:00:00 2001
From: Jan Faracik <43062514+janfaracik@users.noreply.github.com>
Date: Thu, 16 Jul 2026 19:53:48 +0100
Subject: [PATCH 7/7] Add save bar, only visible in experimental UI
---
.../GlobalSecurityConfiguration/index.groovy | 14 +++---
.../AppearanceGlobalConfiguration/index.jelly | 14 +++---
.../jenkins/model/Jenkins/configure.jelly | 9 +++-
.../GlobalToolConfiguration/index.groovy | 13 +++---
.../src/main/resources/lib/form/saveBar.jelly | 43 +++++++++++++++++++
5 files changed, 72 insertions(+), 21 deletions(-)
create mode 100644 core/src/main/resources/lib/form/saveBar.jelly
diff --git a/core/src/main/resources/hudson/security/GlobalSecurityConfiguration/index.groovy b/core/src/main/resources/hudson/security/GlobalSecurityConfiguration/index.groovy
index c9555cf750b4..4dd1072fc3be 100644
--- a/core/src/main/resources/hudson/security/GlobalSecurityConfiguration/index.groovy
+++ b/core/src/main/resources/hudson/security/GlobalSecurityConfiguration/index.groovy
@@ -5,10 +5,12 @@ import hudson.markup.MarkupFormatterDescriptor
import hudson.security.AuthorizationStrategy
import hudson.Functions
import hudson.model.Descriptor
+import jenkins.model.experimentalflags.UserExperimentalFlag
def f=namespace(lib.FormTagLib)
def l=namespace(lib.LayoutTagLib)
def st=namespace("jelly:stapler")
+def newManageJenkins = UserExperimentalFlag.getFlagValueForCurrentUser("jenkins.model.experimentalflags.NewManageJenkinsUserExperimentalFlag")
l.'settings-subpage'(permission: app.SYSTEM_READ) {
set("readOnlyMode", !app.hasPermission(app.ADMINISTER))
@@ -55,15 +57,11 @@ l.'settings-subpage'(permission: app.SYSTEM_READ) {
}
l.isAdmin() {
- f.bottomButtonBar {
- f.submit(value: _("Save"))
- f.apply()
+ if (newManageJenkins) {
+ f.saveBar()
+ } else {
+ f.saveApplyBar()
}
}
}
-
- l.isAdmin() {
- st.adjunct(includes: "lib.form.confirm")
- }
}
-
diff --git a/core/src/main/resources/jenkins/appearance/AppearanceGlobalConfiguration/index.jelly b/core/src/main/resources/jenkins/appearance/AppearanceGlobalConfiguration/index.jelly
index 14316bec25a9..fff488e20e3d 100644
--- a/core/src/main/resources/jenkins/appearance/AppearanceGlobalConfiguration/index.jelly
+++ b/core/src/main/resources/jenkins/appearance/AppearanceGlobalConfiguration/index.jelly
@@ -46,6 +46,7 @@ THE SOFTWARE.
+
@@ -71,12 +72,15 @@ THE SOFTWARE.
-
+
+
+
+
+
+
+
+
-
-
-
-
diff --git a/core/src/main/resources/jenkins/model/Jenkins/configure.jelly b/core/src/main/resources/jenkins/model/Jenkins/configure.jelly
index eeeb6906b433..980b48673c23 100644
--- a/core/src/main/resources/jenkins/model/Jenkins/configure.jelly
+++ b/core/src/main/resources/jenkins/model/Jenkins/configure.jelly
@@ -71,7 +71,14 @@ THE SOFTWARE.
-
+
+
+
+
+
+
+
+
diff --git a/core/src/main/resources/jenkins/tools/GlobalToolConfiguration/index.groovy b/core/src/main/resources/jenkins/tools/GlobalToolConfiguration/index.groovy
index 26960945eed6..f8a918842ff6 100644
--- a/core/src/main/resources/jenkins/tools/GlobalToolConfiguration/index.groovy
+++ b/core/src/main/resources/jenkins/tools/GlobalToolConfiguration/index.groovy
@@ -2,10 +2,12 @@ package jenkins.tools.GlobalToolConfiguration
import hudson.Functions
import hudson.model.Descriptor
+import jenkins.model.experimentalflags.UserExperimentalFlag
def f=namespace(lib.FormTagLib)
def l=namespace(lib.LayoutTagLib)
def st=namespace("jelly:stapler")
+def newManageJenkins = UserExperimentalFlag.getFlagValueForCurrentUser("jenkins.model.experimentalflags.NewManageJenkinsUserExperimentalFlag")
l.'settings-subpage'(permission: app.SYSTEM_READ) {
set("readOnlyMode", !app.hasPermission(app.ADMINISTER))
@@ -22,14 +24,11 @@ l.'settings-subpage'(permission: app.SYSTEM_READ) {
}
l.isAdmin() {
- f.bottomButtonBar {
- f.submit(value: _("Save"))
- f.apply(value: _("Apply"))
+ if (newManageJenkins) {
+ f.saveBar()
+ } else {
+ f.saveApplyBar()
}
}
}
-
- l.isAdmin() {
- st.adjunct(includes: "lib.form.confirm")
- }
}
diff --git a/core/src/main/resources/lib/form/saveBar.jelly b/core/src/main/resources/lib/form/saveBar.jelly
new file mode 100644
index 000000000000..0b1118bcc41f
--- /dev/null
+++ b/core/src/main/resources/lib/form/saveBar.jelly
@@ -0,0 +1,43 @@
+
+
+
+
+
+ Creates the bottom bar for the "Save" button.
+ In read only mode (<j:set var="readOnlyMode" value="true"/>) the button is not displayed.
+
+
+ Optionally hides the save bar, can then be made visible with JavaScript.
+ Defaults to false.
+
+
+
+
+
+
+
+
+
+