Making the JADA Maintenance Dashboard Task Counter Interactive: UI State Management and CloudFront Cache Invalidation
What Was Done
The JADA maintenance hub dashboard displays a "Total Tasks" card showing the current count of tracked maintenance items. This card was previously static—clicking it did nothing. The requirement was to make it actionable: clicking the card should navigate the user to the Tasks view where they can see the full task list and manage items. This required coordinating UI state management across multiple infrastructure layers: the S3-hosted HTML file, CSS styling for interactivity affordances, JavaScript event handling, and CloudFront cache invalidation.
Technical Details: The Implementation Path
1. Locating and Downloading the Source File
The maintenance hub lives in an S3 bucket (accessed via AWS CLI) rather than in local version control. The initial challenge was identifying the correct resource:
aws s3 ls s3://maintenance-hub-jada/
aws s3 cp s3://maintenance-hub-jada/index.html /tmp/maintenance_index.html
The file path /tmp/maintenance_index.html served as the working copy for inspection and modification. This S3-first deployment pattern is appropriate for single-page applications with infrequent code changes and high availability requirements—the static hosting + CloudFront edge caching strategy eliminates the need for application servers while ensuring sub-100ms response times globally.
2. Understanding Tab Navigation Architecture
The maintenance hub uses a tab-based interface with JavaScript tab switching. Inspecting the HTML revealed the pattern:
// Existing tab structure in index.html
<div class="tab-content" id="systems-tab" data-tab="systems">
<!-- Task table rendered here -->
</div>
// Tab switching function
function switchTab(tabName) {
document.querySelectorAll('.tab-content').forEach(tab => {
tab.style.display = tab.id === tabName + '-tab' ? 'block' : 'none';
});
// Update active indicator
document.querySelectorAll('.tab-button').forEach(btn => {
btn.classList.toggle('active', btn.dataset.tab === tabName);
});
}
The Systems tab (specifically the div with `id="systems-tab"`) contained the task table. The switchTab('systems') function was the established pattern for tab navigation—consistent and idempotent.
3. Adding Interactivity to the Total Tasks Card
The Total Tasks card was originally a static `
Change 1: Semantic HTML and Click Handler
Wrapped the card in a clickable container and added the onclick handler:
<div class="info-card info-card-link" onclick="switchTab('systems')" role="button" tabindex="0">
<h3>Total Tasks</h3>
<p class="stat-value">82</p>
</div>
The role="button" and tabindex="0" attributes ensure keyboard accessibility—screen reader users and keyboard-only users can activate the card using Enter/Space keys (with appropriate JavaScript handling for the keydown event if needed).
Change 2: CSS for Visual Affordance
Added a new CSS class to signal interactivity:
.info-card-link {
cursor: pointer;
transition: all 0.2s ease-in-out;
border: 2px solid transparent;
}
.info-card-link:hover {
transform: translateY(-2px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.12);
border-color: #0066cc;
}
.info-card-link:active {
transform: translateY(0);
}
The hover effect (slight upward translation + enhanced shadow + border highlight) provides immediate visual feedback that the card is clickable. The 0.2s transition timing is intentional—faster than 300ms to feel responsive, but slow enough to be perceived as intentional rather than accidental.
Change 3: Optional Keyboard Support
While the onclick handler works for click events, full keyboard support requires handling the Enter and Space keys:
document.querySelectorAll('.info-card-link').forEach(card => {
card.addEventListener('keydown', function(event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
switchTab('systems');
}
});
});
Infrastructure: S3 and CloudFront Synchronization
S3 Upload and Cache Invalidation
After modifying the HTML locally, the updated file was re-uploaded to S3:
aws s3 cp /tmp/maintenance_index.html s3://maintenance-hub-jada/index.html --cache-control "public, max-age=3600"
The --cache-control parameter sets a 1-hour expiration for the HTML object in S3. This is a safety boundary: even if CloudFront caching is misconfigured, browsers will re-validate the object after 1 hour.
CloudFront Cache Invalidation
S3 uploads do not automatically purge CloudFront edge caches. Users in different geographic regions are served from the nearest edge location, and those caches must be explicitly invalidated:
aws cloudfront create-invalidation --distribution-id E2ABC1DEF2GHIJ --paths "/index.html" --query 'Invalidation.Id' --output text
The distribution ID E2ABC1DEF2GHIJ (example; the real ID would be unique to the JADA maintenance domain) was identified from the CloudFront console. The invalidation targets only /index.html rather than /* to minimize cost—CloudFront charges per invalidation path, and targeted invalidations are cheaper and faster to complete.
The invalidation is asynchronous. The returned ID can be polled to confirm completion:
aws cloudfront get-invalidation --distribution-id E2ABC1DEF2GHIJ --id <INVALIDATION_ID>
Status transitions from InProgress → Completed typically within 60 seconds, though edge locations in remote regions may take longer.
Why These Design Decisions
- S3 + CloudFront over traditional hosting: Eliminates server management, provides automatic global distribution, and scales to handle traffic spikes with zero operational overhead. The tradeoff is no server-side logic or dynamic content—appropriate for a dashboard that pulls data via API calls.
- Tab switching via JavaScript: Keeps state in the browser DOM rather than requiring server round-trips. All tab content is loaded in the initial HTML payload, making tab switches instant (no network latency). The pattern is RESTless but appropriate for small, self-contained dashboards.
- CSS transitions for hover/active states: Modern UX expectation. The subtle animation signals that the element is interactive without being jarring. The 2px upward translation is barely perceptible but sufficient to register as feedback.