Listening to the shaggs!
This commit is contained in:
1 parent
238cd9f2da
commit
9f86d53d11
9 files changed
+65
-62
No files matched your search
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -16,7 +16,10 @@
|
|||||||
|
|
||||||
<nav class="uk-navbar-container" uk-navbar>
|
<nav class="uk-navbar-container" uk-navbar>
|
||||||
<div class="uk-navbar-left">
|
<div class="uk-navbar-left">
|
||||||
<a href="/" class="uk-navbar-item uk-logo">Ledger</a>
|
<a href="/" class="uk-navbar-item uk-logo uk-margin-medium-left">
|
||||||
|
<img src="/static/images/33-game-robot.png" class="uk-margin-medium" style="height: 1em;">
|
||||||
|
Ledger
|
||||||
|
</a>
|
||||||
<ul class="uk-navbar-nav">
|
<ul class="uk-navbar-nav">
|
||||||
{% set nav_bar_items = [{'id': 'overview', 'label': 'Overview'},
|
{% set nav_bar_items = [{'id': 'overview', 'label': 'Overview'},
|
||||||
{'id': 'actions', 'label': 'Actions'}]%}
|
{'id': 'actions', 'label': 'Actions'}]%}
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<h2>Securities</h2>
|
|
||||||
<table class="uk-table">
|
<div class="uk-flex-center" uk-grid>
|
||||||
<thead>
|
<div style="text-align: center;">
|
||||||
<tr>
|
<h3 class="uk-h3">Our goal: to not be your stupidest investment option.</h3>
|
||||||
<th>Security</th>
|
<img src="/static/images/33-game-robot.png" style="height: 50%">
|
||||||
</tr>
|
</div>
|
||||||
</thead>
|
</div>
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>UAD</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
<div class="uk-margin">
|
<div class="uk-margin">
|
||||||
<label class="uk-form-label"> Name
|
<label class="uk-form-label"> Name
|
||||||
<input class="uk-input" type="text" placeholder="Caroline Ellison" aria-label="Default"
|
<input class="uk-input" type="text" placeholder="Caroline Ellison" aria-label="Default"
|
||||||
name="event.NewUser.name">
|
name="event.CreateNewUser.name">
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="uk-margin">
|
<div class="uk-margin">
|
||||||
<label class="uk-form-label"> Public Key
|
<label class="uk-form-label"> Public Key
|
||||||
<input class="uk-input" type="text" placeholder="xxxxx" aria-label="Default"
|
<input class="uk-input" type="text" placeholder="xxxxx" aria-label="Default"
|
||||||
name="event.NewUser.PublicKey">
|
name="event.CreateNewUser.public_key">
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
+10
-8
@@ -1,21 +1,23 @@
|
|||||||
use rusqlite::{Connection, Transaction};
|
use rusqlite::{Connection, Transaction};
|
||||||
|
|
||||||
use crate::events::{Bogus, CreateNewUser, Event};
|
use crate::db::users::create_user;
|
||||||
|
use crate::events::{CreateNewSecurity, CreateNewUser, Event};
|
||||||
use crate::util::{CustomResult, Error};
|
use crate::util::{CustomResult, Error};
|
||||||
|
|
||||||
fn process_bogus_event(tx: &Transaction, event: Bogus) -> CustomResult<()> {
|
fn process_bogus_event(tx: &Transaction, event: CreateNewSecurity) -> CustomResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_create_new_user_event(tx: &Transaction, event: CreateNewUser) -> CustomResult<()> {
|
fn process_create_new_user_event(tx: &mut Transaction, event: CreateNewUser) -> CustomResult<()> {
|
||||||
|
create_user(&tx, &event.name, &event.public_key)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn process_event(conn: &mut Connection, event: Event) -> CustomResult<()> {
|
pub fn process_event(conn: &mut Connection, event: Event) -> CustomResult<()> {
|
||||||
let tx = conn.transaction().map_err(Error::SqlError)?;
|
let mut tx = conn.transaction().map_err(Error::SqlError)?;
|
||||||
match event {
|
match event {
|
||||||
Event::Bogus(e) => process_bogus_event(&tx, e),
|
Event::CreateNewSecurity(e) => process_bogus_event(&mut tx, e)?,
|
||||||
Event::CreateNewUser(e) => process_create_new_user_event(&tx, e),
|
Event::CreateNewUser(e) => process_create_new_user_event(&mut tx, e)?,
|
||||||
}
|
};
|
||||||
|
tx.commit().map_err(Error::SqlError)
|
||||||
}
|
}
|
||||||
+3
-3
@@ -2,7 +2,7 @@ use serde::Deserialize;
|
|||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct Bogus {
|
pub struct CreateNewSecurity {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub age: i64,
|
pub age: i64,
|
||||||
}
|
}
|
||||||
@@ -10,11 +10,11 @@ pub struct Bogus {
|
|||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct CreateNewUser {
|
pub struct CreateNewUser {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub score: i64,
|
pub public_key: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
Bogus(Bogus),
|
CreateNewSecurity(CreateNewSecurity),
|
||||||
CreateNewUser(CreateNewUser),
|
CreateNewUser(CreateNewUser),
|
||||||
}
|
}
|
||||||
+4
-23
@@ -17,22 +17,15 @@ pub enum Error {
|
|||||||
|
|
||||||
pub type CustomResult<T, E = Error> = Result<T, E>;
|
pub type CustomResult<T, E = Error> = Result<T, E>;
|
||||||
|
|
||||||
trait SQLiteConnectionFactory {
|
pub struct SQLiteConnectionFactory {
|
||||||
fn connection(&self) -> Connection;
|
|
||||||
fn readonly(&self) -> Connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PathSQLiteConnectionFactory {
|
|
||||||
path: String,
|
path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PathSQLiteConnectionFactory {
|
impl SQLiteConnectionFactory {
|
||||||
pub fn new(path: String) -> PathSQLiteConnectionFactory {
|
pub fn new(path: String) -> SQLiteConnectionFactory {
|
||||||
PathSQLiteConnectionFactory { path }
|
SQLiteConnectionFactory { path }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl SQLiteConnectionFactory for PathSQLiteConnectionFactory {
|
|
||||||
fn connection(&self) -> Connection {
|
fn connection(&self) -> Connection {
|
||||||
Connection::open(&self.path).unwrap()
|
Connection::open(&self.path).unwrap()
|
||||||
}
|
}
|
||||||
@@ -41,15 +34,3 @@ impl SQLiteConnectionFactory for PathSQLiteConnectionFactory {
|
|||||||
Connection::open_with_flags(&self.path, OpenFlags::SQLITE_OPEN_READ_ONLY).unwrap()
|
Connection::open_with_flags(&self.path, OpenFlags::SQLITE_OPEN_READ_ONLY).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InMemorySQLiteConnectionFactory {}
|
|
||||||
|
|
||||||
impl SQLiteConnectionFactory for InMemorySQLiteConnectionFactory {
|
|
||||||
fn connection(&self) -> Connection {
|
|
||||||
Connection::open_in_memory().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn readonly(&self) -> Connection {
|
|
||||||
Connection::open_in_memory_with_flags(OpenFlags::SQLITE_OPEN_READ_ONLY).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+24
-10
@@ -19,11 +19,19 @@ use rusqlite::Connection;
|
|||||||
|
|
||||||
use crate::events::Event;
|
use crate::events::Event;
|
||||||
use crate::util::{CustomResult, Error};
|
use crate::util::{CustomResult, Error};
|
||||||
use crate::webui::worker::worker_loop;
|
use crate::webui::worker::{bob, event_processor_loop};
|
||||||
|
|
||||||
mod views;
|
mod views;
|
||||||
mod worker;
|
mod worker;
|
||||||
|
|
||||||
|
struct Service {}
|
||||||
|
|
||||||
|
impl Service {
|
||||||
|
fn get_users(self) -> Vec<String> {
|
||||||
|
vec!["to".to_string(), "foo".to_string()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct MiniJinjaRenderer {
|
struct MiniJinjaRenderer {
|
||||||
tmpl_env: web::Data<minijinja_autoreload::AutoReloader>,
|
tmpl_env: web::Data<minijinja_autoreload::AutoReloader>,
|
||||||
}
|
}
|
||||||
@@ -58,12 +66,8 @@ impl FromRequest for MiniJinjaRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
fn create_auto_reloader(enable_template_autoreload: bool) -> AutoReloader {
|
||||||
pub async fn web_ui_main(conn: &mut Connection,
|
AutoReloader::new(move |notifier| {
|
||||||
port: u16,
|
|
||||||
enable_template_autoreload: bool) -> CustomResult<()> {
|
|
||||||
// The closure is invoked every time the environment is outdated to recreate it.
|
|
||||||
let tmpl_reloader = AutoReloader::new(move |notifier| {
|
|
||||||
let mut env: minijinja::Environment<'static> = minijinja::Environment::new();
|
let mut env: minijinja::Environment<'static> = minijinja::Environment::new();
|
||||||
|
|
||||||
let tmpl_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("resources/templates");
|
let tmpl_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("resources/templates");
|
||||||
@@ -75,7 +79,15 @@ pub async fn web_ui_main(conn: &mut Connection,
|
|||||||
}
|
}
|
||||||
env.set_source(minijinja::Source::from_path(tmpl_path));
|
env.set_source(minijinja::Source::from_path(tmpl_path));
|
||||||
Ok(env)
|
Ok(env)
|
||||||
});
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
pub async fn web_ui_main(conn: &mut Connection,
|
||||||
|
port: u16,
|
||||||
|
enable_template_autoreload: bool) -> CustomResult<()> {
|
||||||
|
// The closure is invoked every time the environment is outdated to recreate it.
|
||||||
|
let tmpl_reloader = create_auto_reloader(enable_template_autoreload);
|
||||||
|
|
||||||
let (s, r) = async_channel::unbounded::<Event>();
|
let (s, r) = async_channel::unbounded::<Event>();
|
||||||
|
|
||||||
@@ -102,12 +114,14 @@ pub async fn web_ui_main(conn: &mut Connection,
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let t1 = server.run().fuse();
|
let t1 = server.run().fuse();
|
||||||
let t2 = worker_loop(conn, r).fuse();
|
let t2 = event_processor_loop(conn, r).fuse();
|
||||||
pin_mut!(t1, t2);
|
let t3 = bob().fuse();
|
||||||
|
pin_mut!(t1, t2, t3);
|
||||||
|
|
||||||
select! {
|
select! {
|
||||||
x = t1 => x.map_err(Error::IOError),
|
x = t1 => x.map_err(Error::IOError),
|
||||||
y = t2 => y,
|
y = t2 => y,
|
||||||
|
z = t3 => z,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-2
@@ -1,18 +1,20 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
|
use tokio::time::sleep;
|
||||||
|
|
||||||
use crate::event_processor::process_event;
|
use crate::event_processor::process_event;
|
||||||
use crate::events::Event;
|
use crate::events::Event;
|
||||||
use crate::util::CustomResult;
|
use crate::util::CustomResult;
|
||||||
use crate::util::Error::FuckingError;
|
use crate::util::Error::FuckingError;
|
||||||
|
|
||||||
pub async fn worker_loop(conn: &mut Connection,
|
pub async fn event_processor_loop(conn: &mut Connection,
|
||||||
r: async_channel::Receiver<Event>) -> CustomResult<()> {
|
r: async_channel::Receiver<Event>) -> CustomResult<()> {
|
||||||
loop {
|
loop {
|
||||||
let res = r.recv().await;
|
let res = r.recv().await;
|
||||||
match res {
|
match res {
|
||||||
Ok(event) => process_event(conn, event)?, // todo, remove ?
|
Ok(event) => process_event(conn, event)?, // todo, remove "?"
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error: {:?}", e);
|
println!("Error: {:?}", e);
|
||||||
return Err(FuckingError(e.to_string()));
|
return Err(FuckingError(e.to_string()));
|
||||||
@@ -20,3 +22,10 @@ pub async fn worker_loop(conn: &mut Connection,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn bob() -> CustomResult<()> {
|
||||||
|
loop {
|
||||||
|
sleep(Duration::from_millis(1000)).await;
|
||||||
|
println!("100 ms have elapsed");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user