From dea461d92dd6f098facfc6a70a75d613490eba80 Mon Sep 17 00:00:00 2001 From: Scott Berg <saberg3@wisc.edu> Date: Wed, 20 Feb 2019 16:21:54 -0600 Subject: [PATCH] ROENROLL-1395 --- .../degree-planner.component.html | 5 +- .../course-item/course-item.component.html | 1 - .../course-item/course-item.component.ts | 7 +- .../store/actions/course.actions.ts | 4 +- .../store/effects/plan.effects.ts | 1 + src/app/degree-planner/store/reducer.ts | 8 +- .../course-details.component.html | 18 +++-- .../course-details.component.ts | 77 +++++++++++++++++-- 8 files changed, 97 insertions(+), 24 deletions(-) diff --git a/src/app/degree-planner/degree-planner.component.html b/src/app/degree-planner/degree-planner.component.html index 7205e64..a30c99e 100644 --- a/src/app/degree-planner/degree-planner.component.html +++ b/src/app/degree-planner/degree-planner.component.html @@ -128,7 +128,6 @@ </ng-container> </mat-accordion> </div> - </mat-sidenav-content> - </mat-sidenav-container> - </mat-sidenav-content> + + </mat-sidenav-content> </mat-sidenav-container> diff --git a/src/app/degree-planner/shared/course-item/course-item.component.html b/src/app/degree-planner/shared/course-item/course-item.component.html index ba27d1b..5d97eb9 100644 --- a/src/app/degree-planner/shared/course-item/course-item.component.html +++ b/src/app/degree-planner/shared/course-item/course-item.component.html @@ -27,7 +27,6 @@ <button mat-menu-item (click)="openCourseDetailsDialog(course)">Course Details</button> <button mat-menu-item [matMenuTriggerFor]="academicYearsGroup">Move</button> <mat-menu #academicYearsGroup="matMenu" class="course-item-submenu"> - <button mat-menu-item (click)="moveToSavedForLater(course)" *ngIf="type != 'saved'" class="saved-for-later-list">Saved for later</button> <button mat-menu-item *ngFor="let term of (droppableTermCodes$ | async)" (click)="onMove(term)">{{ term | getTermDescription }}</button> </mat-menu> <button mat-menu-item *ngIf="type !== 'saved'" (click)="onSaveForLater()">Save for later</button> diff --git a/src/app/degree-planner/shared/course-item/course-item.component.ts b/src/app/degree-planner/shared/course-item/course-item.component.ts index 07e090f..4ae7859 100644 --- a/src/app/degree-planner/shared/course-item/course-item.component.ts +++ b/src/app/degree-planner/shared/course-item/course-item.component.ts @@ -205,9 +205,7 @@ export class CourseItemComponent implements OnInit { const termCode = term; const newIndex = 0; - this.store.dispatch( - new AddCourse({ subjectCode, courseId, termCode, newIndex }), - ); + this.store.dispatch(new AddCourse({ subjectCode, courseId, termCode })); } switchTerm(course, term) { @@ -223,7 +221,8 @@ export class CourseItemComponent implements OnInit { .subscribe(courseDetails => { const dialogRef = this.dialog.open(CourseDetailsDialogComponent, { maxWidth: '800px', - data: { courseDetails: courseDetails }, + width: '80%', + data: { courseDetails: courseDetails, courseType: this.type }, }); }); } diff --git a/src/app/degree-planner/store/actions/course.actions.ts b/src/app/degree-planner/store/actions/course.actions.ts index 749984a..5f6f44d 100644 --- a/src/app/degree-planner/store/actions/course.actions.ts +++ b/src/app/degree-planner/store/actions/course.actions.ts @@ -52,14 +52,14 @@ export class AddCourse implements Action { subjectCode: string; courseId: string; termCode: string; - newIndex: number; + newIndex?: number; }, ) {} } export class AddCourseSuccess implements Action { public readonly type = CourseActionTypes.AddCourseSuccess; - constructor(public payload: { course: Course; newIndex: number }) {} + constructor(public payload: { course: Course; newIndex?: number }) {} } export class RemoveCourse implements Action { diff --git a/src/app/degree-planner/store/effects/plan.effects.ts b/src/app/degree-planner/store/effects/plan.effects.ts index b6a601d..012d51b 100644 --- a/src/app/degree-planner/store/effects/plan.effects.ts +++ b/src/app/degree-planner/store/effects/plan.effects.ts @@ -104,6 +104,7 @@ export class DegreePlanEffects { subjects: of(subjects), expandedYears: of([] as string[]), subjectDescriptions: of(descriptions), + search: of({ visible: false, selectedTerm: activeTermCodes[0] }), }); }, ), diff --git a/src/app/degree-planner/store/reducer.ts b/src/app/degree-planner/store/reducer.ts index 162fe78..2f8e88b 100644 --- a/src/app/degree-planner/store/reducer.ts +++ b/src/app/degree-planner/store/reducer.ts @@ -319,11 +319,11 @@ export function degreePlannerReducer( const toYear = createYearWithCourse( toTermCode, course, - newIndex, state.activeTermCodes, fromYearCode === toYearCode ? fromYear : state.visibleYears[toYearCode], + newIndex, ); const visibleYears = { @@ -346,9 +346,9 @@ export function degreePlannerReducer( const year: Year = createYearWithCourse( termCode, course, - newIndex, state.activeTermCodes, state.visibleYears[yearCode], + newIndex, ); const visibleYears = { @@ -570,14 +570,14 @@ const findCourse = (years: YearMapping, termCode: string, recordId: number) => { const createYearWithCourse = ( termCode: string, course: Course, - newIndex: number, activeTermCodes: string[], year = generateYearForTermCode(termCode, activeTermCodes), + newIndex?: number, ): Year => { const { termName } = parseTermCode(termCode); const term = year[termName]; const courses = term.courses.slice(); - courses.splice(newIndex, 0, course); + courses.splice(newIndex !== undefined ? newIndex : courses.length, 0, course); return { ...year, [termName]: { ...term, courses } }; }; diff --git a/src/app/shared/components/course-details/course-details.component.html b/src/app/shared/components/course-details/course-details.component.html index cf07238..0362a9d 100644 --- a/src/app/shared/components/course-details/course-details.component.html +++ b/src/app/shared/components/course-details/course-details.component.html @@ -4,11 +4,19 @@ <div fxFlex="50" class="course-detail-title" fxLayoutAlign="start center"> <h3>{{ courseDetails.fullCourseDesignation | titlecase }}<span class="course-detail-subtitle">{{ courseDetails.title }}</span></h3> </div> - <!-- <div fxFlex="50" fxLayout="row" fxLayoutAlign="end start" > - <mat-dialog-actions> - <button mat-raised-button class="btn-primary mat-button">See Sections</button> - </mat-dialog-actions> - </div> --> + <div *ngIf="type === 'search' || type === 'saved'" fxFlex="50" fxLayout="row" fxLayoutAlign="end start" > + <div style="margin-top: 10px;"> + <form [formGroup]='termSelector' (ngSubmit)="addCourseToPlan($event)"> + <mat-form-field style="margin-right:20px;"> + <mat-select placeholder="Term" aria-label="Term" matInput formControlName="term"> + <mat-option *ngFor="let term of (droppableTermCodes$ | async)" [value]="term">{{term | getTermDescription}}</mat-option> + </mat-select> + </mat-form-field> + + <button mat-raised-button color="primary" mat-dialog-close (click)="addCourseToPlan($event)">Add to plan</button> + </form> + </div> + </div> </div> </div> diff --git a/src/app/shared/components/course-details/course-details.component.ts b/src/app/shared/components/course-details/course-details.component.ts index bec3f7b..47fa4a8 100644 --- a/src/app/shared/components/course-details/course-details.component.ts +++ b/src/app/shared/components/course-details/course-details.component.ts @@ -1,18 +1,85 @@ -import { Component, OnInit, Inject } from '@angular/core'; +import { Observable, Subscription } from 'rxjs'; +import { Component, OnInit, OnDestroy, Inject } from '@angular/core'; import { CourseDetails } from '../../../core/models/course-details'; import { MAT_DIALOG_DATA } from '@angular/material'; +import * as selectors from '@app/degree-planner/store/selectors'; +import * as utils from '@app/degree-planner/shared/utils'; +import { GlobalState } from '@app/core/state'; +import { Store, select } from '@ngrx/store'; +import { distinctUntilChanged } from 'rxjs/operators'; +import { FormBuilder, FormGroup } from '@angular/forms'; + +import { + AddCourse, + RemoveSaveForLater, +} from '@app/degree-planner/store/actions/course.actions'; @Component({ selector: 'cse-course-details', templateUrl: './course-details.component.html', styleUrls: ['./course-details.component.scss'], }) -export class CourseDetailsComponent implements OnInit { - courseDetails: CourseDetails; +export class CourseDetailsComponent implements OnInit, OnDestroy { + public courseDetails: CourseDetails; + public type: 'course' | 'search' | 'saved'; + public selectedSearchTerm: string; + + public termSelector: FormGroup; - constructor(@Inject(MAT_DIALOG_DATA) public data: any) { + public selectedSearchTerm$: Observable<string>; + public droppableTermCodes$: Observable<string[]>; + public searchTermSubscription: Subscription; + + constructor( + @Inject(MAT_DIALOG_DATA) public data: any, + private store: Store<GlobalState>, + private fb: FormBuilder, + ) { this.courseDetails = data.courseDetails; + this.type = data.courseType; } - ngOnInit() {} + ngOnInit() { + this.selectedSearchTerm$ = this.store.pipe( + select(selectors.getSelectedSearchTerm), + ); + + this.droppableTermCodes$ = this.store.pipe( + select(selectors.selectAllVisibleYears), + utils.yearsToDroppableTermCodes(), + distinctUntilChanged(utils.compareStringArrays), + ); + + this.searchTermSubscription = this.selectedSearchTerm$.subscribe( + termCode => { + this.selectedSearchTerm = termCode; + }, + ); + + this.termSelector = this.fb.group({ + term: this.selectedSearchTerm, + }); + } + + ngOnDestroy() { + this.searchTermSubscription.unsubscribe(); + } + + addCourseToPlan($event) { + $event.preventDefault(); + const termCode = this.termSelector.value.term; + const subjectCode = this.courseDetails.subject.subjectCode; + const courseId = this.courseDetails.courseId; + + switch (this.type) { + case 'search': + this.store.dispatch(new AddCourse({ subjectCode, courseId, termCode })); + break; + + case 'saved': + this.store.dispatch(new AddCourse({ subjectCode, courseId, termCode })); + this.store.dispatch(new RemoveSaveForLater({ subjectCode, courseId })); + break; + } + } } -- GitLab