1484 - Dashboard visualizations

This commit is contained in:
Jonathan Bobel
2024-05-03 11:10:41 -04:00
parent a378a58686
commit afdc0ed58d
4 changed files with 184 additions and 1 deletions

View File

@@ -0,0 +1,71 @@
(function (window) {
// Dummy data (replace with API data)
const data = {
messageStats: {
totalMessages: 1000,
delivered: 800,
pending: 100,
failed: 100
},
dailyUsage: {
dailyUsage: 20,
dailyUsageLimit: 100
},
yearlyUsage: {
yearlyUsage: 2000,
yearlyUsageLimit: 250000
}
};
// Update total messages progress bar percentages
const messageStats = data.messageStats;
const messageBars = ["delivered", "pending", "failed"];
for (const bar of messageBars) {
const percentage = messageStats[bar] / messageStats.totalMessages * 100;
const elementId = `${bar}-bar`;
const element = document.getElementById(elementId);
element.style.width = `${parseFloat(percentage)}%`;
}
// Update total messages progress bar percentages
const dailyUsage = data.dailyUsage;
const dailyUsageLimit = dailyUsage.dailyUsageLimit;
const yearlyUsage = data.yearlyUsage;
const yearlyUsageLimit = yearlyUsage.yearlyUsageLimit;
function updateUsageBar(elementId, dailyUsage, dailyUsageLimit, yearlyUsage, yearlyUsageLimit) {
// Ensure element exists
if (!elementId || !document.getElementById(elementId)) {
console.error(`Element with ID "${elementId}" not found`);
return;
}
// Calculate percentage
const percentage = dailyUsage / dailyUsageLimit * 100;
// Update bar width
const element = document.getElementById(elementId);
element.style.width = `${parseFloat(percentage)}%`;
}
// Update usage bars
updateUsageBar("dailyUsage-bar", dailyUsage.dailyUsage, dailyUsageLimit);
updateUsageBar("dailyUsageRemaining-bar", dailyUsageLimit - dailyUsage.dailyUsage, dailyUsageLimit);
updateUsageBar("yearlyUsage-bar", yearlyUsage.yearlyUsage, yearlyUsageLimit);
updateUsageBar("yearlyUsageRemaining-bar", yearlyUsageLimit - yearlyUsage.yearlyUsage, yearlyUsageLimit);
// Update total messages legend values
document.getElementById("total-value").innerText = `Total: ${messageStats.totalMessages} messages`;
document.getElementById("delivered-value").innerText = `Delivered: ${messageStats.delivered}`;
document.getElementById("pending-value").innerText = `Pending: ${messageStats.pending}`;
document.getElementById("failed-value").innerText = `Failed: ${messageStats.failed}`;
// Update usage legend values
document.getElementById("daily-usage-value").innerText = `Daily usage: ${dailyUsage.dailyUsage}`;
document.getElementById("daily-remaining-value").innerText = `Remaining messages: ${dailyUsage.dailyUsageLimit - dailyUsage.dailyUsage}`;
document.getElementById("yearly-usage-value").innerText = `Yearly usage: ${yearlyUsage.yearlyUsage}`;
document.getElementById("yearly-remaining-value").innerText = `Remaining messages: ${yearlyUsage.yearlyUsageLimit - yearlyUsage.yearlyUsage}`;
})(window);

View File

@@ -0,0 +1,79 @@
@use "uswds-core" as *;
$delivered: color('blue-50v');
$pending: color('green-cool-40v');
$failed: color('orange-30v');
.chart-container {
display: flex;
height: units(8);
&.usage {
height: units(4);
}
}
.bar {
border-radius: units(0.5);
&.delivered, &.usage {
background-color: $delivered;
margin-right: 1px;
}
&.pending{
background-color: $pending;
margin-right: 1px;
}
&.failed, &.remaining {
background-color: $failed;
}
}
.legend {
display: flex;
margin: units(1) 0;
.legend-item {
display: flex;
align-items: flex-start;
margin-right: units(2);
}
.legend-color {
width: units(3);
height: units(3);
margin-right: 0;
padding: 0;
border-radius: 2px;
background-color: $delivered;
&.pending {
background-color: $pending;
}
&.failed, &.remaining {
background-color: $failed;
}
}
.legend-value {
margin: 0 units(1);
}
}
.usa-tooltip {
line-height: 1;
.usa-tooltip__body {
width: units(mobile);
height: auto;
white-space: wrap;
line-height: 1.3;
}
}
.progress-bar {
width: 300px;
height: 20px;
background-color: #eee;
border-radius: 5px;
margin-bottom: 10px;
}
.progress-bar-inner {
height: 100%;
background-color: #007bff;
border-radius: inherit;
}

View File

@@ -18,6 +18,39 @@
{{ ajax_block(partials, updates_url, 'upcoming') }}
<h2 class="font-body-xl margin-0">
SMS Activity
</h2>
<h3 id="total-value" class="margin-y-1"></h3>
<div class="chart-container">
<div class="bar delivered" id="delivered-bar"></div>
<div class="bar pending" id="pending-bar"></div>
<div class="bar failed" id="failed-bar"></div>
</div>
<div class="legend">
<div class="legend-item">
<button type="button" class="usa-button usa-tooltip legend-color delivered" data-position="bottom"
data-classes="width-full tablet:width-auto"
title="Delivered means that the message was successfully delivered to the mobile device.">
</button>
<div class="legend-value" id="delivered-value"></div>
</div>
<div class="legend-item width-card">
<button type="button" class="usa-button usa-tooltip legend-color pending" data-position="bottom"
data-classes="width-full tablet:width-auto"
title="Pending means that Notify has sent the message, but has not received the delivery status from the carrier. Messages remain in the Pending state until Notify has received the status, typically about five minutes.">
</button>
<div class="legend-value" id="pending-value"></div>
</div>
<div class="legend-item">
<button type="button" class="usa-button usa-tooltip legend-color failed" data-position="bottom"
data-classes="width-full tablet:width-auto"
title="Failed means that the carrier could not deliver the message, generally because the phone is unavailable or the number is no longer active.">
</button>
<div class="legend-value" id="failed-value"></div>
</div>
</div>
<h2 class="font-body-2xl line-height-sans-2 margin-0">
Messages sent
</h2>

2
poetry.lock generated
View File

@@ -1517,7 +1517,6 @@ files = [
{file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"},
{file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"},
{file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"},
{file = "msgpack-1.0.8-py3-none-any.whl", hash = "sha256:24f727df1e20b9876fa6e95f840a2a2651e34c0ad147676356f4bf5fbb0206ca"},
{file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"},
]
@@ -2384,6 +2383,7 @@ files = [
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},