feat: add parameters as navigation

Now there is automatic navigation on the inserted url and on localStorage
This commit is contained in:
Polianin Nikita 2024-08-28 03:52:47 +03:00
parent 60218a73f2
commit 79393a39c3
7 changed files with 131 additions and 80 deletions

View File

@ -9,7 +9,7 @@ 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, TabSelectType, TabStorageService} from "@service/tab-storage.service"; import {TabSelect, TabSelectData, TabSelectType, TabStorageService} from "@service/tab-storage.service";
@Component({ @Component({
selector: 'app-group', selector: 'app-group',
@ -45,20 +45,17 @@ 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) { constructor(private facultyApi: FacultyService, private groupApi: GroupService, private tabStorage: TabStorageService) {
let selectedData = TabStorageService.selected; }
if (selectedData !== null && selectedData.selected !== null) {
if (selectedData.type === TabSelectType.group) existParams(data: TabSelectData): boolean {
this.selected = selectedData.selected; return data.selected['group'] !== undefined || data.selected['course'] !== undefined || data.selected['faculty'] !== undefined;
}
} }
protected loadFaculties() { protected loadFaculties() {
@ -70,11 +67,12 @@ export class GroupComponent implements IScheduleTab {
.subscribe(data => { .subscribe(data => {
this.faculties = data; this.faculties = data;
if (this.selected !== null && this.selected.length >= 1) { let selected = TabStorageService.selected?.selected['faculty'];
let selectedFaculty = data.find(x => x.id === this.selected![0].index); if (selected) {
let selectedFaculty = data.find(x => x.id === selected.index);
if (selectedFaculty === undefined || selectedFaculty.name !== this.selected[0].name) if (selectedFaculty === undefined || selectedFaculty.name !== selected.name)
selectedFaculty = data.find(x => x.name === this.selected![0].name); selectedFaculty = data.find(x => x.name === selected.name);
if (selectedFaculty !== undefined) { if (selectedFaculty !== undefined) {
TabStorageService.trySelectChip(selectedFaculty.id, this.facultyChip); TabStorageService.trySelectChip(selectedFaculty.id, this.facultyChip);
@ -104,8 +102,12 @@ export class GroupComponent implements IScheduleTab {
.sort((a, b) => a - b)) .sort((a, b) => a - b))
); );
if (this.selected !== null && this.selected.length >= 2) { let selected = TabStorageService.selected?.selected['course'];
let selectedCourse = this.courseNumbers.find(x => x === this.selected![1].index); if (selected) {
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); TabStorageService.trySelectChip(selectedCourse, this.courseChip);
@ -113,11 +115,12 @@ export class GroupComponent implements IScheduleTab {
} }
} }
if (this.selected !== null && this.selected.length >= 3) { let selectedGroupStorage = TabStorageService.selected?.selected['group'];
let selectedGroup = data.find(x => x.id === this.selected![2].index); if (selectedGroupStorage) {
let selectedGroup = data.find(x => x.id === selectedGroupStorage.index);
if (selectedGroup === undefined || selectedGroup.name !== this.selected[2].name) if (selectedGroup === undefined || selectedGroup.name !== selectedGroupStorage.name)
selectedGroup = data.find(x => x.name === this.selected![2].name); selectedGroup = data.find(x => x.name === selectedGroupStorage.name);
if (selectedGroup !== undefined) { if (selectedGroup !== undefined) {
TabStorageService.trySelectChip(selectedGroup.id, this.groupChip); TabStorageService.trySelectChip(selectedGroup.id, this.groupChip);
@ -144,7 +147,7 @@ export class GroupComponent implements IScheduleTab {
return; return;
} }
TabStorageService.select(new TabSelect(index, this.faculties!.find(x => x.id === index)?.name ?? ''), TabSelectType.group, 0); this.tabStorage.select(new TabSelect(index, this.faculties!.find(x => x.id === index)?.name ?? ''), TabSelectType.group, 'faculty');
this.facultyId = index; this.facultyId = index;
this.courseNumberPanel.open(); this.courseNumberPanel.open();
@ -161,7 +164,7 @@ export class GroupComponent implements IScheduleTab {
return; return;
} }
TabStorageService.select(new TabSelect(course, course.toString()), TabSelectType.group, 1); this.tabStorage.select(new TabSelect(course, course.toString()), TabSelectType.group, 'course');
this.courseNumber = course; this.courseNumber = course;
this.groupPanel.open(); this.groupPanel.open();
@ -172,7 +175,7 @@ export class GroupComponent implements IScheduleTab {
if (index === undefined) if (index === undefined)
return; return;
TabStorageService.select(new TabSelect(index, this.groups!.find(x => x.id == index)?.name ?? ''), TabSelectType.group, 2); this.tabStorage.select(new TabSelect(index, this.groups!.find(x => x.id == index)?.name ?? ''), TabSelectType.group, 'group');
this.groupPanel.close(); this.groupPanel.close();
this.eventResult.emit(index); this.eventResult.emit(index);

View File

@ -1,6 +1,8 @@
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, TabSelectType, TabStorageService} from "@service/tab-storage.service"; import {TabSelect, TabSelectData, TabSelectType, TabStorageService} from "@service/tab-storage.service";
@Component({ @Component({
selector: 'app-lecture-hall', selector: 'app-lecture-hall',
@ -45,14 +45,12 @@ 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) { constructor(private campusApi: CampusService, private lectureHallApi: LectureHallService, private tabStorage: TabStorageService) {
let selectedData = TabStorageService.selected; }
if (selectedData !== null && selectedData.selected !== null) {
if (selectedData.type === TabSelectType.lecture) existParams(data: TabSelectData): boolean {
this.selected = selectedData.selected; return data.selected['campus'] !== undefined || data.selected['lecture'] !== undefined;
}
} }
protected loadCampuses() { protected loadCampuses() {
@ -64,11 +62,12 @@ export class LectureHallComponent implements IScheduleTab {
.subscribe(data => { .subscribe(data => {
this.campuses = data; this.campuses = data;
if (this.selected !== null && this.selected.length >= 1) { let selected = TabStorageService.selected?.selected['campus'];
let selectedCampus = data.find(x => x.id === this.selected![0].index); if (selected) {
let selectedCampus = data.find(x => x.id === selected.index);
if (selectedCampus === undefined || selectedCampus.codeName !== this.selected![0].name) if (selectedCampus === undefined || selectedCampus.codeName !== selected.name)
selectedCampus = data.find(x => x.codeName === this.selected![0].name); selectedCampus = data.find(x => x.codeName === selected.name);
if (selectedCampus !== undefined) { if (selectedCampus !== undefined) {
TabStorageService.trySelectChip(selectedCampus.id, this.campusChip); TabStorageService.trySelectChip(selectedCampus.id, this.campusChip);
@ -85,7 +84,7 @@ export class LectureHallComponent implements IScheduleTab {
protected onCampusSelected(index: number) { protected onCampusSelected(index: number) {
this.formLectureHalls.reset(); this.formLectureHalls.reset();
TabStorageService.select(new TabSelect(index, this.campuses!.find(x => x.id === index)?.codeName ?? ''), TabSelectType.lecture, 0); this.tabStorage.select(new TabSelect(index, this.campuses!.find(x => x.id === index)?.codeName ?? ''), TabSelectType.lecture, 'campus');
if (index === undefined) { if (index === undefined) {
this.campusId = null; this.campusId = null;
@ -111,11 +110,13 @@ 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);
if (selectedLecture === undefined || selectedLecture.name !== this.selected![1].name) let selected = TabStorageService.selected?.selected['lecture'];
selectedLecture = data.find(x => x.name === this.selected![1].name); if (selected) {
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); TabStorageService.trySelectChip(selectedLecture.id, this.lectureChip);
@ -129,7 +130,7 @@ export class LectureHallComponent implements IScheduleTab {
if (index === undefined) if (index === undefined)
return; return;
TabStorageService.select(new TabSelect(index, this.lectureHallsFiltered!.find(x => x.id === index)?.name ?? ''), TabSelectType.lecture, 1); this.tabStorage.select(new TabSelect(index, this.lectureHallsFiltered!.find(x => x.id === index)?.name ?? ''), TabSelectType.lecture, 'lecture');
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, TabSelectType, TabStorageService} from "@service/tab-storage.service"; import {TabSelect, TabSelectData, TabSelectType, TabStorageService} from "@service/tab-storage.service";
@Component({ @Component({
selector: 'app-professor', selector: 'app-professor',
@ -30,18 +30,16 @@ 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) { constructor(private api: ProfessorService, private tabStorage: TabStorageService) {
let selectedData = TabStorageService.selected; }
if (selectedData !== null && selectedData.selected !== null) {
if (selectedData.type === TabSelectType.professor) existParams(data: TabSelectData): boolean {
this.selected = selectedData.selected; return data.selected['professor'] !== undefined;
}
} }
protected loadProfessors() { protected loadProfessors() {
@ -54,11 +52,12 @@ export class ProfessorComponent implements OnInit, IScheduleTab {
.subscribe(data => { .subscribe(data => {
this.professors = data; this.professors = data;
if (this.selected !== null && this.selected.length >= 1) { let selected = TabStorageService.selected?.selected['professor'];
let selectedProfessor = data.find(x => x.id === this.selected![0].index); if (selected) {
let selectedProfessor = data.find(x => x.id === selected.index);
if (selectedProfessor === undefined || selectedProfessor.name !== this.selected[0].name) if (selectedProfessor === undefined || selectedProfessor.name !== selected.name)
selectedProfessor = data.find(x => x.name === this.selected![0].name); selectedProfessor = data.find(x => x.name === selected.name);
if (selectedProfessor !== undefined) if (selectedProfessor !== undefined)
this.onOptionSelected(selectedProfessor.id); this.onOptionSelected(selectedProfessor.id);
@ -96,7 +95,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);
TabStorageService.select(new TabSelect(selectedOption.id, selectedOption.name), TabSelectType.professor, 0); this.tabStorage.select(new TabSelect(selectedOption.id, selectedOption.name), TabSelectType.professor, 'professor');
} }
} }

View File

@ -61,8 +61,18 @@ export class TabsComponent implements AfterViewInit {
let selected = TabStorageService.selected; let selected = TabStorageService.selected;
let index = 0; let index = 0;
if (selected !== null)
index = selected.type; if (selected !== null) {
if (selected.type === null) {
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) if (index === null || index === 0)
this.chooseTabs(0).then(); this.chooseTabs(0).then();

View File

@ -1,4 +1,4 @@
import {Component, LOCALE_ID, ViewChild} from '@angular/core'; import {Component, LOCALE_ID, OnInit, 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";
@ -13,6 +13,8 @@ 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 {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',
@ -37,7 +39,7 @@ import {MatCheckbox} from "@angular/material/checkbox";
] ]
}) })
export class ScheduleComponent { export class ScheduleComponent implements OnInit {
protected startWeek: Date; protected startWeek: Date;
protected data: ScheduleResponse[] = []; protected data: ScheduleResponse[] = [];
protected startTerm: Date; protected startTerm: Date;
@ -47,7 +49,11 @@ export class ScheduleComponent {
@ViewChild('tableHeader') childComponent!: TableHeaderComponent; @ViewChild('tableHeader') childComponent!: TableHeaderComponent;
constructor(api: ScheduleService) { constructor(api: ScheduleService, route: ActivatedRoute) {
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);
@ -65,6 +71,9 @@ export class ScheduleComponent {
}); });
} }
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]

View File

@ -1,5 +1,7 @@
import {MatChipListbox} from "@angular/material/chips"; import {MatChipListbox} from "@angular/material/chips";
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import {Params, Router} from "@angular/router";
import {Location} from '@angular/common';
export class TabSelect { export class TabSelect {
public index: number; public index: number;
@ -19,8 +21,8 @@ export enum TabSelectType {
} }
export interface TabSelectData { export interface TabSelectData {
selected: TabSelect[] | null; selected: { [key: string]: TabSelect };
type: TabSelectType; type: TabSelectType | null;
} }
@Injectable({ @Injectable({
@ -29,6 +31,9 @@ export interface TabSelectData {
export class TabStorageService { export class TabStorageService {
private static dataName = 'tabSelectedData'; private static dataName = 'tabSelectedData';
constructor(private router: Router, private location: Location) {
}
public static trySelectChip(index: number, chip: MatChipListbox, tryCount: number = 0) { public static trySelectChip(index: number, chip: MatChipListbox, tryCount: number = 0) {
setTimeout(() => { setTimeout(() => {
if (chip?._chips !== undefined && chip._chips.length !== 0) { if (chip?._chips !== undefined && chip._chips.length !== 0) {
@ -47,32 +52,54 @@ export class TabStorageService {
}, 100); }, 100);
} }
public static select(selected: TabSelect, type: TabSelectType, index: number) { private resetIfNeed(type: TabSelectType) {
let selectedData = this.selected; let selectedData = TabStorageService.selected;
if (selectedData === null) if (selectedData === null || selectedData?.type === null)
selectedData = {} as TabSelectData; return;
if (selectedData.type !== type || selectedData.selected === null || selectedData.selected.length === 0) { if (selectedData.type !== type) {
if (index !== 0) localStorage.removeItem(TabStorageService.dataName);
return; const currentUrl = this.router.url.split('?')[0];
else this.location.replaceState(currentUrl);
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);
} }
}
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; selectedData.type = type;
localStorage.setItem(this.dataName, JSON.stringify(selectedData)); 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 { public static get selected(): TabSelectData | null {