Skip to content

Commit 8c4038d

Browse files
committed
[JENKINS-75683] re-introduce actions for Jenkins with custom action.jelly
actions without a URL but a custom action.jelly where not shown correctly in the header. This re-introduces them and allows custom rendering of actions again (by using an action.jelly). Things still to do, * task taglib needs to be adjusted to style correctly when tasks are in the header * remote the url hack.
1 parent 7aa9647 commit 8c4038d

File tree

2 files changed

+90
-60
lines changed

2 files changed

+90
-60
lines changed

core/src/main/java/jenkins/views/Header.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,19 @@ public List<Action> getActions() {
8181
return Jenkins.get()
8282
.getActions()
8383
.stream()
84-
.filter(e -> e.getIconFileName() != null || (e instanceof IconSpec is && is.getIconClassName() != null))
84+
//.filter(e -> e.getIconFileName() != null || (e instanceof IconSpec is && is.getIconClassName() != null))
8585
.sorted(Comparator.comparingDouble(
8686
a -> rootActionsOrdinal.getOrDefault(a.getClass().getName(), Double.MAX_VALUE)
8787
).reversed())
8888
.toList();
8989
}
90+
91+
@Restricted(NoExternalUse.class)
92+
public String getUrl() {
93+
// tasks (using in actions) use it.URL and it is Header here.
94+
// so return the root URL of Jenkins
95+
// XXX HACK HACK - need to check why the tasks taglib calculates URLs as ${JENKINS_URL}/null/action.url
96+
// should probably set ${it} to Jenkins in the jelly instead but this hack is quick and easy for now
97+
return "";
98+
}
9099
}

core/src/main/resources/lib/layout/header/actions.jelly

Lines changed: 80 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -4,67 +4,88 @@
44
<st:include page="suffix" optional="true" />
55

