diff --git a/package-lock.json b/package-lock.json index be03885..8027eba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "frontend", - "version": "1.0.0-b6", + "version": "1.0.0-b7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "frontend", - "version": "1.0.0-b6", + "version": "1.0.0-b7", "dependencies": { "@angular/animations": "^18.2.6", "@angular/cdk": "~18.2.6", diff --git a/package.json b/package.json index f5ce5e8..e83155a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "frontend", - "version": "1.0.0-b6", + "version": "1.0.0-b7", "scripts": { "ng": "ng", "start": "ng serve", diff --git a/src/components/schedule/tabs/group/group.component.ts b/src/components/schedule/tabs/group/group.component.ts index bdaaecd..ea24966 100644 --- a/src/components/schedule/tabs/group/group.component.ts +++ b/src/components/schedule/tabs/group/group.component.ts @@ -1,4 +1,4 @@ -import {Component, EventEmitter, Output, ViewChild} from '@angular/core'; +import {Component, EventEmitter, ViewChild} from '@angular/core'; import {MatExpansionModule, MatExpansionPanel} from "@angular/material/expansion"; import {MatChipListbox, MatChipsModule} from '@angular/material/chips'; import {FormControl, FormsModule, ReactiveFormsModule} from "@angular/forms"; @@ -9,7 +9,11 @@ import {FacultyResponse} from "@api/v1/facultyResponse"; import {FacultyService} from "@api/v1/faculty.service"; import {GroupService} from "@api/v1/group.service"; import {IScheduleTab} from "@component/schedule/tabs/ischedule-tab"; -import {TabSelect, TabSelectData, TabSelectType, TabStorageService} from "@service/tab-storage.service"; +import {TabSelect, TabStorageService} from "@service/tab-storage.service"; + +enum Enclosure { + faculty, course, group +} @Component({ selector: 'app-group', @@ -25,7 +29,6 @@ import {TabSelect, TabSelectData, TabSelectType, TabStorageService} from "@servi styleUrl: './group.component.css', providers: [FacultyService, GroupService] }) - export class GroupComponent implements IScheduleTab { protected faculties: FacultyResponse[] | null = null; protected courseNumbers: number[] | null = null; @@ -51,13 +54,50 @@ export class GroupComponent implements IScheduleTab { @ViewChild('courseIndicator') courseIndicator!: LoadingIndicatorComponent; @ViewChild('groupIndicator') groupIndicator!: LoadingIndicatorComponent; - @Output() eventResult = new EventEmitter(); - - constructor(private facultyApi: FacultyService, private groupApi: GroupService, private tabStorage: TabStorageService) { + private resetCourse() { + this.courseNumber = null; + this.groups = []; + this.formChipCourse.reset(); + this.courseChip.value = undefined; } - existParams(data: TabSelectData): boolean { - return data.selected['group'] !== undefined || data.selected['course'] !== undefined || data.selected['faculty'] !== undefined; + private resetGroup() { + this.filteredGroupsBehaviour = []; + this.filteredGroupsMagistracy = []; + this.filteredGroupsSpecialist = []; + this.formChipGroup.reset(); + this.groupChip.value = undefined; + } + + public eventResult = new EventEmitter(); + public selectChangeEvent = new EventEmitter(); + + constructor(private facultyApi: FacultyService, private groupApi: GroupService) { + } + + private getSelectedTabs(): TabSelect[] { + const faculty = this.facultyChip.value; + const course = this.courseChip.value; + const group = this.groupChip.value; + + const result: TabSelect[] = []; + + if (faculty) + result.push(new TabSelect(faculty, this.faculties!.find(x => x.id === faculty)?.name ?? '')); + + if (course) + result.push(new TabSelect(course, course.toString())); + + if (group) + result.push(new TabSelect(group, this.groups!.find(x => x.id == group)?.name ?? '')); + + return result; + } + + public getEnclosureList(): string[] { + return Object.keys(Enclosure).filter((item) => { + return isNaN(Number(item)); + }); } protected loadFaculties() { @@ -69,7 +109,8 @@ export class GroupComponent implements IScheduleTab { .subscribe(data => { this.faculties = data; - let selected = TabStorageService.selected?.selected['faculty']; + let selected = TabStorageService.selected?.selected[this.getEnclosureList()[Enclosure.faculty]]; + if (selected) { let selectedFaculty = data.find(x => x.id === selected.index); @@ -78,7 +119,7 @@ export class GroupComponent implements IScheduleTab { if (selectedFaculty !== undefined) { TabStorageService.trySelectChip(selectedFaculty.id, this.facultyChip); - this.onFacultySelected(selectedFaculty.id); + this.onFacultySelected(selectedFaculty.id, true); } } }); @@ -104,7 +145,7 @@ export class GroupComponent implements IScheduleTab { .sort((a, b) => a - b)) ); - let selected = TabStorageService.selected?.selected['course']; + let selected = TabStorageService.selected?.selected[this.getEnclosureList()[Enclosure.course]]; if (selected) { let selectedCourse = this.courseNumbers.find(x => x === selected.index); @@ -113,11 +154,11 @@ export class GroupComponent implements IScheduleTab { if (selectedCourse !== undefined) { TabStorageService.trySelectChip(selectedCourse, this.courseChip); - this.onCourseSelected(selectedCourse); + this.onCourseSelected(selectedCourse, true); } } - let selectedGroupStorage = TabStorageService.selected?.selected['group']; + let selectedGroupStorage = TabStorageService.selected?.selected[this.getEnclosureList()[Enclosure.group]]; if (selectedGroupStorage) { let selectedGroup = data.find(x => x.id === selectedGroupStorage.index); @@ -126,7 +167,7 @@ export class GroupComponent implements IScheduleTab { if (selectedGroup !== undefined) { TabStorageService.trySelectChip(selectedGroup.id, this.groupChip); - this.onGroupSelected(selectedGroup.id); + this.onGroupSelected(selectedGroup.id, true); } } }); @@ -147,18 +188,19 @@ export class GroupComponent implements IScheduleTab { } } - protected onFacultySelected(index: number) { - this.courseNumber = null; - this.groups = []; - this.formChipGroup.reset(); - this.formChipCourse.reset(); + protected onFacultySelected(index: number, loadMode: boolean = false) { + this.resetCourse(); + this.resetGroup(); if (index === undefined) { this.facultyId = null; return; } - this.tabStorage.select(new TabSelect(index, this.faculties!.find(x => x.id === index)?.name ?? ''), TabSelectType.group, 'faculty'); + if (loadMode) + this.facultyChip.value = index; + else + this.selectChangeEvent.emit(this.getSelectedTabs()); this.facultyId = index; this.courseNumberPanel.open(); @@ -166,29 +208,32 @@ export class GroupComponent implements IScheduleTab { this.loadCourseGroup(); } - protected onCourseSelected(course: number) { - this.filteredGroupsBehaviour = []; - this.filteredGroupsMagistracy = []; - this.filteredGroupsSpecialist = []; - this.formChipGroup.reset(); + protected onCourseSelected(course: number, loadMode: boolean = false) { + this.resetGroup(); if (course === undefined) { this.courseNumber = null; return; } - this.tabStorage.select(new TabSelect(course, course.toString()), TabSelectType.group, 'course'); + if (loadMode) + this.courseChip.value = course; + else + this.selectChangeEvent.emit(this.getSelectedTabs()); this.courseNumber = course; this.groupPanel.open(); this.loadCourseGroup(); } - protected onGroupSelected(index: number) { + protected onGroupSelected(index: number, loadMode: boolean = false) { if (index === undefined) return; - this.tabStorage.select(new TabSelect(index, this.groups!.find(x => x.id == index)?.name ?? ''), TabSelectType.group, 'group'); + if (loadMode) + this.groupChip.value = index; + + this.selectChangeEvent.emit(this.getSelectedTabs()); this.groupPanel.close(); this.eventResult.emit(index); diff --git a/src/components/schedule/tabs/ischedule-tab.ts b/src/components/schedule/tabs/ischedule-tab.ts index 7265cf6..8784c91 100644 --- a/src/components/schedule/tabs/ischedule-tab.ts +++ b/src/components/schedule/tabs/ischedule-tab.ts @@ -1,8 +1,12 @@ import {EventEmitter} from "@angular/core"; -import {TabSelectData} from "@service/tab-storage.service"; +import {TabSelect} from "@service/tab-storage.service"; + export interface IScheduleTab { load(): void; + + getEnclosureList(): string[]; + eventResult: EventEmitter; - existParams(data: TabSelectData): boolean; + selectChangeEvent: EventEmitter; } diff --git a/src/components/schedule/tabs/lecture-hall/lecture-hall.component.ts b/src/components/schedule/tabs/lecture-hall/lecture-hall.component.ts index a0faf3c..82ff2cb 100644 --- a/src/components/schedule/tabs/lecture-hall/lecture-hall.component.ts +++ b/src/components/schedule/tabs/lecture-hall/lecture-hall.component.ts @@ -1,4 +1,4 @@ -import {Component, EventEmitter, Output, ViewChild} from '@angular/core'; +import {Component, EventEmitter, ViewChild} from '@angular/core'; import {AsyncPipe} from "@angular/common"; import {MatAccordion, MatExpansionModule, MatExpansionPanel} from "@angular/material/expansion"; import {MatChipListbox, MatChipsModule} from "@angular/material/chips"; @@ -10,7 +10,11 @@ import {LectureHallResponse} from "@api/v1/lectureHallResponse"; import {CampusService} from "@api/v1/campus.service"; import {LectureHallService} from "@api/v1/lectureHall.service"; import {IScheduleTab} from "@component/schedule/tabs/ischedule-tab"; -import {TabSelect, TabSelectData, TabSelectType, TabStorageService} from "@service/tab-storage.service"; +import {TabSelect, TabStorageService} from "@service/tab-storage.service"; + +enum Enclosure { + campus, lecture +} @Component({ selector: 'app-lecture-hall', @@ -27,7 +31,6 @@ import {TabSelect, TabSelectData, TabSelectType, TabStorageService} from "@servi styleUrl: './lecture-hall.component.css', providers: [CampusService, LectureHallService] }) - export class LectureHallComponent implements IScheduleTab { protected campusId: number | null = null; protected formLectureHalls: FormControl = new FormControl(); @@ -35,8 +38,6 @@ export class LectureHallComponent implements IScheduleTab { protected campuses: CampusBasicInfoResponse[] | null = null; protected lectureHallsFiltered: LectureHallResponse[] | null = null; - @Output() eventResult = new EventEmitter(); - @ViewChild('lecturePanel') lecturePanel!: MatExpansionPanel; @ViewChild('lectureIndicator') lectureIndicator!: LoadingIndicatorComponent; @ViewChild('campusIndicator') campusIndicator!: LoadingIndicatorComponent; @@ -46,11 +47,31 @@ export class LectureHallComponent implements IScheduleTab { private lectureHalls: LectureHallResponse[] | null = null; - constructor(private campusApi: CampusService, private lectureHallApi: LectureHallService, private tabStorage: TabStorageService) { + public eventResult = new EventEmitter(); + public selectChangeEvent = new EventEmitter(); + + constructor(private campusApi: CampusService, private lectureHallApi: LectureHallService) { } - existParams(data: TabSelectData): boolean { - return data.selected['campus'] !== undefined || data.selected['lecture'] !== undefined; + private getSelectedTabs(): TabSelect[] { + const campus = this.campusChip.value; + const lecture = this.lectureChip.value; + + const result: TabSelect[] = []; + + if (campus) + result.push(new TabSelect(campus, this.campuses!.find(x => x.id === campus)?.codeName ?? '')); + + if (lecture) + result.push(new TabSelect(lecture, this.lectureHallsFiltered!.find(x => x.id === lecture)?.name ?? '')); + + return result; + } + + getEnclosureList(): string[] { + return Object.keys(Enclosure).filter((item) => { + return isNaN(Number(item)); + }); } protected loadCampuses() { @@ -62,7 +83,7 @@ export class LectureHallComponent implements IScheduleTab { .subscribe(data => { this.campuses = data; - let selected = TabStorageService.selected?.selected['campus']; + let selected = TabStorageService.selected?.selected[this.getEnclosureList()[Enclosure.campus]]; if (selected) { let selectedCampus = data.find(x => x.id === selected.index); @@ -71,7 +92,7 @@ export class LectureHallComponent implements IScheduleTab { if (selectedCampus !== undefined) { TabStorageService.trySelectChip(selectedCampus.id, this.campusChip); - this.onCampusSelected(selectedCampus.id); + this.onCampusSelected(selectedCampus.id, true); } } }); @@ -81,10 +102,14 @@ export class LectureHallComponent implements IScheduleTab { this.lectureHallsFiltered = this.lectureHalls?.filter(x => x.campusId === this.campusId) ?? null; } - protected onCampusSelected(index: number) { + protected onCampusSelected(index: number, loadMode: boolean = false) { this.formLectureHalls.reset(); + this.lectureChip.value = undefined; - this.tabStorage.select(new TabSelect(index, this.campuses!.find(x => x.id === index)?.codeName ?? ''), TabSelectType.lecture, 'campus'); + if (loadMode) + this.campusChip.value = index; + else + this.selectChangeEvent.emit(this.getSelectedTabs()); if (index === undefined) { this.campusId = null; @@ -111,7 +136,7 @@ export class LectureHallComponent implements IScheduleTab { this.lectureHalls = data; this.filteringLectureHalls(); - let selected = TabStorageService.selected?.selected['lecture']; + let selected = TabStorageService.selected?.selected[this.getEnclosureList()[Enclosure.lecture]]; if (selected) { let selectedLecture = data.find(x => x.id === selected.index); @@ -120,17 +145,20 @@ export class LectureHallComponent implements IScheduleTab { if (selectedLecture !== undefined) { TabStorageService.trySelectChip(selectedLecture.id, this.lectureChip); - this.onLectureHallSelected(selectedLecture.id); + this.onLectureHallSelected(selectedLecture.id, true); } } }); } - protected onLectureHallSelected(index: number) { + protected onLectureHallSelected(index: number, loadMode: boolean = false) { if (index === undefined) return; - this.tabStorage.select(new TabSelect(index, this.lectureHallsFiltered!.find(x => x.id === index)?.name ?? ''), TabSelectType.lecture, 'lecture'); + if (loadMode) + this.lectureChip.value = index; + else + this.selectChangeEvent.emit(this.getSelectedTabs()); this.lecturePanel.close(); this.eventResult.emit(index); diff --git a/src/components/schedule/tabs/professor/professor.component.ts b/src/components/schedule/tabs/professor/professor.component.ts index 7d21e94..58fb0fe 100644 --- a/src/components/schedule/tabs/professor/professor.component.ts +++ b/src/components/schedule/tabs/professor/professor.component.ts @@ -1,4 +1,4 @@ -import {Component, EventEmitter, OnInit, Output, ViewChild} from "@angular/core"; +import {Component, EventEmitter, OnInit, ViewChild} from "@angular/core"; import {MatFormField, MatInput} from "@angular/material/input"; import {FormControl, ReactiveFormsModule} from "@angular/forms"; import {MatAutocompleteModule} from "@angular/material/autocomplete"; @@ -8,7 +8,7 @@ import {LoadingIndicatorComponent} from "@component/common/loading-indicator/loa import {ProfessorResponse} from "@api/v1/professorResponse"; import {ProfessorService} from "@api/v1/professor.service"; import {IScheduleTab} from "@component/schedule/tabs/ischedule-tab"; -import {TabSelect, TabSelectData, TabSelectType, TabStorageService} from "@service/tab-storage.service"; +import {TabSelect, TabStorageService} from "@service/tab-storage.service"; @Component({ selector: 'app-professor', @@ -33,13 +33,14 @@ export class ProfessorComponent implements OnInit, IScheduleTab { @ViewChild('professorIndicator') professorIndicator!: LoadingIndicatorComponent; - @Output() eventResult = new EventEmitter(); + public eventResult = new EventEmitter(); + public selectChangeEvent = new EventEmitter(); - constructor(private api: ProfessorService, private tabStorage: TabStorageService) { + constructor(private api: ProfessorService) { } - existParams(data: TabSelectData): boolean { - return data.selected['professor'] !== undefined; + getEnclosureList(): string[] { + return ['professor']; } protected loadProfessors() { @@ -95,7 +96,7 @@ export class ProfessorComponent implements OnInit, IScheduleTab { this.professorControl.setValue(selectedOption.name); this.eventResult.emit(selectedOption.id); - this.tabStorage.select(new TabSelect(selectedOption.id, selectedOption.name), TabSelectType.professor, 'professor'); + this.selectChangeEvent.emit([new TabSelect(selectedOption.id, selectedOption.name)]); } } diff --git a/src/components/schedule/tabs/tabs.component.html b/src/components/schedule/tabs/tabs.component.html index 072c955..ce06774 100644 --- a/src/components/schedule/tabs/tabs.component.html +++ b/src/components/schedule/tabs/tabs.component.html @@ -3,17 +3,17 @@ (selectedTabChange)="chooseTabs($event.index)">
- +
- +
- +
diff --git a/src/components/schedule/tabs/tabs.component.ts b/src/components/schedule/tabs/tabs.component.ts index 0ba069a..5ec9a7b 100644 --- a/src/components/schedule/tabs/tabs.component.ts +++ b/src/components/schedule/tabs/tabs.component.ts @@ -17,7 +17,7 @@ import {GroupService} from "@api/v1/group.service"; import {ProfessorService} from "@api/v1/professor.service"; import {AuthRoles} from "@model/AuthRoles"; import {HasRoleDirective} from "@/directives/has-role.directive"; -import {TabStorageService} from "@service/tab-storage.service"; +import {TabSelectType, TabStorageService} from "@service/tab-storage.service"; export enum TabsSelect { Group, @@ -49,77 +49,91 @@ export enum TabsSelect { export class TabsComponent implements AfterViewInit { @Output() eventResult = new EventEmitter<[TabsSelect, number, Observable]>(); + private currentTab: number = -1; constructor(private scheduleApi: ScheduleService, private disciplineApi: DisciplineService, private lectureApi: LectureHallService, private groupApi: GroupService, - private professorApi: ProfessorService) { + private professorApi: ProfessorService, + private tabStorage: TabStorageService) { } ngAfterViewInit(): void { + this.groupTab.selectChangeEvent.subscribe(event => this.tabStorage.select(TabSelectType.group, event)); + this.professorTab.selectChangeEvent.subscribe(event => this.tabStorage.select(TabSelectType.professor, event)); + this.lectureHallTab.selectChangeEvent.subscribe(event => this.tabStorage.select(TabSelectType.lecture, event)); + + this.groupTab.eventResult.subscribe(event => this.eventResult.emit( + [ + TabsSelect.Group, + event, + this.scheduleApi.getByGroup(event) + ] + )); + + this.professorTab.eventResult.subscribe(event => this.eventResult.emit( + [ + TabsSelect.Professor, + event, + this.scheduleApi.getByProfessor(event) + ] + )); + + this.lectureHallTab.eventResult.subscribe(event => this.eventResult.emit( + [ + TabsSelect.LectureHall, + event, + this.scheduleApi.getByLectureHall(event) + ] + )); + let selected = TabStorageService.selected; let index = 0; if (selected !== null) { + const selectedKeys = Object.keys(selected?.selected); if (selected.type === null) { - if (this.groupTab.existParams(selected)) + if (this.groupTab.getEnclosureList().every((value, index) => value === selectedKeys[index])) index = 0; - else if (this.professorTab.existParams(selected)) + else if (this.professorTab.getEnclosureList().every((value, index) => value === selectedKeys[index])) index = 1; - else if (this.lectureHallTab.existParams(selected)) + else if (this.lectureHallTab.getEnclosureList().every((value, index) => value === selectedKeys[index])) index = 2; } else index = selected.type; } - if (index === null || index === 0) + if (index === 0) this.chooseTabs(0).then(); else this.tabs.selectedIndex = index; } - protected groupSelected(id: number) { - this.eventResult.emit( - [ - TabsSelect.Group, - id, - this.scheduleApi.getByGroup(id) - ] - ); - } - - protected professorSelected(id: number) { - this.eventResult.emit( - [ - TabsSelect.Professor, - id, - this.scheduleApi.getByProfessor(id) - ] - ); - } - - protected lectureHallSelected(id: number) { - this.eventResult.emit( - [ - TabsSelect.LectureHall, - id, - this.scheduleApi.getByLectureHall(id) - ] - ); - } - protected async chooseTabs(index: number) { + let needGetEnclosure = false; + + if (this.currentTab !== index) { + this.currentTab = index; + needGetEnclosure = true; + } + switch (index) { case 0: this.groupTab.load(); + if (needGetEnclosure) + this.tabStorage.enclosure = this.groupTab.getEnclosureList(); break; case 1: this.professorTab.load(); + if (needGetEnclosure) + this.tabStorage.enclosure = this.professorTab.getEnclosureList(); break; case 2: this.lectureHallTab.load(); + if (needGetEnclosure) + this.tabStorage.enclosure = this.lectureHallTab.getEnclosureList(); break; case 3: await this.loadDisciplines(); diff --git a/src/services/tab-storage.service.ts b/src/services/tab-storage.service.ts index db6fd1c..23fe383 100644 --- a/src/services/tab-storage.service.ts +++ b/src/services/tab-storage.service.ts @@ -30,6 +30,7 @@ export interface TabSelectData { }) export class TabStorageService { private static dataName = 'tabSelectedData'; + private _enclosure: string[] = []; constructor(private router: Router, private location: Location) { } @@ -52,27 +53,18 @@ export class TabStorageService { }, 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 set enclosure(data: string[]) { + this._enclosure = data; } - public select(selected: TabSelect, type: TabSelectType, navigateName: string) { - this.resetIfNeed(type); - let selectedData = TabStorageService.selected; + public select(type: TabSelectType, tabSelected: TabSelect[]) { + let selectedData = {selected: {}} as TabSelectData; - if (selectedData === null || !selectedData.selected) - selectedData = {selected: {}} as TabSelectData; + for (let index = 0; index < this._enclosure.length; index++) { + if (tabSelected[index]) + selectedData.selected[this._enclosure[index]] = tabSelected[index]; + } - selectedData.selected[navigateName] = selected; selectedData.type = type; localStorage.setItem(TabStorageService.dataName, JSON.stringify(selectedData));