From a75de3dbefa4d36f37c58cc313fd3c573e78447f Mon Sep 17 00:00:00 2001 From: schn33fuchs Date: Fri, 22 May 2026 14:04:45 +0200 Subject: [PATCH] README update --- README.cargo.md | 295 ++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 243 ++++++++++++++++++++++++++++++++++++++- src/lib.rs | 2 +- 3 files changed, 535 insertions(+), 5 deletions(-) create mode 100644 README.cargo.md diff --git a/README.cargo.md b/README.cargo.md new file mode 100644 index 0000000..e6ce0fb --- /dev/null +++ b/README.cargo.md @@ -0,0 +1,295 @@ +# Ticketsystem + +A ticket system with backend and frontend components. + +## Components + +- **[Backend](../backend/index.html)** - The server-side API and business logic +- **[Frontend](../frontend/index.html)** - The client-side user interface + +## Usage +### Prerequisite +#### IMPORTANT +Before compiling the programm you have to install the rust toolchain. +For a guide to do this, visit: + +A instance of a postgresql has to be accessible to the backend. Place the connection details in a .env file into the variable `DATABASE_URL` +To setup the tables you either can create them manually by following the sheme specified in `backend/migrations` or apply them with sqlx +To install sqlx run `cargo install sqlx` and then in the `backend` directory run `sqlx migrate run` to create the tables + +### Environment +The .env file has to be in the root directory of the project or in the same directory as the executable + +Keys: +`DATABASE_URL`: Specifying the url and connection details for the database +`TOKEN_SECRET`: The JWT token secret, can theoretically be anything but is more secure when generated with a tool, e.g: +`ORIGIN`: The origin of the frontend, used for CORS rules +`BACKEND_PORT`: The port which the backend should use to run on + +### Backend +The backend can either be run via `cargo run --release` or `cargo build --release` using the correct target architecture, e.g. 'x86_64-unknown-linux-gnu', +the executable will be placed in the `target/release` directory and can then be run via any method + +### Frontend +The HTML code for the frontend can be generated by using `trunk build`. The resulting files will end up in the `frontend/dist` directory and can be served over any webserver supporting wasm +#### NOTE +To install trunk run `cargo install trunk` + +#### IMPORTANT +Requests from the frontend to /api/* have to be proxied to the Backend +Example with nginx and frontend running at localhost:8000 and backend at localhost:9000 : +```nginx +location /api/ { + proxy_pass http://localhost:9000/api; +} +``` + +## Diagramms +### Class Diagram +```mermaid +classDiagram + class backend_src_cookie_Error { + +status: &'static str + +message: String + } + class backend_src_TicketResponse { + +id: i32 + +category: String + +betreff: String + +description: String + +room: i16 + +status: String + +date: chrono::DateTime~chrono::Utc~ + +user_id: i16 + +user_first_name: String + +user_last_name: String + } + class backend_src_User { + +id: i16 + +last_name: String + +first_name: String + +username: String + +is_admin: bool + +pwd: String + } + class backend_src_TicketCreateScheme { + +category: String + +betreff: String + +description: String + +room: i16 + } + class backend_src_TicketUpdateScheme { + +status: String + } + class backend_src_UserUpdateScheme { + +id: i16 + +first_name: String + +last_name: String + +username: String + +make_admin: bool + +new_pwd: String + } + class backend_src_UserCreateScheme { + +first_name: String + +last_name: String + +username: String + +is_admin: bool + +pwd: String + } + class backend_src_LoginScheme { + +username: String + +pwd: String + } + class backend_src_FilteredUser { + +id: i16 + +first_name: String + +last_name: String + +username: String + +is_admin: bool + } + class backend_src_Claims { + +sub: String + +issued: usize + +expires: usize + } + class backend_src_AppState { + -db: PgPool + -env: backend_src_Env + } + class backend_src_Env { + +db_url: String + +token_secret: String + +origin: String + +backend_port: String + +load() backend_src_Env + } + class backend_target_debug_build_chrono-tz-56cec396bfb3cea1_out_FromStr { + +from_str(s:&str) Result~Self, Self::Err~ + } + class backend_target_debug_build_chrono-tz-56cec396bfb3cea1_out_Tz { + +name() &'static str + } + class backend_target_debug_build_chrono-tz-56cec396bfb3cea1_out_Debug { + +fmt(f:&mut Formatter) fmt::Result + } + class backend_target_debug_build_chrono-tz-56cec396bfb3cea1_out_Display { + +fmt(f:&mut Formatter) fmt::Result + } + class backend_target_debug_build_chrono-tz-56cec396bfb3cea1_out_TimeSpans { + +timespans() FixedTimespanSet + } + class backend_target_debug_build_chrono-tz-261584f9cc573a32_out_FromStr { + +from_str(s:&str) Result~Self, Self::Err~ + } + class backend_target_debug_build_chrono-tz-261584f9cc573a32_out_Tz { + +name() &'static str + } + class backend_target_debug_build_chrono-tz-261584f9cc573a32_out_Debug { + +fmt(f:&mut Formatter) fmt::Result + } + class backend_target_debug_build_chrono-tz-261584f9cc573a32_out_Display { + +fmt(f:&mut Formatter) fmt::Result + } + class backend_target_debug_build_chrono-tz-261584f9cc573a32_out_TimeSpans { + +timespans() FixedTimespanSet + } + class frontend_src_pages_TicketCreateScheme { + +category: String + +betreff: String + +description: String + +room: i16 + } + class frontend_src_pages_TicketUpdateScheme { + +status: String + } + class frontend_src_pages_Ticket { + +id: i32 + +category: String + +betreff: String + +description: String + +room: i16 + +status: String + +date: chrono::DateTime~chrono::Utc~ + +user_id: i16 + +user_first_name: String + +user_last_name: String + } + class frontend_src_pages_TicketProps { + +id: i32 + } + class frontend_src_pages_ActiveUser { + +id: Option~i16~ + +is_admin: bool + } + class frontend_src_pages_ApiError { + -message: String + -_status: String + } + class frontend_src_pages_SidebarExpandState { + +ticket_open: bool + +users_open: bool + } + class frontend_src_pages_Default { + +default() Self + } + class frontend_src_pages_SidebarState { + +expand: frontend_src_pages_SidebarExpandState + +set_tickets_open: Callback~bool~ + +toggle_tickets: Callback~()~ + +set_users_open: Callback~bool~ + +toggle_users: Callback~()~ + +new(expand:frontend_src_pages_SidebarExpandState, set_tickets_open:Callback~bool~, toggle_tickets:Callback~()~, set_users_open:Callback~bool~, toggle_users:Callback~()~) Self + } + class frontend_src_pages_SidebarProps { + +children: Children + } + class frontend_src_pages_TicketPartial { + -date: DateTime~Utc~ + -room: i16 + -user_id: i16 + } + class frontend_src_pages_UserPartial { + -id: i16 + -first_name: String + -last_name: String + } + class frontend_src_pages_RoomTotalsProps { + -tickets: Vec~frontend_src_pages_TicketPartial~ + } + class frontend_src_pages_UserTotalProps { + -users: Vec~frontend_src_pages_UserPartial~ + -tickets: Vec~frontend_src_pages_TicketPartial~ + } + class frontend_src_pages_AdminSetupScheme { + +first_name: String + +last_name: String + +username: String + +pwd: String + } + class frontend_src_pages_UserCreateScheme { + +first_name: String + +last_name: String + +username: String + +is_admin: bool + +pwd: String + } + class frontend_src_pages_LoginScheme { + +username: String + +pwd: String + } + class frontend_src_pages_UserUpdateScheme { + +id: i16 + +first_name: String + +last_name: String + +username: String + +make_admin: bool + +new_pwd: String + } + class frontend_src_pages_FilteredUser { + +id: i16 + +first_name: String + +last_name: String + +username: String + +is_admin: bool + } + class frontend_src_pages_UserProps { + +id: i16 + } + class frontend_src_pages_ApiError { + -message: String + -_status: String + } + class frontend_src_AuthState { + +is_authenticated: Option~bool~ + +is_admin: Option~bool~ + } + class frontend_src_ProtectedRouteProps { + +children: Children + +admin_page: bool + } + class frontend_src_SidebarShellProps { + +children: Children + } + class frontend_src_AdminCheckWrapperProps { + +children: Children + } + backend_src_AppState --> backend_src_Env + backend_src_Env ..> backend_src_Env + frontend_src_pages_SidebarState --> frontend_src_pages_SidebarExpandState + frontend_src_pages_RoomTotalsProps --> frontend_src_pages_TicketPartial + frontend_src_pages_UserTotalProps --> frontend_src_pages_UserPartial + frontend_src_pages_UserTotalProps --> frontend_src_pages_TicketPartial + +``` + + +## Usage of AI + +Github Copilot CLI was used with the model Claude Haiku 4.5 to generate most of the documentation: + +### Prompt +Generate comments for cargo doc describing the indivilual components and create links to relevant structs, functions etc. + +### Output +The comments with `///` or `//!` +I've gone over most of it and modified it to my needs and opinions diff --git a/README.md b/README.md index 24f2ac3..c7ccc08 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,8 @@ A ticket system with backend and frontend components. ## Components -- **[Backend](../backend/index.html)** - The server-side API and business logic -- **[Frontend](../frontend/index.html)** - The client-side user interface -> [!NOTE] -> Links only works in docs.rs +- **[Backend]** - The server-side API and business logic +- **[Frontend]** - The client-side user interface ## Usage ### Prerequisite @@ -46,6 +44,243 @@ The HTML code for the frontend can be generated by using `trunk build`. The resu > } > ``` +## Diagramms +### Class Diagramm +```mermaid +classDiagram + class backend_src_cookie_Error { + +status: &'static str + +message: String + } + class backend_src_TicketResponse { + +id: i32 + +category: String + +betreff: String + +description: String + +room: i16 + +status: String + +date: chrono::DateTime~chrono::Utc~ + +user_id: i16 + +user_first_name: String + +user_last_name: String + } + class backend_src_User { + +id: i16 + +last_name: String + +first_name: String + +username: String + +is_admin: bool + +pwd: String + } + class backend_src_TicketCreateScheme { + +category: String + +betreff: String + +description: String + +room: i16 + } + class backend_src_TicketUpdateScheme { + +status: String + } + class backend_src_UserUpdateScheme { + +id: i16 + +first_name: String + +last_name: String + +username: String + +make_admin: bool + +new_pwd: String + } + class backend_src_UserCreateScheme { + +first_name: String + +last_name: String + +username: String + +is_admin: bool + +pwd: String + } + class backend_src_LoginScheme { + +username: String + +pwd: String + } + class backend_src_FilteredUser { + +id: i16 + +first_name: String + +last_name: String + +username: String + +is_admin: bool + } + class backend_src_Claims { + +sub: String + +issued: usize + +expires: usize + } + class backend_src_AppState { + -db: PgPool + -env: backend_src_Env + } + class backend_src_Env { + +db_url: String + +token_secret: String + +origin: String + +backend_port: String + +load() backend_src_Env + } + class backend_target_debug_build_chrono-tz-56cec396bfb3cea1_out_FromStr { + +from_str(s:&str) Result~Self, Self::Err~ + } + class backend_target_debug_build_chrono-tz-56cec396bfb3cea1_out_Tz { + +name() &'static str + } + class backend_target_debug_build_chrono-tz-56cec396bfb3cea1_out_Debug { + +fmt(f:&mut Formatter) fmt::Result + } + class backend_target_debug_build_chrono-tz-56cec396bfb3cea1_out_Display { + +fmt(f:&mut Formatter) fmt::Result + } + class backend_target_debug_build_chrono-tz-56cec396bfb3cea1_out_TimeSpans { + +timespans() FixedTimespanSet + } + class backend_target_debug_build_chrono-tz-261584f9cc573a32_out_FromStr { + +from_str(s:&str) Result~Self, Self::Err~ + } + class backend_target_debug_build_chrono-tz-261584f9cc573a32_out_Tz { + +name() &'static str + } + class backend_target_debug_build_chrono-tz-261584f9cc573a32_out_Debug { + +fmt(f:&mut Formatter) fmt::Result + } + class backend_target_debug_build_chrono-tz-261584f9cc573a32_out_Display { + +fmt(f:&mut Formatter) fmt::Result + } + class backend_target_debug_build_chrono-tz-261584f9cc573a32_out_TimeSpans { + +timespans() FixedTimespanSet + } + class frontend_src_pages_TicketCreateScheme { + +category: String + +betreff: String + +description: String + +room: i16 + } + class frontend_src_pages_TicketUpdateScheme { + +status: String + } + class frontend_src_pages_Ticket { + +id: i32 + +category: String + +betreff: String + +description: String + +room: i16 + +status: String + +date: chrono::DateTime~chrono::Utc~ + +user_id: i16 + +user_first_name: String + +user_last_name: String + } + class frontend_src_pages_TicketProps { + +id: i32 + } + class frontend_src_pages_ActiveUser { + +id: Option~i16~ + +is_admin: bool + } + class frontend_src_pages_ApiError { + -message: String + -_status: String + } + class frontend_src_pages_SidebarExpandState { + +ticket_open: bool + +users_open: bool + } + class frontend_src_pages_Default { + +default() Self + } + class frontend_src_pages_SidebarState { + +expand: frontend_src_pages_SidebarExpandState + +set_tickets_open: Callback~bool~ + +toggle_tickets: Callback~()~ + +set_users_open: Callback~bool~ + +toggle_users: Callback~()~ + +new(expand:frontend_src_pages_SidebarExpandState, set_tickets_open:Callback~bool~, toggle_tickets:Callback~()~, set_users_open:Callback~bool~, toggle_users:Callback~()~) Self + } + class frontend_src_pages_SidebarProps { + +children: Children + } + class frontend_src_pages_TicketPartial { + -date: DateTime~Utc~ + -room: i16 + -user_id: i16 + } + class frontend_src_pages_UserPartial { + -id: i16 + -first_name: String + -last_name: String + } + class frontend_src_pages_RoomTotalsProps { + -tickets: Vec~frontend_src_pages_TicketPartial~ + } + class frontend_src_pages_UserTotalProps { + -users: Vec~frontend_src_pages_UserPartial~ + -tickets: Vec~frontend_src_pages_TicketPartial~ + } + class frontend_src_pages_AdminSetupScheme { + +first_name: String + +last_name: String + +username: String + +pwd: String + } + class frontend_src_pages_UserCreateScheme { + +first_name: String + +last_name: String + +username: String + +is_admin: bool + +pwd: String + } + class frontend_src_pages_LoginScheme { + +username: String + +pwd: String + } + class frontend_src_pages_UserUpdateScheme { + +id: i16 + +first_name: String + +last_name: String + +username: String + +make_admin: bool + +new_pwd: String + } + class frontend_src_pages_FilteredUser { + +id: i16 + +first_name: String + +last_name: String + +username: String + +is_admin: bool + } + class frontend_src_pages_UserProps { + +id: i16 + } + class frontend_src_pages_ApiError { + -message: String + -_status: String + } + class frontend_src_AuthState { + +is_authenticated: Option~bool~ + +is_admin: Option~bool~ + } + class frontend_src_ProtectedRouteProps { + +children: Children + +admin_page: bool + } + class frontend_src_SidebarShellProps { + +children: Children + } + class frontend_src_AdminCheckWrapperProps { + +children: Children + } + backend_src_AppState --> backend_src_Env + backend_src_Env ..> backend_src_Env + frontend_src_pages_SidebarState --> frontend_src_pages_SidebarExpandState + frontend_src_pages_RoomTotalsProps --> frontend_src_pages_TicketPartial + frontend_src_pages_UserTotalProps --> frontend_src_pages_UserPartial + frontend_src_pages_UserTotalProps --> frontend_src_pages_TicketPartial + +``` diff --git a/src/lib.rs b/src/lib.rs index 7913c79..a23a1d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1 @@ -#![doc = include_str!("../README.md")] +#![doc = include_str!("../README.cargo.md")]