Initial commit

Signed-off-by: Tuan-Dat Tran <tuan-dat.tran@tudattr.dev>
master
Tuan-Dat Tran 2024-04-29 22:48:53 +02:00
commit 75c64a7227
27 changed files with 7453 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
# Generated by Cargo
# will have compiled files and executables
/target/
/dist/
/static/
/.dioxus/
/node_modules/
# These are backup files generated by rustfmt
**/*.rs.bk

3470
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

23
Cargo.toml Normal file
View File

@ -0,0 +1,23 @@
[package]
name = "athome"
version = "0.1.0"
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"] }
# Debug
tracing = "0.1.40"
dioxus-logger = "0.5.0"
manganis = "0.2.2"
dioxus-free-icons = { version = "0.8", features = ["font-awesome-brands"] }
[features]
default = []
server = ["dioxus/axum"]
web = ["dioxus/web"]

43
Dioxus.toml Normal file
View File

@ -0,0 +1,43 @@
[application]
# App (Project) Name
name = "athome"
# Dioxus App Default Platform
# desktop, web
default_platform = "web"
# `build` & `serve` dist path
out_dir = "dist"
# resource (assets) file folder
asset_dir = "assets"
[web.app]
# HTML title tag content
title = "athome"
[web.watcher]
# when watcher trigger, regenerate the `index.html`
reload_html = true
# which files or dirs will be watcher monitoring
watch_path = ["src", "assets"]
# include `assets` in web platform
[web.resource]
# CSS style file
style = ["tailwind.css"]
# Javascript code file
script = []
[web.resource.dev]
# Javascript code file
# serve: [dev-server] only
script = []

17
Dockerfile Normal file
View File

@ -0,0 +1,17 @@
FROM rust:1.77.2 as builder
WORKDIR /athome/
RUN cargo install dioxus-cli@^0.5
RUN apt update && apt install nodejs npm -y && rm -rf /var/lib/apt/lists/*
RUN npm install -D tailwindcss
FROM builder
WORKDIR /athome/
COPY ./src/ ./src/
COPY ./assets/ ./assets/
COPY ./Cargo.toml ./Cargo.toml
COPY ./input.css ./input.css
COPY ./Dioxus.toml ./Dioxus.toml
COPY ./tailwind.config.js ./tailwind.config.js
RUN npx tailwindcss -i ./input.css -o ./assets/tailwind.css
RUN dx build --platform fullstack --release
ENTRYPOINT [ "./dist/athome" ]

7
README.md Normal file
View File

@ -0,0 +1,7 @@
# @Home
My personal website.
## Screenshot
[[./resources/screenshot.png]]

BIN
assets/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

20
assets/header.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

40
assets/main.css Normal file
View File

@ -0,0 +1,40 @@
body {
background-color: #111216;
}
#main {
margin: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif
}
#links {
width: 400px;
text-align: left;
font-size: x-large;
color: white;
display: flex;
flex-direction: column;
}
#links a {
color: white;
text-decoration: none;
margin-top: 20px;
margin: 10px;
border: white 1px solid;
border-radius: 5px;
padding: 10px;
}
#links a:hover {
background-color: #1f1f1f;
cursor: pointer;
}
#header {
max-width: 1200px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
assets/pictures/comfy.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

1657
assets/tailwind.css Normal file

File diff suppressed because it is too large Load Diff

3
input.css Normal file
View File

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

1379
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

5
package.json Normal file
View File

@ -0,0 +1,5 @@
{
"devDependencies": {
"tailwindcss": "^3.4.3"
}
}

BIN
resources/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

99
src/components/mod.rs Normal file
View File

@ -0,0 +1,99 @@
use dioxus::prelude::*;
#[derive(PartialEq, Props, Clone)]
pub struct PProps {
#[props(default = "".to_string())]
pub class: String,
pub children: Element,
}
#[component]
pub fn P(props: PProps) -> Element {
rsx! {
div {
class: "{props.class}",
p {
class: "mb-2 font-normal text-gray-900 dark:text-white",
{props.children}
},
}
}
}
#[component]
pub fn H1(props: PProps) -> Element {
rsx! {
div {
class: "{props.class}",
h1 {
class: "mb-4 text-3xl font-extrabold text-gray-900 dark:text-white md:text-5xl lg:text-6xl",
span {
class: "text-transparent bg-clip-text bg-gradient-to-r to-emerald-600 from-sky-400",
{props.children}
}
}
}
}
}
pub fn H4(props: PProps) -> Element {
rsx! {
div {
class: "{props.class}",
class: "mb-4",
h3 {
class: "text-lg uppercase text-cyan-600 dark:text-cyan-400 tracking-widest mb-4 font-bold",
{props.children}
}
}
}
}
#[component]
pub fn H5(props: PProps) -> Element {
rsx! {
div {
class: "{props.class}",
h5 {
class: "mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white",
{props.children}
}
}
}
}
#[derive(PartialEq, Props, Clone)]
pub struct CardProp {
#[props(default = "".to_string())]
class: String,
children: Element,
}
pub fn Card(prop: CardProp) -> Element {
rsx! {
div {
class: "flex flex-col py-10 items-center min-w-fit",
div {
class: "text-white bg-gradient-to-r from-purple-500 to-blue-500 hover:bg-gradient-to-br focus:ring-4 focus:outline-none focus:ring-cyan-300 dark:focus:ring-cyan-800 rounded-lg px-5 py-2.5 min-w-fit max-w-8 center",
{ prop.children }
}
}
}
}
pub fn UnderConstruction() -> Element {
rsx! {
div {
class:"rounded flex justify-between w-full p-4 border-b border-gray-200 bg-gray-50 dark:bg-gray-700 dark:border-gray-600 m-16",
div {
class:"flex items-center mx-auto",
p {
class:"flex items-center text-sm font-normal text-gray-500 dark:text-gray-400",
span {
"This site is currenlty under construction",
}
}
}
}
}
}

264
src/cv.rs Normal file
View File

@ -0,0 +1,264 @@
use dioxus::prelude::*;
use crate::components::H4;
#[component]
pub fn CV() -> Element {
rsx! {
div {
class: "flex flex-col ",
Introduction {},
hr { class:"h-px my-8 bg-gray-200 border-0 dark:bg-gray-700"},
div {
class: "flex justify-between",
WorkExperience {},
Miscellaneous {},
},
hr { class:"h-px my-8 bg-gray-200 border-0 dark:bg-gray-700"},
Socials {}
}
}
}
fn Introduction() -> Element {
rsx! {
div {
class: "flex",
img {
class: "rounded-full w-16 h-16 mx-16",
src: "/pictures/portrait.webp"
}
P {
"While studying for my bachelors degree I collected a lot of
industry and academic experience. My professional and personal
intererests are DevOps/IaC, Systems/Software Security and Computer
Networking. All of which I deepen in personal projects such as my
homelab and CTF challenges."
}
}
}
}
fn WorkExperience() -> Element {
rsx! {
div {
class: "ms-8 max-w-3/4",
H4 { "Work Experience" },
ol {
class:"relative border-s border-gray-200 dark:border-gray-700",
CVEntry {time: "2021 - now", title: "Research Assistant @ UDE",
technologies: vec!["Rust".to_string(), "Python".to_string(), "P4".to_string(), "Linux".to_string(), "Docker".to_string(), "Kubernetes".to_string()],
description:
"While working for the Network Communication System Research
Group at the University Duisburg-Essen as a research assistant
I've assisted in research around software defined networking,
5G, congestion control algorithms and federated machine learning.
I've established and managed the research groups on-premise and
cloud infractructure, inventory system and online presence."
},
CVEntry {time: "2021 - 2022", title: "Mentoring @ UDE",
technologies: vec!["Powerpoint".to_string()],
description:
"As a mentor for students enrolling into the computer
science program of the University Duisburg-Essen I
introduced groups of ~20 freshmen to their new academic
environment at the beginning of each semester. Offering
additional organizational and technical guidance for an
two-semesters."
},
CVEntry {time: "2018 - 2020", title: "Software Engineer @ gefeba Engineering GmbH",
technologies: vec!["C#".to_string(), "Angular".to_string(), "bootstrap".to_string(), "Entity Framework".to_string()],
description:
"As a software engineer at gefeba Engineering I worked
worked the companies main software product, which was a
frame-based data exchange system to monitor industry
machinary using C# and Entity Framework. Another project
I worked on was a real time log visualization application
for the same machinary."
},
CVEntry {time: "2016 - 2019", title: "Student Council Member @ UDE",
technologies: vec!["Linux".to_string(), "Networking".to_string(), "LaTeX".to_string()],
description:
"As a student council member I participated in faculty
committees and organized social events. My
main responsabilities as a member were the management
of the IT infrastructure and supporting students, be it
organizationally or subject-specific."
},
CVEntry {time: "2013 - 2015", title: "Software Engineer @ gefeba Engineering GmbH",
technologies: vec!["C#".to_string(), "HTML".to_string(), "Javascript".to_string(), "CSS".to_string()],
description:
"After a school internship I got offered a job as a
Software Engineer. I mostly worked on internal ERP
projects, designed a tool which aided in managing
project related mail traffic and worked on the
internal master data management tool."
},
}
},
}
}
fn Miscellaneous() -> Element {
rsx! {
div {
class: "",
Education {},
Skills {},
Languages {},
Interests {},
}
}
}
fn Education() -> Element {
rsx! {
div {
H4 {"Education"},
Entry {
title: "BSc Systems Engineering",
time { class:"mb-1 text-sm font-normal leading-none text-gray-400 dark:text-gray-500", "2015 - now"},
},
}
}
}
fn Skills() -> Element {
rsx! {
div {
H4 {"Skills"},
Entry {
title: "DevOps",
P { "Ansible" },
P { "Kubernetes" },
P { "GitOps" },
}Entry {
title: "Software Development",
P { "Rust" },
P { "Python" },
P { "Java" },
}
}
}
}
fn Languages() -> Element {
rsx! {
div {
H4 {"Languages"},
Entry {
P { "German (Native)" },
P { "English (C2)" },
P { "Vietnamese (B1)" },
P { "Japanese (A1)" },
}
}
}
}
fn Interests() -> Element {
rsx! {
div {
H4 {"Interests"}
Entry {
P { "Coffee" },
P { "Mechanical Keyboards" },
P { "Tech/IT" },
P { "Music" },
}
}
}
}
#[derive(PartialEq, Props, Clone)]
struct EntryProps {
#[props(default = "mb-4".to_string())]
class: String,
#[props(default = "".to_string())]
title: String,
children: Element,
}
fn Entry(props: EntryProps) -> Element {
rsx! {
div {
class: "{props.class}",
h6 { class: "font-semibold text-gray-900 dark:text-white", "{props.title}"}
{props.children},
}
}
}
#[derive(PartialEq, Props, Clone)]
struct CVEntryProps {
#[props(default = "mb-10 ms-4".to_string())]
class: String,
time: String,
title: String,
technologies: Vec<String>,
#[props(default = "".to_string())]
description: String,
children: Element,
}
fn CVEntry(props: CVEntryProps) -> Element {
rsx! {
li {
class: "max-w-xl",
class: "{props.class}",
div { class:"absolute w-3 h-3 bg-gray-200 rounded-full mt-1.5 -start-1.5 border border-white dark:border-gray-900 dark:bg-gray-700"},
time { class:"mb-1 text-sm font-normal leading-none text-gray-400 dark:text-gray-500", "{props.time}"},
h6 { class: "text-lg font-semibold text-gray-900 dark:text-white", "{props.title}"}
for tech in props.technologies {
RandomBadge {text: "{tech}"}
}
p { class:"text-base font-normal text-gray-500 dark:text-gray-400", "{props.description}"},
{props.children}
}
}
}
#[component]
fn RandomBadge(text: String) -> Element {
let badge_color = random_badge_color(text.len());
rsx! {
span {
class:"text-xs font-medium me-2 px-2.5 py-0.5 rounded ",
class: "{badge_color}",
"{text}"
}
}
}
fn random_badge_color(seed: usize) -> String {
let colors = [
"bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300",
"bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300",
"bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300",
"bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300",
"bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300",
"bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-300",
"bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-300",
"bg-pink-100 text-pink-800 dark:bg-pink-900 dark:text-pink-300",
];
colors[seed % colors.len()].to_string()
}
fn Socials() -> Element {
rsx! {
div {
"todo!()"
}
}
}
#[component]
fn P(children: Element) -> Element {
rsx! {
p {
class: "text-base font-normal text-gray-500 dark:text-gray-400",
{children},
}
}
}

61
src/home.rs Normal file
View File

@ -0,0 +1,61 @@
use crate::components::{Card, H5, P};
use dioxus::prelude::*;
#[component]
pub fn Home() -> Element {
rsx! {
Card {
div {
class: "p-5",
div {
class: "pb-4",
div {
class: "flex justify-between",
Picture {src: "/pictures/comfy.webp"},
}
}
H5 { "Tuan-Dat Tran", span { class: "text-grey-600 dark:text-grey-500 text-lg", " (He/Him)" } },
div {
class: "py-4",
P { "Hey there! 👋🏻👋🏼👋🏽👋🏾👋🏿" },
P { "Welcome to my little place on the internet." },
P { "While you're here, why don't you check out my other projects over on my ",
Link {
to: "https://git.tudattr.dev/explore/repos",
new_tab: true,
class: "inline-flex items-center font-medium hover:underline",
"gitea"},
"?"
},
P { "I also offer IT-related consulting." },
P { "Have a look at my CV and contact me if you're interested." },
},
Link {
to: "mailto:tuan-dat.tran@tudattr.dev",
class: "w-fit relative inline-flex items-center justify-center p-1 mb-2 me-2 overflow-hidden text-sm font-medium text-gray-900 rounded-lg group bg-gradient-to-br from-green-400 to-blue-600 group-hover:from-green-400 group-hover:to-blue-600 hover:text-white dark:text-white w-fill",
p {
class: "p-1",
"Get in touch."
}
},
}
},
}
}
#[derive(PartialEq, Props, Clone)]
struct PictureProp {
#[props(default = "".to_string())]
class: String,
src: String,
}
fn Picture(prop: PictureProp) -> Element {
rsx! {
img {
class: "w-24 h-24 rounded-full shadow-lg",
src: "{prop.src}",
alt: "",
},
}
}

50
src/impressum.rs Normal file
View File

@ -0,0 +1,50 @@
use dioxus::prelude::{server_fn::error::ServerFnError, *};
use tracing::info;
use crate::components::{H1, P};
#[component]
pub fn Impressum() -> Element {
let mut show_impressum = use_signal(|| false);
let mut check_impressum = move || {
if !show_impressum() {
show_impressum.set(true);
}
};
rsx! {
if show_impressum() {
div {
class: "flex flex-col items-center",
H1 { "Impressum" },
P { "Tuan-Dat Tran" },
P { "c/o AutorenServices.de" },
P { "Birkenallee 24" },
P { "36037 Fulda" },
}
hr { class:"h-px my-8 bg-gray-200 border-0 dark:bg-gray-700"}
div {
class: "flex flex-col items-center",
P { "tuan-dat.tran@tudattr.dev" },
P { "+49 176 83468388" },
}
} else {
div {
class: "flex flex-col items-center p-3",
button {
onclick: move |_| {
info!("Showing impressum.");
check_impressum();
},
H1 { "Show Impressum" },
},
}
}
}
}
#[server(GetImpressum)]
pub async fn get_impressum() -> Result<(), ServerFnError> {
Ok(())
}

76
src/layout/footer.rs Normal file
View File

@ -0,0 +1,76 @@
use dioxus::prelude::*;
use crate::components::H1;
pub fn Footer() -> Element {
rsx! {
div {
ToolsUsed {},
footer {
class:"bg-white rounded-lg shadow dark:bg-gray-800 my-4:wa
",
div {
class:"w-full mx-auto max-w-screen-xl p-4 md:flex md:items-center md:justify-between",
span {
class:"text-sm text-gray-500 sm:text-center dark:text-gray-400",
"© 2024 ",
a { href: "#", class: "hover:underline", "Tuan-Dat Tran"},
". All Rights Reserved."
}
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", "Contact" }
},
}
}
}
}
}
}
fn ToolsUsed() -> Element {
rsx! {
div {
class:"items-center bg-white rounded-lg shadow dark:bg-gray-800 p-4 my-4",
div {
H1 {class: "justify-center", "Tools used" },
}
div {
class: "flex h-fill overflow-x-auto",
Logo {
src: "https://raw.githubusercontent.com/SAWARATSUKI/ServiceLogos/main/Rust/Rust.png",
alt: "Rust"
},
Logo {
src: "https://raw.githubusercontent.com/SAWARATSUKI/ServiceLogos/main/Tailwindcss/Tailwindcss6.png",
alt: "Tailwindcss"
},
Logo {
src: "https://raw.githubusercontent.com/SAWARATSUKI/ServiceLogos/main/Html/HTML.png",
alt: "HTML"
},
Logo {
src: "https://raw.githubusercontent.com/Aikoyori/ProgrammingVTuberLogos/main/Docker/DockerLogo.png",
alt: "Docker"
},
Logo {
src: "https://raw.githubusercontent.com/Aikoyori/ProgrammingVTuberLogos/main/Neovim/NeovimLogo.png",
alt: "NeoVim"
},
}
}
}
}
#[component]
fn Logo(src: String, alt: String) -> Element {
rsx! {
img {
class: "h-auto max-w-40 transition-all duration-300 rounded-lg cursor-pointer filter grayscale hover:grayscale-0",
src: "{src}",
alt: "{alt}"
}
}
}

41
src/layout/header.rs Normal file
View File

@ -0,0 +1,41 @@
use dioxus::prelude::*;
use crate::Route;
pub fn Header() -> Element {
rsx! {
nav {
div { class:" flex flex-wrap items-center justify-between mx-auto p-4",
Link {
to: Route::Home {},
class:"flex items-center space-x-3 rtl:space-x-reverse",
img { src:"/pictures/ClackCat_t.webp", class:"rounded-full h-8", alt:"Flowbite Logo" },
span { class:"self-center text-2xl font-semibold whitespace-nowrap dark:text-white", "" }
}
button {
r#type:"button",
class:"inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600",
aria_controls:"navbar-default",
aria_expanded:"false",
span { class:"sr-only", "Open main menu" },
}
div { class:"hidden w-full md:block md:w-auto", id:"navbar-default",
ul { class:"font-medium flex flex-col p-4 md:p-0 mt-4 border border-gray-100 rounded-lg bg-gray-50 md:flex-row md:space-x-8 rtl:space-x-reverse md:mt-0 md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700",
li {
Link { to: Route::Home {}, class:"block py-2 px-3 text-white bg-blue-700 rounded md:bg-transparent md:text-blue-700 md:p-0 dark:text-white md:dark:text-blue-500", "Home" }
}
li {
Link { to: Route::CV {}, class:"block py-2 px-3 text-white bg-blue-700 rounded md:bg-transparent md:text-blue-700 md:p-0 dark:text-white md:dark:text-blue-500", "CV" }
}
li {
Link { to: Route::Publications {}, class:"block py-2 px-3 text-white bg-blue-700 rounded md:bg-transparent md:text-blue-700 md:p-0 dark:text-white md:dark:text-blue-500", "Publications/Projects" }
}
li {
Link { to: Route::Impressum {}, class:"block py-2 px-3 text-white bg-blue-700 rounded md:bg-transparent md:text-blue-700 md:p-0 dark:text-white md:dark:text-blue-500", "About" }
}
}
}
}
}
}
}

24
src/layout/mod.rs Normal file
View File

@ -0,0 +1,24 @@
use dioxus::prelude::*;
mod footer;
mod header;
use crate::{Body, Route};
use footer::Footer;
use header::Header;
pub fn Layout() -> Element {
rsx! {
div {
class: "flex justify-center",
div {
class: "max-w-screen-xl flex-col" ,
Header {},
Body {
Outlet::<Route> {},
}
Footer {},
}
}
}
}

81
src/main.rs Normal file
View File

@ -0,0 +1,81 @@
#![allow(non_snake_case)]
use dioxus::prelude::*;
use tracing::Level;
pub mod components;
mod cv;
mod home;
mod impressum;
mod layout;
mod publications;
use crate::cv::CV;
use crate::home::Home;
use crate::impressum::Impressum;
use crate::layout::Layout;
use crate::publications::Publications;
#[derive(Clone, Routable, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum Route {
#[layout(Layout)]
#[route("/")]
Home {},
#[route("/impressum")]
Impressum {},
#[route("/publications")]
Publications {},
#[route("/resume")]
CV {},
#[end_layout]
#[route("/:..route")]
PageNotFound { route: Vec<String> },
}
fn main() {
dioxus_logger::init(Level::INFO).expect("failed to init logger");
launch(App);
}
fn App() -> Element {
rsx! {
meta {
name: "robots",
content: "noindex",
},
div {
class: "bg-white dark:bg-gray-900 min-h-screen",
Router::<Route> {},
}
}
}
#[component]
fn PageNotFound(route: Vec<String>) -> Element {
rsx! {
div {
class: "h-screen flex items-center justify-center",
img {
class: "size-auto",
src: "https://raw.githubusercontent.com/SAWARATSUKI/ServiceLogos/main/404Notfound/NotFound.png"
}
}
}
}
#[derive(PartialEq, Props, Clone)]
pub struct BodyProp {
children: Element,
}
pub fn Body(prop: BodyProp) -> Element {
rsx! {
div {
class: "flex justify-center my-4",
div {
class: "max-w-screen-md min-w-full",
{prop.children}
}
}
}
}

74
src/publications.rs Normal file
View File

@ -0,0 +1,74 @@
use dioxus::prelude::*;
use crate::components::UnderConstruction;
#[component]
pub fn Publications() -> Element {
rsx! {
UnderConstruction { },
div {
class: "flex gap-4 items-center",
Publication {
doi: "https://doi.org/10.48550/arXiv.2307.09639",
conference: "IEEE LCN 2023",
title: "RPM: Reverse Path Congestion Marking on P4 Programmable Switches",
authors: "N. Baganal-Krishna, T.-D. Tran, R. Kundel and A. Rizk",
description: "
In this paper, we present Reverse Path Congestion Marking
(RPM) to accelerate the reaction to network congestion
events without changing the end-host stack. RPM decouples
the conges- tion signal from the downstream path after the
bottleneck while maintaining the stability of the
congestion control loop. We show that RPM improves
throughput fairness for RTT- heterogeneous TCP flows as
well as the flow completion time, especially for small
Data Center TCP (DCTCP) flows. around P4 programmable ASIC
switches."
}
Publication {
doi: "https://git.tudattr.dev/AISE/seminar/src/branch/main/paper.pdf",
conference: "Seminar",
title: "Overview of IoT Fuzzing Techniques",
authors: "Tuan-Dat Tran",
description: "
In this paper, we are comparing techniques used
by IoT fuzzers to circumvent the challenges presented
by IoT devices and the constraints of the
solutions proposed by the IoT fuzzers."
}
}
}
}
#[derive(Clone, PartialEq, Props)]
struct PublicationProp {
#[props(default = "".to_string())]
doi: String,
authors: String,
title: String,
conference: String,
#[props(default = "".to_string())]
description: String,
}
fn Publication(prop: PublicationProp) -> Element {
rsx! {
Link {
class:"block max-w-sm p-6 bg-white border border-gray-200 rounded-lg shadow hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700",
to:"{prop.doi}",
new_tab: true,
h5 {
class:"mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white",
"{prop.title}",
},
p {
class:"font-normal text-gray-700 dark:text-gray-400",
"{prop.authors}",
}
p {
class:"font-normal text-gray-700 dark:text-gray-400",
"{prop.description}",
}
}
}
}

9
tailwind.config.js Normal file
View File

@ -0,0 +1,9 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
mode: "all",
content: ["./src/**/*.{rs,html,css}", "./dist/**/*.html"],
theme: {
extend: {},
},
plugins: [],
};