Skip to content

Commit b9f677a

Browse files
committed
init htmx
1 parent cf0a32d commit b9f677a

File tree

5 files changed

+141
-15
lines changed

5 files changed

+141
-15
lines changed

frontend_api/assets/css/main.css

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/** write some css to display two divs side by side that contain lists of elements */
2+
/* Path: main.css */
3+
4+
div {
5+
display: grid;
6+
grid-template-columns: repeat(2, 1fr);
7+
width: 75%;
8+
}
9+
10+
.queue {
11+
/** flex items-center justify-between */
12+
display: flex;
13+
flex-direction: column;
14+
justify-content: space-between;
15+
align-items: center;
16+
}
17+
18+
ul {
19+
list-style-type: none;
20+
padding: 0;
21+
}
22+
23+
li {
24+
cursor: pointer;
25+
}
26+
27+

frontend_api/src/lib.rs

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,25 @@ use tokio_tungstenite::{
2222

2323
type Tx = UnboundedSender<Message>;
2424
pub type ConnectionMap = Arc<Mutex<HashMap<SocketAddr, Tx>>>;
25-
type MessageQueue = Arc<Mutex<VecDeque<DisplayMessage>>>;
25+
type EventQueues = Arc<Mutex<Queues>>;
26+
27+
static EVENT_QUEUE_ACTIVE: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(true);
28+
static TTS_QUEUE_ACTIVE: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
29+
static IS_DISPLAYING: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
30+
31+
pub struct Queues {
32+
pub events: VecDeque<DisplayMessage>,
33+
pub tts: VecDeque<DisplayMessage>,
34+
}
35+
36+
impl Queues {
37+
pub fn new() -> Queues {
38+
Queues {
39+
events: VecDeque::new(),
40+
tts: VecDeque::new(),
41+
}
42+
}
43+
}
2644

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

5169
let connection_state = self.connection_state.clone();
52-
let message_queue_arc: MessageQueue = Arc::new(Mutex::new(VecDeque::new()));
70+
let message_queue_arc: EventQueues = Arc::new(Mutex::new(Queues::new()));
71+
72+
//TODO: Need to fetch un presented messages from database
5373

74+
let queue = message_queue_arc.clone();
75+
let state = connection_state.clone();
76+
// Listen for incoming events and store them in the queues
5477
tokio::spawn(async move {
5578
loop {
5679
let msg = (&mut receiver).recv().await;
57-
handle_message(connection_state.clone(), message_queue_arc.clone(), msg).await;
80+
handle_message(state.clone(), queue.clone(), msg);
5881
}
5982
});
6083

84+
// Process the Queues on a new thread
85+
86+
//tokio::spawn(async move {
87+
// loop {
88+
// let mut queues = message_queue_arc.lock().unwrap();
89+
// if !queues.events.is_empty() {
90+
// let message = queues.events.pop_front();
91+
// handle_message(connection_state.clone(), message_queue_arc.clone(), message);
92+
// }
93+
// }
94+
//});
95+
6196
let https_address = self.http_address.clone();
6297
tokio::spawn(async move {
6398
let listener = TcpListener::bind(&https_address)
@@ -66,6 +101,7 @@ impl FrontendApi {
66101
// build our application
67102
let app = Router::new()
68103
.route("/", get(index))
104+
.route("/admin", get(admin))
69105
//TODO: understand where to put our assets
70106
// Remember that these need served by nginx in production
71107
.nest_service("/assets", ServeDir::new("assets"));
@@ -96,13 +132,21 @@ impl FrontendApi {
96132
#[template(path = "index.html")]
97133
struct IndexTemplate {}
98134

135+
#[derive(askama::Template)]
136+
#[template(path = "admin.html")]
137+
struct AdminTemplate {}
138+
99139
async fn index() -> IndexTemplate {
100140
IndexTemplate {}
101141
}
102142

103-
async fn handle_message(
143+
async fn admin() -> AdminTemplate {
144+
AdminTemplate {}
145+
}
146+
147+
fn handle_message(
104148
connection_state: ConnectionMap,
105-
message_queue: MessageQueue,
149+
event_queues: EventQueues,
106150
message: Option<DisplayMessage>,
107151
) {
108152
match message {
@@ -113,14 +157,17 @@ async fn handle_message(
113157

114158
//Enqueue message
115159
{
116-
let mut message_queue = message_queue.lock().unwrap();
117-
message_queue.push_back(message.clone());
160+
let mut queues = event_queues.lock().unwrap();
161+
//TODO: need to handle different types of messages
162+
163+
queues.events.push_back(message.clone());
118164
}
119165

120166
//Make html message to send to frontend
121167
//<div id="alerts" hx-swap-oob="true">
168+
let trigger = format!("delay:{}ms", message.display_time);
122169
let html_message = html! {
123-
div id="alerts" hx-swap-oob="true" {
170+
div id="notifications" hx-swap="afterend" hx-target="notifications" ws-send="done" hx-trigger=(trigger) {
124171
h1 { (message.message) }
125172
img src=(message.image_url) {}
126173
}
@@ -158,6 +205,7 @@ async fn handle_connection(
158205
state.lock().unwrap().insert(peer, tx);
159206
}
160207
let (mut ws_sender, mut ws_receiver) = ws_stream.split();
208+
println!("Connection state: {:?}", state.lock().unwrap().keys());
161209
loop {
162210
tokio::select! {
163211
msg = ws_receiver.next() => {

frontend_api/src/main.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use forntend_api_lib::FrontendApi;
2-
use serde_json::to_string;
32
use tokio::sync::mpsc;
43

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

2423
loop {
2524
let display_message = messages::DisplayMessage {
26-
message: "hello fome htmx".to_string(),
25+
message: "hello from htmx".to_string(),
2726
image_url: "".to_string(),
2827
sound_url: "".to_string(),
29-
display_time: 20,
28+
display_time: 5000,
3029
payload: messages::TwitchEvent::ChannelFollow(messages::FollowEvent {
3130
user_name: "some user".to_string(),
3231
user_id: 123,
@@ -35,6 +34,6 @@ async fn main() {
3534

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

38-
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
37+
tokio::time::sleep(tokio::time::Duration::from_secs(20)).await;
3938
}
4039
}

frontend_api/templates/admin.html

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<title>TODO with HTMX</title>
7+
<link rel="stylesheet" href="/assets/css/main.css">
8+
<script src="https://unpkg.com/[email protected]"
9+
integrity="sha384-ujb1lZYygJmzgSwoxRggbCHcjc0rB2XoQrxeTUQyRjrOnlCoYta87iKBWq3EsdM2"
10+
crossorigin="anonymous"></script>
11+
<script src="https://unpkg.com/[email protected]/dist/ext/ws.js"></script>
12+
</head>
13+
14+
<body>
15+
<main class="flex flex-row justify-center w-full">
16+
<!-- Should display 2 queues with buttons at the bottom -->
17+
<div>
18+
<div class="queue">
19+
<h1>Events</h1>
20+
<div class="">
21+
<h1>TODO</h1>
22+
<div id="todo-queue"></div>
23+
</div>
24+
<div class="">
25+
<h1>DOING</h1>
26+
<div id="doing-queue"></div>
27+
</div>
28+
</div>
29+
<div class="queue">
30+
<h1>TTS</h1>
31+
<div>
32+
<h1>DONE</h1>
33+
<div id=""></div>
34+
</div>
35+
<div class="">
36+
<h1>ARCHIVED</h1>
37+
<div id="archived-queue"></div>
38+
</div>
39+
</div>
40+
<div class="">
41+
<button id="event-queue-start-stop">Stop</button>
42+
<button id="tts">Play Next TTS</button>
43+
</div>
44+
</div>
45+
<!-- Should display notifications and alerts -->
46+
<div hx-ext="ws" ws-connect="ws://localhost:9000/">
47+
<div id="notifications"></div>
48+
<div id="alerts">
49+
<h1>TODO with HTMX</h1>
50+
</div>
51+
</div>
52+
</main>
53+
</body>
54+
55+
</html>

frontend_api/templates/index.html

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
<main class="flex flex-row justify-center w-full">
1616
<div hx-ext="ws" ws-connect="ws://localhost:9000/">
1717
<div id="notifications"></div>
18-
<div id="alerts">
19-
<h1>TODO with HTMX</h1>
20-
</div>
2118
</div>
2219
</main>
2320
</body>

0 commit comments

Comments
 (0)