Better index page

pull/28/head
Miroito 3 years ago
parent ddd9e36288
commit eda7176812

@ -1,6 +1,6 @@
use crate::api::types::{ use crate::api::types::{
paginated_response::PaginatedResponse, paginated_response::PaginatedResponse,
transaction::{TransactionCompany, TransactionsAggregated}, transaction::{LatestTransaction, TransactionCompany, TransactionsAggregated},
}; };
pub async fn get_transactions( pub async fn get_transactions(
@ -76,3 +76,34 @@ pub async fn get_aggregated_transactions(
return Ok(res); return Ok(res);
} }
pub async fn get_latest_transactions(
_: Option<String>,
page: i64,
size: i64,
) -> Result<PaginatedResponse<LatestTransaction>, ()> {
use crate::env::Config;
// TODO: Remove build-time environment variable
let api_url = Config::new().api_url;
let route = &format!("{}transaction/latest?page={}&size={}", api_url, page, size,);
#[cfg(client)]
let res = reqwasm::http::Request::get(route)
.send()
.await
.map_err(|_| ())?
.json::<PaginatedResponse<LatestTransaction>>()
.await
.map_err(|_| ())?;
#[cfg(engine)]
let res = reqwest::get(route)
.await
.map_err(|_| ())?
.json::<PaginatedResponse<LatestTransaction>>()
.await
.map_err(|_| ())?;
return Ok(res);
}

@ -3,7 +3,7 @@ use sycamore::prelude::*;
use crate::components::base_table::TableContent; use crate::components::base_table::TableContent;
use super::transaction::{TransactionCompany, TransactionsAggregated}; use super::transaction::{TransactionCompany, TransactionsAggregated, LatestTransaction};
pub trait IntoTableData<G> pub trait IntoTableData<G>
where where
@ -106,3 +106,40 @@ where
} }
} }
} }
impl<G> IntoTableData<G> for PaginatedResponse<LatestTransaction>
where
G: GenericNode,
{
fn into_table_data<'a>(self, cx: Scope<'a>) -> TableContent<G> {
let headers_view = vec![
view! {cx, "Company" },
view! {cx, "nature" },
view! {cx, "Total" },
];
let data_view: Vec<Vec<View<G>>> = self
.list
.into_iter()
.map(|t| {
let mut res = vec![];
res.push(view! {cx,
a (href=format!("transactions/{}", t.slug),
class="text-indigo-800 dark:text-indigo-300 hover:text-indigo-500 dark:hover:text-indigo-600 hover:underline",
) {
(t.company_name.to_owned())
}
});
res.push(view! {cx, (t.nature) });
res.push(view! {cx, (t.total.to_string()) });
res
})
.collect();
TableContent {
headers_view,
data_view,
}
}
}

@ -44,3 +44,11 @@ pub struct TransactionsAggregated {
pub slug: String, pub slug: String,
pub transaction_count: i32, pub transaction_count: i32,
} }
#[derive(Deserialize, Clone)]
pub struct LatestTransaction {
pub company_name: String,
pub slug: String,
pub nature: String,
pub total: f32,
}

@ -1,5 +1,3 @@
use std::rc::Rc;
use perseus::prelude::*; use perseus::prelude::*;
use serde::Deserialize; use serde::Deserialize;
use sycamore::prelude::*; use sycamore::prelude::*;

