Add tags for schedules
This commit is contained in:
parent
f3f3d36eed
commit
75f8afd624
10 changed files with 375 additions and 184 deletions
|
@ -3,12 +3,13 @@ use actix_web::http::StatusCode;
|
|||
use serde::ser::SerializeStruct;
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DatabaseError {
|
||||
DeleteError,
|
||||
InsertError,
|
||||
InsertError(diesel::result::Error),
|
||||
InsertGetError,
|
||||
NotFound,
|
||||
Protected
|
||||
Protected,
|
||||
}
|
||||
|
||||
impl DatabaseError {
|
||||
|
@ -37,7 +38,7 @@ impl Serialize for DatabaseError {
|
|||
impl From<&DatabaseError> for String {
|
||||
fn from(err: &DatabaseError) -> Self {
|
||||
match err {
|
||||
DatabaseError::InsertError => String::from("error on inserting into database"),
|
||||
DatabaseError::InsertError(_) => String::from("error on inserting into database"),
|
||||
DatabaseError::InsertGetError => {
|
||||
String::from("error on retrieving new entry from database (your entry was saved)")
|
||||
}
|
||||
|
|
|
@ -2,10 +2,17 @@ use diesel::sql_types::Binary;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use crate::db::model_utils::Period;
|
||||
|
||||
use super::schema::schedules;
|
||||
use super::schema::*;
|
||||
use crate::types::EmgauwaUid;
|
||||
|
||||
#[derive(Serialize, Queryable)]
|
||||
#[derive(Debug, Serialize, Identifiable, Queryable)]
|
||||
pub struct Relay {
|
||||
#[serde(skip)]
|
||||
pub id: i32,
|
||||
// TODO
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Identifiable, Queryable)]
|
||||
pub struct Schedule {
|
||||
#[serde(skip)]
|
||||
pub id: i32,
|
||||
|
@ -27,7 +34,7 @@ pub struct NewSchedule<'a> {
|
|||
#[sql_type = "Binary"]
|
||||
pub struct Periods(pub(crate) Vec<Period>);
|
||||
|
||||
#[derive(Serialize, Queryable)]
|
||||
#[derive(Debug, Serialize, Identifiable, Queryable, Clone)]
|
||||
pub struct Tag {
|
||||
pub id: i32,
|
||||
pub tag: String,
|
||||
|
@ -39,9 +46,22 @@ pub struct NewTag<'a> {
|
|||
pub tag: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "junction_tag_schedule"]
|
||||
pub struct NewJunctionTagSchedule<'a> {
|
||||
#[derive(Queryable, Associations, Identifiable)]
|
||||
#[belongs_to(Relay)]
|
||||
#[belongs_to(Schedule)]
|
||||
#[belongs_to(Tag)]
|
||||
#[table_name = "junction_tag"]
|
||||
pub struct JunctionTag {
|
||||
pub id: i32,
|
||||
pub tag_id: i32,
|
||||
pub schedule_id: i32,
|
||||
pub relay_id: Option<i32>,
|
||||
pub schedule_id: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "junction_tag"]
|
||||
pub struct NewJunctionTag {
|
||||
pub tag_id: i32,
|
||||
pub relay_id: Option<i32>,
|
||||
pub schedule_id: Option<i32>,
|
||||
}
|
||||
|
|
109
src/db/schedule.rs
Normal file
109
src/db/schedule.rs
Normal file
|
@ -0,0 +1,109 @@
|
|||
use diesel::dsl::sql;
|
||||
use diesel::prelude::*;
|
||||
|
||||
use crate::types::EmgauwaUid;
|
||||
|
||||
use crate::db::errors::DatabaseError;
|
||||
use crate::db::{get_connection, schema};
|
||||
use crate::db::models::*;
|
||||
use crate::db::schema::tags::dsl::tags;
|
||||
use crate::db::schema::junction_tag::dsl::junction_tag;
|
||||
use crate::db::schema::schedules::dsl::schedules;
|
||||
use crate::db::tag::{create_junction_tag, create_tag};
|
||||
|
||||
pub fn get_schedule_tags(schedule: &Schedule) -> Vec<String> {
|
||||
let connection = get_connection();
|
||||
JunctionTag::belonging_to(schedule)
|
||||
.inner_join(schema::tags::dsl::tags)
|
||||
.select(schema::tags::tag)
|
||||
.load::<String>(&connection)
|
||||
.expect("Error loading tags")
|
||||
}
|
||||
|
||||
pub fn get_schedules() -> Vec<Schedule> {
|
||||
let connection = get_connection();
|
||||
schedules
|
||||
.load::<Schedule>(&connection)
|
||||
.expect("Error loading schedules")
|
||||
}
|
||||
|
||||
pub fn get_schedule_by_uid(filter_uid: EmgauwaUid) -> Result<Schedule, DatabaseError> {
|
||||
let connection = get_connection();
|
||||
let result = schedules
|
||||
.filter(schema::schedules::uid.eq(filter_uid))
|
||||
.first::<Schedule>(&connection)
|
||||
.or(Err(DatabaseError::NotFound))?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn delete_schedule_by_uid(filter_uid: EmgauwaUid) -> Result<(), DatabaseError> {
|
||||
let filter_uid = match filter_uid {
|
||||
EmgauwaUid::Off => Err(DatabaseError::Protected),
|
||||
EmgauwaUid::On => Err(DatabaseError::Protected),
|
||||
EmgauwaUid::Any(_) => Ok(filter_uid)
|
||||
}?;
|
||||
|
||||
let connection = get_connection();
|
||||
match diesel::delete(schedules.filter(schema::schedules::uid.eq(filter_uid))).execute(&connection) {
|
||||
Ok(rows) => {
|
||||
if rows != 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(DatabaseError::DeleteError)
|
||||
}
|
||||
}
|
||||
Err(_) => Err(DatabaseError::DeleteError),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_schedule(new_name: &str, new_periods: &Periods) -> Result<Schedule, DatabaseError> {
|
||||
let connection = get_connection();
|
||||
|
||||
let new_schedule = NewSchedule {
|
||||
uid: &EmgauwaUid::default(),
|
||||
name: new_name,
|
||||
periods: new_periods,
|
||||
};
|
||||
|
||||
diesel::insert_into(schedules)
|
||||
.values(&new_schedule)
|
||||
.execute(&connection)
|
||||
.map_err(DatabaseError::InsertError)?;
|
||||
|
||||
let result = schedules
|
||||
.find(sql("last_insert_rowid()"))
|
||||
.get_result::<Schedule>(&connection)
|
||||
.or(Err(DatabaseError::InsertGetError))?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn set_schedule_tags(schedule: &Schedule, new_tags: &[String]) -> Result<(), DatabaseError> {
|
||||
let connection = get_connection();
|
||||
diesel::delete(junction_tag.filter(schema::junction_tag::schedule_id.eq(schedule.id)))
|
||||
.execute(&connection)
|
||||
.or(Err(DatabaseError::DeleteError))?;
|
||||
|
||||
let mut database_tags: Vec<Tag> = tags.filter(schema::tags::tag.eq_any(new_tags))
|
||||
.load::<Tag>(&connection)
|
||||
.expect("Error loading tags");
|
||||
|
||||
let mut database_tags_iter = database_tags.clone().into_iter().map(|tag_db| tag_db.tag);
|
||||
|
||||
// create missing tags
|
||||
for new_tag in new_tags {
|
||||
if !database_tags_iter.any(|t| t.eq(new_tag)) {
|
||||
database_tags.push(
|
||||
create_tag(new_tag).expect("Error inserting tag")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for database_tag in database_tags {
|
||||
create_junction_tag(database_tag, None, Some(schedule))
|
||||
.expect("Error saving junction between tag and schedule");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -2,7 +2,7 @@ table! {
|
|||
controllers (id) {
|
||||
id -> Integer,
|
||||
uid -> Text,
|
||||
name -> Nullable<Text>,
|
||||
name -> Text,
|
||||
ip -> Nullable<Text>,
|
||||
port -> Nullable<Integer>,
|
||||
relay_count -> Nullable<Integer>,
|
||||
|
@ -32,8 +32,8 @@ table! {
|
|||
macro_actions (id) {
|
||||
id -> Integer,
|
||||
macro_id -> Integer,
|
||||
relay_id -> Nullable<Integer>,
|
||||
schedule_id -> Nullable<Integer>,
|
||||
relay_id -> Integer,
|
||||
schedule_id -> Integer,
|
||||
weekday -> SmallInt,
|
||||
}
|
||||
}
|
||||
|
@ -42,14 +42,14 @@ table! {
|
|||
macros (id) {
|
||||
id -> Integer,
|
||||
uid -> Text,
|
||||
name -> Nullable<Text>,
|
||||
name -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
relays (id) {
|
||||
id -> Integer,
|
||||
name -> Nullable<Text>,
|
||||
name -> Text,
|
||||
number -> Integer,
|
||||
controller_id -> Integer,
|
||||
}
|
||||
|
|
52
src/db/tag.rs
Normal file
52
src/db/tag.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
use diesel::dsl::sql;
|
||||
use diesel::prelude::*;
|
||||
|
||||
|
||||
use crate::db::errors::DatabaseError;
|
||||
use crate::db::{get_connection};
|
||||
use crate::db::models::*;
|
||||
use crate::db::schema::tags::dsl::tags;
|
||||
use crate::db::schema::junction_tag::dsl::junction_tag;
|
||||
|
||||
|
||||
pub fn create_tag(new_tag: &str) -> Result<Tag, DatabaseError> {
|
||||
let connection = get_connection();
|
||||
|
||||
let new_tag = NewTag {
|
||||
tag: new_tag,
|
||||
};
|
||||
|
||||
diesel::insert_into(tags)
|
||||
.values(&new_tag)
|
||||
.execute(&connection)
|
||||
.map_err(DatabaseError::InsertError)?;
|
||||
|
||||
let result = tags
|
||||
.find(sql("last_insert_rowid()"))
|
||||
.get_result::<Tag>(&connection)
|
||||
.or(Err(DatabaseError::InsertGetError))?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn create_junction_tag(target_tag: Tag, target_relay: Option<&Relay>, target_schedule: Option<&Schedule>) -> Result<JunctionTag, DatabaseError> {
|
||||
let connection = get_connection();
|
||||
|
||||
let new_junction_tag = NewJunctionTag {
|
||||
relay_id: target_relay.map(|r| r.id),
|
||||
schedule_id: target_schedule.map(|s| s.id),
|
||||
tag_id: target_tag.id
|
||||
};
|
||||
|
||||
diesel::insert_into(junction_tag)
|
||||
.values(&new_junction_tag)
|
||||
.execute(&connection)
|
||||
.map_err(DatabaseError::InsertError)?;
|
||||
|
||||
let result = junction_tag
|
||||
.find(sql("last_insert_rowid()"))
|
||||
.get_result::<JunctionTag>(&connection)
|
||||
.or(Err(DatabaseError::InsertGetError))?;
|
||||
|
||||
Ok(result)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue