mirror of
https://github.com/jenkinsci/jenkins.git
synced 2026-10-26 19:15:09 +00:00
Standardise experimental Jenkins pages, make the side panel independently scrollable + make the build bar sticky (#27380)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Mark Waite <mark.earl.waite@gmail.com>
This commit is contained in:
24 files changed
+417
-435
No files matched your search
@@ -27,7 +27,7 @@ THE SOFTWARE.
|
||||
-->
|
||||
<?jelly escape-by-default='true'?>
|
||||
<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:side-panel sticky="true">
|
||||
<l:side-panel>
|
||||
<l:app-bar title="${%Plugins}" />
|
||||
<l:tasks>
|
||||
<l:task href="${rootURL}/manage/pluginManager/" icon="symbol-download" title="${%Updates}" badge="${app.updateCenter.badge}"/>
|
||||
|
||||
@@ -36,14 +36,14 @@ THE SOFTWARE.
|
||||
|
||||
<l:breadcrumb title="${readOnlyMode ? '%Configuration' : '%Configure'}" />
|
||||
|
||||
<l:side-panel sticky="true">
|
||||
<l:side-panel>
|
||||
<l:app-bar title="${readOnlyMode ? '%Configuration' : '%Configure'}" />
|
||||
<div id="tasks">
|
||||
<l:skeleton type="side-panel" />
|
||||
</div>
|
||||
</l:side-panel>
|
||||
|
||||
<l:main-panel>
|
||||
<l:main-panel width="narrow">
|
||||
<f:form method="post" class="jenkins-form" action="configSubmit" name="config" tableClass="config-table">
|
||||
<l:app-bar title="${%General}" headingLevel="h2">
|
||||
<p:config-disableBuild />
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<!--
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2026, Jan Faracik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<?jelly escape-by-default='true'?>
|
||||
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:dd="/lib/layout/dropdowns">
|
||||
<footer class="page-footer">
|
||||
<div class="page-footer__flex-row">
|
||||
<div class="page-footer__footer-id-placeholder" id="footer"></div>
|
||||
|
||||
<div class="page-footer__links">
|
||||
<l:overflowButton text="Jenkins ${h.version}"
|
||||
clazz="jenkins-button--tertiary jenkins_ver"
|
||||
icon="${null}"
|
||||
tooltip="${null}">
|
||||
<l:hasPermission permission="${app.SYSTEM_READ}">
|
||||
<dd:item icon="symbol-jenkins"
|
||||
text="${%About Jenkins}"
|
||||
href="${rootURL}/manage/about" />
|
||||
<dd:separator />
|
||||
</l:hasPermission>
|
||||
<dd:item icon="symbol-heart"
|
||||
text="${%Get involved}"
|
||||
href="https://www.jenkins.io/participate/" />
|
||||
<dd:item icon="symbol-external"
|
||||
text="${%Website}"
|
||||
href="${h.getFooterURL()}" />
|
||||
</l:overflowButton>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</j:jelly>
|
||||
@@ -48,6 +48,8 @@ THE SOFTWARE.
|
||||
|
||||
<j:set var="items" value="${it.items}"/>
|
||||
<st:include page="main.jelly" />
|
||||
|
||||
<st:include page="footer.jelly" />
|
||||
</l:main-panel>
|
||||
<l:header>
|
||||
<!-- for screen resolution detection -->
|
||||
|
||||
@@ -139,6 +139,8 @@ THE SOFTWARE.
|
||||
|
||||
<j:set var="items" value="${it.items}"/>
|
||||
<st:include page="main.jelly" />
|
||||
|
||||
<st:include page="footer.jelly" />
|
||||
</div>
|
||||
</l:main-panel>
|
||||
</l:layout>
|
||||
|
||||
@@ -25,7 +25,7 @@ THE SOFTWARE.
|
||||
-->
|
||||
<?jelly escape-by-default='true'?>
|
||||
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:i="jelly:fmt"
|
||||
xmlns:x="jelly:xml" xmlns:dd="/lib/layout/dropdowns">
|
||||
xmlns:x="jelly:xml">
|
||||
<st:documentation> <![CDATA[
|
||||
Outer-most tag for a normal (non-AJAX) HTML rendering.
|
||||
This is used with nested <header>, <side-panel>, and <main-panel>
|
||||
@@ -172,53 +172,27 @@ THE SOFTWARE.
|
||||
logout="${%logout}"/>
|
||||
</j:if>
|
||||
|
||||
<div id="page-body" class="app-page-body app-page-body--${layoutType} clear">
|
||||
<j:if test="${layoutType != 'full-screen'}">
|
||||
<div class="app-page-frame__blur" />
|
||||
<div class="app-page-frame__mask" />
|
||||
<div class="app-page-frame__background" />
|
||||
</j:if>
|
||||
|
||||
<div id="page-body" class="${layoutType eq 'full-screen' ? 'app-full-screen-page-body' : 'app-page-body'} clear">
|
||||
<j:if test="${layoutType=='two-column'}">
|
||||
<j:set var="mode" value="side-panel" />
|
||||
<d:invokeBody />
|
||||
</j:if>
|
||||
<div id="main-panel">
|
||||
<div class="app-page-body__contents">
|
||||
<j:set var="mode" value="main-panel" />
|
||||
<d:invokeBody/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<j:if test="${layoutType!='full-screen'}">
|
||||
<footer class="page-footer jenkins-mobile-hide">
|
||||
<div class="page-footer__flex-row">
|
||||
<div class="page-footer__footer-id-placeholder" id="footer"></div>
|
||||
|
||||
<j:if test="${extensionsAvailable}">
|
||||
<j:forEach var="pd" items="${h.pageDecorators}">
|
||||
<st:include it="${pd}" page="footer.jelly" optional="true" />
|
||||
</j:forEach>
|
||||
</j:if>
|
||||
|
||||
<div class="page-footer__links">
|
||||
<j:if test="${!empty(it.api)}">
|
||||
<a class="jenkins-button jenkins-button--tertiary rest-api" href="api/">REST API</a>
|
||||
</j:if>
|
||||
|
||||
<l:overflowButton text="Jenkins ${h.version}"
|
||||
clazz="jenkins-button--tertiary jenkins_ver"
|
||||
icon="${null}"
|
||||
tooltip="${null}">
|
||||
<l:hasPermission permission="${app.SYSTEM_READ}">
|
||||
<dd:item icon="symbol-jenkins"
|
||||
text="${%About Jenkins}"
|
||||
href="${rootURL}/manage/about" />
|
||||
<dd:separator />
|
||||
</l:hasPermission>
|
||||
<dd:item icon="symbol-heart"
|
||||
text="${%Get involved}"
|
||||
href="https://www.jenkins.io/participate/" />
|
||||
<dd:item icon="symbol-external"
|
||||
text="${%Website}"
|
||||
href="${h.getFooterURL()}" />
|
||||
</l:overflowButton>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<j:if test="${layoutType!='full-screen' and extensionsAvailable}">
|
||||
<j:forEach var="pd" items="${h.pageDecorators}">
|
||||
<st:include it="${pd}" page="footer.jelly" optional="true" />
|
||||
</j:forEach>
|
||||
</j:if>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -26,40 +26,47 @@ THE SOFTWARE.
|
||||
<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns:st="jelly:stapler" xmlns:d="jelly:define">
|
||||
<st:documentation>
|
||||
Generates the body as the main content part of a Jenkins page.
|
||||
<st:attribute name="width">
|
||||
Optional, sets the width of the page. Available options are 'default', 'narrow', or 'wide'.
|
||||
</st:attribute>
|
||||
</st:documentation>
|
||||
|
||||
<j:if test="${mode=='main-panel'}">
|
||||
<j:if test="${app.isQuietingDown()}">
|
||||
<j:choose>
|
||||
<j:when test="${app.isPreparingSafeRestart()}">
|
||||
<div id='safe-restart-msg'>
|
||||
<j:choose>
|
||||
<j:when test="${!app.getQuietDownReason().trim().isEmpty()}">
|
||||
${app.getQuietDownReason()}
|
||||
</j:when>
|
||||
<j:otherwise>
|
||||
${%saferestart}
|
||||
</j:otherwise>
|
||||
</j:choose>
|
||||
</div>
|
||||
</j:when>
|
||||
<j:otherwise>
|
||||
<div id='shutdown-msg'>
|
||||
<j:choose>
|
||||
<j:when test="${app.getQuietDownReason() != null}">
|
||||
${app.getQuietDownReason()}
|
||||
</j:when>
|
||||
<j:otherwise>
|
||||
${%shutdown}
|
||||
</j:otherwise>
|
||||
</j:choose>
|
||||
</div>
|
||||
</j:otherwise>
|
||||
</j:choose>
|
||||
</j:if>
|
||||
<a id="skip2content" />
|
||||
<x:comment> start of main content ⇒ </x:comment>
|
||||
<d:invokeBody />
|
||||
<x:comment> ⇐ end of main content </x:comment>
|
||||
<div id="main-panel" class="app-main-panel
|
||||
${attrs.width eq 'wide' ? 'app-main-panel--wide' : ''}
|
||||
${attrs.width eq 'narrow' ? 'app-main-panel--narrow' : ''}">
|
||||
<j:if test="${app.isQuietingDown()}">
|
||||
<j:choose>
|
||||
<j:when test="${app.isPreparingSafeRestart()}">
|
||||
<div id='safe-restart-msg'>
|
||||
<j:choose>
|
||||
<j:when test="${!app.getQuietDownReason().trim().isEmpty()}">
|
||||
${app.getQuietDownReason()}
|
||||
</j:when>
|
||||
<j:otherwise>
|
||||
${%saferestart}
|
||||
</j:otherwise>
|
||||
</j:choose>
|
||||
</div>
|
||||
</j:when>
|
||||
<j:otherwise>
|
||||
<div id='shutdown-msg'>
|
||||
<j:choose>
|
||||
<j:when test="${app.getQuietDownReason() != null}">
|
||||
${app.getQuietDownReason()}
|
||||
</j:when>
|
||||
<j:otherwise>
|
||||
${%shutdown}
|
||||
</j:otherwise>
|
||||
</j:choose>
|
||||
</div>
|
||||
</j:otherwise>
|
||||
</j:choose>
|
||||
</j:if>
|
||||
<a id="skip2content" />
|
||||
<x:comment> start of main content ⇒ </x:comment>
|
||||
<d:invokeBody />
|
||||
<x:comment> ⇐ end of main content </x:comment>
|
||||
</div>
|
||||
</j:if>
|
||||
</j:jelly>
|
||||
@@ -65,7 +65,7 @@ THE SOFTWARE.
|
||||
Defaults to false if not set.
|
||||
</st:attribute>
|
||||
<st:attribute name="width">
|
||||
Optional, sets the width of the page. Available options are 'default' or 'wide'.
|
||||
Optional, sets the width of the page. Available options are 'narrow' or 'wide'.
|
||||
</st:attribute>
|
||||
</st:documentation>
|
||||
|
||||
@@ -78,8 +78,7 @@ THE SOFTWARE.
|
||||
|
||||
<l:layout title="${pageTitle} - ${manageJenkinsAction.displayName}"
|
||||
permission="${attrs.permission}"
|
||||
permissions="${attrs.permissions}"
|
||||
type="${(newManageJenkins or attrs.includeSidepanel) ? 'two-column' : 'one-column'}">
|
||||
permissions="${attrs.permissions}">
|
||||
|
||||
<j:if test="${attrs.includeBreadcrumb}">
|
||||
<!-- Hacky - this will be improved in subsequent PRs -->
|
||||
@@ -120,23 +119,19 @@ THE SOFTWARE.
|
||||
</j:forEach>
|
||||
</l:tasks>
|
||||
</l:side-panel>
|
||||
<l:main-panel>
|
||||
<div class="app-settings-container">
|
||||
<div class="app-settings-container__inner ${attrs.width eq 'wide' ? 'app-settings-container__inner--wide' : ''}">
|
||||
<j:if test="${!attrs.containsKey('header')}">
|
||||
<l:app-bar title="${pageTitle}" />
|
||||
<j:if test="${!empty(description)}">
|
||||
<div class="jenkins-page-description">
|
||||
${description}
|
||||
</div>
|
||||
</j:if>
|
||||
</j:if>
|
||||
<l:main-panel width="${attrs.width ?: 'narrow'}">
|
||||
<j:if test="${!attrs.containsKey('header')}">
|
||||
<l:app-bar title="${pageTitle}" />
|
||||
<j:if test="${!empty(description)}">
|
||||
<div class="jenkins-page-description">
|
||||
${description}
|
||||
</div>
|
||||
</j:if>
|
||||
</j:if>
|
||||
|
||||
<j:out value="${attrs.header}" />
|
||||
<j:out value="${attrs.header}" />
|
||||
|
||||
<d:invokeBody />
|
||||
</div>
|
||||
</div>
|
||||
<d:invokeBody />
|
||||
</l:main-panel>
|
||||
</j:when>
|
||||
<j:otherwise>
|
||||
@@ -144,7 +139,7 @@ THE SOFTWARE.
|
||||
<st:include page="sidepanel" />
|
||||
</j:if>
|
||||
|
||||
<l:main-panel>
|
||||
<l:main-panel width="${attrs.width ?: 'narrow'}">
|
||||
<j:if test="${!attrs.containsKey('header')}">
|
||||
<l:app-bar title="${pageTitle}" />
|
||||
<j:if test="${!empty(description)}">
|
||||
|
||||
@@ -26,17 +26,11 @@ THE SOFTWARE.
|
||||
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define">
|
||||
<st:documentation>
|
||||
Generates a left side content as part of a Jenkins page. Typically known as two-column or left-side + main-content layouts
|
||||
<st:attribute name="sticky">
|
||||
Make the side panel sticky. Should not be used on pages that include widgets in the sidepanel and when plugins can
|
||||
add their own tasks, so the number of tasks is not fixed.
|
||||
</st:attribute>
|
||||
|
||||
</st:documentation>
|
||||
|
||||
<j:if test="${mode=='side-panel'}">
|
||||
<div id="side-panel" class="app-page-body__sidebar ${attrs.sticky == 'true' ? 'app-page-body__sidebar--sticky' : ''}">
|
||||
<div id="side-panel" class="app-page-body__sidebar">
|
||||
<d:invokeBody />
|
||||
</div>
|
||||
</j:if>
|
||||
|
||||
</j:jelly>
|
||||
@@ -17,44 +17,9 @@ function init() {
|
||||
computeOverflow();
|
||||
});
|
||||
|
||||
// Fade in the page header on scroll, increasing opacity and intensity of the backdrop blur
|
||||
window.addEventListener("scroll", () => {
|
||||
const navigation = document.querySelector("#page-header");
|
||||
const scrollY = Math.max(0, window.scrollY);
|
||||
navigation.style.setProperty(
|
||||
"--background-opacity",
|
||||
Math.min(70, scrollY) + "%",
|
||||
);
|
||||
navigation.style.setProperty(
|
||||
"--background-blur",
|
||||
Math.min(40, scrollY) + "px",
|
||||
);
|
||||
if (
|
||||
!document.querySelector("#main-panel > .jenkins-search--app-bar") &&
|
||||
!document.querySelector(".app-page-body__sidebar--sticky")
|
||||
) {
|
||||
const prefersContrast = window.matchMedia(
|
||||
"(prefers-contrast: more)",
|
||||
).matches;
|
||||
navigation.style.setProperty(
|
||||
"--border-opacity",
|
||||
Math.min(
|
||||
prefersContrast ? 100 : 15,
|
||||
prefersContrast ? scrollY * 3 : scrollY,
|
||||
) + "%",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
// We can't use :has due to HtmlUnit CSS Parser not supporting it, so
|
||||
// these are workarounds for that same behaviour
|
||||
if (document.querySelector("#main-panel > .jenkins-app-bar--sticky")) {
|
||||
document
|
||||
.querySelector(".jenkins-header")
|
||||
.classList.add("jenkins-header--has-sticky-app-bar");
|
||||
}
|
||||
|
||||
if (!document.querySelector(".jenkins-breadcrumbs__list-item")) {
|
||||
document
|
||||
.querySelector(".jenkins-header")
|
||||
|
||||
@@ -78,11 +78,21 @@ $semantics: (
|
||||
// Background colors
|
||||
--background: rgb(254 254 254);
|
||||
|
||||
// Body
|
||||
--body-background-top: color-mix(
|
||||
in oklch,
|
||||
white 1.5%,
|
||||
var(--card-background)
|
||||
);
|
||||
|
||||
// Header
|
||||
--header-background: var(--background);
|
||||
--header-border: var(--text-color-secondary);
|
||||
--header-background: color-mix(
|
||||
in sRGB,
|
||||
var(--background),
|
||||
var(--text-color-secondary) 2.5%
|
||||
);
|
||||
--header-color: var(--text-color);
|
||||
--header-height: 4.125rem;
|
||||
--header-height: 3.5rem;
|
||||
|
||||
// App bar
|
||||
--bottom-app-bar-padding: 0.875rem;
|
||||
@@ -152,7 +162,6 @@ $semantics: (
|
||||
var(--jenkins-border-color--subtle);
|
||||
|
||||
@media (prefers-contrast: more) {
|
||||
--header-border: var(--text-color);
|
||||
--focus-input-border: var(--text-color);
|
||||
--jenkins-border-color: var(--text-color);
|
||||
--jenkins-border-color--subtle: var(--text-color);
|
||||
@@ -268,7 +277,7 @@ $semantics: (
|
||||
--panel-border-color: var(--light-grey);
|
||||
|
||||
// Form
|
||||
--section-padding: 1.625rem;
|
||||
--section-padding: 1.25rem;
|
||||
--input-color: var(--white);
|
||||
--input-border: color-mix(
|
||||
in sRGB,
|
||||
@@ -285,7 +294,7 @@ $semantics: (
|
||||
--form-item-max-width--small: min(35vw, 1200px);
|
||||
|
||||
@media screen and (max-width: breakpoints.$tablet-breakpoint) {
|
||||
--section-padding: 1.25rem;
|
||||
--section-padding: 1rem;
|
||||
--form-item-max-width: 100%;
|
||||
--form-item-max-width--medium: 100%;
|
||||
--form-item-max-width--small: 100%;
|
||||
@@ -293,7 +302,7 @@ $semantics: (
|
||||
|
||||
--form-label-font-weight: var(--font-bold-weight);
|
||||
--form-input-padding: 0.5rem 0.625rem;
|
||||
--form-input-border-radius: 0.625rem;
|
||||
--form-input-border-radius: 0.6875rem;
|
||||
--form-input-glow: 0 0 0 0.5rem transparent;
|
||||
--form-input-glow--focus: 0 0 0 0.25rem var(--focus-input-glow);
|
||||
--pre-background: var(--button-background);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
html {
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
color: var(--text-color);
|
||||
scroll-padding-top: calc(var(--header-height) + var(--section-padding));
|
||||
overscroll-behavior: none;
|
||||
scrollbar-color: oklch(from var(--text-color-secondary) l c h / 0.35)
|
||||
oklch(from var(--text-color-secondary) l c h / 0.05);
|
||||
}
|
||||
@@ -13,7 +13,8 @@ body {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: var(--background);
|
||||
background: var(--header-background);
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
*,
|
||||
|
||||
@@ -1,112 +1,194 @@
|
||||
@use "../base/breakpoints";
|
||||
|
||||
/* -------------------------------------- */
|
||||
|
||||
.app-page-body {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
position: relative;
|
||||
display: grid;
|
||||
align-items: stretch;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
border: 1px solid transparent;
|
||||
margin-inline: var(--page-inset);
|
||||
isolation: isolate;
|
||||
flex-grow: 1;
|
||||
|
||||
.app-page-body__sidebar {
|
||||
@media (min-width: breakpoints.$tablet-breakpoint) {
|
||||
&--sticky {
|
||||
position: sticky;
|
||||
top: var(--header-height);
|
||||
align-self: flex-start;
|
||||
&:has(> .app-page-body__sidebar) {
|
||||
grid-template-columns: auto 1fr;
|
||||
}
|
||||
|
||||
@media (width < 740px) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
& > .app-page-body__sidebar {
|
||||
padding: var(--section-padding);
|
||||
|
||||
@media (width >= 740px) {
|
||||
width: 280px;
|
||||
|
||||
&:not(:has(.pane, .jenkins-card)) {
|
||||
position: sticky;
|
||||
top: calc(var(--header-height) + var(--jenkins-border-width));
|
||||
height: calc(100vh - var(--header-height) - var(--page-inset));
|
||||
overflow-y: auto;
|
||||
border-right: var(--jenkins-border);
|
||||
}
|
||||
}
|
||||
|
||||
@media (width > breakpoints.$tablet-breakpoint) {
|
||||
width: 320px;
|
||||
}
|
||||
}
|
||||
|
||||
& > .app-page-body__contents {
|
||||
padding: var(--section-padding);
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
// Remove this when sidepanels no longer contain widgets
|
||||
&:has(#side-panel .pane, #side-panel .jenkins-card) {
|
||||
& > .app-page-body__sidebar {
|
||||
padding-right: 0;
|
||||
|
||||
#tasks {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.jenkins-card,
|
||||
.pane-frame {
|
||||
margin-inline: -0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.app-main-panel {
|
||||
margin-bottom: var(--section-padding);
|
||||
|
||||
&--narrow {
|
||||
max-width: 900px;
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
&--wide {
|
||||
width: 70vw;
|
||||
max-width: 1700px;
|
||||
margin-inline: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.app-full-screen-page-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
|
||||
& > .app-page-body__contents {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.app-main-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
min-height: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Page frame
|
||||
.app-page-frame__background {
|
||||
position: relative;
|
||||
pointer-events: none;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: "";
|
||||
position: fixed;
|
||||
inset: var(--header-height) var(--page-inset) var(--page-inset)
|
||||
var(--page-inset);
|
||||
border-radius: var(--form-input-border-radius);
|
||||
}
|
||||
|
||||
&::before {
|
||||
--background: var(--card-background);
|
||||
|
||||
background-color: var(--card-background);
|
||||
background-image: linear-gradient(
|
||||
in oklch,
|
||||
var(--body-background-top),
|
||||
var(--background)
|
||||
);
|
||||
background-size: 100% 90vh;
|
||||
background-repeat: no-repeat;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
&::after {
|
||||
border: var(--jenkins-border);
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.app-page-frame__mask {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
mask:
|
||||
linear-gradient(#000 0 0),
|
||||
linear-gradient(#000 0 0) left calc(var(--page-inset) + 1px) top
|
||||
calc(var(--header-height) + 1px) /
|
||||
calc(100% - calc(var(--page-inset) + 1px) * 2)
|
||||
calc(
|
||||
100% - calc(var(--header-height) + 1px) - calc(var(--page-inset) + 1px)
|
||||
)
|
||||
no-repeat;
|
||||
mask-composite: exclude;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: var(--header-background);
|
||||
background-attachment: fixed;
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
|
||||
.app-page-frame__blur {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
backdrop-filter: blur(15px);
|
||||
}
|
||||
|
||||
&::before {
|
||||
top: 0;
|
||||
height: calc(var(--header-height) + var(--jenkins-border-width));
|
||||
}
|
||||
|
||||
&::after {
|
||||
bottom: 0;
|
||||
height: var(--page-inset);
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy
|
||||
#page-body.clear::after {
|
||||
clear: both;
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
|
||||
#side-panel {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
#main-panel {
|
||||
padding: 0 var(--section-padding) var(--section-padding)
|
||||
var(--section-padding);
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.app-page-body--one-column {
|
||||
--form-item-max-width: calc(85vw - 4rem);
|
||||
|
||||
@media screen and (width <= 1200px) {
|
||||
--form-item-max-width: 100%;
|
||||
}
|
||||
|
||||
max-width: 85vw;
|
||||
|
||||
#main-panel {
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.jenkins-section {
|
||||
max-width: unset;
|
||||
}
|
||||
|
||||
@media (width <= 1200px) {
|
||||
max-width: unset;
|
||||
}
|
||||
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
body.two-column #main-panel {
|
||||
width: calc(100% - var(--side-panel-width));
|
||||
flex: 1;
|
||||
display: block;
|
||||
}
|
||||
|
||||
body.full-screen {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body.full-screen #main-panel {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body.two-column #side-panel {
|
||||
width: var(--side-panel-width);
|
||||
}
|
||||
|
||||
@media (max-width: breakpoints.$tablet-breakpoint) {
|
||||
body.two-column #page-body {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
body.two-column #side-panel {
|
||||
width: 100%;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
body.two-column #main-panel {
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.app-project-status-table {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
@media (width >= 1170px) {
|
||||
body.two-column #main-panel {
|
||||
width: calc(
|
||||
100% - calc(var(--side-panel-width) + calc(var(--section-padding) * 2))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Clearfixes extracted from responsive-grid.css as they essential
|
||||
.clearfix::before,
|
||||
.clearfix::after,
|
||||
|
||||
@@ -3,13 +3,19 @@
|
||||
// clicks.
|
||||
// Keep this list in sync with the `position: sticky` rules across the SCSS sources.
|
||||
:root[data-disable-sticky="true"] {
|
||||
.app-page-frame__blur,
|
||||
.app-page-frame__mask,
|
||||
.app-page-frame__background {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jenkins-header,
|
||||
.jenkins-app-bar--sticky,
|
||||
.jenkins-bottom-app-bar__shadow,
|
||||
.bottom-sticker,
|
||||
#bottom-sticker,
|
||||
.app-page-body__sidebar--sticky,
|
||||
.app-plugin-manager__sidebar {
|
||||
.app-build-bar,
|
||||
.app-page-body__sidebar {
|
||||
position: relative !important;
|
||||
|
||||
// Reset the sticky offsets too — with relative positioning these would otherwise
|
||||
@@ -19,6 +25,12 @@
|
||||
bottom: auto !important;
|
||||
}
|
||||
|
||||
// Don't allow for sidebar scrolling
|
||||
.app-page-body__sidebar {
|
||||
overflow-y: visible !important;
|
||||
height: unset !important;
|
||||
}
|
||||
|
||||
// The bottom app bar shadow uses negative margins to overlap content; reset them so it
|
||||
// cannot intercept clicks when sticky positioning is disabled.
|
||||
.jenkins-bottom-app-bar__shadow {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 0.875rem;
|
||||
min-height: 2.875rem;
|
||||
min-height: 2.5rem;
|
||||
gap: var(--section-padding);
|
||||
flex-wrap: wrap;
|
||||
|
||||
@@ -68,23 +68,23 @@
|
||||
|
||||
&--sticky {
|
||||
position: sticky;
|
||||
top: var(--header-height);
|
||||
top: calc(var(--header-height) + 1.3125rem);
|
||||
z-index: 2;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: calc(var(--header-height) * -1)
|
||||
inset: calc(var(--section-padding) * -1)
|
||||
calc(var(--section-padding) * -1) -0.875rem;
|
||||
z-index: -1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&::before {
|
||||
background: var(--background);
|
||||
background: var(--body-background-top);
|
||||
mask-image: linear-gradient(black 70%, transparent);
|
||||
opacity: 0.55;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
&::after {
|
||||
@@ -106,7 +106,8 @@
|
||||
h1,
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: 1.3125rem;
|
||||
font-size: 1.1875rem;
|
||||
font-weight: 550;
|
||||
}
|
||||
|
||||
&__subtitle {
|
||||
@@ -126,6 +127,7 @@
|
||||
}
|
||||
|
||||
.jenkins-bottom-app-bar__shadow {
|
||||
--background: var(--card-background);
|
||||
--semi-translucent: color-mix(in sRGB, var(--background) 70%, transparent);
|
||||
|
||||
position: sticky;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
&__list {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
|
||||
& > * {
|
||||
z-index: 1;
|
||||
|
||||
@@ -6,10 +6,6 @@
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.page-footer .container-fluid {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.page-footer__flex-row {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
@@ -19,8 +15,6 @@
|
||||
.page-footer__flex-row > *:not(script) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: calc(var(--section-padding) / 2)
|
||||
calc(var(--section-padding) - 0.85rem);
|
||||
gap: calc(var(--section-padding) / 2);
|
||||
}
|
||||
|
||||
@@ -32,16 +26,3 @@
|
||||
.page-footer span {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.page-footer .jenkins-button {
|
||||
transition: var(--standard-transition);
|
||||
|
||||
&:hover {
|
||||
color: var(--text-color) !important;
|
||||
}
|
||||
|
||||
svg,
|
||||
.jenkins-overflow-button__ellipsis {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,9 @@
|
||||
@use "../abstracts/mixins";
|
||||
|
||||
.jenkins-header {
|
||||
--background-opacity: 0%;
|
||||
--background-blur: 0;
|
||||
--border-opacity: 0%;
|
||||
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 999;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--section-padding);
|
||||
@@ -16,26 +12,6 @@
|
||||
min-height: var(--header-height);
|
||||
color: var(--header-color);
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
backdrop-filter: blur(var(--background-blur));
|
||||
background: color-mix(
|
||||
in sRGB,
|
||||
var(--header-background) var(--background-opacity),
|
||||
transparent
|
||||
);
|
||||
border-bottom: var(--jenkins-border-width) solid
|
||||
color-mix(
|
||||
in sRGB,
|
||||
var(--header-border) var(--border-opacity),
|
||||
transparent
|
||||
);
|
||||
background-clip: padding-box;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.app-jenkins-logo {
|
||||
@include mixins.item($border: false);
|
||||
|
||||
@@ -79,7 +55,7 @@
|
||||
}
|
||||
|
||||
#jenkins-head-icon {
|
||||
width: 1.625rem;
|
||||
width: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,11 +67,6 @@
|
||||
// For customizable-header-plugin
|
||||
color: inherit !important;
|
||||
|
||||
svg {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 1.625rem;
|
||||
height: 1.625rem;
|
||||
@@ -121,7 +92,7 @@
|
||||
&__main {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
padding-left: var(--section-padding);
|
||||
padding-left: calc(var(--section-padding) + var(--page-inset));
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -135,14 +106,8 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
padding-right: var(--section-padding);
|
||||
}
|
||||
|
||||
&--has-sticky-app-bar {
|
||||
&::before {
|
||||
mask-image: linear-gradient(black 50%, transparent);
|
||||
}
|
||||
gap: 0.25rem;
|
||||
padding-right: calc(var(--section-padding) + var(--page-inset));
|
||||
}
|
||||
|
||||
&--no-breadcrumbs {
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
@use "../abstracts/mixins";
|
||||
@use "../base/breakpoints";
|
||||
|
||||
$background-outset: 0.5rem;
|
||||
$inset: 0.6875rem;
|
||||
|
||||
#tasks,
|
||||
.tasks,
|
||||
.subtasks {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0 var(--section-padding) var(--section-padding) var(--section-padding);
|
||||
gap: 0.125rem;
|
||||
|
||||
@media (min-width: breakpoints.$tablet-breakpoint) {
|
||||
margin-right: calc($background-outset);
|
||||
}
|
||||
}
|
||||
|
||||
.subtasks {
|
||||
@@ -27,12 +22,11 @@ $background-outset: 0.5rem;
|
||||
|
||||
#side-panel {
|
||||
.jenkins-app-bar {
|
||||
margin-left: var(--section-padding);
|
||||
margin-right: var(--section-padding);
|
||||
margin-inline: $inset;
|
||||
}
|
||||
|
||||
& > #tasks > .jenkins-search-container {
|
||||
margin: 0 0 1rem #{-$background-outset};
|
||||
margin: 0 0 1rem;
|
||||
|
||||
.jenkins-search__icon {
|
||||
width: 2.625rem;
|
||||
@@ -45,10 +39,6 @@ $background-outset: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
#tasks .task {
|
||||
margin: 0 0 0 calc($background-outset * -1);
|
||||
}
|
||||
|
||||
#tasks,
|
||||
.tasks {
|
||||
.task .task-link {
|
||||
@@ -57,7 +47,7 @@ $background-outset: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 0.5rem 0.6875rem;
|
||||
padding: 0.5rem $inset;
|
||||
gap: 0.625rem;
|
||||
width: 100%;
|
||||
font-size: var(--font-size-sm);
|
||||
@@ -115,7 +105,7 @@ $background-outset: 0.5rem;
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--text-color-secondary);
|
||||
font-weight: var(--font-bold-weight);
|
||||
margin: 1rem 0 0.375rem;
|
||||
margin: 1rem 0 0.375rem $inset;
|
||||
|
||||
&:first-of-type {
|
||||
margin-top: 0.375rem;
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#side-panel .pane-frame {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#side-panel .pane-header,
|
||||
.app-build-content .pane-header {
|
||||
font-size: var(--font-size-sm);
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
.app-build__grid {
|
||||
gap: calc(var(--section-padding) / 2);
|
||||
margin-bottom: calc(var(--section-padding) * -0.5);
|
||||
|
||||
& > * {
|
||||
height: 350px;
|
||||
@@ -139,101 +138,74 @@
|
||||
}
|
||||
}
|
||||
|
||||
body:has(.app-build-bar),
|
||||
body:has(.app-settings-container) {
|
||||
--top: color-mix(in sRGB, var(--text-color-secondary) 4%, var(--background));
|
||||
--bottom: color-mix(
|
||||
in sRGB,
|
||||
var(--text-color-secondary) 2%,
|
||||
var(--background)
|
||||
);
|
||||
@keyframes app-build-bar-border-on-scroll {
|
||||
from {
|
||||
border-bottom-color: color-mix(
|
||||
in sRGB,
|
||||
var(--jenkins-border-color),
|
||||
transparent
|
||||
);
|
||||
}
|
||||
|
||||
background: linear-gradient(var(--top), var(--bottom));
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.app-settings-container {
|
||||
--background: var(--card-background);
|
||||
--top: color-mix(
|
||||
in sRGB,
|
||||
var(--text-color-secondary) 2%,
|
||||
var(--card-background)
|
||||
);
|
||||
|
||||
position: relative;
|
||||
background-color: var(--card-background);
|
||||
background-image: linear-gradient(var(--top), var(--card-background));
|
||||
background-size: 100% 90vh;
|
||||
background-repeat: no-repeat;
|
||||
border: var(--jenkins-border);
|
||||
border-radius: var(--form-input-border-radius);
|
||||
z-index: 0;
|
||||
min-height: calc(100vh - var(--header-height) - var(--section-padding));
|
||||
|
||||
&__inner {
|
||||
max-width: 900px;
|
||||
margin: auto;
|
||||
padding: var(--section-padding);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&--wide {
|
||||
width: 70vw;
|
||||
max-width: 1700px;
|
||||
}
|
||||
|
||||
// TODO - this can be moved to app-bar.scss when Manage Jenkins flag is removed
|
||||
.jenkins-app-bar--sticky {
|
||||
padding: var(--section-padding) 0 !important;
|
||||
margin: -1rem 0 0.5rem !important;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
inset: 0 !important;
|
||||
}
|
||||
|
||||
&::before {
|
||||
background: color-mix(
|
||||
in sRGB,
|
||||
var(--text-color-secondary) 2%,
|
||||
var(--card-background)
|
||||
) !important;
|
||||
mask-image: linear-gradient(black 60%, transparent) !important;
|
||||
opacity: 0.75 !important;
|
||||
}
|
||||
|
||||
&::after {
|
||||
left: calc(var(--section-padding) * -1) !important;
|
||||
right: calc(var(--section-padding) * -1) !important;
|
||||
mask-image: linear-gradient(black 65%, transparent) !important;
|
||||
}
|
||||
}
|
||||
to {
|
||||
border-bottom-color: var(--jenkins-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
.app-build-bar {
|
||||
position: relative;
|
||||
--app-build-bar-border-color: color-mix(
|
||||
in sRGB,
|
||||
var(--jenkins-border-color),
|
||||
transparent
|
||||
);
|
||||
|
||||
position: sticky;
|
||||
top: calc(var(--header-height) + var(--jenkins-border-width));
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto 1fr;
|
||||
align-items: start;
|
||||
align-items: center;
|
||||
gap: 0.5rem 1.5rem;
|
||||
min-height: 2.875rem;
|
||||
margin-top: -5px;
|
||||
padding-bottom: 0.75rem;
|
||||
min-height: var(--header-height);
|
||||
background-color: color-mix(
|
||||
in oklch,
|
||||
transparent 25%,
|
||||
var(--body-background-top)
|
||||
);
|
||||
padding-inline: var(--section-padding);
|
||||
z-index: 102;
|
||||
|
||||
@media (width <= 1200px) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
border-bottom: var(--jenkins-border-width) solid
|
||||
var(--app-build-bar-border-color);
|
||||
margin-left: calc(var(--section-padding) * -1);
|
||||
margin-right: calc(var(--section-padding) * -1);
|
||||
border-top-left-radius: var(--form-input-border-radius);
|
||||
border-top-right-radius: var(--form-input-border-radius);
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -1000px calc(var(--section-padding) * -1) 0;
|
||||
background-color: var(--background);
|
||||
border-bottom: var(--jenkins-border-width) solid var(--card-border-color);
|
||||
inset: 0;
|
||||
z-index: -1;
|
||||
pointer-events: none;
|
||||
backdrop-filter: blur(15px);
|
||||
border-radius: inherit;
|
||||
}
|
||||
|
||||
@supports (animation-timeline: scroll()) {
|
||||
animation-name: app-build-bar-border-on-scroll;
|
||||
animation-duration: 1s;
|
||||
animation-fill-mode: both;
|
||||
animation-timing-function: linear;
|
||||
animation-timeline: scroll(nearest block);
|
||||
animation-range: 0 var(--header-height);
|
||||
}
|
||||
|
||||
@media (width < 740px) {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
padding-block: var(--section-padding);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.app-build-bar__content {
|
||||
@@ -247,6 +219,7 @@ body:has(.app-settings-container) {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-block: 0.5rem;
|
||||
}
|
||||
|
||||
.app-build-bar__controls {
|
||||
@@ -254,7 +227,7 @@ body:has(.app-settings-container) {
|
||||
align-items: center;
|
||||
justify-content: end;
|
||||
flex: 1;
|
||||
gap: 0.75rem;
|
||||
gap: 0.5rem;
|
||||
|
||||
@media (width <= 600px) {
|
||||
justify-content: stretch;
|
||||
@@ -278,12 +251,14 @@ body:has(.app-settings-container) {
|
||||
svg {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 0;
|
||||
font-size: 1.25rem;
|
||||
font-size: 1.1875rem;
|
||||
font-weight: 550;
|
||||
}
|
||||
|
||||
.jenkins-button {
|
||||
@@ -325,6 +300,10 @@ body:has(.app-settings-container) {
|
||||
}
|
||||
}
|
||||
|
||||
.app-page-body__contents:has(.app-build-bar) {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.app-build-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
@use "../abstracts/mixins";
|
||||
|
||||
#side-panel {
|
||||
#buildHistoryPage {
|
||||
margin: 10px 0 10px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
#buildHistoryPage {
|
||||
.jenkins-search {
|
||||
margin-inline: -0.25rem;
|
||||
|
||||
@@ -104,13 +104,3 @@
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
}
|
||||
|
||||
.app-plugin-manager__sidebar {
|
||||
position: sticky;
|
||||
top: calc(40px + 1.6rem);
|
||||
|
||||
h1 {
|
||||
margin-top: 1rem !important;
|
||||
margin-bottom: 0.1rem !important;
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,6 @@ class ErrorPageTest {
|
||||
final String content = ex.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
assertThat(content, not(containsString(j.contextPath + "/login?from=")));
|
||||
assertThat(content, containsString("This page does not exist."));
|
||||
assertThat(content, not(containsString("REST API")));
|
||||
}
|
||||
|
||||
{ // paths are fine on error page even when nested
|
||||
@@ -66,7 +65,6 @@ class ErrorPageTest {
|
||||
final String content = ex.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
assertThat(content, not(containsString(j.contextPath + "/login?from=")));
|
||||
assertThat(content, containsString("This page does not exist."));
|
||||
assertThat(content, not(containsString("REST API")));
|
||||
}
|
||||
|
||||
{ // resource root action have custom (less) error message content
|
||||
@@ -76,7 +74,6 @@ class ErrorPageTest {
|
||||
assertThat(content, not(containsString(j.contextPath + "/login?from=")));
|
||||
assertThat(content, not(containsString("This page does not exist.")));
|
||||
assertThat(content, not(containsString("This page may not exist, or you may not have permission to see it.")));
|
||||
assertThat(content, not(containsString("REST API")));
|
||||
}
|
||||
|
||||
/* Set up security realm and request as anonymous, we expect login link and hedged response */
|
||||
@@ -90,7 +87,6 @@ class ErrorPageTest {
|
||||
assertThat(content, containsString(j.contextPath + "/login?from=" + j.contextPath.replace("/", "%2F") + "%2Ffoo"));
|
||||
assertThat(content, not(containsString(j.contextPath + "/login?from=" + j.contextPath.replace("/", "%2F") + "%2F404")));
|
||||
assertThat(content, containsString("This page may not exist, or you may not have permission to see it."));
|
||||
assertThat(content, not(containsString("REST API")));
|
||||
}
|
||||
|
||||
{ // paths are fine on error page even when nested
|
||||
@@ -100,7 +96,6 @@ class ErrorPageTest {
|
||||
assertThat(content, containsString(j.contextPath + "/login?from=" + j.contextPath.replace("/", "%2F") + "%2Ffoo%2Fbar%2Fbaz%2F"));
|
||||
assertThat(content, not(containsString(j.contextPath + "/login?from=" + j.contextPath.replace("/", "%2F") + "%2F404")));
|
||||
assertThat(content, containsString("This page may not exist, or you may not have permission to see it."));
|
||||
assertThat(content, not(containsString("REST API")));
|
||||
}
|
||||
|
||||
{ // resource root action have custom (less) error message content
|
||||
@@ -111,7 +106,6 @@ class ErrorPageTest {
|
||||
assertThat(content, not(containsString(j.contextPath + "/login?from=" + j.contextPath.replace("/", "%2F") + "%2F404")));
|
||||
assertThat(content, not(containsString("This page does not exist.")));
|
||||
assertThat(content, not(containsString("This page may not exist, or you may not have permission to see it.")));
|
||||
assertThat(content, not(containsString("REST API")));
|
||||
}
|
||||
|
||||
/* With the security realm still set up, log in and expect the profile link to show */
|
||||
@@ -124,7 +118,6 @@ class ErrorPageTest {
|
||||
assertThat(content, not(containsString(j.contextPath + "/login?from=")));
|
||||
assertThat(content, containsString("user/alice"));
|
||||
assertThat(content, containsString("This page may not exist, or you may not have permission to see it."));
|
||||
assertThat(content, not(containsString("REST API")));
|
||||
}
|
||||
|
||||
{ // paths are fine on error page even when nested
|
||||
@@ -134,7 +127,6 @@ class ErrorPageTest {
|
||||
assertThat(content, not(containsString(j.contextPath + "/login?from=")));
|
||||
assertThat(content, containsString("user/alice"));
|
||||
assertThat(content, containsString("This page may not exist, or you may not have permission to see it."));
|
||||
assertThat(content, not(containsString("REST API")));
|
||||
}
|
||||
|
||||
{ // resource root action have custom (less) error message content
|
||||
@@ -145,7 +137,6 @@ class ErrorPageTest {
|
||||
assertThat(content, containsString("user/alice"));
|
||||
assertThat(content, not(containsString("This page does not exist.")));
|
||||
assertThat(content, not(containsString("This page may not exist, or you may not have permission to see it.")));
|
||||
assertThat(content, not(containsString("REST API")));
|
||||
}
|
||||
} finally {
|
||||
Dispatcher.TRACE = true;
|
||||
@@ -176,13 +167,11 @@ class ErrorPageTest {
|
||||
final String content = page.getWebResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
assertThat(content, containsString("Back to Jenkins"));
|
||||
assertThat(content, containsString("Jenkins serves only static files on this domain."));
|
||||
assertThat(content, not(containsString("REST API")));
|
||||
if (page.isHtmlPage()) {
|
||||
final HtmlPage htmlPage = (HtmlPage) page;
|
||||
final Page nextPage = htmlPage.getAnchorByText("Back to Jenkins").click();
|
||||
final String nextContent = nextPage.getWebResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
assertThat(nextContent, containsString("Welcome to Jenkins"));
|
||||
assertThat(nextContent, containsString("REST API")); // Rest API exists for Jenkins main page
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user