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]]
|
||||
name = "actix-http"
|
||||
version = "3.3.0"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0070905b2c4a98d184c4e81025253cb192aa8a73827553f38e9410801ceb35bb"
|
||||
checksum = "c2079246596c18b4a33e274ae10c0e50613f4d32a4198e09c7b93771013fed74"
|
||||
dependencies = [
|
||||
"actix-codec",
|
||||
"actix-rt",
|
||||
"actix-service",
|
||||
"actix-utils",
|
||||
"ahash",
|
||||
"ahash 0.8.3",
|
||||
"base64",
|
||||
"bitflags",
|
||||
"brotli",
|
||||
|
@ -145,7 +145,7 @@ dependencies = [
|
|||
"actix-service",
|
||||
"actix-utils",
|
||||
"actix-web-codegen",
|
||||
"ahash",
|
||||
"ahash 0.7.6",
|
||||
"bytes",
|
||||
"bytestring",
|
||||
"cfg-if",
|
||||
|
@ -221,6 +221,18 @@ dependencies = [
|
|||
"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]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.20"
|
||||
|
@ -450,12 +462,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "async-lock"
|
||||
version = "2.6.0"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685"
|
||||
checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
"futures-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -636,7 +647,6 @@ dependencies = [
|
|||
"env_logger",
|
||||
"envconfig",
|
||||
"fancy-regex",
|
||||
"flate2",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"minify-html",
|
||||
|
@ -644,7 +654,6 @@ dependencies = [
|
|||
"reqwest",
|
||||
"scraper",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"static-files",
|
||||
"stdext",
|
||||
"tikv-jemallocator",
|
||||
|
@ -694,8 +703,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "celery"
|
||||
version = "0.5.2"
|
||||
source = "git+https://github.com/rusty-celery/rusty-celery.git?branch=main#6a71f338dc6decdb647ebfa48628444e1cfc6582"
|
||||
version = "0.5.3"
|
||||
source = "git+https://github.com/rusty-celery/rusty-celery.git?branch=main#32cb1c97d3bf8b57a1f4a501ec50024fbb0cea7f"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64",
|
||||
|
@ -723,8 +732,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "celery-codegen"
|
||||
version = "0.5.2"
|
||||
source = "git+https://github.com/rusty-celery/rusty-celery.git?branch=main#6a71f338dc6decdb647ebfa48628444e1cfc6582"
|
||||
version = "0.5.3"
|
||||
source = "git+https://github.com/rusty-celery/rusty-celery.git?branch=main#32cb1c97d3bf8b57a1f4a501ec50024fbb0cea7f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -876,9 +885,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.14"
|
||||
version = "0.8.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
|
||||
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
@ -1674,9 +1683,9 @@ checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
|||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.25"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b"
|
||||
checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
@ -3099,9 +3108,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.25.0"
|
||||
version = "1.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af"
|
||||
checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
|
@ -3114,7 +3123,7 @@ dependencies = [
|
|||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.42.0",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -28,7 +28,6 @@ diesel = { version = "2.0.2", features = ["i-implement-a-third-party-backend-and
|
|||
env_logger = "0.9.3"
|
||||
envconfig = "0.10.0"
|
||||
fancy-regex = "0.11.0"
|
||||
flate2 = "1.0.25"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.17"
|
||||
minify-html = "0.10.8"
|
||||
|
@ -36,7 +35,6 @@ r2d2_redis = "0.14.0"
|
|||
reqwest = "0.11.13"
|
||||
scraper = "0.14.0"
|
||||
serde = "1.0.148"
|
||||
serde_json = "1.0.93"
|
||||
static-files = "0.2.3"
|
||||
stdext = "0.3.1"
|
||||
tokio = { version = "1.22.0", features = ["full"] }
|
||||
|
|
|
@ -38,7 +38,3 @@ function scrollDown() {
|
|||
}
|
||||
|
||||
window.scrollTo(0, 0);
|
||||
setTimeout(
|
||||
$(document).height() > $(window).height() ? scrollDown : reload,
|
||||
waitDelay
|
||||
);
|
||||
|
|
|
@ -7,10 +7,13 @@ body {
|
|||
body {
|
||||
min-height: 100%;
|
||||
margin: 0 5vw;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
|
||||
&.display {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
#info {
|
||||
|
@ -84,7 +87,8 @@ body {
|
|||
}
|
||||
|
||||
#footer {
|
||||
margin: auto 0 2vh;
|
||||
margin-top: auto;
|
||||
padding-bottom: 2vh;
|
||||
text-align: center;
|
||||
|
||||
p {
|
||||
|
|
|
@ -38,7 +38,45 @@ async fn index(redis_pool: web::Data<cache::RedisPool>) -> HttpResponse {
|
|||
};
|
||||
|
||||
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())
|
||||
{
|
||||
Ok(x) => x,
|
||||
|
@ -74,6 +112,7 @@ async fn main() -> std::io::Result<()> {
|
|||
.wrap(middleware::Compress::default())
|
||||
.wrap(middleware::Logger::default())
|
||||
.service(index)
|
||||
.service(display)
|
||||
.service(ResourceFiles::new("/static", generated))
|
||||
.default_service(web::route().to(not_found))
|
||||
})
|
||||
|
|
|
@ -4,7 +4,6 @@ use lazy_static::lazy_static;
|
|||
use r2d2_redis::{r2d2, redis, RedisConnectionManager};
|
||||
|
||||
use crate::config;
|
||||
use crate::db;
|
||||
|
||||
pub type RedisPool = r2d2::Pool<RedisConnectionManager>;
|
||||
pub type ConnectionPool = r2d2::PooledConnection<RedisConnectionManager>;
|
||||
|
@ -25,52 +24,7 @@ lazy_static! {
|
|||
}
|
||||
|
||||
pub mod keys {
|
||||
use super::*;
|
||||
|
||||
// pub const SUBSTITUTIONS: &str = "substs";
|
||||
pub const SUBSTITUTIONS_HTML: &str = "substs_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>,
|
||||
}
|
||||
}
|
||||
pub const HTML: &str = "html";
|
||||
pub const DISPLAY_HTML: &str = "disp_html";
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@ use actix_web::{body::BoxBody, http, HttpResponse, HttpResponseBuilder, Response
|
|||
use askama::Template;
|
||||
use std::fmt;
|
||||
|
||||
use crate::cache;
|
||||
|
||||
struct ActixError(askama::Error);
|
||||
|
||||
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)]
|
||||
#[template(path = "bvplan.html")]
|
||||
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)]
|
||||
|
|
|
@ -7,9 +7,6 @@ use diesel::prelude::*;
|
|||
use fancy_regex::Regex;
|
||||
use lazy_static::lazy_static;
|
||||
use r2d2_redis::redis;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
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)
|
||||
.context("Could not find period from start time")?,
|
||||
classes,
|
||||
|
@ -427,7 +424,7 @@ fn cache_substitutions(
|
|||
)
|
||||
});
|
||||
|
||||
let query = cache::keys::substitutions::SubstitutionQuery {
|
||||
let query = templates::substitutions::SubstitutionQuery {
|
||||
date: format!(
|
||||
"{} {}",
|
||||
date.format("%d.%m.%Y"),
|
||||
|
@ -455,22 +452,30 @@ fn cache_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")
|
||||
.arg(cache::keys::SUBSTITUTIONS_HTML)
|
||||
.arg(cache::keys::HTML)
|
||||
.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 {
|
||||
do_not_minify_doctype: false,
|
||||
ensure_spec_compliant_unquoted_attribute_values: false,
|
||||
|
|
|
@ -25,7 +25,7 @@ pub async fn init() {
|
|||
tasks = [
|
||||
get_substitutions::get_substitutions,
|
||||
update_meta::update_meta,
|
||||
cleanup::cleanup,
|
||||
// cleanup::cleanup,
|
||||
],
|
||||
task_routes = [
|
||||
"*" => QUEUE_NAME,
|
||||
|
@ -57,11 +57,11 @@ pub fn beat() -> impl std::future::Future<
|
|||
schedule = DeltaSchedule::new(Duration::from_hours(6)),
|
||||
args = (),
|
||||
},
|
||||
"cleanup" => {
|
||||
cleanup::cleanup,
|
||||
schedule = DeltaSchedule::new(Duration::from_hours(1)),
|
||||
args = (),
|
||||
}
|
||||
// "cleanup" => {
|
||||
// cleanup::cleanup,
|
||||
// schedule = DeltaSchedule::new(Duration::from_hours(1)),
|
||||
// args = (),
|
||||
// }
|
||||
],
|
||||
task_routes = [
|
||||
"*" => QUEUE_NAME,
|
||||
|
|
|
@ -15,6 +15,13 @@
|
|||
|
||||
{% 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 -->
|
||||
<script>
|
||||
var _paq = window._paq = window._paq || [];
|
||||
|
@ -31,7 +38,5 @@
|
|||
</script>
|
||||
<!-- End Matomo Code -->
|
||||
</head>
|
||||
<body>
|
||||
{% block body %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -6,16 +6,10 @@
|
|||
<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
|
||||
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 %}
|
||||
|
||||
{% block body %}
|
||||
<body>
|
||||
<header id="info">
|
||||
<div id="title-wrapper" class="column">
|
||||
<h1 id="title">BVplan</h1>
|
||||
|
@ -140,4 +134,8 @@
|
|||
</footer>
|
||||
|
||||
<script src="/static/js/bvplan.js"></script>
|
||||
<script>
|
||||
setTimeout(reload, waitDelay);
|
||||
</script>
|
||||
</body>
|
||||
{% 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_USERNAME: ${BVPLAN_UNTIS_VPLAN_USERNAME}
|
||||
BVPLAN_UNTIS_VPLAN_PASSWORD: ${BVPLAN_UNTIS_VPLAN_PASSWORD}
|
||||
volumes:
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
|
||||
services:
|
||||
nginx:
|
||||
|
@ -82,10 +85,6 @@ services:
|
|||
worker:
|
||||
<<: *bvplan
|
||||
command: worker
|
||||
volumes:
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- ./data/backups:/backups
|
||||
|
||||
web:
|
||||
<<: *bvplan
|
||||
|
@ -95,9 +94,6 @@ services:
|
|||
- rabbitmq
|
||||
- worker
|
||||
- redis
|
||||
volumes:
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
|
||||
volumes:
|
||||
db:
|
||||
|
|
Loading…
Reference in a new issue