66
<j:forEach var="action" items="${it.actions}">
7-
<j:set var="isCurrent" value="${h.hyperlinkMatchesCurrentPage(action.urlName)}" />
8-
9-
<j:set var="jumplist">
10-
<st:include it="${action}" page="jumplist.jelly" optional="true" />
11-
</j:set>
12-
13-
<j:if test="${jumplist.length() == 0}">
14-
<j:set var="tooltip">
15-
<st:include it="${action}" page="tooltip.jelly" optional="true" />
16-
</j:set>
17-
</j:if>
18-
19-
<j:set var="badge" value="${action.badge}" />
20-
<j:if test="${jumplist.length() == 0 and tooltip.length() == 0}">
21-
<j:set var="tooltip">
22-
<div style="text-align: center;">${action.displayName}</div>
23-
<j:if test="${badge != null}">
24-
<div style="text-align: center; color: var(--text-color-secondary)">${badge.tooltip}</div>
7+
<!--
8+
allow the action to take over the rendering, but otherwise fall back to the default
9+
the action object itself is available in the 'action' variable
10+
-->
11+
<x:comment>Processing ${action.class.name}</x:comment>
12+
<j:choose>
13+
<j:when test="${h.hasView(action, 'action')}">
14+
<x:comment>${action.class.name} using action view</x:comment>
15+
<st:include page="action.jelly" from="${action}" optional="true"/>
16+
</j:when>
17+
<j:otherwise>
18+
<j:set var="icon" value="${action.iconClassName != null ? action.iconClassName : action.iconFileName}"/>
19+
<j:if test="${icon == null}">
20+
<x:comment>${action.class.name} has no icon</x:comment>
2521
</j:if>
26-
</j:set>
27-
</j:if>
28-
29-
<j:set var="interactive" value="${jumplist.length() gt 0}" />
30-
<j:set var="icon" value="${action.iconClassName != null ? action.iconClassName : action.iconFileName}"/>
31-
<x:element name="${action.urlName == null ? 'button' : 'a'}">
32-
<x:attribute name="data-dropdown">${interactive}</x:attribute>
33-
<x:attribute name="id">root-action-${action.class.simpleName}</x:attribute>
34-
<x:attribute name="href">${h.getActionUrl(app.url, action)}</x:attribute>
35-
<j:if test="${interactive}">
36-
<x:attribute name="data-tippy-offset">[0, 10]</x:attribute>
37-
</j:if>
38-
<j:if test="${!interactive}">
39-
<x:attribute name="data-html-tooltip" escapeText="false"><j:out value="${tooltip}" /></x:attribute>
40-
</j:if>
41-
<x:attribute name="data-tooltip-interactive">${interactive}</x:attribute>
42-
<x:attribute name="data-tippy-animation">tooltip</x:attribute>
43-
<x:attribute name="data-tippy-theme">${interactive ? 'dropdown' : 'tooltip'}</x:attribute>
44-
<x:attribute name="data-tippy-trigger">mouseenter focus</x:attribute>
45-
<x:attribute name="data-tippy-touch">${interactive}</x:attribute>
46-
<x:attribute name="data-type">header-action</x:attribute>
47-
<x:attribute name="draggable">false</x:attribute>
48-
<x:attribute name="class">jenkins-button ${isCurrent ? '' : 'jenkins-button--tertiary'}</x:attribute>
49-
<l:icon src="${icon}" class="${action.class.name == 'jenkins.model.navigation.UserAction' ? 'jenkins-avatar' : ''}"/>
50-
<span class="jenkins-visually-hidden" data-type="action-label">${action.displayName}</span>
51-
<j:if test="${badge != null}">
52-
<span class="jenkins-badge jenkins-!-${badge.severity}-color" />
53-
</j:if>
54-
</x:element>
55-
56-
<j:if test="${interactive}">
57-
<template>
58-
<div class="jenkins-dropdown">
59-
<j:out value="${jumplist}" />
60-
</div>
61-
</template>
62-
</j:if>
63-
64-
<j:set var="jumplist" />
65-
<j:set var="tooltip" />
22+
<!-- there was no custom action and we have no icon so this is intended to be hidden -->
23+
<j:if test="${icon != null}">
24+
<x:comment>${action.class.name} has an icon</x:comment>
25+
26+
<j:set var="isCurrent" value="${h.hyperlinkMatchesCurrentPage(action.urlName)}" />
27+
28+
<j:set var="jumplist">
29+
<st:include it="${action}" page="jumplist.jelly" optional="true" />
30+
</j:set>
31+
32+
<j:if test="${jumplist.length() == 0}">
33+
<j:set var="tooltip">
34+
<st:include it="${action}" page="tooltip.jelly" optional="true" />
35+
</j:set>
36+
</j:if>
37+
38+
<j:set var="badge" value="${action.badge}" />
39+
<j:if test="${jumplist.length() == 0 and tooltip.length() == 0}">
40+
<j:set var="tooltip">
41+
<div style="text-align: center;">${action.displayName}</div>
42+
<j:if test="${badge != null}">
43+
<div style="text-align: center; color: var(--text-color-secondary)">${badge.tooltip}</div>
44+
</j:if>
45+
</j:set>
46+
</j:if>
47+
48+
<j:set var="interactive" value="${jumplist.length() gt 0}" />
49+
<x:element name="${action.urlName == null ? 'button' : 'a'}">
50+
<x:attribute name="data-dropdown">${interactive}</x:attribute>
51+
<x:attribute name="id">root-action-${action.class.simpleName}</x:attribute>
52+
<x:attribute name="href">${h.getActionUrl(app.url, action)}</x:attribute>
53+
<j:if test="${interactive}">
54+
<x:attribute name="data-tippy-offset">[0, 10]</x:attribute>
55+
</j:if>
56+
<j:if test="${!interactive}">
57+
<x:attribute name="data-html-tooltip" escapeText="false"><j:out value="${tooltip}" /></x:attribute>
58+
</j:if>
59+
<x:attribute name="data-tooltip-interactive">${interactive}</x:attribute>
60+
<x:attribute name="data-tippy-animation">tooltip</x:attribute>
61+
<x:attribute name="data-tippy-theme">${interactive ? 'dropdown' : 'tooltip'}</x:attribute>
62+
<x:attribute name="data-tippy-trigger">mouseenter focus</x:attribute>
63+
<x:attribute name="data-tippy-touch">${interactive}</x:attribute>
64+
<x:attribute name="data-type">header-action</x:attribute>
65+
<x:attribute name="draggable">false</x:attribute>
66+
<x:attribute name="class">jenkins-button ${isCurrent ? '' : 'jenkins-button--tertiary'}</x:attribute>
67+
<l:icon src="${icon}" class="${action.class.name == 'jenkins.model.navigation.UserAction' ? 'jenkins-avatar' : ''}"/>
68+
<span class="jenkins-visually-hidden" data-type="action-label">${action.displayName}</span>
69+
<j:if test="${badge != null}">
70+
<span class="jenkins-badge jenkins-!-${badge.severity}-color" />
71+
</j:if>
72+
</x:element>
73+
74+
<j:if test="${interactive}">
75+
<template>
76+
<div class="jenkins-dropdown">
77+
<j:out value="${jumplist}" />
78+
</div>
79+
</template>
80+
</j:if>
81+
82+
<j:set var="jumplist" />
83+
<j:set var="tooltip" />
84+
</j:if>
85+
<!-- </st:include> -->
86+
</j:otherwise>
87+
</j:choose>
6688
</j:forEach>
67-
6889
<h:login/>
6990
</div>
7091
</j:jelly>

0 commit comments

Comments
 (0)