Fix some things (#32)

Fixes the issue with the background color not taking up the whole screen. This was noticeable when the page was loading in dark mode, the user would get a white flash.

Fixes the docker build with axum that was never tested with the axum integration PR.

Removed useless dependencies at the workspace level.

Rustywind has done some tailwind classes sorting here and there where files were saved.

Co-authored-by: Miroito <alban.vachette@gmail.com>
Reviewed-on: #32
pull/33/head
alban 3 years ago
parent b65cde32e4
commit 3cfbf0e5f2

4
Cargo.lock generated

@ -971,10 +971,6 @@ dependencies = [
[[package]] [[package]]
name = "fast-insiders" name = "fast-insiders"
version = "0.1.0" version = "0.1.0"
dependencies = [
"client",
"server",
]
[[package]] [[package]]
name = "fastrand" name = "fastrand"

@ -5,10 +5,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
server = { version = "0.1.0", path = "./server" }
client = { version = "0.1.0", path = "./client" }
[workspace] [workspace]
members = ["server", "client"] members = ["server", "client"]
@ -18,4 +14,3 @@ serde = { version = "1.0.152", features = ["derive"] }
dotenvy = "0.15.6" dotenvy = "0.15.6"
envy = "0.4.2" envy = "0.4.2"
serde_json = "1.0.91" serde_json = "1.0.91"
# chrono = { workspace = true, features = ["serde"] }

@ -33,13 +33,13 @@ pub fn TheHeader<'a, G: Html>(cx: Scope<'a>) -> View<G> {
"Fast Insiders" "Fast Insiders"
} }
} }
div (class="grow text-left") { div (class="text-left grow") {
a (id="header-all-transactions", href="/transactions", class="hover:underline") { a (id="header-all-transactions", href="/transactions", class="hover:underline") {
"All transactions" "All transactions"
} }
} }
div (class="flex-none") { div (class="flex-none") {
button (on:click=toggle_dark_mode, class="mx-1 py-1 px-2 bg-slate-200 dark:bg-slate-800 rounded-full") button (on:click=toggle_dark_mode, class="py-1 px-2 mx-1 rounded-full bg-slate-200 dark:bg-slate-800")
{ "Toggle dark mode" } { "Toggle dark mode" }
} }
} }

