more groundwork for the frontend
This commit is contained in:
parent
d0dadfea39
commit
afc1d2c764
|
@ -103,6 +103,65 @@ dependencies = [
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "askama"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70a6e7ebd44d0047fd48206c83c5cd3214acc7b9d87f001da170145c47ef7d12"
|
||||||
|
dependencies = [
|
||||||
|
"askama_derive",
|
||||||
|
"askama_escape",
|
||||||
|
"askama_shared",
|
||||||
|
"mime 0.3.16",
|
||||||
|
"mime_guess",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "askama_derive"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e1d7169690c4f56343dcd821ab834972a22570a2662a19a84fd7775d5e1c3881"
|
||||||
|
dependencies = [
|
||||||
|
"askama_shared",
|
||||||
|
"proc-macro2 1.0.21",
|
||||||
|
"quote 1.0.7",
|
||||||
|
"syn 1.0.40",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "askama_escape"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90c108c1a94380c89d2215d0ac54ce09796823cca0fd91b299cfff3b33e346fb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "askama_rocket"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "40428c13bd027adfd481391729b85bf9961b59e5b21bb55e80f603d19d054583"
|
||||||
|
dependencies = [
|
||||||
|
"askama",
|
||||||
|
"rocket",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "askama_shared"
|
||||||
|
version = "0.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62fc272363345c8cdc030e4c259d9d028237f8b057dc9bb327772a257bde6bb5"
|
||||||
|
dependencies = [
|
||||||
|
"askama_escape",
|
||||||
|
"humansize",
|
||||||
|
"nom",
|
||||||
|
"num-traits",
|
||||||
|
"percent-encoding 2.1.0",
|
||||||
|
"proc-macro2 1.0.21",
|
||||||
|
"quote 1.0.7",
|
||||||
|
"serde",
|
||||||
|
"syn 1.0.40",
|
||||||
|
"toml 0.5.7",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
|
@ -742,6 +801,12 @@ version = "1.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
|
checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humansize"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "0.10.16"
|
version = "0.10.16"
|
||||||
|
@ -974,6 +1039,8 @@ checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
||||||
name = "mi"
|
name = "mi"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"askama",
|
||||||
|
"askama_rocket",
|
||||||
"chrono",
|
"chrono",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"diesel",
|
"diesel",
|
||||||
|
@ -1016,6 +1083,16 @@ version = "0.3.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mime_guess"
|
||||||
|
version = "2.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212"
|
||||||
|
dependencies = [
|
||||||
|
"mime 0.3.16",
|
||||||
|
"unicase 2.6.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
@ -1079,6 +1156,16 @@ dependencies = [
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "5.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"version_check 0.9.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "notify"
|
name = "notify"
|
||||||
version = "4.0.15"
|
version = "4.0.15"
|
||||||
|
@ -1539,7 +1626,7 @@ dependencies = [
|
||||||
"rocket_http",
|
"rocket_http",
|
||||||
"state",
|
"state",
|
||||||
"time 0.1.44",
|
"time 0.1.44",
|
||||||
"toml",
|
"toml 0.4.10",
|
||||||
"version_check 0.9.2",
|
"version_check 0.9.2",
|
||||||
"yansi",
|
"yansi",
|
||||||
]
|
]
|
||||||
|
@ -2053,6 +2140,15 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.19"
|
version = "0.1.19"
|
||||||
|
|
|
@ -7,6 +7,7 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
askama_rocket = "0.10"
|
||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
color-eyre = "0.5"
|
color-eyre = "0.5"
|
||||||
futures-io = "0.3"
|
futures-io = "0.3"
|
||||||
|
@ -31,6 +32,10 @@ twapi-ureq = "0.1.5"
|
||||||
ureq = { version = "1", features = ["json", "charset"] }
|
ureq = { version = "1", features = ["json", "charset"] }
|
||||||
url = "2"
|
url = "2"
|
||||||
|
|
||||||
|
[dependencies.askama]
|
||||||
|
version = "0.10"
|
||||||
|
features = [ "with-rocket" ]
|
||||||
|
|
||||||
[dependencies.diesel]
|
[dependencies.diesel]
|
||||||
version = "1"
|
version = "1"
|
||||||
features = ["sqlite", "r2d2", "chrono"]
|
features = ["sqlite", "r2d2", "chrono"]
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
address = "0.0.0.0"
|
address = "0.0.0.0"
|
||||||
switchcounter_webhook = "..."
|
switchcounter_webhook = "..."
|
||||||
discord_webhook = ""
|
discord_webhook = ""
|
||||||
|
asset_path = "../static"
|
||||||
|
|
||||||
# I don't know how to generate these without using Go, sorry. These are hex-encoded
|
# I don't know how to generate these without using Go, sorry. These are hex-encoded
|
||||||
# ED25519 public/private keys.
|
# ED25519 public/private keys.
|
||||||
|
|
|
@ -6,6 +6,7 @@ let
|
||||||
rustc = rust;
|
rustc = rust;
|
||||||
cargo = rust;
|
cargo = rust;
|
||||||
};
|
};
|
||||||
|
gruvbox = pkgs.callPackage sources.gruvbox-css { };
|
||||||
src = builtins.filterSource
|
src = builtins.filterSource
|
||||||
(path: type: type != "directory" || builtins.baseNameOf path != "target")
|
(path: type: type != "directory" || builtins.baseNameOf path != "target")
|
||||||
./.;
|
./.;
|
||||||
|
@ -13,6 +14,7 @@ in naersk.buildPackage {
|
||||||
name = "mi_backend";
|
name = "mi_backend";
|
||||||
inherit src;
|
inherit src;
|
||||||
buildInputs = with pkgs; [ openssl pkg-config sqlite libsodium ];
|
buildInputs = with pkgs; [ openssl pkg-config sqlite libsodium ];
|
||||||
|
GRUVBOX_CSS = "${gruvbox}/gruvbox.css";
|
||||||
SODIUM_USE_PKG_CONFIG = "1";
|
SODIUM_USE_PKG_CONFIG = "1";
|
||||||
SODIUM_SHARED = "1";
|
SODIUM_SHARED = "1";
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
use askama::Template;
|
||||||
|
use rocket::{fairing::AdHoc, response::content::Css, Request};
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "app.html")]
|
||||||
|
struct App {
|
||||||
|
title: String,
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
|
fn frontend() -> App {
|
||||||
|
App {
|
||||||
|
title: "Mi".to_string(),
|
||||||
|
message: "Loading...".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "notfound.html")]
|
||||||
|
struct NotFound {
|
||||||
|
title: String,
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[catch(404)]
|
||||||
|
fn not_found(req: &Request) -> NotFound {
|
||||||
|
NotFound {
|
||||||
|
title: "Not found".to_string(),
|
||||||
|
message: format!("{} not found", req.uri()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/static/gruvbox.css")]
|
||||||
|
fn gruvbox() -> Css<String> {
|
||||||
|
Css(include_str!(env!("GRUVBOX_CSS")).to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fairing() -> AdHoc {
|
||||||
|
AdHoc::on_attach("frontend integration", |rocket| {
|
||||||
|
Ok(rocket
|
||||||
|
.register(catchers![not_found])
|
||||||
|
.mount("/", routes![frontend, gruvbox]))
|
||||||
|
})
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ pub const APPLICATION_NAME: &str = concat!(
|
||||||
);
|
);
|
||||||
|
|
||||||
pub mod api;
|
pub mod api;
|
||||||
|
pub mod frontend;
|
||||||
pub mod models;
|
pub mod models;
|
||||||
pub mod paseto;
|
pub mod paseto;
|
||||||
pub mod rocket_trace;
|
pub mod rocket_trace;
|
||||||
|
|
|
@ -11,7 +11,7 @@ use rocket_contrib::helmet::SpaceHelmet;
|
||||||
use rocket_cors::{AllowedHeaders, AllowedOrigins};
|
use rocket_cors::{AllowedHeaders, AllowedOrigins};
|
||||||
use rocket_prometheus::PrometheusMetrics;
|
use rocket_prometheus::PrometheusMetrics;
|
||||||
|
|
||||||
use ::mi::{api, paseto, rocket_trace::*, web::*, MainDatabase, APPLICATION_NAME};
|
use ::mi::{api, frontend, paseto, rocket_trace::*, web::*, MainDatabase, APPLICATION_NAME};
|
||||||
|
|
||||||
#[get("/.within/botinfo")]
|
#[get("/.within/botinfo")]
|
||||||
fn botinfo() -> &'static str {
|
fn botinfo() -> &'static str {
|
||||||
|
@ -58,8 +58,10 @@ fn main() -> Result<()> {
|
||||||
rocket::ignite()
|
rocket::ignite()
|
||||||
.attach(prometheus.clone())
|
.attach(prometheus.clone())
|
||||||
.attach(cors)
|
.attach(cors)
|
||||||
.attach(MainDatabase::fairing())
|
|
||||||
.attach(SpaceHelmet::default())
|
.attach(SpaceHelmet::default())
|
||||||
|
.attach(static_files())
|
||||||
|
.attach(frontend::fairing())
|
||||||
|
.attach(MainDatabase::fairing())
|
||||||
.attach(RequestId {})
|
.attach(RequestId {})
|
||||||
.attach(paseto::ed25519_keypair())
|
.attach(paseto::ed25519_keypair())
|
||||||
.attach(DiscordWebhook::fairing())
|
.attach(DiscordWebhook::fairing())
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
use rocket::fairing::{Fairing, Info, Kind};
|
use rocket::fairing::{AdHoc, Fairing, Info, Kind};
|
||||||
use rocket::http::Header;
|
use rocket::http::Header;
|
||||||
use rocket::{Data, Request, Response};
|
use rocket::{Data, Request, Response};
|
||||||
|
use rocket_contrib::serve::StaticFiles;
|
||||||
use rusty_ulid::generate_ulid_string;
|
use rusty_ulid::generate_ulid_string;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct RequestId;
|
pub struct RequestId;
|
||||||
|
|
||||||
impl Fairing for RequestId {
|
impl Fairing for RequestId {
|
||||||
|
@ -32,3 +34,11 @@ impl Fairing for RequestId {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn static_files() -> AdHoc {
|
||||||
|
AdHoc::on_attach("Static fileserver", |rocket| {
|
||||||
|
let asset_path = rocket.config().get_string("asset_path").unwrap();
|
||||||
|
|
||||||
|
Ok(rocket.mount("/static", StaticFiles::from(asset_path)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{{ title }}</title>
|
||||||
|
<link rel="stylesheet" href="/static/gruvbox.css">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="icon" type="image/png" href="/static/favicon.png"/>
|
||||||
|
<link rel="icon" href="/static/favicon.ico" type="image/x-icon"/>
|
||||||
|
</head>
|
||||||
|
<body id="top">
|
||||||
|
<main>
|
||||||
|
<div id="app">{{ message }}</div>
|
||||||
|
<script src="/static/elm.js"></script>
|
||||||
|
<script>
|
||||||
|
var app = Elm.Signup.init({
|
||||||
|
node: document.getElementById("app")
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{{ title }}</title>
|
||||||
|
<link rel="stylesheet" href="/static/gruvbox.css">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="icon" type="image/png" href="/static/favicon.png"/>
|
||||||
|
<link rel="icon" href="/static/favicon.ico" type="image/x-icon"/>
|
||||||
|
</head>
|
||||||
|
<body id="top">
|
||||||
|
<main>
|
||||||
|
<nav class="nav">
|
||||||
|
<a href="/">Mi</a>
|
||||||
|
</nav>
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
<p>{{ message }}</p>
|
||||||
|
<a href="/">Go home</a>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,3 +1,2 @@
|
||||||
index.html
|
elm-stuff
|
||||||
index.js
|
elm.js
|
||||||
elm-stuff
|
|
|
@ -15,6 +15,11 @@
|
||||||
version = "1.0.2";
|
version = "1.0.2";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
"rtfeldman/elm-css" = {
|
||||||
|
sha256 = "0nxiyxyw3kw55whkpwhrcgc0dr6a8zlm2nqvsaqdw6mzkykg0ba6";
|
||||||
|
version = "16.1.0";
|
||||||
|
};
|
||||||
|
|
||||||
"elm/core" = {
|
"elm/core" = {
|
||||||
sha256 = "19w0iisdd66ywjayyga4kv2p1v9rxzqjaxhckp8ni6n8i0fb2dvf";
|
sha256 = "19w0iisdd66ywjayyga4kv2p1v9rxzqjaxhckp8ni6n8i0fb2dvf";
|
||||||
version = "1.0.5";
|
version = "1.0.5";
|
||||||
|
@ -50,6 +55,11 @@
|
||||||
version = "1.0.5";
|
version = "1.0.5";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
"rtfeldman/elm-hex" = {
|
||||||
|
sha256 = "1y0aa16asvwdqmgbskh5iba6psp43lkcjjw9mgzj3gsrg33lp00d";
|
||||||
|
version = "1.0.0";
|
||||||
|
};
|
||||||
|
|
||||||
"elm/parser" = {
|
"elm/parser" = {
|
||||||
sha256 = "0a3cxrvbm7mwg9ykynhp7vjid58zsw03r63qxipxp3z09qks7512";
|
sha256 = "0a3cxrvbm7mwg9ykynhp7vjid58zsw03r63qxipxp3z09qks7512";
|
||||||
version = "1.1.0";
|
version = "1.1.0";
|
||||||
|
|
|
@ -13,13 +13,15 @@
|
||||||
"elm/json": "1.1.3",
|
"elm/json": "1.1.3",
|
||||||
"elm/time": "1.0.0",
|
"elm/time": "1.0.0",
|
||||||
"elm/url": "1.0.0",
|
"elm/url": "1.0.0",
|
||||||
|
"rtfeldman/elm-css": "16.1.0",
|
||||||
"rtfeldman/elm-iso8601-date-strings": "1.1.3"
|
"rtfeldman/elm-iso8601-date-strings": "1.1.3"
|
||||||
},
|
},
|
||||||
"indirect": {
|
"indirect": {
|
||||||
"elm/bytes": "1.0.8",
|
"elm/bytes": "1.0.8",
|
||||||
"elm/file": "1.0.5",
|
"elm/file": "1.0.5",
|
||||||
"elm/parser": "1.1.0",
|
"elm/parser": "1.1.0",
|
||||||
"elm/virtual-dom": "1.0.2"
|
"elm/virtual-dom": "1.0.2",
|
||||||
|
"rtfeldman/elm-hex": "1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"test-dependencies": {
|
"test-dependencies": {
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env nix-shell
|
||||||
|
#! nix-shell -i bash -p elmPackages.elm
|
||||||
|
|
||||||
|
elm make ./src/Main.elm --output elm.js
|
|
@ -6,6 +6,7 @@ import Html.Attributes exposing (autofocus, class, value)
|
||||||
import Html.Events exposing (onClick, onInput)
|
import Html.Events exposing (onClick, onInput)
|
||||||
import Mi
|
import Mi
|
||||||
import Mi.Switch
|
import Mi.Switch
|
||||||
|
import Mi.WebMention
|
||||||
|
|
||||||
|
|
||||||
-- We added a new AddTodo message type.
|
-- We added a new AddTodo message type.
|
||||||
|
@ -48,7 +49,6 @@ update msg model =
|
||||||
UpdateText newText ->
|
UpdateText newText ->
|
||||||
{ model | text = newText }
|
{ model | text = newText }
|
||||||
|
|
||||||
-- We append the model.text value to the end of our list of todo strings.
|
|
||||||
AddTodo ->
|
AddTodo ->
|
||||||
{ model | text = "", todos = model.todos ++ [ model.text ] }
|
{ model | text = "", todos = model.todos ++ [ model.text ] }
|
||||||
|
|
||||||
|
@ -76,4 +76,4 @@ main =
|
||||||
{ init = { text = "", todos = [] }
|
{ init = { text = "", todos = [] }
|
||||||
, view = view
|
, view = view
|
||||||
, update = update
|
, update = update
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
module Mi.Switch exposing (..)
|
module Mi.Switch exposing (Switch, decoder, frontURL, idURL, listURL, switchURL)
|
||||||
|
|
||||||
import Html exposing (..)
|
|
||||||
import Html.Attributes exposing (..)
|
|
||||||
import Iso8601
|
import Iso8601
|
||||||
import Json.Decode exposing (Decoder, field, int, map5, nullable, string)
|
import Json.Decode exposing (Decoder, field, int, map5, nullable, string)
|
||||||
import Time exposing (..)
|
import Time exposing (Posix)
|
||||||
import Url.Builder as UB
|
import Url.Builder as UB
|
||||||
|
|
||||||
|
|
||||||
type alias Switch =
|
type alias Switch =
|
||||||
{ id : String
|
{ id : String
|
||||||
, who : String
|
, who : String
|
||||||
|
@ -36,21 +35,21 @@ switchURL =
|
||||||
idURL : String -> String
|
idURL : String -> String
|
||||||
idURL id =
|
idURL id =
|
||||||
UB.absolute
|
UB.absolute
|
||||||
[ "api","switches", "id", id ]
|
[ "api", "switches", "id", id ]
|
||||||
[]
|
[]
|
||||||
|
|
||||||
|
|
||||||
frontURL : String
|
frontURL : String
|
||||||
frontURL =
|
frontURL =
|
||||||
UB.absolute
|
UB.absolute
|
||||||
["api", "switches", "current" ]
|
[ "api", "switches", "current" ]
|
||||||
[]
|
[]
|
||||||
|
|
||||||
|
|
||||||
listURL : Int -> Int -> String
|
listURL : Int -> Int -> String
|
||||||
listURL limit page =
|
listURL limit page =
|
||||||
UB.absolute
|
UB.absolute
|
||||||
["api", "switches", "" ]
|
[ "api", "switches", "" ]
|
||||||
[ UB.int "limit" limit
|
[ UB.int "limit" limit
|
||||||
, UB.int "page" page
|
, UB.int "page" page
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
module Mi.WebMention exposing (decoder, idURL, listURL)
|
||||||
|
|
||||||
|
import Json.Decode exposing (Decoder, field, map3, string)
|
||||||
|
import Url.Builder as UB
|
||||||
|
|
||||||
|
|
||||||
|
type alias WebMention =
|
||||||
|
{ id : String
|
||||||
|
, source_url : String
|
||||||
|
, target_url : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
decoder : Decoder WebMention
|
||||||
|
decoder =
|
||||||
|
map3 WebMention
|
||||||
|
(field "id" string)
|
||||||
|
(field "source_url" string)
|
||||||
|
(field "target_url" string)
|
||||||
|
|
||||||
|
|
||||||
|
idURL : String -> String
|
||||||
|
idURL id =
|
||||||
|
UB.absolute
|
||||||
|
[ "api", "webmention", id ]
|
||||||
|
[]
|
||||||
|
|
||||||
|
|
||||||
|
listURL : Int -> Int -> String
|
||||||
|
listURL limit page =
|
||||||
|
UB.absolute
|
||||||
|
[ "api", "webmention" ]
|
||||||
|
[ UB.int "limit" limit
|
||||||
|
, UB.int "page" page
|
||||||
|
]
|
|
@ -0,0 +1,115 @@
|
||||||
|
module Signup exposing (main)
|
||||||
|
|
||||||
|
import Browser
|
||||||
|
import Css exposing (..)
|
||||||
|
import Html exposing (Attribute, Html, button, div, h1, input, text)
|
||||||
|
import Html.Attributes exposing (id, style, type_)
|
||||||
|
import Html.Events exposing (onClick, onInput)
|
||||||
|
|
||||||
|
|
||||||
|
type alias User =
|
||||||
|
{ name : String
|
||||||
|
, email : String
|
||||||
|
, password : String
|
||||||
|
, loggedIn : Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
initialModel : User
|
||||||
|
initialModel =
|
||||||
|
{ name = ""
|
||||||
|
, email = ""
|
||||||
|
, password = ""
|
||||||
|
, loggedIn = False
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
view : User -> Html Msg
|
||||||
|
view user =
|
||||||
|
div [ style "margin" "auto" ]
|
||||||
|
[ h1 [ style "padding-left" "3cm" ] [ text "Sign up" ]
|
||||||
|
, Html.form formStyle
|
||||||
|
[ div []
|
||||||
|
[ text "Name"
|
||||||
|
, input ([ id "name", type_ "text", onInput SaveName ] ++ inputStyle) []
|
||||||
|
]
|
||||||
|
, div []
|
||||||
|
[ text "Email"
|
||||||
|
, input ([ id "email", type_ "email", onInput SaveEmail ] ++ inputStyle) []
|
||||||
|
]
|
||||||
|
, div []
|
||||||
|
[ text "Password"
|
||||||
|
, input ([ id "password", type_ "password", onInput SavePassword ] ++ inputStyle) []
|
||||||
|
]
|
||||||
|
, div []
|
||||||
|
[ button
|
||||||
|
([ type_ "submit", onClick Signup ] ++ buttonStyle)
|
||||||
|
[ text "Create my account" ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
formStyle : List (Attribute msg)
|
||||||
|
formStyle =
|
||||||
|
[ style "border-radius" "5px"
|
||||||
|
, style "background-color" "#f2f2f2"
|
||||||
|
, style "padding" "20px"
|
||||||
|
, style "width" "300px"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
inputStyle : List (Attribute msg)
|
||||||
|
inputStyle =
|
||||||
|
[ style "display" "block"
|
||||||
|
, style "width" "260px"
|
||||||
|
, style "padding" "12px 20px"
|
||||||
|
, style "margin" "8px 0"
|
||||||
|
, style "border" "none"
|
||||||
|
, style "border-radius" "4px"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
buttonStyle : List (Attribute msg)
|
||||||
|
buttonStyle =
|
||||||
|
[ style "width" "300px"
|
||||||
|
, style "background-color" "#397cd5"
|
||||||
|
, style "color" "white"
|
||||||
|
, style "padding" "14px 20px"
|
||||||
|
, style "margin-top" "10px"
|
||||||
|
, style "border" "none"
|
||||||
|
, style "border-radius" "4px"
|
||||||
|
, style "font-size" "16px"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= SaveName String
|
||||||
|
| SaveEmail String
|
||||||
|
| SavePassword String
|
||||||
|
| Signup
|
||||||
|
|
||||||
|
|
||||||
|
update : Msg -> User -> User
|
||||||
|
update message user =
|
||||||
|
case message of
|
||||||
|
SaveName name ->
|
||||||
|
{ user | name = name }
|
||||||
|
|
||||||
|
SaveEmail email ->
|
||||||
|
{ user | email = email }
|
||||||
|
|
||||||
|
SavePassword password ->
|
||||||
|
{ user | password = password }
|
||||||
|
|
||||||
|
Signup ->
|
||||||
|
{ user | loggedIn = True }
|
||||||
|
|
||||||
|
|
||||||
|
main : Program () User Msg
|
||||||
|
main =
|
||||||
|
Browser.sandbox
|
||||||
|
{ init = initialModel
|
||||||
|
, view = view
|
||||||
|
, update = update
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ let
|
||||||
pkgs =
|
pkgs =
|
||||||
import sources.nixpkgs { overlays = [ (import sources.nixpkgs-mozilla) ]; };
|
import sources.nixpkgs { overlays = [ (import sources.nixpkgs-mozilla) ]; };
|
||||||
rust = import ./nix/rust.nix { };
|
rust = import ./nix/rust.nix { };
|
||||||
|
gruvbox = pkgs.callPackage sources.gruvbox-css { };
|
||||||
in pkgs.mkShell rec {
|
in pkgs.mkShell rec {
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
# rust
|
# rust
|
||||||
|
@ -26,6 +27,8 @@ in pkgs.mkShell rec {
|
||||||
bashInteractive
|
bashInteractive
|
||||||
];
|
];
|
||||||
|
|
||||||
|
GRUVBOX_CSS = "${gruvbox}/gruvbox.css";
|
||||||
|
|
||||||
DATABASE_URL = "./mi.db";
|
DATABASE_URL = "./mi.db";
|
||||||
ROCKET_DATABASES = ''{ main_data = { url = "${DATABASE_URL}" } }'';
|
ROCKET_DATABASES = ''{ main_data = { url = "${DATABASE_URL}" } }'';
|
||||||
RUST_LOG = "info";
|
RUST_LOG = "info";
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
elm.js
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 63 KiB |
|
@ -0,0 +1 @@
|
||||||
|
../frontend/app.html
|
Loading…
Reference in New Issue