Update
This commit is contained in:
parent
73fdcb4bd2
commit
e00f809d00
13 changed files with 416 additions and 237 deletions
49
bvplan/Cargo.lock
generated
49
bvplan/Cargo.lock
generated
|
@ -21,15 +21,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "actix-http"
|
name = "actix-http"
|
||||||
version = "3.3.0"
|
version = "3.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0070905b2c4a98d184c4e81025253cb192aa8a73827553f38e9410801ceb35bb"
|
checksum = "c2079246596c18b4a33e274ae10c0e50613f4d32a4198e09c7b93771013fed74"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-codec",
|
"actix-codec",
|
||||||
"actix-rt",
|
"actix-rt",
|
||||||
"actix-service",
|
"actix-service",
|
||||||
"actix-utils",
|
"actix-utils",
|
||||||
"ahash",
|
"ahash 0.8.3",
|
||||||
"base64",
|
"base64",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"brotli",
|
"brotli",
|
||||||
|
@ -145,7 +145,7 @@ dependencies = [
|
||||||
"actix-service",
|
"actix-service",
|
||||||
"actix-utils",
|
"actix-utils",
|
||||||
"actix-web-codegen",
|
"actix-web-codegen",
|
||||||
"ahash",
|
"ahash 0.7.6",
|
||||||
"bytes",
|
"bytes",
|
||||||
"bytestring",
|
"bytestring",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
@ -221,6 +221,18 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"getrandom 0.2.8",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "0.7.20"
|
version = "0.7.20"
|
||||||
|
@ -450,12 +462,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-lock"
|
name = "async-lock"
|
||||||
version = "2.6.0"
|
version = "2.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685"
|
checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"event-listener",
|
"event-listener",
|
||||||
"futures-lite",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -636,7 +647,6 @@ dependencies = [
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"envconfig",
|
"envconfig",
|
||||||
"fancy-regex",
|
"fancy-regex",
|
||||||
"flate2",
|
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"minify-html",
|
"minify-html",
|
||||||
|
@ -644,7 +654,6 @@ dependencies = [
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"scraper",
|
"scraper",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
|
||||||
"static-files",
|
"static-files",
|
||||||
"stdext",
|
"stdext",
|
||||||
"tikv-jemallocator",
|
"tikv-jemallocator",
|
||||||
|
@ -694,8 +703,8 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "celery"
|
name = "celery"
|
||||||
version = "0.5.2"
|
version = "0.5.3"
|
||||||
source = "git+https://github.com/rusty-celery/rusty-celery.git?branch=main#6a71f338dc6decdb647ebfa48628444e1cfc6582"
|
source = "git+https://github.com/rusty-celery/rusty-celery.git?branch=main#32cb1c97d3bf8b57a1f4a501ec50024fbb0cea7f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"base64",
|
"base64",
|
||||||
|
@ -723,8 +732,8 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "celery-codegen"
|
name = "celery-codegen"
|
||||||
version = "0.5.2"
|
version = "0.5.3"
|
||||||
source = "git+https://github.com/rusty-celery/rusty-celery.git?branch=main#6a71f338dc6decdb647ebfa48628444e1cfc6582"
|
source = "git+https://github.com/rusty-celery/rusty-celery.git?branch=main#32cb1c97d3bf8b57a1f4a501ec50024fbb0cea7f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -876,9 +885,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.14"
|
version = "0.8.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
|
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
@ -1674,9 +1683,9 @@ checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jobserver"
|
name = "jobserver"
|
||||||
version = "0.1.25"
|
version = "0.1.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b"
|
checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
@ -3099,9 +3108,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.25.0"
|
version = "1.26.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af"
|
checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -3114,7 +3123,7 @@ dependencies = [
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.42.0",
|
"windows-sys 0.45.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -28,7 +28,6 @@ diesel = { version = "2.0.2", features = ["i-implement-a-third-party-backend-and
|
||||||
env_logger = "0.9.3"
|
env_logger = "0.9.3"
|
||||||
envconfig = "0.10.0"
|
envconfig = "0.10.0"
|
||||||
fancy-regex = "0.11.0"
|
fancy-regex = "0.11.0"
|
||||||
flate2 = "1.0.25"
|
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
minify-html = "0.10.8"
|
minify-html = "0.10.8"
|
||||||
|
@ -36,7 +35,6 @@ r2d2_redis = "0.14.0"
|
||||||
reqwest = "0.11.13"
|
reqwest = "0.11.13"
|
||||||
scraper = "0.14.0"
|
scraper = "0.14.0"
|
||||||
serde = "1.0.148"
|
serde = "1.0.148"
|
||||||
serde_json = "1.0.93"
|
|
||||||
static-files = "0.2.3"
|
static-files = "0.2.3"
|
||||||
stdext = "0.3.1"
|
stdext = "0.3.1"
|
||||||
tokio = { version = "1.22.0", features = ["full"] }
|
tokio = { version = "1.22.0", features = ["full"] }
|
||||||
|
|
|
@ -38,7 +38,3 @@ function scrollDown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
setTimeout(
|
|
||||||
$(document).height() > $(window).height() ? scrollDown : reload,
|
|
||||||
waitDelay
|
|
||||||
);
|
|
||||||
|
|
|
@ -7,10 +7,13 @@ body {
|
||||||
body {
|
body {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
margin: 0 5vw;
|
margin: 0 5vw;
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
|
||||||
|
&.display {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#info {
|
#info {
|
||||||
|
@ -84,7 +87,8 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
#footer {
|
#footer {
|
||||||
margin: auto 0 2vh;
|
margin-top: auto;
|
||||||
|
padding-bottom: 2vh;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
p {
|
p {
|
||||||
|
|
|
@ -38,7 +38,45 @@ async fn index(redis_pool: web::Data<cache::RedisPool>) -> HttpResponse {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(html) = match redis::cmd("GET")
|
if let Some(html) = match redis::cmd("GET")
|
||||||
.arg(cache::keys::SUBSTITUTIONS_HTML)
|
.arg(cache::keys::HTML)
|
||||||
|
.query::<Option<String>>(redis_conn.deref_mut())
|
||||||
|
{
|
||||||
|
Ok(x) => x,
|
||||||
|
Err(_) => {
|
||||||
|
return templates::StatusCode {
|
||||||
|
status_code: http::StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
message: None,
|
||||||
|
}
|
||||||
|
.to_response()
|
||||||
|
}
|
||||||
|
} {
|
||||||
|
HttpResponse::Accepted()
|
||||||
|
.content_type("text/html; charset=utf-8")
|
||||||
|
.body(html)
|
||||||
|
} else {
|
||||||
|
templates::StatusCode {
|
||||||
|
status_code: http::StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
message: None,
|
||||||
|
}
|
||||||
|
.to_response()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/display")]
|
||||||
|
async fn display(redis_pool: web::Data<cache::RedisPool>) -> HttpResponse {
|
||||||
|
let redis_conn = &mut match redis_pool.get() {
|
||||||
|
Ok(x) => x,
|
||||||
|
Err(_) => {
|
||||||
|
return templates::StatusCode {
|
||||||
|
status_code: http::StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
message: None,
|
||||||
|
}
|
||||||
|
.to_response()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(html) = match redis::cmd("GET")
|
||||||
|
.arg(cache::keys::DISPLAY_HTML)
|
||||||
.query::<Option<String>>(redis_conn.deref_mut())
|
.query::<Option<String>>(redis_conn.deref_mut())
|
||||||
{
|
{
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
|
@ -74,6 +112,7 @@ async fn main() -> std::io::Result<()> {
|
||||||
.wrap(middleware::Compress::default())
|
.wrap(middleware::Compress::default())
|
||||||
.wrap(middleware::Logger::default())
|
.wrap(middleware::Logger::default())
|
||||||
.service(index)
|
.service(index)
|
||||||
|
.service(display)
|
||||||
.service(ResourceFiles::new("/static", generated))
|
.service(ResourceFiles::new("/static", generated))
|
||||||
.default_service(web::route().to(not_found))
|
.default_service(web::route().to(not_found))
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,7 +4,6 @@ use lazy_static::lazy_static;
|
||||||
use r2d2_redis::{r2d2, redis, RedisConnectionManager};
|
use r2d2_redis::{r2d2, redis, RedisConnectionManager};
|
||||||
|
|
||||||
use crate::config;
|
use crate::config;
|
||||||
use crate::db;
|
|
||||||
|
|
||||||
pub type RedisPool = r2d2::Pool<RedisConnectionManager>;
|
pub type RedisPool = r2d2::Pool<RedisConnectionManager>;
|
||||||
pub type ConnectionPool = r2d2::PooledConnection<RedisConnectionManager>;
|
pub type ConnectionPool = r2d2::PooledConnection<RedisConnectionManager>;
|
||||||
|
@ -25,52 +24,7 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod keys {
|
pub mod keys {
|
||||||
use super::*;
|
|
||||||
|
|
||||||
// pub const SUBSTITUTIONS: &str = "substs";
|
pub const HTML: &str = "html";
|
||||||
pub const SUBSTITUTIONS_HTML: &str = "substs_html";
|
pub const DISPLAY_HTML: &str = "disp_html";
|
||||||
|
|
||||||
pub mod substitutions {
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct Substitution {
|
|
||||||
#[serde(rename = "p")]
|
|
||||||
pub period: usize,
|
|
||||||
#[serde(rename = "cl")]
|
|
||||||
pub classes: Vec<String>,
|
|
||||||
#[serde(rename = "ps")]
|
|
||||||
pub prev_subject: Option<String>,
|
|
||||||
#[serde(rename = "s")]
|
|
||||||
pub subject: Option<String>,
|
|
||||||
#[serde(rename = "t")]
|
|
||||||
pub teachers: Option<Vec<String>>,
|
|
||||||
#[serde(rename = "pr")]
|
|
||||||
pub prev_rooms: Vec<String>,
|
|
||||||
#[serde(rename = "r")]
|
|
||||||
pub rooms: Vec<String>,
|
|
||||||
#[serde(rename = "tx")]
|
|
||||||
pub text: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct SubstitutionQuery {
|
|
||||||
#[serde(rename = "d")]
|
|
||||||
pub date: String,
|
|
||||||
#[serde(rename = "w")]
|
|
||||||
pub week_type: db::models::WeekType,
|
|
||||||
#[serde(rename = "q")]
|
|
||||||
pub queried_at: String,
|
|
||||||
#[serde(rename = "i")]
|
|
||||||
pub last_import_time: String,
|
|
||||||
#[serde(rename = "y")]
|
|
||||||
pub schoolyear: String,
|
|
||||||
#[serde(rename = "t")]
|
|
||||||
pub tenant: String,
|
|
||||||
#[serde(rename = "s")]
|
|
||||||
pub substitutions: Vec<Substitution>,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ use actix_web::{body::BoxBody, http, HttpResponse, HttpResponseBuilder, Response
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use crate::cache;
|
|
||||||
|
|
||||||
struct ActixError(askama::Error);
|
struct ActixError(askama::Error);
|
||||||
|
|
||||||
impl fmt::Debug for ActixError {
|
impl fmt::Debug for ActixError {
|
||||||
|
@ -37,10 +35,43 @@ impl<T: askama_actix::Template> TemplateToResponseWithStatusCode for T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod substitutions {
|
||||||
|
use crate::db;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Substitution {
|
||||||
|
pub period: usize,
|
||||||
|
pub classes: Vec<String>,
|
||||||
|
pub prev_subject: Option<String>,
|
||||||
|
pub subject: Option<String>,
|
||||||
|
pub teachers: Option<Vec<String>>,
|
||||||
|
pub prev_rooms: Vec<String>,
|
||||||
|
pub rooms: Vec<String>,
|
||||||
|
pub text: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct SubstitutionQuery {
|
||||||
|
pub date: String,
|
||||||
|
pub week_type: db::models::WeekType,
|
||||||
|
pub queried_at: String,
|
||||||
|
pub last_import_time: String,
|
||||||
|
pub schoolyear: String,
|
||||||
|
pub tenant: String,
|
||||||
|
pub substitutions: Vec<Substitution>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "bvplan.html")]
|
#[template(path = "bvplan.html")]
|
||||||
pub struct BVplan {
|
pub struct BVplan {
|
||||||
pub data: cache::keys::substitutions::SubstitutionQuery,
|
pub data: substitutions::SubstitutionQuery,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "bvplan_display.html")]
|
||||||
|
pub struct BVplanDisplay {
|
||||||
|
pub data: substitutions::SubstitutionQuery,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
|
|
|
@ -7,9 +7,6 @@ use diesel::prelude::*;
|
||||||
use fancy_regex::Regex;
|
use fancy_regex::Regex;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use r2d2_redis::redis;
|
use r2d2_redis::redis;
|
||||||
use std::fs;
|
|
||||||
use std::io::Write;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
@ -371,7 +368,7 @@ fn cache_substitutions(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some(cache::keys::substitutions::Substitution {
|
Ok(Some(templates::substitutions::Substitution {
|
||||||
period: get_period(×, true, s.start_time)
|
period: get_period(×, true, s.start_time)
|
||||||
.context("Could not find period from start time")?,
|
.context("Could not find period from start time")?,
|
||||||
classes,
|
classes,
|
||||||
|
@ -427,7 +424,7 @@ fn cache_substitutions(
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let query = cache::keys::substitutions::SubstitutionQuery {
|
let query = templates::substitutions::SubstitutionQuery {
|
||||||
date: format!(
|
date: format!(
|
||||||
"{} {}",
|
"{} {}",
|
||||||
date.format("%d.%m.%Y"),
|
date.format("%d.%m.%Y"),
|
||||||
|
@ -455,22 +452,30 @@ fn cache_substitutions(
|
||||||
substitutions,
|
substitutions,
|
||||||
};
|
};
|
||||||
|
|
||||||
fs::write(
|
|
||||||
Path::new("/backups").join(format!(
|
|
||||||
"{}_{}_{}.json.gz",
|
|
||||||
date, queried_at, substitution_query_id
|
|
||||||
)),
|
|
||||||
{
|
|
||||||
let mut e = flate2::write::ZlibEncoder::new(vec![], flate2::Compression::best());
|
|
||||||
e.write_all(serde_json::to_string(&query)?.as_bytes())?;
|
|
||||||
e.finish()?
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
redis::cmd("SET")
|
redis::cmd("SET")
|
||||||
.arg(cache::keys::SUBSTITUTIONS_HTML)
|
.arg(cache::keys::HTML)
|
||||||
.arg(minify_html::minify(
|
.arg(minify_html::minify(
|
||||||
templates::BVplan { data: query }.render()?.as_bytes(),
|
templates::BVplan {
|
||||||
|
data: query.to_owned(),
|
||||||
|
}
|
||||||
|
.render()?
|
||||||
|
.as_bytes(),
|
||||||
|
&minify_html::Cfg {
|
||||||
|
do_not_minify_doctype: false,
|
||||||
|
ensure_spec_compliant_unquoted_attribute_values: false,
|
||||||
|
keep_spaces_between_attributes: false,
|
||||||
|
minify_css: true,
|
||||||
|
minify_js: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.query::<()>(redis_conn)?;
|
||||||
|
redis::cmd("SET")
|
||||||
|
.arg(cache::keys::DISPLAY_HTML)
|
||||||
|
.arg(minify_html::minify(
|
||||||
|
templates::BVplanDisplay { data: query }
|
||||||
|
.render()?
|
||||||
|
.as_bytes(),
|
||||||
&minify_html::Cfg {
|
&minify_html::Cfg {
|
||||||
do_not_minify_doctype: false,
|
do_not_minify_doctype: false,
|
||||||
ensure_spec_compliant_unquoted_attribute_values: false,
|
ensure_spec_compliant_unquoted_attribute_values: false,
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub async fn init() {
|
||||||
tasks = [
|
tasks = [
|
||||||
get_substitutions::get_substitutions,
|
get_substitutions::get_substitutions,
|
||||||
update_meta::update_meta,
|
update_meta::update_meta,
|
||||||
cleanup::cleanup,
|
// cleanup::cleanup,
|
||||||
],
|
],
|
||||||
task_routes = [
|
task_routes = [
|
||||||
"*" => QUEUE_NAME,
|
"*" => QUEUE_NAME,
|
||||||
|
@ -57,11 +57,11 @@ pub fn beat() -> impl std::future::Future<
|
||||||
schedule = DeltaSchedule::new(Duration::from_hours(6)),
|
schedule = DeltaSchedule::new(Duration::from_hours(6)),
|
||||||
args = (),
|
args = (),
|
||||||
},
|
},
|
||||||
"cleanup" => {
|
// "cleanup" => {
|
||||||
cleanup::cleanup,
|
// cleanup::cleanup,
|
||||||
schedule = DeltaSchedule::new(Duration::from_hours(1)),
|
// schedule = DeltaSchedule::new(Duration::from_hours(1)),
|
||||||
args = (),
|
// args = (),
|
||||||
}
|
// }
|
||||||
],
|
],
|
||||||
task_routes = [
|
task_routes = [
|
||||||
"*" => QUEUE_NAME,
|
"*" => QUEUE_NAME,
|
||||||
|
|
|
@ -15,6 +15,13 @@
|
||||||
|
|
||||||
{% block head %}{% endblock %}
|
{% block head %}{% endblock %}
|
||||||
|
|
||||||
|
<script
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js"
|
||||||
|
integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
|
|
||||||
<!-- Matomo -->
|
<!-- Matomo -->
|
||||||
<script>
|
<script>
|
||||||
var _paq = window._paq = window._paq || [];
|
var _paq = window._paq = window._paq || [];
|
||||||
|
@ -31,7 +38,5 @@
|
||||||
</script>
|
</script>
|
||||||
<!-- End Matomo Code -->
|
<!-- End Matomo Code -->
|
||||||
</head>
|
</head>
|
||||||
<body>
|
{% block body %}{% endblock %}
|
||||||
{% block body %}{% endblock %}
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -6,138 +6,136 @@
|
||||||
<link rel="stylesheet" type="text/css" href="/static/css/bvplan.css" />
|
<link rel="stylesheet" type="text/css" href="/static/css/bvplan.css" />
|
||||||
|
|
||||||
<script id="data-element-count" type="application/json">{{ data.substitutions.len()|json|safe }}</script>
|
<script id="data-element-count" type="application/json">{{ data.substitutions.len()|json|safe }}</script>
|
||||||
|
|
||||||
<script
|
|
||||||
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js"
|
|
||||||
integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ=="
|
|
||||||
crossorigin="anonymous"
|
|
||||||
referrerpolicy="no-referrer"
|
|
||||||
></script>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<header id="info">
|
<body>
|
||||||
<div id="title-wrapper" class="column">
|
<header id="info">
|
||||||
<h1 id="title">BVplan</h1>
|
<div id="title-wrapper" class="column">
|
||||||
<span id="subtitle">dergrimm.net</span>
|
<h1 id="title">BVplan</h1>
|
||||||
</div>
|
<span id="subtitle">dergrimm.net</span>
|
||||||
<div id="tenant-info" class="column">
|
</div>
|
||||||
<span>{{ data.tenant }}, {{ data.schoolyear }}</span>
|
<div id="tenant-info" class="column">
|
||||||
<br />
|
<span>{{ data.tenant }}, {{ data.schoolyear }}</span>
|
||||||
<span>Stand: {{ data.queried_at }}</span>
|
<br />
|
||||||
<br />
|
<span>Stand: {{ data.queried_at }}</span>
|
||||||
<span>Vertretungsplan (offline): {{ data.last_import_time }}</span>
|
<br />
|
||||||
</div>
|
<span>Vertretungsplan (offline): {{ data.last_import_time }}</span>
|
||||||
</header>
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<table id="plan">
|
<table id="plan">
|
||||||
<caption>
|
<caption>
|
||||||
{{ data.date }}, Woche {{ data.week_type }}
|
{{ data.date }}, Woche {{ data.week_type }}
|
||||||
</caption>
|
</caption>
|
||||||
|
|
||||||
<colgroup>
|
<colgroup>
|
||||||
<col />
|
<col />
|
||||||
<col />
|
<col />
|
||||||
<col />
|
<col />
|
||||||
<col style="width: 30%" />
|
<col style="width: 30%" />
|
||||||
<col />
|
<col />
|
||||||
<col />
|
<col />
|
||||||
<col />
|
<col />
|
||||||
<col style="width: 20%" />
|
<col style="width: 20%" />
|
||||||
</colgroup>
|
</colgroup>
|
||||||
|
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Stunde</th>
|
<th>Stunde</th>
|
||||||
<th>Klasse(n)</th>
|
<th>Klasse(n)</th>
|
||||||
<th>(Fach)</th>
|
<th>(Fach)</th>
|
||||||
<th>Fach</th>
|
<th>Fach</th>
|
||||||
<th>Vertreter</th>
|
<th>Vertreter</th>
|
||||||
<th>(Raum)</th>
|
<th>(Raum)</th>
|
||||||
<th>Raum</th>
|
<th>Raum</th>
|
||||||
<th>Text</th>
|
<th>Text</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for subst in data.substitutions %}
|
{% for subst in data.substitutions %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ subst.period }}</td>
|
<td>{{ subst.period }}</td>
|
||||||
<td>{{ subst.classes|join(", ") }}</td>
|
<td>{{ subst.classes|join(", ") }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% match subst.prev_subject %}
|
{% match subst.prev_subject %}
|
||||||
{% when Some with (x) %}
|
{% when Some with (x) %}
|
||||||
{{ x }}
|
{{ x }}
|
||||||
{% when None %}
|
{% when None %}
|
||||||
|
---
|
||||||
|
{% endmatch %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% match subst.subject %}
|
||||||
|
{% when Some with (x) %}
|
||||||
|
{{ x }}
|
||||||
|
{% when None %}
|
||||||
|
---
|
||||||
|
{% endmatch %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% match subst.teachers %}
|
||||||
|
{% when Some with (x) %}
|
||||||
|
{{ x|join(", ") }}
|
||||||
|
{% when None %}
|
||||||
|
---
|
||||||
|
{% endmatch %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if subst.prev_rooms.is_empty() %}
|
||||||
---
|
---
|
||||||
{% endmatch %}
|
{% else %}
|
||||||
</td>
|
{{ subst.prev_rooms|join(", ") }}
|
||||||
<td>
|
{% endif %}
|
||||||
{% match subst.subject %}
|
</td>
|
||||||
{% when Some with (x) %}
|
<td>
|
||||||
{{ x }}
|
{% if subst.rooms.is_empty() %}
|
||||||
{% when None %}
|
|
||||||
---
|
---
|
||||||
{% endmatch %}
|
{% else %}
|
||||||
</td>
|
{{ subst.rooms|join(", ") }}
|
||||||
<td>
|
{% endif %}
|
||||||
{% match subst.teachers %}
|
</td>
|
||||||
{% when Some with (x) %}
|
<td>
|
||||||
{{ x|join(", ") }}
|
{% match subst.text %}
|
||||||
{% when None %}
|
{% when Some with (x) %}
|
||||||
---
|
{{ x }}
|
||||||
{% endmatch %}
|
{% when None %}
|
||||||
</td>
|
{% endmatch %}
|
||||||
<td>
|
</td>
|
||||||
{% if subst.prev_rooms.is_empty() %}
|
</tr>
|
||||||
---
|
{% endfor %}
|
||||||
{% else %}
|
</tbody>
|
||||||
{{ subst.prev_rooms|join(", ") }}
|
</table>
|
||||||
{% endif %}
|
</main>
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{% if subst.rooms.is_empty() %}
|
|
||||||
---
|
|
||||||
{% else %}
|
|
||||||
{{ subst.rooms|join(", ") }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{% match subst.text %}
|
|
||||||
{% when Some with (x) %}
|
|
||||||
{{ x }}
|
|
||||||
{% when None %}
|
|
||||||
{% endmatch %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer id="footer">
|
<footer id="footer">
|
||||||
<div class="element">
|
<div class="element">
|
||||||
<p>
|
<p>
|
||||||
BVplan - der bessere Vertretungsplan sogar mit UTF-8 Support!
|
BVplan - der bessere Vertretungsplan sogar mit UTF-8 Support!
|
||||||
Wow
|
Wow
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://git.dergrimm.net/dergrimm/bvplan">
|
||||||
|
https://git.dergrimm.net/dergrimm/bvplan
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<p class="element">
|
||||||
|
<code>
|
||||||
|
Powered by Dominic Grimm <<a
|
||||||
|
href="mailto:dominic@dergrimm.net"
|
||||||
|
>dominic@dergrimm.net</a
|
||||||
|
>>, Untis sucks
|
||||||
|
</code>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
</footer>
|
||||||
<a href="https://git.dergrimm.net/dergrimm/bvplan">
|
|
||||||
https://git.dergrimm.net/dergrimm/bvplan
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<hr />
|
|
||||||
<p class="element">
|
|
||||||
<code>
|
|
||||||
Powered by Dominic Grimm <<a
|
|
||||||
href="mailto:dominic@dergrimm.net"
|
|
||||||
>dominic@dergrimm.net</a
|
|
||||||
>>, Untis sucks
|
|
||||||
</code>
|
|
||||||
</p>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<script src="/static/js/bvplan.js"></script>
|
<script src="/static/js/bvplan.js"></script>
|
||||||
|
<script>
|
||||||
|
setTimeout(reload, waitDelay);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
144
bvplan/templates/bvplan_display.html
Normal file
144
bvplan/templates/bvplan_display.html
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}BVplan{% endblock %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<link rel="stylesheet" type="text/css" href="/static/css/bvplan.css" />
|
||||||
|
|
||||||
|
<script id="data-element-count" type="application/json">{{ data.substitutions.len()|json|safe }}</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<body class="display">
|
||||||
|
<header id="info">
|
||||||
|
<div id="title-wrapper" class="column">
|
||||||
|
<h1 id="title">BVplan</h1>
|
||||||
|
<span id="subtitle">dergrimm.net</span>
|
||||||
|
</div>
|
||||||
|
<div id="tenant-info" class="column">
|
||||||
|
<span>{{ data.tenant }}, {{ data.schoolyear }}</span>
|
||||||
|
<br />
|
||||||
|
<span>Stand: {{ data.queried_at }}</span>
|
||||||
|
<br />
|
||||||
|
<span>Vertretungsplan (offline): {{ data.last_import_time }}</span>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<table id="plan">
|
||||||
|
<caption>
|
||||||
|
{{ data.date }}, Woche {{ data.week_type }}
|
||||||
|
</caption>
|
||||||
|
|
||||||
|
<colgroup>
|
||||||
|
<col />
|
||||||
|
<col />
|
||||||
|
<col />
|
||||||
|
<col style="width: 30%" />
|
||||||
|
<col />
|
||||||
|
<col />
|
||||||
|
<col />
|
||||||
|
<col style="width: 20%" />
|
||||||
|
</colgroup>
|
||||||
|
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Stunde</th>
|
||||||
|
<th>Klasse(n)</th>
|
||||||
|
<th>(Fach)</th>
|
||||||
|
<th>Fach</th>
|
||||||
|
<th>Vertreter</th>
|
||||||
|
<th>(Raum)</th>
|
||||||
|
<th>Raum</th>
|
||||||
|
<th>Text</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{% for subst in data.substitutions %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ subst.period }}</td>
|
||||||
|
<td>{{ subst.classes|join(", ") }}</td>
|
||||||
|
<td>
|
||||||
|
{% match subst.prev_subject %}
|
||||||
|
{% when Some with (x) %}
|
||||||
|
{{ x }}
|
||||||
|
{% when None %}
|
||||||
|
---
|
||||||
|
{% endmatch %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% match subst.subject %}
|
||||||
|
{% when Some with (x) %}
|
||||||
|
{{ x }}
|
||||||
|
{% when None %}
|
||||||
|
---
|
||||||
|
{% endmatch %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% match subst.teachers %}
|
||||||
|
{% when Some with (x) %}
|
||||||
|
{{ x|join(", ") }}
|
||||||
|
{% when None %}
|
||||||
|
---
|
||||||
|
{% endmatch %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if subst.prev_rooms.is_empty() %}
|
||||||
|
---
|
||||||
|
{% else %}
|
||||||
|
{{ subst.prev_rooms|join(", ") }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if subst.rooms.is_empty() %}
|
||||||
|
---
|
||||||
|
{% else %}
|
||||||
|
{{ subst.rooms|join(", ") }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% match subst.text %}
|
||||||
|
{% when Some with (x) %}
|
||||||
|
{{ x }}
|
||||||
|
{% when None %}
|
||||||
|
{% endmatch %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer id="footer">
|
||||||
|
<div class="element">
|
||||||
|
<p>
|
||||||
|
BVplan - der bessere Vertretungsplan sogar mit UTF-8 Support!
|
||||||
|
Wow
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://git.dergrimm.net/dergrimm/bvplan">
|
||||||
|
https://git.dergrimm.net/dergrimm/bvplan
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<p class="element">
|
||||||
|
<code>
|
||||||
|
Powered by Dominic Grimm <<a
|
||||||
|
href="mailto:dominic@dergrimm.net"
|
||||||
|
>dominic@dergrimm.net</a
|
||||||
|
>>, Untis sucks
|
||||||
|
</code>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="/static/js/bvplan.js"></script>
|
||||||
|
<script>
|
||||||
|
setTimeout(
|
||||||
|
$(document).height() > $(window).height() ? scrollDown : reload,
|
||||||
|
waitDelay
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
{% endblock %}
|
|
@ -24,6 +24,9 @@ x-bvplan:
|
||||||
BVPLAN_UNTIS_VPLAN_URL: ${BVPLAN_UNTIS_VPLAN_URL}
|
BVPLAN_UNTIS_VPLAN_URL: ${BVPLAN_UNTIS_VPLAN_URL}
|
||||||
BVPLAN_UNTIS_VPLAN_USERNAME: ${BVPLAN_UNTIS_VPLAN_USERNAME}
|
BVPLAN_UNTIS_VPLAN_USERNAME: ${BVPLAN_UNTIS_VPLAN_USERNAME}
|
||||||
BVPLAN_UNTIS_VPLAN_PASSWORD: ${BVPLAN_UNTIS_VPLAN_PASSWORD}
|
BVPLAN_UNTIS_VPLAN_PASSWORD: ${BVPLAN_UNTIS_VPLAN_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
|
||||||
services:
|
services:
|
||||||
nginx:
|
nginx:
|
||||||
|
@ -82,10 +85,6 @@ services:
|
||||||
worker:
|
worker:
|
||||||
<<: *bvplan
|
<<: *bvplan
|
||||||
command: worker
|
command: worker
|
||||||
volumes:
|
|
||||||
- /etc/timezone:/etc/timezone:ro
|
|
||||||
- /etc/localtime:/etc/localtime:ro
|
|
||||||
- ./data/backups:/backups
|
|
||||||
|
|
||||||
web:
|
web:
|
||||||
<<: *bvplan
|
<<: *bvplan
|
||||||
|
@ -95,9 +94,6 @@ services:
|
||||||
- rabbitmq
|
- rabbitmq
|
||||||
- worker
|
- worker
|
||||||
- redis
|
- redis
|
||||||
volumes:
|
|
||||||
- /etc/timezone:/etc/timezone:ro
|
|
||||||
- /etc/localtime:/etc/localtime:ro
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
db:
|
db:
|
||||||
|
|
Loading…
Reference in a new issue