Files
opportunities-extension/src/features/opportunities/links.js

119 lines
4.1 KiB
JavaScript

function createOpportunitiesLinks({
MODAL_ID,
environment
}) {
const { document, navigator, window } = environment;
function createDetailLink(label, href) {
if (label === null || label === undefined || label === "") {
const placeholder = document.createElement("span");
placeholder.textContent = "-";
return placeholder;
}
if (!href) {
const text = document.createElement("span");
text.textContent = String(label);
return text;
}
const link = document.createElement("a");
link.href = href;
link.target = "_blank";
link.rel = "noopener noreferrer";
link.textContent = String(label);
return link;
}
function createCopyOpportunityButton(optyNumber) {
const button = document.createElement("button");
const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
button.type = "button";
button.className = "opportunities-extension-copy-button";
button.setAttribute("aria-label", `Copy opportunity number ${optyNumber}`);
button.title = "Copy opportunity number";
button.addEventListener("click", (event) => {
event.preventDefault();
event.stopPropagation();
copyOpportunityNumber(String(optyNumber));
});
icon.setAttribute("viewBox", "0 0 24 24");
icon.setAttribute("aria-hidden", "true");
path.setAttribute("d", "M8 8V5.5A2.5 2.5 0 0 1 10.5 3h8A2.5 2.5 0 0 1 21 5.5v8a2.5 2.5 0 0 1-2.5 2.5H16v2.5a2.5 2.5 0 0 1-2.5 2.5h-8A2.5 2.5 0 0 1 3 18.5v-8A2.5 2.5 0 0 1 5.5 8H8zm2 0h3.5A2.5 2.5 0 0 1 16 10.5v3.5h2.5a.5.5 0 0 0 .5-.5v-8a.5.5 0 0 0-.5-.5h-8a.5.5 0 0 0-.5.5V8zm3.5 2h-8a.5.5 0 0 0-.5.5v8a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5v-8a.5.5 0 0 0-.5-.5z");
icon.append(path);
button.append(icon);
return button;
}
async function copyOpportunityNumber(optyNumber) {
try {
if (navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(optyNumber);
} else {
const input = document.createElement("textarea");
input.value = optyNumber;
input.setAttribute("readonly", "true");
input.style.position = "fixed";
input.style.opacity = "0";
document.body.append(input);
input.select();
document.execCommand("copy");
input.remove();
}
showCopyConfirmation(`Opty Number ${optyNumber} copied.`);
} catch (error) {
showCopyConfirmation("Unable to copy opportunity number.", true);
}
}
function showCopyConfirmation(message, isError = false) {
const modal = document.getElementById(MODAL_ID);
if (!modal) {
return;
}
let toast = modal.querySelector(".opportunities-extension-copy-toast");
if (!toast) {
toast = document.createElement("div");
toast.className = "opportunities-extension-copy-toast";
toast.setAttribute("role", "status");
modal.append(toast);
}
toast.classList.toggle("opportunities-extension-copy-toast-error", isError);
toast.textContent = message;
toast.hidden = false;
window.clearTimeout(toast.copyTimeout);
toast.copyTimeout = window.setTimeout(() => {
toast.hidden = true;
}, 2400);
}
function createStageBadge(stage) {
const badge = document.createElement("span");
const normalizedStage = typeof stage === "string" ? stage.toUpperCase() : "";
badge.className = "opportunities-extension-stage-badge";
badge.setAttribute("data-stage", normalizedStage);
badge.textContent = normalizedStage || "-";
return badge;
}
function createStatusBadge(status) {
const badge = document.createElement("span");
const normalizedStatus = typeof status === "string" ? status.toUpperCase() : "";
badge.className = "opportunities-extension-status-badge";
badge.setAttribute("data-status", normalizedStatus);
badge.textContent = normalizedStatus || "-";
return badge;
}
return { createDetailLink, createCopyOpportunityButton, copyOpportunityNumber, showCopyConfirmation, createStageBadge, createStatusBadge };
}