From: Greg Burri Date: Wed, 4 Dec 2024 16:39:56 +0000 (+0100) Subject: * Create a minimalistic toast X-Git-Url: https://git.euphorik.ch/?a=commitdiff_plain;h=1c79cc890db3a1833e829164e14ea49831897c29;p=recipes.git * Create a minimalistic toast * Profile editing (WIP) --- diff --git a/Cargo.lock b/Cargo.lock index fc305e6..60bf62f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -40,9 +40,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-tzdata" @@ -142,7 +142,7 @@ checksum = "a41603f7cdbf5ac4af60760f17253eb6adf6ec5b6f14a7ed830cf687d375f163" dependencies = [ "askama", "axum-core", - "http", + "http 1.2.0", ] [[package]] @@ -204,16 +204,16 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ "async-trait", "axum-core", "axum-macros", "bytes", "futures-util", - "http", + "http 1.2.0", "http-body", "http-body-util", "hyper", @@ -229,7 +229,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tokio", "tower", "tower-layer", @@ -246,13 +246,13 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http", + "http 1.2.0", "http-body", "http-body-util", "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tower-layer", "tower-service", "tracing", @@ -260,25 +260,26 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.9.4" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73c3220b188aea709cf1b6c5f9b01c3bd936bb08bd2b5184a12b35ac8131b1f9" +checksum = "c794b30c904f0a1c2fb7740f7df7f7972dfaa14ef6f57cb6178dc63e5dca2f04" dependencies = [ "axum", "axum-core", "bytes", "cookie", + "fastrand", "futures-util", - "http", + "http 1.2.0", "http-body", "http-body-util", "mime", + "multer", "pin-project-lite", "serde", "tower", "tower-layer", "tower-service", - "tracing", ] [[package]] @@ -334,6 +335,15 @@ dependencies = [ "serde", ] +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bitflags" version = "2.6.0" @@ -375,15 +385,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "shlex", ] @@ -420,9 +430,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.21" +version = "4.5.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "69371e34337c4c984bbe322360c2547210bf632eb2814bbe78a6e87a2935bd2b" dependencies = [ "clap_builder", "clap_derive", @@ -430,9 +440,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "6e24c1b4099818523236a8ca881d2b45db98dadfb4625cf6608c12069fcbbde1" dependencies = [ "anstream", "anstyle", @@ -542,9 +552,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -677,9 +687,9 @@ dependencies = [ [[package]] name = "email-encoding" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60d1d33cdaede7e24091f039632eb5d3c7469fe5b066a985281a34fc70fa317f" +checksum = "ea3d894bbbab314476b265f9b2d46bf24b123a36dd0e96b06a1b49545b9d9dcc" dependencies = [ "base64 0.22.1", "memchr", @@ -691,6 +701,15 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "entities" version = "1.0.1" @@ -705,12 +724,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -773,10 +792,26 @@ version = "0.1.0" dependencies = [ "common", "console_error_panic_hook", + "gloo", "wasm-bindgen", + "wasm-bindgen-futures", "web-sys", ] +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -821,6 +856,17 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.31" @@ -839,8 +885,10 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ + "futures-channel", "futures-core", "futures-io", + "futures-macro", "futures-sink", "futures-task", "memchr", @@ -866,8 +914,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -876,6 +926,187 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "gloo" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15282ece24eaf4bd338d73ef580c6714c8615155c4190c781290ee3fa0fd372" +dependencies = [ + "gloo-console", + "gloo-dialogs", + "gloo-events", + "gloo-file", + "gloo-history", + "gloo-net", + "gloo-render", + "gloo-storage", + "gloo-timers", + "gloo-utils", + "gloo-worker", +] + +[[package]] +name = "gloo-console" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a17868f56b4a24f677b17c8cb69958385102fa879418052d60b50bc1727e261" +dependencies = [ + "gloo-utils", + "js-sys", + "serde", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-dialogs" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4748e10122b01435750ff530095b1217cf6546173459448b83913ebe7815df" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-events" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c26fb45f7c385ba980f5fa87ac677e363949e065a083722697ef1b2cc91e41" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-file" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97563d71863fb2824b2e974e754a81d19c4a7ec47b09ced8a0e6656b6d54bd1f" +dependencies = [ + "gloo-events", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-history" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "903f432be5ba34427eac5e16048ef65604a82061fe93789f2212afc73d8617d6" +dependencies = [ + "getrandom", + "gloo-events", + "gloo-utils", + "serde", + "serde-wasm-bindgen", + "serde_urlencoded", + "thiserror 1.0.69", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-net" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43aaa242d1239a8822c15c645f02166398da4f8b5c4bae795c1f5b44e9eee173" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "http 0.2.12", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror 1.0.69", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-render" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56008b6744713a8e8d98ac3dcb7d06543d5662358c9c805b4ce2167ad4649833" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-storage" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc8031e8c92758af912f9bc08fbbadd3c6f3cfcbf6b64cdf3d6a81f0139277a" +dependencies = [ + "gloo-utils", + "js-sys", + "serde", + "serde_json", + "thiserror 1.0.69", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-worker" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "085f262d7604911c8150162529cefab3782e91adb20202e8658f7275d2aefe5d" +dependencies = [ + "bincode", + "futures", + "gloo-utils", + "gloo-worker-macros", + "js-sys", + "pinned", + "serde", + "thiserror 1.0.69", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-worker-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956caa58d4857bc9941749d55e4bd3000032d8212762586fa5705632967140e7" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "hashbrown" version = "0.14.5" @@ -888,9 +1119,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "hashlink" @@ -907,12 +1138,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hex" version = "0.4.3" @@ -959,9 +1184,20 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -975,7 +1211,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.2.0", ] [[package]] @@ -986,16 +1222,16 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http", + "http 1.2.0", "http-body", "pin-project-lite", ] [[package]] name = "http-range-header" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" +checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" [[package]] name = "httparse" @@ -1020,14 +1256,14 @@ dependencies = [ [[package]] name = "hyper" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" dependencies = [ "bytes", "futures-channel", "futures-util", - "http", + "http 1.2.0", "http-body", "httparse", "httpdate", @@ -1045,7 +1281,7 @@ checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-util", - "http", + "http 1.2.0", "http-body", "hyper", "pin-project-lite", @@ -1217,12 +1453,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -1242,16 +1478,17 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1297,9 +1534,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.162" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libm" @@ -1326,9 +1563,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litemap" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lock_api" @@ -1410,16 +1647,32 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi", "libc", "wasi", "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", +] + [[package]] name = "nom" version = "7.1.3" @@ -1575,6 +1828,26 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pin-project" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.15" @@ -1587,6 +1860,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pinned" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a829027bd95e54cfe13e3e258a1ae7b645960553fb82b75ff852c29688ee595b" +dependencies = [ + "futures", + "rustversion", + "thiserror 1.0.69", +] + [[package]] name = "pkcs1" version = "0.7.5" @@ -1629,11 +1913,21 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -1712,7 +2006,7 @@ dependencies = [ "ron", "serde", "sqlx", - "thiserror 2.0.3", + "thiserror 2.0.4", "tokio", "tower", "tower-http", @@ -1802,9 +2096,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" dependencies = [ "const-oid", "digest", @@ -1828,9 +2122,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.40" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags", "errno", @@ -1841,9 +2135,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.16" +version = "0.23.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" +checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1" dependencies = [ "log", "once_cell", @@ -1907,6 +2201,17 @@ 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.215" @@ -1920,9 +2225,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -2038,9 +2343,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2317,9 +2622,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.87" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -2334,9 +2639,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" [[package]] name = "synstructure" @@ -2373,11 +2678,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "2f49a1853cf82743e3b7950f77e0f4d622ca36cf4317cba00c767838bac8d490" dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl 2.0.4", ] [[package]] @@ -2393,9 +2698,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "8381894bb3efe0c4acac3ded651301ceee58a15d47c2e34885ed1908ad667061" dependencies = [ "proc-macro2", "quote", @@ -2414,9 +2719,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -2435,9 +2740,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -2470,9 +2775,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -2521,9 +2826,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -2532,6 +2837,23 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.5.1" @@ -2550,14 +2872,14 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97" +checksum = "403fa3b783d4b626a8ad51d766ab03cb6d2dbfc46b1c5d4448395e6628dc9697" dependencies = [ "bitflags", "bytes", "futures-util", - "http", + "http 1.2.0", "http-body", "http-body-util", "http-range-header", @@ -2587,9 +2909,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -2599,9 +2921,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", @@ -2610,9 +2932,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -2631,9 +2953,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", @@ -2673,9 +2995,9 @@ checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-normalization" @@ -2718,9 +3040,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -2777,9 +3099,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" dependencies = [ "cfg-if", "once_cell", @@ -2788,9 +3110,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" dependencies = [ "bumpalo", "log", @@ -2801,11 +3123,24 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dfaf8f50e5f293737ee323940c7d8b08a66a95a419223d9f41610ca08b0833d" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2813,9 +3148,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" dependencies = [ "proc-macro2", "quote", @@ -2826,15 +3161,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "a98bc3c33f0fe7e59ad7cd041b89034fa82a7c2d4365ca538dda6cdaf513863c" dependencies = [ "js-sys", "wasm-bindgen", @@ -2842,9 +3177,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.6" +version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" dependencies = [ "rustls-pki-types", ] @@ -3048,6 +3383,15 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + [[package]] name = "write16" version = "1.0.0" @@ -3062,9 +3406,9 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", @@ -3074,9 +3418,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", @@ -3107,18 +3451,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", diff --git a/backend/build.rs b/backend/build.rs index 45ca9a5..5628d92 100644 --- a/backend/build.rs +++ b/backend/build.rs @@ -28,7 +28,7 @@ fn main() { fn run_sass(command: &mut Command) -> Output { command - .arg("style.scss") + .arg("scss/style.scss") .arg("static/style.css") .output() .expect("Unable to compile SASS file, install SASS, see https://sass-lang.com/") diff --git a/backend/scss/style.scss b/backend/scss/style.scss new file mode 100644 index 0000000..da019cf --- /dev/null +++ b/backend/scss/style.scss @@ -0,0 +1,159 @@ +@use 'toast.scss'; + +@font-face { + font-family: Fira Code; + font-weight: 200; + src: url(FiraCode-Light.woff2) format("woff2"); +} + +@font-face { + font-family: Fira Code; + font-weight: 400; + src: url(FiraCode-Regular.woff2) format("woff2"); +} + +@font-face { + font-family: Fira Code; + font-weight: 600; + src: url(FiraCode-SemiBold.woff2) format("woff2"); +} + +@font-face { + font-family: Fira Code; + font-weight: 700; + src: url(FiraCode-Bold.woff2) format("woff2"); +} + +$primary: #182430; +$background: darken($primary, 5%); +$background-container: lighten($primary, 10%); + +* { + margin: 5px; + padding: 0px; +} + +html { + font-size: 80% +} + +a { + color: lighten($primary, 40%); + text-decoration: none; + + &:hover { + color: lighten($primary, 60%); + } +} + +body { + display: flex; + flex-direction: column; + + font-family: Fira Code, Helvetica Neue, Helvetica, Arial, sans-serif; + text-shadow: 2px 2px 2px rgb(0, 0, 0); + // line-height: 18px; + color: rgb(255, 255, 255); + background-color: $background; + margin: 0px; + + .recipe-item { + padding: 4px; + } + + .recipe-item-current { + padding: 3px; + border: 1px solid white; + } + + .header-container { + align-self: center; + } + + .footer-container { + align-self: center; + font-size: 0.5em; + } + + .main-container { + display: flex; + flex-direction: row; + + // .recipes-list { + // text-align: left; + // } + + .content { + flex-grow: 1; + + background-color: $background-container; + border: 0.1em solid white; + padding: 0.5em; + + h1 { + text-align: center; + } + } + + form { + display: grid; + grid-template-columns: auto 1fr; + gap: 3px; + + input, + button { + background-color: rgb(52, 40, 85); + border-width: 1px; + border-color: white; + color: white; + } + } + + // #user-edit { + // .label-name { + // grid-column: 1; + // grid-row: 1; + // } + + // .input-name { + // grid-column: 2; + // grid-row: 1; + // } + + // .label-password-1 { + // grid-column: 1; + // grid-row: 2; + // } + + // .input-password-1 { + // grid-column: 2; + // grid-row: 2; + // } + + // .label-password-2 { + // grid-column: 1; + // grid-row: 3; + // } + + // .input-password-2 { + // grid-column: 2; + // grid-row: 3; + // } + + // .button-save { + // grid-column: 2; + // grid-row: 4; + // width: fit-content; + // justify-self: flex-end; + // } + // } + + // #sign-in { + + // } + } + + img { + border: 0px; + } +} \ No newline at end of file diff --git a/backend/scss/toast.scss b/backend/scss/toast.scss new file mode 100644 index 0000000..e6b4582 --- /dev/null +++ b/backend/scss/toast.scss @@ -0,0 +1,44 @@ +#toast { + visibility: hidden; + max-width: 300px; + margin-left: -125px; + background-color: black; + text-align: center; + border-radius: 2px; + padding: 16px; // TODO: 'rem' better? + position: fixed; + z-index: 1; + left: 50%; + bottom: 30px; + box-shadow: -1px 1px 10px rgba(0, 0, 0, 0.3); +} + +#toast.show { + visibility: visible; + animation: fadein 0.5s, fadeout 0.5s 3.6s; + animation-iteration-count: 1; +} + +@keyframes fadein { + from { + bottom: 0; + opacity: 0; + } + + to { + bottom: 30px; + opacity: 1; + } +} + +@keyframes fadeout { + from { + bottom: 30px; + opacity: 1; + } + + to { + bottom: 0; + opacity: 0; + } +} \ No newline at end of file diff --git a/backend/src/html_templates.rs b/backend/src/html_templates.rs new file mode 100644 index 0000000..bb9aa7f --- /dev/null +++ b/backend/src/html_templates.rs @@ -0,0 +1,70 @@ +use askama::Template; + +use crate::model; + +#[derive(Template)] +#[template(path = "home.html")] +pub struct HomeTemplate { + pub user: Option, + pub recipes: Vec<(i64, String)>, + pub current_recipe_id: Option, +} + +#[derive(Template)] +#[template(path = "view_recipe.html")] +pub struct ViewRecipeTemplate { + pub user: Option, + pub recipes: Vec<(i64, String)>, + pub current_recipe_id: Option, + pub current_recipe: model::Recipe, +} + +#[derive(Template)] +#[template(path = "message.html")] +pub struct MessageTemplate<'a> { + pub user: Option, + pub message: &'a str, + pub as_code: bool, // Display the message in
 markup.
+}
+
+#[derive(Template)]
+#[template(path = "sign_up_form.html")]
+pub struct SignUpFormTemplate {
+    pub user: Option,
+    pub email: String,
+    pub message: String,
+    pub message_email: String,
+    pub message_password: String,
+}
+
+#[derive(Template)]
+#[template(path = "sign_in_form.html")]
+pub struct SignInFormTemplate {
+    pub user: Option,
+    pub email: String,
+    pub message: String,
+}
+
+#[derive(Template)]
+#[template(path = "ask_reset_password.html")]
+pub struct AskResetPasswordTemplate {
+    pub user: Option,
+    pub email: String,
+    pub message: String,
+    pub message_email: String,
+}
+
+#[derive(Template)]
+#[template(path = "reset_password.html")]
+pub struct ResetPasswordTemplate {
+    pub user: Option,
+    pub reset_token: String,
+    pub message: String,
+    pub message_password: String,
+}
+
+#[derive(Template)]
+#[template(path = "profile.html")]
+pub struct ProfileTemplate {
+    pub user: Option,
+}
diff --git a/backend/src/main.rs b/backend/src/main.rs
index 74cc54c..9d4f02d 100644
--- a/backend/src/main.rs
+++ b/backend/src/main.rs
@@ -2,9 +2,10 @@ use std::{net::SocketAddr, path::Path};
 
 use axum::{
     extract::{ConnectInfo, FromRef, Request, State},
+    http::StatusCode,
     middleware::{self, Next},
     response::{Response, Result},
-    routing::{get, post, put},
+    routing::{get, put},
     Router,
 };
 use axum_extra::extract::cookie::CookieJar;
@@ -21,8 +22,10 @@ mod consts;
 mod data;
 mod email;
 mod hash;
+mod html_templates;
 mod model;
 mod ron_extractor;
+mod ron_utils;
 mod services;
 mod utils;
 
@@ -44,6 +47,12 @@ impl FromRef for db::Connection {
     }
 }
 
+impl axum::response::IntoResponse for db::DBError {
+    fn into_response(self) -> Response {
+        ron_utils::ron_error(StatusCode::INTERNAL_SERVER_ERROR, &self.to_string()).into_response()
+    }
+}
+
 #[cfg(debug_assertions)]
 const TRACING_LEVEL: tracing::Level = tracing::Level::DEBUG;
 
@@ -75,7 +84,12 @@ async fn main() {
         db_connection,
     };
 
-    let app = Router::new()
+    // TODO: Add fallback fo ron_api_routes.
+    let ron_api_routes = Router::new()
+        .route("/user/update", put(services::ron::update_user))
+        .fallback(services::ron::not_found);
+
+    let html_routes = Router::new()
         .route("/", get(services::home_page))
         .route(
             "/signup",
@@ -99,15 +113,19 @@ async fn main() {
         .route("/recipe/view/:id", get(services::view_recipe))
         // User.
         .route("/user/edit", get(services::edit_user))
-        // RON API.
-        .route("/user/set_name", put(services::ron::update_user))
+        .route_layer(middleware::from_fn(services::ron_error_to_html));
+
+    let app = Router::new()
+        .merge(html_routes)
+        .nest("/ron-api", ron_api_routes)
+        .fallback(services::not_found)
         .layer(TraceLayer::new_for_http())
-        .route_layer(middleware::from_fn_with_state(
+        // FIXME: Should be 'route_layer' but it doesn't work for 'fallback(..)'.
+        .layer(middleware::from_fn_with_state(
             state.clone(),
             user_authentication,
         ))
         .nest_service("/static", ServeDir::new("static"))
-        .fallback(services::not_found)
         .with_state(state)
         .into_make_service_with_connect_info::();
 
diff --git a/backend/src/ron_extractor.rs b/backend/src/ron_extractor.rs
index 8f52ec6..8062c89 100644
--- a/backend/src/ron_extractor.rs
+++ b/backend/src/ron_extractor.rs
@@ -5,63 +5,9 @@ use axum::{
     http::{header, StatusCode},
     response::{IntoResponse, Response},
 };
-use ron::{
-    de::from_bytes,
-    ser::{to_string_pretty, PrettyConfig},
-};
-use serde::{de::DeserializeOwned, Serialize};
-
-const RON_CONTENT_TYPE: &'static str = "application/ron";
-
-#[derive(Debug, Serialize, Clone)]
-pub struct RonError {
-    pub error: String,
-}
-
-impl axum::response::IntoResponse for RonError {
-    fn into_response(self) -> Response {
-        let ron_as_str = to_string_pretty(&self, PrettyConfig::new()).unwrap();
-        ron_as_str.into_response()
-    }
-}
-
-impl From for Response {
-    fn from(value: RonError) -> Self {
-        value.into_response()
-    }
-}
-
-pub fn ron_error(status: StatusCode, message: &str) -> impl IntoResponse {
-    (
-        status,
-        [(header::CONTENT_TYPE, RON_CONTENT_TYPE)],
-        RonError {
-            error: message.to_string(),
-        },
-    )
-}
-
-pub fn ron_response(ron: T) -> impl IntoResponse
-where
-    T: Serialize,
-{
-    let ron_as_str = to_string_pretty(&ron, PrettyConfig::new()).unwrap();
-    ([(header::CONTENT_TYPE, RON_CONTENT_TYPE)], ron_as_str)
-}
+use serde::de::DeserializeOwned;
 
-fn parse_body(body: Bytes) -> Result
-where
-    T: DeserializeOwned,
-{
-    match from_bytes::(&body) {
-        Ok(ron) => Ok(ron),
-        Err(error) => {
-            return Err(RonError {
-                error: format!("Ron parsing error: {}", error),
-            });
-        }
-    }
-}
+use crate::ron_utils;
 
 pub struct ExtractRon(pub T);
 
@@ -71,22 +17,26 @@ where
     S: Send + Sync,
     T: DeserializeOwned,
 {
-    type Rejection = Response; // axum::Error::ErrorResponse;
+    type Rejection = Response;
 
     async fn from_request(req: Request, state: &S) -> Result {
         match req.headers().get(header::CONTENT_TYPE) {
             Some(content_type) => {
-                if content_type != RON_CONTENT_TYPE {
-                    return Err(ron_error(
+                if content_type != ron_utils::RON_CONTENT_TYPE {
+                    return Err(ron_utils::ron_error(
                         StatusCode::BAD_REQUEST,
-                        &format!("Invalid content type, must be {}", RON_CONTENT_TYPE),
+                        &format!(
+                            "Invalid content type, must be {:?}",
+                            ron_utils::RON_CONTENT_TYPE
+                        ),
                     )
                     .into_response());
                 }
             }
             None => {
                 return Err(
-                    ron_error(StatusCode::BAD_REQUEST, "No content type given").into_response()
+                    ron_utils::ron_error(StatusCode::BAD_REQUEST, "No content type given")
+                        .into_response(),
                 )
             }
         }
@@ -95,7 +45,7 @@ where
             .await
             .map_err(IntoResponse::into_response)?;
 
-        let ron = parse_body(body)?;
+        let ron = ron_utils::parse_body(body)?;
 
         Ok(Self(ron))
     }
diff --git a/backend/src/ron_utils.rs b/backend/src/ron_utils.rs
new file mode 100644
index 0000000..36789ed
--- /dev/null
+++ b/backend/src/ron_utils.rs
@@ -0,0 +1,71 @@
+use axum::{
+    async_trait,
+    body::Bytes,
+    extract::{FromRequest, Request},
+    http::{header, HeaderValue, StatusCode},
+    response::{IntoResponse, Response},
+};
+use common::ron_api;
+use ron::de::from_bytes;
+use serde::{de::DeserializeOwned, Serialize};
+
+pub const RON_CONTENT_TYPE: HeaderValue = HeaderValue::from_static("application/ron");
+
+#[derive(Debug, Serialize, Clone)]
+pub struct RonError {
+    pub error: String,
+}
+
+impl axum::response::IntoResponse for RonError {
+    fn into_response(self) -> Response {
+        let ron_as_str = ron_api::to_string(&self);
+        (
+            StatusCode::BAD_REQUEST,
+            [(header::CONTENT_TYPE, RON_CONTENT_TYPE)],
+            ron_as_str,
+        )
+            .into_response()
+    }
+}
+
+impl From for Response {
+    fn from(value: RonError) -> Self {
+        value.into_response()
+    }
+}
+
+pub fn ron_error(status: StatusCode, message: &str) -> impl IntoResponse {
+    (
+        status,
+        [(header::CONTENT_TYPE, RON_CONTENT_TYPE)],
+        RonError {
+            error: message.to_string(),
+        },
+    )
+}
+
+pub fn ron_response(status: StatusCode, ron: T) -> impl IntoResponse
+where
+    T: Serialize,
+{
+    let ron_as_str = ron_api::to_string(&ron);
+    (
+        status,
+        [(header::CONTENT_TYPE, RON_CONTENT_TYPE)],
+        ron_as_str,
+    )
+}
+
+pub fn parse_body(body: Bytes) -> Result
+where
+    T: DeserializeOwned,
+{
+    match from_bytes::(&body) {
+        Ok(ron) => Ok(ron),
+        Err(error) => {
+            return Err(RonError {
+                error: format!("Ron parsing error: {}", error),
+            });
+        }
+    }
+}
diff --git a/backend/src/services.rs b/backend/src/services.rs
index 7f9e75a..c8bcb4a 100644
--- a/backend/src/services.rs
+++ b/backend/src/services.rs
@@ -1,11 +1,11 @@
 use std::{collections::HashMap, net::SocketAddr};
 
-use askama::Template;
 use axum::{
-    body::Body,
+    body::{self, Body},
     debug_handler,
     extract::{ConnectInfo, Extension, Host, Path, Query, Request, State},
-    http::{HeaderMap, StatusCode},
+    http::{header, HeaderMap},
+    middleware::Next,
     response::{IntoResponse, Redirect, Response, Result},
     Form,
 };
@@ -14,30 +14,36 @@ use chrono::Duration;
 use serde::Deserialize;
 use tracing::{event, Level};
 
-use crate::{config::Config, consts, data::db, email, model, utils, AppState};
+use crate::{
+    config::Config, consts, data::db, email, html_templates::*, model, ron_utils, utils, AppState,
+};
 
 pub mod ron;
 
-impl axum::response::IntoResponse for db::DBError {
-    fn into_response(self) -> Response {
-        let body = MessageTemplate {
-            user: None,
-            message: &self.to_string(),
-        };
-        (StatusCode::INTERNAL_SERVER_ERROR, body).into_response()
+// Will embed RON error in HTML page.
+pub async fn ron_error_to_html(req: Request, next: Next) -> Result {
+    let response = next.run(req).await;
+
+    if let Some(content_type) = response.headers().get(header::CONTENT_TYPE) {
+        if content_type == ron_utils::RON_CONTENT_TYPE {
+            let message = match body::to_bytes(response.into_body(), usize::MAX).await {
+                Ok(bytes) => String::from_utf8(bytes.to_vec()).unwrap_or_default(),
+                Err(error) => error.to_string(),
+            };
+            return Ok(MessageTemplate {
+                user: None,
+                message: &message,
+                as_code: true,
+            }
+            .into_response());
+        }
     }
+
+    Ok(response)
 }
 
 ///// HOME /////
 
-#[derive(Template)]
-#[template(path = "home.html")]
-struct HomeTemplate {
-    user: Option,
-    recipes: Vec<(i64, String)>,
-    current_recipe_id: Option,
-}
-
 #[debug_handler]
 pub async fn home_page(
     State(connection): State,
@@ -54,15 +60,6 @@ pub async fn home_page(
 
 ///// VIEW RECIPE /////
 
-#[derive(Template)]
-#[template(path = "view_recipe.html")]
-struct ViewRecipeTemplate {
-    user: Option,
-    recipes: Vec<(i64, String)>,
-    current_recipe_id: Option,
-    current_recipe: model::Recipe,
-}
-
 #[debug_handler]
 pub async fn view_recipe(
     State(connection): State,
@@ -78,121 +75,36 @@ pub async fn view_recipe(
             current_recipe: recipe,
         }
         .into_response()),
-        None => Ok(MessageTemplate {
+        None => Ok(MessageTemplate::new_with_user(
+            &format!("Cannot find the recipe {}", recipe_id),
             user,
-            message: &format!("Cannot find the recipe {}", recipe_id),
-        }
+        )
         .into_response()),
     }
 }
 
-///// EDIT/NEW RECIPE /////
-
-// #[derive(Template)]
-// #[template(path = "edit_recipe.html")]
-// struct EditRecipeTemplate {
-//     user: Option,
-//     recipes: Vec<(i64, String)>,
-//     current_recipe_id: Option,
-
-//     current_recipe: model::Recipe,
-// }
-
-// #[get("/recipe/edit/{id}")]
-// pub async fn edit_recipe(
-//     req: HttpRequest,
-//     path: web::Path<(i64,)>,
-//     connection: web::Data,
-// ) -> Result {
-//     let (id,) = path.into_inner();
-//     let user = match get_current_user(&req, connection.clone()).await {
-//         Some(u) => u,
-//         None => {
-//             return Ok(MessageTemplate {
-//                 user: None,
-//                 message: "Cannot edit a recipe without being logged in",
-//             }
-//             .to_response())
-//         }
-//     };
-
-//     let recipe = connection.get_recipe_async(id).await?;
-
-//     if recipe.user_id != user.id {
-//         return Ok(MessageTemplate {
-//             message: "Cannot edit a recipe you don't own",
-//             user: Some(user),
-//         }
-//         .to_response());
-//     }
-
-//     let recipes = connection.get_all_recipe_titles_async().await?;
-
-//     Ok(EditRecipeTemplate {
-//         user: Some(user),
-//         current_recipe_id: Some(recipe.id),
-//         recipes,
-//         current_recipe: recipe,
-//     }
-//     .to_response())
-// }
-
-// #[get("/recipe/new")]
-// pub async fn new_recipe(
-//     req: HttpRequest,
-//     connection: web::Data,
-// ) -> Result {
-//     let user = match get_current_user(&req, connection.clone()).await {
-//         Some(u) => u,
-//         None => {
-//             return Ok(MessageTemplate {
-//                 message: "Cannot create a recipe without being logged in",
-//                 user: None,
-//             }
-//             .to_response())
-//         }
-//     };
-
-//     let recipe_id = connection.create_recipe_async(user.id).await?;
-//     let recipes = connection.get_all_recipe_titles_async().await?;
-//     let user_id = user.id;
-
-//     Ok(EditRecipeTemplate {
-//         user: Some(user),
-//         current_recipe_id: Some(recipe_id),
-//         recipes,
-//         current_recipe: model::Recipe::empty(recipe_id, user_id),
-//     }
-//     .to_response())
-// }
-
 ///// MESSAGE /////
 
-#[derive(Template)]
-#[template(path = "message_without_user.html")]
-struct MessageWithoutUser<'a> {
-    message: &'a str,
-}
+impl<'a> MessageTemplate<'a> {
+    pub fn new(message: &'a str) -> MessageTemplate<'a> {
+        MessageTemplate {
+            user: None,
+            message,
+            as_code: false,
+        }
+    }
 
-#[derive(Template)]
-#[template(path = "message.html")]
-struct MessageTemplate<'a> {
-    user: Option,
-    message: &'a str,
+    pub fn new_with_user(message: &'a str, user: Option) -> MessageTemplate<'a> {
+        MessageTemplate {
+            user,
+            message,
+            as_code: false,
+        }
+    }
 }
 
 //// SIGN UP /////
 
-#[derive(Template)]
-#[template(path = "sign_up_form.html")]
-struct SignUpFormTemplate {
-    user: Option,
-    email: String,
-    message: String,
-    message_email: String,
-    message_password: String,
-}
-
 #[debug_handler]
 pub async fn sign_up_get(
     Extension(user): Extension>,
@@ -300,11 +212,10 @@ pub async fn sign_up_post(
             )
             .await
             {
-                Ok(()) => Ok(MessageTemplate {
-                    user,
-                    message: "An email has been sent, follow the link to validate your account.",
-                }
-                .into_response()),
+                Ok(()) => Ok(
+                    MessageTemplate::new_with_user(
+                        "An email has been sent, follow the link to validate your account.",
+                    user).into_response()),
                 Err(_) => {
                     // error!("Email validation error: {}", error); // TODO: log
                     error_response(SignUpError::UnableSendEmail, &form_data, user)
@@ -330,10 +241,7 @@ pub async fn sign_up_validation(
     if user.is_some() {
         return Ok((
             jar,
-            MessageTemplate {
-                user,
-                message: "User already exists",
-            },
+            MessageTemplate::new_with_user("User already exists", user),
         ));
     }
     let (client_ip, client_user_agent) = utils::get_ip_and_user_agent(&headers, addr);
@@ -355,48 +263,34 @@ pub async fn sign_up_validation(
                     let user = connection.load_user(user_id).await?;
                     Ok((
                         jar,
-                        MessageTemplate {
+                        MessageTemplate::new_with_user(
+                            "Email validation successful, your account has been created",
                             user,
-                            message: "Email validation successful, your account has been created",
-                        },
+                        ),
                     ))
                 }
                 db::ValidationResult::ValidationExpired => Ok((
                     jar,
-                    MessageTemplate {
+                    MessageTemplate::new_with_user(
+                        "The validation has expired. Try to sign up again",
                         user,
-                        message: "The validation has expired. Try to sign up again",
-                    },
+                    ),
                 )),
                 db::ValidationResult::UnknownUser => Ok((
                     jar,
-                    MessageTemplate {
-                        user,
-                        message: "Validation error. Try to sign up again",
-                    },
+                    MessageTemplate::new_with_user("Validation error. Try to sign up again", user),
                 )),
             }
         }
         None => Ok((
             jar,
-            MessageTemplate {
-                user,
-                message: "Validation error",
-            },
+            MessageTemplate::new_with_user("Validation error", user),
         )),
     }
 }
 
 ///// SIGN IN /////
 
-#[derive(Template)]
-#[template(path = "sign_in_form.html")]
-struct SignInFormTemplate {
-    user: Option,
-    email: String,
-    message: String,
-}
-
 #[debug_handler]
 pub async fn sign_in_get(
     Extension(user): Extension>,
@@ -477,24 +371,15 @@ pub async fn sign_out(
 
 ///// RESET PASSWORD /////
 
-#[derive(Template)]
-#[template(path = "ask_reset_password.html")]
-struct AskResetPasswordTemplate {
-    user: Option,
-    email: String,
-    message: String,
-    message_email: String,
-}
-
 #[debug_handler]
 pub async fn ask_reset_password_get(
     Extension(user): Extension>,
 ) -> Result {
     if user.is_some() {
-        Ok(MessageTemplate {
+        Ok(MessageTemplate::new_with_user(
+            "Can't ask to reset password when already logged in",
             user,
-            message: "Can't ask to reset password when already logged in",
-        }
+        )
         .into_response())
     } else {
         Ok(AskResetPasswordTemplate {
@@ -591,10 +476,10 @@ pub async fn ask_reset_password_post(
             )
             .await
             {
-                Ok(()) => Ok(MessageTemplate {
+                Ok(()) => Ok(MessageTemplate::new_with_user(
+                    "An email has been sent, follow the link to reset your password.",
                     user,
-                    message: "An email has been sent, follow the link to reset your password.",
-                }
+                )
                 .into_response()),
                 Err(_) => {
                     // error!("Email validation error: {}", error); // TODO: log
@@ -613,15 +498,6 @@ pub async fn ask_reset_password_post(
     }
 }
 
-#[derive(Template)]
-#[template(path = "reset_password.html")]
-struct ResetPasswordTemplate {
-    user: Option,
-    reset_token: String,
-    message: String,
-    message_password: String,
-}
-
 #[debug_handler]
 pub async fn reset_password_get(
     Extension(user): Extension>,
@@ -636,11 +512,7 @@ pub async fn reset_password_get(
         }
         .into_response())
     } else {
-        Ok(MessageTemplate {
-            user,
-            message: "Reset token missing",
-        }
-        .into_response())
+        Ok(MessageTemplate::new_with_user("Reset token missing", user).into_response())
     }
 }
 
@@ -708,10 +580,10 @@ pub async fn reset_password_post(
         )
         .await
     {
-        Ok(db::ResetPasswordResult::Ok) => Ok(MessageTemplate {
+        Ok(db::ResetPasswordResult::Ok) => Ok(MessageTemplate::new_with_user(
+            "Your password has been reset",
             user,
-            message: "Your password has been reset",
-        }
+        )
         .into_response()),
         Ok(db::ResetPasswordResult::ResetTokenExpired) => {
             error_response(ResetPasswordError::TokenExpired, &form_data, user)
@@ -722,12 +594,6 @@ pub async fn reset_password_post(
 
 ///// EDIT PROFILE /////
 
-#[derive(Template)]
-#[template(path = "profile.html")]
-struct ProfileTemplate {
-    user: Option,
-}
-
 #[debug_handler]
 pub async fn edit_user(
     State(connection): State,
@@ -736,18 +602,12 @@ pub async fn edit_user(
     if user.is_some() {
         ProfileTemplate { user }.into_response()
     } else {
-        MessageTemplate {
-            user: None,
-            message: "Not logged in",
-        }
-        .into_response()
+        MessageTemplate::new("Not logged in").into_response()
     }
 }
 
 ///// 404 /////
 #[debug_handler]
-pub async fn not_found() -> Result {
-    Ok(MessageWithoutUser {
-        message: "404: Not found",
-    })
+pub async fn not_found(Extension(user): Extension>) -> impl IntoResponse {
+    MessageTemplate::new_with_user("404: Not found", user)
 }
diff --git a/backend/src/services/ron.rs b/backend/src/services/ron.rs
index 7592cb1..4b3e749 100644
--- a/backend/src/services/ron.rs
+++ b/backend/src/services/ron.rs
@@ -46,21 +46,15 @@
 // #[put("/ron-api/recipe/rm-step")]
 // #[put("/ron-api/recipe/set-steps-order")]
 
-use askama_axum::IntoResponse;
 use axum::{
     debug_handler,
     extract::{Extension, State},
     http::StatusCode,
-    response::ErrorResponse,
-    response::Result,
+    response::{ErrorResponse, IntoResponse, Result},
 };
 use tracing::{event, Level};
 
-use crate::{
-    data::db,
-    model,
-    ron_extractor::{ron_error, ron_response, ExtractRon},
-};
+use crate::{data::db, model, ron_extractor::ExtractRon, ron_utils::ron_error};
 
 #[debug_handler]
 pub async fn update_user(
@@ -69,7 +63,14 @@ pub async fn update_user(
     ExtractRon(ron): ExtractRon,
 ) -> Result {
     if let Some(user) = user {
-        // connection.set_user_name(user.id, &ron.name).await?;
+        connection
+            .update_user(
+                user.id,
+                ron.email.as_deref(),
+                ron.name.as_deref(),
+                ron.password.as_deref(),
+            )
+            .await?;
     } else {
         return Err(ErrorResponse::from(ron_error(
             StatusCode::UNAUTHORIZED,
@@ -79,17 +80,8 @@ pub async fn update_user(
     Ok(StatusCode::OK)
 }
 
-/* Example with RON return value.
+///// 404 /////
 #[debug_handler]
-pub async fn set_user_name(
-    State(connection): State,
-    Extension(user): Extension>,
-    ExtractRon(ron): ExtractRon,
-) -> Result {
-
-
-    Ok(ron_response(common::ron_api::SetProfileName {
-        name: "abc".to_string(),
-    }))
+pub async fn not_found(Extension(user): Extension>) -> impl IntoResponse {
+    ron_error(StatusCode::NOT_FOUND, "Not found")
 }
-*/
diff --git a/backend/style.scss b/backend/style.scss
deleted file mode 100644
index 4f7cc70..0000000
--- a/backend/style.scss
+++ /dev/null
@@ -1,71 +0,0 @@
-@font-face{font-family: Fira Code; font-weight:200; src:url(FiraCode-Light.woff2) format("woff2"); }
-@font-face{font-family: Fira Code; font-weight:400; src:url(FiraCode-Regular.woff2) format("woff2"); }
-@font-face{font-family: Fira Code; font-weight:600; src:url(FiraCode-SemiBold.woff2) format("woff2"); }
-@font-face{font-family: Fira Code; font-weight:700; src:url(FiraCode-Bold.woff2) format("woff2"); }
-
-$primary: #182430;
-
-$background: darken($primary, 5%);
-$background-container: lighten($primary, 10%);
-
-* {
-    margin: 10px;
-    padding: 0px;
-}
-
-html {
-    font-size: 80%
-}
-
-a {
-    color: lighten($primary, 40%);
-    text-decoration: none;
-    &:hover { color: lighten($primary, 60%); }
-}
-
-body {
-    font-family: Fira Code, Helvetica Neue, Helvetica, Arial, sans-serif;
-    text-shadow: 2px 2px 2px rgb(0, 0, 0);
-    text-align: center;
-    // line-height: 18px;
-    color: rgb(255, 255, 255);
-    background-color: $background;
-    margin: 0px;
-
-    .recipe-item {
-        padding: 4px;
-    }
-
-    .recipe-item-current {
-        padding: 3px;
-        border: 1px solid white;
-    }
-
-    /*
-    .header-container {
-
-    }
-    */
-
-    .main-container {
-        display: flex;
-
-        .list {
-            text-align: left;
-        }
-
-        .content {
-            background-color: $background-container;
-            border: 0.1em solid white;
-            padding: 0.5em;
-        }
-    }
-
-    .footer-container {
-        font-size: 0.5em;
-    }
-}
-
-img {
-    border: 0px;
-}
\ No newline at end of file
diff --git a/backend/templates/base.html b/backend/templates/base.html
index b3216e2..147ed3d 100644
--- a/backend/templates/base.html
+++ b/backend/templates/base.html
@@ -16,7 +16,10 @@
             run();
         
 
+        
+ {% block body_container %}{% endblock %} +
gburri - 2022
\ No newline at end of file diff --git a/backend/templates/base_with_list.html b/backend/templates/base_with_list.html index dab52d4..7a4e937 100644 --- a/backend/templates/base_with_list.html +++ b/backend/templates/base_with_list.html @@ -5,7 +5,7 @@ {% endmacro %} {% block main_container %} -