1 Commits
Author SHA1 Message Date
woggioni 888fb46f4e Split database config into DATABASE_* components
Assemble the Postgres DSN from DATABASE_ENGINE/HOST/PORT/NAME/USER/
PASSWORD/OPTIONS so only the password needs to live in a secret; the
rest can go in a ConfigMap. DATABASE_URL remains a full-DSN override
(used by the sqlite test suite). Credentials are percent-encoded, the
port and options are omitted when empty, and the k8s migrate
initContainer now also reads the config ConfigMap.
2026-09-17 11:45:53 +00:00
6 changed files with 4 additions and 29 deletions
-1
View File
@@ -1,3 +1,2 @@
pub mod card; pub mod card;
pub mod summary; pub mod summary;
pub mod toast;
-20
View File
@@ -1,20 +0,0 @@
//! Auto-dismissing error toast.
use gloo_timers::callback::Timeout;
use sycamore::prelude::*;
const TOAST_MS: u32 = 10_000;
/// Renders the error from `error` as a toast; hides it after `TOAST_MS`.
/// A new error replaces the message and restarts the timer.
pub fn toast(error: Signal<Option<String>>) -> View {
create_effect(move || {
if error.get_clone().is_some() {
// Held until cleanup; dropped (cancelled) when the effect re-runs.
let timeout = Timeout::new(TOAST_MS, move || error.set(None));
on_cleanup(move || drop(timeout));
}
});
view! {
(move || error.get_clone().map(|e| view! { div(class="toast") { (e) } }))
}
}
+1 -2
View File
@@ -3,7 +3,6 @@ use sycamore::prelude::*;
use crate::components::card::{card_back, card_img}; use crate::components::card::{card_back, card_img};
use crate::components::summary::{hand_summary_modal, summary_rows}; use crate::components::summary::{hand_summary_modal, summary_rows};
use crate::components::toast::toast;
use crate::model::{card_label, GameView, MoveView, PlayerView, Scores, ServerMessage}; use crate::model::{card_label, GameView, MoveView, PlayerView, Scores, ServerMessage};
use crate::ws::{self, GameSocket}; use crate::ws::{self, GameSocket};
@@ -124,7 +123,7 @@ pub fn GamePage(id: String) -> View {
view! { view! {
div(class="game-page") { div(class="game-page") {
(toast(error)) (move || error.get_clone().map(|e| view! { div(class="toast") { (e) } }))
(move || match game.get_clone() { (move || match game.get_clone() {
None => { None => {
let status = if closed.get() { let status = if closed.get() {
+1 -2
View File
@@ -3,7 +3,6 @@ use wasm_bindgen_futures::spawn_local;
use sycamore::prelude::*; use sycamore::prelude::*;
use crate::api; use crate::api;
use crate::components::toast::toast;
use crate::model::MatchesPage; use crate::model::MatchesPage;
#[component] #[component]
@@ -46,7 +45,7 @@ pub fn HistoryPage() -> View {
a(href="/leaderboard") { "Leaderboard" } a(href="/leaderboard") { "Leaderboard" }
} }
h1 { "My matches" } h1 { "My matches" }
(toast(error)) (move || error.get_clone().map(|e| view! { div(class="toast") { (e) } }))
(move || match page.get_clone() { (move || match page.get_clone() {
None => view! { p(class="status") { "Loading…" } }, None => view! { p(class="status") { "Loading…" } },
Some(_) if rows.get_clone().is_empty() => view! { Some(_) if rows.get_clone().is_empty() => view! {
+1 -2
View File
@@ -3,7 +3,6 @@ use wasm_bindgen_futures::spawn_local;
use sycamore::prelude::*; use sycamore::prelude::*;
use crate::api; use crate::api;
use crate::components::toast::toast;
use crate::model::LeaderboardPage; use crate::model::LeaderboardPage;
#[component] #[component]
@@ -25,7 +24,7 @@ pub fn LeaderboardPage() -> View {
a(href="/history") { "My matches" } a(href="/history") { "My matches" }
} }
h1 { "Leaderboard" } h1 { "Leaderboard" }
(toast(error)) (move || error.get_clone().map(|e| view! { div(class="toast") { (e) } }))
(move || match page.get_clone() { (move || match page.get_clone() {
None => view! { p(class="status") { "Loading…" } }, None => view! { p(class="status") { "Loading…" } },
Some(p) => { Some(p) => {
+1 -2
View File
@@ -4,7 +4,6 @@ use sycamore::prelude::*;
use sycamore_router::navigate; use sycamore_router::navigate;
use crate::api; use crate::api;
use crate::components::toast::toast;
use crate::model::{GameTypeInfo, User}; use crate::model::{GameTypeInfo, User};
/// Used when the game-types fetch fails: match creation must still work. /// Used when the game-types fetch fails: match creation must still work.
@@ -71,7 +70,7 @@ pub fn LobbyPage() -> View {
view! { view! {
div(class="lobby") { div(class="lobby") {
h1 { "Scopone scientifico" } h1 { "Scopone scientifico" }
(toast(error)) (move || error.get_clone().map(|e| view! { div(class="toast") { (e) } }))
(move || match user.get_clone() { (move || match user.get_clone() {
None => view! { p(class="status") { "Loading…" } }, None => view! { p(class="status") { "Loading…" } },
Some(None) => view! { Some(None) => view! {