From d7baadec6cc20c22a51bc7ec28249a6b77088e75 Mon Sep 17 00:00:00 2001 From: Vivian Lim Date: Sun, 19 Jul 2020 18:26:49 -0700 Subject: [PATCH] data is being loaded into preact SPA --- Cargo.lock | 16 +++++++ Cargo.toml | 4 +- frontend/size-plugin.json | 2 +- frontend/src/components/app.tsx | 5 +-- frontend/src/components/header/index.tsx | 8 +--- frontend/src/routes/dataset/index.tsx | 42 ++++++++++++++++++ .../src/routes/{profile => dataset}/style.css | 0 .../{profile => dataset}/style.css.d.ts | 0 frontend/src/routes/home/index.tsx | 40 +++++++++++++---- frontend/src/routes/profile/index.tsx | 44 ------------------- src/main.rs | 26 ++++++++++- src/models.rs | 3 +- 12 files changed, 123 insertions(+), 67 deletions(-) create mode 100644 frontend/src/routes/dataset/index.tsx rename frontend/src/routes/{profile => dataset}/style.css (100%) rename frontend/src/routes/{profile => dataset}/style.css.d.ts (100%) delete mode 100644 frontend/src/routes/profile/index.tsx diff --git a/Cargo.lock b/Cargo.lock index a48bbc8..9ed28d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -211,6 +211,8 @@ dependencies = [ "libsqlite3-sys", "rocket", "rocket_contrib", + "serde", + "serde_json", ] [[package]] @@ -978,6 +980,20 @@ name = "serde" version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e" +dependencies = [ + "proc-macro2 1.0.18", + "quote 1.0.7", + "syn 1.0.34", +] [[package]] name = "serde_json" diff --git a/Cargo.toml b/Cargo.toml index bea9273..983d2e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,4 +13,6 @@ anyhow = "1.0" chrono = "0.4" diesel = { version = "1.4.5", features = ["sqlite"] } dotenv = "0.15.0" -libsqlite3-sys = { version = "0.18.0", features = ["bundled"] } \ No newline at end of file +libsqlite3-sys = { version = "0.18.0", features = ["bundled"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" \ No newline at end of file diff --git a/frontend/size-plugin.json b/frontend/size-plugin.json index 81ac3fd..4cd4505 100644 --- a/frontend/size-plugin.json +++ b/frontend/size-plugin.json @@ -1 +1 @@ -[{"timestamp":1595203869912,"files":[{"filename":"ssr-bundle.ac348.css","previous":602,"size":0,"diff":-602},{"filename":"ssr-bundle.js","previous":4208,"size":0,"diff":-4208},{"filename":"bundle.7e56a.css","previous":0,"size":445,"diff":445},{"filename":"bundle.*****.esm.js","previous":0,"size":8377,"diff":8377},{"filename":"polyfills.*****.esm.js","previous":0,"size":1969,"diff":1969},{"filename":"route-home/index.tsx.chunk.e6c71.css","previous":0,"size":74,"diff":74},{"filename":"route-home/index.tsx.chunk.*****.esm.js","previous":0,"size":237,"diff":237},{"filename":"route-notfound/index.tsx.chunk.c3378.css","previous":0,"size":65,"diff":65},{"filename":"route-notfound/index.tsx.chunk.*****.esm.js","previous":0,"size":282,"diff":282},{"filename":"route-profile/index.tsx.chunk.62c75.css","previous":0,"size":77,"diff":77},{"filename":"route-profile/index.tsx.chunk.*****.esm.js","previous":0,"size":1027,"diff":1027},{"filename":"sw-esm.js","previous":0,"size":8272,"diff":8272},{"filename":"sw.js","previous":0,"size":8272,"diff":8272},{"filename":"bundle.7b2b9.js","previous":0,"size":8384,"diff":8384},{"filename":"polyfills.694cb.js","previous":0,"size":2013,"diff":2013},{"filename":"route-home/index.tsx.chunk.d60a2.js","previous":0,"size":283,"diff":283},{"filename":"route-notfound/index.tsx.chunk.6e171.js","previous":0,"size":329,"diff":329},{"filename":"route-profile/index.tsx.chunk.df698.js","previous":0,"size":1096,"diff":1096}]},{"timestamp":1595203853803,"files":[{"filename":"ssr-bundle.ac348.css","previous":0,"size":602,"diff":602},{"filename":"ssr-bundle.js","previous":0,"size":4208,"diff":4208}]}] +[{"timestamp":1595206583004,"files":[{"filename":"ssr-bundle.b3409.css","previous":588,"size":0,"diff":-588},{"filename":"ssr-bundle.js","previous":4344,"size":0,"diff":-4344},{"filename":"bundle.7e56a.css","previous":0,"size":445,"diff":445},{"filename":"bundle.*****.esm.js","previous":0,"size":8373,"diff":8373},{"filename":"polyfills.*****.esm.js","previous":0,"size":1969,"diff":1969},{"filename":"route-home/index.tsx.chunk.*****.esm.js","previous":0,"size":294,"diff":294},{"filename":"route-notfound/index.tsx.chunk.c3378.css","previous":0,"size":65,"diff":65},{"filename":"route-notfound/index.tsx.chunk.*****.esm.js","previous":0,"size":282,"diff":282},{"filename":"route-profile/index.tsx.chunk.62c75.css","previous":0,"size":77,"diff":77},{"filename":"route-profile/index.tsx.chunk.*****.esm.js","previous":0,"size":1027,"diff":1027},{"filename":"sw.js","previous":0,"size":8272,"diff":8272},{"filename":"sw-esm.js","previous":0,"size":8272,"diff":8272},{"filename":"bundle.414e4.js","previous":0,"size":8381,"diff":8381},{"filename":"polyfills.694cb.js","previous":0,"size":2013,"diff":2013},{"filename":"route-home/index.tsx.chunk.2e3dc.js","previous":0,"size":453,"diff":453},{"filename":"route-notfound/index.tsx.chunk.6e171.js","previous":0,"size":329,"diff":329},{"filename":"route-profile/index.tsx.chunk.df698.js","previous":0,"size":1096,"diff":1096}]},{"timestamp":1595206565923,"files":[{"filename":"bundle.7e56a.css","previous":445,"size":0,"diff":-445},{"filename":"bundle.*****.esm.js","previous":8374,"size":0,"diff":-8374},{"filename":"polyfills.*****.esm.js","previous":1969,"size":0,"diff":-1969},{"filename":"route-home/index.tsx.chunk.*****.esm.js","previous":287,"size":0,"diff":-287},{"filename":"route-notfound/index.tsx.chunk.c3378.css","previous":65,"size":0,"diff":-65},{"filename":"route-notfound/index.tsx.chunk.*****.esm.js","previous":282,"size":0,"diff":-282},{"filename":"route-profile/index.tsx.chunk.62c75.css","previous":77,"size":0,"diff":-77},{"filename":"route-profile/index.tsx.chunk.*****.esm.js","previous":1027,"size":0,"diff":-1027},{"filename":"sw-esm.js","previous":8272,"size":0,"diff":-8272},{"filename":"sw.js","previous":8272,"size":0,"diff":-8272},{"filename":"bundle.afe39.js","previous":8382,"size":0,"diff":-8382},{"filename":"polyfills.694cb.js","previous":2013,"size":0,"diff":-2013},{"filename":"route-home/index.tsx.chunk.2f59b.js","previous":448,"size":0,"diff":-448},{"filename":"route-notfound/index.tsx.chunk.6e171.js","previous":329,"size":0,"diff":-329},{"filename":"route-profile/index.tsx.chunk.df698.js","previous":1096,"size":0,"diff":-1096},{"filename":"ssr-bundle.b3409.css","previous":0,"size":588,"diff":588},{"filename":"ssr-bundle.js","previous":0,"size":4344,"diff":4344}]},{"timestamp":1595205954134,"files":[{"filename":"ssr-bundle.b3409.css","previous":588,"size":0,"diff":-588},{"filename":"ssr-bundle.js","previous":4338,"size":0,"diff":-4338},{"filename":"bundle.7e56a.css","previous":0,"size":445,"diff":445},{"filename":"bundle.*****.esm.js","previous":0,"size":8374,"diff":8374},{"filename":"polyfills.*****.esm.js","previous":0,"size":1969,"diff":1969},{"filename":"route-home/index.tsx.chunk.*****.esm.js","previous":0,"size":287,"diff":287},{"filename":"route-notfound/index.tsx.chunk.c3378.css","previous":0,"size":65,"diff":65},{"filename":"route-notfound/index.tsx.chunk.*****.esm.js","previous":0,"size":282,"diff":282},{"filename":"route-profile/index.tsx.chunk.62c75.css","previous":0,"size":77,"diff":77},{"filename":"route-profile/index.tsx.chunk.*****.esm.js","previous":0,"size":1027,"diff":1027},{"filename":"sw-esm.js","previous":0,"size":8272,"diff":8272},{"filename":"sw.js","previous":0,"size":8272,"diff":8272},{"filename":"bundle.afe39.js","previous":0,"size":8382,"diff":8382},{"filename":"polyfills.694cb.js","previous":0,"size":2013,"diff":2013},{"filename":"route-home/index.tsx.chunk.2f59b.js","previous":0,"size":448,"diff":448},{"filename":"route-notfound/index.tsx.chunk.6e171.js","previous":0,"size":329,"diff":329},{"filename":"route-profile/index.tsx.chunk.df698.js","previous":0,"size":1096,"diff":1096}]},{"timestamp":1595205938508,"files":[{"filename":"bundle.7e56a.css","previous":445,"size":0,"diff":-445},{"filename":"bundle.*****.esm.js","previous":8377,"size":0,"diff":-8377},{"filename":"polyfills.*****.esm.js","previous":1969,"size":0,"diff":-1969},{"filename":"route-home/index.tsx.chunk.e6c71.css","previous":74,"size":0,"diff":-74},{"filename":"route-home/index.tsx.chunk.*****.esm.js","previous":237,"size":0,"diff":-237},{"filename":"route-notfound/index.tsx.chunk.c3378.css","previous":65,"size":0,"diff":-65},{"filename":"route-notfound/index.tsx.chunk.*****.esm.js","previous":282,"size":0,"diff":-282},{"filename":"route-profile/index.tsx.chunk.62c75.css","previous":77,"size":0,"diff":-77},{"filename":"route-profile/index.tsx.chunk.*****.esm.js","previous":1027,"size":0,"diff":-1027},{"filename":"sw-esm.js","previous":8272,"size":0,"diff":-8272},{"filename":"sw.js","previous":8272,"size":0,"diff":-8272},{"filename":"bundle.7b2b9.js","previous":8384,"size":0,"diff":-8384},{"filename":"polyfills.694cb.js","previous":2013,"size":0,"diff":-2013},{"filename":"route-home/index.tsx.chunk.d60a2.js","previous":283,"size":0,"diff":-283},{"filename":"route-notfound/index.tsx.chunk.6e171.js","previous":329,"size":0,"diff":-329},{"filename":"route-profile/index.tsx.chunk.df698.js","previous":1096,"size":0,"diff":-1096},{"filename":"ssr-bundle.b3409.css","previous":0,"size":588,"diff":588},{"filename":"ssr-bundle.js","previous":0,"size":4338,"diff":4338}]},{"timestamp":1595203869912,"files":[{"filename":"ssr-bundle.ac348.css","previous":602,"size":0,"diff":-602},{"filename":"ssr-bundle.js","previous":4208,"size":0,"diff":-4208},{"filename":"bundle.7e56a.css","previous":0,"size":445,"diff":445},{"filename":"bundle.*****.esm.js","previous":0,"size":8377,"diff":8377},{"filename":"polyfills.*****.esm.js","previous":0,"size":1969,"diff":1969},{"filename":"route-home/index.tsx.chunk.e6c71.css","previous":0,"size":74,"diff":74},{"filename":"route-home/index.tsx.chunk.*****.esm.js","previous":0,"size":237,"diff":237},{"filename":"route-notfound/index.tsx.chunk.c3378.css","previous":0,"size":65,"diff":65},{"filename":"route-notfound/index.tsx.chunk.*****.esm.js","previous":0,"size":282,"diff":282},{"filename":"route-profile/index.tsx.chunk.62c75.css","previous":0,"size":77,"diff":77},{"filename":"route-profile/index.tsx.chunk.*****.esm.js","previous":0,"size":1027,"diff":1027},{"filename":"sw-esm.js","previous":0,"size":8272,"diff":8272},{"filename":"sw.js","previous":0,"size":8272,"diff":8272},{"filename":"bundle.7b2b9.js","previous":0,"size":8384,"diff":8384},{"filename":"polyfills.694cb.js","previous":0,"size":2013,"diff":2013},{"filename":"route-home/index.tsx.chunk.d60a2.js","previous":0,"size":283,"diff":283},{"filename":"route-notfound/index.tsx.chunk.6e171.js","previous":0,"size":329,"diff":329},{"filename":"route-profile/index.tsx.chunk.df698.js","previous":0,"size":1096,"diff":1096}]},{"timestamp":1595203853803,"files":[{"filename":"ssr-bundle.ac348.css","previous":0,"size":602,"diff":602},{"filename":"ssr-bundle.js","previous":0,"size":4208,"diff":4208}]}] diff --git a/frontend/src/components/app.tsx b/frontend/src/components/app.tsx index d602d9d..94367d5 100644 --- a/frontend/src/components/app.tsx +++ b/frontend/src/components/app.tsx @@ -2,7 +2,7 @@ import { FunctionalComponent, h } from "preact"; import { Route, Router, RouterOnChangeArgs } from "preact-router"; import Home from "../routes/home"; -import Profile from "../routes/profile"; +import Dataset from "../routes/dataset"; import NotFoundPage from '../routes/notfound'; import Header from "./header"; @@ -23,8 +23,7 @@ const App: FunctionalComponent = () => {
- - + diff --git a/frontend/src/components/header/index.tsx b/frontend/src/components/header/index.tsx index c9074a2..016757b 100644 --- a/frontend/src/components/header/index.tsx +++ b/frontend/src/components/header/index.tsx @@ -5,17 +5,11 @@ import * as style from "./style.css"; const Header: FunctionalComponent = () => { return (
-

Preact App

+

datalog viewer thing

); diff --git a/frontend/src/routes/dataset/index.tsx b/frontend/src/routes/dataset/index.tsx new file mode 100644 index 0000000..634a79b --- /dev/null +++ b/frontend/src/routes/dataset/index.tsx @@ -0,0 +1,42 @@ +import { Component, h } from "preact"; +import { useEffect, useState } from "preact/hooks"; +import * as style from "./style.css"; + +export interface DatasetProps { + name: string, +} + +export interface Datapoint { + id: number, + devicename: string, + value: number, + timestamp: string, +} + +export interface DatasetState { + data: Datapoint[], +} + +class Dataset extends Component { + constructor(){ + super(); + this.state = { data: [] }; + } + + async componentDidMount() { + var devicesResponse = await fetch(`/api/device/${this.props.name}`); + this.setState({ data: await devicesResponse.json() as Datapoint[] }) + } + + // Lifecycle: Called just before our component will be destroyed + componentWillUnmount() { + // stop when not renderable + } + + render() { + var deviceLinks = this.state.data.map((d) =>
{d.devicename},{d.value},{d.timestamp}
) + return
{this.props.name}{deviceLinks}
; + } +} + +export default Dataset; diff --git a/frontend/src/routes/profile/style.css b/frontend/src/routes/dataset/style.css similarity index 100% rename from frontend/src/routes/profile/style.css rename to frontend/src/routes/dataset/style.css diff --git a/frontend/src/routes/profile/style.css.d.ts b/frontend/src/routes/dataset/style.css.d.ts similarity index 100% rename from frontend/src/routes/profile/style.css.d.ts rename to frontend/src/routes/dataset/style.css.d.ts diff --git a/frontend/src/routes/home/index.tsx b/frontend/src/routes/home/index.tsx index df906bd..df11b8e 100644 --- a/frontend/src/routes/home/index.tsx +++ b/frontend/src/routes/home/index.tsx @@ -1,13 +1,35 @@ -import { FunctionalComponent, h } from "preact"; +import { Component, h } from "preact"; +import { Link } from "preact-router/match"; import * as style from "./style.css"; -const Home: FunctionalComponent = () => { - return ( -
-

Home

-

This is the Home component.

-
- ); -}; +export interface HomeProps { + +} + +export interface HomeState { + devices: string[], +} + +class Home extends Component { + constructor(){ + super(); + this.state = { devices: [] }; + } + + async componentDidMount() { + var devicesResponse = await fetch('/api/devices'); + this.setState({ devices: await devicesResponse.json() as string[] }) + } + + // Lifecycle: Called just before our component will be destroyed + componentWillUnmount() { + // stop when not renderable + } + + render() { + var deviceLinks = this.state.devices.map((d) =>
{d}
) + return
{deviceLinks}
; + } +} export default Home; diff --git a/frontend/src/routes/profile/index.tsx b/frontend/src/routes/profile/index.tsx deleted file mode 100644 index 567d79a..0000000 --- a/frontend/src/routes/profile/index.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { FunctionalComponent, h } from "preact"; -import { useEffect, useState } from "preact/hooks"; -import * as style from "./style.css"; - -interface Props { - user: string; -} - -const Profile: FunctionalComponent = (props: Props) => { - const { user } = props; - const [time, setTime] = useState(Date.now()); - const [count, setCount] = useState(0); - - // gets called when this route is navigated to - useEffect(() => { - const timer = window.setInterval(() => setTime(Date.now()), 1000); - - // gets called just before navigating away from the route - return () => { - clearInterval(timer); - }; - }, []); - - // update the current time - const increment = () => { - setCount(count + 1); - }; - - return ( -
-

Profile: {user}

-

This is the user profile for a user named {user}.

- -
Current time: {new Date(time).toLocaleString()}
- -

- Clicked {count}{" "} - times. -

-
- ); -}; - -export default Profile; diff --git a/src/main.rs b/src/main.rs index bd37596..5e8de4f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,9 @@ extern crate rocket_contrib; #[macro_use] extern crate anyhow; +#[macro_use] +extern crate serde; + extern crate chrono; pub mod models; @@ -81,6 +84,27 @@ fn log_get(device_name: &RawStr, conn: DbConn) -> Result Ok(lines) } +#[get("/devices")] +fn devices_get(conn: DbConn) -> Result { + use self::schema::events::dsl::*; + let devices = events + .select(devicename) + .distinct() + .load::(&*conn)?; + + Ok(serde_json::to_string(&devices)?) +} + +#[get("/device/")] +fn device_get(name: &RawStr, conn: DbConn) -> Result { + use self::schema::events::dsl::*; + let results = events + .filter(devicename.eq(name.as_str())) + .load::(&*conn)?; + + Ok(serde_json::to_string(&results)?) +} + #[catch(404)] fn not_found() -> Option { NamedFile::open("frontend/build/index.html").ok() @@ -93,7 +117,7 @@ fn main() { "/", rocket_contrib::serve::StaticFiles::from("frontend/build"), ) - .mount("/api", routes![log_new, log_get]) + .mount("/api", routes![log_new, log_get, devices_get, device_get]) .register(catchers![not_found]) .launch(); diff --git a/src/models.rs b/src/models.rs index 4144d7b..1e14462 100644 --- a/src/models.rs +++ b/src/models.rs @@ -1,6 +1,7 @@ use super::schema::events; +use serde::Serialize; -#[derive(Queryable, Debug)] +#[derive(Queryable, Debug, Serialize)] pub struct Event { pub id: i32, pub devicename: String,