Newer
Older
import { Component, OnInit } from '@angular/core';
import { DarsApiService } from '../services/api.service';
import { DegreePrograms, DegreeProgram } from '../models/degree-program';
import { Observable, combineLatest, Subject } from 'rxjs';
import {
FormBuilder,
FormGroup,
Validators,
FormArray,
FormControl,
} from '@angular/forms';
import { HonorsOption } from '../models/honors-option';
import {
map,
share,
flatMap,
shareReplay,
distinctUntilChanged,
} from 'rxjs/operators';
import { CourseBase } from '@app/core/models/course';
import { Store } from '@ngrx/store';
import { GlobalState } from '@app/core/state';
import { degreePlans } from '../store/selectors';
import { DegreePlan } from '@app/core/models/degree-plan';
import { MatDialogRef } from '@angular/material';
const inclusiveRange = (from: number, to: number) => {
const range: number[] = [];
for (let i = from; i <= to; i++) {
range.push(i);
}
return range;
};
export interface NewWhatIfAuditFields {
darsInstitutionCode: string;
darsDegreeProgramCode: string;
degreePlannerPlanName: string;
darsHonorsOptionCode: string;
whichEnrolledCoursesIncluded: string;
fixedCredits: {
termCode: string;
subjectCode: string;
courseId: string;
credits: number;
}[];
}
@Component({
selector: 'cse-new-what-if-audit-dialog',
templateUrl: './new-what-if-audit-dialog.component.html',
styleUrls: ['./new-what-if-audit-dialog.component.scss'],
})
export class NewWhatIfAuditDialogComponent implements OnInit {
// Form-builder objects
public chosenProgram: FormGroup;
public chosenAuditSettings: FormGroup;
public chosenCreditSettings: FormArray;
// API observables
public institutions$: Observable<DegreePrograms>;
public programOrPlanOptions$: Observable<DegreeProgram[]>;
public degreePlans$: Observable<DegreePlan[]>;
public chosenRoadmapId$ = new Subject<number>();
public honorsOptions$: Observable<HonorsOption[]>;
public variableCreditCourses$: Observable<
(CourseBase & { range: number[] })[]
>;
constructor(
private fb: FormBuilder,
private api: DarsApiService,
private store: Store<GlobalState>,
private dialogRef: MatDialogRef<
NewWhatIfAuditDialogComponent,
NewWhatIfAuditFields
>,
) {
this.chosenProgram = fb.group({
institution: fb.control('', Validators.required),
planOrProgram: fb.control(
{ value: '', disabled: true },
Validators.required,
),
});
this.chosenAuditSettings = fb.group({
honorsOptions: fb.control(' ', Validators.required),
includeCoursesFrom: fb.control('planned', Validators.required),
degreePlan: fb.control('', Validators.required),
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
});
this.chosenCreditSettings = fb.array([]);
}
public ngOnInit() {
this.institutions$ = this.api.getStaticData().pipe(share());
this.programOrPlanOptions$ = combineLatest([
this.institutions$,
(this.chosenProgram.get('institution') as FormControl).valueChanges,
]).pipe(
map(([institutions, darsInstitutionCode]) => {
this.chosenProgram.controls.planOrProgram.enable();
if (institutions.hasOwnProperty(darsInstitutionCode)) {
return institutions[darsInstitutionCode].programs;
} else {
return [];
}
}),
);
this.honorsOptions$ = combineLatest([
this.institutions$,
(this.chosenProgram.get('institution') as FormControl).valueChanges,
]).pipe(
map(([institutions, darsInstitutionCode]) => {
return institutions.hasOwnProperty(darsInstitutionCode)
? institutions[darsInstitutionCode].honorsOptions
: [];
}),
);
const degreePlanFormControl = this.chosenAuditSettings.get('degreePlan');
const includeCoursesFrom = this.chosenAuditSettings.get(
'includeCoursesFrom',
);
if (includeCoursesFrom && degreePlanFormControl) {
includeCoursesFrom.valueChanges.subscribe(selected => {
if (selected !== 'planned') {
degreePlanFormControl.reset();
degreePlanFormControl.disable();
} else {
degreePlanFormControl.enable();
degreePlanFormControl.valueChanges.subscribe(plan => {
this.chosenRoadmapId$.next(plan.roadmapId);
});
}
if (degreePlanFormControl) {
this.variableCreditCourses$ = this.chosenRoadmapId$.pipe(
distinctUntilChanged(),
flatMap(roadmapId => this.api.getAllCourses(roadmapId)),
map(courses => {
return courses.filter(course => {
return (
!!course.creditMin &&
!!course.creditMax &&
course.creditMax > course.creditMin
);
});
}),
map(courses =>
courses.map(course => ({
...course,
range: inclusiveRange(
course.creditMin as number,
course.creditMax as number,
),
})),
),
shareReplay(),
);
}
this.variableCreditCourses$.subscribe(courses => {
while (this.chosenCreditSettings.length !== 0) {
this.chosenCreditSettings.removeAt(0);
}
courses.forEach(course => {
this.chosenCreditSettings.push(
this.fb.group({
course,
credits: this.fb.control(course.credits || '', Validators.required),
}),
);
});
});
this.degreePlans$ = this.store.select(degreePlans).pipe(shareReplay());
this.degreePlans$.subscribe(plans => {
const primaryPlan = plans.find(p => p.primary);
this.chosenAuditSettings.controls['degreePlan'].setValue(primaryPlan);
if (primaryPlan) {
this.chosenRoadmapId$.next(primaryPlan.roadmapId);
}
});
}
public comparePlans(a: DegreePlan, b: DegreePlan): boolean {
return a.roadmapId === b.roadmapId;
}
public darsInstitutionCode<T>(fallback: T): string | T {
const control = this.chosenProgram.get('institution');
if (control !== null) {
return control.value.toString();
} else {
return fallback;
}
}
public darsDegreeProgramCode<T>(fallback: T): string | T {
const control = this.chosenProgram.get('planOrProgram');
if (control !== null) {
return control.value.toString();
} else {
return fallback;
}
}
public degreePlannerPlanName<T>(fallback: T): string | T {
const control = this.chosenAuditSettings.get('degreePlan');
if (control && control.value !== null) {
return control.value.name;
} else {
return fallback;
}
}
public darsHonorsOptionCode<T>(fallback: T): string | T {
const control = this.chosenAuditSettings.get('honorsOptions');
if (control !== null) {
return control.value.toString();
} else {
return fallback;
}
}
// If a degree plan name is included in the request we do not need this property
public includeCoursesFrom<T>(fallback: T): string | T {
const controlDegreePlan = this.chosenAuditSettings.get('degreePlan');
if (controlDegreePlan && controlDegreePlan.status === 'DISABLED') {
const control = this.chosenAuditSettings.get('includeCoursesFrom');
if (control !== null) {
return control.value.toString();
} else {
return fallback;
}
} else {
return fallback;
}
}
public fixedCredits(): NewWhatIfAuditFields['fixedCredits'] {
return (this.chosenCreditSettings.value as any[]).map(
(group: { course: CourseBase; credits: number }) => {
return {
termCode: group.course.termCode || '',
subjectCode: group.course.subjectCode || '',
courseId: group.course.courseId || '',
credits: group.credits,
};
},
);
}
public submitAudit() {
this.dialogRef.close({
darsInstitutionCode: this.darsInstitutionCode(''),
darsDegreeProgramCode: this.darsDegreeProgramCode(''),
degreePlannerPlanName: this.degreePlannerPlanName(''),
darsHonorsOptionCode: this.darsHonorsOptionCode(''),
whichEnrolledCoursesIncluded: this.includeCoursesFrom(''),
fixedCredits: this.fixedCredits(),
});
}
}