Skip to content

Commit

Permalink
[JENKINS-32936] Support for multiple layouts in Jelly Layout tag (#2253)
Browse files Browse the repository at this point in the history
* [JENKINS-32936] Initial source code modifications

* [JENKINS-32936] Three views are using this approach

* [JENKINS-32936] Conflicts were resolved in a wrong way
  • Loading branch information
recena authored and oleg-nenashev committed May 5, 2016
1 parent 31ad770 commit cb058a1
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 261 deletions.
71 changes: 37 additions & 34 deletions core/src/main/resources/hudson/AboutJenkins/index.jelly
Expand Up @@ -25,44 +25,47 @@ THE SOFTWARE.
<!-- 3rd party license acknowledgements and -->
<?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:s="/lib/form">
<l:layout title="${%about(app.VERSION)}" norefresh="true">
<l:main-panel>
<h1 version="${app.VERSION}">${%about(app.VERSION)}</h1>
<p>
${%blurb}
</p>

<p>
${%dependencies}
</p>
<j:set var="uri" value="${it.licensesURL}"/>
<j:choose>
<j:when test="${uri != null}">
<l:layout norefresh="true" type="one-column" title="${%about(app.VERSION)}">

<l:main-panel>
<div class="container-fluid">
<div class="row">
<div class="col-md-24">
<h1 version="${app.VERSION}">${%about(app.VERSION)}</h1>
<p>${%blurb}</p>
<p>${%dependencies}</p>
<j:set var="uri" value="${it.licensesURL}"/>
<j:choose>
<j:when test="${uri != null}">
<t:thirdPartyLicenses>
<j:include uri="${uri}"/>
<j:include uri="${uri}"/>
</t:thirdPartyLicenses>
</j:when>
<j:otherwise>
</j:when>
<j:otherwise>
<p>${%No information recorded}</p>
</j:otherwise>
</j:choose>
<p>${%plugin.dependencies}</p>
<ul>
<j:forEach var="p" items="${app.pluginManager.plugins}"> <!-- TODO sort -->
<li>
<a href="${rootURL}/pluginManager/plugin/${p.shortName}/thirdPartyLicenses">
<j:choose>
<j:when test="${p.active}">
${p.displayName}
</j:when>
<j:otherwise>
<strike>${p.displayName}</strike>
</j:otherwise>
</j:choose>
</a>
</li>
</j:forEach>
</ul>
</j:otherwise>
</j:choose>
<p>${%plugin.dependencies}</p>
<ul>
<j:forEach var="p" items="${app.pluginManager.plugins}"> <!-- TODO sort -->
<li>
<a href="${rootURL}/pluginManager/plugin/${p.shortName}/thirdPartyLicenses">
<j:choose>
<j:when test="${p.active}">
${p.displayName}
</j:when>
<j:otherwise>
<strike>${p.displayName}</strike>
</j:otherwise>
</j:choose>
</a>
</li>
</j:forEach>
</ul>
</div>
</div>
</div>
</l:main-panel>
</l:layout>
</j:jelly>
68 changes: 39 additions & 29 deletions core/src/main/resources/hudson/model/Job/configure.jelly
Expand Up @@ -27,41 +27,51 @@ 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:layout title="${it.displayName} Config" cssclass="main-panel-only" norefresh="true" permission="${it.EXTENDED_READ}">

<l:layout norefresh="true" type="one-column" permission="${it.EXTENDED_READ}" title="${it.displayName} Config">

<l:js src="jsbundles/config-scrollspy.js" />
<l:css src="jsbundles/config-scrollspy.css" />

<l:main-panel>
<l:js src="jsbundles/config-scrollspy.js" />
<l:css src="jsbundles/config-scrollspy.css" />
<div class="container">
<div class="row">
<div class="col-md-offset-2 col-md-20">

<div class="behavior-loading">${%LOADING}</div>

<div class="behavior-loading">${%LOADING}</div>
<f:form method="post" action="configSubmit" name="config" tableClass="config-table scrollspy">
<j:set var="descriptor" value="${it.descriptor}" />
<j:set var="instance" value="${it}" />
<f:form method="post" action="configSubmit" name="config" tableClass="config-table scrollspy">
<j:set var="descriptor" value="${it.descriptor}" />
<j:set var="instance" value="${it}" />

<j:if test="${it.isNameEditable()}">
<f:entry title="${%name(it.pronoun)}">
<f:textbox name="name" value="${it.name}" />
</f:entry>
</j:if>
<f:entry title="${%Description}" help="${app.markupFormatter.helpUrl}">
<f:textarea name="description" value="${it.description}" codemirror-mode="${app.markupFormatter.codeMirrorMode}" codemirror-config="${app.markupFormatter.codeMirrorConfig}" previewEndpoint="/markupFormatter/previewDescription"/>
</f:entry>
<j:if test="${it.isNameEditable()}">
<f:entry title="${%name(it.pronoun)}">
<f:textbox name="name" value="${it.name}" />
</f:entry>
</j:if>
<f:entry title="${%Description}" help="${app.markupFormatter.helpUrl}">
<f:textarea name="description" value="${it.description}" codemirror-mode="${app.markupFormatter.codeMirrorMode}" codemirror-config="${app.markupFormatter.codeMirrorConfig}" previewEndpoint="/markupFormatter/previewDescription"/>
</f:entry>

<f:descriptorList field="properties" descriptors="${h.getJobPropertyDescriptors(it)}" forceRowSet="true"/>
<f:descriptorList field="properties" descriptors="${h.getJobPropertyDescriptors(it)}" forceRowSet="true"/>

<!-- additional entries from derived classes -->
<st:include page="configure-entries.jelly" />
<!-- additional entries from derived classes -->
<st:include page="configure-entries.jelly" />

<j:if test="${h.hasPermission(it,it.CONFIGURE)}">
<f:bottomButtonBar>
<!--<input type="button" name="StructureTest" value="Test" onclick="buildFormTree(this.form)" />-->
<f:submit value="${%Save}"/>
<f:apply value="${%Apply}"/>
</f:bottomButtonBar>
</j:if>
</f:form>
<j:if test="${h.hasPermission(it,it.CONFIGURE)}">
<st:adjunct includes="lib.form.confirm" />
</j:if>
<j:if test="${h.hasPermission(it,it.CONFIGURE)}">
<f:bottomButtonBar>
<!--<input type="button" name="StructureTest" value="Test" onclick="buildFormTree(this.form)" />-->
<f:submit value="${%Save}"/>
<f:apply value="${%Apply}"/>
</f:bottomButtonBar>
</j:if>
</f:form>
<j:if test="${h.hasPermission(it,it.CONFIGURE)}">
<st:adjunct includes="lib.form.confirm" />
</j:if>
</div>
</div>
</div>
</l:main-panel>
</l:layout>
</j:jelly>
65 changes: 34 additions & 31 deletions core/src/main/resources/hudson/model/View/newJob.jelly
Expand Up @@ -26,50 +26,53 @@ 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:s="/lib/form">
<j:getStatic var="permission" className="hudson.model.Item" field="CREATE"/>

<l:layout norefresh="true" cssclass="main-panel-only" permission="${permission}" title="${%NewJob(it.newPronoun)}">
<l:layout norefresh="true" type="one-column" permission="${permission}" title="${%NewJob(it.newPronoun)}">

<l:js src="jsbundles/add-item.js" />
<l:css src="jsbundles/add-item.css" />

<l:main-panel>
<div id="add-item-panel" style="display: none;">
<form method="post" action="createItem" name="createItem" id="createItem">
<div class="header">
<div class="add-item-name">
<label for="name">${%ItemName.label}</label>
<input name="name" id="name" type="text" tabindex="0" />
<div class="input-help">&#187; ${%ItemName.help}</div>
<div id="itemname-required" class="input-validation-message input-message-disabled">&#187; ${%ItemName.validation.required}</div>
<div id="itemname-invalid" class="input-validation-message input-message-disabled"></div>
<div id="itemtype-required" class="input-validation-message input-message-disabled">&#187; ${%ItemType.validation.required}</div>
<div class="container" id="add-item-panel" style="display: none;">
<div class="row">
<div class="col-md-offset-2 col-md-20">
<form method="post" action="createItem" name="createItem" id="createItem">
<div class="header">
<div class="add-item-name">
<label for="name">${%ItemName.label}</label>
<input name="name" id="name" type="text" tabindex="0" />
<div class="input-help">&#187; ${%ItemName.help}</div>
<div id="itemname-required" class="input-validation-message input-message-disabled">&#187; ${%ItemName.validation.required}</div>
<div id="itemname-invalid" class="input-validation-message input-message-disabled"></div>
<div id="itemtype-required" class="input-validation-message input-message-disabled">&#187; ${%ItemType.validation.required}</div>
</div>
</div>
</div>

<div class="categories flat" role="radiogroup" aria-labelledby="Items"/>
<div class="categories flat" role="radiogroup" aria-labelledby="Items" />

<j:if test="${!empty(app.itemMap)}">
<div class="item-copy">
<p class="description">${%CopyOption.description}:</p>
<div class="add-item-copy">
<input type="radio" name="mode" value="copy" />
<div class="icon">
<img src="${resURL}/images/48x48/copy.png" />
<j:if test="${!empty(app.itemMap)}">
<div class="item-copy">
<p class="description">${%CopyOption.description}:</p>
<div class="add-item-copy">
<input type="radio" name="mode" value="copy" />
<div class="icon">
<img src="${resURL}/images/48x48/copy.png" />
</div>
<label>${%CopyOption.label}</label>
<j:set var="descriptor" value="${it.descriptor}" />
<s:textbox id="from" name="from" placeholder="${%CopyOption.placeholder}" field="copyNewItemFrom"/>
</div>
<label>${%CopyOption.label}</label>
<j:set var="descriptor" value="${it.descriptor}" />
<s:textbox id="from" name="from" placeholder="${%CopyOption.placeholder}" field="copyNewItemFrom"/>
</div>
</div>
</j:if>
</j:if>

<div class="footer">
<div class="btn-decorator">
<button type="submit" id="ok-button">OK</button>
<div class="footer">
<div class="btn-decorator">
<button type="submit" id="ok-button">OK</button>
</div>
</div>
</div>
</form>
</form>
</div>
</div>

</div>
</l:main-panel>
</l:layout>
</j:jelly>
67 changes: 36 additions & 31 deletions core/src/main/resources/lib/layout/layout.jelly
Expand Up @@ -37,24 +37,24 @@ THE SOFTWARE.
If non-null and not "false", auto refresh is disabled on this page.
This is necessary for pages that include forms.
</st:attribute>
<st:attribute name="cssclass">
A css class name to include in the body element.
</st:attribute>
<st:attribute name="css" deprecated="true">
specify path that starts from "/" for loading additional CSS stylesheet.
path is interprted as relative to the context root. e.g.,
path is interpreted as relative to the context root. e.g.,

{noformat}&lt;l:layout css="/plugin/mysuperplugin/css/myneatstyle.css">{noformat}

This was originally added to allow plugins to load their stylesheets, but
*the use of thie attribute is discouraged now.*
*the use of the attribute is discouraged now.*
plugins should now do so by inserting &lt;style> elements and/or &lt;script> elements
in &lt;l:header/> tag.
</st:attribute>
<st:attribute name="permission">
If given, this page is only made available to users that has the specified permission.
(The permission will be checked against the "it" object.)
</st:attribute>
<st:attribute name="type" use="optional">
Available values: two-column (by default) or one-column (full-width size).
</st:attribute>
</st:documentation>
<st:setHeader name="Expires" value="0" />
<st:setHeader name="Cache-Control" value="no-cache,no-store,must-revalidate" />
Expand All @@ -69,18 +69,21 @@ ${h.initPageVariables(context)}
this also allows us to configure HttpSessionContextIntegrationFilter not to create sessions,
which I suspect can end up creating sessions for wrong resource types (such as static resources.)
-->
<j:if test="${attrs.type==null}">
<j:set var="layoutType" value="two-column"/>
</j:if>
<j:set var="isMSIE" value="${userAgent.contains('MSIE')}"/>
<j:set var="_" value="${request.getSession()}"/>
<j:set var="_" value="${h.configureAutoRefresh(request, response, attrs.norefresh!=null and !attrs.norefresh.equals(false))}"/>
<j:set var="extensionsAvailable" value="${h.extensionsAvailable}"/>
<j:if test="${request.servletPath=='/' || request.servletPath==''}">
${h.advertiseHeaders(response)}
<j:if test="${extensionsAvailable}">
<j:forEach var="pd" items="${h.pageDecorators}">
<st:include it="${pd}" page="httpHeaders.jelly" optional="true"/>
</j:forEach>
</j:if>
<j:set var="extensionsAvailable" value="${h.extensionsAvailable}"/>
<j:if test="${request.servletPath=='/' || request.servletPath==''}">
${h.advertiseHeaders(response)}
<j:if test="${extensionsAvailable}">
<j:forEach var="pd" items="${h.pageDecorators}">
<st:include it="${pd}" page="httpHeaders.jelly" optional="true"/>
</j:forEach>
</j:if>
</j:if>
<x:doctype name="html" />
<html>
<head data-rooturl="${rootURL}" data-resurl="${resURL}" resURL="${resURL}">
Expand All @@ -91,6 +94,7 @@ ${h.initPageVariables(context)}
</j:if>

<title>${h.appendIfNotNull(title, ' [Jenkins]', 'Jenkins')}</title>
<link rel="stylesheet" href="${resURL}/css/layout-common.css" type="text/css" />
<link rel="stylesheet" href="${resURL}/css/style.css" type="text/css" />
<link rel="stylesheet" href="${resURL}/css/color.css" type="text/css" />
<link rel="stylesheet" href="${resURL}/css/responsive-grid.css" type="text/css" />
Expand All @@ -107,8 +111,7 @@ ${h.initPageVariables(context)}
<script src="${resURL}/scripts/behavior.js" type="text/javascript"/>

<!-- we include our own prototype.js, so don't let stapler pull in another. -->
<st:adjunct assumes="org.kohsuke.stapler.framework.prototype.prototype"
includes="org.kohsuke.stapler.bind"/>
<st:adjunct assumes="org.kohsuke.stapler.framework.prototype.prototype" includes="org.kohsuke.stapler.bind"/>

<!-- To use the debug version of YUI, set the system property 'debug.YUI' to true -->
<j:set var="yuiSuffix" value="${h.yuiSuffix}" />
Expand Down Expand Up @@ -165,7 +168,7 @@ ${h.initPageVariables(context)}
<script src="${resURL}/jsbundles/page-init.js" type="text/javascript"/>

</head>
<body id="jenkins" class="yui-skin-sam jenkins-${h.version} ${attrs.cssclass}" data-version="${h.version}" data-model-type="${it.class.name}">
<body id="jenkins" class="yui-skin-sam jenkins-${h.version} ${layoutType}" data-version="${h.version}" data-model-type="${it.class.name}">
<!-- for accessibility, skip the entire navigation bar and etc and go straight to the head of the content -->
<a href="#skip2content" class="skiplink">Skip to content</a>

Expand Down Expand Up @@ -233,21 +236,23 @@ ${h.initPageVariables(context)}
</div>

<div id="page-body" class="clear">
<div id="side-panel">
<j:set var="mode" value="side-panel" />
<d:invokeBody />

<!-- add YUI logger if debugging YUI -->
<j:if test="${h.yuiSuffix=='debug'}">
<div id="yui-logreader" style="margin-top:1em"/>
<script>
Behaviour.addLoadEvent(function(){
var logReader = new YAHOO.widget.LogReader("yui-logreader");
logReader.collapse();
});
</script>
</j:if>
</div>
<j:if test="${layoutType=='two-column'}">
<div id="side-panel">
<j:set var="mode" value="side-panel" />
<d:invokeBody />

<!-- add YUI logger if debugging YUI -->
<j:if test="${h.yuiSuffix=='debug'}">
<div id="yui-logreader" style="margin-top:1em"/>
<script>
Behaviour.addLoadEvent(function(){
var logReader = new YAHOO.widget.LogReader("yui-logreader");
logReader.collapse();
});
</script>
</j:if>
</div>
</j:if>
<div id="main-panel">
<j:set var="mode" value="main-panel" />
<d:invokeBody/>
Expand Down
7 changes: 6 additions & 1 deletion core/src/main/resources/lib/layout/side-panel.jelly
Expand Up @@ -23,8 +23,13 @@ THE SOFTWARE.
-->

<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:s="jelly:stapler" xmlns:d="jelly:define">
<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:documentation>

<j:if test="${mode=='side-panel'}">
<d:invokeBody />
</j:if>

</j:jelly>
2 changes: 1 addition & 1 deletion core/src/main/resources/lib/layout/taglib
@@ -1 +1 @@
Tag library that defines the basic layout of Hudson pages.
Tag library that defines the basic layouts of Jenkins pages.

0 comments on commit cb058a1

Please sign in to comment.