Skip to content

Commit d20cac6

Browse files
authored
[JENKINS-75634] Restore children context menu for breadcrumbs (#10629)
* Init * Format * Update jumplists.js * Tidy * Update jumplists.js * Update jumplists.js * Update jumplists.js * Don't use async/awai
1 parent 5f090c4 commit d20cac6

File tree

4 files changed

+88
-16
lines changed

4 files changed

+88
-16
lines changed

core/src/main/resources/lib/layout/breadcrumb.jelly

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,12 @@ THE SOFTWARE.
3737
This is useful for programmatically adding the context menu
3838
</st:attribute>
3939
<st:attribute name="hasMenu">
40-
If true, this breadcrumb item will include a '⌄' symbol to display a dropdown menu with items
41-
from the '{breadcrumb.href}/contextMenu' path. Since 2.361.
40+
If true, this breadcrumb item will display a dropdown menu with items
41+
from the '{breadcrumb.href}/contextMenu' path on hover. Since 2.361.
42+
</st:attribute>
43+
<st:attribute name="hasChildrenMenu">
44+
If true, this breadcrumb item will display a dropdown menu with items
45+
from the '{breadcrumb.href}/childrenContextMenu' path on hover. Since TODO.
4246
</st:attribute>
4347
</st:documentation>
4448

@@ -50,7 +54,7 @@ THE SOFTWARE.
5054
<span>${attrs.title}</span>
5155
</j:when>
5256
<j:otherwise>
53-
<a href="${attrs.href}" class="${attrs.hasMenu ? 'hoverable-model-link' : ''}">
57+
<a href="${attrs.href}" class="${attrs.hasMenu ? 'hoverable-model-link' : ''} ${attrs.hasChildrenMenu ? 'hoverable-children-model-link' : ''}">
5458
${attrs.title}
5559
</a>
5660
</j:otherwise>

core/src/main/resources/lib/layout/breadcrumbBar.jelly

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ THE SOFTWARE.
4444
<j:if test="${anc.object != app}">
4545
<l:breadcrumb title="${anc.object.displayName}"
4646
href="${anc.url}/"
47-
hasMenu="${h.isModelWithContextMenu(anc.object)}" />
47+
hasMenu="${h.isModelWithContextMenu(anc.object)}"
48+
hasChildrenMenu="${h.isModelWithChildren(anc.object)}" />
4849
</j:if>
4950
</j:if>
5051
</j:forEach>

src/main/js/components/dropdowns/jumplists.js

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function generateJumplistAccessors() {
3131
*/
3232
function generateDropdowns() {
3333
behaviorShim.specify(
34-
".hoverable-model-link",
34+
".hoverable-model-link, .hoverable-children-model-link",
3535
"-hoverable-dropdown-",
3636
1000,
3737
(element) =>
@@ -45,17 +45,65 @@ function generateDropdowns() {
4545
return;
4646
}
4747

48-
fetch(Path.combinePath(href, "contextMenu"))
49-
.then((response) => response.json())
50-
.then((json) =>
51-
instance.setContent(
52-
Utils.generateDropdownItems(
53-
mapChildrenItemsToDropdownItems(json.items),
54-
),
55-
),
56-
)
57-
.catch((error) => console.log(`Jumplist request failed: ${error}`))
58-
.finally(() => (instance.loaded = true));
48+
const hasModelLink = element.classList.contains(
49+
"hoverable-model-link",
50+
);
51+
const hasChildrenLink = element.classList.contains(
52+
"hoverable-children-model-link",
53+
);
54+
55+
const sections = {
56+
model: null,
57+
children: null,
58+
};
59+
60+
const fetchSection = function (urlSuffix) {
61+
return fetch(Path.combinePath(href, urlSuffix))
62+
.then((response) => response.json())
63+
.then((json) => {
64+
const items = mapChildrenItemsToDropdownItems(json.items);
65+
const section = document.createElement("div");
66+
section.appendChild(Utils.generateDropdownItems(items));
67+
return section;
68+
});
69+
};
70+
71+
const promises = [];
72+
73+
if (hasModelLink) {
74+
promises.push(
75+
fetchSection("contextMenu").then((section) => {
76+
sections.model = section;
77+
}),
78+
);
79+
}
80+
81+
if (hasChildrenLink) {
82+
promises.push(
83+
fetchSection("childrenContextMenu").then((section) => {
84+
sections.children = section;
85+
}),
86+
);
87+
}
88+
89+
Promise.all(promises)
90+
.then(() => {
91+
const container = document.createElement("div");
92+
container.className = "jenkins-dropdown__split-container";
93+
if (sections.model) {
94+
container.appendChild(sections.model);
95+
}
96+
if (sections.children) {
97+
container.appendChild(sections.children);
98+
}
99+
instance.setContent(container);
100+
})
101+
.catch((error) => {
102+
console.log(`Dropdown fetch failed: ${error}`);
103+
})
104+
.finally(() => {
105+
instance.loaded = true;
106+
});
59107
},
60108
false,
61109
{
@@ -74,6 +122,7 @@ function generateDropdowns() {
74122
(element) =>
75123
Utils.generateDropdown(element, (instance) => {
76124
const href = element.dataset.href;
125+
77126
const jumplistType = !element.classList.contains("children")
78127
? "contextMenu"
79128
: "childrenContextMenu";

src/main/scss/components/_dropdowns.scss

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,3 +288,21 @@ $dropdown-padding: 0.375rem;
288288
height: 1.25rem;
289289
}
290290
}
291+
292+
.jenkins-dropdown__split-container {
293+
display: grid;
294+
grid-template-columns: auto auto;
295+
296+
& > * {
297+
min-width: 215px;
298+
299+
&:not(:first-of-type) {
300+
background: color-mix(
301+
in sRGB,
302+
var(--text-color-secondary) 5%,
303+
transparent
304+
);
305+
border-left: var(--jenkins-border--subtle);
306+
}
307+
}
308+
}

0 commit comments

Comments
 (0)