Fix no poll showing up if no one voted in it yet
This commit is contained in:
parent
28812699c7
commit
cdb1b35ced
1 changed files with 179 additions and 159 deletions
338
src/main.rs
338
src/main.rs
|
@ -1,4 +1,5 @@
|
||||||
use axum::extract::{Path, State};
|
use axum::extract::{Path, State};
|
||||||
|
use axum::http::header::SET_COOKIE;
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use axum::response::{AppendHeaders, Html, IntoResponse, Redirect, Response};
|
use axum::response::{AppendHeaders, Html, IntoResponse, Redirect, Response};
|
||||||
use axum::Form;
|
use axum::Form;
|
||||||
|
@ -6,11 +7,10 @@ use axum::{
|
||||||
routing::{get, post},
|
routing::{get, post},
|
||||||
Json, Router,
|
Json, Router,
|
||||||
};
|
};
|
||||||
|
use axum_extra::extract::CookieJar;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use axum::http::header::SET_COOKIE;
|
|
||||||
use axum_extra::extract::CookieJar;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
struct Page {
|
struct Page {
|
||||||
|
@ -212,44 +212,44 @@ async fn view_current_poll(State(state): State<AppState>) -> Response {
|
||||||
.filter(|poll| poll.id == current_poll)
|
.filter(|poll| poll.id == current_poll)
|
||||||
.collect();
|
.collect();
|
||||||
if !current_poll.is_empty() {
|
if !current_poll.is_empty() {
|
||||||
if let Some(poll) = state.get_poll_votes_by_poll_id(current_poll[0].id) {
|
let poll_config = current_poll.first().unwrap();
|
||||||
let poll_config = current_poll.first().unwrap();
|
let mut choices = vec![];
|
||||||
let mut choices = vec![];
|
|
||||||
|
|
||||||
let find_vote_choice = |id: i32| {
|
let find_vote_choice = |id: i32| {
|
||||||
|
if let Some(poll) = state.get_poll_votes_by_poll_id(current_poll[0].id) {
|
||||||
for choice in &poll.choices {
|
for choice in &poll.choices {
|
||||||
if choice.id == id {
|
if choice.id == id {
|
||||||
return Some(choice);
|
return Some(choice.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
|
|
||||||
for choice in &poll_config.choices {
|
|
||||||
if let Some(vote_choice) = find_vote_choice(choice.id) {
|
|
||||||
choices.push(PollChoiceResponse {
|
|
||||||
id: choice.id,
|
|
||||||
name: choice.name.clone(),
|
|
||||||
url: choice.url.clone(),
|
|
||||||
votes: vote_choice.votes,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
choices.push(PollChoiceResponse {
|
|
||||||
id: choice.id,
|
|
||||||
name: choice.name.clone(),
|
|
||||||
url: choice.url.clone(),
|
|
||||||
votes: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Json(PollResponse {
|
return None;
|
||||||
title: current_poll.first().unwrap().title.clone(),
|
};
|
||||||
choices,
|
|
||||||
})
|
for choice in &poll_config.choices {
|
||||||
.into_response();
|
if let Some(vote_choice) = find_vote_choice(choice.id) {
|
||||||
|
choices.push(PollChoiceResponse {
|
||||||
|
id: choice.id,
|
||||||
|
name: choice.name.clone(),
|
||||||
|
url: choice.url.clone(),
|
||||||
|
votes: vote_choice.votes,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
choices.push(PollChoiceResponse {
|
||||||
|
id: choice.id,
|
||||||
|
name: choice.name.clone(),
|
||||||
|
url: choice.url.clone(),
|
||||||
|
votes: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Json(PollResponse {
|
||||||
|
title: current_poll.first().unwrap().title.clone(),
|
||||||
|
choices,
|
||||||
|
})
|
||||||
|
.into_response();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,10 @@ struct SubmitForm {
|
||||||
choice: i32,
|
choice: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn vote_current_poll(State(state): State<AppState>, Form(form): Form<SubmitForm>) -> Response {
|
async fn vote_current_poll(
|
||||||
|
State(state): State<AppState>,
|
||||||
|
Form(form): Form<SubmitForm>,
|
||||||
|
) -> Response {
|
||||||
let id = form.choice;
|
let id = form.choice;
|
||||||
tracing::info!("Submitting vote for choice {id}");
|
tracing::info!("Submitting vote for choice {id}");
|
||||||
|
|
||||||
|
@ -279,7 +282,10 @@ async fn vote_current_poll(State(state): State<AppState>, Form(form): Form<Submi
|
||||||
state.vote_poll(current_poll.first().unwrap().id, id);
|
state.vote_poll(current_poll.first().unwrap().id, id);
|
||||||
state.save_polls();
|
state.save_polls();
|
||||||
|
|
||||||
let headers = AppendHeaders([(SET_COOKIE, format!("poll_{}={}", current_poll.first().unwrap().id, id))]);
|
let headers = AppendHeaders([(
|
||||||
|
SET_COOKIE,
|
||||||
|
format!("poll_{}={}", current_poll.first().unwrap().id, id),
|
||||||
|
)]);
|
||||||
|
|
||||||
// make sure to redirect the iframe back to results
|
// make sure to redirect the iframe back to results
|
||||||
return (headers, Redirect::to("/polls/frame/results")).into_response();
|
return (headers, Redirect::to("/polls/frame/results")).into_response();
|
||||||
|
@ -302,82 +308,92 @@ async fn poll_frame_vote(State(state): State<AppState>, jar: CookieJar) -> Html<
|
||||||
.filter(|poll| poll.id == current_poll)
|
.filter(|poll| poll.id == current_poll)
|
||||||
.collect();
|
.collect();
|
||||||
if !current_poll.is_empty() {
|
if !current_poll.is_empty() {
|
||||||
if let Some(poll) = state.get_poll_votes_by_poll_id(current_poll[0].id) {
|
let poll_config = current_poll.first().unwrap();
|
||||||
let poll_config = current_poll.first().unwrap();
|
let mut choices = vec![];
|
||||||
let mut choices = vec![];
|
|
||||||
|
|
||||||
let find_vote_choice = |id: i32| {
|
let find_vote_choice = |id: i32| {
|
||||||
|
if let Some(poll) = state.get_poll_votes_by_poll_id(current_poll[0].id) {
|
||||||
for choice in &poll.choices {
|
for choice in &poll.choices {
|
||||||
if choice.id == id {
|
if choice.id == id {
|
||||||
return Some(choice);
|
return Some(choice.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
|
|
||||||
for choice in &poll_config.choices {
|
|
||||||
if let Some(vote_choice) = find_vote_choice(choice.id) {
|
|
||||||
choices.push(PollChoiceResponse {
|
|
||||||
id: choice.id,
|
|
||||||
name: choice.name.clone(),
|
|
||||||
url: choice.url.clone(),
|
|
||||||
votes: vote_choice.votes,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
choices.push(PollChoiceResponse {
|
|
||||||
id: choice.id,
|
|
||||||
name: choice.name.clone(),
|
|
||||||
url: choice.url.clone(),
|
|
||||||
votes: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut html = String::new();
|
return None;
|
||||||
html.push_str(&format!(
|
};
|
||||||
"<h3>{}</h3>",
|
|
||||||
current_poll.first().unwrap().title.clone()
|
|
||||||
));
|
|
||||||
|
|
||||||
let mut existing_choice = None;
|
for choice in &poll_config.choices {
|
||||||
for cookie in jar.iter() {
|
if let Some(vote_choice) = find_vote_choice(choice.id) {
|
||||||
if cookie.name().contains("poll_") {
|
choices.push(PollChoiceResponse {
|
||||||
let id = cookie.name().replace("poll_", "");
|
id: choice.id,
|
||||||
if let Ok(id) = id.parse::<i32>() {
|
name: choice.name.clone(),
|
||||||
if id == poll_config.id {
|
url: choice.url.clone(),
|
||||||
if let Ok(value) = cookie.value().parse::<i32>() {
|
votes: vote_choice.votes,
|
||||||
existing_choice = Some(value);
|
});
|
||||||
}
|
} else {
|
||||||
|
choices.push(PollChoiceResponse {
|
||||||
|
id: choice.id,
|
||||||
|
name: choice.name.clone(),
|
||||||
|
url: choice.url.clone(),
|
||||||
|
votes: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut html = String::new();
|
||||||
|
html.push_str(&format!(
|
||||||
|
"<h3>{}</h3>",
|
||||||
|
current_poll.first().unwrap().title.clone()
|
||||||
|
));
|
||||||
|
|
||||||
|
let mut existing_choice = None;
|
||||||
|
for cookie in jar.iter() {
|
||||||
|
if cookie.name().contains("poll_") {
|
||||||
|
let id = cookie.name().replace("poll_", "");
|
||||||
|
if let Ok(id) = id.parse::<i32>() {
|
||||||
|
if id == poll_config.id {
|
||||||
|
if let Ok(value) = cookie.value().parse::<i32>() {
|
||||||
|
existing_choice = Some(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
html.push_str("<form id=\"results\" action=\"/polls/frame/results\">");
|
|
||||||
html.push_str("</form>");
|
|
||||||
|
|
||||||
html.push_str("<form action=\"/polls/vote\" method=\"post\">");
|
|
||||||
html.push_str("<fieldset>");
|
|
||||||
let inert = if existing_choice.is_some() { "inert" } else { "" };
|
|
||||||
html.push_str(&format!("<div {}>", inert));
|
|
||||||
for choice in choices {
|
|
||||||
let checked = if Some(choice.id) == existing_choice { "checked" } else { "" };
|
|
||||||
html.push_str(&format!("<input type=\"radio\" name=\"choice\" id=\"choice{}\" value=\"{}\" {}>", choice.id, choice.id, checked));
|
|
||||||
html.push_str(&format!(
|
|
||||||
"<label for=\"choice{}\">{}</label>",
|
|
||||||
choice.id,
|
|
||||||
choice.name.clone()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
html.push_str("</div>");
|
|
||||||
html.push_str(&format!("<input type=\"submit\" {}/>", inert));
|
|
||||||
html.push_str("<input form=\"results\" type=\"submit\" value=\"View Results\"/>");
|
|
||||||
html.push_str("</fieldset>");
|
|
||||||
html.push_str("</form>");
|
|
||||||
|
|
||||||
return Html(html);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html.push_str("<form id=\"results\" action=\"/polls/frame/results\">");
|
||||||
|
html.push_str("</form>");
|
||||||
|
|
||||||
|
html.push_str("<form action=\"/polls/vote\" method=\"post\">");
|
||||||
|
html.push_str("<fieldset>");
|
||||||
|
let inert = if existing_choice.is_some() {
|
||||||
|
"inert"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
html.push_str(&format!("<div {}>", inert));
|
||||||
|
for choice in choices {
|
||||||
|
let checked = if Some(choice.id) == existing_choice {
|
||||||
|
"checked"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
html.push_str(&format!("<input type=\"radio\" name=\"choice\" id=\"choice{}\" value=\"{}\" {}>", choice.id, choice.id, checked));
|
||||||
|
html.push_str(&format!(
|
||||||
|
"<label for=\"choice{}\">{}</label>",
|
||||||
|
choice.id,
|
||||||
|
choice.name.clone()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
html.push_str("</div>");
|
||||||
|
html.push_str(&format!("<input type=\"submit\" {}/>", inert));
|
||||||
|
html.push_str(
|
||||||
|
"<input form=\"results\" type=\"submit\" value=\"View Results\"/>",
|
||||||
|
);
|
||||||
|
html.push_str("</fieldset>");
|
||||||
|
html.push_str("</form>");
|
||||||
|
|
||||||
|
return Html(html);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -396,82 +412,86 @@ async fn poll_frame_results(State(state): State<AppState>, jar: CookieJar) -> Ht
|
||||||
.filter(|poll| poll.id == current_poll)
|
.filter(|poll| poll.id == current_poll)
|
||||||
.collect();
|
.collect();
|
||||||
if !current_poll.is_empty() {
|
if !current_poll.is_empty() {
|
||||||
if let Some(poll) = state.get_poll_votes_by_poll_id(current_poll[0].id) {
|
let poll_config = current_poll.first().unwrap();
|
||||||
let poll_config = current_poll.first().unwrap();
|
let mut choices = vec![];
|
||||||
let mut choices = vec![];
|
|
||||||
|
|
||||||
let find_vote_choice = |id: i32| {
|
let find_vote_choice = |id: i32| {
|
||||||
|
if let Some(poll) = state.get_poll_votes_by_poll_id(current_poll[0].id) {
|
||||||
for choice in &poll.choices {
|
for choice in &poll.choices {
|
||||||
if choice.id == id {
|
if choice.id == id {
|
||||||
return Some(choice);
|
return Some(choice.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
|
|
||||||
for choice in &poll_config.choices {
|
|
||||||
if let Some(vote_choice) = find_vote_choice(choice.id) {
|
|
||||||
choices.push(PollChoiceResponse {
|
|
||||||
id: choice.id,
|
|
||||||
name: choice.name.clone(),
|
|
||||||
url: choice.url.clone(),
|
|
||||||
votes: vote_choice.votes,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
choices.push(PollChoiceResponse {
|
|
||||||
id: choice.id,
|
|
||||||
name: choice.name.clone(),
|
|
||||||
url: choice.url.clone(),
|
|
||||||
votes: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut html = String::new();
|
return None;
|
||||||
html.push_str(&format!(
|
};
|
||||||
"<h3>{}</h3>",
|
|
||||||
current_poll.first().unwrap().title.clone()
|
|
||||||
));
|
|
||||||
|
|
||||||
html.push_str("<form id=\"results\" action=\"/polls/frame/vote\">");
|
for choice in &poll_config.choices {
|
||||||
html.push_str("</form>");
|
if let Some(vote_choice) = find_vote_choice(choice.id) {
|
||||||
|
choices.push(PollChoiceResponse {
|
||||||
|
id: choice.id,
|
||||||
|
name: choice.name.clone(),
|
||||||
|
url: choice.url.clone(),
|
||||||
|
votes: vote_choice.votes,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
choices.push(PollChoiceResponse {
|
||||||
|
id: choice.id,
|
||||||
|
name: choice.name.clone(),
|
||||||
|
url: choice.url.clone(),
|
||||||
|
votes: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut existing_choice = None;
|
let mut html = String::new();
|
||||||
for cookie in jar.iter() {
|
html.push_str(&format!(
|
||||||
if cookie.name().contains("poll_") {
|
"<h3>{}</h3>",
|
||||||
let id = cookie.name().replace("poll_", "");
|
current_poll.first().unwrap().title.clone()
|
||||||
if let Ok(id) = id.parse::<i32>() {
|
));
|
||||||
if id == poll_config.id {
|
|
||||||
if let Ok(value) = cookie.value().parse::<i32>() {
|
html.push_str("<form id=\"results\" action=\"/polls/frame/vote\">");
|
||||||
existing_choice = Some(value);
|
html.push_str("</form>");
|
||||||
}
|
|
||||||
|
let mut existing_choice = None;
|
||||||
|
for cookie in jar.iter() {
|
||||||
|
if cookie.name().contains("poll_") {
|
||||||
|
let id = cookie.name().replace("poll_", "");
|
||||||
|
if let Ok(id) = id.parse::<i32>() {
|
||||||
|
if id == poll_config.id {
|
||||||
|
if let Ok(value) = cookie.value().parse::<i32>() {
|
||||||
|
existing_choice = Some(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
html.push_str("<form>");
|
|
||||||
html.push_str("<fieldset>");
|
|
||||||
html.push_str("<div inert>");
|
|
||||||
for choice in choices {
|
|
||||||
let checked = if Some(choice.id) == existing_choice { "checked" } else { "" };
|
|
||||||
|
|
||||||
html.push_str(&format!("<input type=\"radio\" name=\"choice\" id=\"choice{}\" value=\"{}\" {}>", choice.id, choice.id, checked));
|
|
||||||
html.push_str(&format!(
|
|
||||||
"<label for=\"choice{}\">{} ({} votes)</label>",
|
|
||||||
choice.id,
|
|
||||||
choice.name.clone(),
|
|
||||||
choice.votes
|
|
||||||
));
|
|
||||||
}
|
|
||||||
html.push_str("</div>");
|
|
||||||
html.push_str("<input form=\"results\" type=\"submit\" value=\"Back\"/>");
|
|
||||||
html.push_str("</fieldset>");
|
|
||||||
html.push_str("</form>");
|
|
||||||
|
|
||||||
return Html(html);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html.push_str("<form>");
|
||||||
|
html.push_str("<fieldset>");
|
||||||
|
html.push_str("<div inert>");
|
||||||
|
for choice in choices {
|
||||||
|
let checked = if Some(choice.id) == existing_choice {
|
||||||
|
"checked"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
|
html.push_str(&format!("<input type=\"radio\" name=\"choice\" id=\"choice{}\" value=\"{}\" {}>", choice.id, choice.id, checked));
|
||||||
|
html.push_str(&format!(
|
||||||
|
"<label for=\"choice{}\">{} ({} votes)</label>",
|
||||||
|
choice.id,
|
||||||
|
choice.name.clone(),
|
||||||
|
choice.votes
|
||||||
|
));
|
||||||
|
}
|
||||||
|
html.push_str("</div>");
|
||||||
|
html.push_str("<input form=\"results\" type=\"submit\" value=\"Back\"/>");
|
||||||
|
html.push_str("</fieldset>");
|
||||||
|
html.push_str("</form>");
|
||||||
|
|
||||||
|
return Html(html);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue