Compare commits
1 Commits
fef5d771ba
...
login
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b44792871c |
725
Cargo.lock
generated
725
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
22
Cargo.toml
22
Cargo.toml
@@ -4,22 +4,22 @@ version = "0.2.2"
|
||||
authors = ["Tuan-Dat Tran <tuan-dat.tran@tudattr.dev>"]
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
dioxus = { version = "0.5", features = ["fullstack", "router"] }
|
||||
tokio = { version = "1", features = ["full"], optional = true }
|
||||
|
||||
# Debug
|
||||
tracing = "0.1.40"
|
||||
dioxus-logger = "0.5.0"
|
||||
manganis = "0.2.2"
|
||||
dioxus-free-icons = { version = "0.8", features = ["font-awesome-brands"] }
|
||||
dioxus-sdk = { version = "0.5.0", features = ["i18n"] }
|
||||
dioxus-logger = "0.5.0"
|
||||
dioxus-free-icons = { version = "0.8", features = ["font-awesome-brands"] }
|
||||
|
||||
tokio = { version = "1", features = ["full"], optional = true }
|
||||
tracing = "0.1.40"
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
|
||||
lazy_static = "1.4.0"
|
||||
manganis = "0.2.2"
|
||||
simple_logger = { version = "4.2.0", optional = true }
|
||||
axum-login = "0.16.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
server = ["dioxus/axum"]
|
||||
server = ["dioxus/fullstack"]
|
||||
web = ["dioxus/web"]
|
||||
|
||||
@@ -613,11 +613,6 @@ video {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.my-4 {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.my-8 {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
@@ -691,6 +686,30 @@ video {
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.h-screen {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.h-5\/6 {
|
||||
height: 83.333333%;
|
||||
}
|
||||
|
||||
.h-1\/6 {
|
||||
height: 16.666667%;
|
||||
}
|
||||
|
||||
.h-2\/3 {
|
||||
height: 66.666667%;
|
||||
}
|
||||
|
||||
.h-4\/6 {
|
||||
height: 66.666667%;
|
||||
}
|
||||
|
||||
.h-full {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.min-h-screen {
|
||||
min-height: 100vh;
|
||||
}
|
||||
@@ -707,6 +726,10 @@ video {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.w-screen {
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.min-w-fit {
|
||||
min-width: -moz-fit-content;
|
||||
min-width: fit-content;
|
||||
@@ -748,6 +771,10 @@ video {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.content-center {
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
@@ -778,12 +805,6 @@ video {
|
||||
margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
|
||||
}
|
||||
|
||||
.space-x-8 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-x-reverse: 0;
|
||||
margin-right: calc(2rem * var(--tw-space-x-reverse));
|
||||
margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse)));
|
||||
}
|
||||
|
||||
.space-y-2 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-y-reverse: 0;
|
||||
margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
|
||||
@@ -796,10 +817,6 @@ video {
|
||||
margin-bottom: calc(2rem * var(--tw-space-y-reverse));
|
||||
}
|
||||
|
||||
.overflow-x-auto {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.rounded {
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
@@ -816,6 +833,10 @@ video {
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.rounded-xl {
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.rounded-e-lg {
|
||||
border-start-end-radius: 0.5rem;
|
||||
border-end-end-radius: 0.5rem;
|
||||
@@ -826,6 +847,11 @@ video {
|
||||
border-end-start-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.rounded-l {
|
||||
border-top-left-radius: 0.25rem;
|
||||
border-bottom-left-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.border {
|
||||
border-width: 1px;
|
||||
}
|
||||
@@ -842,6 +868,10 @@ video {
|
||||
border-inline-start-width: 1px;
|
||||
}
|
||||
|
||||
.border-none {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
.border-gray-200 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(229 231 235 / var(--tw-border-opacity));
|
||||
@@ -907,6 +937,21 @@ video {
|
||||
background-color: rgb(254 249 195 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-gray-900 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(17 24 39 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-gray-700 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-gray-800 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-gradient-to-br {
|
||||
background-image: linear-gradient(to bottom right, var(--tw-gradient-stops));
|
||||
}
|
||||
@@ -933,6 +978,12 @@ video {
|
||||
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
||||
}
|
||||
|
||||
.from-blue-600 {
|
||||
--tw-gradient-from: #2563eb var(--tw-gradient-from-position);
|
||||
--tw-gradient-to: rgb(37 99 235 / 0) var(--tw-gradient-to-position);
|
||||
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
||||
}
|
||||
|
||||
.to-blue-500 {
|
||||
--tw-gradient-to: #3b82f6 var(--tw-gradient-to-position);
|
||||
}
|
||||
@@ -945,15 +996,15 @@ video {
|
||||
--tw-gradient-to: #059669 var(--tw-gradient-to-position);
|
||||
}
|
||||
|
||||
.to-cyan-300 {
|
||||
--tw-gradient-to: #67e8f9 var(--tw-gradient-to-position);
|
||||
}
|
||||
|
||||
.bg-clip-text {
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.p-3 {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
.p-4 {
|
||||
padding: 1rem;
|
||||
}
|
||||
@@ -1012,10 +1063,28 @@ video {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.px-10 {
|
||||
padding-left: 2.5rem;
|
||||
padding-right: 2.5rem;
|
||||
}
|
||||
|
||||
.py-8 {
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
}
|
||||
|
||||
.pb-4 {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.pl-2 {
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
|
||||
.pb-2 {
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.text-2xl {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
@@ -1160,6 +1229,11 @@ video {
|
||||
color: rgb(133 77 14 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-black {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(0 0 0 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.shadow {
|
||||
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
||||
@@ -1178,6 +1252,17 @@ video {
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow-xl {
|
||||
--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.outline-none {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.grayscale {
|
||||
--tw-grayscale: grayscale(100%);
|
||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||
|
||||
@@ -142,10 +142,13 @@
|
||||
"under_construction": "Diese Seite befindet sich gerade im Aufbau"
|
||||
},
|
||||
"footer": {
|
||||
"year": "© 2024 ",
|
||||
"year": " 2024 ",
|
||||
"name": "Tuan-Dat Tran",
|
||||
"rights": ". All Rights Reserved.",
|
||||
"contact": "Kontakt"
|
||||
},
|
||||
"login": {
|
||||
"title": "Login"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"card": {
|
||||
"name": "Tuan-Dat Tran",
|
||||
"gender": "(He/Him)",
|
||||
"text": "Hey there! 👋🏻👋🏼👋🏽👋🏾👋🏿\nWelcome to my little place on the internet\nMy name is Tuan and I'm passionate about Linux, system security, automation, network performance tweaking and all things tech.\nWhile you're here, why don't you check out my projects over on Gitea?",
|
||||
"text": "Hey there! 👋🏻👋🏼👋🏽👋🏾👋🏿\nWelcome to my little place on the internet\nMy name is Tuan and I'm passionate about Linux, system security, automation and all things tech.\nWhile you're here, why don't you check out my projects over on Gitea?",
|
||||
"contact_button": "Get in touch."
|
||||
}
|
||||
},
|
||||
@@ -142,10 +142,13 @@
|
||||
"under_construction": "This page is currently under construction"
|
||||
},
|
||||
"footer": {
|
||||
"year": "© 2024 ",
|
||||
"year": " 2024 ",
|
||||
"name": "Tuan-Dat Tran",
|
||||
"rights": ". All Rights Reserved.",
|
||||
"contact": "Contact"
|
||||
},
|
||||
"login": {
|
||||
"title": "Login"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_sdk::{i18n::use_i18, translate};
|
||||
|
||||
use crate::Route;
|
||||
|
||||
pub fn Footer() -> Element {
|
||||
let i18 = use_i18();
|
||||
|
||||
@@ -13,15 +15,15 @@ pub fn Footer() -> Element {
|
||||
class:"w-full mx-auto p-4 flex items-center justify-between",
|
||||
span {
|
||||
class:"text-sm text-gray-500 sm:text-center dark:text-gray-400",
|
||||
Link {to: Route::Home {}, "©"},
|
||||
{ translate!(i18, "footer.year") },
|
||||
a { href: "#", class: "hover:underline", { translate!(i18, "footer.name") }},
|
||||
Link { class: "hover:underline", to: "#", { translate!(i18, "footer.name") }},
|
||||
{ translate!(i18, "footer.rights") }
|
||||
}
|
||||
ul {
|
||||
class:"flex flex-wrap items-center mt-3 text-sm font-medium text-gray-500 dark:text-gray-400 sm:mt-0",
|
||||
li {
|
||||
Link { to:"mailto:tuan-dat.tran@tudattr.dev", class:"hover:underline", { translate!(i18, "footer.contact") } }
|
||||
},
|
||||
},
|
||||
Link {
|
||||
class:"text-sm text-gray-500 sm:text-center dark:text-gray-400 hover:underline",
|
||||
to:"mailto:tuan-dat.tran@tudattr.dev",
|
||||
{ translate!(i18, "footer.contact") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
80
src/login.rs
Normal file
80
src/login.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_sdk::{i18n::use_i18, translate};
|
||||
|
||||
use crate::components::{H5, HR, P};
|
||||
|
||||
#[component]
|
||||
pub fn Login() -> Element {
|
||||
#[allow(unused_mut)]
|
||||
let mut debug = use_signal(|| "".to_string());
|
||||
|
||||
let default_username = "Enter username here.";
|
||||
let mut username = use_signal(|| default_username.to_string());
|
||||
let mut password = use_signal(|| "".to_string());
|
||||
let i18 = use_i18();
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
class: "flex justify-center items-center w-full",
|
||||
div {
|
||||
class: "text-black bg-gray-800 px-10 py-8 rounded-xl w-screen shadow-xl max-w-sm",
|
||||
div {
|
||||
H5 { { translate!(i18, "login.title") } },
|
||||
}
|
||||
HR {},
|
||||
div {
|
||||
P { "Username" },
|
||||
input {
|
||||
class: if username.read().to_string() == default_username {
|
||||
"pl-2 outline-none border-none w-full rounded-xl text-gray-400"
|
||||
} else {
|
||||
"pl-2 outline-none border-none w-full rounded-xl text-black"
|
||||
},
|
||||
value: "{username}",
|
||||
oninput: move |event| username.set(event.value()),
|
||||
onfocusin: move |_| {
|
||||
if username.read().to_string() == default_username {
|
||||
username.set("".to_string());
|
||||
}
|
||||
},
|
||||
onfocusout: move |_| {
|
||||
if username.read().to_string().is_empty() {
|
||||
username.set(default_username.to_string());
|
||||
}
|
||||
},
|
||||
onkeypress: move |event| async move {
|
||||
if event.key() == Key::Enter {
|
||||
let u = username.read().to_string();
|
||||
let p = password.read().to_string();
|
||||
login(u,p).await.unwrap();
|
||||
}
|
||||
},
|
||||
}
|
||||
div {
|
||||
class: "py-2",
|
||||
P { "Password" },
|
||||
input {
|
||||
class: "pl-2 outline-none border-none w-full rounded-xl text-gray-900",
|
||||
value: "{password}",
|
||||
oninput: move |event| password.set(event.value()),
|
||||
onkeypress: move |event| async move {
|
||||
if event.key() == Key::Enter {
|
||||
let u = username.read().to_string();
|
||||
let p = password.read().to_string();
|
||||
login(u,p).await.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"{debug}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[server(Login)]
|
||||
async fn login(username: String, password: String) -> Result<(), ServerFnError> {
|
||||
println!("Username: {}, Password: {}", username, password);
|
||||
Ok(())
|
||||
}
|
||||
@@ -10,12 +10,18 @@ use layout::footer::Footer;
|
||||
use layout::header::Header;
|
||||
use tracing::Level;
|
||||
|
||||
use axum::routing::*;
|
||||
use axum_session::SessionConfig;
|
||||
use axum_session::SessionStore;
|
||||
use axum_session_auth::AuthConfig;
|
||||
|
||||
pub mod components;
|
||||
mod cv;
|
||||
mod home;
|
||||
mod impressum;
|
||||
mod languages;
|
||||
mod layout;
|
||||
mod login;
|
||||
mod publications;
|
||||
|
||||
use crate::cv::CV;
|
||||
@@ -24,6 +30,7 @@ use crate::impressum::Impressum;
|
||||
use crate::languages::DE_DE;
|
||||
use crate::languages::EN_GB;
|
||||
use crate::layout::Layout;
|
||||
use crate::login::Login;
|
||||
use crate::publications::PublicationsProjects;
|
||||
|
||||
#[derive(Clone, Routable, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
@@ -37,6 +44,8 @@ pub enum Route {
|
||||
PublicationsProjects {},
|
||||
#[route("/resume")]
|
||||
CV {},
|
||||
#[route("/login")]
|
||||
Login {},
|
||||
#[end_layout]
|
||||
#[route("/:..route")]
|
||||
PageNotFound { route: Vec<String> },
|
||||
|
||||
Reference in New Issue
Block a user