Newer
Older
import { CdkDragDrop } from '@angular/cdk/drag-drop';

Scott Berg
committed
import { Observable } from 'rxjs';
import { filter, map, distinctUntilChanged } from 'rxjs/operators';

Scott Berg
committed
import { Store, select } from '@ngrx/store';
import { DegreePlannerState } from '@app/degree-planner/store/state';
import {
ToggleCourseSearch,
OpenCourseSearch,
} from '@app/degree-planner/store/actions/ui.actions';
import * as actions from '@app/degree-planner/store/actions/course.actions';
import * as selectors from '@app/degree-planner/store/selectors';
import { PlannedTerm, PlannedTermNote } from '@app/core/models/planned-term';
import { Note } from '@app/core/models/note';
import { Course } from '@app/core/models/course';
} from '@app/degree-planner/dialogs/notes-dialog/notes-dialog.component';
import * as utils from '@app/degree-planner/shared/utils';
const isntUndefined = <T>(thing: T | undefined): thing is T => {
return thing !== undefined;
};
const sumCredits = (courses: Course[]): number => {
return courses.reduce((sum, course) => {
return sum + course.credits;
}, 0);
};
pnogal
committed
const sumCreditsInCart = (courses: Course[]): number => {
return courses
.filter(course => course.id)
.reduce((sum, course) => {
return sum + parseInt(course.creditRange);
}, 0);
};
pnogal
committed
@Component({
selector: 'cse-term-container',
templateUrl: './term-container.component.html',
styleUrls: ['./term-container.component.scss'],
pnogal
committed
})

Scott Berg
committed
export class TermContainerComponent implements OnInit {
@Input() yearCode: string;
@Input() termName: 'fall' | 'spring' | 'summer';
public termCode: string;
public term$: Observable<PlannedTerm>;
public courses$: Observable<Course[]>;
public credits$: Observable<number>;
public isPastTerm$: Observable<boolean>;
public dropZoneIds$: Observable<string[]>;
public isCurrentTerm$: Observable<boolean>;
constructor(
public dialog: MatDialog,
private store: Store<{ degreePlanner: DegreePlannerState }>,
) {}
public ngOnInit() {
const termOffset = { fall: 2, spring: 4, summer: 6 };
this.termCode = `${this.yearCode}${termOffset[this.termName]}`;
this.term$ = this.store.pipe(
select(selectors.selectVisibleTerm, { termCode: this.termCode }),
filter(isntUndefined),
distinctUntilChanged(),
this.note$ = this.term$.pipe(
map(term => term.note),
distinctUntilChanged(),
);
this.courses$ = this.term$.pipe(
map(term => term.courses),
distinctUntilChanged(),
);
this.credits$ = this.courses$.pipe(
map(sumCredits),
distinctUntilChanged(),
);
this.cartCredits$ = this.courses$.pipe(
map(sumCreditsInCart),
distinctUntilChanged(),
);
this.isPastTerm$ = this.term$.pipe(
map(term => term.era === 'past'),
distinctUntilChanged(),
);
this.dropZoneIds$ = this.store.pipe(
select(selectors.selectAllVisibleYears),
utils.yearsToDropZoneIds(),
distinctUntilChanged(utils.compareStringArrays),
);
this.isPastTerm$ = this.store.pipe(
select(selectors.isPastTerm(this.termCode)),
);
this.isCurrentTerm$ = this.store.pipe(
select(selectors.isCurrentTerm(this.termCode)),
);
openNotesDialog(note?: PlannedTermNote) {
if (note === undefined || note.isLoaded) {
const termCode = this.termCode;
const data: NotesDialogData = note
? {
termCode,
hasExistingNote: true,
initialText: note.text,
noteId: note.id,
}
: { termCode, hasExistingNote: false };
this.dialog.open(NotesDialogComponent, { data });
}
openCourseSearch() {
this.store.dispatch(new OpenCourseSearch(this.termCode));
drop(event: CdkDragDrop<string>) {
const newContainer = event.container.id;
const previousContainer = event.previousContainer.id;
if (newContainer === previousContainer) {
const newIndex = event.currentIndex;
const { id: recordId, termCode } = event.item.data as Course;
if (recordId !== null) {
const action = new actions.MoveCourseInsideTerm({
termCode,
recordId,
newIndex,
});
this.store.dispatch(action);
}
} else if (previousContainer.indexOf('term-') === 0) {
// If moving from term to term
// Get the pervious and new term code, and the record ID
const from = event.previousContainer.data;
const to = event.container.data;
const { id } = event.item.data;
const newIndex = event.currentIndex;
this.store.dispatch(
new actions.MoveCourseBetweenTerms({ to, from, id, newIndex }),
);
} else if (previousContainer === 'saved-courses') {
// If moving from saved courses to term
// Get the term code from the new term dropzone's ID
const termCode = newContainer.substr(5);
const newIndex = event.currentIndex;
const { subjectCode, courseId, title, catalogNumber } = event.item.data;
this.store.dispatch(
new actions.AddCourse({
courseId,
termCode,
}),
);
this.store.dispatch(
new actions.RemoveSaveForLater({ subjectCode, courseId }),
);
} else if (
previousContainer === 'queried-courses-list' &&
newContainer.indexOf('term-') === 0
) {
const termCode = newContainer.substr(5);
const newIndex = event.currentIndex;
new actions.AddCourse({
courseId: event.item.data.courseId,
termCode,
subjectCode: event.item.data.subjectCode,
title: event.item.data.title,
catalogNumber: event.item.data.catalogNumber,
newIndex,
}),