Skip to content

Commit

Permalink
Allow formatted markup for node descriptions (#6511)
Browse files Browse the repository at this point in the history
Co-authored-by: Adrien Lecharpentier <[email protected]>
Co-authored-by: Daniel Beck <[email protected]>
Co-authored-by: Alexander Brandes <[email protected]>
Co-authored-by: Daniel Beck <[email protected]>
Co-authored-by: Basil Crow <[email protected]>
Co-authored-by: Tim Jacomb <[email protected]>
Co-authored-by: Tim Jacomb <[email protected]>
  • Loading branch information
8 people authored Jan 2, 2023
1 parent 4dda635 commit 5522f60
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 26 deletions.
17 changes: 17 additions & 0 deletions core/src/main/java/hudson/slaves/SlaveComputer.java
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,23 @@ public List<LogRecord> getLogRecords() throws IOException, InterruptedException
return channel.call(new SlaveLogFetcher());
}

/**
* Inline editing of description
*/
@RequirePOST
@Restricted(NoExternalUse.class)
public synchronized void doSubmitDescription(StaplerResponse rsp, @QueryParameter String description) throws IOException {
checkPermission(CONFIGURE);

final Slave node = this.getNode();
if (node != null) {
node.setNodeDescription(description);
} else { // Node has been disabled/removed during other session tries to change the description.
throw new IOException("Description will be not set. The node " + nodeName + " does not exist (anymore).");
}
rsp.sendRedirect(".");
}

@RequirePOST
public HttpResponse doDoDisconnect(@QueryParameter String offlineMessage) {
if (channel != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,19 @@ THE SOFTWARE.
<j:if test="${it.getPrimaryView() != null}">
<j:set var="it" value="${it.getPrimaryView()}"/>
</j:if>
<j:set var="submissionUrl" value="${request.getParameter('submissionUrl')}" defaultValue="submitDescription"/>
<j:invokeStatic className="hudson.Util" method="isSafeToRedirectTo" var="isSafeToRedirectTo">
<j:arg value="${submissionUrl}"/>
</j:invokeStatic>
<j:if test="${!isSafeToRedirectTo}">
<j:set var="submissionUrl" value="submitDescription"/>
</j:if>
<j:set var="initialDescription" value="${request.getParameter('description')}" defaultValue="${it.description}"/>
<l:ajax>
<form action="submitDescription" method="post">
<form action="${submissionUrl}" method="post">
<table>
<f:entry help="${app.markupFormatter.helpUrl}">
<f:textarea name="description" value="${it.description}"
<f:textarea name="description" value="${initialDescription}"
codemirror-mode="${app.markupFormatter.codeMirrorMode}" codemirror-config="${app.markupFormatter.codeMirrorConfig}" previewEndpoint="/markupFormatter/previewDescription"/>
</f:entry>
</table>
Expand Down
11 changes: 11 additions & 0 deletions core/src/main/resources/hudson/model/Computer/index-top.jelly
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:t="/lib/hudson">
<!-- Node name and status -->
<h1>
<l:icon src="${it.iconClassName}" class="icon-xlg" />
${it.caption}
</h1>

<!-- Node description -->
<t:editableDescription permission="${it.CONFIGURE}" description="${it.node.nodeDescription}" submissionUrl="submitDescription" />
</j:jelly>
11 changes: 1 addition & 10 deletions core/src/main/resources/hudson/model/Computer/index.jelly
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ THE SOFTWARE.
<st:include page="sidepanel.jelly" />
<!-- no need for additional breadcrumb here as we're on an index page already including breadcrumb -->
<l:main-panel>
<st:include page="index-top.jelly" it="${it}" />

<!-- temporarily offline switch -->
<div style="float:right">
Expand All @@ -53,16 +54,6 @@ THE SOFTWARE.
</j:choose>
</div>

<h1>
<span class="icon-lg">
<l:icon src="${it.iconClassName}" />
</span>
${it.caption}
<j:if test="${!empty(it.node.nodeDescription)}">
<span style="font-size:smaller">(${it.node.nodeDescription})</span>
</j:if>
</h1>

<j:if test="${it.offlineCause!=null and it.offline and !it.connecting}">
<st:include it="${it.offlineCause}" page="cause.jelly" />
</j:if>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ 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">
<f:entry title="${%Description}" help="/help/system-config/master-slave/description.html">
<f:textbox field="nodeDescription" />
</f:entry>
<div class="jenkins-section">
<f:entry title="${%Description}" help="/help/system-config/master-slave/description.html">
<f:textarea name="nodeDescription" value="${it.nodeDescription}" codemirror-mode="${app.markupFormatter.codeMirrorMode}" codemirror-config="${app.markupFormatter.codeMirrorConfig}" previewEndpoint="/markupFormatter/previewDescription"/>
</f:entry>
</div>

<f:entry title="${%Number of executors}" field="numExecutors">
<f:number clazz="positive-number-required" min="1" step="1" default="1"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,8 @@ THE SOFTWARE.
<h1>
<span class="icon-lg">
<l:icon src="${it.icon}"/>
</span>
${it.caption} ${%System Information}
<j:if test="${!empty(it.node.nodeDescription)}">
<span style="font-size:smaller">(${it.node.nodeDescription})</span>
</j:if>
</span>${it.caption}
${%System Information}
</h1>

<j:choose>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout">
<!-- Node name and status -->
<h1>
<l:icon src="${it.iconClassName}" class="icon-xlg" />
${it.caption}
</h1>

<!-- Node description -->
<div class="jenkins-!-margin-bottom-5">
${%blurb}
</div>
</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
blurb = This is the Jenkins controller''s built-in node. \
Builds running on this node will execute on the same system and as the same user as the Jenkins controller. \
This is appropriate e.g. for special jobs performing backups, but in general you should run builds on agents. \
<a rel="noopener noreferrer nofollow" target="_blank" href="http://www.jenkins.io/redirect/distributed-builds/">Learn more about distributed builds.</a>
16 changes: 16 additions & 0 deletions core/src/main/resources/lib/hudson/editable-description.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* global replaceDescription */
(function () {
document.addEventListener("DOMContentLoaded", function () {
let descriptionLink = document.querySelector("#description-link");
descriptionLink.addEventListener("click", function (e) {
e.preventDefault();
let url = descriptionLink.getAttribute("data-url");
let description = descriptionLink.getAttribute("data-description");
if (url == null && description == null) {
return replaceDescription();
} else {
return replaceDescription(description, url);
}
});
});
})();
21 changes: 16 additions & 5 deletions core/src/main/resources/lib/hudson/editableDescription.jelly
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,30 @@ THE SOFTWARE.
If the current user doesn't have this permission, the description
is not editable.
</st:attribute>
<st:attribute name="description">
Optional value of the description. If not specified, will use '${it.description}'.
</st:attribute>
<st:attribute name="submissionUrl">
Optional submission URL. If not specified, will use 'submitDescription'.
</st:attribute>
</st:documentation>

<div id="description">
<j:set var="actualDescription" value="${description}" defaultValue="${it.description}"/>

<div id="description" class="jenkins-!-margin-bottom-0">
<div>
<j:out value="${it.description!=null ? app.markupFormatter.translate(it.description) : ''}" />
<j:out value="${actualDescription!=null ? app.markupFormatter.translate(actualDescription) : ''}" />
</div>

<l:hasPermission permission="${permission}">
<div class="jenkins-buttons-row jenkins-buttons-row--invert">
<a class="jenkins-button jenkins-button--tertiary" id="description-link" href="editDescription" onclick="return replaceDescription();">
<l:icon src="symbol-edit" />
<st:adjunct includes="lib.hudson.editable-description"/>
<a class="jenkins-button jenkins-button--tertiary" id="description-link" href="editDescription" data-description="${actualDescription}" data-url="${submissionUrl}">
<span class="leading-icon">
<l:icon src="symbol-edit" />
</span>
<j:choose>
<j:when test="${empty(it.description)}">
<j:when test="${empty(actualDescription)}">
${%add description}
</j:when>
<j:otherwise>
Expand Down
10 changes: 9 additions & 1 deletion war/src/main/webapp/scripts/hudson-behavior.js
Original file line number Diff line number Diff line change
Expand Up @@ -1841,10 +1841,18 @@ function xor(a, b) {
}

// used by editableDescription.jelly to replace the description field with a form
function replaceDescription() {
function replaceDescription(initialDescription, submissionUrl) {
var d = document.getElementById("description");
$(d).down().next().innerHTML = "<div class='jenkins-spinner'></div>";
let parameters = {};
if (initialDescription !== undefined && submissionUrl !== undefined) {
parameters = {
description: initialDescription,
submissionUrl: submissionUrl,
};
}
new Ajax.Request("./descriptionForm", {
parameters: parameters,
onComplete: function (x) {
d.innerHTML = x.responseText;
evalInnerHtmlScripts(x.responseText, function () {
Expand Down

0 comments on commit 5522f60

Please sign in to comment.