Archived
Private
Public Access
1
0

Improved substitution page

This commit is contained in:
2023-04-24 18:50:10 +02:00
parent 45a7457ef3
commit 5f3016eccb
12 changed files with 186 additions and 53 deletions

View File

@@ -9,6 +9,7 @@ import {firstValueFrom} from "rxjs";
export class IServService {
public userdata?: Userdata;
public keys?: AuthKeys;
public backend: string = "http://localhost:5273";
constructor(private client: HttpClient) {
@@ -16,6 +17,11 @@ export class IServService {
if (data != null) {
this.userdata = JSON.parse(data);
}
const keys = localStorage.getItem("keys");
if (keys != null) {
this.keys = JSON.parse(keys);
}
}
public async login(email: string, password: string): Promise<boolean> {
@@ -27,8 +33,9 @@ export class IServService {
};
try {
await firstValueFrom(this.client.post(this.backend + "/auth/login", this.userdata));
const keys = await firstValueFrom(this.client.post<AuthKeys>(this.backend + "/iserv/login", this.userdata));
localStorage.setItem("userdata", JSON.stringify(this.userdata));
localStorage.setItem("keys", JSON.stringify(keys));
return true;
}catch (error) {
return false;
@@ -36,7 +43,18 @@ export class IServService {
}
public async getKeys(): Promise<AuthKeys> {
return await firstValueFrom(this.client.post<AuthKeys>(this.backend + "/auth/login", this.userdata));
const keys = await firstValueFrom(this.client.post<AuthKeys>(this.backend + "/iserv/login", this.userdata));
localStorage.setItem("keys", JSON.stringify(keys));
return keys;
}
public async getGroups(): Promise<string[]> {
try {
return (await firstValueFrom(this.client.post<{value: string[]}>(this.backend + "/iserv/groups?domain=" + this.userdata.domain, this.keys))).value;
} catch {
await this.getKeys();
return (await firstValueFrom(this.client.post<{value: string[]}>(this.backend + "/iserv/groups?domain=" + this.userdata.domain, this.keys))).value;
}
}
}

View File

@@ -9,15 +9,24 @@ import {firstValueFrom} from "rxjs";
})
export class UnitsService {
private schools: {[domain: string]: {today: string, tomorrow: string}} = {
public schools: {[domain: string]: {today: string, tomorrow: string, classes: string[]}} = {
["hgbp.de"]: {
today: "https://www.humboldt-gymnasium.de/vertretungsplan/PlanINet/heute/subst_001.htm",
tomorrow: "https://www.humboldt-gymnasium.de/vertretungsplan/PlanINet/morgen/subst_001.htm"
tomorrow: "https://www.humboldt-gymnasium.de/vertretungsplan/PlanINet/morgen/subst_001.htm",
classes: ["5a", "5b", "5c", "5d", "6a", "6b", "6c", "6d", "7a", "7b", "7c", "7d", "8a", "8b", "8c", "8d", "9a", "9b", "9c", "9d", "10a", "10b", "10c", "10d", "11a", "11b", "11c", "11d", "Q1", "Q2"]
}
}
constructor(private iserv: IServService, private client: HttpClient) {}
public doesSchoolExist(): boolean {
return this.schools[this.iserv.userdata.domain] != undefined;
}
public getClasses(): string[] {
return this.schools[this.iserv.userdata.domain]?.classes;
}
public async getSubstitutionPlan(date: "today" | "tomorrow"): Promise<UnitsData> {
if (this.schools[this.iserv.userdata.domain] == undefined) return undefined;
const url = this.schools[this.iserv.userdata.domain][date];

View File

@@ -1,9 +1,10 @@
export interface Substitution {
class: string;
classes: string[];
times: number[];
type: string;
representative: string;
lesson: string;
newLesson: string;
room: string;
teacher: string;
description: string;

View File

@@ -44,11 +44,13 @@
</ion-toolbar>
</ion-header>
<ion-select label="Ordner" [value]="folders[0]" interface="action-sheet" (ionChange)="changeFolder(select.value)" #select>
<ion-select-option *ngFor="let folder of folders" [value]="folder">
{{folder.name}}
</ion-select-option>
</ion-select>
<ion-item style="--background: transparent; --border-color: transparent">
<ion-select label="Ordner" [value]="folders[0]" interface="action-sheet" (ionChange)="changeFolder(select.value)" #select>
<ion-select-option *ngFor="let folder of folders" [value]="folder">
{{folder.name}}
</ion-select-option>
</ion-select>
</ion-item>
<ion-list>
<ion-item *ngFor="let message of mails" class="mail pointer" (click)="selectMail(message, mailModal)">

View File

@@ -3,15 +3,7 @@
<ion-buttons slot="start">
<ion-menu-button></ion-menu-button>
</ion-buttons>
<ion-segment value="today" (ionChange)="changeDate(segment.value)" #segment>
<ion-segment-button value="today">
<ion-label>Heute</ion-label>
</ion-segment-button>
<ion-segment-button value="tomorrow">
<ion-label>Morgen</ion-label>
</ion-segment-button>
</ion-segment>
<ion-title>Vertretungsplan</ion-title>
</ion-toolbar>
</ion-header>
@@ -22,9 +14,14 @@
</ion-toolbar>
</ion-header>
<ion-select label="Klasse" [value]="currentClass" interface="action-sheet" (ionChange)="changeClass(select.value)" #select>
<ion-select-option *ngFor="let className of getDistinctClasses()" [value]="className" [innerHtml]="className" />
</ion-select>
<ion-segment value="today" (ionChange)="changeDate(segment.value)" #segment>
<ion-segment-button value="today">
<ion-label>Heute</ion-label>
</ion-segment-button>
<ion-segment-button value="tomorrow">
<ion-label>Morgen</ion-label>
</ion-segment-button>
</ion-segment>
<section *ngIf="showNews">
<ion-card *ngFor="let info of data?.notifications">
@@ -35,16 +32,26 @@
</section>
<section *ngIf="!showNews">
<ion-item style="--background: transparent; --border-color: transparent">
<ion-select label="Klasse" [value]="currentClass" interface="action-sheet" (ionChange)="changeClass(select.value)" #select>
<ion-select-option value="all">Alle Klassen</ion-select-option>
<ion-select-option *ngFor="let className of units.getClasses()" [value]="className" [innerHtml]="className" />
</ion-select>
</ion-item>
<ion-item style="--background: transparent; --border-color: transparent" *ngIf="currentClass == 'Q1' || currentClass == 'Q2'">
<ion-checkbox justify="space-between" [(ngModel)]="filterByClasses" (ionChange)="showOnlyCourses(classes.checked)" #classes>Nur eigene Kurse anzeigen</ion-checkbox>
</ion-item>
<ion-card
*ngFor="let subs of data?.substitutions"
class="subs {{subs.type.replace(' ', '')}}"
[ngClass]="{'hide': subs.class != currentClass && currentClass != undefined}"
class="subs {{subs.type.replace(' ', '').replace('.', '')}}"
[ngClass]="{'hide': (subs.classes.indexOf(currentClass) == -1 && currentClass != 'all') || !hasClass(subs.lesson)}"
>
<ion-card-content>
<ion-label class="times">{{subs.times.join(" - ")}}</ion-label>
<div>
<ion-label class="type">{{subs.type}}</ion-label>
<ion-label class="desc" [innerHtml]="subs.lesson + ' (' + subs.teacher + ') ' + subs.room + ' ' + subs.description"></ion-label>
<ion-label class="desc" [innerHtml]="getDetails(subs)"></ion-label>
</div>
</ion-card-content>
</ion-card>

View File

@@ -26,8 +26,8 @@
--background: var(--ion-color-success-shade);
}
&.bittebeachten {
--background: var(--ion-color-warning-shade);
&.bittebeachten, &.stregulärem {
--background: var(--ion-color-tertiary-shade);
}
&.Vertretung {
@@ -39,7 +39,7 @@
}
&.Verlegung {
--background: var(--ion-color-secondary-shade);
--background: var(--ion-color-warning-shade);
}
&.hide {

View File

@@ -1,9 +1,10 @@
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import {AlertController, IonicModule} from '@ionic/angular';
import {UnitsService} from "../../api/units.service";
import {UnitsData} from "../../entities/substitution";
import {Substitution, UnitsData} from "../../entities/substitution";
import {IServService} from "../../api/iserv.service";
@Component({
selector: 'app-substitution',
@@ -16,36 +17,89 @@ export class SubstitutionPage implements OnInit {
public data: UnitsData;
public showNews: boolean = false;
public courses: string[] = [];
public currentClass: string;
public filterByClasses: boolean = false;
constructor(private units: UnitsService) {
this.currentClass = localStorage.getItem("class");
constructor(public units: UnitsService, private iserv: IServService, private alerts: AlertController) {
this.currentClass = localStorage.getItem("class") || 'all';
this.filterByClasses = localStorage.getItem("filterByClasses") == "true";
}
async ngOnInit() {
if (!this.units.doesSchoolExist()) {
const alert = await this.alerts.create({
subHeader: "Fehler",
message: "Deine Schule wird nicht unterstützt!",
buttons: ["Ok"]
});
await alert.present();
return;
}
this.data = await this.units.getSubstitutionPlan("today");
const groups = await this.iserv.getGroups();
for (let group of groups) {
if (!group.includes(".")) continue;
this.courses.push(group.split(".")[1]);
}
}
public async changeDate(date: string) {
this.data = await this.units.getSubstitutionPlan(date as "today" | "tomorrow");
}
public getDistinctClasses(): string[] {
const classes: string[] = [];
if (this.data == undefined) return [];
for (let subs of this.data.substitutions) {
if (classes.indexOf(subs.class) == -1) {
classes.push(subs.class)
}
}
return classes;
}
public changeClass(className: string) {
this.currentClass = className;
localStorage.setItem("class", className);
this.filterByClasses = false;
this.showOnlyCourses(false);
}
public getDetails(subs: Substitution): string {
if (subs.type == "bitte beachten") {
const desc = subs.description != "&nbsp;" ? ' - ' + subs.description : "";
let info = `${subs.lesson} (${subs.teacher}) in ${subs.room}`;
if (subs.lesson != subs.newLesson) {
info = `${subs.newLesson} (${subs.representative}) statt ${subs.lesson} (${subs.teacher}) in ${subs.room}`;
}
return info + desc;
}
switch (subs.type) {
case "Vertretung":
case "st. regulärem Unt.":
return `${subs.lesson} (${subs.representative} statt ${subs.teacher}) in ${subs.room}`;
case "Raumtausch":
return `${subs.lesson} (${subs.teacher}) in ${subs.room}`;
case "Entfall":
return `${subs.lesson} (${subs.teacher})`;
case "Stillarbeit":
return `${subs.lesson} (${subs.teacher}) in ${subs.room}`;
case "Verlegung":
return `${subs.newLesson} (${subs.representative}) statt ${subs.lesson} (${subs.teacher}) in ${subs.room}`;
default:
return subs.lesson + ' (' + subs.teacher + ') ' + subs.room;
}
}
public showOnlyCourses(toggle: boolean) {
localStorage.setItem("filterByClasses", toggle.toString());
}
public hasClass(course: string): boolean {
if (!this.filterByClasses) return true;
return this.courses.includes(course);
}
}