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 formatted markup for node descriptions #6511

Merged
merged 34 commits into from
Jan 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
e7da6ca
markup formatted description for node
mPokornyETM Apr 23, 2022
fa64008
Merge branch 'master' into feature/nodeDescription
NotMyFault Apr 23, 2022
ed91cfe
markup node description
mPokornyETM Apr 25, 2022
0a0967a
Merge branch 'feature/nodeDescription' of https://github.com/mPokorny…
mPokornyETM Apr 25, 2022
b356957
node description in system info page
mPokornyETM Apr 26, 2022
d595371
fix padding for description field
mPokornyETM Apr 27, 2022
0f0a509
Merge branch 'jenkinsci:master' into feature/nodeDescription
mPokornyETM May 5, 2022
51dd1fb
comments
mPokornyETM May 24, 2022
25de136
Merge branch 'master' into feature/nodeDescription
NotMyFault Jun 9, 2022
966aa5d
use medium icon size
mPokornyETM Jun 10, 2022
a185f36
Update core/src/main/resources/hudson/model/Computer/index.jelly
mPokornyETM Jun 10, 2022
a318cf9
Merge branch 'master' into feature/nodeDescription
NotMyFault Jun 23, 2022
cbcf105
Merge branch 'jenkinsci:master' into feature/nodeDescription
mPokornyETM Jul 6, 2022
ca5adf9
built-in node description
mPokornyETM Jul 6, 2022
7a1643f
Merge branch 'master' into feature/nodeDescription
daniel-beck Jul 15, 2022
ae3e1c0
Split description of built-in node from other nodes', more descriptive
daniel-beck Jul 15, 2022
94d5752
Add inline editing of node description
daniel-beck Jul 15, 2022
00752ef
Merge pull request #20 from daniel-beck/feature/nodeDescription-inline
mPokornyETM Jul 30, 2022
3b7f3c9
Merge branch 'feature/nodeDescription2' of https://github.com/daniel-…
mPokornyETM Jul 30, 2022
75d87d1
Merge branch 'daniel-beck-feature/nodeDescription2' into feature/node…
mPokornyETM Jul 30, 2022
358c62a
error handling
mPokornyETM Jul 30, 2022
eb7d328
some style fixes
mPokornyETM Jul 30, 2022
4ecea00
use jenkins library style
mPokornyETM Aug 13, 2022
a62d088
PR review
mPokornyETM Aug 13, 2022
67438c7
Merge branch 'master' into feature/nodeDescription
daniel-beck Aug 16, 2022
acfbe38
Merge remote-tracking branch 'origin/master' into nodeDescription
basil Aug 25, 2022
4a8353f
Merge branch 'master' into feature/nodeDescription
basil Aug 25, 2022
37d2121
Thanks Spotless
daniel-beck Aug 26, 2022
404b103
This was fun because we have no documentation for any of this
daniel-beck Aug 26, 2022
15ccece
Merge branch 'master' into feature/nodeDescription
mPokornyETM Nov 2, 2022
286f73d
Merge branch 'master' into feature/nodeDescription
daniel-beck Dec 15, 2022
c4571b9
Merge branch 'master' into feature/nodeDescription
timja Dec 31, 2022
f55352e
Update core/src/main/resources/jenkins/model/Jenkins/MasterComputer/i…
timja Dec 31, 2022
9f85ab7
Mark as restricted
timja Dec 31, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
*/
timja marked this conversation as resolved.
Show resolved Hide resolved
@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 @@ -27,6 +27,7 @@ THE SOFTWARE.
<l:layout title="${it.displayName}">
<st:include page="sidepanel.jelly" />
<l:main-panel>
<st:include page="index-top.jelly" it="${it}" />

<!-- temporarily offline switch -->
<div style="float:right">
Expand All @@ -52,16 +53,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>

mPokornyETM marked this conversation as resolved.
Show resolved Hide resolved
<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