initial working
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
pub mod errors;
|
||||
pub mod read;
|
||||
@@ -0,0 +1,26 @@
|
||||
use actix_files::NamedFile;
|
||||
use actix_web::{dev, middleware::ErrorHandlerResponse, Result};
|
||||
|
||||
pub fn bad_request<B>(res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
|
||||
let new_resp = NamedFile::open("static/errors/400.html")?
|
||||
.set_status_code(res.status())
|
||||
.into_response(res.request())
|
||||
.map_into_right_body();
|
||||
Ok(ErrorHandlerResponse::Response(res.into_response(new_resp)))
|
||||
}
|
||||
|
||||
pub fn not_found<B>(res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
|
||||
let new_resp = NamedFile::open("static/errors/404.html")?
|
||||
.set_status_code(res.status())
|
||||
.into_response(res.request())
|
||||
.map_into_right_body();
|
||||
Ok(ErrorHandlerResponse::Response(res.into_response(new_resp)))
|
||||
}
|
||||
|
||||
pub fn internal_server_error<B>(res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
|
||||
let new_resp = NamedFile::open("static/errors/500.html")?
|
||||
.set_status_code(res.status())
|
||||
.into_response(res.request())
|
||||
.map_into_right_body();
|
||||
Ok(ErrorHandlerResponse::Response(res.into_response(new_resp)))
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use actix_web::{error, web, Error, HttpResponse};
|
||||
|
||||
use crate::db::{self, Pool};
|
||||
|
||||
pub async fn get_teachers_json(pool: web::Data<Pool>) -> Result<HttpResponse, Error> {
|
||||
let tasks = db::read::get_teachers(&pool)
|
||||
.await
|
||||
.map_err(error::ErrorInternalServerError)?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(tasks))
|
||||
}
|
||||
pub async fn get_subjects_json(pool: web::Data<Pool>) -> Result<HttpResponse, Error> {
|
||||
let tasks = db::read::get_subjects(&pool)
|
||||
.await
|
||||
.map_err(error::ErrorInternalServerError)?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(tasks))
|
||||
}
|
||||
|
||||
pub async fn get_free_slots_json(pool: web::Data<Pool>) -> Result<HttpResponse, Error> {
|
||||
let tasks = db::read::get_free_slots(&pool)
|
||||
.await
|
||||
.map_err(error::ErrorInternalServerError)?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(tasks))
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
|
||||
use dotenv::dotenv;
|
||||
use std::env;
|
||||
use terminwahl_back::db;
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
dotenv().ok();
|
||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
|
||||
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||
let pool = db::init_pool(&database_url)
|
||||
.await
|
||||
.expect("Failed to create pool");
|
||||
let duration = chrono::Duration::minutes(15);
|
||||
let date = NaiveDate::from_ymd_opt(2023, 2, 28).unwrap();
|
||||
let time = NaiveTime::from_hms_opt(14, 30, 0).unwrap();
|
||||
let mut start = NaiveDateTime::new(date, time);
|
||||
for _ in 0..4 {
|
||||
let end = start + duration;
|
||||
sqlx::query("INSERT INTO appointment_slots (start_time, end_time) VALUES (?, ?)")
|
||||
.bind(start)
|
||||
.bind(end)
|
||||
.execute(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
start = end;
|
||||
}
|
||||
start += duration;
|
||||
for _ in 0..4 {
|
||||
let end = start + duration;
|
||||
sqlx::query("INSERT INTO appointment_slots (start_time, end_time) VALUES (?, ?)")
|
||||
.bind(start)
|
||||
.bind(end)
|
||||
.execute(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
start = end;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
pub mod read;
|
||||
pub mod write;
|
||||
|
||||
use sqlx::sqlite::{SqlitePool, SqlitePoolOptions};
|
||||
|
||||
pub async fn init_pool(database_url: &str) -> Result<SqlitePool, sqlx::Error> {
|
||||
SqlitePoolOptions::new().connect(database_url).await
|
||||
}
|
||||
|
||||
pub type Pool = SqlitePool;
|
||||
@@ -0,0 +1,42 @@
|
||||
use sqlx::query_as;
|
||||
|
||||
use crate::types::{AppointmentSlot, AppointmentSlots, Subject, Subjects, Teacher, Teachers};
|
||||
|
||||
use super::Pool;
|
||||
|
||||
pub async fn get_teachers(db: &Pool) -> Result<Teachers, sqlx::Error> {
|
||||
query_as!(
|
||||
Teacher,
|
||||
r#"
|
||||
SELECT *
|
||||
FROM `teachers`"#,
|
||||
)
|
||||
.fetch_all(&*db)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_subjects(db: &Pool) -> Result<Subjects, sqlx::Error> {
|
||||
query_as!(
|
||||
Subject,
|
||||
r#"
|
||||
SELECT *
|
||||
FROM `subjects`"#,
|
||||
)
|
||||
.fetch_all(&*db)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_free_slots(db: &Pool) -> Result<AppointmentSlots, sqlx::Error> {
|
||||
match query_as!(
|
||||
AppointmentSlot,
|
||||
r#"
|
||||
SELECT *
|
||||
FROM `appointment_slots`"#,
|
||||
)
|
||||
.fetch_all(&*db)
|
||||
.await
|
||||
{
|
||||
Ok(elems) => Ok(elems.into_iter().map(|e| (e.id, e)).collect()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
pub mod api;
|
||||
pub mod db;
|
||||
pub mod types;
|
||||
@@ -0,0 +1,62 @@
|
||||
use actix_files::Files;
|
||||
use actix_session::{storage::CookieSessionStore, SessionMiddleware};
|
||||
use actix_web::{
|
||||
cookie::Key,
|
||||
http,
|
||||
middleware::{ErrorHandlers, Logger},
|
||||
web, App, HttpServer,
|
||||
};
|
||||
use dotenv::dotenv;
|
||||
use std::{
|
||||
env,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use terminwahl_back::{api, db};
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
dotenv().ok();
|
||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
|
||||
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||
let pool = db::init_pool(&database_url)
|
||||
.await
|
||||
.expect("Failed to create pool");
|
||||
|
||||
log::info!("starting HTTP server at http://localhost:8080");
|
||||
|
||||
HttpServer::new(move || {
|
||||
log::debug!("Constructing the App");
|
||||
|
||||
let session_store = SessionMiddleware::new(CookieSessionStore::default(), Key::generate());
|
||||
|
||||
let error_handlers = ErrorHandlers::new()
|
||||
.handler(
|
||||
http::StatusCode::INTERNAL_SERVER_ERROR,
|
||||
api::errors::internal_server_error,
|
||||
)
|
||||
.handler(http::StatusCode::BAD_REQUEST, api::errors::bad_request)
|
||||
.handler(http::StatusCode::NOT_FOUND, api::errors::not_found);
|
||||
|
||||
App::new()
|
||||
.app_data(web::Data::new(pool.clone()))
|
||||
.wrap(Logger::default())
|
||||
.wrap(session_store)
|
||||
.wrap(error_handlers)
|
||||
.service(
|
||||
web::resource("/get/teachers").route(web::get().to(api::read::get_teachers_json)),
|
||||
)
|
||||
.service(
|
||||
web::resource("/get/subjects").route(web::get().to(api::read::get_subjects_json)),
|
||||
)
|
||||
.service(
|
||||
web::resource("/get/free_slots")
|
||||
.route(web::get().to(api::read::get_free_slots_json)),
|
||||
)
|
||||
.service(Files::new("/", "./terminwahl_front/dist/").index_file("index.html"))
|
||||
})
|
||||
.bind(("127.0.0.1", 8080))?
|
||||
.workers(2)
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use chrono::{DateTime, Local, NaiveDateTime};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub type IdType = i64;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct Teacher {
|
||||
pub id: IdType,
|
||||
pub ansprache: String,
|
||||
pub last_name: String,
|
||||
pub subject_id: IdType,
|
||||
}
|
||||
|
||||
pub type Teachers = Vec<Teacher>;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct Subject {
|
||||
pub id: IdType,
|
||||
pub name: String,
|
||||
}
|
||||
pub type Subjects = Vec<Subject>;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct Appointment {
|
||||
pub id: IdType,
|
||||
pub teacher_id: IdType,
|
||||
pub slot_id: IdType,
|
||||
}
|
||||
|
||||
pub type AppointmentSlots = HashMap<IdType, AppointmentSlot>;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct AppointmentSlot {
|
||||
pub id: IdType,
|
||||
pub start_time: NaiveDateTime,
|
||||
pub end_time: NaiveDateTime,
|
||||
}
|
||||
Reference in New Issue
Block a user