Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for more flexible layouts in layout.jelly #8794

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -27,8 +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">
<l:layout permissions="${app.MANAGE_AND_SYSTEM_READ}" title="${%System}" type="one-column">
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One issue with the current approach is that there can be a mismatch between the page type and it's contents - on the Configure page it includes a sidebar however it isn't displayed due to the type being set to one-column. The inverse could be true as well where the page type is two-column but a side panel hasn't been provided.

<st:include page="sidepanel.jelly" />
<l:layout permissions="${app.MANAGE_AND_SYSTEM_READ}" title="${%System}">
<f:breadcrumb-config-outline title="${%System}" />

<l:main-panel>
Expand Down
20 changes: 9 additions & 11 deletions core/src/main/resources/lib/layout/app-bar.jelly
Expand Up @@ -34,16 +34,14 @@ THE SOFTWARE.
Generates a row containing the page title and an optional set of controls
</st:documentation>

<j:if test="${mode=='main-panel' or mode=='side-panel'}">
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if condition wasn't needed so I've removed it.

<div class="jenkins-app-bar">
<div class="jenkins-app-bar__content">
<x:element name="${headingLevel ?: 'h1'}">
${title}
</x:element>
</div>
<div class="jenkins-app-bar__controls">
<d:invokeBody/>
</div>
<div class="jenkins-app-bar">
<div class="jenkins-app-bar__content">
<x:element name="${headingLevel ?: 'h1'}">
${title}
</x:element>
</div>
</j:if>
<div class="jenkins-app-bar__controls">
<d:invokeBody/>
</div>
</div>
</j:jelly>
12 changes: 3 additions & 9 deletions core/src/main/resources/lib/layout/layout.jelly
Expand Up @@ -58,7 +58,7 @@ THE SOFTWARE.
(The permissions will be checked against the "it" object.)
</st:attribute>
<st:attribute name="type" use="optional">
Available values: two-column (by default), one-column (full-width size) or full-screen (since 2.53).
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type attribute now only works if it's set to full-screen.

Set to 'full-screen' to hide the navigation bar, breadcrumb bar and footer
</st:attribute>
<st:attribute name="nogrid" use="optional">
Do not include Bootstrap 3 grid. When a plugin wants to use a more recent version of Bootstrap then
Expand Down Expand Up @@ -191,14 +191,8 @@ THE SOFTWARE.
</j:if>

<div id="page-body" class="app-page-body app-page-body--${layoutType} clear">
<j:if test="${layoutType=='two-column'}">
<j:set var="mode" value="side-panel" />
<d:invokeBody />
Comment on lines -196 to -197
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaks all context menus, see ModelObjectWithContextMenu.ContextMenu#from.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Fixed it and added a comment to side-panel.jelly

</j:if>
<div id="main-panel">
<j:set var="mode" value="main-panel" />
<d:invokeBody/>
</div>
<j:set var="mode" value="main" />
<d:invokeBody />
</div>

<j:if test="${layoutType!='full-screen'}">
Expand Down
64 changes: 33 additions & 31 deletions core/src/main/resources/lib/layout/main-panel.jelly
Expand Up @@ -28,36 +28,38 @@ THE SOFTWARE.
Generates the body as the main content part of a Jenkins page.
</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" />
<d:invokeBody />
<j:if test="${mode == 'main'}">
<div class="app-page-body__main-panel" id="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" />
<d:invokeBody />
</div>
</j:if>
</j:jelly>
9 changes: 4 additions & 5 deletions core/src/main/resources/lib/layout/side-panel.jelly
Expand Up @@ -26,22 +26,21 @@ 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' : ''}">
<d:invokeBody />
<j:if test="${mode == 'main'}">
<div id="side-panel" class="app-page-body__side-panel ${attrs.sticky == 'true' ? 'app-page-body__side-panel--sticky' : ''}">
<d:invokeBody />
<!-- add YUI logger if debugging YUI -->
<j:if test="${h.yuiSuffix=='debug'}">
<!-- script to transform this into the Logger Console is done in hudson-behavior.js -->
<div id="yui-logreader" style="margin-top:1em"/>
</j:if>
</div>
</j:if>

</j:jelly>
108 changes: 26 additions & 82 deletions war/src/main/scss/base/_layout-commons.scss
@@ -1,7 +1,5 @@
@use "../base/breakpoints";

/* --------------- header --------------- */

#page-header .logo {
margin-left: 1.2rem;
display: inline-flex;
Expand All @@ -23,102 +21,48 @@
margin-left: 0.25rem;
}