@ -35,10 +35,18 @@ fn index_page<G: Html>(cx: Scope) -> View<G> {
table_class: table_classes, table_class: table_classes,
}; };
let dark_mode_class = create_memo(cx, || {
if *global_state.dark_mode.get() {
"dark"
} else {
""
}
});
view! {cx, view! {cx,
main (class=if *global_state.dark_mode.get() { "dark" } else { "" }) { main (class=format!("{} flex flex-1", dark_mode_class)) {
div (class="bg-slate-200 dark:bg-slate-700 text-slate-700 dark:text-slate-100 font-sans") { div (class="flex-1 font-sans bg-slate-200 text-slate-700 dark:bg-slate-700 dark:text-slate-100") {
TheHeader() TheHeader()
MainContentContainer(useless_prop=1) { MainContentContainer(useless_prop=1) {
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") {
@ -55,9 +63,9 @@ fn index_page<G: Html>(cx: Scope) -> View<G> {
} }
} }
} }
}
} }
} }
}
} }
pub fn get_template<G: Html>() -> Template<G> { pub fn get_template<G: Html>() -> Template<G> {

@ -25,7 +25,6 @@ pub struct TransactionsPageState {
#[auto_scope] #[auto_scope]
fn transactions_page<G: Html>(cx: Scope, state: &TransactionsPageStateRx) -> View<G> { fn transactions_page<G: Html>(cx: Scope, state: &TransactionsPageStateRx) -> View<G> {
let global_state = Reactor::<G>::from_cx(cx).get_global_state::<AppStateRx>(cx); let global_state = Reactor::<G>::from_cx(cx).get_global_state::<AppStateRx>(cx);
let dark_mode = &global_state.dark_mode;
let expand = create_signal(cx, false); let expand = create_signal(cx, false);
let filter_expand = BaseButtonStateRx { let filter_expand = BaseButtonStateRx {
@ -73,33 +72,41 @@ fn transactions_page<G: Html>(cx: Scope, state: &TransactionsPageStateRx) -> Vie
} }
}); });
let dark_mode_class = create_memo(cx, || {
if *global_state.dark_mode.get() {
"dark"
} else {
""
}
});
view! {cx, view! {cx,
main (class=if *dark_mode.get() { "dark" } else { "" }) { main (class=format!("{} flex flex-1", dark_mode_class)) {
div (class="bg-slate-200 dark:bg-slate-700 text-slate-700 dark:text-slate-100 font-sans") { div (class="flex-1 font-sans bg-slate-200 text-slate-700 dark:bg-slate-700 dark:text-slate-100") {
TheHeader() TheHeader()
MainContentContainer(useless_prop=1) { MainContentContainer(useless_prop=1) {
a (class="hover:underline", href="/transactions") { a (class="hover:underline", href="/transactions") {
h1 ( h1 (
class="text-center text-lg" class="text-lg text-center"
) { ) {
"Insider Transactions published by the AMF" "Insider Transactions published by the AMF"
}
} }
BaseButton(filter_expand) }
div (id="filters", BaseButton(filter_expand)
class=format!("p-2 border rounded-lg border-slate-200 dark:border-slate-800 bg-slate-200 dark:bg-slate-700 transition-all ease-in {}", div (id="filters",
if *expand.get() { "h-40 visible" } else { "h-0 collapse" }, class=format!("p-2 border rounded-lg border-slate-200 dark:border-slate-800 bg-slate-200 dark:bg-slate-700 transition-all ease-in {}",
) if *expand.get() { "h-40 visible" } else { "h-0 collapse" },
) )
{ )
{
div (class="w-80") { div (class="w-80") {
p () {"Search for a company:"} p () {"Search for a company:"}
BaseAsyncSelect(async_select_prop) BaseAsyncSelect(async_select_prop)
BaseButton(search_button) BaseButton(search_button)
} }
} }
PaginatedTable(paginated_table_state) PaginatedTable(paginated_table_state)
} }
} }
} }
} }

@ -1,3 +1,20 @@
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
html {
height: 100%;
width: 100%;
}
body {
min-height: 100%;
display: flex;
flex-direction: column;
}
div#root {
flex: 1;
display: flex;
flex-direction: column;
}

File diff suppressed because one or more lines are too long

@ -1,4 +1,4 @@
version: '3' version: "3"
services: services:
client: client:
container_name: fast-insiders-client container_name: fast-insiders-client
@ -6,7 +6,7 @@ services:
build: build:
context: . context: .
args: args:
API_URL: http://localhost:8000/v1/ API_URL: http://localhost:8000/
dockerfile: ./client/Dockerfile dockerfile: ./client/Dockerfile
restart: always restart: always
ports: ports:
@ -19,7 +19,7 @@ services:
build: build:
context: . context: .
args: args:
API_URL: http://localhost:8000/v1/ API_URL: http://localhost:8000/
dockerfile: ./server/Dockerfile dockerfile: ./server/Dockerfile
restart: always restart: always
ports: ports:
@ -44,9 +44,7 @@ services:
- MYSQL_DATABASE=fast_insiders - MYSQL_DATABASE=fast_insiders
- MYSQL_USER=fiuser - MYSQL_USER=fiuser
volumes: volumes:
fi-data: fi-data:
driver: local driver: local
db: db:

@ -13,7 +13,7 @@ server-dev:
tailwind: tailwind:
cd client && \ cd client && \
tailwindcss -i static/style.css -o static/tailwind.css -w tailwindcss -i static/style.css -o static/tailwind.css -w --minify
serve: serve:
cd client && \ cd client && \

