Compare commits

..

No commits in common. "b341d66f08dd38e0671a7e3848c2342e0ae16cdb" and "49179d2a8a00164038fca249980a2b7024a64181" have entirely different histories.

16 changed files with 172 additions and 291 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "frontend", "name": "frontend",
"version": "1.0.0-b4", "version": "1.0.0-b3",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "frontend", "name": "frontend",
"version": "1.0.0-b4", "version": "1.0.0-b3",
"dependencies": { "dependencies": {
"@angular/animations": "^18.2.1", "@angular/animations": "^18.2.1",
"@angular/cdk": "~18.2.1", "@angular/cdk": "~18.2.1",

View File

@ -1,6 +1,6 @@
{ {
"name": "frontend", "name": "frontend",
"version": "1.0.0-b4", "version": "1.0.0-b3",
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
"start": "ng serve", "start": "ng serve",

View File

@ -1,4 +1,3 @@
<mat-toolbar style="justify-content: space-between;"> <mat-toolbar style="justify-content: space-between;">
<a href="/" style="color: inherit;">Winsomnia</a> <a href="/" style="color: inherit;">Winsomnia</a>
<a href="/admin" style="color: inherit; font-size: 14px" *appHasRole="AuthRoles.Admin">Админ панель</a>
</mat-toolbar> </mat-toolbar>

View File

@ -1,8 +1,6 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import {MatToolbar} from "@angular/material/toolbar"; import {MatToolbar} from "@angular/material/toolbar";
import {MatAnchor, MatButton} from "@angular/material/button"; import {MatAnchor, MatButton} from "@angular/material/button";
import {HasRoleDirective} from "@/directives/has-role.directive";
import {AuthRoles} from "@model/AuthRoles";
@Component({ @Component({
selector: 'app-header', selector: 'app-header',
@ -10,13 +8,11 @@ import {AuthRoles} from "@model/AuthRoles";
imports: [ imports: [
MatToolbar, MatToolbar,
MatButton, MatButton,
MatAnchor, MatAnchor
HasRoleDirective
], ],
templateUrl: './header.component.html', templateUrl: './header.component.html',
styleUrl: './header.component.css' styleUrl: './header.component.css'
}) })
export class HeaderComponent { export class HeaderComponent {
protected readonly AuthRoles = AuthRoles;
} }

View File

@ -0,0 +1,81 @@
import {MatChipListbox} from "@angular/material/chips";
export class TabSelect {
public index: number;
public name: string;
constructor(index: number, name: string) {
this.index = index;
this.name = name;
}
}
export enum TabSelectType {
group,
professor,
lecture,
other
}
export interface TabSelectData {
selected: TabSelect[] | null;
type: TabSelectType;
}
export class TabStorageComponent {
private static dataName = 'tabSelectedData';
public static trySelectChip(index: number, chip: MatChipListbox, tryCount: number = 0) {
setTimeout(() => {
if (chip?._chips !== undefined && chip._chips.length !== 0) {
let selected = chip._chips.find(x => x.value == index.toString());
if (selected !== undefined) {
selected.select();
return;
}
}
if (tryCount >= 10)
return;
this.trySelectChip(index, chip, ++tryCount);
}, 100);
}
public static select(selected: TabSelect, type: TabSelectType, index: number) {
let selectedData = this.selected;
if (selectedData === null)
selectedData = {} as TabSelectData;
if (selectedData.type !== type || selectedData.selected === null || selectedData.selected.length === 0) {
if (index !== 0)
return;
else
selectedData.selected = [selected];
} else {
if (selectedData.selected.length < index)
return;
if (selectedData.selected.length - 1 === index)
selectedData.selected[index] = selected;
else if (selectedData.selected.length > index + 1)
selectedData.selected = selectedData.selected.slice(0, index + 1);
else
selectedData.selected.push(selected);
}
selectedData.type = type;
localStorage.setItem(this.dataName, JSON.stringify(selectedData));
}
public static get selected(): TabSelectData | null {
let data = localStorage.getItem(this.dataName);
if (data === null)
return null;
return JSON.parse(data) as TabSelectData;
}
}

View File

@ -31,9 +31,7 @@ interface Dictionary {
}) })
export class TableComponent implements OnChanges { export class TableComponent implements OnChanges {
private isDisciplineWithWeeks: boolean = false;
protected tableDataSource: MatTableDataSource<TableData> = new MatTableDataSource<TableData>([]); protected tableDataSource: MatTableDataSource<TableData> = new MatTableDataSource<TableData>([]);
private backupDisciplines: string[] = [];
protected daysOfWeek: string[] = ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота']; protected daysOfWeek: string[] = ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'];
protected displayedColumns: string[] = ['pairNumber']; protected displayedColumns: string[] = ['pairNumber'];
protected dataSource: ScheduleResponse[] = []; protected dataSource: ScheduleResponse[] = [];
@ -43,11 +41,6 @@ export class TableComponent implements OnChanges {
@Input() startWeek!: Date; @Input() startWeek!: Date;
@Input() isLoad: boolean = false; @Input() isLoad: boolean = false;
@Input() set disciplineWithWeeks(value: boolean) {
this.isDisciplineWithWeeks = value;
this.convertData();
}
@Input() set data(schedule: ScheduleResponse[]) { @Input() set data(schedule: ScheduleResponse[]) {
this.dataSource = schedule; this.dataSource = schedule;
this.convertData(); this.convertData();
@ -75,35 +68,14 @@ export class TableComponent implements OnChanges {
}; };
for (let k: number = 1; k < 7; k++) { for (let k: number = 1; k < 7; k++) {
let filteredData = this.dataSource.filter(x => convertedData.data[k.toString()] = this.dataSource.filter(x =>
x.pairNumber === i && x.pairNumber === i &&
x.dayOfWeek === k && x.dayOfWeek === k &&
x.isEven === (this.currentWeek % 2 === 0) x.isEven === (this.currentWeek % 2 === 0) &&
); (
(x.isExcludedWeeks && (!x.weeks || !x.weeks.includes(this.currentWeek))) ||
if (!this.isDisciplineWithWeeks) (!x.isExcludedWeeks && (!x.weeks || x.weeks.includes(this.currentWeek)))
filteredData = filteredData.filter(x => ));
x.isExcludedWeeks == undefined ||
x.weeks == undefined ||
(x.isExcludedWeeks && (!x.weeks.includes(this.currentWeek))) ||
(!x.isExcludedWeeks && (x.weeks.includes(this.currentWeek)))
);
filteredData.forEach(x => {
if (this.isDisciplineWithWeeks) {
if (x.isExcludedWeeks != undefined && x.weeks != undefined) {
if (this.backupDisciplines[x.disciplineId])
x.discipline = this.backupDisciplines[x.disciplineId];
else
this.backupDisciplines[x.disciplineId] = x.discipline;
x.discipline = `${(x.isExcludedWeeks ? 'кр.' : 'н.')} ${x.weeks.join(', ')} ${x.discipline}`;
}
} else if (this.backupDisciplines[x.disciplineId])
x.discipline = this.backupDisciplines[x.disciplineId];
});
convertedData.data[k.toString()] = filteredData;
} }
tableData.push(convertedData); tableData.push(convertedData);

View File

@ -9,7 +9,11 @@ import {FacultyResponse} from "@api/v1/facultyResponse";
import {FacultyService} from "@api/v1/faculty.service"; import {FacultyService} from "@api/v1/faculty.service";
import {GroupService} from "@api/v1/group.service"; import {GroupService} from "@api/v1/group.service";
import {IScheduleTab} from "@component/schedule/tabs/ischedule-tab"; import {IScheduleTab} from "@component/schedule/tabs/ischedule-tab";
import {TabSelect, TabSelectData, TabSelectType, TabStorageService} from "@service/tab-storage.service"; import {
TabSelect,
TabSelectType,
TabStorageComponent
} from "@component/common/tab-storage/tab-storage.component";
@Component({ @Component({
selector: 'app-group', selector: 'app-group',
@ -45,17 +49,20 @@ export class GroupComponent implements IScheduleTab {
@ViewChild('courseChip') courseChip!: MatChipListbox; @ViewChild('courseChip') courseChip!: MatChipListbox;
@ViewChild('groupChip') groupChip!: MatChipListbox; @ViewChild('groupChip') groupChip!: MatChipListbox;
private readonly selected: TabSelect[] | null = null;
@ViewChild('facultyIndicator') facultyIndicator!: LoadingIndicatorComponent; @ViewChild('facultyIndicator') facultyIndicator!: LoadingIndicatorComponent;
@ViewChild('courseIndicator') courseIndicator!: LoadingIndicatorComponent; @ViewChild('courseIndicator') courseIndicator!: LoadingIndicatorComponent;
@ViewChild('groupIndicator') groupIndicator!: LoadingIndicatorComponent; @ViewChild('groupIndicator') groupIndicator!: LoadingIndicatorComponent;
@Output() eventResult = new EventEmitter<number>(); @Output() eventResult = new EventEmitter<number>();
constructor(private facultyApi: FacultyService, private groupApi: GroupService, private tabStorage: TabStorageService) { constructor(private facultyApi: FacultyService, private groupApi: GroupService) {
} let selectedData = TabStorageComponent.selected;
if (selectedData !== null && selectedData.selected !== null) {
existParams(data: TabSelectData): boolean { if (selectedData.type === TabSelectType.group)
return data.selected['group'] !== undefined || data.selected['course'] !== undefined || data.selected['faculty'] !== undefined; this.selected = selectedData.selected;
}
} }
protected loadFaculties() { protected loadFaculties() {
@ -66,16 +73,14 @@ export class GroupComponent implements IScheduleTab {
})) }))
.subscribe(data => { .subscribe(data => {
this.faculties = data; this.faculties = data;
if (this.selected !== null && this.selected.length >= 1) {
let selectedFaculty = data.find(x => x.id === this.selected![0].index);
let selected = TabStorageService.selected?.selected['faculty']; if (selectedFaculty === undefined || selectedFaculty.name !== this.selected[0].name)
if (selected) { selectedFaculty = data.find(x => x.name === this.selected![0].name);
let selectedFaculty = data.find(x => x.id === selected.index);
if (selectedFaculty === undefined || selectedFaculty.name !== selected.name)
selectedFaculty = data.find(x => x.name === selected.name);
if (selectedFaculty !== undefined) { if (selectedFaculty !== undefined) {
TabStorageService.trySelectChip(selectedFaculty.id, this.facultyChip); TabStorageComponent.trySelectChip(selectedFaculty.id, this.facultyChip);
this.onFacultySelected(selectedFaculty.id); this.onFacultySelected(selectedFaculty.id);
} }
} }
@ -102,28 +107,23 @@ export class GroupComponent implements IScheduleTab {
.sort((a, b) => a - b)) .sort((a, b) => a - b))
); );
let selected = TabStorageService.selected?.selected['course']; if (this.selected !== null && this.selected.length >= 2) {
if (selected) { let selectedCourse = this.courseNumbers.find(x => x === this.selected![1].index);
let selectedCourse = this.courseNumbers.find(x => x === selected.index);
if (selectedCourse === undefined)
selectedCourse = this.courseNumbers.find(x => x.toString() === selected.name);
if (selectedCourse !== undefined) { if (selectedCourse !== undefined) {
TabStorageService.trySelectChip(selectedCourse, this.courseChip); TabStorageComponent.trySelectChip(selectedCourse, this.courseChip);
this.onCourseSelected(selectedCourse); this.onCourseSelected(selectedCourse);
} }
} }
let selectedGroupStorage = TabStorageService.selected?.selected['group']; if (this.selected !== null && this.selected.length >= 3) {
if (selectedGroupStorage) { let selectedGroup = data.find(x => x.id === this.selected![2].index);
let selectedGroup = data.find(x => x.id === selectedGroupStorage.index);
if (selectedGroup === undefined || selectedGroup.name !== selectedGroupStorage.name) if (selectedGroup === undefined || selectedGroup.name !== this.selected[2].name)
selectedGroup = data.find(x => x.name === selectedGroupStorage.name); selectedGroup = data.find(x => x.name === this.selected![2].name);
if (selectedGroup !== undefined) { if (selectedGroup !== undefined) {
TabStorageService.trySelectChip(selectedGroup.id, this.groupChip); TabStorageComponent.trySelectChip(selectedGroup.id, this.groupChip);
this.onGroupSelected(selectedGroup.id); this.onGroupSelected(selectedGroup.id);
} }
} }
@ -147,7 +147,7 @@ export class GroupComponent implements IScheduleTab {
return; return;
} }
this.tabStorage.select(new TabSelect(index, this.faculties!.find(x => x.id === index)?.name ?? ''), TabSelectType.group, 'faculty'); TabStorageComponent.select(new TabSelect(index, this.faculties!.find(x => x.id === index)?.name ?? ''), TabSelectType.group, 0);
this.facultyId = index; this.facultyId = index;
this.courseNumberPanel.open(); this.courseNumberPanel.open();
@ -164,7 +164,7 @@ export class GroupComponent implements IScheduleTab {
return; return;
} }
this.tabStorage.select(new TabSelect(course, course.toString()), TabSelectType.group, 'course'); TabStorageComponent.select(new TabSelect(course, course.toString()), TabSelectType.group, 1);
this.courseNumber = course; this.courseNumber = course;
this.groupPanel.open(); this.groupPanel.open();
@ -175,7 +175,7 @@ export class GroupComponent implements IScheduleTab {
if (index === undefined) if (index === undefined)
return; return;
this.tabStorage.select(new TabSelect(index, this.groups!.find(x => x.id == index)?.name ?? ''), TabSelectType.group, 'group'); TabStorageComponent.select(new TabSelect(index, this.groups!.find(x => x.id == index)?.name ?? ''), TabSelectType.group, 2);
this.groupPanel.close(); this.groupPanel.close();
this.eventResult.emit(index); this.eventResult.emit(index);

View File

@ -1,8 +1,6 @@
import {EventEmitter} from "@angular/core"; import {EventEmitter} from "@angular/core";
import {TabSelectData} from "@service/tab-storage.service";
export interface IScheduleTab { export interface IScheduleTab {
load(): void; load(): void;
eventResult: EventEmitter<number>; eventResult: EventEmitter<number>;
existParams(data: TabSelectData): boolean;
} }

View File

@ -10,7 +10,7 @@ import {LectureHallResponse} from "@api/v1/lectureHallResponse";
import {CampusService} from "@api/v1/campus.service"; import {CampusService} from "@api/v1/campus.service";
import {LectureHallService} from "@api/v1/lectureHall.service"; import {LectureHallService} from "@api/v1/lectureHall.service";
import {IScheduleTab} from "@component/schedule/tabs/ischedule-tab"; import {IScheduleTab} from "@component/schedule/tabs/ischedule-tab";
import {TabSelect, TabSelectData, TabSelectType, TabStorageService} from "@service/tab-storage.service"; import {TabSelect, TabSelectType, TabStorageComponent} from "@component/common/tab-storage/tab-storage.component";
@Component({ @Component({
selector: 'app-lecture-hall', selector: 'app-lecture-hall',
@ -45,12 +45,14 @@ export class LectureHallComponent implements IScheduleTab {
@ViewChild('lectureChip') lectureChip!: MatChipListbox; @ViewChild('lectureChip') lectureChip!: MatChipListbox;
private lectureHalls: LectureHallResponse[] | null = null; private lectureHalls: LectureHallResponse[] | null = null;
private readonly selected: TabSelect[] | null = null;
constructor(private campusApi: CampusService, private lectureHallApi: LectureHallService, private tabStorage: TabStorageService) { constructor(private campusApi: CampusService, private lectureHallApi: LectureHallService) {
} let selectedData = TabStorageComponent.selected;
if (selectedData !== null && selectedData.selected !== null) {
existParams(data: TabSelectData): boolean { if (selectedData.type === TabSelectType.lecture)
return data.selected['campus'] !== undefined || data.selected['lecture'] !== undefined; this.selected = selectedData.selected;
}
} }
protected loadCampuses() { protected loadCampuses() {
@ -62,15 +64,14 @@ export class LectureHallComponent implements IScheduleTab {
.subscribe(data => { .subscribe(data => {
this.campuses = data; this.campuses = data;
let selected = TabStorageService.selected?.selected['campus']; if (this.selected !== null && this.selected.length >= 1) {
if (selected) { let selectedCampus = data.find(x => x.id === this.selected![0].index);
let selectedCampus = data.find(x => x.id === selected.index);
if (selectedCampus === undefined || selectedCampus.codeName !== selected.name) if (selectedCampus === undefined || selectedCampus.codeName !== this.selected![0].name)
selectedCampus = data.find(x => x.codeName === selected.name); selectedCampus = data.find(x => x.codeName === this.selected![0].name);
if (selectedCampus !== undefined) { if (selectedCampus !== undefined) {
TabStorageService.trySelectChip(selectedCampus.id, this.campusChip); TabStorageComponent.trySelectChip(selectedCampus.id, this.campusChip);
this.onCampusSelected(selectedCampus.id); this.onCampusSelected(selectedCampus.id);
} }
} }
@ -84,7 +85,7 @@ export class LectureHallComponent implements IScheduleTab {
protected onCampusSelected(index: number) { protected onCampusSelected(index: number) {
this.formLectureHalls.reset(); this.formLectureHalls.reset();
this.tabStorage.select(new TabSelect(index, this.campuses!.find(x => x.id === index)?.codeName ?? ''), TabSelectType.lecture, 'campus'); TabStorageComponent.select(new TabSelect(index, this.campuses!.find(x => x.id === index)?.codeName ?? ''), TabSelectType.lecture, 0);
if (index === undefined) { if (index === undefined) {
this.campusId = null; this.campusId = null;
@ -110,16 +111,14 @@ export class LectureHallComponent implements IScheduleTab {
.subscribe(data => { .subscribe(data => {
this.lectureHalls = data; this.lectureHalls = data;
this.filteringLectureHalls(); this.filteringLectureHalls();
if (this.selected !== null && this.selected.length >= 2) {
let selectedLecture = data.find(x => x.id === this.selected![1].index);
let selected = TabStorageService.selected?.selected['lecture']; if (selectedLecture === undefined || selectedLecture.name !== this.selected![1].name)
if (selected) { selectedLecture = data.find(x => x.name === this.selected![1].name);
let selectedLecture = data.find(x => x.id === selected.index);
if (selectedLecture === undefined || selectedLecture.name !== selected.name)
selectedLecture = data.find(x => x.name === selected.name);
if (selectedLecture !== undefined) { if (selectedLecture !== undefined) {
TabStorageService.trySelectChip(selectedLecture.id, this.lectureChip); TabStorageComponent.trySelectChip(selectedLecture.id, this.lectureChip);
this.onLectureHallSelected(selectedLecture.id); this.onLectureHallSelected(selectedLecture.id);
} }
} }
@ -130,7 +129,7 @@ export class LectureHallComponent implements IScheduleTab {
if (index === undefined) if (index === undefined)
return; return;
this.tabStorage.select(new TabSelect(index, this.lectureHallsFiltered!.find(x => x.id === index)?.name ?? ''), TabSelectType.lecture, 'lecture'); TabStorageComponent.select(new TabSelect(index, this.lectureHallsFiltered!.find(x => x.id === index)?.name ?? ''), TabSelectType.lecture, 1);
this.lecturePanel.close(); this.lecturePanel.close();
this.eventResult.emit(index); this.eventResult.emit(index);

View File

@ -8,7 +8,7 @@ import {LoadingIndicatorComponent} from "@component/common/loading-indicator/loa
import {ProfessorResponse} from "@api/v1/professorResponse"; import {ProfessorResponse} from "@api/v1/professorResponse";
import {ProfessorService} from "@api/v1/professor.service"; import {ProfessorService} from "@api/v1/professor.service";
import {IScheduleTab} from "@component/schedule/tabs/ischedule-tab"; import {IScheduleTab} from "@component/schedule/tabs/ischedule-tab";
import {TabSelect, TabSelectData, TabSelectType, TabStorageService} from "@service/tab-storage.service"; import {TabSelect, TabSelectType, TabStorageComponent} from "@component/common/tab-storage/tab-storage.component";
@Component({ @Component({
selector: 'app-professor', selector: 'app-professor',
@ -30,16 +30,18 @@ export class ProfessorComponent implements OnInit, IScheduleTab {
protected filteredProfessors!: Observable<ProfessorResponse[]>; protected filteredProfessors!: Observable<ProfessorResponse[]>;
protected professors: ProfessorResponse[] | null = null; protected professors: ProfessorResponse[] | null = null;
private readonly selected: TabSelect[] | null = null;
@ViewChild('professorIndicator') professorIndicator!: LoadingIndicatorComponent; @ViewChild('professorIndicator') professorIndicator!: LoadingIndicatorComponent;
@Output() eventResult = new EventEmitter<number>(); @Output() eventResult = new EventEmitter<number>();
constructor(private api: ProfessorService, private tabStorage: TabStorageService) { constructor(private api: ProfessorService) {
} let selectedData = TabStorageComponent.selected;
if (selectedData !== null && selectedData.selected !== null) {
existParams(data: TabSelectData): boolean { if (selectedData.type === TabSelectType.professor)
return data.selected['professor'] !== undefined; this.selected = selectedData.selected;
}
} }
protected loadProfessors() { protected loadProfessors() {
@ -52,12 +54,11 @@ export class ProfessorComponent implements OnInit, IScheduleTab {
.subscribe(data => { .subscribe(data => {
this.professors = data; this.professors = data;
let selected = TabStorageService.selected?.selected['professor']; if (this.selected !== null && this.selected.length >= 1) {
if (selected) { let selectedProfessor = data.find(x => x.id === this.selected![0].index);
let selectedProfessor = data.find(x => x.id === selected.index);
if (selectedProfessor === undefined || selectedProfessor.name !== selected.name) if (selectedProfessor === undefined || selectedProfessor.name !== this.selected[0].name)
selectedProfessor = data.find(x => x.name === selected.name); selectedProfessor = data.find(x => x.name === this.selected![0].name);
if (selectedProfessor !== undefined) if (selectedProfessor !== undefined)
this.onOptionSelected(selectedProfessor.id); this.onOptionSelected(selectedProfessor.id);
@ -95,7 +96,7 @@ export class ProfessorComponent implements OnInit, IScheduleTab {
this.professorControl.setValue(selectedOption.name); this.professorControl.setValue(selectedOption.name);
this.eventResult.emit(selectedOption.id); this.eventResult.emit(selectedOption.id);
this.tabStorage.select(new TabSelect(selectedOption.id, selectedOption.name), TabSelectType.professor, 'professor'); TabStorageComponent.select(new TabSelect(selectedOption.id, selectedOption.name), TabSelectType.professor, 0);
} }
} }

View File

@ -1,5 +1,5 @@
.padding-content div { .padding-content div {
padding: 15px 0; padding: 30px 15px;
} }
.margin-other-button { .margin-other-button {

View File

@ -17,7 +17,7 @@ import {GroupService} from "@api/v1/group.service";
import {ProfessorService} from "@api/v1/professor.service"; import {ProfessorService} from "@api/v1/professor.service";
import {AuthRoles} from "@model/AuthRoles"; import {AuthRoles} from "@model/AuthRoles";
import {HasRoleDirective} from "@/directives/has-role.directive"; import {HasRoleDirective} from "@/directives/has-role.directive";
import {TabStorageService} from "@service/tab-storage.service"; import {TabStorageComponent} from "@component/common/tab-storage/tab-storage.component";
export enum TabsSelect { export enum TabsSelect {
Group, Group,
@ -44,7 +44,7 @@ export enum TabsSelect {
], ],
templateUrl: './tabs.component.html', templateUrl: './tabs.component.html',
styleUrl: './tabs.component.css', styleUrl: './tabs.component.css',
providers: [ScheduleService, DisciplineService, LectureHallService, GroupService, ProfessorService, TabStorageService] providers: [ScheduleService, DisciplineService, LectureHallService, GroupService, ProfessorService]
}) })
export class TabsComponent implements AfterViewInit { export class TabsComponent implements AfterViewInit {
@ -58,26 +58,14 @@ export class TabsComponent implements AfterViewInit {
} }
ngAfterViewInit(): void { ngAfterViewInit(): void {
let selected = TabStorageService.selected; let selected = TabStorageComponent.selected;
let index = 0; let index = 0;
if (selected !== null)
index = selected.type;
if (selected !== null) { this.chooseTabs(index).then();
if (selected.type === null) { this.tabs.selectedIndex = index;
if (this.groupTab.existParams(selected))
index = 0;
else if (this.professorTab.existParams(selected))
index = 1;
else if (this.lectureHallTab.existParams(selected))
index = 2;
} else
index = selected.type;
}
if (index === null || index === 0)
this.chooseTabs(0).then();
else
this.tabs.selectedIndex = index;
} }
protected groupSelected(id: number) { protected groupSelected(id: number) {

View File

@ -1,12 +1,6 @@
.schedule { .schedule {
padding: 50px 15%; padding: 50px 15%;
min-height: 60vh; min-height: 60vh;
overflow: visible;
}
.schedule mat-sidenav-content {
overflow: inherit;
margin-bottom: 15px;
} }
@media screen and (max-width: 599px) { @media screen and (max-width: 599px) {

View File

@ -1,18 +1,6 @@
<mat-sidenav-container class="schedule"> <mat-sidenav-container class="schedule">
<mat-sidenav-content> <app-tabs (eventResult)="result($event)"/>
<app-tabs (eventResult)="result($event)"/> <app-table-header [startWeek]="startWeek" [currentWeek]="currentWeek" (weekEvent)="handleWeekEvent($event)"
</mat-sidenav-content> #tableHeader/>
<app-table [currentWeek]="currentWeek" [startWeek]="startWeek" [data]="data" [isLoad]="isLoadTable"/>
<mat-sidenav-content>
<app-table-header [startWeek]="startWeek" [currentWeek]="currentWeek" (weekEvent)="handleWeekEvent($event)"
#tableHeader/>
</mat-sidenav-content>
<mat-sidenav-content>
<app-table [currentWeek]="currentWeek" [startWeek]="startWeek" [data]="data" [isLoad]="isLoadTable" [disciplineWithWeeks]="disciplineWithWeeks"/>
</mat-sidenav-content>
<mat-sidenav-content>
<mat-checkbox (change)="changeDisciplineWeeksView($event.checked)" [checked]="disciplineWithWeeks">Показать недели в дисциплине</mat-checkbox>
</mat-sidenav-content>
</mat-sidenav-container> </mat-sidenav-container>

View File

@ -1,4 +1,4 @@
import {Component, LOCALE_ID, OnInit, ViewChild} from '@angular/core'; import {Component, LOCALE_ID, ViewChild} from '@angular/core';
import {TableComponent} from "@component/schedule/table/table.component"; import {TableComponent} from "@component/schedule/table/table.component";
import {MatFormField, MatInput} from "@angular/material/input"; import {MatFormField, MatInput} from "@angular/material/input";
import {MatButton} from "@angular/material/button"; import {MatButton} from "@angular/material/button";
@ -6,15 +6,12 @@ import {FormsModule} from "@angular/forms";
import {AdditionalText, TableHeaderComponent} from "@component/schedule/table-header/table-header.component"; import {AdditionalText, TableHeaderComponent} from "@component/schedule/table-header/table-header.component";
import {addDays, weekInYear} from "@progress/kendo-date-math"; import {addDays, weekInYear} from "@progress/kendo-date-math";
import {MatCard} from "@angular/material/card"; import {MatCard} from "@angular/material/card";
import {MatSidenavModule} from "@angular/material/sidenav"; import {MatSidenavContainer} from "@angular/material/sidenav";
import {TabsComponent, TabsSelect} from "@component/schedule/tabs/tabs.component"; import {TabsComponent, TabsSelect} from "@component/schedule/tabs/tabs.component";
import {catchError, Observable} from "rxjs"; import {catchError, Observable} from "rxjs";
import {ScheduleService} from "@api/v1/schedule.service"; import {ScheduleService} from "@api/v1/schedule.service";
import {ScheduleResponse} from "@api/v1/scheduleResponse"; import {ScheduleResponse} from "@api/v1/scheduleResponse";
import {PeriodTimes} from "@model/pairPeriodTime"; import {PeriodTimes} from "@model/pairPeriodTime";
import {MatCheckbox} from "@angular/material/checkbox";
import {ActivatedRoute} from "@angular/router";
import {TabStorageService} from "@service/tab-storage.service";
@Component({ @Component({
selector: 'app-schedule', selector: 'app-schedule',
@ -27,9 +24,8 @@ import {TabStorageService} from "@service/tab-storage.service";
FormsModule, FormsModule,
TableHeaderComponent, TableHeaderComponent,
MatCard, MatCard,
MatSidenavModule, MatSidenavContainer,
TabsComponent, TabsComponent
MatCheckbox
], ],
templateUrl: './schedule.component.html', templateUrl: './schedule.component.html',
styleUrl: './schedule.component.css', styleUrl: './schedule.component.css',
@ -39,29 +35,19 @@ import {TabStorageService} from "@service/tab-storage.service";
] ]
}) })
export class ScheduleComponent implements OnInit { export class ScheduleComponent {
protected startWeek: Date; protected startWeek!: Date;
protected data: ScheduleResponse[] = []; protected data: ScheduleResponse[] = [];
protected startTerm: Date; protected startTerm: Date;
protected isLoadTable: boolean = false; protected isLoadTable: boolean = false;
protected pairPeriods: PeriodTimes = {}; protected pairPeriods: PeriodTimes = {};
protected disciplineWithWeeks: boolean = false;
@ViewChild('tableHeader') childComponent!: TableHeaderComponent; @ViewChild('tableHeader') childComponent!: TableHeaderComponent;
constructor(api: ScheduleService, route: ActivatedRoute) { constructor(api: ScheduleService) {
route.queryParams.subscribe(params => {
TabStorageService.selectDataFromQuery(params);
});
this.startTerm = new Date(1, 1, 1); this.startTerm = new Date(1, 1, 1);
this.startWeek = new Date(1, 1, 1); this.startWeek = new Date(1, 1, 1);
let disciplineWithWeeksStorage = localStorage.getItem('disciplineWithWeeks');
if (disciplineWithWeeksStorage)
this.disciplineWithWeeks = disciplineWithWeeksStorage.toLowerCase() === 'true';
api.pairPeriod().subscribe(date => { api.pairPeriod().subscribe(date => {
this.pairPeriods = date; this.pairPeriods = date;
}); });
@ -71,9 +57,6 @@ export class ScheduleComponent implements OnInit {
}); });
} }
ngOnInit(): void {
}
protected result(data: [TabsSelect, number, Observable<ScheduleResponse[]>]) { protected result(data: [TabsSelect, number, Observable<ScheduleResponse[]>]) {
this.isLoadTable = true; this.isLoadTable = true;
data[2] data[2]
@ -137,9 +120,4 @@ export class ScheduleComponent implements OnInit {
return result; return result;
} }
protected changeDisciplineWeeksView(checked: boolean) {
localStorage.setItem('disciplineWithWeeks', checked.toString());
this.disciplineWithWeeks = checked;
}
} }

View File

@ -1,113 +0,0 @@
import {MatChipListbox} from "@angular/material/chips";
import {Injectable} from "@angular/core";
import {Params, Router} from "@angular/router";
import {Location} from '@angular/common';
export class TabSelect {
public index: number;
public name: string;
constructor(index: number, name: string) {
this.index = index;
this.name = name;
}
}
export enum TabSelectType {
group,
professor,
lecture,
other
}
export interface TabSelectData {
selected: { [key: string]: TabSelect };
type: TabSelectType | null;
}
@Injectable({
providedIn: 'root'
})
export class TabStorageService {
private static dataName = 'tabSelectedData';
constructor(private router: Router, private location: Location) {
}
public static trySelectChip(index: number, chip: MatChipListbox, tryCount: number = 0) {
setTimeout(() => {
if (chip?._chips !== undefined && chip._chips.length !== 0) {
let selected = chip._chips.find(x => x.value == index.toString());
if (selected !== undefined) {
selected.select();
return;
}
}
if (tryCount < 10)
this.trySelectChip(index, chip, ++tryCount);
else
return;
}, 100);
}
private resetIfNeed(type: TabSelectType) {
let selectedData = TabStorageService.selected;
if (selectedData === null || selectedData?.type === null)
return;
if (selectedData.type !== type) {
localStorage.removeItem(TabStorageService.dataName);
const currentUrl = this.router.url.split('?')[0];
this.location.replaceState(currentUrl);
}
}
public select(selected: TabSelect, type: TabSelectType, navigateName: string) {
this.resetIfNeed(type);
let selectedData = TabStorageService.selected;
if (selectedData === null || !selectedData.selected)
selectedData = {selected: {}} as TabSelectData;
selectedData.selected[navigateName] = selected;
selectedData.type = type;
localStorage.setItem(TabStorageService.dataName, JSON.stringify(selectedData));
const currentUrl = this.router.url.split('?')[0];
const queryParam = new URLSearchParams();
for (let select in selectedData.selected)
queryParam.set(select, selectedData.selected[select].name);
this.location.replaceState(currentUrl, queryParam.toString());
}
public static selectDataFromQuery(query: Params) {
if (Object.keys(query).length === 0)
return;
let selectedData = {selected: {}} as TabSelectData;
selectedData.type = null;
for (let select in query) {
selectedData.selected[select] = {} as TabSelect;
selectedData.selected[select].name = query[select];
selectedData.selected[select].index = -1;
}
localStorage.setItem(TabStorageService.dataName, JSON.stringify(selectedData));
}
public static get selected(): TabSelectData | null {
let data = localStorage.getItem(this.dataName);
if (data === null)
return null;
return JSON.parse(data) as TabSelectData;
}
}