173 lines
6.7 KiB
JavaScript
173 lines
6.7 KiB
JavaScript
function createConsumptionTrendController({
|
|
messageTypes,
|
|
CONSUMPTION_TREND_PERIODS,
|
|
DEFAULT_CONSUMPTION_TREND_PERIOD,
|
|
appendBackgroundRequestLog,
|
|
consumptionTrendState,
|
|
createPlanDetailSection,
|
|
renderConsumptionTrendChart,
|
|
requestConsumerTokenServiceOnce,
|
|
sendRuntimeMessage,
|
|
environment
|
|
}) {
|
|
const { document } = environment;
|
|
function createConsumptionTrendSection(plan) {
|
|
const section = document.createElement("section");
|
|
section.className = "opportunities-extension-consumption-trend";
|
|
section.dataset.subPlanNum = String(plan.subPlanNum || "");
|
|
section.dataset.period = DEFAULT_CONSUMPTION_TREND_PERIOD;
|
|
|
|
const header = document.createElement("header");
|
|
header.className = "opportunities-extension-consumption-trend-header";
|
|
|
|
const periodControls = document.createElement("div");
|
|
periodControls.className = "opportunities-extension-consumption-periods";
|
|
periodControls.setAttribute("role", "group");
|
|
periodControls.setAttribute("aria-label", "Consumption period");
|
|
|
|
CONSUMPTION_TREND_PERIODS.forEach((periodOption) => {
|
|
const button = document.createElement("button");
|
|
button.type = "button";
|
|
button.dataset.period = periodOption.value;
|
|
button.setAttribute("aria-pressed", String(periodOption.value === DEFAULT_CONSUMPTION_TREND_PERIOD));
|
|
button.textContent = periodOption.label;
|
|
button.addEventListener("click", () => {
|
|
section.dataset.period = periodOption.value;
|
|
consumptionTrendState.consumptionTrendWindowOffsets.set(
|
|
createConsumptionTrendKey(section.dataset.subPlanNum, periodOption.value),
|
|
0
|
|
);
|
|
loadConsumptionTrendForPanel(section.closest("[role='tabpanel']"), plan, periodOption.value);
|
|
});
|
|
periodControls.append(button);
|
|
});
|
|
|
|
const chart = document.createElement("div");
|
|
chart.className = "opportunities-extension-consumption-chart";
|
|
chart.setAttribute("aria-live", "polite");
|
|
header.append(createPlanDetailSection(plan), periodControls);
|
|
section.append(header, chart);
|
|
return section;
|
|
}
|
|
|
|
function loadConsumptionTrendForPanel(panel, plan, period) {
|
|
if (!panel) {
|
|
return;
|
|
}
|
|
|
|
const section = panel.querySelector(".opportunities-extension-consumption-trend");
|
|
|
|
if (!section) {
|
|
return;
|
|
}
|
|
|
|
const subPlanNum = String(plan.subPlanNum || "").trim();
|
|
const selectedPeriod = CONSUMPTION_TREND_PERIODS.some((item) => item.value === period)
|
|
? period
|
|
: DEFAULT_CONSUMPTION_TREND_PERIOD;
|
|
const key = createConsumptionTrendKey(subPlanNum, selectedPeriod);
|
|
const chart = section.querySelector(".opportunities-extension-consumption-chart");
|
|
section.dataset.period = selectedPeriod;
|
|
chart.dataset.requestKey = key;
|
|
updateConsumptionPeriodButtons(section, selectedPeriod);
|
|
|
|
if (!subPlanNum) {
|
|
renderConsumptionTrendError(chart, "Sub plan number is unavailable.");
|
|
return;
|
|
}
|
|
|
|
const cached = consumptionTrendState.consumptionTrendCache.get(key);
|
|
|
|
renderConsumptionTrendSkeleton(chart);
|
|
|
|
if (cached && cached.status === "loading") {
|
|
cached.promise
|
|
.then((items) => renderConsumptionTrendIfCurrent(section, chart, items, selectedPeriod, subPlanNum, key))
|
|
.catch((error) => renderConsumptionTrendErrorIfCurrent(chart, error.message, key));
|
|
return;
|
|
}
|
|
|
|
const request = requestConsumerTokenServiceOnce()
|
|
.then((authorizations) => sendRuntimeMessage({
|
|
type: messageTypes.requestConsumptionTrend,
|
|
subPlanNum,
|
|
period: selectedPeriod,
|
|
authorization: authorizations && authorizations.accountPlans
|
|
}))
|
|
.then((response) => {
|
|
appendBackgroundRequestLog(response && response.debugRequests);
|
|
|
|
if (!response || !response.ok) {
|
|
throw new Error(response && response.error ? response.error : "Unable to load consumption trend.");
|
|
}
|
|
|
|
return Array.isArray(response.items) ? response.items : [];
|
|
})
|
|
.finally(() => {
|
|
if (consumptionTrendState.consumptionTrendCache.get(key)?.promise === request) {
|
|
consumptionTrendState.consumptionTrendCache.delete(key);
|
|
}
|
|
});
|
|
|
|
consumptionTrendState.consumptionTrendCache.set(key, { status: "loading", promise: request });
|
|
request
|
|
.then((items) => renderConsumptionTrendIfCurrent(section, chart, items, selectedPeriod, subPlanNum, key))
|
|
.catch((error) => renderConsumptionTrendErrorIfCurrent(chart, error.message, key));
|
|
}
|
|
|
|
function createConsumptionTrendKey(subPlanNum, period) {
|
|
return `${subPlanNum}:${period}`;
|
|
}
|
|
|
|
function updateConsumptionPeriodButtons(section, period) {
|
|
section.querySelectorAll(".opportunities-extension-consumption-periods button").forEach((button) => {
|
|
button.setAttribute("aria-pressed", String(button.dataset.period === period));
|
|
});
|
|
}
|
|
|
|
function renderConsumptionTrendIfCurrent(section, chart, items, period, subPlanNum, key) {
|
|
if (chart.dataset.requestKey === key) {
|
|
renderConsumptionTrendChart(section, chart, items, period, subPlanNum);
|
|
}
|
|
}
|
|
|
|
function renderConsumptionTrendErrorIfCurrent(chart, errorMessage, key) {
|
|
if (chart.dataset.requestKey === key) {
|
|
renderConsumptionTrendError(chart, errorMessage || "Unable to load consumption trend.");
|
|
}
|
|
}
|
|
|
|
function renderConsumptionTrendSkeleton(chart) {
|
|
chart.textContent = "";
|
|
chart.setAttribute("aria-busy", "true");
|
|
const skeleton = document.createElement("div");
|
|
skeleton.className = "opportunities-extension-consumption-chart-skeleton";
|
|
const announcement = document.createElement("span");
|
|
announcement.className = "opportunities-extension-visually-hidden";
|
|
announcement.textContent = "Loading consumption trend";
|
|
const plot = document.createElement("div");
|
|
plot.className = "opportunities-extension-consumption-chart-skeleton-plot";
|
|
|
|
for (let index = 0; index < 13; index += 1) {
|
|
const bar = document.createElement("span");
|
|
bar.style.height = `${28 + ((index * 17) % 58)}%`;
|
|
plot.append(bar);
|
|
}
|
|
|
|
skeleton.append(announcement, plot);
|
|
chart.append(skeleton);
|
|
}
|
|
|
|
function renderConsumptionTrendError(chart, errorMessage) {
|
|
chart.textContent = "";
|
|
chart.setAttribute("aria-busy", "false");
|
|
const error = document.createElement("p");
|
|
error.className = "opportunities-extension-consumption-chart-error";
|
|
error.setAttribute("role", "alert");
|
|
error.textContent = errorMessage;
|
|
chart.append(error);
|
|
}
|
|
|
|
return { createConsumptionTrendSection, loadConsumptionTrendForPanel, createConsumptionTrendKey, updateConsumptionPeriodButtons, renderConsumptionTrendIfCurrent, renderConsumptionTrendErrorIfCurrent, renderConsumptionTrendSkeleton, renderConsumptionTrendError };
|
|
}
|