Skip to content

Commit

Permalink
init htmx
Browse files Browse the repository at this point in the history
  • Loading branch information
Klaven committed May 18, 2024
1 parent cf0a32d commit b9f677a
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 15 deletions.
27 changes: 27 additions & 0 deletions frontend_api/assets/css/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/** write some css to display two divs side by side that contain lists of elements */
/* Path: main.css */

div {
display: grid;
grid-template-columns: repeat(2, 1fr);
width: 75%;
}

.queue {
/** flex items-center justify-between */
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}

ul {
list-style-type: none;
padding: 0;
}

li {
cursor: pointer;
}


64 changes: 56 additions & 8 deletions frontend_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,25 @@ use tokio_tungstenite::{

type Tx = UnboundedSender<Message>;
pub type ConnectionMap = Arc<Mutex<HashMap<SocketAddr, Tx>>>;
type MessageQueue = Arc<Mutex<VecDeque<DisplayMessage>>>;
type EventQueues = Arc<Mutex<Queues>>;

static EVENT_QUEUE_ACTIVE: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(true);
static TTS_QUEUE_ACTIVE: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
static IS_DISPLAYING: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);

pub struct Queues {
pub events: VecDeque<DisplayMessage>,
pub tts: VecDeque<DisplayMessage>,
}

impl Queues {
pub fn new() -> Queues {
Queues {
events: VecDeque::new(),
tts: VecDeque::new(),
}
}
}

pub struct FrontendApi {
ws_address: String,
Expand All @@ -49,15 +67,32 @@ impl FrontendApi {
println!("Listening on: {}", self.ws_address);

let connection_state = self.connection_state.clone();
let message_queue_arc: MessageQueue = Arc::new(Mutex::new(VecDeque::new()));
let message_queue_arc: EventQueues = Arc::new(Mutex::new(Queues::new()));

//TODO: Need to fetch un presented messages from database

let queue = message_queue_arc.clone();
let state = connection_state.clone();
// Listen for incoming events and store them in the queues
tokio::spawn(async move {
loop {
let msg = (&mut receiver).recv().await;
handle_message(connection_state.clone(), message_queue_arc.clone(), msg).await;
handle_message(state.clone(), queue.clone(), msg);
}
});

// Process the Queues on a new thread

//tokio::spawn(async move {
// loop {
// let mut queues = message_queue_arc.lock().unwrap();
// if !queues.events.is_empty() {
// let message = queues.events.pop_front();
// handle_message(connection_state.clone(), message_queue_arc.clone(), message);
// }
// }
//});

let https_address = self.http_address.clone();
tokio::spawn(async move {
let listener = TcpListener::bind(&https_address)
Expand All @@ -66,6 +101,7 @@ impl FrontendApi {
// build our application
let app = Router::new()
.route("/", get(index))
.route("/admin", get(admin))
//TODO: understand where to put our assets
// Remember that these need served by nginx in production
.nest_service("/assets", ServeDir::new("assets"));
Expand Down Expand Up @@ -96,13 +132,21 @@ impl FrontendApi {
#[template(path = "index.html")]
struct IndexTemplate {}

#[derive(askama::Template)]
#[template(path = "admin.html")]
struct AdminTemplate {}

async fn index() -> IndexTemplate {
IndexTemplate {}
}

async fn handle_message(
async fn admin() -> AdminTemplate {
AdminTemplate {}
}

fn handle_message(
connection_state: ConnectionMap,
message_queue: MessageQueue,
event_queues: EventQueues,
message: Option<DisplayMessage>,
) {
match message {
Expand All @@ -113,14 +157,17 @@ async fn handle_message(

//Enqueue message
{
let mut message_queue = message_queue.lock().unwrap();
message_queue.push_back(message.clone());
let mut queues = event_queues.lock().unwrap();
//TODO: need to handle different types of messages

queues.events.push_back(message.clone());
}

//Make html message to send to frontend
//<div id="alerts" hx-swap-oob="true">
let trigger = format!("delay:{}ms", message.display_time);
let html_message = html! {
div id="alerts" hx-swap-oob="true" {
div id="notifications" hx-swap="afterend" hx-target="notifications" ws-send="done" hx-trigger=(trigger) {
h1 { (message.message) }
img src=(message.image_url) {}
}
Expand Down Expand Up @@ -158,6 +205,7 @@ async fn handle_connection(
state.lock().unwrap().insert(peer, tx);
}
let (mut ws_sender, mut ws_receiver) = ws_stream.split();
println!("Connection state: {:?}", state.lock().unwrap().keys());
loop {
tokio::select! {
msg = ws_receiver.next() => {
Expand Down
7 changes: 3 additions & 4 deletions frontend_api/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use forntend_api_lib::FrontendApi;
use serde_json::to_string;
use tokio::sync::mpsc;

//TODO: This should run like the "full app" does in the lib.rs file
Expand All @@ -23,10 +22,10 @@ async fn main() {

loop {
let display_message = messages::DisplayMessage {
message: "hello fome htmx".to_string(),
message: "hello from htmx".to_string(),
image_url: "".to_string(),
sound_url: "".to_string(),
display_time: 20,
display_time: 5000,
payload: messages::TwitchEvent::ChannelFollow(messages::FollowEvent {
user_name: "some user".to_string(),
user_id: 123,
Expand All @@ -35,6 +34,6 @@ async fn main() {

let _ = tx.send(display_message).unwrap();

tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
tokio::time::sleep(tokio::time::Duration::from_secs(20)).await;
}
}
55 changes: 55 additions & 0 deletions frontend_api/templates/admin.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<title>TODO with HTMX</title>
<link rel="stylesheet" href="/assets/css/main.css">
<script src="https://unpkg.com/[email protected]"
integrity="sha384-ujb1lZYygJmzgSwoxRggbCHcjc0rB2XoQrxeTUQyRjrOnlCoYta87iKBWq3EsdM2"
crossorigin="anonymous"></script>
<script src="https://unpkg.com/[email protected]/dist/ext/ws.js"></script>
</head>

<body>
<main class="flex flex-row justify-center w-full">
<!-- Should display 2 queues with buttons at the bottom -->
<div>
<div class="queue">
<h1>Events</h1>
<div class="">
<h1>TODO</h1>
<div id="todo-queue"></div>
</div>
<div class="">
<h1>DOING</h1>
<div id="doing-queue"></div>
</div>
</div>
<div class="queue">
<h1>TTS</h1>
<div>
<h1>DONE</h1>
<div id=""></div>
</div>
<div class="">
<h1>ARCHIVED</h1>
<div id="archived-queue"></div>
</div>
</div>
<div class="">
<button id="event-queue-start-stop">Stop</button>
<button id="tts">Play Next TTS</button>
</div>
</div>
<!-- Should display notifications and alerts -->
<div hx-ext="ws" ws-connect="ws://localhost:9000/">
<div id="notifications"></div>
<div id="alerts">
<h1>TODO with HTMX</h1>
</div>
</div>
</main>
</body>

</html>
3 changes: 0 additions & 3 deletions frontend_api/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
<main class="flex flex-row justify-center w-full">
<div hx-ext="ws" ws-connect="ws://localhost:9000/">
<div id="notifications"></div>
<div id="alerts">
<h1>TODO with HTMX</h1>
</div>
</div>
</main>
</body>
Expand Down

0 comments on commit b9f677a

Please sign in to comment.