Use symbols for build status (#8705)

* Init

* Rename ID

* Fix icon position

* Fix app bar build status icon being incorrect

* Address missed icons

---------

Co-authored-by: Alexander Brandes <mc.cache@web.de>
This commit is contained in:
Jan Faracik 2023-11-27 19:36:43 +00:00 committed by GitHub
parent f9f542bffd
commit 1f95b09518
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 165 additions and 111 deletions

View File

@ -1,6 +1,6 @@
root = true
[*.{js, scss, css, hbs}]
[*.{js, scss, css, hbs, svg}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true

View File

@ -76,7 +76,7 @@ THE SOFTWARE.
<j:choose>
<j:when test="${dep.from!=null}">
<a href="${rootURL}/${dep.from.url}" class="model-link inside">
<l:icon class="${dep.from.buildStatusIconClassName} icon-sm" alt="${dep.from.iconColor.description}"/>${dep.from.displayName}</a>
<l:icon src="symbol-status-${dep.from.iconColor.iconName}" class="icon-sm" alt="${dep.from.iconColor.description}"/>${dep.from.displayName}</a>
</j:when>
<j:otherwise>
?
@ -86,7 +86,7 @@ THE SOFTWARE.
&#x2192; <!-- right arrow -->
<a href="${rootURL}/${dep.to.url}" class="model-link inside">
<l:icon class="${dep.to.buildStatusIconClassName} icon-sm" alt="${dep.to.iconColor.description}" />${dep.to.displayName}</a>
<l:icon src="symbol-status-${dep.to.iconColor.iconName}" class="icon-sm" alt="${dep.to.iconColor.description}" />${dep.to.displayName}</a>
(<a href="${rootURL}/${dep.project.url}changes?from=${dep.fromId}&amp;to=${dep.toId}">${%detail}</a>)
</li>

View File

@ -31,6 +31,14 @@ THE SOFTWARE.
<l:breadcrumb title="${%Build Time Trend}" />
<st:adjunct includes="hudson.model.Job.buildTimeTrend_resources" />
<l:main-panel>
<template id="jenkins-build-status-icons">
<l:icon src="symbol-status-blue" id="blue" />
<l:icon src="symbol-status-yellow" id="yellow" />
<l:icon src="symbol-status-red" id="red" />
<l:icon src="symbol-status-nobuilt" id="nobuilt" />
<l:icon src="symbol-status-aborted" id="aborted" />
<l:icon src="symbol-status-disabled" id="disabled" />
</template>
<h1>${%Build Time Trend}</h1>
<div align="center">
<img class="build-time-graph" src="buildTimeGraph/png" width="500" height="400" lazymap="buildTimeGraph/map" alt="[${%Build time graph}]" />

View File

@ -67,76 +67,11 @@ window.buildTimeTrend_displayBuilds = function (data) {
/**
* Generate SVG Icon
*/
function generateSVGIcon(iconName, iconSizeClass) {
const imagesURL = document.head.getAttribute("data-imagesurl");
function generateSVGIcon(iconName) {
const icons = document.querySelector("#jenkins-build-status-icons");
iconName = iconName.replace("-anime", "");
const isInProgress = iconName.endsWith("anime");
let buildStatus = "never-built";
switch (iconName) {
case "red":
case "red-anime":
buildStatus = "last-failed";
break;
case "yellow":
case "yellow-anime":
buildStatus = "last-unstable";
break;
case "blue":
case "blue-anime":
buildStatus = "last-successful";
break;
case "grey":
case "grey-anime":
case "disabled":
case "disabled-anime":
buildStatus = "last-disabled";
break;
case "aborted":
case "aborted-anime":
buildStatus = "last-aborted";
break;
case "nobuilt":
case "nobuilt-anime":
buildStatus = "never-built";
break;
}
const svg1 = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg1.setAttribute("class", "svg-icon");
svg1.setAttribute("viewBox", "0 0 24 24");
const use1 = document.createElementNS("http://www.w3.org/2000/svg", "use");
use1.setAttribute(
"href",
imagesURL +
"/build-status/build-status-sprite.svg#build-status-" +
(isInProgress ? "in-progress" : "static"),
);
svg1.appendChild(use1);
const svg2 = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg2.setAttribute(
"class",
"svg-icon icon-" + iconName + " " + (iconSizeClass || "icon-sm"),
);
svg2.setAttribute("viewBox", "0 0 24 24");
const use2 = document.createElementNS("http://www.w3.org/2000/svg", "use");
use2.setAttribute(
"href",
imagesURL + "/build-status/build-status-sprite.svg#" + buildStatus,
);
svg2.appendChild(use2);
const span = document.createElement("span");
span.classList.add("build-status-icon__wrapper", "icon-" + iconName);
let span2 = document.createElement("span");
span2.classList.add("build-status-icon__outer");
span2.appendChild(svg1);
span.appendChild(span2);
span.appendChild(svg2);
return span;
return icons.content.querySelector(`#${iconName}`).cloneNode(true);
}
/**
@ -155,7 +90,7 @@ window.displayBuilds = function (data) {
td1.classList.add("jenkins-table__cell--tight", "jenkins-table__icon");
var div1 = document.createElement("div");
div1.classList.add("jenkins-table__cell__button-wrapper");
var svg = generateSVGIcon(e.iconName, p.dataset.iconSizeClass);
var svg = generateSVGIcon(e.iconName);
div1.appendChild(svg);
td1.appendChild(div1);
tr.appendChild(td1);

View File

@ -33,7 +33,7 @@ THE SOFTWARE.
<j:set var="lastBuild" value="${it.lastBuild}" />
<j:if test="${lastBuild != null}">
<a href="${rootURL + '/' + lastBuild.url}" class="jenkins-!-display-contents" tabindex="-1">
<l:icon class="${lastBuild.buildStatusIconClassName}" tooltip="${lastBuild.iconColor.description}"/>
<l:icon src="symbol-status-${lastBuild.iconColor.iconName}" tooltip="${lastBuild.iconColor.description}"/>
</a>
</j:if>
<h1 class="job-index-headline page-headline">

View File

@ -31,6 +31,6 @@ THE SOFTWARE.
<st:compress 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">
<st:setHeader name="X-Building" value="${it.building}" />
<l:ajax>
<l:icon alt="${it.iconColor.description}" class="${it.buildStatusIconClassName} icon-xlg" tooltip="${it.iconColor.description}"/>
<l:icon alt="${it.iconColor.description}" src="symbol-status-${it.iconColor.iconName}" class="icon-xlg" tooltip="${it.iconColor.description}"/>
</l:ajax>
</st:compress>

View File

@ -23,6 +23,18 @@ THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:t="/lib/hudson">
<t:ballColorTd it="${job.iconColor}" />
</j:jelly>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout">
<td class="jenkins-table__cell--tight jenkins-table__icon" data="${job.iconColor.ordinal()}">
<div class="jenkins-table__cell__button-wrapper">
<j:choose>
<j:when test="${job.iconColor.iconName != null}">
<l:icon src="symbol-status-${job.iconColor.iconName}" tooltip="${job.iconColor.description}" />
</j:when>
<j:otherwise>
<!-- This is for special conditions, such as folders -->
<l:icon src="${job.iconColor.iconClassName}" />
</j:otherwise>
</j:choose>
</div>
</td>
</j:jelly>

View File

@ -39,7 +39,7 @@ THE SOFTWARE.
<div class="pane build-name">
<div class="build-icon">
<a class="build-status-link" href="${h.getConsoleUrl(build)}" tooltip="${build.iconColor.description} > ${%Console Output}">
<l:icon class="${build.buildStatusIconClassName} icon-sm" />
<l:icon src="symbol-status-${build.iconColor.iconName}" />
</a>
</div>
<a class="model-link inside build-link display-name" update-parent-class=".build-row" href="${link}">${build.displayName}</a>

View File

@ -29,88 +29,88 @@ THE SOFTWARE.
<dl class="app-icon-legend">
<dt>
<l:icon class="icon-blue icon-lg"/>
<l:icon src="symbol-status-blue" />
</dt>
<dd>
${%blue}
</dd>
<dt>
<l:icon class="icon-blue-anime icon-lg"/>
<l:icon src="symbol-status-blue-anime" />
</dt>
<dd>
${%blue_anime}
</dd>
<dt>
<l:icon class="icon-yellow icon-lg"/>
<l:icon src="symbol-status-yellow" />
</dt>
<dd>
${%yellow}
</dd>
<dt>
<l:icon class="icon-yellow-anime icon-lg"/>
<l:icon src="symbol-status-yellow-anime" />
</dt>
<dd>
${%yellow_anime}
</dd>
<dt>
<l:icon class="icon-red icon-lg"/>
<l:icon src="symbol-status-red" />
</dt>
<dd>
${%red}
</dd>
<dt>
<l:icon class="icon-red-anime icon-lg"/>
<l:icon src="symbol-status-red-anime" />
</dt>
<dd>
${%red_anime}
</dd>
<dt>
<l:icon class="icon-nobuilt icon-lg"/>
<l:icon src="symbol-status-nobuilt" />
</dt>
<dd>
${%lightgrey}
</dd>
<dt>
<l:icon class="icon-nobuilt-anime icon-lg"/>
<l:icon src="symbol-status-nobuilt-anime" />
</dt>
<dd>
${%lightgrey_anime}
</dd>
<dt>
<l:icon class="icon-disabled icon-lg"/>
</dt>
<dd>
${%grey}
</dd>
<dt>
<l:icon class="icon-disabled-anime icon-lg"/>
</dt>
<dd>
${%grey_anime}
</dd>
<dt>
<l:icon class="icon-aborted icon-lg"/>
<l:icon src="symbol-status-aborted" />
</dt>
<dd>
${%darkgrey}
</dd>
<dt>
<l:icon class="icon-aborted-anime icon-lg"/>
<l:icon src="symbol-status-aborted-anime" />
</dt>
<dd>
${%darkgrey_anime}
</dd>
<dt>
<l:icon src="symbol-status-disabled" />
</dt>
<dd>
${%grey}
</dd>
<dt>
<l:icon src="symbol-status-disabled-anime" />
</dt>
<dd>
${%grey_anime}
</dd>
</dl>
<h2 class="jenkins-dialog__subtitle">${%Project Health}</h2>

View File

@ -29,7 +29,7 @@ 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:f="/lib/form">
<div class="jenkins-app-bar">
<div class="jenkins-app-bar__content jenkins-build-caption">
<l:icon alt="${it.iconColor.description}" class="${it.buildStatusIconClassName} icon-xlg"
<l:icon alt="${it.iconColor.description}" src="symbol-status-${it.iconColor.iconName}"
tooltip="${it.iconColor.description}"/>
<h1>
<d:invokeBody trim="true"/>

View File

@ -52,7 +52,7 @@ THE SOFTWARE.
</j:when>
<j:otherwise>
<a href="${attrs.href ?: rootURL+'/'+r.url}" class="model-link">
<l:icon alt="${r.iconColor.description}" class="${r.buildStatusIconClassName} icon-sm" style="margin-left: 0; position: relative; top: -0.1rem;"/><span class="jenkins-icon-adjacent">${jobName_}#<!-- -->${number}</span></a>
<l:icon alt="${r.iconColor.description}" src="symbol-status-${r.iconColor.iconName}" class="icon-sm" style="margin-left: 0; position: relative; top: -0.1rem;"/><span class="jenkins-icon-adjacent">${jobName_}#<!-- -->${number}</span></a>
</j:otherwise>
</j:choose>
</j:otherwise>

View File

@ -30,6 +30,15 @@ THE SOFTWARE.
A collection of builds to be displayed.
</st:attribute>
</st:documentation>
<template id="jenkins-build-status-icons">
<l:icon src="symbol-status-blue" id="blue" />
<l:icon src="symbol-status-yellow" id="yellow" />
<l:icon src="symbol-status-red" id="red" />
<l:icon src="symbol-status-nobuilt" id="nobuilt" />
<l:icon src="symbol-status-aborted" id="aborted" />
<l:icon src="symbol-status-disabled" id="disabled" />
<l:icon src="symbol-terminal" id="console" />
</template>
<t:setIconSize/>
<st:adjunct includes="hudson.model.Job.buildTimeTrend_resources" />

View File

@ -31,7 +31,7 @@ THE SOFTWARE.
</st:attribute>
</st:documentation>
<l:icon alt="${job.iconColor.description}" class="${job.buildStatusIconClassName} icon-sm"/>
<l:icon alt="${job.iconColor.description}" src="symbol-status-${job.iconColor.iconName}" class="icon-sm"/>
<a href="${h.getRelativeLinkTo(job)}" class="model-link jenkins-icon-adjacent">
<l:breakable value="${job.fullDisplayName}"/>
</a>

View File

@ -93,7 +93,15 @@ THE SOFTWARE.
<div class="jenkins-jobs-list__item">
<a class="jenkins-jobs-list__item__details" href="${jobBaseUrl}${job.shortUrl}">
<div class="jenkins-jobs-list__item__icons">
<t:ballColorTd it="${job.iconColor}" />
<j:choose>
<j:when test="${job.iconColor.iconName != null}">
<l:icon src="symbol-status-${job.iconColor.iconName}" tooltip="${job.iconColor.description}" />
</j:when>
<j:otherwise>
<!-- This is for special conditions, such as folders -->
<l:icon src="${job.iconColor.iconClassName}" />
</j:otherwise>
</j:choose>
</div>
<div class="jenkins-jobs-list__item__details__text">
<p class="jenkins-jobs-list__item__label">${job.displayName}</p>

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<ellipse opacity="0.4" cx="256" cy="256" rx="210" ry="210" fill="none" stroke="var(--text-color-secondary)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="36" />
<path d="M256 46C140.02 46 46 140.02 46 256" fill="transparent" stroke="var(--text-color-secondary)" stroke-width="36" stroke-miterlimit="10" stroke-linecap="round" data-symbol-animation="spin" />
<path fill="none" stroke="var(--text-color-secondary)" stroke-linecap="round" stroke-linejoin="round" stroke-width="36" d="M192 320l128-128"/>
</svg>

After

Width:  |  Height:  |  Size: 597 B

View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<ellipse cx="256" cy="256" rx="210" ry="210" fill="none" stroke="var(--text-color-secondary)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="36" />
<path fill="none" stroke="var(--text-color-secondary)" stroke-linecap="round" stroke-linejoin="round" stroke-width="36" d="M192 320l128-128" />
</svg>

After

Width:  |  Height:  |  Size: 383 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<ellipse opacity="0.4" cx="256" cy="256" rx="210" ry="210" fill="none" stroke="var(--success-color)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="36" />
<path d="M256 46C140.02 46 46 140.02 46 256" fill="transparent" stroke="var(--success-color)" stroke-width="36" stroke-miterlimit="10" stroke-linecap="round" data-symbol-animation="spin" />
<path d="M336 189L224 323L176 269.4" fill="transparent" stroke="var(--success-color)" stroke-width="36" stroke-linecap="round" stroke-linejoin="round" />
</svg>

After

Width:  |  Height:  |  Size: 594 B

View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<ellipse cx="256" cy="256" rx="210" ry="210" fill="none" stroke="var(--success-color)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="36" />
<path d="M336 189L224 323L176 269.4" fill="transparent" stroke="var(--success-color)" stroke-width="36" stroke-linecap="round" stroke-linejoin="round" />
</svg>

After

Width:  |  Height:  |  Size: 386 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<ellipse opacity="0.4" cx="256" cy="256" rx="210" ry="210" fill="none" stroke="var(--text-color-secondary)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="36" />
<path d="M256 46C140.02 46 46 140.02 46 256" fill="transparent" stroke="var(--text-color-secondary)" stroke-width="36" stroke-miterlimit="10" stroke-linecap="round" data-symbol-animation="spin" />
<ellipse cx="256" cy="256" rx="100" ry="100" fill="none" stroke="var(--text-color-secondary)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="36" />
<path fill="none" stroke="var(--text-color-secondary)" stroke-linecap="round" stroke-linejoin="round" stroke-width="36" d="M192 320l128-128" />
</svg>

After

Width:  |  Height:  |  Size: 763 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<ellipse cx="256" cy="256" rx="210" ry="210" fill="none" stroke="var(--text-color-secondary)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="36" />
<ellipse cx="256" cy="256" rx="100" ry="100" fill="none" stroke="var(--text-color-secondary)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="36" />
<path fill="none" stroke="var(--text-color-secondary)" stroke-linecap="round" stroke-linejoin="round" stroke-width="36" d="M192 320l128-128" />
</svg>

After

Width:  |  Height:  |  Size: 548 B

View File

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<ellipse opacity="0.4" cx="256" cy="256" rx="210" ry="210" fill="none" stroke="var(--blue)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="36" />
<path d="M256 46C140.02 46 46 140.02 46 256" fill="transparent" stroke="var(--blue)" stroke-width="36" stroke-miterlimit="10" stroke-linecap="round" data-symbol-animation="spin" />
<circle cx="256" cy="256" r="30" fill="var(--blue)" />
<circle cx="352" cy="256" r="30" fill="var(--blue)" />
<circle cx="160" cy="256" r="30" fill="var(--blue)" />
</svg>

After

Width:  |  Height:  |  Size: 585 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<ellipse cx="256" cy="256" rx="210" ry="210" fill="none" stroke="var(--blue)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="36" />
<circle cx="256" cy="256" r="30" fill="var(--blue)" />
<circle cx="352" cy="256" r="30" fill="var(--blue)" />
<circle cx="160" cy="256" r="30" fill="var(--blue)" />
</svg>

After

Width:  |  Height:  |  Size: 388 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<ellipse opacity="0.4" cx="256" cy="256" rx="210" ry="210" fill="none" stroke="var(--red)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="36" />
<path d="M256 46C140.02 46 46 140.02 46 256" fill="transparent" stroke="var(--red)" stroke-width="36" stroke-miterlimit="10" stroke-linecap="round" data-symbol-animation="spin" />
<path fill="none" stroke="var(--red)" stroke-linecap="round" stroke-linejoin="round" stroke-width="36" d="M320 320L192 192M192 320l128-128"/>
</svg>

After

Width:  |  Height:  |  Size: 562 B

View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<ellipse cx="256" cy="256" rx="210" ry="210" fill="none" stroke="var(--red)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="36" />
<path fill="none" stroke="var(--red)" stroke-linecap="round" stroke-linejoin="round" stroke-width="36" d="M320 320L192 192M192 320l128-128"/>
</svg>

After

Width:  |  Height:  |  Size: 364 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512">
<ellipse opacity="0.4" cx="256" cy="256" rx="210" ry="210" fill="none" stroke="var(--orange)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="36" />
<path d="M256 46C140.02 46 46 140.02 46 256" fill="transparent" stroke="var(--orange)" stroke-width="36" stroke-miterlimit="10" stroke-linecap="round" data-symbol-animation="spin" />
<path d="M250.26 166.05L256 288l5.73-121.95a5.74 5.74 0 00-5.79-6h0a5.74 5.74 0 00-5.68 6z" fill="none" stroke="var(--orange)" stroke-linecap="round" stroke-linejoin="round" stroke-width="36" />
<ellipse cx="256" cy="350" rx="26" ry="26" fill="var(--orange)" />
</svg>

After

Width:  |  Height:  |  Size: 708 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512">
<ellipse cx="256" cy="256" rx="210" ry="210" fill="none" stroke="var(--orange)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="36" />
<path d="M250.26 166.05L256 288l5.73-121.95a5.74 5.74 0 00-5.79-6h0a5.74 5.74 0 00-5.68 6z" fill="none" stroke="var(--orange)" stroke-linecap="round" stroke-linejoin="round" stroke-width="36" />
<ellipse cx="256" cy="350" rx="26" ry="26" fill="var(--orange)" />
</svg>

After

Width:  |  Height:  |  Size: 507 B

View File

@ -866,13 +866,22 @@ table.progress-bar.red td.progress-bar-done {
/* Unknown */
[data-symbol-animation] {
animation: spin 1s linear infinite;
transform-origin: center;
@media (prefers-reduced-motion) {
animation-duration: 3s;
}
}
@keyframes spin {
from {
transform: rotate(0deg) translateZ(0);
transform: rotate(0deg);
}
to {
transform: rotate(360deg) translateZ(0);
transform: rotate(360deg);
}
}

View File

@ -81,8 +81,7 @@
overflow: hidden;
text-overflow: ellipsis;
.build-status-icon__wrapper,
.build-status-icon__wrapper svg {
svg {
width: 2rem !important;
height: 2rem !important;
}

View File

@ -156,6 +156,7 @@
.build-row-cell .pane.build-name .build-icon {
position: absolute;
margin-top: 2px;
z-index: 1;
}

View File

@ -169,3 +169,14 @@ $min-button-size: 36px;
}
}
}
.build-status-link {
display: inline-flex;
align-items: center;
justify-content: center;
svg {
width: 1rem;
height: 1rem;
}
}