diff --git a/.config/nix/.gitignore.nix b/.config/nix/.gitignore.nix new file mode 100644 index 0000000..2509694 --- /dev/null +++ b/.config/nix/.gitignore.nix @@ -0,0 +1,11 @@ +{ pkgs }: + +let + createDotGitignore = content: pkgs.writeText ".gitignore" content; +in + createDotGitignore '' + /target + /node_modules + .direnv + result + '' diff --git a/.config/nix/.npmrc.nix b/.config/nix/.npmrc.nix new file mode 100644 index 0000000..902d6ff --- /dev/null +++ b/.config/nix/.npmrc.nix @@ -0,0 +1,13 @@ +{ nixago }: + +let + data = { + modules-dir = "project_dependencies/node/"; + }; +in +nixago.lib.make { + inherit data; + output = ".npmrc"; + format = "ini"; # Optional if it matches the file extension + engine = nixago.engines.nix { }; # Optional as this is the default engine +} \ No newline at end of file diff --git a/.config/nix/Cargo.nix b/.config/nix/Cargo.nix new file mode 100644 index 0000000..11cc74b --- /dev/null +++ b/.config/nix/Cargo.nix @@ -0,0 +1,51 @@ +{nixago}: + +let + data = { + package = { + name = "sk_tcg_trader"; + version = "0.1.0"; + edition = "2021"; + }; + dependencies = { + axum = "0.6.19"; + chrono = "0.4.26"; + dotenv = "0.15.0"; + hyper = "0.14.27"; + indicatif = "0.17.5"; + lazy_static = "1.4.0"; + prometheus = "0.13.3"; + reqwest = { + version = "0.11.18"; + features = ["json"]; + }; + serde = { + version = "1.0.178"; + features = ["derive"]; + }; + serde_json = "1.0.104"; + tokio = { + version = "1.29.1"; + features = ["full"]; + }; + anyhow = "1.0.72"; + askama = "0.12.0"; + tower = "0.4.13"; + tower-http = { + version = "0.4.3"; + features = ["fs"]; + }; + tracing = "0.1.37"; + tracing-subscriber = { + version = "0.3.17"; + features = ["env-filter"]; + }; + }; + }; +in +nixago.lib.make { + inherit data; + output = "Cargo.toml"; + format = "toml"; # Optional if it matches the file extension + engine = nixago.engines.nix { }; # Optional as this is the default engine +} \ No newline at end of file diff --git a/.config/nix/env.nix b/.config/nix/env.nix new file mode 100644 index 0000000..93b0960 --- /dev/null +++ b/.config/nix/env.nix @@ -0,0 +1,9 @@ +{ pkgs }: + +let + toEnvFile = attrs: pkgs.writeText "myenvfile.env" (nixpkgs.lib.generators.toKeyValue {} attrs); +in + toEnvFile { + UPDATE_INTERVAL = "12"; + PORT = "8080"; + } diff --git a/.config/nix/package.nix b/.config/nix/package.nix new file mode 100644 index 0000000..16321c2 --- /dev/null +++ b/.config/nix/package.nix @@ -0,0 +1,17 @@ +{ nixago }: + +let + data = { + devDependencies = { + prettier = "^3.0.1"; + prettier-plugin-tailwindcss = "^0.4.1"; + tailwindcss = "^3.3.3"; + }; + }; +in +nixago.lib.make { + inherit data; + output = "package.json"; + format = "json"; # Optional if it matches the file extension + engine = nixago.engines.nix { }; # Optional as this is the default engine +} \ No newline at end of file diff --git a/.env b/.env deleted file mode 100644 index 1b128c7..0000000 --- a/.env +++ /dev/null @@ -1,2 +0,0 @@ -UPDATE_INTERVAL=12 -PORT=8080 \ No newline at end of file diff --git a/assets/main.css b/assets/main.css index 9b9c0ca..a0809c4 100644 --- a/assets/main.css +++ b/assets/main.css @@ -551,6 +551,30 @@ video { display: flex; } +.table { + display: table; +} + +.h-6 { + height: 1.5rem; +} + +.h-8 { + height: 2rem; +} + +.w-6 { + width: 1.5rem; +} + +.w-8 { + width: 2rem; +} + +.border-collapse { + border-collapse: collapse; +} + .flex-col { flex-direction: column; } @@ -559,8 +583,27 @@ video { align-items: center; } -.rounded-lg { - border-radius: 0.5rem; +.rounded-xl { + border-radius: 0.75rem; +} + +.border-2 { + border-width: 2px; +} + +.border-gray-950 { + --tw-border-opacity: 1; + border-color: rgb(3 7 18 / var(--tw-border-opacity)); +} + +.bg-gray-300 { + --tw-bg-opacity: 1; + background-color: rgb(209 213 219 / var(--tw-bg-opacity)); +} + +.bg-gray-500 { + --tw-bg-opacity: 1; + background-color: rgb(107 114 128 / var(--tw-bg-opacity)); } .bg-purple-500 { @@ -573,8 +616,12 @@ video { background-color: rgb(51 65 85 / var(--tw-bg-opacity)); } -.p-4 { - padding: 1rem; +.p-2 { + padding: 0.5rem; +} + +.text-center { + text-align: center; } .text-2xl { @@ -582,6 +629,11 @@ video { line-height: 2rem; } +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + .text-xl { font-size: 1.25rem; line-height: 1.75rem; @@ -591,6 +643,16 @@ video { font-weight: 700; } +.text-gray-100 { + --tw-text-opacity: 1; + color: rgb(243 244 246 / var(--tw-text-opacity)); +} + +.text-gray-900 { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); +} + .text-white { --tw-text-opacity: 1; color: rgb(255 255 255 / var(--tw-text-opacity)); diff --git a/flake.lock b/flake.lock index 606a787..0a5d1b1 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,354 @@ { "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_5": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_6": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_7": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_8": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_9": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixago": { + "inputs": { + "flake-utils": "flake-utils", + "nixago-exts": "nixago-exts", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1687381756, + "narHash": "sha256-IUMIlYfrvj7Yli4H2vvyig8HEPpfCeMaE6+kBGPzFyk=", + "owner": "jmgilman", + "repo": "nixago", + "rev": "dacceb10cace103b3e66552ec9719fa0d33c0dc9", + "type": "github" + }, + "original": { + "owner": "jmgilman", + "repo": "nixago", + "type": "github" + } + }, + "nixago-exts": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixago": "nixago_2", + "nixpkgs": [ + "nixago", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1676070308, + "narHash": "sha256-QaJ65oc2l8iwQIGWUJ0EKjCeSuuCM/LqR8RauxZUUkc=", + "owner": "nix-community", + "repo": "nixago-extensions", + "rev": "e5380cb0456f4ea3c86cf94e3039eb856bf07d0b", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixago-extensions", + "type": "github" + } + }, + "nixago-exts_2": { + "inputs": { + "flake-utils": "flake-utils_4", + "nixago": "nixago_3", + "nixpkgs": [ + "nixago", + "nixago-exts", + "nixago", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1655508669, + "narHash": "sha256-BDDdo5dZQMmwNH/GNacy33nPBnCpSIydWFPZs0kkj/g=", + "owner": "nix-community", + "repo": "nixago-extensions", + "rev": "3022a932ce109258482ecc6568c163e8d0b426aa", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixago-extensions", + "type": "github" + } + }, + "nixago-exts_3": { + "inputs": { + "flake-utils": "flake-utils_6", + "nixago": "nixago_4", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1676070308, + "narHash": "sha256-QaJ65oc2l8iwQIGWUJ0EKjCeSuuCM/LqR8RauxZUUkc=", + "owner": "nix-community", + "repo": "nixago-extensions", + "rev": "e5380cb0456f4ea3c86cf94e3039eb856bf07d0b", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixago-extensions", + "type": "github" + } + }, + "nixago-exts_4": { + "inputs": { + "flake-utils": "flake-utils_8", + "nixago": "nixago_5", + "nixpkgs": [ + "nixago-exts", + "nixago", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1655508669, + "narHash": "sha256-BDDdo5dZQMmwNH/GNacy33nPBnCpSIydWFPZs0kkj/g=", + "owner": "nix-community", + "repo": "nixago-extensions", + "rev": "3022a932ce109258482ecc6568c163e8d0b426aa", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixago-extensions", + "type": "github" + } + }, + "nixago_2": { + "inputs": { + "flake-utils": "flake-utils_3", + "nixago-exts": "nixago-exts_2", + "nixpkgs": [ + "nixago", + "nixago-exts", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1676070010, + "narHash": "sha256-iYzJIWptE1EUD8VINAg66AAMUajizg8JUYN3oBmb8no=", + "owner": "nix-community", + "repo": "nixago", + "rev": "d480ba6c0c16e2c5c0bd2122852d6a0c9ad1ed0e", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "rename-config-data", + "repo": "nixago", + "type": "github" + } + }, + "nixago_3": { + "inputs": { + "flake-utils": "flake-utils_5", + "nixpkgs": [ + "nixago", + "nixago-exts", + "nixago", + "nixago-exts", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1655405483, + "narHash": "sha256-Crd49aZWNrpczlRTOwWGfwBMsTUoG9vlHDKQC7cx264=", + "owner": "nix-community", + "repo": "nixago", + "rev": "e6a9566c18063db5b120e69e048d3627414e327d", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixago", + "type": "github" + } + }, + "nixago_4": { + "inputs": { + "flake-utils": "flake-utils_7", + "nixago-exts": "nixago-exts_4", + "nixpkgs": [ + "nixago-exts", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1676070010, + "narHash": "sha256-iYzJIWptE1EUD8VINAg66AAMUajizg8JUYN3oBmb8no=", + "owner": "nix-community", + "repo": "nixago", + "rev": "d480ba6c0c16e2c5c0bd2122852d6a0c9ad1ed0e", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "rename-config-data", + "repo": "nixago", + "type": "github" + } + }, + "nixago_5": { + "inputs": { + "flake-utils": "flake-utils_9", + "nixpkgs": [ + "nixago-exts", + "nixago", + "nixago-exts", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1655405483, + "narHash": "sha256-Crd49aZWNrpczlRTOwWGfwBMsTUoG9vlHDKQC7cx264=", + "owner": "nix-community", + "repo": "nixago", + "rev": "e6a9566c18063db5b120e69e048d3627414e327d", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixago", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1685566663, @@ -17,6 +366,8 @@ }, "root": { "inputs": { + "nixago": "nixago", + "nixago-exts": "nixago-exts_3", "nixpkgs": "nixpkgs" } } diff --git a/flake.nix b/flake.nix index e01a16e..43326de 100644 --- a/flake.nix +++ b/flake.nix @@ -1,12 +1,45 @@ { description = "A TCG card trading tool written in Rust"; - inputs.nixpkgs.url = "nixpkgs/23.05"; - - outputs = { self, nixpkgs }: let + inputs={ + nixpkgs.url = "nixpkgs/23.05"; + nixago = { + url = "github:jmgilman/nixago"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + nixago-exts = { + url = "github:nix-community/nixago-extensions"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { self, nixpkgs, nixago, nixago-exts }: let system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; + build-tailwind = pkgs.writeShellScriptBin "build-tailwind" '' + #!/usr/bin/env zsh + set -e + export PATH=${pkgs.nodejs_20}/bin:${pkgs.nodePackages_latest.pnpm}/bin:$PATH + pnpm dlx tailwindcss -i src/styles/tailwind.css -o assets/main.css --watch + ''; + + # gitignore = import "${self}/.config/nix/.gitignore.nix" { inherit pkgs; }; + # npmrc = import "${self}/.config/nix/.npmrc.nix" { inherit nixago; }; + # cargoConfig = import "${self}/.config/nix/cargo.nix" { inherit nixago; }; + # env = import "${self}/.config/nix/env.nix" { inherit pkgs; }; + # package = import "${self}/.config/nix/package.nix" { inherit nixago; }; + + + # Combine all shell hooks + # combinedShellHook = '' + # ${gitignore} + # ${npmrc.shellHook} + # ${cargoConfig.shellHook} + # ${env} + # ${package.shellHook} + # ''; + in { defaultPackage.${system} = with pkgs; stdenv.mkDerivation { name = "sk-tcg-trader"; @@ -28,6 +61,8 @@ export OPENSSL_LIB_DIR=${openssl.out}/lib export OPENSSL_INCLUDE_DIR=${openssl.dev}/include ''; + # ${combinedShellHook} # Include the combined shell hooks goes in shell hook }; + tailwind = build-tailwind; }; } diff --git a/src/cards.rs b/src/cards.rs index 4f0a39b..2617d80 100644 --- a/src/cards.rs +++ b/src/cards.rs @@ -19,11 +19,18 @@ pub struct Card { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct CardFromFile { - name: String, - count: usize, - usd_value: Option, + pub name: String, + pub count: i32, + pub usd_value: Option, } +pub struct CardForTemplate { + pub name: String, + pub count: i32, + pub usd_value: String, // No longer an Option +} + + #[derive(Serialize, Deserialize, Debug)] pub struct CardFile { pub cards: Vec, @@ -63,8 +70,8 @@ pub fn get_data_update_interval() -> Result> { pub fn process_export_data(cards: &mut Vec) { cards.sort_by(|a, b| b.usd_value.partial_cmp(&a.usd_value).unwrap()); - let top_10_cards = &cards[..10]; - for card in top_10_cards { + let cards = &cards[..10]; + for card in cards { if let Some(price_str) = &card.usd_value { let value = price_str.parse::().unwrap(); CARD_VALUES.with_label_values(&[&card.name]).set(value); @@ -80,9 +87,7 @@ pub async fn process_cards(interval: &mut tokio::time::Interval) -> Result<(), B } let file_path = &args[1]; - let file = File::open(file_path)?; - let reader = BufReader::new(file); - let mut cards_data: CardFile = serde_json::from_reader(reader)?; + let mut cards_data = read_card_file(file_path).await?; let pb = util::setup_progress_bar(cards_data.cards.len() as u64); for card_from_file in &mut cards_data.cards { @@ -103,8 +108,16 @@ pub async fn process_cards(interval: &mut tokio::time::Interval) -> Result<(), B Ok(()) } + pub fn setup_registry() -> Result, Box> { let registry = Arc::new(Registry::new()); registry.register(Box::new(CARD_VALUES.clone())).unwrap(); Ok(registry) -} \ No newline at end of file +} + +pub async fn read_card_file(file_path: &str) -> Result> { + let file = File::open(file_path)?; + let reader = BufReader::new(file); + let cards_data: CardFile = serde_json::from_reader(reader)?; + Ok(cards_data) +} diff --git a/src/handlers.rs b/src/handlers.rs index c1a5138..fddb5ba 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -1,13 +1,32 @@ use axum::response::IntoResponse; +use hyper::StatusCode; +use crate::cards::{read_card_file, CardForTemplate}; use crate::templates::RootTemplate; use crate::util::HtmlTemplate; -pub async fn root() -> impl IntoResponse { - let template = RootTemplate { - name: "Steven" - }; - HtmlTemplate(template) +pub async fn root() -> Result, (StatusCode, String)> { + let file_path = "test_data/test.json"; + match read_card_file(file_path).await { + Ok(card_file) => { + let cards_for_template: Vec<_> = card_file.cards + .into_iter() + .map(|card| CardForTemplate { + name: card.name, + count: card.count, + usd_value: card.usd_value.unwrap_or_else(|| "N/A".into()), + }) + .collect(); + let template = RootTemplate { + name: "Steven".to_string(), + cards: cards_for_template, + }; + Ok(HtmlTemplate(template)) + }, + Err(err) => { + Err((StatusCode::INTERNAL_SERVER_ERROR, format!("An error occurred: {}", err))) + }, + } } pub async fn health() -> impl IntoResponse { diff --git a/src/main.rs b/src/main.rs index 3b55547..1f6a1c4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ use cards::{setup_registry, get_data_update_interval}; #[tokio::main] async fn main() -> Result<(), Box> { - dotenv::from_filename(".config/app.env").ok(); + dotenv::from_filename(".config/.env").ok(); let update_interval = get_data_update_interval()?; let registry = setup_registry()?; diff --git a/src/templates.rs b/src/templates.rs index 4865990..9e75f2a 100644 --- a/src/templates.rs +++ b/src/templates.rs @@ -1,11 +1,17 @@ use askama::Template; +use crate::cards::CardForTemplate; + + #[derive(Template)] #[template(path = "root.html")] -pub struct RootTemplate<'a>{ - pub name: &'a str, +pub struct RootTemplate { + pub name: String, + pub cards: Vec, } + + #[derive(Template)] #[template(path="base.html")] pub struct BaseTemplate; diff --git a/templates/base.html b/templates/base.html index 818da0b..5250d3d 100644 --- a/templates/base.html +++ b/templates/base.html @@ -4,6 +4,7 @@ SK TCG Trader + {% block style %}{% endblock %} {% block body %}{% endblock %} diff --git a/templates/root.html b/templates/root.html index 1ab0dd0..ff8e293 100644 --- a/templates/root.html +++ b/templates/root.html @@ -1,20 +1,34 @@ -{% extends "base.html" %} {% block body %} -
-

{{ name }}'s SK TCG Trader

-
-

- Click the button below to get the metrics -

-
-

- -
-{% endblock %} +{% extends "base.html" %} + +{% block body %} +
+ +

{{ name }}'s SK TCG Trader

+ + + + + + + + + + {% for card in cards %} + + + + + + + {% endfor %} + +
Card NameCard ValueCard CountMore Data
{{ card.name }}{{ card.usd_value }}{{ card.count }} + +
+ +
+{% endblock %} \ No newline at end of file