@ -1,8 +1,8 @@
FROM rust:1.66-slim as build FROM rust:1.66-slim as build
# Install build dependencies # Install build dependencies
RUN apt update \ RUN apt-get update \
&& apt install -y --no-install-recommends lsb-release apt-transport-https \ && apt-get install -y --no-install-recommends lsb-release apt-transport-https \
build-essential curl wget pkg-config libssl-dev build-essential curl wget pkg-config libssl-dev
# Root of the project # Root of the project
@ -21,20 +21,23 @@ RUN rustup default nightly
ARG API_URL ARG API_URL
ENV API_URL=$API_URL ENV API_URL=$API_URL
# go to src dir
WORKDIR /app/server
# Build the final binary # Build the final binary
RUN cargo build --release --bin server RUN cargo build --release
# prepare deployment image # prepare deployment image
FROM debian:stable-slim FROM debian:stable-slim
# For tls to work # For tls to work
RUN apt-get update && apt-get -y install ca-certificates libssl-dev && rm -rf /var/lib/apt/lists/* RUN apt-get update && apt-get -y --no-install-recommends install ca-certificates libssl-dev && rm -rf /var/lib/apt/lists/*
WORKDIR /app WORKDIR /app
COPY --from=build /app/target/release/server /app/ COPY --from=build /app/target/release/server /app/
ENV ROCKET_ADDRESS=0.0.0.0 ENV HOST=0.0.0.0
CMD ./server CMD ["./server"]

@ -1,7 +1,13 @@
use std::net::SocketAddr;
use serde::Deserialize; use serde::Deserialize;
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct Env { pub struct Env {
#[serde(default = "host_default")]
pub host: String,
#[serde(default = "port_default")]
pub port: String,
pub mysql_user: String, pub mysql_user: String,
pub mysql_password: String, pub mysql_password: String,
pub mysql_host: String, pub mysql_host: String,
@ -31,6 +37,14 @@ pub struct Env {
pub get_amf_transaction_interval: u64, pub get_amf_transaction_interval: u64,
} }
fn host_default() -> String {
"127.0.0.1".to_string()
}
fn port_default() -> String {
"8000".to_string()
}
fn mysql_port_default() -> String { fn mysql_port_default() -> String {
"3306".to_string() "3306".to_string()
} }
@ -92,6 +106,7 @@ impl Env {
#[derive(Debug)] #[derive(Debug)]
pub struct Config { pub struct Config {
pub server_address: SocketAddr,
pub database_url: String, pub database_url: String,
pub max_connections: u32, pub max_connections: u32,
pub min_connections: u32, pub min_connections: u32,
@ -113,7 +128,12 @@ impl Config {
env.mysql_user, env.mysql_password, env.mysql_host, env.mysql_port, env.mysql_database env.mysql_user, env.mysql_password, env.mysql_host, env.mysql_port, env.mysql_database
); );
let server_address = format!("{}:{}", env.host, env.port)
.parse()
.expect("Could not parse host and port combination into a valid server address");
let mut config = Config { let mut config = Config {
server_address,
database_url, database_url,
max_connections: env.max_connections, max_connections: env.max_connections,
min_connections: env.min_connections, min_connections: env.min_connections,

@ -16,7 +16,7 @@ use axum::{
Router, Router,
}; };
use sea_orm::DatabaseConnection; use sea_orm::DatabaseConnection;
use std::{net::SocketAddr, time::Duration}; use std::time::Duration;
use tokio::signal; use tokio::signal;
use tower_http::{classify::ServerErrorsFailureClass, cors::CorsLayer, trace::TraceLayer}; use tower_http::{classify::ServerErrorsFailureClass, cors::CorsLayer, trace::TraceLayer};
use tracing::{info, info_span, Span}; use tracing::{info, info_span, Span};
@ -136,7 +136,8 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Run tasks // Run tasks
tokio::task::spawn(async move { run_tasks(&shared_state.db).await }); tokio::task::spawn(async move { run_tasks(&shared_state.db).await });
let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); let addr = CONFIG.server_address;
info!("Server will start listening on {}", addr);
axum::Server::bind(&addr) axum::Server::bind(&addr)
.serve(app.into_make_service()) .serve(app.into_make_service())
.with_graceful_shutdown(shutdown_signal()) .with_graceful_shutdown(shutdown_signal())

Loading…
Cancel
Save