@ -3,8 +3,8 @@ use sycamore::prelude::*;
use crate::{ use crate::{
api::{ api::{
routes::transaction::get_aggregated_transactions, routes::transaction::{get_aggregated_transactions, get_latest_transactions},
types::transaction::TransactionsAggregated, types::transaction::{LatestTransaction, TransactionsAggregated},
}, },
components::{ components::{
main_content_container::MainContentContainer, main_content_container::MainContentContainer,
@ -19,10 +19,10 @@ fn index_page<G: Html>(cx: Scope) -> View<G> {
let table_classes = create_ref(cx, "w-full".to_string()); let table_classes = create_ref(cx, "w-full".to_string());
let table_transactions_24hours: PaginatedTableStateRx<TransactionsAggregated, _, _> = let latest_transactions: PaginatedTableStateRx<LatestTransaction, _, _> =
PaginatedTableStateRx { PaginatedTableStateRx {
record_label: "companies".to_owned(), record_label: "transactions".to_owned(),
route: get_aggregated_transactions, route: get_latest_transactions,
filter: Some("72".to_string()), filter: Some("72".to_string()),
table_class: table_classes, table_class: table_classes,
}; };
@ -43,9 +43,9 @@ fn index_page<G: Html>(cx: Scope) -> View<G> {
div(class="flex flex-wrap gap-4 justify-around") { div(class="flex flex-wrap gap-4 justify-around") {
div (class="flex-grow") { div (class="flex-grow") {
h1 (class="mb-1 text-center") { h1 (class="mb-1 text-center") {
"Latest insider activity (72h)" "Latest transactions aggregated by nature"
} }
PaginatedTable(table_transactions_24hours) PaginatedTable(latest_transactions)
} }
div (class="flex-grow") { div (class="flex-grow") {
h1 (class="mb-1 text-center") { h1 (class="mb-1 text-center") {

@ -55,6 +55,7 @@ async fn start_rocket() -> Result<(), sea_orm_rocket::rocket::Error> {
route::company::get_by_isin, route::company::get_by_isin,
route::transaction::get_transactions, route::transaction::get_transactions,
route::transaction::get_aggregated_transactions, route::transaction::get_aggregated_transactions,
route::transaction::get_latest_transactions,
route::in_process_transaction::get_all, route::in_process_transaction::get_all,
route::in_process_transaction::retry_failed_transaction, route::in_process_transaction::retry_failed_transaction,
route::in_process_transaction::retry_all route::in_process_transaction::retry_all

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.0
use sea_orm::entity::prelude::*; use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.0
use sea_orm::entity::prelude::*; use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.0
pub mod prelude; pub mod prelude;

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.0
pub use super::company::Entity as Company; pub use super::company::Entity as Company;
pub use super::in_process_transaction::Entity as InProcessTransaction; pub use super::in_process_transaction::Entity as InProcessTransaction;

@ -1,4 +1,4 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6 //! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.0
use sea_orm::entity::prelude::*; use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -20,6 +20,7 @@ pub struct Model {
pub isin: Option<String>, pub isin: Option<String>,
pub instrument: String, pub instrument: String,
pub volume: i32, pub volume: i32,
#[sea_orm(column_type = "Float")]
pub unit_price: f32, pub unit_price: f32,
pub created_at_utc: DateTime, pub created_at_utc: DateTime,
} }

@ -1,15 +1,10 @@
use chrono::{Duration, NaiveDate, NaiveDateTime, Utc}; use chrono::{Duration, NaiveDate, NaiveDateTime, Utc};
use rocket::http::Status; use rocket::{http::Status, response::status::Custom};
use rocket::response::status::Custom; use sea_orm::{
use sea_orm::prelude::*; prelude::*, DbBackend, FromQueryResult, ItemsAndPagesNumber, JoinType, Order, QueryOrder,
use sea_orm::FromQueryResult; QuerySelect, Statement,
use sea_orm::ItemsAndPagesNumber; };
use sea_orm::JoinType; use sea_orm_rocket::{rocket::serde::json::Json, Connection};
use sea_orm::Order;
use sea_orm::QueryOrder;
use sea_orm::QuerySelect;
use sea_orm_rocket::rocket::serde::json::Json;
use sea_orm_rocket::Connection;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::db::paginate::{paginate_also_related, PaginatedResponse}; use crate::db::paginate::{paginate_also_related, PaginatedResponse};
@ -105,6 +100,72 @@ pub async fn get_transactions(
Ok(Json(res)) Ok(Json(res))
} }
#[derive(FromQueryResult, Serialize)]
pub struct LatestTransaction {
company_name: String,
slug: String,
nature: String,
total: f32,
}
#[get("/transaction/latest?<page>&<size>")]
pub async fn get_latest_transactions(
conn: Connection<'_, Db>,
page: Option<u64>,
size: Option<u64>,
) -> Result<Json<PaginatedResponse<LatestTransaction>>, Custom<String>> {
let db = conn.into_inner();
let s = size.unwrap_or(20).min(50);
let query_raw = "SELECT
company.name as company_name,
company.slug,
transaction.nature,
SUM(transaction.volume * transaction.unit_price) as total
FROM transaction
JOIN company ON transaction.company_id = company.id
WHERE DATE(created_at_utc) IN (SELECT DATE(MAX(created_at_utc)) FROM transaction)
GROUP BY company.name, transaction.nature
ORDER BY transaction.nature, total DESC"
.to_string();
let query = model::transaction::Entity::find()
.from_raw_sql(Statement::from_string(
DbBackend::MySql,
query_raw.to_string(),
))
.into_model::<LatestTransaction>();
let pages = query.paginate(db, s);
let ItemsAndPagesNumber {
number_of_items: count,
number_of_pages: num_pages,
} = pages.num_items_and_pages().await.map_err(|e| {
Custom(
Status::InternalServerError,
format!("Database error: {}", e),
)
})?;
let p = page.unwrap_or(0).min(num_pages);
let list = pages.fetch_page(p).await.map_err(|e| {
Custom(
Status::InternalServerError,
format!("Database error: {}", e),
)
})?;
let res = PaginatedResponse {
count,
num_pages,
list,
};
Ok(Json(res))
}
#[get("/transaction/aggregated?<page>&<size>&<hours>")] #[get("/transaction/aggregated?<page>&<size>&<hours>")]
pub async fn get_aggregated_transactions( pub async fn get_aggregated_transactions(
conn: Connection<'_, Db>, conn: Connection<'_, Db>,

Loading…
Cancel
Save