feat: add block layout for home page with CSS

This commit is contained in:
Matthieu Bessat 2024-07-22 12:07:02 +02:00
parent 282b719e61
commit c2a2721ec6
13 changed files with 842 additions and 351 deletions

421
Cargo.lock generated
View file

@ -146,18 +146,19 @@ version = "0.1.0"
dependencies = [
"anyhow",
"axum",
"axum-template",
"chrono",
"clap",
"env_logger",
"fully_pub",
"log",
"minijinja",
"minijinja 1.0.20",
"serde",
"serde_json",
"serde_yaml",
"sqlx",
"tera",
"tokio",
"tower-http",
"uuid",
]
@ -216,6 +217,18 @@ dependencies = [
"tracing",
]
[[package]]
name = "axum-template"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7013f6403ac283c62d843b344d27742a3ffb48f57a2263522b7c978cec40cc1"
dependencies = [
"axum",
"minijinja 2.0.3",
"serde",
"thiserror",
]
[[package]]
name = "backtrace"
version = "0.3.71"
@ -267,16 +280,6 @@ dependencies = [
"generic-array",
]
[[package]]
name = "bstr"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
dependencies = [
"memchr",
"serde",
]
[[package]]
name = "bumpalo"
version = "3.15.4"
@ -322,28 +325,6 @@ dependencies = [
"windows-targets 0.52.4",
]
[[package]]
name = "chrono-tz"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d59ae0466b83e838b81a54256c39d5d7c20b9d7daa10510a242d9b75abd5936e"
dependencies = [
"chrono",
"chrono-tz-build",
"phf",
]
[[package]]
name = "chrono-tz-build"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "433e39f13c9a060046954e0592a8d0a4bcb1040125cbf91cb8ee58964cfb350f"
dependencies = [
"parse-zoneinfo",
"phf",
"phf_codegen",
]
[[package]]
name = "clap"
version = "4.5.4"
@ -413,25 +394,6 @@ version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-queue"
version = "0.3.11"
@ -468,12 +430,6 @@ dependencies = [
"zeroize",
]
[[package]]
name = "deunicode"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6e854126756c496b8c81dec88f9a706b15b875c5849d4097a3854476b9fdf94"
[[package]]
name = "digest"
version = "0.10.7"
@ -704,30 +660,6 @@ version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "globset"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
dependencies = [
"aho-corasick",
"bstr",
"log",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "globwalk"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
dependencies = [
"bitflags 1.3.2",
"ignore",
"walkdir",
]
[[package]]
name = "hashbrown"
version = "0.14.3"
@ -829,6 +761,12 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "http-range-header"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a"
[[package]]
name = "httparse"
version = "1.8.0"
@ -841,15 +779,6 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humansize"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7"
dependencies = [
"libm",
]
[[package]]
name = "humantime"
version = "2.1.0"
@ -924,22 +853,6 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "ignore"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1"
dependencies = [
"crossbeam-deque",
"globset",
"log",
"memchr",
"regex-automata",
"same-file",
"walkdir",
"winapi-util",
]
[[package]]
name = "indexmap"
version = "2.2.6"
@ -1056,6 +969,16 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime_guess"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
dependencies = [
"mime",
"unicase",
]
[[package]]
name = "minijinja"
version = "1.0.20"
@ -1065,6 +988,15 @@ dependencies = [
"serde",
]
[[package]]
name = "minijinja"
version = "2.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "933ee10775d58fca8238a84fe165dfe4bde8b07d7574f24d76ffea91170f3ac6"
dependencies = [
"serde",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@ -1196,15 +1128,6 @@ dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "parse-zoneinfo"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
dependencies = [
"regex",
]
[[package]]
name = "paste"
version = "1.0.14"
@ -1226,89 +1149,6 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pest"
version = "2.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95"
dependencies = [
"memchr",
"thiserror",
"ucd-trie",
]
[[package]]
name = "pest_derive"
version = "2.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f73541b156d32197eecda1a4014d7f868fd2bcb3c550d5386087cfba442bf69c"
dependencies = [
"pest",
"pest_generator",
]
[[package]]
name = "pest_generator"
version = "2.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c35eeed0a3fab112f75165fdc026b3913f4183133f19b49be773ac9ea966e8bd"
dependencies = [
"pest",
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]]
name = "pest_meta"
version = "2.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2adbf29bb9776f28caece835398781ab24435585fe0d4dc1374a61db5accedca"
dependencies = [
"once_cell",
"pest",
"sha2",
]
[[package]]
name = "phf"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_codegen"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
dependencies = [
"phf_generator",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
dependencies = [
"phf_shared",
"rand",
]
[[package]]
name = "phf_shared"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
dependencies = [
"siphasher",
]
[[package]]
name = "pin-project"
version = "1.1.5"
@ -1511,15 +1351,6 @@ version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
@ -1633,12 +1464,6 @@ dependencies = [
"rand_core",
]
[[package]]
name = "siphasher"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]]
name = "slab"
version = "0.4.9"
@ -1648,16 +1473,6 @@ dependencies = [
"autocfg",
]
[[package]]
name = "slug"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bd94acec9c8da640005f8e135a39fc0372e74535e6b368b7a04b875f784c8c4"
dependencies = [
"deunicode",
"wasm-bindgen",
]
[[package]]
name = "smallvec"
version = "1.13.2"
@ -1977,28 +1792,6 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "tera"
version = "1.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "970dff17c11e884a4a09bc76e3a17ef71e01bb13447a11e85226e254fe6d10b8"
dependencies = [
"chrono",
"chrono-tz",
"globwalk",
"humansize",
"lazy_static",
"percent-encoding",
"pest",
"pest_derive",
"rand",
"regex",
"serde",
"serde_json",
"slug",
"unic-segment",
]
[[package]]
name = "thiserror"
version = "1.0.58"
@ -2075,6 +1868,19 @@ dependencies = [
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tower"
version = "0.4.13"
@ -2091,6 +1897,31 @@ dependencies = [
"tracing",
]
[[package]]
name = "tower-http"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
dependencies = [
"bitflags 2.5.0",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"http-range-header",
"httpdate",
"mime",
"mime_guess",
"percent-encoding",
"pin-project-lite",
"tokio",
"tokio-util",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-layer"
version = "0.3.2"
@ -2142,59 +1973,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "ucd-trie"
version = "0.1.6"
name = "unicase"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
[[package]]
name = "unic-char-property"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221"
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [
"unic-char-range",
]
[[package]]
name = "unic-char-range"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc"
[[package]]
name = "unic-common"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
[[package]]
name = "unic-segment"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23"
dependencies = [
"unic-ucd-segment",
]
[[package]]
name = "unic-ucd-segment"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700"
dependencies = [
"unic-char-property",
"unic-char-range",
"unic-ucd-version",
]
[[package]]
name = "unic-ucd-version"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4"
dependencies = [
"unic-common",
"version_check",
]
[[package]]
@ -2281,16 +2065,6 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
@ -2367,37 +2141,6 @@ dependencies = [
"wasite",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.52.0"

View file

@ -11,7 +11,6 @@ chrono = { version = "0.4.26", features = ["serde"] }
sqlx = { version = "0.7.4", features = ["sqlite", "runtime-tokio", "chrono"] }
anyhow = "1.0.75"
clap = "4.5.4"
tera = "1.19.1"
tokio = { version = "1.37.0", features = ["full"] }
axum = { version = "0.7.5", features = ["json"] }
minijinja = { version = "1.0.20", features = ["builtins"] }
@ -19,4 +18,6 @@ uuid = { version = "1.8.0", features = ["serde", "v4"] }
fully_pub = "0.1.4"
log = "0.4.22"
env_logger = "0.11.3"
tower-http = { version = "0.5.2", features = ["fs"] }
axum-template = { version = "2.3.0", features = ["minijinja"] }

0
assets/styles/app.css Normal file
View file

712
assets/styles/simple.css Normal file
View file

@ -0,0 +1,712 @@
/* Global variables. */
:root,
::backdrop {
/* Set sans-serif & mono fonts */
--sans-font: -apple-system, BlinkMacSystemFont, "Avenir Next", Avenir,
"Nimbus Sans L", Roboto, "Noto Sans", "Segoe UI", Arial, Helvetica,
"Helvetica Neue", sans-serif;
--mono-font: Consolas, Menlo, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
--standard-border-radius: 5px;
/* Default (light) theme */
--bg: #fff;
--accent-bg: #f5f7ff;
--text: #212121;
--text-light: #585858;
--border: #898EA4;
--accent: #0d47a1;
--accent-hover: #1266e2;
--accent-text: var(--bg);
--code: #d81b60;
--preformatted: #444;
--marked: #ffdd33;
--disabled: #efefef;
}
/* Dark theme */
@media (prefers-color-scheme: dark) {
:root,
::backdrop {
color-scheme: dark;
--bg: #212121;
--accent-bg: #2b2b2b;
--text: #dcdcdc;
--text-light: #ababab;
--accent: #ffb300;
--accent-hover: #ffe099;
--accent-text: var(--bg);
--code: #f06292;
--preformatted: #ccc;
--disabled: #111;
}
/* Add a bit of transparency so light media isn't so glaring in dark mode */
img,
video {
opacity: 0.8;
}
}
/* Reset box-sizing */
*, *::before, *::after {
box-sizing: border-box;
}
/* Reset default appearance */
textarea,
select,
input,
progress {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
}
html {
/* Set the font globally */
font-family: var(--sans-font);
scroll-behavior: smooth;
}
/* Make the body a nice central block */
body {
color: var(--text);
background-color: var(--bg);
font-size: 1.15rem;
line-height: 1.5;
display: grid;
grid-template-columns: 1fr min(45rem, 90%) 1fr;
margin: 0;
}
body > * {
grid-column: 2;
}
/* Make the header bg full width, but the content inline with body */
body > header {
background-color: var(--accent-bg);
border-bottom: 1px solid var(--border);
text-align: center;
padding: 0 0.5rem 2rem 0.5rem;
grid-column: 1 / -1;
}
body > header > *:only-child {
margin-block-start: 2rem;
}
body > header h1 {
max-width: 1200px;
margin: 1rem auto;
}
body > header p {
max-width: 40rem;
margin: 1rem auto;
}
/* Add a little padding to ensure spacing is correct between content and header > nav */
main {
padding-top: 1.5rem;
}
body > footer {
margin-top: 4rem;
padding: 2rem 1rem 1.5rem 1rem;
color: var(--text-light);
font-size: 0.9rem;
text-align: center;
border-top: 1px solid var(--border);
}
/* Format headers */
h1 {
font-size: 3rem;
}
h2 {
font-size: 2.6rem;
margin-top: 3rem;
}
h3 {
font-size: 2rem;
margin-top: 3rem;
}
h4 {
font-size: 1.44rem;
}
h5 {
font-size: 1.15rem;
}
h6 {
font-size: 0.96rem;
}
p {
margin: 1.5rem 0;
}
/* Prevent long strings from overflowing container */
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
}
/* Fix line height when title wraps */
h1,
h2,
h3 {
line-height: 1.1;
}
/* Reduce header size on mobile */
@media only screen and (max-width: 720px) {
h1 {
font-size: 2.5rem;
}
h2 {
font-size: 2.1rem;
}
h3 {
font-size: 1.75rem;
}
h4 {
font-size: 1.25rem;
}
}
/* Format links & buttons */
a,
a:visited {
color: var(--accent);
}
a:hover {
text-decoration: none;
}
button,
.button,
a.button, /* extra specificity to override a */
input[type="submit"],
input[type="reset"],
input[type="button"],
label[type="button"] {
border: 1px solid var(--accent);
background-color: var(--accent);
color: var(--accent-text);
padding: 0.5rem 0.9rem;
text-decoration: none;
line-height: normal;
}
.button[aria-disabled="true"],
input:disabled,
textarea:disabled,
select:disabled,
button[disabled] {
cursor: not-allowed;
background-color: var(--disabled);
border-color: var(--disabled);
color: var(--text-light);
}
input[type="range"] {
padding: 0;
}
/* Set the cursor to '?' on an abbreviation and style the abbreviation to show that there is more information underneath */
abbr[title] {
cursor: help;
text-decoration-line: underline;
text-decoration-style: dotted;
}
button:enabled:hover,
.button:not([aria-disabled="true"]):hover,
input[type="submit"]:enabled:hover,
input[type="reset"]:enabled:hover,
input[type="button"]:enabled:hover,
label[type="button"]:hover {
background-color: var(--accent-hover);
border-color: var(--accent-hover);
cursor: pointer;
}
.button:focus-visible,
button:focus-visible:where(:enabled),
input:enabled:focus-visible:where(
[type="submit"],
[type="reset"],
[type="button"]
) {
outline: 2px solid var(--accent);
outline-offset: 1px;
}
/* Format navigation */
header > nav {
font-size: 1rem;
line-height: 2;
padding: 1rem 0 0 0;
}
/* Use flexbox to allow items to wrap, as needed */
header > nav ul,
header > nav ol {
align-content: space-around;
align-items: center;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
list-style-type: none;
margin: 0;
padding: 0;
}
/* List items are inline elements, make them behave more like blocks */
header > nav ul li,
header > nav ol li {
display: inline-block;
}
header > nav a,
header > nav a:visited {
margin: 0 0.5rem 1rem 0.5rem;
border: 1px solid var(--border);
border-radius: var(--standard-border-radius);
color: var(--text);
display: inline-block;
padding: 0.1rem 1rem;
text-decoration: none;
}
header > nav a:hover,
header > nav a.current,
header > nav a[aria-current="page"] {
border-color: var(--accent);
color: var(--accent);
cursor: pointer;
}
/* Reduce nav side on mobile */
@media only screen and (max-width: 720px) {
header > nav a {
border: none;
padding: 0;
text-decoration: underline;
line-height: 1;
}
}
/* Consolidate box styling */
aside, details, pre, progress {
background-color: var(--accent-bg);
border: 1px solid var(--border);
border-radius: var(--standard-border-radius);
margin-bottom: 1rem;
}
aside {
font-size: 1rem;
width: 30%;
padding: 0 15px;
margin-inline-start: 15px;
float: right;
}
*[dir="rtl"] aside {
float: left;
}
/* Make aside full-width on mobile */
@media only screen and (max-width: 720px) {
aside {
width: 100%;
float: none;
margin-inline-start: 0;
}
}
article, fieldset, dialog {
border: 1px solid var(--border);
padding: 1rem;
border-radius: var(--standard-border-radius);
margin-bottom: 1rem;
}
article h2:first-child,
section h2:first-child,
article h3:first-child,
section h3:first-child {
margin-top: 1rem;
}
section {
border-top: 1px solid var(--border);
border-bottom: 1px solid var(--border);
padding: 2rem 1rem;
margin: 3rem 0;
}
/* Don't double separators when chaining sections */
section + section,
section:first-child {
border-top: 0;
padding-top: 0;
}
section + section {
margin-top: 0;
}
section:last-child {
border-bottom: 0;
padding-bottom: 0;
}
details {
padding: 0.7rem 1rem;
}
summary {
cursor: pointer;
font-weight: bold;
padding: 0.7rem 1rem;
margin: -0.7rem -1rem;
word-break: break-all;
}
details[open] > summary + * {
margin-top: 0;
}
details[open] > summary {
margin-bottom: 0.5rem;
}
details[open] > :last-child {
margin-bottom: 0;
}
/* Format tables */
table {
border-collapse: collapse;
margin: 1.5rem 0;
}
figure > table {
width: max-content;
margin: 0;
}
td,
th {
border: 1px solid var(--border);
text-align: start;
padding: 0.5rem;
}
th {
background-color: var(--accent-bg);
font-weight: bold;
}
tr:nth-child(even) {
/* Set every other cell slightly darker. Improves readability. */
background-color: var(--accent-bg);
}
table caption {
font-weight: bold;
margin-bottom: 0.5rem;
}
/* Format forms */
textarea,
select,
input,
button,
.button {
font-size: inherit;
font-family: inherit;
padding: 0.5rem;
margin-bottom: 0.5rem;
border-radius: var(--standard-border-radius);
box-shadow: none;
max-width: 100%;
display: inline-block;
}
textarea,
select,
input {
color: var(--text);
background-color: var(--bg);
border: 1px solid var(--border);
}
label {
display: block;
}
textarea:not([cols]) {
width: 100%;
}
/* Add arrow to drop-down */
select:not([multiple]) {
background-image: linear-gradient(45deg, transparent 49%, var(--text) 51%),
linear-gradient(135deg, var(--text) 51%, transparent 49%);
background-position: calc(100% - 15px), calc(100% - 10px);
background-size: 5px 5px, 5px 5px;
background-repeat: no-repeat;
padding-inline-end: 25px;
}
*[dir="rtl"] select:not([multiple]) {
background-position: 10px, 15px;
}
/* checkbox and radio button style */
input[type="checkbox"],
input[type="radio"] {
vertical-align: middle;
position: relative;
width: min-content;
}
input[type="checkbox"] + label,
input[type="radio"] + label {
display: inline-block;
}
input[type="radio"] {
border-radius: 100%;
}
input[type="checkbox"]:checked,
input[type="radio"]:checked {
background-color: var(--accent);
}
input[type="checkbox"]:checked::after {
/* Creates a rectangle with colored right and bottom borders which is rotated to look like a check mark */
content: " ";
width: 0.18em;
height: 0.32em;
border-radius: 0;
position: absolute;
top: 0.05em;
left: 0.17em;
background-color: transparent;
border-right: solid var(--bg) 0.08em;
border-bottom: solid var(--bg) 0.08em;
font-size: 1.8em;
transform: rotate(45deg);
}
input[type="radio"]:checked::after {
/* creates a colored circle for the checked radio button */
content: " ";
width: 0.25em;
height: 0.25em;
border-radius: 100%;
position: absolute;
top: 0.125em;
background-color: var(--bg);
left: 0.125em;
font-size: 32px;
}
/* Makes input fields wider on smaller screens */
@media only screen and (max-width: 720px) {
textarea,
select,
input {
width: 100%;
}
}
/* Set a height for color input */
input[type="color"] {
height: 2.5rem;
padding: 0.2rem;
}
/* do not show border around file selector button */
input[type="file"] {
border: 0;
}
/* Misc body elements */
hr {
border: none;
height: 1px;
background: var(--border);
margin: 1rem auto;
}
mark {
padding: 2px 5px;
border-radius: var(--standard-border-radius);
background-color: var(--marked);
color: black;
}
mark a {
color: #0d47a1;
}
img,
video {
max-width: 100%;
height: auto;
border-radius: var(--standard-border-radius);
}
figure {
margin: 0;
display: block;
overflow-x: auto;
}
figure > img,
figure > picture > img {
display: block;
margin-inline: auto;
}
figcaption {
text-align: center;
font-size: 0.9rem;
color: var(--text-light);
margin-block: 1rem;
}
blockquote {
margin-inline-start: 2rem;
margin-inline-end: 0;
margin-block: 2rem;
padding: 0.4rem 0.8rem;
border-inline-start: 0.35rem solid var(--accent);
color: var(--text-light);
font-style: italic;
}
cite {
font-size: 0.9rem;
color: var(--text-light);
font-style: normal;
}
dt {
color: var(--text-light);
}
/* Use mono font for code elements */
code,
pre,
pre span,
kbd,
samp {
font-family: var(--mono-font);
color: var(--code);
}
kbd {
color: var(--preformatted);
border: 1px solid var(--preformatted);
border-bottom: 3px solid var(--preformatted);
border-radius: var(--standard-border-radius);
padding: 0.1rem 0.4rem;
}
pre {
padding: 1rem 1.4rem;
max-width: 100%;
overflow: auto;
color: var(--preformatted);
}
/* Fix embedded code within pre */
pre code {
color: var(--preformatted);
background: none;
margin: 0;
padding: 0;
}
/* Progress bars */
/* Declarations are repeated because you */
/* cannot combine vendor-specific selectors */
progress {
width: 100%;
}
progress:indeterminate {
background-color: var(--accent-bg);
}
progress::-webkit-progress-bar {
border-radius: var(--standard-border-radius);
background-color: var(--accent-bg);
}
progress::-webkit-progress-value {
border-radius: var(--standard-border-radius);
background-color: var(--accent);
}
progress::-moz-progress-bar {
border-radius: var(--standard-border-radius);
background-color: var(--accent);
transition-property: width;
transition-duration: 0.3s;
}
progress:indeterminate::-moz-progress-bar {
background-color: var(--accent-bg);
}
dialog {
max-width: 40rem;
margin: auto;
}
dialog::backdrop {
background-color: var(--bg);
opacity: 0.8;
}
@media only screen and (max-width: 720px) {
dialog {
max-width: 100%;
margin: auto 1em;
}
}
/* Superscript & Subscript */
/* Prevent scripts from affecting line-height. */
sup, sub {
vertical-align: baseline;
position: relative;
}
sup {
top: -0.4em;
}
sub {
top: 0.3em;
}
/* Classes for notices */
.notice {
background: var(--accent-bg);
border: 2px solid var(--border);
border-radius: var(--standard-border-radius);
padding: 1.5rem;
margin: 2rem 0;
}

View file

@ -2,23 +2,28 @@ use crate::models::{Task, TaskRun, TaskRunSummary};
use axum::extract::{Path as ExtractPath, State};
use axum::http::StatusCode;
use axum::Json;
use axum::response::Html;
use minijinja::render;
use axum::response::{Html, IntoResponse, Response};
use axum_template::RenderHtml;
use minijinja::{context, render};
use uuid::Uuid;
use crate::models::ExecutorOrder;
use crate::AppState;
use crate::{AppState};
pub async fn home() -> Html<String> {
Html(render!(
include_str!("./templates/home.html"),
))
pub async fn home(
State(app_state): State<AppState>
) -> impl IntoResponse {
Html(
app_state.template_engine.get_template("pages/home.html").unwrap()
.render(context!())
.unwrap()
)
}
pub async fn list_tasks(State(app_state): State<AppState>) -> Html<String> {
let tasks: Vec<Task> = app_state.config.tasks;
Html(render!(
include_str!("./templates/list_tasks.html"),
include_str!("./templates/pages/list_tasks.html"),
tasks => tasks
))
}
@ -49,7 +54,7 @@ pub async fn trigger_task(
(
StatusCode::OK,
Html(render!(
include_str!("./templates/run_task.html"),
include_str!("./templates/pages/run_task.html"),
tasks => tasks
)),
)
@ -80,7 +85,7 @@ pub async fn list_task_runs(
}
};
Html(render!(
include_str!("./templates/list_task_runs.html"),
include_str!("./templates/pages/list_task_runs.html"),
task => task,
runs => runs,
))
@ -102,7 +107,7 @@ pub async fn get_task_run(
};
Html(render!(
include_str!("./templates/task_run_details.html"),
include_str!("./templates/pages/task_run_details.html"),
run => run_details
))
}

View file

@ -2,12 +2,15 @@ mod controllers;
mod models;
mod executor;
use axum_template::engine::Engine;
use log::info;
use anyhow::{anyhow, Context, Result};
use axum::routing::get;
use axum::Router;
use minijinja::Environment;
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
use sqlx::{ConnectOptions, Pool, Sqlite};
use tower_http::services::ServeDir;
use std::fs;
use std::str::FromStr;
use std::sync::Arc;
@ -20,6 +23,7 @@ pub struct AppState {
config: Config,
db: Pool<Sqlite>,
executor_tx: Arc<Sender<ExecutorOrder>>,
template_engine: Environment<'static>
}
fn get_config() -> Result<Config> {
@ -42,10 +46,17 @@ async fn main() -> Result<()> {
let (tx, rx) = mpsc::channel::<ExecutorOrder>(32);
let config: Config = get_config().expect("Cannot get config");
let mut jinja = Environment::new();
jinja
.add_template("layouts/base.html", include_str!("./templates/layouts/base.html"))
.unwrap();
jinja.add_template("pages/home.html", include_str!("./templates/pages/home.html")).unwrap();
let state = AppState {
config,
db: pool,
executor_tx: Arc::new(tx),
template_engine: jinja
};
// start executor daemon
@ -65,6 +76,7 @@ async fn main() -> Result<()> {
get(controllers::get_task_run),
)
.route("/webhooks/:token", get(controllers::handle_webhook))
.nest_service("/assets", ServeDir::new("./assets"))
.with_state(state);
let listen_addr = "0.0.0.0:8085";

View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Autotasker</title>
<link href="/assets/styles/simple.css" rel="stylesheet">
<link href="/assets/styles/app.css" rel="stylesheet">
</head>
<body>
<div class="container">
{% block body %}{% endblock %}
</div>
</body>
</html>

View file

@ -1,3 +1,5 @@
{% extends "layouts/base.html" %}
{% block body %}
<h1>Hello welcome on autotasker</h1>
You main want to start in here.
@ -10,3 +12,4 @@ Autotasker is free software under <a href="https://www.gnu.org/licenses/gpl-3.0.
You can find source code on a <a href="https://forge.lefuturiste.fr/mbess/autotasker">self-hosted forge repository</a>.
</p>
{% endblock %}

BIN
tmp/dbs/current.db Normal file

Binary file not shown.