Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
5edf6f5
Initial widget implementation from Claude.
jkuester Dec 17, 2025
8f1778d
Split into separate files since things is getting large.
jkuester Dec 17, 2025
0ed2f72
Tweak input parameters to just be the most relevant.
jkuester Dec 17, 2025
2390d55
Add pie chart with the cost breakdown
jkuester Dec 17, 2025
dc85f82
Clean up Annual Cost Estimate widget
jkuester Dec 17, 2025
9b785fc
Tweak Recommended Host widget
jkuester Dec 17, 2025
88c656c
Tweak cost breakdown labels and adjust Recommended Host layout
jkuester Dec 17, 2025
ffcaa94
Refactor layout to include estimated user count in Cost Calculator wi…
jkuester Dec 17, 2025
124c9d8
Swap 'Age of Deployment' and 'Population Served' fields in Cost Calcu…
jkuester Dec 17, 2025
977550f
Simplify Cost Calculator widget by removing unused metrics and detail…
jkuester Dec 18, 2025
fbc46f7
Rearrange HTML sections in Cost Calculator for improved structure and…
jkuester Dec 18, 2025
cef3bf6
Prefix instance names with "EC2" in Cost Calculator for clarity.
jkuester Dec 18, 2025
13f3b6b
Refactor cost calculations in Cost Calculator to use constants for im…
jkuester Dec 18, 2025
43aa078
Add advanced parameter support and toggle functionality in Cost Calcu…
jkuester Dec 18, 2025
9c1461d
Enforce minimum values for advanced parameters in Cost Calculator and…
jkuester Dec 18, 2025
de483f6
Improve layout of input groups in Cost Calculator with consistent spa…
jkuester Dec 18, 2025
ac8c5da
Add user count slider to Cost Calculator and update related calculati…
jkuester Dec 18, 2025
b05a719
Add "People per User" metric and visualization to Cost Calculator.
jkuester Dec 18, 2025
359322c
Add "Docs per User" metric and visualization to Cost Calculator. Upda…
jkuester Dec 18, 2025
15f247b
Add "Resource Utilization" metric and visualization to Cost Calculato…
jkuester Dec 18, 2025
4a1406d
Add "Disk Usage Breakdown" metric and visualization to Cost Calculato…
jkuester Dec 18, 2025
9d2a275
Add "Monthly Cost" metric to Cost Calculator. Update layout and calcu…
jkuester Dec 18, 2025
0ccea1d
Simplify code
jkuester Dec 18, 2025
8f87ab7
Simplify html/css
jkuester Dec 18, 2025
1ccfa5c
Tweak up grid sizing
jkuester Dec 18, 2025
dde8720
Initial manual refactoring
jkuester Dec 19, 2025
5b7b2a0
More tweaks and cleanup
jkuester Dec 19, 2025
069ed5f
Move remaining styles to css
jkuester Dec 19, 2025
14604b6
Clean up js
jkuester Dec 19, 2025
9d005c6
Switch from chart.js to just a css pie chart.
jkuester Dec 19, 2025
1ff995e
Clean and left-aligned
jkuester Dec 19, 2025
e587bbf
Remove cost calculator info callout and add margin-top to calculator …
jkuester Dec 19, 2025
8f9b130
Refactor viz-section layout for flexibility and improved styling.
jkuester Dec 19, 2025
008d619
Add "Cost Per User" calculation and styling to cost calculator.
jkuester Dec 19, 2025
4df5238
Set range-labels width to 100% for consistent alignment.
jkuester Dec 19, 2025
b0d1189
Merge branch 'main' into cost-calculator
jkuester Jan 16, 2026
0cf7397
Make parameter number boxes editable
jkuester Jan 16, 2026
d00e00d
Remove unnecessary decimal data
jkuester Jan 16, 2026
f904b01
Add reset button for advanced parameters
jkuester Jan 16, 2026
f1d1fbf
Clean up more around the interface
jkuester Jan 16, 2026
3df4046
Give the Number of Users selector a step value
jkuester Jan 16, 2026
13a1231
Better background/boarder contrast in light-mode
jkuester Jan 23, 2026
56ba489
Simplify the CSS grid
jkuester Jan 23, 2026
06497bc
Make the Recommended Host content responsive
jkuester Jan 23, 2026
326f3d5
Give everything consistent width on mobile.
jkuester Jan 23, 2026
cf340d0
Add separator between Recommended Host columns
jkuester Jan 23, 2026
664040c
Move age of deployment to Advanced Parameters
jkuester Jan 23, 2026
93f36fd
Add sub-titles to Parameters
jkuester Jan 23, 2026
7f5cfbd
Make Advanced Parameters scrollable
jkuester Jan 23, 2026
d9ff619
Clean up parameters layout to make it more consistent
jkuester Jan 24, 2026
b01ba9c
Show cost per user per year
jkuester Jan 24, 2026
929f793
Merge branch 'main' into cost-calculator
jkuester Mar 5, 2026
8880055
Remove workflow docs per year config (just using `1`)
jkuester Mar 9, 2026
6eb82b2
Set new DOCS_PER_GB value
jkuester Mar 9, 2026
852b1fc
Remove contacts_per_place logic. Instead just assume 0.36 places per …
jkuester Mar 9, 2026
28e8f13
Remove instance name logic
jkuester Mar 9, 2026
ff06e7f
Update instance cost logic to be based purely on a per-cpu cost.
jkuester Mar 9, 2026
b02680d
Remove resource utilization visualization
jkuester Mar 9, 2026
37cea09
Refactor Recommended Host section to use inner columns for cost.
jkuester Mar 9, 2026
86c57ab
Clean up interface
jkuester Mar 9, 2026
ee565c3
Add totalDocCount tool-tip
jkuester Mar 9, 2026
300e91d
Change default workflows to 4
jkuester Mar 9, 2026
4a4cb16
Use ceiling of disk GB.
jkuester Mar 9, 2026
7b1adec
Adjust per user label colors based on value.
jkuester Mar 9, 2026
120e778
Tweak defaults and limits
jkuester Mar 10, 2026
83b9dab
Include root disk size in model
jkuester Mar 10, 2026
9f875ed
Update over provisioning to 3
jkuester Mar 10, 2026
9fdd951
First pass at revamping the hosting costs page.
jkuester Mar 10, 2026
22e3708
Clean up additional page contents
jkuester Mar 10, 2026
ade10cd
Move Calculation details section up in page ordering
jkuester Mar 18, 2026
7784848
Format numbers according to the locale
jkuester Mar 18, 2026
92e7a37
Fix setting locale
jkuester Mar 18, 2026
4b54fdb
Remove labels from the user range-bars
jkuester Mar 18, 2026
8c65fcc
Clean up layout
jkuester Mar 18, 2026
b9a0870
Move js file to assets
jkuester Mar 18, 2026
2b725a8
Clean up, simplify implementation
jkuester Mar 18, 2026
1c98b69
Clean up, simplify implementation
jkuester Mar 18, 2026
4df620e
Clean up, simplify implementation
jkuester Mar 18, 2026
de9e3c7
Clean up and format js code
jkuester Mar 18, 2026
0039ceb
Apply suggestion from @mrjones-plip
jkuester Mar 18, 2026
f9b952e
Remove dup title front-matter
jkuester Mar 18, 2026
79791b6
Address code review comments
jkuester Mar 20, 2026
9c14974
Extract constants for input params to JS
jkuester Mar 20, 2026
e0a5676
Clean up js
jkuester Mar 24, 2026
9f4088d
Switch "user" to "health worker"
jkuester Mar 27, 2026
0f637b5
Update based on review comments
jkuester Mar 27, 2026
d7079cd
Fix whitespace wrapping in FF.
jkuester Mar 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
336 changes: 336 additions & 0 deletions assets/css/cost-calculator.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,336 @@
:root {
--calc-border: #a4a4a4;
--calc-text: #1f2937;
--calc-text-light: #6b7280;
--calc-input-bg: #f9fafb;
--calc-input-border: #d1d5db;
--calc-card-bg: #efefef;
--calc-label-bg: #f3f4f6;

--calc-link: #3b82f6;
--calc-grad-start: #10b981;
--calc-grad-mid: #f59e0b;
--calc-grad-end: #ef4444;
}

