diff --git a/src/handlers/wizard.rs b/src/handlers/wizard.rs index ee47b70..9e1709b 100644 --- a/src/handlers/wizard.rs +++ b/src/handlers/wizard.rs @@ -69,7 +69,11 @@ pub async fn create_step_1( return r.into_response(); } let base = parse_wizard_base(&q); - let (regions, _lookup) = load_regions_wrapper(&state).await; + let (all_regions, _lookup) = load_regions_wrapper(&state).await; + // Filter to only show active, non-hidden regions + let regions: Vec = all_regions.into_iter() + .filter(|r| r.is_active && !r.is_hidden) + .collect(); let mut region_sel = base.region.clone(); if region_sel.is_empty() && !regions.is_empty() { region_sel = regions[0].id.clone(); diff --git a/src/models/os_item.rs b/src/models/os_item.rs index 6b19540..74262d9 100644 --- a/src/models/os_item.rs +++ b/src/models/os_item.rs @@ -7,6 +7,7 @@ pub struct OsItem { pub family: String, pub arch: Option, pub min_ram: Option, + #[serde(default)] pub is_default: bool, pub is_active: bool, } diff --git a/static/4k.css b/static/4k.css new file mode 100644 index 0000000..8af10c4 --- /dev/null +++ b/static/4k.css @@ -0,0 +1,52 @@ +/* 4K displays (2560px and above) */ + +/* Maximum columns for 4K displays */ +.product-grid { + grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); +} + +div[data-admin-grid] { + grid-template-columns: repeat(auto-fit, minmax(450px, 1fr)); +} + +.grid-4k-6 { + grid-template-columns: repeat(6, 1fr); +} + +.grid-4k-8 { + grid-template-columns: repeat(8, 1fr); +} + +.grid-4k-12 { + grid-template-columns: repeat(12, 1fr); +} + +/* Extra wide navigation for 4K */ +body { + grid-template-columns: 360px 1fr; +} + +nav { + width: 360px; +} + +nav div[role="navigation"] a { + font-size: 1.1rem; + padding: var(--space-4); +} + +main { + padding: calc(var(--space-6) * 1.5); +} + +/* Extra large region icons */ +.region-icon { + width: 64px; + height: 64px; +} + +/* Even more generous table spacing */ +table.table-responsive th, +table.table-responsive td { + padding: var(--space-5); +} diff --git a/static/desktop.css b/static/desktop.css new file mode 100644 index 0000000..23a0e88 --- /dev/null +++ b/static/desktop.css @@ -0,0 +1,40 @@ +/* Desktop (1024px - 1535px) */ + +/* Increase grid columns for more screen space */ +.product-grid { + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); +} + +div[data-admin-grid] { + grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); +} + +.grid-lg-2 { + grid-template-columns: repeat(2, 1fr); +} + +.grid-lg-3 { + grid-template-columns: repeat(3, 1fr); +} + +.grid-lg-4 { + grid-template-columns: repeat(4, 1fr); +} + +.grid-lg-6 { + grid-template-columns: repeat(6, 1fr); +} + +/* Wider navigation for desktop */ +nav { + width: 280px; +} + +main { + padding: var(--space-6); +} + +/* Show desktop-only elements */ +.hide-desktop { + display: none !important; +} diff --git a/static/large-desktop.css b/static/large-desktop.css new file mode 100644 index 0000000..8576e04 --- /dev/null +++ b/static/large-desktop.css @@ -0,0 +1,52 @@ +/* Large desktop (1536px - 2559px) */ + +/* Even more columns for large screens */ +.product-grid { + grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); +} + +div[data-admin-grid] { + grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); +} + +.grid-2xl-4 { + grid-template-columns: repeat(4, 1fr); +} + +.grid-2xl-6 { + grid-template-columns: repeat(6, 1fr); +} + +.grid-2xl-8 { + grid-template-columns: repeat(8, 1fr); +} + +/* Wider navigation for large screens */ +body { + grid-template-columns: 300px 1fr; +} + +nav { + width: 300px; +} + +nav div[role="navigation"] a { + font-size: 1rem; + padding: var(--space-3) var(--space-4); +} + +main { + padding: calc(var(--space-6) * 1.25); +} + +/* More generous table spacing */ +table.table-responsive th, +table.table-responsive td { + padding: var(--space-4); +} + +/* Larger region icons */ +.region-icon { + width: 48px; + height: 48px; +} diff --git a/static/mobile.css b/static/mobile.css new file mode 100644 index 0000000..0e0459c --- /dev/null +++ b/static/mobile.css @@ -0,0 +1,80 @@ +/* Mobile phones (300px - 479px) */ + +/* Ensure touch-friendly elements on small screens */ +button, +a.btn, +input[type="submit"], +input[type="button"] { + min-height: 48px; + font-size: 1rem; +} + +/* Stacked buttons on mobile */ +.button-group { + display: flex; + flex-direction: column; + gap: var(--space-2); +} + +.button-group button, +.button-group a.btn { + width: 100%; +} + +/* Mobile navigation - fixed top */ +nav { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1000; +} + +main { + margin-top: 70px; +} + +/* Mobile-friendly tables - card layout */ +table.table-responsive, +table.table-responsive thead, +table.table-responsive tbody, +table.table-responsive th, +table.table-responsive td, +table.table-responsive tr { + display: block; +} + +table.table-responsive thead tr { + position: absolute; + top: -9999px; + left: -9999px; +} + +table.table-responsive tr { + margin-bottom: var(--space-4); + border: 1px solid var(--border-color); + border-radius: var(--border-radius); + padding: var(--space-3); + background: var(--canvas-bg); +} + +table.table-responsive td { + border: none; + position: relative; + padding-left: 50%; + padding-top: var(--space-2); + padding-bottom: var(--space-2); +} + +table.table-responsive td:before { + content: attr(data-label); + position: absolute; + left: var(--space-3); + font-weight: 600; + color: var(--text-muted); +} + +/* Hide desktop-only elements */ +.hide-mobile { + display: none !important; +} diff --git a/static/phone.css b/static/phone.css new file mode 100644 index 0000000..8b50c14 --- /dev/null +++ b/static/phone.css @@ -0,0 +1,30 @@ +/* Small phones (480px - 767px) */ + +/* Grid adjustments for small phones */ +.grid-sm-2 { + grid-template-columns: repeat(2, 1fr); +} + +.product-grid { + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); +} + +/* Adjust button sizing */ +button, +a.btn { + min-height: 44px; +} + +/* Side-by-side buttons for small phones */ +.button-group { + display: flex; + flex-direction: row; + gap: var(--space-2); + flex-wrap: wrap; +} + +.button-group button, +.button-group a.btn { + flex: 1 1 auto; + min-width: 120px; +} diff --git a/static/styles.css b/static/styles.css index 156f988..faabf2c 100644 --- a/static/styles.css +++ b/static/styles.css @@ -2506,3 +2506,59 @@ code { border-bottom-color: var(--red-400); color: var(--red-700); } + +/* Badge Styles */ +.badge { + display: inline-flex; + align-items: center; + padding: 0.25rem 0.5rem; + font-size: 0.75rem; + font-weight: 600; + border-radius: var(--border-radius); + background-color: var(--gray-100); + color: var(--text-secondary); + border: 1px solid var(--border-color); +} + +.badge-premium { + background-color: #ffd700; + color: #000; + border-color: #ffcd00; +} + +.badge-warning { + background-color: var(--red-100); + color: var(--red-700); + border-color: var(--red-400); +} + +.badge-success { + background-color: #d1f4e0; + color: #0f5132; + border-color: #0f5132; +} + +.badge-security { + background-color: #cfe2ff; + color: #084298; + border-color: #084298; +} + +/* Application card styles */ +.app-header { + display: flex; + justify-content: space-between; + align-items: start; + gap: 0.5rem; + margin-bottom: 0.5rem; +} + +.badge-container { + display: flex; + gap: 0.25rem; + flex-wrap: wrap; +} + +.product-card--inactive { + opacity: 0.6; +} diff --git a/templates/base.html b/templates/base.html index dbd5b53..e93a31b 100644 --- a/templates/base.html +++ b/templates/base.html @@ -6,7 +6,12 @@ {% block title %}Zy{% endblock %} + + + + + {% if current_user.is_some() %} diff --git a/templates/change_os_instance.html b/templates/change_os_instance.html index d3b6381..4ee9e8d 100644 --- a/templates/change_os_instance.html +++ b/templates/change_os_instance.html @@ -65,7 +65,7 @@

⚠️ Warning

@@ -83,12 +83,12 @@

⚠️ Warning

- Select the operating system you want to install on this instance. + Select the operating system you want to install on this instance. Unavailable OS options are disabled.