feat: list survey responses per campaign
This commit is contained in:
parent
f6030577a0
commit
aa63783794
2 changed files with 170 additions and 118 deletions
|
@ -23,6 +23,7 @@ use sqlx::types::time::OffsetDateTime;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{get_admin_check_login, get_uuid};
|
use super::{get_admin_check_login, get_uuid};
|
||||||
|
use crate::api::v1::bench::Bench;
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use crate::AppData;
|
use crate::AppData;
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ pub mod routes {
|
||||||
pub delete: &'static str,
|
pub delete: &'static str,
|
||||||
// pub get_feedback: &'static str,
|
// pub get_feedback: &'static str,
|
||||||
pub list: &'static str,
|
pub list: &'static str,
|
||||||
|
pub results: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Campaign {
|
impl Campaign {
|
||||||
|
@ -43,8 +45,14 @@ pub mod routes {
|
||||||
let delete = "/admin/api/v1/campaign/{uuid}/delete";
|
let delete = "/admin/api/v1/campaign/{uuid}/delete";
|
||||||
// let get_feedback = "/api/v1/campaign/{uuid}/feedback";
|
// let get_feedback = "/api/v1/campaign/{uuid}/feedback";
|
||||||
let list = "/admin/api/v1/campaign/list";
|
let list = "/admin/api/v1/campaign/list";
|
||||||
|
let results = "/admin/api/v1/campaign/{uuid}/results";
|
||||||
|
|
||||||
Campaign { add, delete, list }
|
Campaign {
|
||||||
|
add,
|
||||||
|
delete,
|
||||||
|
list,
|
||||||
|
results,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// pub fn get_benches_route(&self, campaign_id: &str) -> String {
|
// pub fn get_benches_route(&self, campaign_id: &str) -> String {
|
||||||
// self.get_feedback.replace("{uuid}", &campaign_id)
|
// self.get_feedback.replace("{uuid}", &campaign_id)
|
||||||
|
@ -53,10 +61,18 @@ pub mod routes {
|
||||||
pub fn get_delete_route(&self, campaign_id: &str) -> String {
|
pub fn get_delete_route(&self, campaign_id: &str) -> String {
|
||||||
self.delete.replace("{uuid}", campaign_id)
|
self.delete.replace("{uuid}", campaign_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_results_route(&self, campaign_id: &str) -> String {
|
||||||
|
self.results.replace("{uuid}", campaign_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod runners {
|
pub mod runners {
|
||||||
|
use futures::try_join;
|
||||||
|
|
||||||
|
use crate::api::v1::bench::Bench;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub async fn add_runner(
|
pub async fn add_runner(
|
||||||
|
@ -144,86 +160,111 @@ pub mod runners {
|
||||||
Ok(list_resp)
|
Ok(list_resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub async fn get_benches(
|
#[derive(Debug)]
|
||||||
// username: &str,
|
struct InternalSurveyResp {
|
||||||
// uuid: &str,
|
id: i32,
|
||||||
// data: &AppData,
|
user_id: Uuid,
|
||||||
// ) -> ServiceResult<GetFeedbackResp> {
|
threads: Option<i32>,
|
||||||
// let uuid = Uuid::parse_str(uuid).map_err(|_| ServiceError::NotAnId)?;
|
device_user_provided: String,
|
||||||
//
|
device_software_recognised: String,
|
||||||
// struct FeedbackInternal {
|
}
|
||||||
// time: OffsetDateTime,
|
|
||||||
// description: String,
|
#[derive(Debug)]
|
||||||
// helpful: bool,
|
struct InnerU {
|
||||||
// }
|
created_at: OffsetDateTime,
|
||||||
//
|
id: Uuid,
|
||||||
// struct Name {
|
}
|
||||||
// name: String,
|
|
||||||
// }
|
impl From<InnerU> for SurveyUser {
|
||||||
//
|
fn from(u: InnerU) -> Self {
|
||||||
// let name_fut = sqlx::query_as!(
|
Self {
|
||||||
// Name,
|
id: u.id,
|
||||||
// "SELECT name
|
created_at: u.created_at.unix_timestamp(),
|
||||||
// FROM survey_campaigns
|
}
|
||||||
// WHERE uuid = $1
|
}
|
||||||
// AND
|
}
|
||||||
// user_id = (
|
|
||||||
// SELECT
|
pub async fn get_results(
|
||||||
// ID
|
username: &str,
|
||||||
// FROM
|
uuid: &Uuid,
|
||||||
// kaizen_users
|
data: &AppData,
|
||||||
// WHERE
|
page: usize,
|
||||||
// name = $2
|
limit: usize,
|
||||||
// )
|
) -> ServiceResult<Vec<SurveyResponse>> {
|
||||||
// ",
|
// let uuid = Uuid::parse_str(uuid).map_err(|_| ServiceError::NotAnId)?;
|
||||||
// uuid,
|
|
||||||
// username
|
let mut db_responses = sqlx::query_as!(
|
||||||
// )
|
InternalSurveyResp,
|
||||||
// .fetch_one(&data.db); //.await?;
|
"SELECT
|
||||||
//
|
ID,
|
||||||
// let feedback_fut = sqlx::query_as!(
|
device_software_recognised,
|
||||||
// FeedbackInternal,
|
threads,
|
||||||
// "SELECT
|
user_id,
|
||||||
// time, description, helpful
|
device_user_provided
|
||||||
// FROM
|
FROM
|
||||||
// kaizen_feedbacks
|
survey_responses
|
||||||
// WHERE campaign_id = (
|
WHERE
|
||||||
// SELECT uuid
|
campaign_id = (
|
||||||
// FROM
|
SELECT ID FROM survey_campaigns
|
||||||
// survey_campaigns
|
WHERE
|
||||||
// WHERE
|
ID = $1
|
||||||
// uuid = $1
|
AND
|
||||||
// AND
|
user_id = (SELECT ID FROM survey_admins WHERE name = $2)
|
||||||
// user_id = (
|
)
|
||||||
// SELECT
|
LIMIT $3 OFFSET $4
|
||||||
// ID
|
",
|
||||||
// FROM
|
uuid,
|
||||||
// kaizen_users
|
username,
|
||||||
// WHERE
|
limit as i32,
|
||||||
// name = $2
|
page as i32,
|
||||||
// )
|
)
|
||||||
// )",
|
.fetch_all(&data.db)
|
||||||
// uuid,
|
.await?;
|
||||||
// username
|
|
||||||
// )
|
let mut responses = Vec::with_capacity(db_responses.len());
|
||||||
// .fetch_all(&data.db);
|
println!("responses {:?}", db_responses);
|
||||||
// let (name, mut feedbacks) = try_join!(name_fut, feedback_fut)?;
|
for r in db_responses.drain(0..) {
|
||||||
// //.await?;
|
let benches_fut = sqlx::query_as!(
|
||||||
//
|
Bench,
|
||||||
// let mut feedback_resp = Vec::with_capacity(feedbacks.len());
|
"SELECT
|
||||||
// feedbacks.drain(0..).for_each(|f| {
|
duration,
|
||||||
// feedback_resp.push(Feedback {
|
difficulty
|
||||||
// time: f.time.unix_timestamp() as u64,
|
FROM
|
||||||
// description: f.description,
|
survey_benches
|
||||||
// helpful: f.helpful,
|
WHERE
|
||||||
// });
|
resp_id = $1
|
||||||
// });
|
",
|
||||||
//
|
r.id,
|
||||||
// Ok(GetFeedbackResp {
|
)
|
||||||
// feedbacks: feedback_resp,
|
.fetch_all(&data.db);
|
||||||
// name: name.name,
|
|
||||||
// })
|
let user_fut = sqlx::query_as!(
|
||||||
// }
|
InnerU,
|
||||||
|
"SELECT
|
||||||
|
created_at,
|
||||||
|
ID
|
||||||
|
FROM
|
||||||
|
survey_users
|
||||||
|
WHERE
|
||||||
|
ID = $1
|
||||||
|
",
|
||||||
|
r.user_id,
|
||||||
|
)
|
||||||
|
.fetch_one(&data.db);
|
||||||
|
|
||||||
|
let (benches, user) = try_join!(benches_fut, user_fut)?;
|
||||||
|
let user = user.into();
|
||||||
|
responses.push(SurveyResponse {
|
||||||
|
benches,
|
||||||
|
user,
|
||||||
|
device_user_provided: r.device_user_provided,
|
||||||
|
device_software_recognised: r.device_software_recognised,
|
||||||
|
id: r.id as usize,
|
||||||
|
threads: r.threads.map(|t| t as usize),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Ok(responses)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn delete(
|
pub async fn delete(
|
||||||
uuid: &Uuid,
|
uuid: &Uuid,
|
||||||
|
@ -236,11 +277,11 @@ pub mod runners {
|
||||||
WHERE
|
WHERE
|
||||||
user_id = (
|
user_id = (
|
||||||
SELECT
|
SELECT
|
||||||
ID
|
ID
|
||||||
FROM
|
FROM
|
||||||
survey_admins
|
survey_admins
|
||||||
WHERE
|
WHERE
|
||||||
name = $1
|
name = $1
|
||||||
)
|
)
|
||||||
AND
|
AND
|
||||||
id = ($2)",
|
id = ($2)",
|
||||||
|
@ -269,35 +310,23 @@ pub async fn delete(
|
||||||
Ok(HttpResponse::Ok())
|
Ok(HttpResponse::Ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[derive(Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
//pub struct Feedback {
|
pub struct SurveyResponse {
|
||||||
// pub time: u64,
|
pub user: SurveyUser,
|
||||||
// pub description: String,
|
pub device_user_provided: String,
|
||||||
// pub helpful: bool,
|
pub device_software_recognised: String,
|
||||||
//}
|
pub id: usize,
|
||||||
//
|
pub threads: Option<usize>,
|
||||||
//#[derive(Serialize, Deserialize)]
|
pub benches: Vec<Bench>,
|
||||||
//pub struct GetFeedbackResp {
|
}
|
||||||
// pub name: String,
|
|
||||||
// pub feedbacks: Vec<Feedback>,
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//#[actix_web_codegen_const_routes::post(
|
|
||||||
// path = "crate::V1_API_ROUTES.campaign.get_feedback",
|
|
||||||
// wrap = "crate::CheckLogin"
|
|
||||||
//)]
|
|
||||||
//pub async fn get_feedback(
|
|
||||||
// id: Identity,
|
|
||||||
// data: AppData,
|
|
||||||
// path: web::Path<String>,
|
|
||||||
//) -> ServiceResult<impl Responder> {
|
|
||||||
// let username = id.identity().unwrap();
|
|
||||||
// let path = path.into_inner();
|
|
||||||
// let feedback_resp = runners::get_feedback(&username, &path, &data).await?;
|
|
||||||
// Ok(HttpResponse::Ok().json(feedback_resp))
|
|
||||||
//}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct SurveyUser {
|
||||||
|
pub created_at: i64, // OffsetDateTime,
|
||||||
|
pub id: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct ListCampaignResp {
|
pub struct ListCampaignResp {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub uuid: String,
|
pub uuid: String,
|
||||||
|
@ -317,13 +346,13 @@ pub async fn list_campaign(
|
||||||
Ok(HttpResponse::Ok().json(list_resp))
|
Ok(HttpResponse::Ok().json(list_resp))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct AddCapmaign {
|
pub struct AddCapmaign {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub difficulties: Vec<i32>,
|
pub difficulties: Vec<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct AddCapmaignResp {
|
pub struct AddCapmaignResp {
|
||||||
pub campaign_id: String,
|
pub campaign_id: String,
|
||||||
}
|
}
|
||||||
|
@ -431,6 +460,29 @@ mod tests {
|
||||||
let list = list_campaings(data.clone(), cookies.clone()).await;
|
let list = list_campaings(data.clone(), cookies.clone()).await;
|
||||||
assert!(list.iter().any(|c| c.name == NAME));
|
assert!(list.iter().any(|c| c.name == NAME));
|
||||||
|
|
||||||
|
let responses = super::runners::get_results(
|
||||||
|
NAME,
|
||||||
|
&uuid::Uuid::parse_str(&campaign.campaign_id).unwrap(),
|
||||||
|
&AppData::new(data.clone()),
|
||||||
|
0,
|
||||||
|
50,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(responses.len(), 1);
|
||||||
|
assert_eq!(responses[0].threads, Some(THREADS as usize));
|
||||||
|
let mut l = responses[0].benches.clone();
|
||||||
|
l.sort_by(|a, b| a.difficulty.cmp(&b.difficulty));
|
||||||
|
let mut r = BENCHES.clone();
|
||||||
|
r.sort_by(|a, b| a.difficulty.cmp(&b.difficulty));
|
||||||
|
|
||||||
|
assert_eq!(l, r);
|
||||||
|
assert_eq!(
|
||||||
|
responses[0].device_software_recognised,
|
||||||
|
DEVICE_SOFTWARE_RECOGNISED
|
||||||
|
);
|
||||||
|
assert_eq!(responses[0].device_user_provided, DEVICE_USER_PROVIDED);
|
||||||
|
|
||||||
bad_post_req_test_witout_payload(
|
bad_post_req_test_witout_payload(
|
||||||
NAME,
|
NAME,
|
||||||
PASSWORD,
|
PASSWORD,
|
||||||
|
|
|
@ -157,13 +157,13 @@ async fn register(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Bench {
|
pub struct Bench {
|
||||||
pub duration: f32,
|
pub duration: f32,
|
||||||
pub difficulty: i32,
|
pub difficulty: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Submission {
|
pub struct Submission {
|
||||||
pub device_user_provided: String,
|
pub device_user_provided: String,
|
||||||
pub device_software_recognised: String,
|
pub device_software_recognised: String,
|
||||||
|
@ -171,7 +171,7 @@ pub struct Submission {
|
||||||
pub benches: Vec<Bench>,
|
pub benches: Vec<Bench>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct SubmissionProof {
|
pub struct SubmissionProof {
|
||||||
pub token: String,
|
pub token: String,
|
||||||
pub proof: String,
|
pub proof: String,
|
||||||
|
@ -304,7 +304,7 @@ async fn submit(
|
||||||
Ok(HttpResponse::Ok().json(resp))
|
Ok(HttpResponse::Ok().json(resp))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct BenchConfig {
|
pub struct BenchConfig {
|
||||||
pub difficulties: Vec<i32>,
|
pub difficulties: Vec<i32>,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue