Skip to content

Commit

Permalink
feat: add dashboard page skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
JacksonVirgo committed Jul 23, 2024
1 parent 29308a2 commit 22af8c9
Show file tree
Hide file tree
Showing 16 changed files with 331 additions and 113 deletions.
2 changes: 1 addition & 1 deletion src/components/forms/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub fn gen_input(raw_input: InputType) -> Markup {
}
InputType::SelectMenuInput(input) => {
html! {
select."w-full px-4 py-2 border border-gray-300 rounded text-white bg-zinc-700" name=(input.name) id=(input.name) placeholder=(input.placeholder) {
select."w-full px-4 py-2 border border-gray-300 rounded text-white bg-zinc-700" name=(input.name) id=(input.name) placeholder=(input.placeholder) required=(input.is_required.unwrap_or(false)) {
@for option in &input.options {
option value=(option.clone()) selected=(Some(option.clone()) == input.default_value.clone()) {
(option)
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use dotenv::dotenv;
use mime;
use sqlx::{postgres::PgPoolOptions, Pool, Postgres};
mod components;
mod models;
mod routes;
mod scraping;

Expand Down
1 change: 1 addition & 0 deletions src/models/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod thread;
45 changes: 45 additions & 0 deletions src/models/thread.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use crate::AppState;
use actix_web::web::Data;
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use sqlx::{self, FromRow};

#[derive(Serialize, Deserialize, FromRow, Debug)]
pub struct Thread {
id: i32,
thread_id: String,
title: Option<String>,
queue: Option<String>,
queue_index: Option<i32>,
created_at: Option<NaiveDateTime>,
}

pub async fn get_thread(app_state: Data<AppState>, thread_id: String) -> Option<Thread> {
let db = &app_state.db;
match sqlx::query_as!(
Thread,
"SELECT * FROM threads WHERE thread_id = $1",
thread_id
)
.fetch_optional(db)
.await
{
Ok(Some(thread)) => Some(thread),
_ => None,
}
}

// pub async fn create_thread(app_state: Data<AppState>, thread_id: String) -> Option<Thread> {
// let db = &app_state.db;
// match sqlx::query_as!(
// Thread,
// "INSERT INTO threads (thread_id) VALUES ($1) RETURNING *",
// thread_id
// )
// .fetch_one(db)
// .await
// {
// Ok(thread) => Some(thread),
// _ => None,
// }
// }
9 changes: 9 additions & 0 deletions src/routes/api/dashboard/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pub mod player_data;
pub mod setup_data;
pub mod vote_data;

pub fn init(cfg: &mut actix_web::web::ServiceConfig) {
cfg.service(player_data::player_data);
cfg.service(vote_data::vote_data);
cfg.service(setup_data::setup_data);
}
34 changes: 34 additions & 0 deletions src/routes/api/dashboard/player_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use crate::components::{
buttons::{gen_button, ButtonType, FormSubmitButton},
forms::input::{gen_input, InputType, SelectMenuInput},
};
use actix_web::{get, HttpResponse, Responder};
use maud::html;


#[get("/players")]
async fn player_data() -> impl Responder {
HttpResponse::Ok().body(
html! {
div."w-full h-full flex flex-col p-4" {
h1."text-3xl text-white font-bold pb-2" { "Player Data" }
div."text-xl text-white pb-2" { "Enter the data for the players in the game" }
form."flex flex-col gap-2" {
label."text-xl" for="game_queue" { "Placeholder" }
(gen_input(InputType::SelectMenuInput(SelectMenuInput {
name: "game_queue".to_string(),
placeholder: "Select the game queue".to_string(),
options: vec![String::from("Open"), String::from("Newbie"), String::from("Normal"), String::from("Mini/Micro Theme"), String::from("Large Theme"), String::from("Other/Unknown")],
is_required: Some(true),
default_value: Some(String::from("Other/Unknown"))
})))

(gen_button(ButtonType::FormSubmit(FormSubmitButton {
text: "Save".to_string(),
})))
}
}
}
.into_string(),
)
}
49 changes: 49 additions & 0 deletions src/routes/api/dashboard/setup_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use crate::components::{
buttons::{gen_button, ButtonType, FormSubmitButton},
forms::input::{gen_input, InputType, SelectMenuInput, TextInput},
};
use actix_web::{get, HttpResponse, Responder};
use maud::html;

#[get("/setup")]
async fn setup_data() -> impl Responder {
HttpResponse::Ok().body(
html! {
div."w-full h-full flex flex-col p-4" {
h1."text-3xl text-white font-bold pb-2" { "Setup Data" }
div."text-xl text-white pb-2" { "Enter the data for the setup" }
form."flex flex-col gap-2" {
label."text-xl" for="game_queue" { "Game Queue" }
(gen_input(InputType::SelectMenuInput(SelectMenuInput {
name: "game_queue".to_string(),
placeholder: "Select the game queue".to_string(),
options: vec![String::from("Open"), String::from("Newbie"), String::from("Normal"), String::from("Mini/Micro Theme"), String::from("Large Theme"), String::from("Other/Unknown")],
is_required: Some(true),
default_value: Some(String::from("Other/Unknown"))
})))

label."text-xl" for="game_index" { "Game Index" }
(gen_input(InputType::TextInput(TextInput {
name: "game_index".to_string(),
placeholder: "Game Index".to_string(),
is_required: Some(true),
default_value: None
})))

label."text-xl" for="title" { "Title" }
(gen_input(InputType::TextInput(TextInput {
name: "title".to_string(),
placeholder: "Enter the game title".to_string(),
is_required: Some(true),
default_value: None
})))

(gen_button(ButtonType::FormSubmit(FormSubmitButton {
text: "Save".to_string(),
})))
}
}
}
.into_string(),
)
}
81 changes: 81 additions & 0 deletions src/routes/api/dashboard/vote_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use crate::components::{
buttons::{gen_button, ButtonType, FormSubmitButton},
forms::input::{gen_input, InputType, SelectMenuInput},
};
use actix_web::{get, HttpResponse, Responder};
use maud::{html, Markup};

struct TableRow {
name: String,
alignment: String,
role: String,
replacements: String
}
fn format_table_row(row:TableRow) -> Markup {
html!({
tr."even:bg-zinc-600" {
td."px-4 py-2" { (row.name) }
td."px-4 py-2 border-l border-gray-200" { (row.alignment) }
td."px-4 py-2 border-l border-gray-200" { (row.role) }
td."px-4 py-2 border-l border-gray-200" { (row.replacements) }
}
})
}


#[get("/votes")]
async fn vote_data() -> impl Responder {
HttpResponse::Ok().body(
html! {
div."w-full h-full flex flex-col p-4" {
h1."text-3xl text-white font-bold pb-2" { "Player Data" }
div."text-xl text-white pb-2" { "Enter the data for the players in the game" }
form."flex flex-col gap-2" {
label."text-xl" for="game_queue" { "Placeholder" }
(gen_input(InputType::SelectMenuInput(SelectMenuInput {
name: "game_queue".to_string(),
placeholder: "Select the game queue".to_string(),
options: vec![String::from("Open"), String::from("Newbie"), String::from("Normal"), String::from("Mini/Micro Theme"), String::from("Large Theme"), String::from("Other/Unknown")],
is_required: Some(true),
default_value: Some(String::from("Other/Unknown"))
})))

(gen_button(ButtonType::FormSubmit(FormSubmitButton {
text: "Save".to_string(),
})))
}
table."min-w-full bg-zinc-700 text-white" {
thead {
tr {
th."px-4 py-2 border-gray-200 bg-zinc-800" { "Player Name" }
th."px-4 py-2 border-l border-gray-200 bg-zinc-800" { "Alignment" }
th."px-4 py-2 border-l border-gray-200 bg-zinc-800" { "Role" }
th."px-4 py-2 border-l border-gray-200 bg-zinc-800" { "Replacements" }
}
}
tbody id="player-table-body" {
(format_table_row(TableRow {
name: "Player 1".to_string(),
alignment: "Town".to_string(),
role: "Cop".to_string(),
replacements: "None".to_string(),
}))
(format_table_row(TableRow {
name: "Player 2".to_string(),
alignment: "Mafia".to_string(),
role: "Goon".to_string(),
replacements: "Player 4".to_string(),
}))
(format_table_row(TableRow {
name: "Player 3".to_string(),
alignment: "Town".to_string(),
role: "Cop".to_string(),
replacements: "None".to_string(),
}))
}
}
}
}
.into_string(),
)
}
6 changes: 4 additions & 2 deletions src/routes/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub mod scrape_activity_page;
pub mod dashboard;
pub mod search_or_register_thread;

pub fn init(cfg: &mut actix_web::web::ServiceConfig) {
cfg.service(scrape_activity_page::scrape_activity_page);
cfg.service(actix_web::web::scope("/dashboard").configure(dashboard::init));
cfg.service(search_or_register_thread::search_or_register_thread);
}
68 changes: 68 additions & 0 deletions src/routes/api/search_or_register_thread.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use crate::scraping::{
parser::{get_search_params, get_url_from_type, PageType, PostURL, ThreadURL, URLType},
scraper::get_page_details,
};
use actix_web::{
post,
web::{self, Data},
HttpResponse, Responder,
};
use maud::html;

use crate::models::thread::get_thread;

use crate::AppState;

#[derive(serde::Deserialize)]
pub struct FormData {
url: String,
}

#[post("/search-or-register-thread")]
async fn search_or_register_thread(
state: Data<AppState>,
form: web::Form<FormData>,
) -> impl Responder {
let query_search_params = get_search_params(&form.url);
let raw_url = match (query_search_params.get("t"), query_search_params.get("p")) {
(Some(thread_id), _) => get_url_from_type(
URLType::Thread(ThreadURL {
thread_id: thread_id.to_string(),
}),
PageType::Thread,
),
(None, Some(post_id)) => get_url_from_type(
URLType::Post(PostURL {
post_id: post_id.to_string(),
}),
PageType::Thread,
),
_ => None,
};

let url = match raw_url {
None => {
return HttpResponse::BadRequest().body(
html! {
div."text-red-500" { "Invalid URL" }
}
.into_string(),
)
}
Some(url) => url,
};

let thread_id = match get_page_details(url.clone()).await {
Some(page) => page.thread_id,
None => None,
};

if let Some(t) = thread_id {
let thread: Option<crate::models::thread::Thread> = get_thread(state, t.clone()).await;
println!("Found thread: {:?}", thread);
} else {
println!("No thread was found");
}

HttpResponse::Ok().body(html! {}.into_string())
}
34 changes: 34 additions & 0 deletions src/routes/pages/dashboard.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use crate::components::header::{generate_header, Header};
use actix_web::{get, HttpResponse, Responder};
use maud::html;

#[get("/dashboard")]
async fn dashboard() -> impl Responder {
let header = generate_header(Header {
title: "Dashboard | MafiaScum Scraper",
});

let markup = html! {
(header)
body."bg-zinc-900 w-screen h-screen flex flex-row items-center justify-center text-white" {
div."bg-zinc-800 border-r border-zinc-600 shrink h-full" {
ul."w-64 flex flex-col gap-2 p-4"{
li."cursor-pointer" hx-get="/api/dashboard/setup" hx-target="#dashboard-content" hx-trigger="click, load" {
"Setup"
}
li."cursor-pointer" hx-get="/api/dashboard/players" hx-target="#dashboard-content" {
"Players"
}
li."cursor-pointer" hx-get="/api/dashboard/votes" hx-target="#dashboard-content" {
"Votes"
}
}
}
div."grow h-full" id="dashboard-content" {}
}
};

let html = markup.into_string();

HttpResponse::Ok().body(html)
}
4 changes: 2 additions & 2 deletions src/routes/pages/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
pub mod dashboard;
pub mod home;
pub mod scraper;
pub mod test;

pub fn init(cfg: &mut actix_web::web::ServiceConfig) {
cfg.service(home::main);
cfg.service(test::test);
cfg.service(scraper::scraper);
cfg.service(dashboard::dashboard);
}
2 changes: 1 addition & 1 deletion src/routes/pages/scraper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ async fn scraper() -> impl Responder {
div."text-xl text-white pb-2" {
"Enter a URL to scrape from mafiascum.net"
}
form."text-center w-1/2 flex flex-col items-center justify-center" hx-post="/api/scrape-activity-page" hx-target="this" hx-indicator="#scrape-form-loading" hx-swap="outerHTML" {
form."text-center w-1/2 flex flex-col items-center justify-center" hx-post="/api/search-or-register-thread" hx-target="this" hx-indicator="#scrape-form-loading" hx-swap="outerHTML" {
(gen_input(InputType::TextInput(TextInput {
name: "url".to_string(),
placeholder: "https://mafiascum.net".to_string(),
Expand Down
Loading

0 comments on commit 22af8c9

Please sign in to comment.