html.dark {
--calc-border: #374151;
--calc-text: #f9fafb;
--calc-text-light: #9ca3af;
--calc-input-bg: #374151;
--calc-input-border: #4b5563;
--calc-card-bg: #111827;
--calc-label-bg: #374151;

--calc-link: #60a5fa;
--calc-grad-start: #34d399;
}

.cht-cost-calculator {
width: 100%;
margin-top: 2rem;
display: grid;
gap: 1rem;
max-width: 48rem;

.calc-hidden {
display: none !important;
}
.calc-text-muted {
color: var(--calc-text-light);
}
.calc-text-blue {
color: var(--calc-link);
}
.calc-text-orange {
color: var(--calc-grad-mid);
}

.calc-divider {
padding-top: 1.5rem;
border-top: 1px solid var(--calc-border);
}

.calc-label {
font-size: 0.875rem;
font-weight: 500;
color: var(--calc-text-light);
margin-bottom: 0.5rem;
}
.range-bar {
position: relative;
height: 1rem;
background: linear-gradient(to right, var(--calc-grad-start), var(--calc-grad-mid), var(--calc-grad-end));
border-radius: 4px;
margin-bottom: 0.25rem;

.range-marker {
position: absolute;
top: -0.25rem;
width: 3px;
height: 1.5rem;
background: white;
border: 2px solid var(--calc-text);
transition: left 0.3s ease;
}
}
.calc-link {
color: var(--calc-link);
font-size: 0.9rem;
font-weight: 500;
background: none;
border: none;
padding: 0;
cursor: pointer;
}
.advanced-footer > :last-child {
float: right;
}
.inline-cost {
text-align: right;
}
.inline-cost-yearly {
font-size: 1.5rem;
font-weight: bold;
color: var(--calc-link);
white-space: nowrap;
}
.inline-cost-monthly {
font-size: 0.75rem;
color: var(--calc-text-light);
}

.calc-card {
background: var(--calc-card-bg);
border: 1px solid var(--calc-border);
border-radius: 8px;
padding: 1.5rem;
max-width: 24rem;

h3 {
margin: 0 0 1.25rem 0;
}
}
.calc-card.params {
display: flex;
flex-direction: column;

.advanced-inputs-scroll {
overflow-y: auto;
min-height: 0;
max-height: 19rem;
margin-right: -0.75rem;
padding-right: 0.25rem;
scrollbar-width: thin;
scrollbar-color: transparent transparent;
&:hover {
scrollbar-color: var(--calc-border) transparent;
}
}

> .calc-divider {
margin-top: auto;
}

.label-with-value {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 0.5rem;
font-weight: 500;
font-size: 0.9rem;
}

.input-value {
background: var(--calc-label-bg);
padding: 0.25rem 0.5rem;
border: 1px solid var(--calc-input-border);
border-radius: 4px;
font-size: 0.85rem;
font-weight: 600;
color: var(--calc-text);
width: 4.5rem;
text-align: right;
}
.input-value:focus {
outline: none;
border-color: var(--calc-link);
}
/* Hide spin buttons for number inputs */
.input-value::-webkit-outer-spin-button,
.input-value::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.input-value[type=number] {
-moz-appearance: textfield;
}

.calc-input {
width: 100%;
padding: 0;
height: 2rem;
cursor: pointer;
}

.helper-text {
font-size: 0.8rem;
color: var(--calc-text-light);
margin-top: 0.25rem;
}

.advanced-input-group {
margin-bottom: 1.25rem;

.advanced-input {
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
margin-bottom: 0.25rem;

label {
margin: 0;
flex: 1;
}
}
}
}
.calc-card.cost {
.total-cost {
text-align: center;
font-size: 2.5rem;
font-weight: bold;
color: var(--calc-link);
margin-bottom: 0.25rem;
}
.monthly-cost {
text-align: center;
font-size: 1rem;
color: var(--calc-text-light);
margin-bottom: 1rem;
}
.cost-pie {
--instance-pct: 50;
width: 12rem;
height: 12rem;
margin: 0 auto 1rem;
border-radius: 50%;
background: conic-gradient(
var(--calc-link) 0% calc(var(--instance-pct) * 1%),
var(--calc-grad-start) calc(var(--instance-pct) * 1%) 100%
);
}
.cost-legend {
display: flex;
flex-direction: column;
gap: 0.5rem;
align-items: center;
}
.cost-legend-item {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.9rem;
}
.cost-legend-color {
display: inline-block;
width: 16px;
height: 16px;
border-radius: 4px;
}
.cost-legend-instance {
background: var(--calc-link);
}
.cost-legend-disk {
background: var(--calc-grad-start);
}
}
.calc-card.users {
.calc-label {
font-size: 1rem;
margin-right: 0.5rem;
}
.cost-per-user {
display: flex;
justify-content: space-between;
align-items: baseline;
margin-bottom: 1.5rem;
}

.viz-section {
margin-bottom: 1.5rem;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: baseline;

.viz-value {
font-size: 1.5rem;
font-weight: bold;
margin-bottom: 0.5rem;
}

.range-bar {
width: 100%;
}
}
.viz-section:last-child {
margin-bottom: 0;
}
}
.calc-card.host {
.host-value-large {
font-size: 1.25rem;
font-weight: bold;
margin-bottom: 0.5rem;
}

.host-section-row {
display: flex;
justify-content: space-between;
}

.disk-bar {
display: flex;
height: 20px;
border-radius: 4px;
overflow: hidden;
margin-top: 0.5rem;
}
.disk-bar-segment {
height: 100%;
transition: width 0.3s ease;
}
.disk-bar-segment-root {
background: var(--calc-text-light);
}
.disk-bar-segment-db {
background: var(--calc-link);
}
.disk-bar-segment-overprovision {
background: var(--calc-grad-mid);
}

.breakdown-legend {
margin-top: 0.5rem;
font-size: 0.8rem;
font-weight: 600;
}
.breakdown-label {
color: var(--calc-text-light);
font-weight: normal;
margin-right: 0.25rem;
}
}
}

@media (min-width: 1024px) {
.cht-cost-calculator {
grid-template-columns: repeat(12, 1fr);
}
.calc-card.params { grid-column: span 6; }
.calc-card.cost { grid-column: span 6; }
.calc-card.users { grid-column: span 6; }
.calc-card.host { grid-column: span 6; }
}
Loading
Loading