diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..6b7b557 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,3 @@ +# spow (proof of work for leptos-captcha) needs the getrandom backend selected for the browser +[target.wasm32-unknown-unknown] +rustflags = ['--cfg', 'getrandom_backend="wasm_js"'] diff --git a/.claude/rules/backend.md b/.claude/rules/backend.md index 9122abe..30246de 100644 --- a/.claude/rules/backend.md +++ b/.claude/rules/backend.md @@ -11,7 +11,8 @@ paths: ## Server functions - One file per domain in `src/backend/`. Server-only helpers and their imports go in the `cfg_if! { if #[cfg(feature = "ssr")] { ... }}` block at the top; `#[server]` functions follow below it. Extra server-only imports inside a server fn body are written as local `use` statements. -- Use plain `#[server]` for new functions (older ones spell out `#[server(Name, "/api", "Url", "name")]`; both end up under `/api`). +- Use plain `#[server]` for new functions (a few older ones use `#[server(name = Name, prefix = "/api", endpoint = "name")]`; both end up under `/api`). The positional form with `"Url"` no longer compiles. Server functions are registered by `leptos_routes` in `src/main.rs`; there is no separate `/api` route. +- The current request is `use_context::()` (it derefs to `HttpRequest`); extractors go through `leptos_actix::extract().await?`. - Return `Result, ServerFnError>`. Expected/business failures are `Ok(ApiResponse::Error("English message".to_string()))` — the client passes that string through `trl()`, so add it to the catalogue. `Err(ServerFnError)` is for real failures (DB down etc.). - A function used with `` / `` must return `ApiResponse<()>` and take the form entity as a single struct argument; its name is the prefix of the form field names (`company: Company` ↔ `name="company[name]"`). - For ``, implement `ForValidation` for the generated struct (PascalCase of the fn name) right below the function: diff --git a/.claude/rules/frontend.md b/.claude/rules/frontend.md index f9c6bd2..c563337 100644 --- a/.claude/rules/frontend.md +++ b/.claude/rules/frontend.md @@ -12,15 +12,25 @@ paths: ## Components -- Leptos 0.6 API only. Components are `#[component]` functions returning `impl IntoView`, one page or dialog per file in `src/pages/`; reusable building blocks go to `src/components/`. Register new files in the respective `mod.rs` (`pub mod` only if used from `app.rs`). +- Leptos 0.8 API only (`use leptos::prelude::*`). Components are `#[component]` functions returning `impl IntoView`, one page or dialog per file in `src/pages/`; reusable building blocks go to `src/components/`. Register new files in the respective `mod.rs` (`pub mod` only if used from `app.rs`). - This code runs on the server (SSR) and in the browser (hydration). Browser-only APIs (`window()`, `web_sys`) must not run during SSR — keep them in event handlers/effects or behind `#[cfg(not(feature = "ssr"))]`. Markup must render the same on both sides or hydration breaks. - A new admin page needs a `` in `src/app.rs` wrapped in ``, and a menu entry in `src/components/admin_portal.rs`. Paths starting with `/admin` are login-protected by the middleware; data access is still guarded by `perm_check!` in the server fn. +## Leptos 0.8 pitfalls + +- Views are statically typed: `if`/`else` and `match` arms that return different markup must each end with `.into_any()`. +- Context is not available in event handlers (`on:click` etc.). Call `use_context` in the component body and keep the result — `DialogOpener` and `MenuOpener` do this in `new()`, so create them in a component body, not inside a handler. +- Markup must be valid HTML, or hydration panics in the browser and the whole page stops reacting: no block elements (`
`, ``, another `

`) inside `

`, and `

` only inside ``/``. The compiler doesn't catch this — load the page with a full reload and check the browser console. +- HTML attributes are typed. Deprecated ones (`align`, `width` on `
`) don't compile; use `style`. +- A value used twice in one `view!` (e.g. in an attribute and as a child) must be cloned for the first use. +- Client-side form validation hooks into `` with `on:submit:capture` and `ev.prevent_default()`; a plain `on:submit` runs too late. `DataForm` already does this. +- `action.value()` is not an `RwSignal`; pass it on as `Signal::derive(move || action.value().get())`. + ## Data loading and forms -- Load data with `create_blocking_resource` / `create_resource` calling the server fn, rendered inside `` with `{trl("Loading...")}`. Use a dialog's `opener.visible()` as the resource source so lists reload after the dialog closes (see `src/pages/users.rs`). +- Load data with `Resource::new_blocking` / `Resource::new` calling the server fn, rendered inside `` with `{trl("Loading...")}`. Read the resource in a closure — `{move || res.get().map(...)}` — a plain `{res.get()...}` block is evaluated once and never updates. Use a dialog's `opener.visible()` as the resource source so lists reload after the dialog closes (see `src/pages/users.rs`). - Handle all three outcomes of a server call: `Err(e)`, `Ok(ApiResponse::Error(msg))`, `Ok(ApiResponse::Data(d))`. -- Edit/create dialogs: `DialogOpener::new()` in the parent, `create_server_action::()` in the dialog, wrapped in ``. It supplies the modal, Save/Close buttons, client validation and server error display. Confirmations use ``. +- Edit/create dialogs: `DialogOpener::new()` in the parent, `ServerAction::::new()` in the dialog, wrapped in ``. It supplies the modal, Save/Close buttons, client validation and server error display. Confirmations use ``. - Form field names follow the server fn argument: `name="company[name]"`. Pass the id as a hidden input. Fill inputs with `prop:value={move || signal.get().field}`. - `DataForm`/`ModalDialog` take `title` as an untranslated English key (`&'static str`); they translate it themselves. diff --git a/CLAUDE.md b/CLAUDE.md index d156e57..32a14f1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ # Rezervovator -Booking system for sport/service facilities. Full-stack Rust: Leptos 0.6 (SSR + hydration) on Actix Web, PostgreSQL via sqlx. Crate name is `rezervator`, product name is "Rezervovator". +Booking system for sport/service facilities. Full-stack Rust: Leptos 0.8 (SSR + hydration) on Actix Web, PostgreSQL via sqlx. Crate name is `rezervator`, product name is "Rezervovator". One crate, compiled twice by cargo-leptos: @@ -19,7 +19,7 @@ cargo check --lib --features hydrate --target wasm32-unknown-unknown # type-ch cargo test --features ssr # unit tests ``` -Run both `cargo check` commands and the tests after any change; a plain `cargo check` / `cargo test` (no features) checks neither side properly. +Run both `cargo check` commands and the tests after any change. They don't catch hydration errors, so after changing a view also load the page in a browser with a full reload (the browser caches the old WASM otherwise) and check the console; a plain `cargo check` / `cargo test` (no features) checks neither side properly. Unit tests are `#[cfg(test)] mod tests` at the bottom of the file they test (`#[cfg(all(test, feature = "ssr"))]` for ssr-only code). They cover pure logic only — parsing, validation, paging, slot merging, mail templates, config. Nothing touches the database, so server functions, permissions and SQL are untested. Add tests for new pure logic; keep them free of DB and network. @@ -54,8 +54,10 @@ Routes: `/` public booking form, `/login`, `/admin`, `/admin/settings`, `/admin/ - Code, comments, identifiers, log messages and commit messages are in English. UI strings are English keys translated at runtime (see `.claude/rules/frontend.md`). - Commit messages are always written in English, even when the conversation is in Czech: short past-tense sentences ending with a period, e.g. "Added setting for closing days." - The project has no rustfmt config and the code is not rustfmt-formatted. Don't run `cargo fmt` over existing files; match the surrounding style and keep diffs limited to what you changed. -- Leptos is 0.6 — use the 0.6 API (`create_signal`, `create_resource`, `create_server_action`, `#[component]` returning `impl IntoView`), not 0.7/0.8 (`signal()`, `Resource::new`, …). -- `wasm-bindgen` is pinned to `=0.2.100`; it must match the wasm-bindgen version of the installed cargo-leptos. Don't bump it on its own. +- Leptos is 0.8 — use the 0.8 API (`use leptos::prelude::*`, `signal()`, `RwSignal::new`, `Resource::new_blocking`, `ServerAction::::new()`), not the 0.6 `create_*` functions. +- `wasm-bindgen` is pinned to an exact version in `Cargo.toml`. The `wasm-bindgen` CLI that cargo-leptos runs must be exactly the same version (`cargo install -f wasm-bindgen-cli --version `), otherwise the front-end build fails with a schema version mismatch. Leptos 0.8 needs at least 0.2.108. Change the pin and the CLI together, never one of them. +- `#![recursion_limit = "512"]` at the top of `src/lib.rs` and `src/main.rs` is required: without it the release build fails with "queries overflow the depth limit". +- `.cargo/config.toml` selects the `getrandom` backend for the WASM target (needed by the captcha's proof of work). `getrandom` and `uuid` have their `js` features enabled in `Cargo.toml` for the same reason; don't remove them. - Version lives in `Cargo.toml` and is shown in the page footer. Detailed rules are in `.claude/rules/`: `backend.md`, `frontend.md`, `database.md`. diff --git a/Cargo.lock b/Cargo.lock index 56d24d3..852fece 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,23 +44,22 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.9.0" +version = "3.18.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48f96fc3003717aeb9856ca3d02a8c7de502667ad76eeacd830b48d2e91fac4" +checksum = "a3f290edc569ad10c07287eebb96629686b37f1e55283a093569151d3adde0c7" dependencies = [ "actix-codec", - "actix-rt", "actix-service", "actix-utils", - "ahash 0.8.11", "base64 0.22.1", "bitflags", "brotli", "bytes", "bytestring", - "derive_more 0.99.18", + "derive_more 2.1.1", "encoding_rs", "flate2", + "foldhash", "futures-core", "h2", "http 0.2.12", @@ -72,8 +71,8 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rand", - "sha1", + "rand 0.10.3", + "sha1 0.11.0", "smallvec", "tokio", "tokio-util", @@ -88,7 +87,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -108,7 +107,7 @@ dependencies = [ "log", "memchr", "mime", - "rand", + "rand 0.8.5", "serde", "serde_json", "serde_plain", @@ -122,18 +121,18 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e11eb847f49a700678ea2fa73daeb3208061afa2b9d1a8527c03390f4c4a1c6b" dependencies = [ - "darling 0.20.10", + "darling", "parse-size", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] name = "actix-router" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" +checksum = "14f8c75c51892f18d9c46150c5ac7beb81c95f78c8b83a634d49f4ca32551fe7" dependencies = [ "bytestring", "cfg-if", @@ -156,17 +155,16 @@ dependencies = [ [[package]] name = "actix-server" -version = "2.5.0" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca2549781d8dd6d75c40cf6b6051260a2cc2f3c62343d761a969a0640646894" +checksum = "164ab0b702b578c93901482aea90729bcb8b0822b090194372ad2966393778fa" dependencies = [ "actix-rt", "actix-service", - "actix-utils", "futures-core", "futures-util", "mio", - "socket2", + "socket2 0.6.5", "tokio", "tracing", ] @@ -193,7 +191,7 @@ dependencies = [ "actix-web", "anyhow", "derive_more 1.0.0", - "rand", + "rand 0.8.5", "serde", "serde_json", "tracing", @@ -211,9 +209,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.9.0" +version = "4.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9180d76e5cc7ccbc4d60a506f2c727730b154010262df5b910eb17dbe4b8cb38" +checksum = "bbacab3593b6b4f7be815076fc52d60a83c873426824675417e2abdd229e2e36" dependencies = [ "actix-codec", "actix-http", @@ -224,13 +222,13 @@ dependencies = [ "actix-service", "actix-utils", "actix-web-codegen", - "ahash 0.8.11", "bytes", "bytestring", "cfg-if", "cookie 0.16.2", - "derive_more 0.99.18", + "derive_more 2.1.1", "encoding_rs", + "foldhash", "futures-core", "futures-util", "impl-more", @@ -246,8 +244,9 @@ dependencies = [ "serde_json", "serde_urlencoded", "smallvec", - "socket2", + "socket2 0.6.5", "time", + "tracing", "url", ] @@ -260,16 +259,21 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] -name = "addr2line" -version = "0.24.2" +name = "actix-ws" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "12d4f2fbee3ef7a22fa6cb0e416b962237a167ed0419f22d4e451da2d7f082f8" dependencies = [ - "gimli", + "actix-codec", + "actix-http", + "actix-web", + "bytestring", + "futures-core", + "tokio", ] [[package]] @@ -284,7 +288,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "generic-array", ] @@ -296,7 +300,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher 0.4.4", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -432,6 +436,18 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "any_spawner" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1384d3fe1eecb464229fcf6eebb72306591c56bf27b373561489458a7c73027d" +dependencies = [ + "futures", + "thiserror 2.0.21", + "tokio", + "wasm-bindgen-futures", +] + [[package]] name = "anyhow" version = "1.0.95" @@ -451,16 +467,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] -name = "async-recursion" -version = "1.1.1" +name = "async-lock" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", + "event-listener", + "event-listener-strategy", + "pin-project-lite", ] +[[package]] +name = "async-once-cell" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288f83726785267c6f2ef073a3d83dc3f9b81464e9f99898240cced85fce35a" + [[package]] name = "async-trait" version = "0.1.86" @@ -469,7 +491,7 @@ checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -483,32 +505,31 @@ dependencies = [ [[package]] name = "attribute-derive" -version = "0.9.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f1ee502851995027b06f99f5ffbeffa1406b38d0b318a1ebfa469332c6cbafd" +checksum = "d2f9ef7a68684657ce9da341c934c73b63df7a3585a61e366d84c84ed5d3d167" dependencies = [ "attribute-derive-macro", - "derive-where", "manyhow", "proc-macro2", "quote", - "syn 2.0.96", + "syn 3.0.7", ] [[package]] name = "attribute-derive-macro" -version = "0.9.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3601467f634cfe36c4780ca9c75dea9a5b34529c1f2810676a337e7e0997f954" +checksum = "300d426e5e73549125bb8e4649bdd5508f82c94ddf898fb0517246e71dfb8e98" dependencies = [ "collection_literals", "interpolator", "manyhow", - "proc-macro-utils 0.8.0", + "proc-macro-utils", "proc-macro2", "quote", "quote-use", - "syn 2.0.96", + "syn 3.0.7", ] [[package]] @@ -518,19 +539,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] -name = "backtrace" -version = "0.3.74" +name = "base16" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] +checksum = "d27c3610c36aee21ce8ac510e6224498de4228ad772a171ed65643a24693a5a8" [[package]] name = "base64" @@ -595,6 +607,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +dependencies = [ + "hybrid-array", +] + [[package]] name = "blowfish" version = "0.7.0" @@ -626,14 +647,14 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] name = "brotli" -version = "6.0.0" +version = "8.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" +checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -642,9 +663,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "4.0.2" +version = "5.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37" +checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -686,9 +707,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.9.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "bytestring" @@ -699,43 +720,11 @@ dependencies = [ "bytes", ] -[[package]] -name = "cached" -version = "0.45.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90eb5776f28a149524d1d8623035760b4454ec881e8cf3838fa8d7e1b11254b3" -dependencies = [ - "cached_proc_macro", - "cached_proc_macro_types", - "hashbrown 0.13.2", - "instant", - "once_cell", - "thiserror", -] - -[[package]] -name = "cached_proc_macro" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c878c71c2821aa2058722038a59a67583a4240524687c6028571c9b395ded61f" -dependencies = [ - "darling 0.14.4", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "cached_proc_macro_types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0" - [[package]] name = "camino" -version = "1.1.9" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +checksum = "bbbad30e4b4c14a39e3cc8aed085a12a327257c316619c93581e017bc52be591" [[package]] name = "cc" @@ -760,6 +749,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", + "rand_core 0.10.1", +] + [[package]] name = "charts-rs" version = "0.3.19" @@ -785,7 +785,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "218a07f694e17fb902c2fe72ba31ab821f2d57c146d51761aae00ab5614a3727" dependencies = [ "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -813,33 +813,6 @@ dependencies = [ "stacker", ] -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - [[package]] name = "cipher" version = "0.2.5" @@ -855,17 +828,19 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "inout", ] [[package]] name = "codee" -version = "0.2.0" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3ad3122b0001c7f140cf4d605ef9a9e2c24d96ab0b4fb4347b76de2425f445" +checksum = "a9dbbdc4b4d349732bc6690de10a9de952bd39ba6a065c586e26600b6b0b91f5" dependencies = [ - "thiserror", + "serde", + "serde_json", + "thiserror 2.0.21", ] [[package]] @@ -891,15 +866,15 @@ dependencies = [ [[package]] name = "config" -version = "0.14.1" +version = "0.15.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68578f196d2a33ff61b27fae256c3164f65e36382648e30666dde05b8cc9dfdf" +checksum = "38e9fbc53afcec54441422f1c596cd054655b32e70e1cbac956651b7b175a404" dependencies = [ "convert_case 0.6.0", - "nom", "pathdiff", - "serde", - "toml", + "serde_core", + "toml 1.1.8+spec-1.1.0", + "winnow 1.0.4", ] [[package]] @@ -918,6 +893,18 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + +[[package]] +name = "const-str" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18f12cc9948ed9604230cdddc7c86e270f9401ccbe3c2e98a4378c5e7632212f" + [[package]] name = "const_format" version = "0.2.34" @@ -938,6 +925,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "const_str_slice_concat" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f67855af358fcb20fac58f9d714c94e2b228fe5694c1c9b4ead4a366343eda1b" + [[package]] name = "convert_case" version = "0.4.0" @@ -953,6 +946,33 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "convert_case" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "affbf0190ed2caf063e3def54ff444b449371d55c58e513a95ab98eca50adb49" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "convert_case_extras" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589c70f0faf8aa9d17787557d5eae854d7755cac50f5c3d12c81d3d57661cebb" +dependencies = [ + "convert_case 0.11.0", +] + [[package]] name = "cookie" version = "0.16.2" @@ -964,7 +984,7 @@ dependencies = [ "hkdf", "hmac 0.12.1", "percent-encoding", - "rand", + "rand 0.8.5", "sha2 0.10.8", "subtle", "time", @@ -1007,6 +1027,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + [[package]] name = "crc" version = "3.2.1" @@ -1046,12 +1075,6 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" -[[package]] -name = "crunchy" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" - [[package]] name = "crypto-common" version = "0.1.6" @@ -1059,10 +1082,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + [[package]] name = "crypto-mac" version = "0.10.1" @@ -1082,38 +1114,14 @@ dependencies = [ "cipher 0.4.4", ] -[[package]] -name = "darling" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" -dependencies = [ - "darling_core 0.14.4", - "darling_macro 0.14.4", -] - [[package]] name = "darling" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core 0.20.10", - "darling_macro 0.20.10", -] - -[[package]] -name = "darling_core" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.10.0", - "syn 1.0.109", + "darling_core", + "darling_macro", ] [[package]] @@ -1126,19 +1134,8 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.11.1", - "syn 2.0.96", -] - -[[package]] -name = "darling_macro" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" -dependencies = [ - "darling_core 0.14.4", - "quote", - "syn 1.0.109", + "strsim", + "syn 2.0.119", ] [[package]] @@ -1147,22 +1144,9 @@ version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core 0.20.10", + "darling_core", "quote", - "syn 2.0.96", -] - -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", + "syn 2.0.119", ] [[package]] @@ -1171,10 +1155,10 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0df63c21a4383f94bd5388564829423f35c316aed85dc4f8427aded372c7c0d" dependencies = [ - "darling 0.20.10", + "darling", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -1183,7 +1167,7 @@ version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ - "const-oid", + "const-oid 0.9.6", "pem-rfc7468", "zeroize", ] @@ -1199,13 +1183,13 @@ dependencies = [ [[package]] name = "derive-where" -version = "1.2.7" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" +checksum = "2e2b94854e8576378ccda7c8de8a66ed8b4e8acbd2c50ec3418ea6c8aaf4b567" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 3.0.7", ] [[package]] @@ -1218,7 +1202,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -1227,7 +1211,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "derive_more-impl", + "derive_more-impl 1.0.0", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl 2.1.1", ] [[package]] @@ -1238,7 +1231,21 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", + "unicode-xid", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case 0.10.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.119", "unicode-xid", ] @@ -1258,11 +1265,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", - "const-oid", - "crypto-common", + "const-oid 0.9.6", + "crypto-common 0.1.6", "subtle", ] +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.1", + "const-oid 0.10.2", + "crypto-common 0.2.2", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -1271,7 +1289,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -1295,6 +1313,16 @@ dependencies = [ "serde", ] +[[package]] +name = "either_of" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5060e0a4cbf26a87550792688ade88e6b8aec9208613631a7a363bda7bc2d4cd" +dependencies = [ + "paste", + "pin-project-lite", +] + [[package]] name = "email-encoding" version = "0.3.1" @@ -1349,6 +1377,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "erased" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1731451909bde27714eacba19c2566362a7f35224f52b153d3f42cf60f72472" + [[package]] name = "errno" version = "0.3.10" @@ -1381,6 +1415,16 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -1414,6 +1458,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "fontdue" version = "0.9.2" @@ -1494,6 +1544,7 @@ dependencies = [ "futures-core", "futures-task", "futures-util", + "num_cpus", ] [[package]] @@ -1521,7 +1572,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -1593,11 +1644,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.13.3+wasi-0.2.2", + "wasm-bindgen", "windows-targets 0.52.6", ] +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "rand_core 0.10.1", + "wasm-bindgen", +] + [[package]] name = "ghash" version = "0.5.1" @@ -1608,12 +1675,6 @@ dependencies = [ "polyval", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "gloo-net" version = "0.6.0" @@ -1624,12 +1685,12 @@ dependencies = [ "futures-core", "futures-sink", "gloo-utils", - "http 1.2.0", + "http 1.5.0", "js-sys", "pin-project", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -1637,9 +1698,9 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +checksum = "482ce8a491a501da4cd806bd190275363d674f2845005c6ddbd5d3e1dd54495d" dependencies = [ "futures-channel", "futures-core", @@ -1661,10 +1722,16 @@ dependencies = [ ] [[package]] -name = "h2" -version = "0.3.26" +name = "guardian" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +checksum = "17e2ac29387b1aa07a1e448f7bb4f35b500787971e965b02842b900afa5c8f6f" + +[[package]] +name = "h2" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ "bytes", "fnv", @@ -1679,16 +1746,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "half" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" -dependencies = [ - "cfg-if", - "crunchy", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -1698,12 +1755,6 @@ dependencies = [ "ahash 0.7.8", ] -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" - [[package]] name = "hashbrown" version = "0.14.5" @@ -1716,9 +1767,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "hashlink" @@ -1735,6 +1786,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" + [[package]] name = "hex" version = "0.4.3" @@ -1811,12 +1868,11 @@ dependencies = [ [[package]] name = "http" -version = "1.2.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -1844,6 +1900,30 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "hybrid-array" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" +dependencies = [ + "typenum", +] + +[[package]] +name = "hydration_context" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "285b05858fe7d58c5eff059f7b46c228fd86996d996c59eb35fc0340d174f640" +dependencies = [ + "futures", + "js-sys", + "or_poisoned", + "pin-project-lite", + "serde", + "throw_error", + "wasm-bindgen", +] + [[package]] name = "iana-time-zone" version = "0.1.61" @@ -1982,7 +2062,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -2030,18 +2110,18 @@ checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" [[package]] name = "impl-more" -version = "0.1.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" +checksum = "2d3a73c82a0b0747dba739b380c046a140b5ae747234bf701df3460282da7193" [[package]] name = "indexmap" -version = "2.7.1" +version = "2.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.17.1", ] [[package]] @@ -2053,15 +2133,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - [[package]] name = "interpolator" version = "0.5.0" @@ -2085,9 +2156,9 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" -version = "0.12.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] @@ -2109,11 +2180,12 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5" dependencies = [ - "once_cell", + "cfg-if", + "futures-util", "wasm-bindgen", ] @@ -2134,29 +2206,51 @@ dependencies = [ [[package]] name = "leptos" -version = "0.6.15" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cbb3237c274dadf00dcc27db96c52601b40375117178fb24a991cda073624f0" +checksum = "713ee6895e3d1126ea9781280d01414f5643f3f201a949b71efffac07d735f00" dependencies = [ + "any_spawner", + "base64 0.22.1", "cfg-if", + "either_of", + "futures", + "getrandom 0.4.3", + "hydration_context", "leptos_config", "leptos_dom", + "leptos_hot_reload", "leptos_macro", - "leptos_reactive", "leptos_server", + "oco_ref", + "or_poisoned", + "paste", + "rand 0.9.5", + "reactive_graph", + "rustc-hash", + "rustc_version", + "send_wrapper", + "serde", + "serde_json", + "serde_qs", "server_fn", - "tracing", + "slotmap", + "tachys", + "thiserror 2.0.21", + "throw_error", "typed-builder", "typed-builder-macro", "wasm-bindgen", + "wasm-bindgen-futures", + "wasm_split_helpers", "web-sys", ] [[package]] name = "leptos-captcha" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad333c9ec3968e6a00dbf227a9f4ecd08931b23d2d720ec0b3cfc1117000b5b" +checksum = "e70cd51cbe605e0e932a1f687ad369882b32b986f78aaa483f50650877d9756c" dependencies = [ "leptos", "spow", @@ -2164,10 +2258,11 @@ dependencies = [ [[package]] name = "leptos-use" -version = "0.13.13" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "789bf9f4337e6ebd8f1b407e3f762fdc538d48dc145f9d1dce2338014b38f4dd" +checksum = "f619160d1a85b7a1dd0dcd79ae1888951b228c7d00bcc32c0ad85eeb80d8936f" dependencies = [ + "actix-web", "cfg-if", "chrono", "codee", @@ -2175,11 +2270,14 @@ dependencies = [ "default-struct-builder", "futures-util", "gloo-timers", + "http 0.2.12", "js-sys", "lazy_static", "leptos", + "leptos_actix", "paste", - "thiserror", + "send_wrapper", + "thiserror 2.0.21", "unic-langid", "wasm-bindgen", "wasm-bindgen-futures", @@ -2188,212 +2286,182 @@ dependencies = [ [[package]] name = "leptos_actix" -version = "0.6.15" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29155efba54ab8c6c3038ce2608500b4aa5d8be04330e5fa08d0fe7cae85308c" +checksum = "c65c0cee7ff1da4bc1c912ad5d01099c399cd546b6ea70f1561778d087d079de" dependencies = [ + "actix-files", "actix-http", "actix-web", + "any_spawner", "futures", + "hydration_context", "leptos", "leptos_integration_utils", "leptos_macro", "leptos_meta", "leptos_router", - "parking_lot", - "regex", + "or_poisoned", + "send_wrapper", "serde_json", "server_fn", + "tachys", "tokio", - "tracing", ] [[package]] name = "leptos_config" -version = "0.6.15" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ed778611380ddea47568ac6ad6ec5158d39b5bd59e6c4dcd24efc15dc3dc0d" +checksum = "0c06f751315bccc0d193fab302ac01d25bcfcd97474d4676440e7e3250dc3fc3" dependencies = [ "config", "regex", "serde", - "thiserror", + "thiserror 2.0.21", "typed-builder", ] [[package]] name = "leptos_dom" -version = "0.6.15" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8401c46c86c1f4c16dcb7881ed319fcdca9cda9b9e78a6088955cb423afcf119" +checksum = "35742e9ed8f8aaf9e549b454c68a7ac0992536e06856365639b111f72ab07884" dependencies = [ - "async-recursion", - "cfg-if", - "drain_filter_polyfill", - "futures", - "getrandom 0.2.15", - "html-escape", - "indexmap", - "itertools", "js-sys", - "leptos_reactive", - "once_cell", - "pad-adapter", - "paste", - "rustc-hash", - "serde", - "serde_json", - "server_fn", - "smallvec", - "tracing", + "or_poisoned", + "reactive_graph", + "send_wrapper", + "tachys", "wasm-bindgen", - "wasm-bindgen-futures", "web-sys", ] [[package]] name = "leptos_hot_reload" -version = "0.6.15" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb53d4794240b684a2f4be224b84bee9e62d2abc498cf2bcd643cd565e01d96" +checksum = "d84989bd3d604e66adbfe13a32bec2ea47bdcb6c9fcd643f784facbb32f6ef10" dependencies = [ "anyhow", "camino", "indexmap", - "parking_lot", + "or_poisoned", "proc-macro2", "quote", "rstml", "serde", - "syn 2.0.96", + "syn 3.0.7", "walkdir", ] [[package]] name = "leptos_integration_utils" -version = "0.6.15" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a96976631c2225ec116a7bf9c0ed5bf6999a19fed33f5e3cbcf37af44c384dc" +checksum = "fd93f4fd62ee9845cc50b0925272bccce6fd18e8168c4ad8a4f50eef9a93f747" dependencies = [ "futures", + "hydration_context", "leptos", "leptos_config", - "leptos_hot_reload", "leptos_meta", - "tracing", + "leptos_router", + "reactive_graph", ] [[package]] name = "leptos_macro" -version = "0.6.15" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b13bc3db70715cd8218c4535a5af3ae3c0e5fea6f018531fc339377b36bc0e0" +checksum = "0902af1e6947ffc7e906b7003a165f76f178dc711a47b74241025090b0c32a72" dependencies = [ "attribute-derive", "cfg-if", - "convert_case 0.6.0", + "convert_case 0.11.0", + "convert_case_extras", "html-escape", "itertools", "leptos_hot_reload", "prettyplease", - "proc-macro-error2", "proc-macro2", "quote", "rstml", + "rustc_version", "server_fn_macro", - "syn 2.0.96", - "tracing", + "syn 3.0.7", "uuid", ] [[package]] name = "leptos_meta" -version = "0.6.15" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25acc2f63cf91932013e400a95bf6e35e5d3dbb44a7b7e25a8e3057d12005b3b" +checksum = "987b1a07addba2647da43c0689408cccc0f428236b714ea606127b9e347d35d8" dependencies = [ - "cfg-if", - "indexmap", - "leptos", - "tracing", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "leptos_reactive" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4161acbf80f59219d8d14182371f57302bc7ff81ee41aba8ba1ff7295727f23" -dependencies = [ - "base64 0.22.1", - "cfg-if", "futures", "indexmap", - "js-sys", - "oco_ref", - "paste", - "pin-project", - "rustc-hash", - "self_cell", - "serde", - "serde-wasm-bindgen", - "serde_json", - "slotmap", - "thiserror", - "tokio", - "tracing", + "leptos", + "or_poisoned", + "send_wrapper", "wasm-bindgen", - "wasm-bindgen-futures", "web-sys", ] [[package]] name = "leptos_router" -version = "0.6.15" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d71dea7d42c0d29c40842750232d3425ed1cf10e313a1f898076d20871dad32" +checksum = "f92787ebcb5f25af6a67513dacfd75cbffce5bda3f361e2e947c3fc4e3adc14b" dependencies = [ - "cached", - "cfg-if", + "any_spawner", + "either_of", + "futures", "gloo-net", - "itertools", "js-sys", - "lazy_static", "leptos", - "leptos_integration_utils", - "leptos_meta", - "linear-map", - "lru", - "once_cell", + "leptos_router_macro", + "or_poisoned", "percent-encoding", - "regex", + "reactive_graph", + "rustc_version", "send_wrapper", - "serde", - "serde_json", - "serde_qs 0.13.0", - "thiserror", - "tracing", + "tachys", + "thiserror 2.0.21", "url", "wasm-bindgen", - "wasm-bindgen-futures", "web-sys", ] [[package]] -name = "leptos_server" -version = "0.6.15" +name = "leptos_router_macro" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a97eb90a13f71500b831c7119ddd3bdd0d7ae0a6b0487cade4fddeed3b8c03f" +checksum = "1bb5c81012dcab0d5cc032a2da0a364a18ce74a0fbeb88f091e9b53a0679bc85" dependencies = [ - "inventory", - "lazy_static", - "leptos_macro", - "leptos_reactive", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "leptos_server" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "202b2d1261c22d886f307934760a6bb566444f68f39b24f6f10defdc23633049" +dependencies = [ + "any_spawner", + "base64 0.22.1", + "codee", + "futures", + "hydration_context", + "or_poisoned", + "reactive_graph", + "send_wrapper", "serde", + "serde_json", "server_fn", - "thiserror", - "tracing", + "tachys", ] [[package]] @@ -2415,10 +2483,10 @@ dependencies = [ "idna 1.0.3", "mime", "native-tls", - "nom", + "nom 7.1.3", "percent-encoding", "quoted_printable", - "socket2", + "socket2 0.5.8", "tokio", "tokio-native-tls", "url", @@ -2427,9 +2495,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.169" +version = "0.2.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" [[package]] name = "libm" @@ -2448,16 +2516,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "linear-map" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfae20f6b19ad527b550c223fddc3077a547fc70cda94b9b566575423fd303ee" -dependencies = [ - "serde", - "serde_test", -] - [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -2503,34 +2561,25 @@ version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" -[[package]] -name = "lru" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a83fb7698b3643a0e34f9ae6f2e8f0178c0fd42f8b59d493aa271ff3a5bf21" -dependencies = [ - "hashbrown 0.14.5", -] - [[package]] name = "manyhow" -version = "0.10.4" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91ea592d76c0b6471965708ccff7e6a5d277f676b90ab31f4d3f3fc77fade64" +checksum = "8c69ea6e469ca785c846b25dd69eac9e9c916b51d8ada1f212866787ee1da12d" dependencies = [ "manyhow-macros", "proc-macro2", "quote", - "syn 2.0.96", + "syn 3.0.7", ] [[package]] name = "manyhow-macros" -version = "0.10.4" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64621e2c08f2576e4194ea8be11daf24ac01249a4f53cd8befcbb7077120ead" +checksum = "22fc5c1b2c4000056dae3619fea36e79ce79dabfee4907d2dcad6612b189e370" dependencies = [ - "proc-macro-utils 0.8.0", + "proc-macro-utils", "proc-macro2", "quote", ] @@ -2595,31 +2644,14 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.3" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "1788edb87fdc09c7e26304471e2f5be8cdefb1b6930d6e3985fc02ff53bf86ee" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", -] - -[[package]] -name = "multer" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" -dependencies = [ - "bytes", - "encoding_rs", - "futures-util", - "http 1.2.0", - "httparse", - "memchr", - "mime", - "spin", - "version_check", + "windows-sys 0.61.2", ] [[package]] @@ -2639,6 +2671,12 @@ dependencies = [ "tempfile", ] +[[package]] +name = "next_tuple" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60993920e071b0c9b66f14e2b32740a4e27ffc82854dcd72035887f336a09a28" + [[package]] name = "nom" version = "7.1.3" @@ -2649,6 +2687,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -2661,7 +2708,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand", + "rand 0.8.5", "smallvec", "zeroize", ] @@ -2703,29 +2750,30 @@ dependencies = [ ] [[package]] -name = "object" -version = "0.36.7" +name = "num_cpus" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "memchr", + "hermit-abi", + "libc", ] [[package]] name = "oco_ref" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51ebcefb2f0b9a5e0bea115532c8ae4215d1b01eff176d0f4ba4192895c2708" +checksum = "ed0423ff9973dea4d6bd075934fdda86ebb8c05bdf9d6b0507067d4a1226371d" dependencies = [ "serde", - "thiserror", + "thiserror 2.0.21", ] [[package]] name = "once_cell" -version = "1.20.2" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "opaque-debug" @@ -2756,7 +2804,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -2778,10 +2826,10 @@ dependencies = [ ] [[package]] -name = "pad-adapter" -version = "0.1.1" +name = "or_poisoned" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d80efc4b6721e8be2a10a5df21a30fa0b470f1539e53d8b4e6e75faf938b63" +checksum = "8c04f5d74368e4d0dfe06c45c8627c81bd7c317d52762d118fb9b3076f6420fd" [[package]] name = "parking" @@ -2862,7 +2910,7 @@ checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -2911,7 +2959,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", "universal-hash", ] @@ -2933,12 +2981,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.29" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" +checksum = "2bfe0f4c752e450fc2faf62654f1c134747922825d5b04ca717b8874f41a40c0" dependencies = [ "proc-macro2", - "syn 2.0.96", + "syn 3.0.7", ] [[package]] @@ -2974,38 +3022,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-utils" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f59e109e2f795a5070e69578c4dc101068139f74616778025ae1011d4cd41a8" -dependencies = [ - "proc-macro2", - "quote", - "smallvec", -] - [[package]] name = "proc-macro-utils" version = "0.10.0" @@ -3028,15 +3044,14 @@ dependencies = [ [[package]] name = "proc-macro2-diagnostics" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +checksum = "df921e1ef974ebc8dd9effdb0c037a96928ae8cbf871438e02d6fd67204b595e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 3.0.7", "version_check", - "yansi", ] [[package]] @@ -3078,7 +3093,7 @@ dependencies = [ "byteorder", "hmac 0.10.1", "md-5 0.9.1", - "rand", + "rand 0.8.5", "sha-1", "sha2 0.9.9", ] @@ -3094,9 +3109,9 @@ dependencies = [ [[package]] name = "quote-use" -version = "0.8.4" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9619db1197b497a36178cfc736dc96b271fe918875fbf1344c436a7e93d0321e" +checksum = "48356e493823dc3c1d7e9fc7b3ff204ecec48afbdd718fc4134091b88eb63f3d" dependencies = [ "quote", "quote-use-macros", @@ -3104,14 +3119,14 @@ dependencies = [ [[package]] name = "quote-use-macros" -version = "0.8.4" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82ebfb7faafadc06a7ab141a6f67bcfb24cb8beb158c6fe933f2f035afa99f35" +checksum = "8cf1c5de6a7cc231c71e03c77aa4c7019097859ea7029156b54d2894a8430704" dependencies = [ - "proc-macro-utils 0.10.0", + "proc-macro-utils", "proc-macro2", "quote", - "syn 2.0.96", + "syn 3.0.7", ] [[package]] @@ -3120,6 +3135,12 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "640c9bd8497b02465aeef5375144c26062e0dcd5939dfcbb0f5db76cb8c17c73" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "radium" version = "0.7.0" @@ -3133,8 +3154,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" +dependencies = [ + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", ] [[package]] @@ -3144,7 +3186,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", ] [[package]] @@ -3156,6 +3208,74 @@ dependencies = [ "getrandom 0.2.15", ] +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.1", +] + +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "reactive_graph" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79f11fac67625645add76313dab8dae510fca0654d96ef98fd8f961a7d2e22c1" +dependencies = [ + "any_spawner", + "async-lock", + "futures", + "guardian", + "hydration_context", + "indexmap", + "or_poisoned", + "paste", + "pin-project-lite", + "rustc-hash", + "rustc_version", + "send_wrapper", + "serde", + "slotmap", + "thiserror 2.0.21", + "web-sys", +] + +[[package]] +name = "reactive_stores" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a29e469b556f25486678e9f5f65fa21a0351d98affde9a7eea9fee286bf8ebd6" +dependencies = [ + "guardian", + "indexmap", + "itertools", + "or_poisoned", + "paste", + "reactive_graph", + "reactive_stores_macro", + "rustc-hash", + "send_wrapper", +] + +[[package]] +name = "reactive_stores_macro" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d11f1b82859d94577892b8037c35f8a4f066cbb3864583e22e68def0af49a88" +dependencies = [ + "convert_case 0.11.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "redox_syscall" version = "0.5.8" @@ -3167,9 +3287,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -3179,9 +3299,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", @@ -3196,9 +3316,9 @@ checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "rend" @@ -3225,6 +3345,7 @@ dependencies = [ "env_logger", "futures-util", "getopts", + "getrandom 0.2.15", "lazy_static", "leptos", "leptos-captcha", @@ -3235,14 +3356,14 @@ dependencies = [ "lettre", "log", "pwhash", - "rand", + "rand 0.8.5", "regex", "rust_decimal", "serde", "serde_json", "server_fn", "sqlx", - "toml", + "toml 0.8.19", "uuid", "validator", "wasm-bindgen", @@ -3299,14 +3420,14 @@ version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" dependencies = [ - "const-oid", + "const-oid 0.9.6", "digest 0.10.7", "num-bigint-dig", "num-integer", "num-traits", "pkcs1", "pkcs8", - "rand_core", + "rand_core 0.6.4", "signature", "spki", "subtle", @@ -3315,16 +3436,16 @@ dependencies = [ [[package]] name = "rstml" -version = "0.11.2" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe542870b8f59dd45ad11d382e5339c9a1047cde059be136a7016095bbdefa77" +checksum = "c6bd1bfba3c4c0b57aae906204d9e5744f3f65800ce6c75bd4cc162f2c26f3aa" dependencies = [ + "derive-where", "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.96", - "syn_derive", - "thiserror", + "syn 3.0.7", + "thiserror 2.0.21", ] [[package]] @@ -3337,23 +3458,17 @@ dependencies = [ "borsh", "bytes", "num-traits", - "rand", + "rand 0.8.5", "rkyv", "serde", "serde_json", ] -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - [[package]] name = "rustc-hash" -version = "1.1.0" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc_version" @@ -3482,12 +3597,6 @@ dependencies = [ "libc", ] -[[package]] -name = "self_cell" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe" - [[package]] name = "semver" version = "1.0.25" @@ -3505,33 +3614,32 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.217" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] -[[package]] -name = "serde-wasm-bindgen" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" -dependencies = [ - "js-sys", - "serde", - "wasm-bindgen", -] - [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 3.0.7", ] [[package]] @@ -3557,24 +3665,13 @@ dependencies = [ [[package]] name = "serde_qs" -version = "0.12.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0431a35568651e363364210c91983c1da5eb29404d9f0928b67d4ebcfa7d330c" +checksum = "f3faaf9e727533a19351a43cc5a8de957372163c7d35cc48c90b75cdda13c352" dependencies = [ "percent-encoding", "serde", - "thiserror", -] - -[[package]] -name = "serde_qs" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd34f36fe4c5ba9654417139a9b3a20d2e1de6012ee678ad14d240c22c78d8d6" -dependencies = [ - "percent-encoding", - "serde", - "thiserror", + "thiserror 2.0.21", ] [[package]] @@ -3587,12 +3684,12 @@ dependencies = [ ] [[package]] -name = "serde_test" -version = "1.0.177" +name = "serde_spanned" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f901ee573cab6b3060453d2d5f0bae4e6d628c23c0a962ff9b5f1d7c8d4f1ed" +checksum = "4e7523beb55eece201a2356bee0bbca0d1ab466c14c07703b2e0ee6d42cb0c2c" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -3609,28 +3706,32 @@ dependencies = [ [[package]] name = "server_fn" -version = "0.6.15" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fae7a3038a32e5a34ba32c6c45eb4852f8affaf8b794ebfcd4b1099e2d62ebe" +checksum = "be8559dd05af1b5b7e363a150616589d5a88af5187273f7f331ba0dae8922812" dependencies = [ "actix-web", + "actix-ws", + "base64 0.22.1", "bytes", - "ciborium", + "const-str", "const_format", - "dashmap", "futures", "gloo-net", - "http 1.2.0", + "http 1.5.0", "inventory", "js-sys", - "multer", - "once_cell", + "or_poisoned", + "pin-project-lite", + "rustc_version", + "rustversion", "send_wrapper", "serde", "serde_json", - "serde_qs 0.12.0", + "serde_qs", "server_fn_macro_default", - "thiserror", + "thiserror 2.0.21", + "throw_error", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -3641,26 +3742,27 @@ dependencies = [ [[package]] name = "server_fn_macro" -version = "0.6.15" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaaf648c6967aef78177c0610478abb5a3455811f401f3c62d10ae9bd3901a1" +checksum = "ce79d7b6ab93f7994e5ff4999eb962f2aea370d7c3b91986eb75da738a8e65f9" dependencies = [ "const_format", - "convert_case 0.6.0", + "convert_case 0.11.0", "proc-macro2", "quote", - "syn 2.0.96", + "rustc_version", + "syn 3.0.7", "xxhash-rust", ] [[package]] name = "server_fn_macro_default" -version = "0.6.15" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2aa8119b558a17992e0ac1fd07f080099564f24532858811ce04f742542440" +checksum = "d9a4f81a0d855f279c3448243138a55cbfdd9851da9341b9c1e5971b90089e61" dependencies = [ "server_fn_macro", - "syn 2.0.96", + "syn 3.0.7", ] [[package]] @@ -3671,7 +3773,7 @@ checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ "block-buffer 0.9.0", "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.9.0", "opaque-debug", ] @@ -3683,10 +3785,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] +[[package]] +name = "sha1" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", + "digest 0.11.3", +] + [[package]] name = "sha2" version = "0.9.9" @@ -3695,7 +3808,7 @@ checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.9.0", "opaque-debug", ] @@ -3707,18 +3820,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", - "sha2-asm", -] - -[[package]] -name = "sha2-asm" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b845214d6175804686b2bd482bcffe96651bb2d1200742b712003504a2dac1ab" -dependencies = [ - "cc", ] [[package]] @@ -3743,7 +3846,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -3763,11 +3866,10 @@ dependencies = [ [[package]] name = "slotmap" -version = "1.0.7" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" dependencies = [ - "serde", "version_check", ] @@ -3798,7 +3900,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -3811,6 +3913,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "spin" version = "0.9.8" @@ -3832,17 +3944,17 @@ dependencies = [ [[package]] name = "spow" -version = "0.2.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33d19caa42297b681c88a844ace448357a2b107e723a9d26239338c8d37aa58" +checksum = "2a323422ef51634c7448e62277561b9b08a1b11b37a1287dfa491277c9870d46" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "chrono", - "getrandom 0.2.15", - "nom", + "getrandom 0.3.1", + "nom 8.0.0", "serde", "sha2 0.10.8", - "thiserror", + "thiserror 2.0.21", ] [[package]] @@ -3851,7 +3963,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" dependencies = [ - "nom", + "nom 7.1.3", "unicode_categories", ] @@ -3904,7 +4016,7 @@ dependencies = [ "sha2 0.10.8", "smallvec", "sqlformat", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "tracing", @@ -3923,7 +4035,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -3946,7 +4058,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.96", + "syn 2.0.119", "tempfile", "tokio", "url", @@ -3982,16 +4094,16 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rand", + "rand 0.8.5", "rsa", "rust_decimal", "serde", - "sha1", + "sha1 0.10.6", "sha2 0.10.8", "smallvec", "sqlx-core", "stringprep", - "thiserror", + "thiserror 1.0.69", "tracing", "uuid", "whoami", @@ -4024,7 +4136,7 @@ dependencies = [ "md-5 0.10.6", "memchr", "once_cell", - "rand", + "rand 0.8.5", "rust_decimal", "serde", "serde_json", @@ -4032,7 +4144,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror", + "thiserror 1.0.69", "tracing", "uuid", "whoami", @@ -4093,12 +4205,6 @@ dependencies = [ "unicode-properties", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strsim" version = "0.11.1" @@ -4133,9 +4239,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.96" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" dependencies = [ "proc-macro2", "quote", @@ -4143,15 +4249,14 @@ dependencies = [ ] [[package]] -name = "syn_derive" -version = "0.1.8" +name = "syn" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +checksum = "d62a2e0561533f2ca2561d0cf27fd9fedb640a1bf2616ff5d5c80d99017faadc" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.96", + "unicode-ident", ] [[package]] @@ -4162,7 +4267,39 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", +] + +[[package]] +name = "tachys" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e47e2220bb9d2a3be976a22a0fb7685a0b84499bb11ea5cb3bbc82907675ac68" +dependencies = [ + "any_spawner", + "async-trait", + "const_str_slice_concat", + "drain_filter_polyfill", + "either_of", + "erased", + "futures", + "html-escape", + "indexmap", + "itertools", + "js-sys", + "next_tuple", + "oco_ref", + "or_poisoned", + "paste", + "reactive_graph", + "reactive_stores", + "rustc-hash", + "rustc_version", + "send_wrapper", + "slotmap", + "throw_error", + "wasm-bindgen", + "web-sys", ] [[package]] @@ -4191,7 +4328,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" +dependencies = [ + "thiserror-impl 2.0.21", ] [[package]] @@ -4202,7 +4348,27 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.7", +] + +[[package]] +name = "throw_error" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc0ed6038fcbc0795aca7c92963ddda636573b956679204e044492d2b13c8f64" +dependencies = [ + "pin-project-lite", ] [[package]] @@ -4263,19 +4429,18 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.43.0" +version = "1.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +checksum = "e95f91fcc7a621e8b030f6aa23c71fe9838ae2fb4d8118b75602a328f5144044" dependencies = [ - "backtrace", "bytes", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", - "windows-sys 0.52.0", + "socket2 0.6.5", + "windows-sys 0.61.2", ] [[package]] @@ -4319,11 +4484,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", - "serde_spanned", - "toml_datetime", + "serde_spanned 0.6.8", + "toml_datetime 0.6.8", "toml_edit", ] +[[package]] +name = "toml" +version = "1.1.8+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20489e00e4d8741d6be680764cc12e270655e375a20d1011e844a9c3379e678d" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned 1.1.2", + "toml_datetime 1.1.2+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.4", +] + [[package]] name = "toml_datetime" version = "0.6.8" @@ -4333,6 +4513,15 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b86d767906c6c42421dcba507eb9d203e779497710a47782a224bb871653053" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.22.23" @@ -4341,11 +4530,26 @@ checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" dependencies = [ "indexmap", "serde", - "serde_spanned", - "toml_datetime", - "winnow", + "serde_spanned 0.6.8", + "toml_datetime 0.6.8", + "winnow 0.7.0", ] +[[package]] +name = "toml_parser" +version = "1.1.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baa693a8032d7e1cada7d0041e96126df243179ff061456783ac7f12bda4744c" +dependencies = [ + "winnow 1.0.4", +] + +[[package]] +name = "toml_writer" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06bdbd8cfc056b8d2e2e85f29b56a3bdbecb527cef81eb39e3e7b98af4652770" + [[package]] name = "tracing" version = "0.1.41" @@ -4366,7 +4570,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -4386,22 +4590,22 @@ checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" [[package]] name = "typed-builder" -version = "0.18.2" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77739c880e00693faef3d65ea3aad725f196da38b22fdc7ea6ded6e1ce4d3add" +checksum = "31aa81521b70f94402501d848ccc0ecaa8f93c8eb6999eb9747e72287757ffda" dependencies = [ "typed-builder-macro", ] [[package]] name = "typed-builder-macro" -version = "0.18.2" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63" +checksum = "076a02dc54dd46795c2e9c8282ed40bcfb1e22747e955de9389a1de28190fb26" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -4491,7 +4695,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "subtle", ] @@ -4538,12 +4742,14 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.12.1" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b" +checksum = "7cc1186384beb7dd8eedea376413fd654937285ea6c9cfbb928dc3043ea4b606" dependencies = [ - "getrandom 0.2.15", - "serde", + "getrandom 0.4.3", + "js-sys", + "serde_core", + "wasm-bindgen", ] [[package]] @@ -4639,48 +4845,33 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.96", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "3cbab34de2d982e9b48e18d216d04c4a6f641066ff19ffb699980f591ee3610e" dependencies = [ - "cfg-if", "js-sys", - "once_cell", + "tokio", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4688,31 +4879,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.96", - "wasm-bindgen-backend", + "syn 3.0.7", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-streams" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" dependencies = [ "futures-util", "js-sys", @@ -4722,10 +4913,32 @@ dependencies = [ ] [[package]] -name = "web-sys" -version = "0.3.77" +name = "wasm_split_helpers" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "ab578aae2fe2916edaea06843187d50f87b0965622da0ceef648edca27b385ba" +dependencies = [ + "async-once-cell", + "wasm_split_macros", +] + +[[package]] +name = "wasm_split_macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e653af7ee4a9ef0fce481a9ec6f43cb78de20d0cdb4f4f5862e1dc6e407e6c8" +dependencies = [ + "base16", + "quote", + "sha2 0.10.8", + "syn 2.0.119", +] + +[[package]] +name = "web-sys" +version = "0.3.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88261b9deccee56594c11a3460c462c41f58d148598fe70ad77070126a68aba4" dependencies = [ "js-sys", "wasm-bindgen", @@ -4775,6 +4988,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-sys" version = "0.48.0" @@ -4802,6 +5021,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -4932,6 +5160,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +dependencies = [ + "memchr", +] + [[package]] name = "wit-bindgen-rt" version = "0.33.0" @@ -4968,12 +5205,6 @@ version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" -[[package]] -name = "yansi" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" - [[package]] name = "yoke" version = "0.7.5" @@ -4994,7 +5225,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", "synstructure", ] @@ -5016,7 +5247,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] @@ -5036,7 +5267,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", "synstructure", ] @@ -5065,7 +5296,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.119", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 7a1f55a..e34d0bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,20 +13,20 @@ actix-session = { version = "0.10.0", optional = true, features = ["cookie-sessi actix-multipart = { version = "0.7.2", optional = true } console_error_panic_hook = "0.1.7" cfg-if = "1" -leptos = { version = "0.6.13" } -leptos_meta = { version = "0.6.13" } -leptos_actix = { version = "0.6.13", optional = true } -server_fn = { version = "0.6.13", features = ["multipart"] } -leptos_router = { version = "0.6.13" } +leptos = { version = "0.8.22" } +leptos_meta = { version = "0.8" } +leptos_actix = { version = "0.8", optional = true } +server_fn = { version = "0.8" } +leptos_router = { version = "0.8" } serde = { version = "1", features = ["derive"] } serde_json = "1.0.117" -wasm-bindgen = "=0.2.100" +wasm-bindgen = "=0.2.129" web-sys = { version = "0.3.69", features = ["Navigator"] } lazy_static = "1.4.0" chrono = { version = "0.4.38", features = ["serde"]} sqlx = { version = "0.8.0", optional = true, features = ["runtime-tokio-rustls", "postgres", "chrono", "rust_decimal", "uuid"] } rust_decimal = "1.35.0" -uuid = {version = "1.8.0", features = ["v4", "serde"]} +uuid = {version = "1.8.0", features = ["v4", "serde", "js"]} validator = {version = "0.16.1", features = ["derive"]} pwhash = "1.0.0" futures-util = "0.3.30" @@ -35,17 +35,19 @@ toml = "0.8.12" log = "0.4.21" env_logger = "0.11.3" getopts = "0.2.21" -leptos-use = "0.13.13" +leptos-use = "0.19.2" lettre = {version = "0.11.6", features = ["tokio1-native-tls", "smtp-transport", "file-transport"], optional = true} -leptos-captcha = "0.2.0" +leptos-captcha = "0.4.0" charts-rs = { version = "0.3.5", optional = true} #image = { version = "0.24.8", optional = true } base64 = "0.22.0" rand = "0.8.5" +# rand needs the "js" backend when compiled for the browser +getrandom = { version = "0.2", features = ["js"] } [features] -csr = ["leptos/csr", "leptos_meta/csr", "leptos_router/csr"] -hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"] +csr = ["leptos/csr"] +hydrate = ["leptos/hydrate"] ssr = [ "dep:actix-files", "dep:actix-web", @@ -59,6 +61,8 @@ ssr = [ "leptos/ssr", "leptos_meta/ssr", "leptos_router/ssr", + "leptos-use/ssr", + "leptos-use/actix", ] [profile.wasm-release] diff --git a/README.md b/README.md index 65e2ccf..3ba3489 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,10 @@ You will need cargo-leptos tool: `cargo install cargo-leptos` +The `wasm-bindgen` command line tool must be exactly the same version as the `wasm-bindgen` dependency pinned in `Cargo.toml`: + +`cargo install -f wasm-bindgen-cli --version 0.2.129` + ## Running project `cargo leptos watch` diff --git a/src/app.rs b/src/app.rs index 3e0a400..36df723 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,9 +1,11 @@ use crate::locales::init_locales; use crate::pages::home_page::HomePage; use crate::pages::settings::Settings; -use leptos::*; +use leptos::prelude::*; use leptos_meta::*; -use leptos_router::*; +use leptos_router::components::{Route, Router, Routes}; +use leptos_router::hooks::use_location; +use leptos_router::path; use crate::components::admin_portal::AdminPortal; use crate::components::header::Header; use crate::components::user_menu::MenuOpener; @@ -14,29 +16,31 @@ use crate::pages::login::Login; use crate::pages::mail_settings::MailSettings; use crate::pages::public::Public; -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub struct MenuHelper { - opened: RwSignal + opened: RwSignal> } impl MenuHelper { pub fn new() -> Self { - let opened = create_rw_signal(MenuOpener::new()); + let opened = RwSignal::new(None); Self { opened } } pub fn set_opened(&self, opened: MenuOpener) { - self.opened.set(opened); + self.opened.set(Some(opened)); } pub fn close(&self) { - self.opened.get().close(); + if let Some(opened) = self.opened.get_untracked() { + opened.close(); + } } pub fn reset(&self) { - self.opened.set(MenuOpener::new()); + self.opened.set(None); } } @@ -47,7 +51,7 @@ pub struct DialogHelper { impl DialogHelper { pub fn new() -> Self { - let opened = create_rw_signal(false); + let opened = RwSignal::new(false); Self { opened } @@ -68,7 +72,7 @@ fn app_footer() -> impl IntoView { view! {
-
+
{format!(" v {}", env!("CARGO_PKG_VERSION"))}
@@ -89,35 +93,35 @@ pub fn App() -> impl IntoView {
- - }/> - }/> - + }/> + }/> + }/> - }/> - }/> - }/> - }/> - diff --git a/src/backend/appearance.rs b/src/backend/appearance.rs index 36cff49..1b7929c 100644 --- a/src/backend/appearance.rs +++ b/src/backend/appearance.rs @@ -1,5 +1,5 @@ use cfg_if::cfg_if; -use leptos::*; +use leptos::prelude::*; use validator::Validate; use crate::backend::data::{ApiResponse, Appearance}; use crate::components::data_form::ForValidation; diff --git a/src/backend/company.rs b/src/backend/company.rs index a93d8cd..7643dde 100644 --- a/src/backend/company.rs +++ b/src/backend/company.rs @@ -1,5 +1,5 @@ use cfg_if::cfg_if; -use leptos::*; +use leptos::prelude::*; use validator::Validate; use crate::backend::data::{ApiResponse, Company}; use crate::components::data_form::ForValidation; @@ -25,7 +25,7 @@ cfg_if! { if #[cfg(feature = "ssr")] { } }} -#[server(GetCompany, "/api", "Url", "get_company")] +#[server(name = GetCompany, prefix = "/api", endpoint = "get_company")] pub async fn get_company() -> Result, ServerFnError> { use crate::perm_check; @@ -40,7 +40,7 @@ pub async fn get_company() -> Result, ServerFnError> { Ok(ApiResponse::Data(cmp)) } -#[server(UpdateCompany, "/api", "Url", "update_company")] +#[server(name = UpdateCompany, prefix = "/api", endpoint = "update_company")] pub async fn update_company(company: Company) -> Result, ServerFnError> { use crate::perm_check; diff --git a/src/backend/customer.rs b/src/backend/customer.rs index a0f0d71..c1e268a 100644 --- a/src/backend/customer.rs +++ b/src/backend/customer.rs @@ -1,5 +1,5 @@ use cfg_if::cfg_if; -use leptos::{server, ServerFnError}; +use leptos::prelude::*; use crate::backend::data::ApiResponse; use crate::backend::data::Customer; @@ -8,7 +8,6 @@ cfg_if! { if #[cfg(feature = "ssr")] { use sqlx::{query_as, query}; use sqlx::Error; use std::ops::DerefMut; - use leptos::expect_context; use leptos_actix::extract; use actix_web::cookie::Cookie; use actix_web::cookie::SameSite; diff --git a/src/backend/mail.rs b/src/backend/mail.rs index a51bfa4..063a1f2 100644 --- a/src/backend/mail.rs +++ b/src/backend/mail.rs @@ -1,5 +1,5 @@ use cfg_if::cfg_if; -use leptos::*; +use leptos::prelude::*; use validator::Validate; use crate::backend::data::{ApiResponse, Message, MessageType}; use crate::components::data_form::ForValidation; diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 1b0f5ff..33a1c80 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -54,7 +54,7 @@ cfg_if!{ use sqlx::PgPool; use actix_web::web::Data; use leptos_actix::extract; - use leptos::ServerFnError; + use leptos::prelude::ServerFnError; use crate::backend::mail::Mailer; #[derive(Clone)] diff --git a/src/backend/opening_hours.rs b/src/backend/opening_hours.rs index cdb4134..3c6238f 100644 --- a/src/backend/opening_hours.rs +++ b/src/backend/opening_hours.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use cfg_if::cfg_if; use chrono::Weekday; -use leptos::*; +use leptos::prelude::*; use validator::Validate; use crate::backend::data::{ApiResponse, ClosingTime, DayHour, WeekHours}; use crate::components::data_form::ForValidation; diff --git a/src/backend/property.rs b/src/backend/property.rs index 0f03778..806632b 100644 --- a/src/backend/property.rs +++ b/src/backend/property.rs @@ -1,5 +1,5 @@ use cfg_if::cfg_if; -use leptos::*; +use leptos::prelude::*; use validator::Validate; use crate::backend::data::{ApiResponse, ResProperty}; use crate::components::data_form::ForValidation; diff --git a/src/backend/reservation.rs b/src/backend/reservation.rs index 690021b..28ffa91 100644 --- a/src/backend/reservation.rs +++ b/src/backend/reservation.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use validator::Validate; use crate::backend::data::{ApiResponse, CrReservation, Reservation, PublicFormData, ResSumWithItems, Page, PagedResponse}; use crate::components::data_form::ForValidation; diff --git a/src/backend/user.rs b/src/backend/user.rs index e9b1e84..2c0f711 100644 --- a/src/backend/user.rs +++ b/src/backend/user.rs @@ -1,5 +1,5 @@ use cfg_if::cfg_if; -use leptos::*; +use leptos::prelude::*; use validator::Validate; use crate::backend::data::{ApiResponse, PwdChange, User, UserProfile}; use crate::components::data_form::ForValidation; @@ -157,7 +157,7 @@ pub async fn get_user() -> Result, ServerFnError> { Ok(logged_in_user().await) } -#[server(GetUsers, "/api", "Url", "get_users")] +#[server(name = GetUsers, prefix = "/api", endpoint = "get_users")] pub async fn get_users() -> Result>, ServerFnError> { use crate::perm_check; use crate::backend::get_pool; diff --git a/src/components/admin_portal.rs b/src/components/admin_portal.rs index 84893b8..de471e0 100644 --- a/src/components/admin_portal.rs +++ b/src/components/admin_portal.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::data::User; use crate::components::modal_box::{DialogOpener, ModalBody, ModalDialog}; use crate::components::user_menu::{MenuOpener, UserMenu}; @@ -12,7 +12,7 @@ fn about(opener: DialogOpener) -> impl IntoView {

-

+

{trl("Online booking application for sports facilities and service providers.")}
{format!(" v {}", env!("CARGO_PKG_VERSION"))}

@@ -20,7 +20,7 @@ fn about(opener: DialogOpener) -> impl IntoView {

"(c) 2023 - 2025"
-

+
} @@ -66,7 +66,7 @@ fn settings_menu(opener: MenuOpener) -> impl IntoView { pub fn AdminPortal(children: Children) -> impl IntoView { let user_menu = MenuOpener::new(); let settings_menu = MenuOpener::new(); - let (user, set_user) = create_signal(User::default()); + let (user, set_user) = signal(User::default()); let editor = DialogOpener::new(); let pw_changer = DialogOpener::new(); let drawer = use_context::().expect("No drawer opener"); diff --git a/src/components/data_form.rs b/src/components/data_form.rs index 99a41f1..c4d62e4 100644 --- a/src/components/data_form.rs +++ b/src/components/data_form.rs @@ -1,11 +1,12 @@ use crate::backend::data::ApiResponse; use crate::components::modal_box::{DialogOpener, ModalBody, ModalDialog, ModalFooter}; -use leptos::*; -use leptos::server_fn::client::browser::BrowserClient; -use leptos::server_fn::codec::{Json, PostUrl}; -use leptos::server_fn::error::NoCustomError; -use leptos::server_fn::ServerFn; -use leptos_router::*; +use leptos::prelude::*; +use leptos::form::{ActionForm, FromFormData}; +use leptos::ev::SubmitEvent; +use leptos::server_fn::client::Client; +use leptos::server_fn::codec::PostUrl; +use leptos::server_fn::request::ClientReq; +use leptos::server_fn::{Http, ServerFn}; use serde::de::DeserializeOwned; use validator::Validate; use crate::components::server_err::ServerErr; @@ -18,27 +19,28 @@ pub trait ForValidation { } #[component] -pub fn data_form> + - DeserializeOwned + ForValidation>( +pub fn data_form( opener: DialogOpener, - action: Action, ServerFnError>>, + action: ServerAction, title: &'static str, children: Children -) -> impl IntoView { - let upd_val = action.value(); +) -> impl IntoView +where + T: ServerFn, Output = ApiResponse<()>, Error = ServerFnError> + + DeserializeOwned + ForValidation + Clone + Send + Sync + 'static, + T::Client: Client, + <>::Request as ClientReq>::FormData: From, + O: 'static +{ + let upd_val = Signal::derive(move || action.value().get()); let validator = Validator::new(); view! { @@ -65,20 +67,20 @@ pub fn data_form> - + DeserializeOwned - + Clone>( +pub fn question_dialog( opener: DialogOpener, - action: Action, ServerFnError>>, + action: ServerAction, title: &'static str, children: Children -) -> impl IntoView { - let upd_val = action.value(); +) -> impl IntoView +where + T: ServerFn, Output = ApiResponse<()>, Error = ServerFnError> + + DeserializeOwned + Clone + Send + Sync + 'static, + T::Client: Client, + <>::Request as ClientReq>::FormData: From, + O: 'static +{ + let upd_val = Signal::derive(move || action.value().get()); view! { diff --git a/src/components/header.rs b/src/components/header.rs index 37db58b..3fc76aa 100644 --- a/src/components/header.rs +++ b/src/components/header.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use leptos_meta::*; use crate::app::DialogHelper; use crate::backend::appearance::get_appearance; @@ -8,18 +8,18 @@ use crate::components::user_menu::MenuOpener; pub fn Header() -> impl IntoView { let drawer = use_context::().expect("No drawer opener"); let dlg_helper = use_context::().expect("No dialog helper"); - let appearance = create_blocking_resource(||(), |_| get_appearance()); + let appearance = Resource::new_blocking(||(), |_| get_appearance()); view! { <Meta charset="utf-8"/> @@ -41,19 +41,20 @@ pub fn Header() -> impl IntoView { <Link rel="stylesheet" href="/vendor/css/theme-default.css" /> <Link rel="stylesheet" href="/css/demo.css" /> <Transition fallback=move || view! {""}> - { - appearance.get().map(|a| match a { - Ok(a) => view! {<Link rel="stylesheet" href={format!("/data/{}", a.css_name.unwrap_or_default())} />}, - Err(_) => view! {<Link rel="stylesheet" href="/data/banner.css" />} + {move || { + appearance.get().map(|a| { + let css_name = match a { + Ok(a) => a.css_name.unwrap_or_default(), + Err(_) => "banner.css".to_string() + }; + view! {<Link rel="stylesheet" href={format!("/data/{}", css_name)} />} }) - } + }} </Transition> <Link rel="stylesheet" href="/vendor/css/control.css" /> //<!-- Vendors CSS --> <Link rel="stylesheet" href="/vendor/libs/perfect-scrollbar/perfect-scrollbar.css" /> - <Body attributes=vec![ - ("style", {move || if dlg_helper.is_open() {"overflow: hidden;"} else {""}}.into_attribute()) - ]/> + <Body {..} style={move || if dlg_helper.is_open() {"overflow: hidden;"} else {""}}/> } } \ No newline at end of file diff --git a/src/components/modal_box.rs b/src/components/modal_box.rs index be3b528..112ff0a 100644 --- a/src/components/modal_box.rs +++ b/src/components/modal_box.rs @@ -1,5 +1,5 @@ use crate::locales::trl; -use leptos::*; +use leptos::prelude::*; use crate::app::DialogHelper; use crate::validator::Validator; @@ -11,15 +11,17 @@ pub struct DialogOpener { set_empty: WriteSignal<String>, not_checked: ReadSignal<Option<String>>, set_not_checked: WriteSignal<Option<String>>, - show_err: RwSignal<bool> + show_err: RwSignal<bool>, + // Context is not available in event handlers, so the helper is looked up when the opener is created + dlg_helper: Option<DialogHelper> } impl DialogOpener { pub fn new() -> Self { - let (visible, set_visible) = create_signal(false); - let (empty, set_empty) = create_signal("".to_string()); - let (not_checked, set_not_checked) = create_signal(None); - let show_err = create_rw_signal(false); + let (visible, set_visible) = signal(false); + let (empty, set_empty) = signal("".to_string()); + let (not_checked, set_not_checked) = signal(None); + let show_err = RwSignal::new(false); DialogOpener { visible, set_visible, @@ -27,7 +29,8 @@ impl DialogOpener { set_empty, not_checked, set_not_checked, - show_err + show_err, + dlg_helper: use_context::<DialogHelper>() } } @@ -36,15 +39,17 @@ impl DialogOpener { } pub fn show(&self) { - let dlg_helper = use_context::<DialogHelper>().expect("No dialog helper"); - dlg_helper.set_opened(true); - self.set_visible.update(|state| *state = true); + if let Some(dlg_helper) = self.dlg_helper { + dlg_helper.set_opened(true); + } + self.set_visible.set(true); } pub fn hide(&self) { - let dlg_helper = use_context::<DialogHelper>().expect("No dialog helper"); - dlg_helper.set_opened(false); - self.set_visible.update(|state| *state = false); + if let Some(dlg_helper) = self.dlg_helper { + dlg_helper.set_opened(false); + } + self.set_visible.set(false); self.set_empty.set("".to_string()); self.set_not_checked.set(None); self.show_err.set(false); diff --git a/src/components/server_err.rs b/src/components/server_err.rs index 3cf1721..456cb4f 100644 --- a/src/components/server_err.rs +++ b/src/components/server_err.rs @@ -1,11 +1,12 @@ use crate::components::modal_box::DialogOpener; -use leptos::*; +use leptos::prelude::*; use crate::backend::data::ApiResponse; use crate::locales::trl; #[component] pub fn ServerErr( - result: RwSignal<Option<Result<ApiResponse<()>, ServerFnError>>>, + #[prop(into)] + result: Signal<Option<Result<ApiResponse<()>, ServerFnError>>>, opener: DialogOpener, ) -> impl IntoView { view! {{move || { @@ -23,22 +24,22 @@ pub fn ServerErr( }}> {trl(&err)} </div> - } + }.into_any() } else { opener.hide(); - view! {<div></div>} + view! {<div></div>}.into_any() } Err(e) => { view! { <div class="alert alert-danger"> "Server error: " {e.to_string()} </div> - } + }.into_any() } } } else { - view! {<div></div>} + view! {<div></div>}.into_any() } }} } diff --git a/src/components/user_menu.rs b/src/components/user_menu.rs index 8e84383..4519364 100644 --- a/src/components/user_menu.rs +++ b/src/components/user_menu.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::app::MenuHelper; use crate::backend::data::User; use crate::backend::user::{get_user, logout}; @@ -9,14 +9,17 @@ use crate::locales::trl; pub struct MenuOpener { visible: ReadSignal<bool>, set_visible: WriteSignal<bool>, + // Context is not available in event handlers, so the helper is looked up when the opener is created + helper: Option<MenuHelper>, } impl MenuOpener { pub fn new() -> Self { - let (visible, set_visible) = create_signal(false); + let (visible, set_visible) = signal(false); MenuOpener { visible, set_visible, + helper: use_context::<MenuHelper>(), } } @@ -25,22 +28,24 @@ impl MenuOpener { } pub fn toggle(self) { - let visible = self.visible.get(); - self.set_visible.update(|v| *v = !visible); + let visible = self.visible.get_untracked(); + self.set_visible.set(!visible); - let helper = use_context::<MenuHelper>().expect("No menu helper"); - if !visible { - helper.close(); - helper.set_opened(self); - } else { - helper.reset(); + if let Some(helper) = self.helper { + if !visible { + helper.close(); + helper.set_opened(self); + } else { + helper.reset(); + } } } pub fn close(&self) { self.set_visible.set(false); - let helper = use_context::<MenuHelper>().expect("No menu helper"); - helper.reset(); + if let Some(helper) = self.helper { + helper.reset(); + } } } @@ -50,7 +55,7 @@ pub fn UserMenu( editor: DialogOpener, pw_dialog: DialogOpener, user_profile: WriteSignal<User>) -> impl IntoView { - let user = create_resource(move || opener.visible(), move |_| get_user()); + let user = Resource::new(move || opener.visible(), move |_| get_user()); view! { <ul @@ -84,13 +89,13 @@ pub fn UserMenu( <span class="fw-semibold d-block"> {usr.full_name} </span> - } + }.into_any() } Err(_) => { view! { // <small class="text-muted">"Admin"</small> <span>"Error loading user"</span> - } + }.into_any() } }) }} @@ -114,7 +119,7 @@ pub fn UserMenu( class="dropdown-item" href="/login" on:click=move |_| { - spawn_local(async move { + leptos::task::spawn_local(async move { let _ = logout().await; }); } diff --git a/src/components/validation_err.rs b/src/components/validation_err.rs index fc88d92..aef4967 100644 --- a/src/components/validation_err.rs +++ b/src/components/validation_err.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::locales::trl; use crate::validator::Validator; @@ -20,16 +20,16 @@ pub fn ValidationErr( <div> {out_msgs} </div> - } + }.into_any() } else { view! { <div class="alert alert-danger"> {trl("Validation error")} </div> - } + }.into_any() } } else { - view! {<div></div>} + view! {<div></div>}.into_any() } }} } diff --git a/src/error.rs b/src/error.rs index 8a401c4..1bf2ed9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,7 +1,7 @@ use std::error::Error; use std::fmt::{Debug, Display, Formatter}; use chrono::ParseError; -use leptos::ServerFnError; +use leptos::prelude::ServerFnError; use log::error; #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] diff --git a/src/lib.rs b/src/lib.rs index a5c8934..10a5992 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,6 @@ +// Leptos view types are deeply nested; release builds overflow the default limit +#![recursion_limit = "512"] + pub mod app; pub mod locales; pub mod backend; @@ -7,23 +10,12 @@ mod validator; pub mod error; pub mod config; -use cfg_if::cfg_if; +#[cfg(feature = "hydrate")] +#[wasm_bindgen::prelude::wasm_bindgen] +pub fn hydrate() { + use crate::app::*; -cfg_if! { -if #[cfg(feature = "hydrate")] { + console_error_panic_hook::set_once(); - use wasm_bindgen::prelude::wasm_bindgen; - - #[wasm_bindgen] - pub fn hydrate() { - use app::*; - use leptos::*; - - console_error_panic_hook::set_once(); - - leptos::mount_to_body(move || { - view! { <App/> } - }); - } -} + leptos::mount::hydrate_body(App); } diff --git a/src/locales/catalogues.rs b/src/locales/catalogues.rs index d8bc9a3..3fb9ba9 100644 --- a/src/locales/catalogues.rs +++ b/src/locales/catalogues.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; use lazy_static::lazy_static; -use leptos::*; +use leptos::prelude::*; use crate::locales::Locales; lazy_static! { @@ -182,16 +182,15 @@ lazy_static! { }; } -fn get_locales() -> Vec<Option<String>> { +pub fn get_locales() -> Vec<Option<String>> { #[cfg(not(feature = "ssr"))] { - use_context::<Locales>().unwrap_or(Locales(vec![])).0 + // Context is not available in event handlers, ask the browser there + use_context::<Locales>().unwrap_or_else(crate::locales::browser_locales).0 } #[cfg(feature = "ssr")] { - use actix_web::HttpRequest; - - let req = use_context::<HttpRequest>(); + let req = use_context::<leptos_actix::Request>(); if let Some(r) = req { if let Some(al) = r.head().headers.get("accept-language") { Locales(al.to_str().unwrap_or("").split(",").map(|l| Some(l.to_string())).collect()).0 diff --git a/src/locales/mod.rs b/src/locales/mod.rs index e084c83..cc929b9 100644 --- a/src/locales/mod.rs +++ b/src/locales/mod.rs @@ -1,6 +1,6 @@ use chrono::{NaiveDate, Weekday}; -use leptos::use_context; -use crate::locales::catalogues::get_dictionary; +use leptos::prelude::*; +use crate::locales::catalogues::{get_dictionary, get_locales}; mod catalogues; @@ -10,24 +10,12 @@ pub struct Locales(pub Vec<Option<String>>); pub fn init_locales() { #[cfg(not(feature = "ssr"))] { - use leptos::*; - let loc = Locales( - window() - .navigator() - .languages() - .into_iter() - .map(|val| val.as_string()) - .collect::<Vec<_>>(), - ); - provide_context(loc); + provide_context(browser_locales()); } #[cfg(feature = "ssr")] { - use actix_web::HttpRequest; - use leptos::provide_context; - - let req = use_context::<HttpRequest>(); + let req = use_context::<leptos_actix::Request>(); if let Some(r) = req { if r.query_string().contains("lang") { let languages = r.query_string() @@ -49,6 +37,19 @@ pub fn init_locales() { } } +/// Languages preferred by the browser +#[cfg(not(feature = "ssr"))] +pub fn browser_locales() -> Locales { + Locales( + window() + .navigator() + .languages() + .into_iter() + .map(|val| val.as_string()) + .collect::<Vec<_>>(), + ) +} + pub fn trl(phrase: &str) -> impl Fn() -> String { let mut translated = phrase; if let Some(dict) = get_dictionary() { @@ -65,8 +66,7 @@ pub fn trl(phrase: &str) -> impl Fn() -> String { // ToDo better date formatting pub fn loc_date(date: NaiveDate) -> impl Fn() -> String { let mut dt = date.format("%Y-%m-%d").to_string(); - let locs = use_context::<Locales>().unwrap_or(Locales(vec![])).0; - for loc in locs { + for loc in get_locales() { if let Some(key) = loc { if let Some(k) = key.split("-").collect::<Vec<_>>().get(0) { if *k != "en" { diff --git a/src/main.rs b/src/main.rs index 5cb9c5a..73f6e09 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,6 @@ +// Leptos view types are deeply nested; release builds overflow the default limit +#![recursion_limit = "512"] + use actix_web::middleware::Logger; use leptos_captcha::spow::pow::Pow; use log::error; @@ -11,7 +14,9 @@ use rezervator::backend::user::create_admin; async fn main() -> std::io::Result<()> { use actix_files::Files; use actix_web::*; - use leptos::*; + use leptos::prelude::*; + use leptos::config::get_configuration; + use leptos_meta::MetaTags; use leptos_actix::{generate_route_list, LeptosRoutes}; use rezervator::app::*; use rezervator::backend::*; @@ -48,9 +53,7 @@ async fn main() -> std::io::Result<()> { env_logger::Builder::from_env(Env::default().default_filter_or(srv_conf.logging().severity())).init(); info!("Starting server"); - let conf = get_configuration(None).await.unwrap(); - // Generate the list of routes in your Leptos App - let routes = generate_route_list(|| view! { <App/> }); + let conf = get_configuration(None).unwrap(); let key = Key::from(srv_conf.session().key()); let pool = PgPoolOptions::new() @@ -75,8 +78,10 @@ async fn main() -> std::io::Result<()> { } HttpServer::new(move || { + // Generate the list of routes in your Leptos App + let routes = generate_route_list(App); let leptos_options = &conf.leptos_options; - let site_root = &leptos_options.site_root; + let site_root = leptos_options.site_root.clone().to_string(); App::new() .app_data(Data::new(AppData::new(pool.clone(), mailer.clone()))) @@ -86,12 +91,26 @@ async fn main() -> std::io::Result<()> { CookieSessionStore::default(), key.clone() )) - .route("/api/{tail:.*}", leptos_actix::handle_server_fns()) - .leptos_routes( - leptos_options.to_owned(), - routes.to_owned(), - || view! { <App/> }, - ) + // Server functions under /api are registered by leptos_routes + .leptos_routes(routes, { + let leptos_options = leptos_options.clone(); + move || { + view! { + <!DOCTYPE html> + <html> + <head> + <AutoReload options=leptos_options.clone()/> + <HydrationScripts options=leptos_options.clone()/> + <MetaTags/> + </head> + <body> + <App/> + </body> + </html> + } + } + }) + .app_data(Data::new(leptos_options.to_owned())) .service(appearance::upload) .service(Files::new("/", site_root)) .wrap(middleware::Compress::default()) @@ -114,15 +133,9 @@ pub fn main() { // a client-side main function is required for using `trunk serve` // prefer using `cargo leptos serve` instead // to run: `trunk serve --open --features ssg` - use leptos::*; - use leptos_start::app::*; - use wasm_bindgen::prelude::wasm_bindgen; + use rezervator::app::*; console_error_panic_hook::set_once(); - leptos::mount_to_body(move || { - // note: for testing it may be preferrable to replace this with a - // more specific component, although leptos_router should still work - view! {<App/> } - }); + leptos::mount::mount_to_body(App); } diff --git a/src/pages/all_reservations.rs b/src/pages/all_reservations.rs index fa131d0..d5dc101 100644 --- a/src/pages/all_reservations.rs +++ b/src/pages/all_reservations.rs @@ -1,5 +1,5 @@ use chrono::{Datelike, Local}; -use leptos::*; +use leptos::prelude::*; use crate::backend::data::{ApiResponse, ReservationState, ResSumWithItems}; use crate::backend::reservation::{month_chart, reservations_in_month, year_chart, years}; use crate::components::modal_box::{DialogOpener, ModalBody, ModalDialog}; @@ -11,7 +11,7 @@ use crate::pages::new_reservations::CancelDialog; fn booking_detail(reservation: ReadSignal<ResSumWithItems>, opener: DialogOpener) -> impl IntoView { let menu = MenuOpener::new(); let cancel_opener = DialogOpener::new(); - let menu_visible = create_rw_signal(false); + let menu_visible = RwSignal::new(false); view! { <CancelDialog opener=cancel_opener reservation=reservation/> <ModalDialog title="Booking detail" opener=opener> @@ -27,7 +27,7 @@ fn booking_detail(reservation: ReadSignal<ResSumWithItems>, opener: DialogOpener let:item> {item.property.name}": "{item.reservation.from.to_string()}" - "{item.reservation.to.to_string()}<br/> </For> - {trl("Customer: ")}{detail.customer.full_name}", "<a href={format!("mailto:{}", detail.customer.email)}>{detail.customer.email}</a>", "{detail.customer.phone}<br/> + {trl("Customer: ")}{detail.customer.full_name}", "<a href={format!("mailto:{}", detail.customer.email)}>{detail.customer.email.clone()}</a>", "{detail.customer.phone}<br/> { let note = detail.summary.note.clone(); let show = note.is_some() && !note.clone().unwrap().is_empty(); @@ -42,7 +42,7 @@ fn booking_detail(reservation: ReadSignal<ResSumWithItems>, opener: DialogOpener }} </p> <Show when=move || menu_visible.get()> - <table width="100%"> + <table style="width: 100%"><tbody> <tr> <td width="100%"></td> <td> @@ -62,7 +62,7 @@ fn booking_detail(reservation: ReadSignal<ResSumWithItems>, opener: DialogOpener </div> </td> </tr> - </table> + </tbody></table> </Show> </ModalBody> </ModalDialog> @@ -71,15 +71,15 @@ fn booking_detail(reservation: ReadSignal<ResSumWithItems>, opener: DialogOpener #[component] pub fn bookings() -> impl IntoView { - let year_chart = create_blocking_resource(||(), |_| year_chart()); - let years = create_blocking_resource(||(), |_| years()); - let year = create_rw_signal(Local::now().year()); - let month = create_rw_signal(Local::now().month()); - let chart = create_blocking_resource(move || year.get(),move |y| month_chart(y)); + let year_chart = Resource::new_blocking(||(), |_| year_chart()); + let years = Resource::new_blocking(||(), |_| years()); + let year = RwSignal::new(Local::now().year()); + let month = RwSignal::new(Local::now().month()); + let chart = Resource::new_blocking(move || year.get(),move |y| month_chart(y)); let detail_dlg = DialogOpener::new(); - let reservations = create_blocking_resource(move || (year.get(), month.get(), detail_dlg.visible()), move |p| reservations_in_month(p.0, p.1)); + let reservations = Resource::new_blocking(move || (year.get(), month.get(), detail_dlg.visible()), move |p| reservations_in_month(p.0, p.1)); let all_months: Vec<u32> = vec![1,2,3,4,5,6,7,8,9,10,11,12]; - let res_detail = create_rw_signal(ResSumWithItems::default()); + let res_detail = RwSignal::new(ResSumWithItems::default()); view! { <h1>{trl("Booking overview")}</h1> @@ -94,7 +94,7 @@ pub fn bookings() -> impl IntoView { </li> <li class="nav-item"> <Transition fallback=move || view! {<div>"Loading"</div>} > - { + {move || { years.get().map(|y| match y { Ok(y) => { view! { @@ -106,11 +106,11 @@ pub fn bookings() -> impl IntoView { <option prop:value=move || y prop:selected=move || year.get() == y>{y}</option> </For> </select> - } + }.into_any() } - Err(_) => {view! {<select><option></option></select>}} + Err(_) => {view! {<select><option></option></select>}.into_any()} }) - } + }} </Transition> </li> <li class="nav-item"> @@ -135,30 +135,24 @@ pub fn bookings() -> impl IntoView { <div class="col-md"> <div class="card md-3"> <Transition fallback=move || view! {<div>"Loading"</div>}> - { + {move || { chart.get().map(move |c| match c { - Ok(c) => { match c { - ApiResponse::Data(c) => {view! {<img style="margin: 1em" src={c.clone()} /> }} - ApiResponse::Error(_) => {view! {<img src=""/> }} } - } - Err(_) => { view! {<img src=""/> } } + Ok(ApiResponse::Data(c)) => {view! {<img style="margin: 1em" src={c.clone()} /> }.into_any()} + _ => { view! {<img src=""/> }.into_any() } }) - } + }} </Transition> </div> </div> <div class="col-md"> <div class="card md-3"> <Transition fallback=move || view! {<div>"Loading"</div>}> - { + {move || { year_chart.get().map(move |c| match c { - Ok(c) => { match c { - ApiResponse::Data(c) => {view! {<img style="margin: 1em" src={c.clone()} /> }} - ApiResponse::Error(_) => {view! {<img src=""/> }} } - } - Err(_) => { view! {<img src=""/> } } + Ok(ApiResponse::Data(c)) => {view! {<img style="margin: 1em" src={c.clone()} /> }.into_any()} + _ => { view! {<img src=""/> }.into_any() } }) - } + }} </Transition> </div> </div> @@ -178,7 +172,7 @@ pub fn bookings() -> impl IntoView { <th>{trl("Actions")}</th> </tr> </thead> - { + {move || { reservations.get().map(|r| match r { Ok(r) => { match r { ApiResponse::Data(r) => { @@ -202,20 +196,20 @@ pub fn bookings() -> impl IntoView { </tr> </For> </tbody> - } + }.into_any() } ApiResponse::Error(e) => { view! {<tbody class="table-border-bottom-0"> - <tr><td colspan=5>{trl("Something went wrong")}<br/>{e.to_string()}</td></tr></tbody>} + <tr><td colspan=5>{trl("Something went wrong")}<br/>{e.to_string()}</td></tr></tbody>}.into_any() } } } Err(e) => { view! {<tbody class="table-border-bottom-0"> - <tr><td colspan=5>{trl("Something went wrong")}<br/>{e.to_string()}</td></tr></tbody>} + <tr><td colspan=5>{trl("Something went wrong")}<br/>{e.to_string()}</td></tr></tbody>}.into_any() } }) - } + }} </table> </Transition> </div> diff --git a/src/pages/appearance_settings.rs b/src/pages/appearance_settings.rs index 62b0571..d9a6128 100644 --- a/src/pages/appearance_settings.rs +++ b/src/pages/appearance_settings.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::appearance::{DeleteBanner, get_appearance, UpdateAppearance}; use crate::backend::data::Appearance; use crate::components::data_form::{DataForm, QuestionDialog}; @@ -7,7 +7,7 @@ use crate::locales::trl; #[component] fn edit_title(opener: DialogOpener, appearance: ReadSignal<Appearance>) -> impl IntoView { - let update = create_server_action::<UpdateAppearance>(); + let update = ServerAction::<UpdateAppearance>::new(); view! { <DataForm opener=opener action=update title="Update title"> <input type="hidden" prop:value={move || appearance.get().text.unwrap_or_default()} name="appearance[text]" /> @@ -31,7 +31,7 @@ fn edit_title(opener: DialogOpener, appearance: ReadSignal<Appearance>) -> impl #[component] fn edit_text(opener: DialogOpener, appearance: ReadSignal<Appearance>) -> impl IntoView { - let update = create_server_action::<UpdateAppearance>(); + let update = ServerAction::<UpdateAppearance>::new(); view! { <DataForm opener=opener action=update title="Update text"> <input type="hidden" prop:value={move || appearance.get().title.unwrap_or_default()} name="appearance[title]" /> @@ -53,7 +53,7 @@ fn edit_text(opener: DialogOpener, appearance: ReadSignal<Appearance>) -> impl I #[component] fn delete_banner(opener: DialogOpener) -> impl IntoView { - let delete = create_server_action::<DeleteBanner>(); + let delete = ServerAction::<DeleteBanner>::new(); view! { <QuestionDialog opener=opener action=delete title="Delete banner"> <div>{trl("Are you sure you want to delete banner?")}</div> @@ -66,8 +66,8 @@ pub fn appearance() -> impl IntoView { let title_edit = DialogOpener::new(); let text_edit = DialogOpener::new(); let del_dialog = DialogOpener::new(); - let appearance = create_resource(move || title_edit.visible() || text_edit.visible() || del_dialog.visible(), |_| get_appearance()); - let app_edit = create_rw_signal(Appearance::default()); + let appearance = Resource::new(move || title_edit.visible() || text_edit.visible() || del_dialog.visible(), |_| get_appearance()); + let app_edit = RwSignal::new(Appearance::default()); view! { <EditTitle opener=title_edit appearance=app_edit.read_only()/> <EditText opener=text_edit appearance=app_edit.read_only()/> @@ -85,16 +85,17 @@ pub fn appearance() -> impl IntoView { </button> </form><br/> <Transition fallback=move || view! {<p>{trl("Loading...")}</p> }> - { + {move || { appearance.get().map(|a| match a { - Ok(a) => { - app_edit.set(a.clone()); - let app = a.clone(); + Ok(app) => { + app_edit.set(app.clone()); + let has_banner = app.banner.is_some(); + let title = app.title.clone().unwrap_or_default(); view! { <div> - <Show when=move || a.clone().banner.is_some()> + <Show when=move || has_banner> <div class="header_banner"> - <h1 class="header_banner">{app.title.clone().unwrap_or_default()}</h1> + <h1 class="header_banner">{title.clone()}</h1> </div> </Show> <div> @@ -111,13 +112,13 @@ pub fn appearance() -> impl IntoView { <i class="bx bx-edit-alt me-1"></i> {trl("Edit text")}</a> </div> </div> - } + }.into_any() } Err(e) => {view! {<div><p>{trl("Error loading data")}</p> <p>{e.to_string()}</p></div> - }} + }.into_any()} }) - } + }} </Transition> </div> diff --git a/src/pages/change_pwd.rs b/src/pages/change_pwd.rs index 029fdfb..e0cfdd7 100644 --- a/src/pages/change_pwd.rs +++ b/src/pages/change_pwd.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::data::User; use crate::backend::user::{ChangePwd, get_user}; use crate::components::data_form::DataForm; @@ -7,8 +7,8 @@ use crate::locales::trl; #[component] pub fn change_password(user: ReadSignal<User>, opener: DialogOpener) -> impl IntoView { - let change_pwd = create_server_action::<ChangePwd>(); - let logged_in = create_resource(||(), move |_| get_user()); + let change_pwd = ServerAction::<ChangePwd>::new(); + let logged_in = Resource::new(||(), move |_| get_user()); view! { <DataForm opener=opener action=change_pwd title="Change password"> diff --git a/src/pages/closing_days.rs b/src/pages/closing_days.rs index ff98472..19e1185 100644 --- a/src/pages/closing_days.rs +++ b/src/pages/closing_days.rs @@ -1,5 +1,5 @@ use chrono::Local; -use leptos::*; +use leptos::prelude::*; use crate::backend::data::ClosingTime; use crate::backend::opening_hours::{get_closing_times, DeleteClosingTime, InsertClosingTime}; use crate::components::data_form::{DataForm, QuestionDialog}; @@ -8,7 +8,7 @@ use crate::locales::{loc_date, trl}; #[component] pub fn del_closing_day(closing_time: ReadSignal<ClosingTime>, opener: DialogOpener) -> impl IntoView { - let delete = create_server_action::<DeleteClosingTime>(); + let delete = ServerAction::<DeleteClosingTime>::new(); view! { <QuestionDialog opener=opener action=delete title="Delete closing days"> @@ -20,7 +20,7 @@ pub fn del_closing_day(closing_time: ReadSignal<ClosingTime>, opener: DialogOpen #[component] pub fn insert_closing_days(opener: DialogOpener) -> impl IntoView { - let insert_day = create_server_action::<InsertClosingTime>(); + let insert_day = ServerAction::<InsertClosingTime>::new(); view! { <DataForm opener=opener action=insert_day title="Closing days"> @@ -52,8 +52,8 @@ pub fn insert_closing_days(opener: DialogOpener) -> impl IntoView { pub fn closing_days() -> impl IntoView { let delete_dialog = DialogOpener::new(); let editor = DialogOpener::new(); - let times = create_blocking_resource(move || editor.visible() || delete_dialog.visible(), move |_| {get_closing_times()}); - let time_to_del = create_rw_signal(ClosingTime::default()); + let times = Resource::new_blocking(move || editor.visible() || delete_dialog.visible(), move |_| {get_closing_times()}); + let time_to_del = RwSignal::new(ClosingTime::default()); view! { <DelClosingDay closing_time=time_to_del.read_only() opener=delete_dialog/> <InsertClosingDays opener=editor/> @@ -78,7 +78,7 @@ pub fn closing_days() -> impl IntoView { e.to_string() }; view! {<tbody class="table-border-bottom-0"> - <tr><td colspan=3>{trl(&err)}</td></tr></tbody>}} + <tr><td colspan=3>{trl(&err)}</td></tr></tbody>}.into_any()} Ok(c) => { view! {<tbody class="table-border-bottom-0"> <For each=move || c.clone() @@ -100,7 +100,7 @@ pub fn closing_days() -> impl IntoView { </tr> } }/></tbody> - } + }.into_any() } }) }} diff --git a/src/pages/company_edit.rs b/src/pages/company_edit.rs index ee1b192..6afdb00 100644 --- a/src/pages/company_edit.rs +++ b/src/pages/company_edit.rs @@ -1,7 +1,7 @@ use crate::backend::data::Company; use crate::backend::company::UpdateCompany; use crate::components::modal_box::DialogOpener; -use leptos::*; +use leptos::prelude::*; use crate::components::data_form::DataForm; use crate::locales::trl; @@ -10,7 +10,7 @@ pub fn CompanyEdit( company: ReadSignal<Company>, opener: DialogOpener, ) -> impl IntoView { - let update_company = create_server_action::<UpdateCompany>(); + let update_company = ServerAction::<UpdateCompany>::new(); view! { <DataForm opener=opener action=update_company title="Edit company"> diff --git a/src/pages/company_info.rs b/src/pages/company_info.rs index 277739c..0a430ee 100644 --- a/src/pages/company_info.rs +++ b/src/pages/company_info.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::company::get_company; use crate::backend::data::{ApiResponse, Company}; use crate::components::modal_box::DialogOpener; @@ -8,21 +8,21 @@ use crate::pages::company_edit::CompanyEdit; #[component] pub fn CompanyInfo() -> impl IntoView { let editor = DialogOpener::new(); - let company = create_blocking_resource(move|| editor.visible(), move |_| { get_company() }); - let (cmp, set_cmp) = create_signal(Company::default()); + let company = Resource::new_blocking(move|| editor.visible(), move |_| { get_company() }); + let (cmp, set_cmp) = signal(Company::default()); view! { <CompanyEdit company={cmp} opener=editor/> <div class="card mb-3"> <div class="card-body"> <h5 class="card-title"><i class="bx bx-buildings"></i>" "{trl("Company info")}</h5> - <p class="card-text"> + <div class="card-text"> <Transition fallback=move || view! {<p>{trl("Loading...")}</p> }> {move || { company.get().map(|c| match c { Err(e) => {view! {<div><p>{trl("Error loading data")}</p> <p>{e.to_string()}</p></div> - }} + }.into_any()} Ok(c) => { match c { ApiResponse::Data(d) => {set_cmp.update(|cmp| *cmp = d.clone()); @@ -30,16 +30,16 @@ pub fn CompanyInfo() -> impl IntoView { <p><b>{d.name}</b></p> <p>{d.street}" "{d.house_number}<br/> {d.zip_code}" "{d.city} - </p></div>} + </p></div>}.into_any() } - ApiResponse::Error(_) => {view! {<div><p>{trl("Error loading data")}</p></div>}} + ApiResponse::Error(_) => {view! {<div><p>{trl("Error loading data")}</p></div>}.into_any()} } } }) }} </Transition> - </p> + </div> <a href="javascript:void(0)" class="card-link" on:click = move |_| editor.show()> <i class="bx bx-edit-alt fs-4 lh-0"></i></a> </div> diff --git a/src/pages/customers.rs b/src/pages/customers.rs index 7f3e8e5..c63d0c1 100644 --- a/src/pages/customers.rs +++ b/src/pages/customers.rs @@ -1,11 +1,11 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::customer::get_customers; use crate::backend::data::ApiResponse; use crate::locales::trl; #[component] pub fn customers() -> impl IntoView { - let customers = create_blocking_resource(||(), |_| get_customers()); + let customers = Resource::new_blocking(||(), |_| get_customers()); view! { <h1>{trl("Customers")}</h1> @@ -21,7 +21,7 @@ pub fn customers() -> impl IntoView { <th>{trl("Phone")}</th> </tr> </thead> - { + {move || { customers.get().map(|c| match c { Ok(c) => {match c { ApiResponse::Data(c) => { @@ -35,20 +35,20 @@ pub fn customers() -> impl IntoView { </tr> </For> </tbody> - } + }.into_any() } ApiResponse::Error(e) => { view! {<tbody class="table-border-bottom-0"> - <tr><td colspan=3>{trl("Something went wrong")}<br/>{e.to_string()}</td></tr></tbody>} + <tr><td colspan=3>{trl("Something went wrong")}<br/>{e.to_string()}</td></tr></tbody>}.into_any() } } } Err(e) => { view! {<tbody class="table-border-bottom-0"> - <tr><td colspan=3>{trl("Something went wrong")}<br/>{e.to_string()}</td></tr></tbody>} + <tr><td colspan=3>{trl("Something went wrong")}<br/>{e.to_string()}</td></tr></tbody>}.into_any() } }) - } + }} </table> </Transition> </div> diff --git a/src/pages/home_page.rs b/src/pages/home_page.rs index d1305b8..78d87ad 100644 --- a/src/pages/home_page.rs +++ b/src/pages/home_page.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::components::modal_box::DialogOpener; use crate::locales::trl; use crate::pages::new_reservations::NewReservations; diff --git a/src/pages/hours_edit.rs b/src/pages/hours_edit.rs index ad36d4a..e602251 100644 --- a/src/pages/hours_edit.rs +++ b/src/pages/hours_edit.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::data::WeekHours; use crate::backend::opening_hours::{DeleteClosingTime, UpdateHours}; use crate::components::data_form::{DataForm, QuestionDialog}; @@ -7,7 +7,7 @@ use crate::locales::trl; #[component] pub fn EditHours(opener: DialogOpener, hours: ReadSignal<WeekHours>) -> impl IntoView { - let update_hours = create_server_action::<UpdateHours>(); + let update_hours = ServerAction::<UpdateHours>::new(); view! { <DataForm opener=opener action=update_hours title="Edit hours"> @@ -31,7 +31,7 @@ pub fn EditHours(opener: DialogOpener, hours: ReadSignal<WeekHours>) -> impl Int #[component] pub fn del_closing_days(opener: DialogOpener) -> impl IntoView { - let delete = create_server_action::<DeleteClosingTime>(); + let delete = ServerAction::<DeleteClosingTime>::new(); view! { <QuestionDialog opener=opener action=delete title="Delete closing days"> diff --git a/src/pages/login.rs b/src/pages/login.rs index fe5f5b9..fedd27f 100644 --- a/src/pages/login.rs +++ b/src/pages/login.rs @@ -1,6 +1,6 @@ -use leptos::*; +use leptos::prelude::*; use leptos_meta::*; -use leptos_router::ActionForm; +use leptos::form::ActionForm; use crate::backend::user::Login; use crate::components::modal_box::DialogOpener; use crate::components::server_err::ServerErr; @@ -8,8 +8,8 @@ use crate::locales::trl; #[component] pub fn Login() -> impl IntoView { - let login = create_server_action::<Login>(); - let login_val = login.value(); + let login = ServerAction::<Login>::new(); + let login_val = Signal::derive(move || login.value().get()); view! { <Link rel="stylesheet" href="/vendor/css/pages/page-auth.css" /> <div class="authentication-wrapper authentication-basic container-p-y"> diff --git a/src/pages/mail_settings.rs b/src/pages/mail_settings.rs index 0341f82..2457a53 100644 --- a/src/pages/mail_settings.rs +++ b/src/pages/mail_settings.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::data::MessageType; use crate::locales::trl; use crate::pages::mail_view::MailView; diff --git a/src/pages/mail_view.rs b/src/pages/mail_view.rs index 9e2c5f0..4a2f5d5 100644 --- a/src/pages/mail_view.rs +++ b/src/pages/mail_view.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::data::{Message, MessageType}; use crate::backend::mail::{get_message, UpdateMessage}; use crate::components::data_form::DataForm; @@ -7,7 +7,7 @@ use crate::locales::trl; #[component] fn mail_edit(opener: DialogOpener, mail: ReadSignal<Message>) -> impl IntoView { - let update = create_server_action::<UpdateMessage>(); + let update = ServerAction::<UpdateMessage>::new(); view! { <DataForm opener=opener title="Edit mail" action=update> @@ -44,17 +44,17 @@ fn mail_edit(opener: DialogOpener, mail: ReadSignal<Message>) -> impl IntoView { #[component] pub fn mail_view(title: &'static str, mail_type: MessageType) -> impl IntoView { let editor = DialogOpener::new(); - let mail = create_blocking_resource( move || editor.visible(), move |_| get_message(mail_type.clone())); - let for_edit = create_rw_signal(Message::default()); + let mail = Resource::new_blocking( move || editor.visible(), move |_| get_message(mail_type.clone())); + let for_edit = RwSignal::new(Message::default()); view! { <MailEdit opener=editor mail={for_edit.read_only()}/> <div class="card mb-3"> <div class="card-body"> <h5 class="card-title"><i class="bx bx-buildings"></i>" "{trl(title)}</h5> - <p class="card-text"> + <div class="card-text"> <Transition fallback=move || view! {<p>{trl("Loading...")}</p> }> - { + {move || { mail.get().map(|m| match m { Ok(m) => { for_edit.set(m.clone()); @@ -63,16 +63,16 @@ pub fn mail_view(title: &'static str, mail_type: MessageType) -> impl IntoView { <p>{trl("Subject: ")}{m.subject}</p> <p>{m.text}</p> </div> - } + }.into_any() } Err(_) => { view! { <div>"Error loading data"</div> - } + }.into_any() }}) - } + }} </Transition> - </p> + </div> <a href="javascript:void(0)" class="card-link" on:click = move |_| editor.show()> <i class="bx bx-edit-alt fs-4 lh-0"></i></a> </div> diff --git a/src/pages/new_reservations.rs b/src/pages/new_reservations.rs index e0e2244..73e3c77 100644 --- a/src/pages/new_reservations.rs +++ b/src/pages/new_reservations.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::data::{ApiResponse, Page, ResSumWithItems}; use crate::backend::reservation::{Approve, Cancel, get_new_reservations}; use crate::components::data_form::QuestionDialog; @@ -10,7 +10,7 @@ use chrono::Datelike; #[component] fn approve_dialog(reservation: ReadSignal<ResSumWithItems>, opener: DialogOpener) -> impl IntoView { - let approve = create_server_action::<Approve>(); + let approve = ServerAction::<Approve>::new(); view! { <QuestionDialog opener=opener action=approve title="Approve booking"> @@ -27,7 +27,7 @@ fn approve_dialog(reservation: ReadSignal<ResSumWithItems>, opener: DialogOpener #[component] pub fn cancel_dialog(reservation: ReadSignal<ResSumWithItems>, opener: DialogOpener) -> impl IntoView { - let cancel = create_server_action::<Cancel>(); + let cancel = ServerAction::<Cancel>::new(); view! { <QuestionDialog opener=opener action=cancel title="Cancel booking"> @@ -56,13 +56,13 @@ fn create_dialog(opener: DialogOpener) -> impl IntoView { #[component] pub fn new_reservations(app_opener: DialogOpener, cancel_opener: DialogOpener) -> impl IntoView { let create = DialogOpener::new(); - let page = create_rw_signal(Page::new(5)); - let first = create_rw_signal(false); - let last = create_rw_signal(false); - let total_pages = create_rw_signal(0i32); - let res = create_blocking_resource(move || (app_opener.visible() || cancel_opener.visible() || create.visible(), page), + let page = RwSignal::new(Page::new(5)); + let first = RwSignal::new(false); + let last = RwSignal::new(false); + let total_pages = RwSignal::new(0i32); + let res = Resource::new_blocking(move || (app_opener.visible() || cancel_opener.visible() || create.visible(), page), move |d| get_new_reservations(d.1.get())); - let reservation = create_rw_signal(ResSumWithItems::default()); + let reservation = RwSignal::new(ResSumWithItems::default()); view! { <ApproveDialog opener=app_opener reservation=reservation.read_only() /> @@ -75,7 +75,7 @@ pub fn new_reservations(app_opener: DialogOpener, cancel_opener: DialogOpener) - {move || { res.get().map(|r| match r { Err(e) => { - view! {<div>{trl("Something went wrong")}<br/>{e.to_string()}</div>}} + view! {<div>{trl("Something went wrong")}<br/>{e.to_string()}</div>}.into_any()} Ok(r) => { match r { ApiResponse::Data(r) => { first.set(r.is_first()); @@ -98,7 +98,7 @@ pub fn new_reservations(app_opener: DialogOpener, cancel_opener: DialogOpener) - let:item> {item.property.name}": "{item.reservation.from.to_string()}" - "{item.reservation.to.to_string()}<br/> </For> - {trl("Customer: ")}{data.customer.full_name}", "<a href={format!("mailto:{}", data.customer.email)}>{data.customer.email}</a>", "{data.customer.phone}<br/> + {trl("Customer: ")}{data.customer.full_name}", "<a href={format!("mailto:{}", data.customer.email)}>{data.customer.email.clone()}</a>", "{data.customer.phone}<br/> {move || { let note = data.summary.note.clone(); let show = note.is_some() && !note.clone().unwrap().is_empty(); @@ -109,7 +109,7 @@ pub fn new_reservations(app_opener: DialogOpener, cancel_opener: DialogOpener) - } }} {trl("Price: ")}{data.summary.price.to_string()}<br/> - <table width="100%"> + <table style="width: 100%"><tbody> <tr> <td width="100%"></td> <td> @@ -135,15 +135,15 @@ pub fn new_reservations(app_opener: DialogOpener, cancel_opener: DialogOpener) - </div> </td> </tr> - </table> + </tbody></table> <hr/> } }} </For> </div> - } + }.into_any() } - ApiResponse::Error(e) => {view! {<div>{trl(&e)}</div>}}} + ApiResponse::Error(e) => {view! {<div>{trl(&e)}</div>}.into_any()}} } }) }} diff --git a/src/pages/opening_hours.rs b/src/pages/opening_hours.rs index 9dabd5d..2e09fc1 100644 --- a/src/pages/opening_hours.rs +++ b/src/pages/opening_hours.rs @@ -1,5 +1,5 @@ use chrono::Weekday; -use leptos::*; +use leptos::prelude::*; use crate::backend::data::{DayHours, WeekHours}; use crate::backend::opening_hours::get_hours; use crate::components::modal_box::DialogOpener; @@ -18,8 +18,8 @@ fn show_time(tm: &str) -> impl Fn() -> String { pub fn OpeningHours() -> impl IntoView { let editor = DialogOpener::new(); let closing_delete = DialogOpener::new(); - let hours = create_blocking_resource(move || editor.visible(), move |_| {get_hours()}); - let hrs = create_rw_signal(WeekHours::default()); + let hours = Resource::new_blocking(move || editor.visible(), move |_| {get_hours()}); + let hrs = RwSignal::new(WeekHours::default()); view! { <EditHours opener=editor hours=hrs.read_only() /> @@ -27,16 +27,16 @@ pub fn OpeningHours() -> impl IntoView { <div class="card mb-3"> <div class="card-body"> <h5 class="card-title"><i class="bx bxs-watch"></i>" "{trl("Opening hours")}</h5> - <p class="card-text"> + <div class="card-text"> <Transition fallback=move || view! {<p>{trl("Loading...")}</p> }> {move || { hours.get().map(|h| match h { Ok(h) => { - let h = create_rw_signal(h); - let d = create_rw_signal((0..7).collect::<Vec<u8>>()); + let h = RwSignal::new(h); + let d = RwSignal::new((0..7).collect::<Vec<u8>>()); view! { <div> - <table class="table card-table"> + <table class="table card-table"><tbody> <For each=move || d.get() key=|day| *day children=move |day| { let week_day = Weekday::try_from(day).unwrap_or(Weekday::Mon); @@ -54,17 +54,17 @@ pub fn OpeningHours() -> impl IntoView { } } /> - </table> + </tbody></table> </div> - } + }.into_any() } Err(e) => {view! {<div><p>{trl("Error loading data")}</p> <p>{e.to_string()}</p></div> - }} + }.into_any()} }) }} </Transition> - </p> + </div> </div> </div> } diff --git a/src/pages/profile_edit.rs b/src/pages/profile_edit.rs index ea9cd4d..e624dfa 100644 --- a/src/pages/profile_edit.rs +++ b/src/pages/profile_edit.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::data::User; use crate::backend::user::{get_user, UpdateProfile}; use crate::components::data_form::DataForm; @@ -7,8 +7,8 @@ use crate::locales::trl; #[component] pub fn ProfileEdit(user: ReadSignal<User>, opener: DialogOpener) -> impl IntoView { - let update_user = create_server_action::<UpdateProfile>(); - let logged_in = create_resource(||(), move |_| get_user()); + let update_user = ServerAction::<UpdateProfile>::new(); + let logged_in = Resource::new(||(), move |_| get_user()); view! { <DataForm opener=opener action=update_user title="Edit profile"> diff --git a/src/pages/properties.rs b/src/pages/properties.rs index 6540667..3e50c22 100644 --- a/src/pages/properties.rs +++ b/src/pages/properties.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use leptos_use::use_media_query; use crate::backend::data::{ApiResponse, ResProperty}; use crate::backend::property::get_properties; @@ -11,13 +11,13 @@ use crate::pages::property_edit::PropertyEdit; #[component] pub fn properties() -> impl IntoView { let is_wide = use_media_query("(min-width: 500px)"); - let properties = create_rw_signal::<Vec<ResProperty>>(vec![]); - let prop = create_rw_signal(ResProperty::default()); - let empty_prop = create_rw_signal(ResProperty::default()); + let properties = RwSignal::<Vec<ResProperty>>::new(vec![]); + let prop = RwSignal::new(ResProperty::default()); + let empty_prop = RwSignal::new(ResProperty::default()); let create_form = DialogOpener::new(); let edit_form = DialogOpener::new(); let delete_dlg = DialogOpener::new(); - let props = create_blocking_resource(move || create_form.visible() || edit_form.visible() || delete_dlg.visible(), move |_| get_properties()); + let props = Resource::new_blocking(move || create_form.visible() || edit_form.visible() || delete_dlg.visible(), move |_| get_properties()); view! { <PropertyEdit property=prop.read_only() opener=edit_form edit=true/> @@ -31,8 +31,8 @@ pub fn properties() -> impl IntoView { <thead> <tr> <th>{trl("Name")}</th> - {move || if is_wide.get() {view! {<th>{trl("Description")}</th>}} - else {view! {<th></th>}} } + {move || if is_wide.get() {view! {<th>{trl("Description")}</th>}.into_any()} + else {view! {<th></th>}.into_any()} } <th>{trl("Price")}</th> <th>{trl("Actions")}</th> </tr> @@ -41,7 +41,7 @@ pub fn properties() -> impl IntoView { props.get().map(|u| match u { Err(e) => { view! {<tbody class="table-border-bottom-0"> - <tr><td colspan=4>{trl("Something went wrong")}<br/>{e.to_string()}</td></tr></tbody>}} + <tr><td colspan=4>{trl("Something went wrong")}<br/>{e.to_string()}</td></tr></tbody>}.into_any()} Ok(u) => { match u { ApiResponse::Data(p) => { @@ -58,8 +58,8 @@ pub fn properties() -> impl IntoView { view! { <tr> <td>{data.name.clone()}</td> - {move || if is_wide.get() {view! {<td>{data.description.clone()}</td>}} - else {view! {<td></td>}} } + {move || if is_wide.get() {view! {<td>{data.description.clone()}</td>}.into_any()} + else {view! {<td></td>}.into_any()} } <td>{data.price.to_string()}</td> <td> <div class="dropdown"> @@ -87,11 +87,11 @@ pub fn properties() -> impl IntoView { }} </For> </tbody> - } + }.into_any() }, ApiResponse::Error(s) => { view! {<tbody class="table-border-bottom-0"> - <tr><td colspan=4>{trl(&s)}</td></tr></tbody>} + <tr><td colspan=4>{trl(&s)}</td></tr></tbody>}.into_any() } } } diff --git a/src/pages/property_delete.rs b/src/pages/property_delete.rs index b7d0ac3..1683071 100644 --- a/src/pages/property_delete.rs +++ b/src/pages/property_delete.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::data::ResProperty; use crate::backend::property::DeleteProperty; use crate::components::data_form::QuestionDialog; @@ -7,7 +7,7 @@ use crate::locales::trl; #[component] pub fn property_delete(property: ReadSignal<ResProperty>, opener: DialogOpener) -> impl IntoView { - let del_property = create_server_action::<DeleteProperty>(); + let del_property = ServerAction::<DeleteProperty>::new(); view! { <QuestionDialog opener=opener action=del_property title="Delete property"> diff --git a/src/pages/property_edit.rs b/src/pages/property_edit.rs index 1083619..a6c4b28 100644 --- a/src/pages/property_edit.rs +++ b/src/pages/property_edit.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::data::{ResProperty, SlotType}; use crate::backend::property::{CreateProperty, EditProperty}; use crate::components::data_form::DataForm; @@ -7,7 +7,7 @@ use crate::locales::trl; #[component] fn form_inner(property: ReadSignal<ResProperty>) -> impl IntoView { - let active_str = create_rw_signal("false".to_string()); + let active_str = RwSignal::new("false".to_string()); view! { <input type="hidden" prop:value={move || property.get().id()} name="property[id]"/> <div class="row"> @@ -79,9 +79,9 @@ fn form_inner(property: ReadSignal<ResProperty>) -> impl IntoView { <input type="hidden" prop:value=active_str name="property[active]"/> </div> </div> - } + }.into_any() } else { - view! {<div></div>} + view! {<div></div>}.into_any() } } }} @@ -89,19 +89,19 @@ fn form_inner(property: ReadSignal<ResProperty>) -> impl IntoView { #[component] pub fn property_edit(property: ReadSignal<ResProperty>, edit: bool, opener: DialogOpener) -> impl IntoView { - let action_create = create_server_action::<CreateProperty>(); - let action_edit = create_server_action::<EditProperty>(); + let action_create = ServerAction::<CreateProperty>::new(); + let action_edit = ServerAction::<EditProperty>::new(); view! { {move || if edit { view! {<DataForm opener=opener action=action_edit title="Edit property"> <FormInner property=property/> - </DataForm>}} + </DataForm>}.into_any()} else { view! {<DataForm opener=opener action=action_create title="Create property"> <FormInner property=property/> - </DataForm>}} + </DataForm>}.into_any()} } } } \ No newline at end of file diff --git a/src/pages/public.rs b/src/pages/public.rs index 63abbea..1a66298 100644 --- a/src/pages/public.rs +++ b/src/pages/public.rs @@ -1,7 +1,8 @@ use chrono::{Duration, Local, NaiveDate, NaiveTime, Timelike}; -use leptos::*; +use leptos::prelude::*; use leptos_captcha::{Captcha, pow_dispatch}; -use leptos_router::*; +use leptos::form::{ActionForm, FromFormData}; +use leptos::ev::SubmitEvent; use rust_decimal::Decimal; use crate::backend::appearance::get_appearance; use crate::backend::customer::get_remembered; @@ -36,7 +37,7 @@ fn time_selector( match property.slot { SlotType::Quarter => { let mut ret: Vec<TmCheck> = vec![]; - logging::log!("quarter"); + leptos::logging::log!("quarter"); for n in 0..(h.to() - h.from()).num_minutes() * 4 / 60 { ret.push(TmCheck { from: h.from() + Duration::minutes(n * 15), @@ -47,7 +48,7 @@ fn time_selector( } SlotType::Half => { let mut ret: Vec<TmCheck> = vec![]; - logging::log!("half"); + leptos::logging::log!("half"); for n in 0..(h.to() - h.from()).num_minutes() * 2 / 60 { ret.push(TmCheck { from: h.from() + Duration::minutes(n * 30), @@ -110,22 +111,22 @@ fn time_selector( #[component] pub fn Public() -> impl IntoView { - let day = create_rw_signal(NaiveDate::default()); - let form_data = create_blocking_resource(move || day.get(), move |d| get_public_form_data(d)); - let slots = create_rw_signal::<Vec<String>>(vec![]); - let price = create_rw_signal(Decimal::from(0)); - let cr_reservation = create_server_action::<CreateReservation>(); + let day = RwSignal::new(NaiveDate::default()); + let form_data = Resource::new_blocking(move || day.get(), move |d| get_public_form_data(d)); + let slots = RwSignal::<Vec<String>>::new(vec![]); + let price = RwSignal::new(Decimal::from(0)); + let cr_reservation = ServerAction::<CreateReservation>::new(); let validator = Validator::new(); let invalid_dlg = DialogOpener::new(); let result_dlg = DialogOpener::new(); - let result = cr_reservation.value(); - let is_pending = create_rw_signal(None); - let active_str = create_rw_signal("true".to_string()); - let get_customer = create_blocking_resource(||(), move |_| get_remembered()); - let appearance = create_blocking_resource(||(), move |_| get_appearance()); - let customer = create_rw_signal(Customer::default()); + let result = Signal::derive(move || cr_reservation.value().get()); + let is_pending = RwSignal::new(None); + let active_str = RwSignal::new("true".to_string()); + let get_customer = Resource::new_blocking(||(), move |_| get_remembered()); + let appearance = Resource::new_blocking(||(), move |_| get_appearance()); + let customer = RwSignal::new(Customer::default()); - create_effect(move |_| { + Effect::new(move |_| { day.set(Local::now().date_naive()); }); @@ -139,36 +140,37 @@ pub fn Public() -> impl IntoView { captcha_state=is_pending.read_only()/> <Transition fallback=move || view! {<p>{trl("Loading...")}</p> }> - { + {move || { appearance.get().map(|a| match a { Ok(a) => { - let app = a.clone(); + let has_banner = a.banner.is_some(); + let title = a.title.clone().unwrap_or_default(); view! { <div> - <Show when=move || a.clone().banner.is_some()> + <Show when=move || has_banner> <div class="header_banner"> - <h1 class="header_banner">{app.title.clone().unwrap_or_default()}</h1> + <h1 class="header_banner">{title.clone()}</h1> </div> </Show> <div> - <div class="header_banner_text" inner_html={app.text.unwrap_or("".to_string())}> + <div class="header_banner_text" inner_html={a.text.unwrap_or("".to_string())}> </div> </div> </div> - } + }.into_any() }, Err(e) => {view! {<div><p>{trl("Error loading data")}</p> <p>{e.to_string()}</p></div> - }} + }.into_any()} }) - } + }} </Transition> <div class="card-body"> <ActionForm - on:submit=move |ev| { - cr_reservation.set_pending(true); + // Capture phase, so the form is validated and the captcha solved before it is dispatched + on:submit:capture=move |ev: SubmitEvent| { if let Ok(mut act) = CreateReservation::from_event(&ev) { validator.check(act.entity(), &ev); @@ -219,7 +221,7 @@ pub fn Public() -> impl IntoView { }); form_data.get().map(|u| match u { Err(e) => { - view! {<div>{e.to_string()}</div>}} + view! {<div>{e.to_string()}</div>}.into_any()} Ok(u) => { match u { ApiResponse::Data(p) => { @@ -252,10 +254,10 @@ pub fn Public() -> impl IntoView { value={data}/> </For> </div> - } + }.into_any() }, ApiResponse::Error(s) => { - view! {<div>{trl(&s)}</div>} + view! {<div>{trl(&s)}</div>}.into_any() } }} }) diff --git a/src/pages/res_dialogs.rs b/src/pages/res_dialogs.rs index 0f41eac..28bb9ef 100644 --- a/src/pages/res_dialogs.rs +++ b/src/pages/res_dialogs.rs @@ -1,5 +1,5 @@ use chrono::{Local, NaiveDate}; -use leptos::*; +use leptos::prelude::*; use rust_decimal::Decimal; use crate::backend::data::ApiResponse; use crate::components::modal_box::{DialogOpener, ModalBody, ModalDialog, ModalFooter}; @@ -29,7 +29,8 @@ pub fn res_error(opener: DialogOpener, validator: Validator) -> impl IntoView { #[component] pub fn res_saved( opener: DialogOpener, - save_result: RwSignal<Option<Result<ApiResponse<NaiveDate>, ServerFnError>>>, + #[prop(into)] + save_result: Signal<Option<Result<ApiResponse<NaiveDate>, ServerFnError>>>, day: RwSignal<NaiveDate>, price: WriteSignal<Decimal>, slots: WriteSignal<Vec<String>>, @@ -68,7 +69,7 @@ pub fn res_saved( </ModalFooter> </ModalDialog> </div> - } + }.into_any() }, ApiResponse::Error(err) => { view! { @@ -88,7 +89,7 @@ pub fn res_saved( </ModalFooter> </ModalDialog> </div> - } + }.into_any() } } } @@ -110,11 +111,11 @@ pub fn res_saved( </ModalFooter> </ModalDialog> </div> - } + }.into_any() } } } else { - view! {<div></div>} + view! {<div></div>}.into_any() } }} } diff --git a/src/pages/settings.rs b/src/pages/settings.rs index 40017da..9b374bc 100644 --- a/src/pages/settings.rs +++ b/src/pages/settings.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::locales::trl; use crate::pages::closing_days::ClosingDays; use crate::pages::company_info::CompanyInfo; diff --git a/src/pages/today_reservations.rs b/src/pages/today_reservations.rs index 1cdfca8..eac336d 100644 --- a/src/pages/today_reservations.rs +++ b/src/pages/today_reservations.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::data::{ApiResponse, ResSumWithItems}; use crate::backend::reservation::get_next_reservations; use crate::components::modal_box::DialogOpener; @@ -9,9 +9,9 @@ use crate::pages::new_reservations::CancelDialog; #[component] pub fn next_reservations(app_opener: DialogOpener, cancel_opener: DialogOpener) -> impl IntoView { - let res = create_blocking_resource( move || app_opener.visible() || cancel_opener.visible(), move |_| get_next_reservations()); + let res = Resource::new_blocking( move || app_opener.visible() || cancel_opener.visible(), move |_| get_next_reservations()); let menu = MenuOpener::new(); - let reservation = create_rw_signal(ResSumWithItems::default()); + let reservation = RwSignal::new(ResSumWithItems::default()); view! { <CancelDialog opener=cancel_opener reservation=reservation.read_only()/> @@ -22,7 +22,7 @@ pub fn next_reservations(app_opener: DialogOpener, cancel_opener: DialogOpener) {move || { res.get().map(|r| match r { Err(e) => { - view! {<div>{trl("Something went wrong")}<br/>{e.to_string()}</div>}} + view! {<div>{trl("Something went wrong")}<br/>{e.to_string()}</div>}.into_any()} Ok(r) => { match r { ApiResponse::Data(r) => { view! { @@ -40,7 +40,7 @@ pub fn next_reservations(app_opener: DialogOpener, cancel_opener: DialogOpener) let:item> {item.property.name}": "{item.reservation.from.to_string()}" - "{item.reservation.to.to_string()}<br/> </For> - {trl("Customer: ")}{data.customer.full_name}", "<a href={format!("mailto:{}", data.customer.email)}>{data.customer.email}</a>", "{data.customer.phone}<br/> + {trl("Customer: ")}{data.customer.full_name}", "<a href={format!("mailto:{}", data.customer.email)}>{data.customer.email.clone()}</a>", "{data.customer.phone}<br/> {move || { let note = data.summary.note.clone(); let show = note.is_some() && !note.clone().unwrap().is_empty(); @@ -51,7 +51,7 @@ pub fn next_reservations(app_opener: DialogOpener, cancel_opener: DialogOpener) } }} {trl("Price: ")}{data.summary.price.to_string()}<br/> - <table width="100%"> + <table style="width: 100%"><tbody> <tr> <td width="100%"></td> <td> @@ -72,15 +72,15 @@ pub fn next_reservations(app_opener: DialogOpener, cancel_opener: DialogOpener) </div> </td> </tr> - </table> + </tbody></table> <hr/> } }} </For> </div> - } + }.into_any() } - ApiResponse::Error(e) => {view! {<div>{trl(&e)}</div>}}} + ApiResponse::Error(e) => {view! {<div>{trl(&e)}</div>}.into_any()}} } }) }} diff --git a/src/pages/user_delete.rs b/src/pages/user_delete.rs index 5110d29..cb2c99f 100644 --- a/src/pages/user_delete.rs +++ b/src/pages/user_delete.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::data::User; use crate::backend::user::DeleteUser; use crate::components::data_form::QuestionDialog; @@ -7,7 +7,7 @@ use crate::locales::trl; #[component] pub fn user_delete(user: ReadSignal<User>, opener: DialogOpener) -> impl IntoView { - let del_user = create_server_action::<DeleteUser>(); + let del_user = ServerAction::<DeleteUser>::new(); view! { <QuestionDialog opener=opener action=del_user title="Delete user"> diff --git a/src/pages/user_edit.rs b/src/pages/user_edit.rs index 34d640a..7155ec6 100644 --- a/src/pages/user_edit.rs +++ b/src/pages/user_edit.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::user::CreateUser; use crate::components::data_form::DataForm; use crate::components::modal_box::DialogOpener; @@ -6,7 +6,7 @@ use crate::locales::trl; #[component] pub fn user_edit(opener: DialogOpener) -> impl IntoView { - let create_usr = create_server_action::<CreateUser>(); + let create_usr = ServerAction::<CreateUser>::new(); view! { <DataForm opener=opener action=create_usr title="Create user"> //<input type="hidden" value={move || company.get().id()} name="company[id]"/> diff --git a/src/pages/users.rs b/src/pages/users.rs index 300f7d1..f507f1c 100644 --- a/src/pages/users.rs +++ b/src/pages/users.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use crate::backend::data::{ApiResponse, User}; use crate::backend::user::get_users; use crate::components::modal_box::DialogOpener; @@ -16,10 +16,10 @@ pub fn users() -> impl IntoView { let profile_editor = DialogOpener::new(); let pwd_dialog = DialogOpener::new(); let delete_dialog = DialogOpener::new(); - let users = create_blocking_resource( + let users = Resource::new_blocking( move || editor.visible() || profile_editor.visible() || delete_dialog.visible(), move |_| {get_users()}); - let (usr, set_usr) = create_signal::<Vec<User>>(vec![]); - let (profile, set_profile) = create_signal(User::default()); + let (usr, set_usr) = signal::<Vec<User>>(vec![]); + let (profile, set_profile) = signal(User::default()); let is_wide = use_media_query("(min-width: 500px)"); view! { @@ -35,8 +35,8 @@ pub fn users() -> impl IntoView { <thead> <tr> <th>{trl("Username")}</th> - {move || if is_wide.get() {view! {<th>{trl("Full name")}</th>}} - else {view! {<th></th>}} } + {move || if is_wide.get() {view! {<th>{trl("Full name")}</th>}.into_any()} + else {view! {<th></th>}.into_any()} } <th>{trl("Admin")}</th> <th>{trl("Actions")}</th> </tr> @@ -50,7 +50,7 @@ pub fn users() -> impl IntoView { e.to_string() }; view! {<tbody class="table-border-bottom-0"> - <tr><td colspan=4>{trl(&err)}</td></tr></tbody>}} + <tr><td colspan=4>{trl(&err)}</td></tr></tbody>}.into_any()} Ok(u) => { match u { ApiResponse::Data(u) => { @@ -66,11 +66,11 @@ pub fn users() -> impl IntoView { let full_name = user.full_name.clone().unwrap_or("".to_string()); view! { <tr> - <td>{&user.login}</td> - {move || if is_wide.get() {view! {<td>{full_name.clone()}</td>}} - else {view! {<td></td>}} } - <td>{if user.admin {view! {<i class="bx bx-check"></i>}} - else {view! {<i></i>}}}</td> + <td>{user.login.clone()}</td> + {move || if is_wide.get() {view! {<td>{full_name.clone()}</td>}.into_any()} + else {view! {<td></td>}.into_any()} } + <td>{if user.admin {view! {<i class="bx bx-check"></i>}.into_any()} + else {view! {<i></i>}.into_any()}}</td> <td> <div class="dropdown"> <button type="button" class="btn p-0 dropdown-toggle hide-arrow" @@ -101,10 +101,10 @@ pub fn users() -> impl IntoView { </tr> } }/></tbody> - } + }.into_any() } ApiResponse::Error(e) => {view! {<tbody class="table-border-bottom-0"> - <tr><td colspan=4>{trl(&e)}</td></tr></tbody>}} + <tr><td colspan=4>{trl(&e)}</td></tr></tbody>}.into_any()} } } }) diff --git a/src/validator.rs b/src/validator.rs index 91d1924..1c5346d 100644 --- a/src/validator.rs +++ b/src/validator.rs @@ -1,4 +1,4 @@ -use leptos::*; +use leptos::prelude::*; use validator::Validate; #[derive(Copy, Clone)] @@ -13,9 +13,9 @@ pub struct Validator { impl Validator { pub fn new() -> Self { - let (valid, set_valid) = create_signal(true); - //let (message, set_message) = create_signal(None); - let (messages, set_messages) = create_signal(None); + let (valid, set_valid) = signal(true); + //let (message, set_message) = signal(None); + let (messages, set_messages) = signal(None); Self { //message, //set_message,