/* -------------------------------------- */

.app-page-body {
display: flex;
justify-content: flex-start;
align-items: stretch;
flex: 1 0 auto;
}
align-items: start;
padding: var(--section-padding);
gap: var(--section-padding);
min-height: calc(100vh - 110px);

&__side-panel {
width: 320px;
flex-shrink: 0;

.app-page-body__sidebar {
@media (min-width: breakpoints.$tablet-breakpoint) {
&--sticky {
position: sticky;
top: 44px;
align-self: flex-start;
top: 40px;
margin-top: calc(var(--section-padding) * -1);
padding-top: var(--section-padding);
}
}
}

#page-body.clear::after {
clear: both;
content: "";
display: table;
}

#side-panel {
flex-shrink: 0;
}

#main-panel {
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% - 320px);
flex: 1;
display: block;
}

body.full-screen {
padding: 0;
}

body.full-screen #main-panel {
padding: 0;
}

@media (max-width: breakpoints.$tablet-breakpoint) {
body.two-column #page-body {
flex-wrap: wrap;
@media (max-width: breakpoints.$tablet-breakpoint) {
width: 100%;
}
}

body.two-column #side-panel {
&__main-panel {
width: 100%;
border-right: none;
}

body.two-column #main-panel {
margin-left: 0;
width: 100%;
&:not(:has(&__side-panel)) {
.app-page-body__main-panel {
max-width: 1150px;
margin-inline: auto;
}
}
}

@media (width >= 1170px) {
body.two-column #side-panel {
width: 340px;
&--full-screen {
flex-direction: column;
padding: 0;
gap: 0;
}

body.two-column #main-panel {
width: calc(100% - 370px);
@media (max-width: breakpoints.$tablet-breakpoint) {
flex-direction: column;
}
}

Expand Down
4 changes: 0 additions & 4 deletions war/src/main/scss/base/_style.scss
Expand Up @@ -1095,10 +1095,6 @@ select.select-ajax-pending {
color: var(--alert-danger-text-color);
}

body.no-decoration #main-panel {
margin: 0 auto !important;
}

body.no-decoration #page-header,
body.no-decoration #side-panel,
body.no-decoration footer {
Expand Down
1 change: 0 additions & 1 deletion war/src/main/scss/components/_section.scss
Expand Up @@ -3,7 +3,6 @@
.jenkins-section {
border-top: 2px solid var(--panel-border-color);
padding: var(--section-padding) 0 0 0;
max-width: 1800px;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplified the styling, let's just fill the available width and let the parent container control how wide that can be.


&:first-of-type {
border-top: none;
Expand Down
13 changes: 1 addition & 12 deletions war/src/main/scss/components/_side-panel-tasks.scss
@@ -1,18 +1,13 @@
@use "../abstracts/mixins";
@use "../base/breakpoints";

$background-outset: 0.7rem;

#tasks,
.subtasks {
display: flex;
flex-direction: column;
margin: var(--section-padding);
gap: 5px;

@media (min-width: breakpoints.$tablet-breakpoint) {
margin-right: calc($background-outset);
}
margin-bottom: var(--section-padding);
}

.subtasks {
Expand All @@ -25,12 +20,6 @@ $background-outset: 0.7rem;
}

#side-panel {
.jenkins-app-bar {
margin-top: var(--section-padding);
margin-left: var(--section-padding);
margin-right: var(--section-padding);
}

& > #tasks > .jenkins-search-container {
margin-left: -$background-outset;
margin-right: -$background-outset;
Expand Down
3 changes: 2 additions & 1 deletion war/src/main/scss/components/_side-panel-widgets.scss
Expand Up @@ -4,7 +4,8 @@
border-radius: 1rem;
background: var(--card-background);
border: var(--card-border-width) solid var(--card-border-color);
margin-left: 10px;
margin-left: -0.7rem;
margin-right: -0.7rem;
margin-bottom: calc(var(--section-padding) / 2);
overflow: hidden;
}
Expand Down
5 changes: 0 additions & 5 deletions war/src/main/scss/form/_layout.scss
@@ -1,7 +1,3 @@
.jenkins-form {
max-width: var(--form-item-max-width);
}

.jenkins-fieldset {
border: none;
margin: 0;
Expand All @@ -13,7 +9,6 @@
}

.jenkins-form-item {
max-width: var(--form-item-max-width);
margin-bottom: var(--section-padding);

// Workaround for float:right button controls
Expand Down