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

220 lines
6.2 KiB
JavaScript

import Path from "@/util/path";
import behaviorShim from "@/util/behavior-shim";
import Utils from "@/components/dropdowns/utils";
function init() {
generateJumplistAccessors();
generateDropdowns();
}
/*
* Appends a ⌄ button at the end of links which support jump lists
*/
function generateJumplistAccessors() {
behaviorShim.specify("A.model-link", "-jumplist-", 999, (link) => {
const isFirefox = navigator.userAgent.indexOf("Firefox") !== -1;
// Firefox adds unwanted lines when copying buttons in text, so use a span instead
const dropdownChevron = document.createElement(
isFirefox ? "span" : "button",
);
dropdownChevron.className = "jenkins-menu-dropdown-chevron";
dropdownChevron.dataset.href = link.href;
dropdownChevron.addEventListener("click", (event) => {
event.preventDefault();
});
link.appendChild(dropdownChevron);
});
}
/*
* Generates the dropdowns for the jump lists
*/
function generateDropdowns() {
behaviorShim.specify(
".hoverable-model-link, .hoverable-children-model-link",
"-hoverable-dropdown-",
1000,
(element) =>
Utils.generateDropdown(
element,
(instance) => {
if (element.items) {
instance.setContent(Utils.generateDropdownItems(element.items));
return;
}
const href = element.href;
const hasModelLink = element.classList.contains(
"hoverable-model-link",
);
const hasChildrenLink = element.classList.contains(
"hoverable-children-model-link",
);
const sections = {
model: null,
children: null,
};
const fetchSection = function (urlSuffix) {
return fetch(Path.combinePath(href, urlSuffix))
.then((response) => response.json())
.then((json) => {
const items = mapChildrenItemsToDropdownItems(json.items);
const section = document.createElement("div");
section.appendChild(Utils.generateDropdownItems(items));
return section;
});
};
const promises = [];
if (hasModelLink) {
promises.push(
fetchSection("contextMenu").then((section) => {
sections.model = section;
}),
);
}
if (hasChildrenLink) {
promises.push(
fetchSection("childrenContextMenu").then((section) => {
sections.children = section;
}),
);
}
Promise.all(promises)
.then(() => {
const container = document.createElement("div");
container.className = "jenkins-dropdown__split-container";
if (sections.model) {
container.appendChild(sections.model);
}
if (sections.children) {
container.appendChild(sections.children);
}
instance.setContent(container);
})
.catch((error) => {
console.log(`Dropdown fetch failed: ${error}`);
})
.finally(() => {
instance.loaded = true;
});
},
element.items != null,
{
trigger: "mouseenter",
offset: [-16, 10],
animation: "tooltip",
touch: false,
},
),
);
behaviorShim.specify(
"li.children, .jenkins-jumplist-link, #menuSelector, .jenkins-menu-dropdown-chevron",
"-dropdown-",
1000,
(element) =>
Utils.generateDropdown(element, (instance) => {
const href = element.dataset.href;
const jumplistType = !element.classList.contains("children")
? "contextMenu"
: "childrenContextMenu";
if (element.items) {
instance.setContent(Utils.generateDropdownItems(element.items));
return;
}
fetch(Path.combinePath(href, jumplistType))
.then((response) => response.json())
.then((json) =>
instance.setContent(
Utils.generateDropdownItems(
mapChildrenItemsToDropdownItems(json.items),
),
),
)
.catch((error) => console.log(`Jumplist request failed: ${error}`))
.finally(() => (instance.loaded = true));
}),
);
}
/*
* Generates the contents for the dropdown
*/
function mapChildrenItemsToDropdownItems(items) {
return items.map((item) => {
if (item.type === "HEADER") {
return {
type: "HEADER",
label: item.displayName,
};
}
if (item.type === "SEPARATOR") {
return {
type: "SEPARATOR",
};
}
return {
icon: item.icon,
iconXml: item.iconXml,
label: item.displayName,
url: item.url,
type: item.post || item.requiresConfirmation ? "button" : "link",
badge: item.badge,
onClick: () => {
if (item.post || item.requiresConfirmation) {
if (item.requiresConfirmation) {
dialog
.confirm(item.displayName, { message: item.message })
.then(() => {
const form = document.createElement("form");
form.setAttribute("method", item.post ? "POST" : "GET");
form.setAttribute("action", item.url);
if (item.post) {
crumb.appendToForm(form);
}
document.body.appendChild(form);
form.submit();
});
} else {
fetch(item.url, {
method: "post",
headers: crumb.wrap({}),
}).then((rsp) => {
if (rsp.ok) {
notificationBar.show(
item.displayName + ": Done.",
notificationBar.SUCCESS,
);
} else {
notificationBar.show(
item.displayName + ": Failed.",
notificationBar.ERROR,
);
}
});
}
}
},
subMenu: item.subMenu
? () => {
return mapChildrenItemsToDropdownItems(item.subMenu.items);
}
: null,
};
});
}
export default { init };