Compare commits
16 Commits
dev-testin
...
tactical-r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
026349e82b | ||
|
|
2247a50296 | ||
|
|
9f18b593f9 | ||
|
|
ec7a79b8b6 | ||
|
|
3581a7edef | ||
|
|
d908755f45 | ||
|
|
f5e3ba706f | ||
|
|
042867e0db | ||
|
|
ebe885e02d | ||
|
|
7fab1257a9 | ||
|
|
3a42785fde | ||
|
|
8859ab7058 | ||
|
|
8ebea56925 | ||
|
|
a4ac6f474b | ||
|
|
9e5caf2043 | ||
|
|
a530303f73 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,2 +1,6 @@
|
||||
/target
|
||||
.env
|
||||
backend/target/sqlx/backend
|
||||
Cargo.lock
|
||||
frontend/dist/db-frontend-a8d46cf89f6300e8.js
|
||||
frontend/dist
|
||||
|
||||
2020
Cargo.lock
generated
2020
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
18
README.md
18
README.md
@@ -4,18 +4,12 @@ The project structure is divided into 3 thingies
|
||||
## Frontend
|
||||
- Utilises YEW
|
||||
- Builds component with HTML macro
|
||||
- Fetches values from API via requests see [https://yew.rs/docs/0.18.0/concepts/services/fetch#dispatching-requests](Yew requests)
|
||||
- Don't need anythign fancy yet
|
||||
- Will hopefully add more here
|
||||
- [ ] Make user input without dying
|
||||
|
||||
## Backend
|
||||
Ohoihohohoho t he fun begins here
|
||||
- Covering get requests for now to fetch data
|
||||
- the path is read from the macro atop the functions
|
||||
- the function takes variables that are in {} in the path
|
||||
- must pass the vars into their smaller first not directly web::Path<Type> or whatever
|
||||
- Template function for ticket extraction exists
|
||||
- [ ] Make retrieval functions for all data types (Refer to models.rs for those and their parameters)
|
||||
|
||||
### Models.rs
|
||||
the good file where the structs that interact with the database occurred
|
||||
|
||||
Realised that diesel is abysmal and should not be used holy fuck
|
||||
- sqlx my beloved
|
||||
- we write the SQL code and it gets checked at compile time very cool
|
||||
- [ ] Define structs for certain types for simplicity sake
|
||||
|
||||
@@ -6,10 +6,14 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
diesel = { version = "2.0.0",features = ["postgres","r2d2","chrono"] }
|
||||
dotenv = "0.15"
|
||||
chrono = "0.2.25"
|
||||
common = { path = "../common"}
|
||||
actix-web = "4.0.0-rc.1"
|
||||
tokio = { version = "1.17.0", features = ["full"] }
|
||||
yew = { version = "0.20.0", features = ["csr"] }
|
||||
anyhow = "1.0"
|
||||
futures = "0.3"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
sqlx = {version = "0.6", features = ["postgres", "json", "runtime-actix-rustls", "chrono", "decimal", "uuid", "offline"] }
|
||||
async-trait = "0.1.60"
|
||||
actix-web = "4"
|
||||
chrono = {version = "0.4.23", features = ["serde"]}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
-- This file was automatically created by Diesel to setup helper functions
|
||||
-- and other internal bookkeeping. This file is safe to edit, any future
|
||||
-- changes will be added to existing projects as new migrations.
|
||||
|
||||
DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
|
||||
DROP FUNCTION IF EXISTS diesel_set_updated_at();
|
||||
@@ -1,36 +0,0 @@
|
||||
-- This file was automatically created by Diesel to setup helper functions
|
||||
-- and other internal bookkeeping. This file is safe to edit, any future
|
||||
-- changes will be added to existing projects as new migrations.
|
||||
|
||||
|
||||
|
||||
|
||||
-- Sets up a trigger for the given table to automatically set a column called
|
||||
-- `updated_at` whenever the row is modified (unless `updated_at` was included
|
||||
-- in the modified columns)
|
||||
--
|
||||
-- # Example
|
||||
--
|
||||
-- ```sql
|
||||
-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());
|
||||
--
|
||||
-- SELECT diesel_manage_updated_at('users');
|
||||
-- ```
|
||||
CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$
|
||||
BEGIN
|
||||
EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
|
||||
FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
IF (
|
||||
NEW IS DISTINCT FROM OLD AND
|
||||
NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
|
||||
) THEN
|
||||
NEW.updated_at := current_timestamp;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
69
backend/sqlx-data.json
Normal file
69
backend/sqlx-data.json
Normal file
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"db": "PostgreSQL",
|
||||
"eab68949a5cbad11b0ca3bc62e4e5c3611df0d3af69633dba08e3ad3941d76d1": {
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"ordinal": 0,
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"nullable": [
|
||||
false
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Text",
|
||||
"Text",
|
||||
"Date",
|
||||
"Date"
|
||||
]
|
||||
}
|
||||
},
|
||||
"query": "\n INSERT INTO drivers ( id, name, address, reg_date, birthdate )\n VALUES ( $1, $2, $3, $4, $5 ) \n RETURNING id\n "
|
||||
},
|
||||
"edfc7e63f5381c6f71191820f798a0f66ebaee1ceb9f3a5466d9f73ffe8271d0": {
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"ordinal": 0,
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"ordinal": 1,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "address",
|
||||
"ordinal": 2,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "reg_date",
|
||||
"ordinal": 3,
|
||||
"type_info": "Date"
|
||||
},
|
||||
{
|
||||
"name": "birthdate",
|
||||
"ordinal": 4,
|
||||
"type_info": "Date"
|
||||
}
|
||||
],
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
}
|
||||
},
|
||||
"query": "SELECT * FROM drivers"
|
||||
}
|
||||
}
|
||||
@@ -1,55 +1,2 @@
|
||||
use crate::models::{Admin, AdminEmail, NewAdmin, NewAdminEmail};
|
||||
use common::CommonAdmin;
|
||||
use diesel::prelude::*;
|
||||
|
||||
pub fn listadmins(connection: &mut PgConnection) -> String {
|
||||
use crate::schema::admins::dsl::*;
|
||||
let query = admins.load::<Admin>(connection).expect("KANKER");
|
||||
let admin_list = query
|
||||
.iter()
|
||||
.map(|admin| format!("{} {}\n", admin.name, admin.address))
|
||||
.collect();
|
||||
return admin_list;
|
||||
}
|
||||
pub fn addmin(connection: &mut PgConnection, new_admin: NewAdmin) {
|
||||
use crate::schema::admins::dsl::*;
|
||||
diesel::insert_into(admins)
|
||||
.values(&new_admin)
|
||||
.execute(connection)
|
||||
.expect("LOL DEAD NOT WORKING INSERTION");
|
||||
}
|
||||
pub fn addmail(connection: &mut PgConnection, admin_email: String, inserted_id: i32) {
|
||||
use crate::schema::admin_emails::dsl::*;
|
||||
let inserted_email = NewAdminEmail {
|
||||
admin_id: &inserted_id,
|
||||
email: &admin_email,
|
||||
};
|
||||
diesel::insert_into(admin_emails)
|
||||
.values(inserted_email)
|
||||
.execute(connection)
|
||||
.expect("You FOOL! You didn't put an email in there");
|
||||
}
|
||||
|
||||
pub fn listadminmails(connection: &mut PgConnection) {
|
||||
use crate::schema::admin_emails::dsl::*;
|
||||
let results = admin_emails
|
||||
.load::<AdminEmail>(connection)
|
||||
.expect("hecc D:");
|
||||
for addmail in results {
|
||||
println!("{} {}", addmail.email, addmail.admin_id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_admin(connection: &mut PgConnection, admin_id: i32) -> CommonAdmin {
|
||||
use crate::schema::admins::dsl::*;
|
||||
let admin = &mut admins
|
||||
.filter(id.eq(admin_id))
|
||||
.limit(1)
|
||||
.load::<Admin>(connection)
|
||||
.expect("no admins :(")[0];
|
||||
return CommonAdmin {
|
||||
id: admin.id,
|
||||
name: String::from(&admin.name),
|
||||
address: String::from(&admin.address),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,38 +1,46 @@
|
||||
use crate::models::{Driver, NewDriver};
|
||||
use common::CommonDriver;
|
||||
use diesel::{prelude::*, query_builder::SqlQuery, sql_query};
|
||||
use crate::pog::SqlStruct;
|
||||
use actix_web::{get, web, HttpResponse, Responder};
|
||||
use async_trait::async_trait;
|
||||
use chrono::NaiveDate;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::PgPool;
|
||||
|
||||
pub fn listdrivers(connection: &mut PgConnection) -> Vec<CommonDriver> {
|
||||
let query = sql_query("SELECT * FROM drivers WHERE id = 10").load::<Driver>(connection);
|
||||
let mut drivers: Vec<CommonDriver> = Vec::new();
|
||||
for driver in query.unwrap() {
|
||||
drivers.push(CommonDriver {
|
||||
id: driver.id,
|
||||
name: driver.name,
|
||||
address: driver.address,
|
||||
});
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, sqlx::FromRow)]
|
||||
pub struct Driver {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub address: String,
|
||||
pub reg_date: NaiveDate,
|
||||
pub birthdate: NaiveDate,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl SqlStruct<i32> for Driver {
|
||||
async fn add(&self, pool: &PgPool) -> anyhow::Result<i32> {
|
||||
let rec = sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO drivers ( id, name, address, reg_date, birthdate )
|
||||
VALUES ( $1, $2, $3, $4, $5 )
|
||||
RETURNING id
|
||||
"#,
|
||||
self.id as i32,
|
||||
self.name,
|
||||
self.address,
|
||||
self.reg_date,
|
||||
self.birthdate,
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await?;
|
||||
Ok(rec.id)
|
||||
}
|
||||
return drivers;
|
||||
}
|
||||
|
||||
pub fn addriver(connection: &mut PgConnection, new_driver: NewDriver) {
|
||||
use crate::schema::drivers::dsl::*;
|
||||
diesel::insert_into(drivers)
|
||||
.values(&new_driver)
|
||||
.execute(connection)
|
||||
.expect("Couldn't insert new driver :)");
|
||||
}
|
||||
|
||||
pub fn get_driver(connection: &mut PgConnection, driver_id: i32) -> CommonDriver {
|
||||
use crate::schema::drivers::dsl::*;
|
||||
let driver = &mut drivers
|
||||
.filter(id.eq(driver_id))
|
||||
.limit(1)
|
||||
.load::<Driver>(connection)
|
||||
.expect("no drivers :(")[0];
|
||||
return CommonDriver {
|
||||
id: driver.id,
|
||||
name: String::from(&driver.name),
|
||||
address: String::from(&driver.address),
|
||||
};
|
||||
#[get("/api/json/drivers")]
|
||||
pub async fn list_all(db_pool: web::Data<PgPool>) -> impl Responder {
|
||||
let drivers = sqlx::query_as!(Driver, "SELECT * FROM drivers")
|
||||
.fetch_all(db_pool.get_ref())
|
||||
.await
|
||||
.expect("Could not fetch anything from the DB D:");
|
||||
HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
.json(drivers)
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
use std::env;
|
||||
pub mod admin_data;
|
||||
pub mod driver_data;
|
||||
pub mod models;
|
||||
pub mod radar_data;
|
||||
pub mod schema;
|
||||
pub mod ticket_data;
|
||||
pub mod vehicle_data;
|
||||
use diesel::{Connection, PgConnection};
|
||||
use dotenv::dotenv;
|
||||
|
||||
//boiler plate :D
|
||||
pub fn establish_connection() -> PgConnection {
|
||||
dotenv().ok();
|
||||
let database_url = env::var("DATABASE_URL").expect("fix your .env idot");
|
||||
PgConnection::establish(&database_url)
|
||||
.unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
|
||||
}
|
||||
//
|
||||
//Pool instead
|
||||
|
||||
// pub type PgPool = r2d2::Pool<ConnectionManager<PgConnection>>;
|
||||
// pub type PgPooledConnection = PooledConnection<ConnectionManager<PgConnection>>;
|
||||
// fn init_pool(database_url: &str) -> Result<PgPool, PoolError> {
|
||||
// let manager = ConnectionManager::<PgConnection>::new(database_url);
|
||||
// Pool::builder().build(manager)
|
||||
// }
|
||||
//
|
||||
// pub fn establish_connection() -> PgPool {
|
||||
// dotenv().ok();
|
||||
//
|
||||
// let database_url = env::var("DATABASE_URL").expect("pls obama put the link this time");
|
||||
// init_pool(&database_url).expect("Failed to create pool")
|
||||
// }
|
||||
38
backend/src/main.rs
Normal file
38
backend/src/main.rs
Normal file
@@ -0,0 +1,38 @@
|
||||
use actix_web::{web, App, HttpServer};
|
||||
use dotenv::dotenv;
|
||||
use sqlx::postgres::PgPoolOptions;
|
||||
use std::env;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub mod admin_data;
|
||||
pub mod driver_data;
|
||||
pub mod pog;
|
||||
pub mod radar_data;
|
||||
pub mod ticket_data;
|
||||
pub mod vehicle_data;
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
dotenv().ok();
|
||||
let port: u16 = env::var("ACTIX_PORT")
|
||||
.expect("SET ACTIX_PORT PLOX")
|
||||
.parse()
|
||||
.expect("NOPE CANT PARSE THIS WHAT DID YOU PUT IN?!!!");
|
||||
let address = env::var("ACTIX_IP").expect("SET ACTIX_IP PLOX");
|
||||
let database_url = env::var("DATABASE_URL").expect("Put a DB url in the .env file dumbass");
|
||||
let pool = PgPoolOptions::new()
|
||||
.max_connections(10)
|
||||
.connect(database_url.as_str())
|
||||
.await
|
||||
.expect("No pool connection man :(");
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.app_data(web::Data::new(pool.clone()))
|
||||
.service(driver_data::list_all)
|
||||
})
|
||||
.bind((address.as_str(), port))?
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
use crate::schema::*;
|
||||
use diesel::{data_types::PgDate, prelude::*};
|
||||
|
||||
//Admins
|
||||
#[derive(Queryable, Debug, AsChangeset, Identifiable)]
|
||||
pub struct Admin {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub address: String,
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[diesel(table_name = admins)]
|
||||
pub struct NewAdmin<'a> {
|
||||
pub id: i32,
|
||||
pub name: &'a str,
|
||||
pub address: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Queryable, AsChangeset, Associations)]
|
||||
#[diesel(belongs_to(Admin))]
|
||||
pub struct AdminEmail {
|
||||
pub admin_id: i32,
|
||||
pub email: String,
|
||||
}
|
||||
|
||||
#[derive(Insertable, Associations)]
|
||||
#[diesel(belongs_to(Admin))]
|
||||
#[diesel(table_name = admin_emails)]
|
||||
pub struct NewAdminEmail<'a> {
|
||||
pub admin_id: &'a i32,
|
||||
pub email: &'a str,
|
||||
}
|
||||
|
||||
//Ticket things
|
||||
#[derive(Queryable)]
|
||||
pub struct Ticket {
|
||||
pub id: i32,
|
||||
pub category: String,
|
||||
pub description: String,
|
||||
pub issue_date: PgDate,
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[diesel(table_name = tickets)]
|
||||
pub struct NewTicket<'a> {
|
||||
pub id: i32,
|
||||
pub category: &'a str,
|
||||
pub description: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[diesel(table_name = issued_tickets)]
|
||||
pub struct IssuedTicket {
|
||||
ticket: i32,
|
||||
vehicle: String,
|
||||
driver: Option<i32>,
|
||||
officer: i32,
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[diesel(table_name = auto_issued_tickets)]
|
||||
pub struct AutoIssuedTicket<'a> {
|
||||
ticket: &'a i32,
|
||||
vehicle: &'a str,
|
||||
driver: Option<i32>,
|
||||
radar: &'a i32,
|
||||
}
|
||||
|
||||
//Drivers
|
||||
#[derive(Queryable, AsChangeset, Identifiable, QueryableByName)]
|
||||
#[table_name = "drivers"]
|
||||
pub struct Driver {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub address: String,
|
||||
pub reg_date: PgDate,
|
||||
pub birthdate: PgDate,
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[diesel(table_name = drivers)]
|
||||
pub struct NewDriver<'a> {
|
||||
pub id: i32,
|
||||
pub name: &'a str,
|
||||
pub address: &'a str,
|
||||
reg_date: PgDate,
|
||||
birthdate: PgDate,
|
||||
}
|
||||
|
||||
//Vehicles
|
||||
#[derive(Queryable, QueryableByName)]
|
||||
#[diesel(belongs_to(Driver), table_name = vehicles)]
|
||||
pub struct Vehicle {
|
||||
pub model: Option<String>,
|
||||
pub color: Option<String>,
|
||||
pub chasse_num: Option<i32>,
|
||||
pub plate_num: String,
|
||||
pub vehicle_type: String,
|
||||
pub category: String,
|
||||
pub owner: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Queryable)]
|
||||
pub struct Radar {
|
||||
pub id: i32,
|
||||
pub category: Option<String>,
|
||||
pub address: Option<String>,
|
||||
}
|
||||
9
backend/src/pog.rs
Normal file
9
backend/src/pog.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use sqlx::PgPool;
|
||||
|
||||
//Nuke happened here but we got POOLS :DDDDDD
|
||||
#[async_trait]
|
||||
pub trait SqlStruct<T> {
|
||||
async fn add(&self, pool: &PgPool) -> Result<T>;
|
||||
}
|
||||
@@ -1,19 +1,2 @@
|
||||
use common::CommonRadar;
|
||||
use diesel::prelude::*;
|
||||
use diesel::PgConnection;
|
||||
|
||||
use crate::models::Radar;
|
||||
|
||||
pub fn get_radar(connection: &mut PgConnection, radar_id: i32) -> CommonRadar {
|
||||
use crate::schema::radars::dsl::*;
|
||||
let radar = &mut radars
|
||||
.filter(id.eq(radar_id))
|
||||
.limit(1)
|
||||
.load::<Radar>(connection)
|
||||
.expect("no radars :(")[0];
|
||||
return CommonRadar {
|
||||
id: radar.id,
|
||||
category: radar.category.clone(),
|
||||
address: radar.address.clone(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
// @generated automatically by Diesel CLI.
|
||||
|
||||
diesel::table! {
|
||||
admin_emails (admin_id, email) {
|
||||
admin_id -> Int4,
|
||||
email -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
admins (id) {
|
||||
id -> Int4,
|
||||
name -> Text,
|
||||
address -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
auto_issued_tickets (ticket) {
|
||||
ticket -> Int4,
|
||||
vehicle -> Text,
|
||||
driver -> Nullable<Int4>,
|
||||
radar -> Int4,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
driver_phones (driver, number) {
|
||||
driver -> Int4,
|
||||
number -> Int4,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
drivers (id) {
|
||||
id -> Int4,
|
||||
name -> Text,
|
||||
address -> Text,
|
||||
reg_date -> Date,
|
||||
birthdate -> Date,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
issued_tickets (ticket) {
|
||||
ticket -> Int4,
|
||||
vehicle -> Text,
|
||||
driver -> Nullable<Int4>,
|
||||
officer -> Int4,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
officer_emails (officer, email) {
|
||||
officer -> Int4,
|
||||
email -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
officer_phones (officer, number) {
|
||||
officer -> Int4,
|
||||
number -> Int4,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
officers (badge_num) {
|
||||
badge_num -> Int4,
|
||||
id -> Text,
|
||||
jurisdiction -> Nullable<Text>,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
radars (id) {
|
||||
id -> Int4,
|
||||
category -> Nullable<Text>,
|
||||
address -> Nullable<Text>,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
tickets (id) {
|
||||
id -> Int4,
|
||||
category -> Text,
|
||||
description -> Text,
|
||||
issue_date -> Date,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
vehicles (plate_num) {
|
||||
model -> Nullable<Text>,
|
||||
color -> Nullable<Text>,
|
||||
chasse_num -> Nullable<Int4>,
|
||||
plate_num -> Text,
|
||||
vehicle_type -> Text,
|
||||
category -> Text,
|
||||
owner -> Nullable<Int4>,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::joinable!(admin_emails -> admins (admin_id));
|
||||
diesel::joinable!(auto_issued_tickets -> drivers (driver));
|
||||
diesel::joinable!(auto_issued_tickets -> radars (radar));
|
||||
diesel::joinable!(auto_issued_tickets -> tickets (ticket));
|
||||
diesel::joinable!(auto_issued_tickets -> vehicles (vehicle));
|
||||
diesel::joinable!(driver_phones -> drivers (driver));
|
||||
diesel::joinable!(issued_tickets -> drivers (driver));
|
||||
diesel::joinable!(issued_tickets -> officers (officer));
|
||||
diesel::joinable!(issued_tickets -> tickets (ticket));
|
||||
diesel::joinable!(issued_tickets -> vehicles (vehicle));
|
||||
diesel::joinable!(officer_emails -> officers (officer));
|
||||
diesel::joinable!(officer_phones -> officers (officer));
|
||||
diesel::joinable!(vehicles -> drivers (owner));
|
||||
|
||||
diesel::allow_tables_to_appear_in_same_query!(
|
||||
admin_emails,
|
||||
admins,
|
||||
auto_issued_tickets,
|
||||
driver_phones,
|
||||
drivers,
|
||||
issued_tickets,
|
||||
officer_emails,
|
||||
officer_phones,
|
||||
officers,
|
||||
radars,
|
||||
tickets,
|
||||
vehicles,
|
||||
);
|
||||
30
backend/src/tests.rs
Normal file
30
backend/src/tests.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
use super::*;
|
||||
use actix_web::{
|
||||
http::header::ContentType,
|
||||
test::{self, init_service},
|
||||
};
|
||||
|
||||
//TODO: sqlx offline mode for these tests
|
||||
#[actix_web::test]
|
||||
async fn test_list_drivers_ok() {
|
||||
dotenv().ok();
|
||||
let database_url = env::var("DATABASE_URL").expect("Put a DB url in the .env file dumbass");
|
||||
let pool = PgPoolOptions::new()
|
||||
.max_connections(10)
|
||||
.connect(database_url.as_str())
|
||||
.await
|
||||
.expect("No pool connection man :(");
|
||||
let app = tests::init_service(
|
||||
App::new()
|
||||
.app_data(web::Data::new(pool.clone()))
|
||||
.service(driver_data::list_all),
|
||||
)
|
||||
.await;
|
||||
let req = test::TestRequest::get()
|
||||
.uri("/api/json/drivers")
|
||||
.insert_header(ContentType::plaintext())
|
||||
.to_request();
|
||||
let resp = test::call_service(&app, req).await;
|
||||
assert!(resp.status().is_success());
|
||||
}
|
||||
//TODO: sqlx tests
|
||||
@@ -1,67 +1,2 @@
|
||||
use crate::{
|
||||
models::{AutoIssuedTicket, IssuedTicket, NewTicket, Ticket},
|
||||
schema::{drivers, issued_tickets, tickets},
|
||||
};
|
||||
use common::CommonTicket;
|
||||
use diesel::prelude::*;
|
||||
|
||||
pub fn create_ticket(connection: &mut PgConnection, ticket: NewTicket) {
|
||||
use crate::schema::tickets::dsl::*;
|
||||
diesel::insert_into(tickets)
|
||||
.values(&ticket)
|
||||
.execute(connection)
|
||||
.expect("Didn't save ticket AAAAAA");
|
||||
}
|
||||
|
||||
pub fn get_tickets(connection: &mut PgConnection, driver_id: i32) -> Vec<CommonTicket> {
|
||||
//Chonky join function for the sake of my life :))
|
||||
let join = tickets::table
|
||||
.left_join(issued_tickets::table)
|
||||
.select((
|
||||
tickets::id,
|
||||
tickets::category,
|
||||
tickets::description,
|
||||
tickets::issue_date,
|
||||
))
|
||||
.filter(issued_tickets::driver.eq(driver_id));
|
||||
let tickets_by_driver = join.load::<Ticket>(connection).expect("oh no!");
|
||||
let common_ticket_output = tickets_by_driver
|
||||
.iter()
|
||||
.map(|ticket| CommonTicket {
|
||||
id: ticket.id,
|
||||
category: String::from(&ticket.category),
|
||||
description: String::from(&ticket.description),
|
||||
})
|
||||
.collect();
|
||||
return common_ticket_output;
|
||||
}
|
||||
|
||||
pub fn get_ticket(connection: &mut PgConnection, tickid: i32) -> CommonTicket {
|
||||
use crate::schema::tickets::dsl::*;
|
||||
let ticket = &mut tickets
|
||||
.filter(id.eq(tickid))
|
||||
.limit(1)
|
||||
.load::<Ticket>(connection)
|
||||
.expect("no tickets :(")[0];
|
||||
return CommonTicket {
|
||||
id: ticket.id,
|
||||
category: String::from(&ticket.category),
|
||||
description: String::from(&ticket.description),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn issue_ticket(connection: &mut PgConnection, issued_ticket: IssuedTicket) {
|
||||
use crate::schema::issued_tickets::dsl::*;
|
||||
diesel::insert_into(issued_tickets)
|
||||
.values(issued_ticket)
|
||||
.execute(connection)
|
||||
.expect("PAINNNN IT NO WORKEY (issued tickets)");
|
||||
}
|
||||
|
||||
pub fn auto_issue_ticket(connection: &mut PgConnection, issued_ticket: AutoIssuedTicket) {
|
||||
use crate::schema::auto_issued_tickets::dsl::*;
|
||||
diesel::insert_into(auto_issued_tickets)
|
||||
.values(issued_ticket)
|
||||
.execute(connection)
|
||||
.expect("PAINNNN IT NO WORKEY (issued tickets)");
|
||||
}
|
||||
|
||||
@@ -1,41 +1,2 @@
|
||||
use common::CommonVehicle;
|
||||
use diesel::prelude::*;
|
||||
use diesel::PgConnection;
|
||||
|
||||
use crate::models::Vehicle;
|
||||
|
||||
pub fn get_vehicle(connection: &mut PgConnection, vehicle_id: String) -> CommonVehicle {
|
||||
use crate::schema::vehicles::dsl::*;
|
||||
let vehicle = &mut vehicles
|
||||
.filter(plate_num.eq(vehicle_id))
|
||||
.limit(1)
|
||||
.load::<Vehicle>(connection)
|
||||
.expect("no vehicles :(")[0];
|
||||
return CommonVehicle {
|
||||
model: vehicle.model.clone(),
|
||||
color: vehicle.color.clone(),
|
||||
chasse_num: vehicle.chasse_num,
|
||||
plate_num: vehicle.plate_num.clone(),
|
||||
vehicle_type: vehicle.vehicle_type.clone(),
|
||||
category: vehicle.category.clone(),
|
||||
owner: vehicle.owner,
|
||||
};
|
||||
}
|
||||
|
||||
// pub fn insert_vehicle(connection: &mut PgConnection, vehicle: CommonVehicle) -> bool {
|
||||
// use crate::schema::vehicles::dsl::*;
|
||||
// //convert CommonVehicle to Vehicle
|
||||
// let vehicle = Vehicle {
|
||||
// model: vehicle.model,
|
||||
// color: vehicle.color,
|
||||
// chasse_num: vehicle.chasse_num,
|
||||
// plate_num: vehicle.plate_num,
|
||||
// vehicle_type: vehicle.vehicle_type,
|
||||
// category: vehicle.category,
|
||||
// owner: vehicle.owner,
|
||||
// };
|
||||
// diesel::insert_into(vehicles)
|
||||
// .values(&vehicle)
|
||||
// .execute(connection)
|
||||
// .is_ok()
|
||||
// }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
mod fetching;
|
||||
use yew::prelude::*;
|
||||
|
||||
use crate::fetching::{DriverComponent, TextRequestComponent};
|
||||
use crate::fetching::DriverComponent;
|
||||
|
||||
#[function_component]
|
||||
fn App() -> Html {
|
||||
@@ -12,7 +12,6 @@ fn App() -> Html {
|
||||
<h2> {"Drivers"} </h2>
|
||||
<DriverComponent {entered_id}/>
|
||||
<h2> {"Admins and Tickets" } </h2>
|
||||
<TextRequestComponent/>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
use actix_web::{
|
||||
get,
|
||||
http::header::ContentType,
|
||||
web::{self},
|
||||
HttpResponse, Responder,
|
||||
};
|
||||
use actix_web::{get, http::header::ContentType, web, HttpResponse, Responder};
|
||||
use backend::{
|
||||
admin_data::get_admin, driver_data::get_driver, establish_connection, ticket_data::get_ticket,
|
||||
vehicle_data::get_vehicle,
|
||||
|
||||
Reference in New Issue
Block a user