From 5cf6f5ed15f97342ba7cf5962adb9af743a57180 Mon Sep 17 00:00:00 2001 From: ievavold <ievavold@wisc.edu> Date: Mon, 11 Feb 2019 13:25:26 -0600 Subject: [PATCH] fix missing saved-for-later titles --- src/app/core/models/saved-for-later-course.ts | 6 +- .../remove-course-confirm-dialog.component.ts | 2 +- .../favorites-container.component.ts | 31 ++++++--- .../degree-planner/services/api.service.ts | 14 ++-- .../store/actions/plan.actions.ts | 22 ++++-- .../store/effects/plan.effects.ts | 68 +++++++++---------- src/app/degree-planner/store/reducer.ts | 21 +++--- 7 files changed, 90 insertions(+), 74 deletions(-) diff --git a/src/app/core/models/saved-for-later-course.ts b/src/app/core/models/saved-for-later-course.ts index aaee440..89c9bb9 100644 --- a/src/app/core/models/saved-for-later-course.ts +++ b/src/app/core/models/saved-for-later-course.ts @@ -1,12 +1,12 @@ export interface SavedForLaterCourseBase { id: number | null; courseId: string; - termCode: string; - topicId: number; + termCode: '0000'; + topicId: 0; subjectCode: string; title: string; catalogNumber: string; - courseOrder: number; + courseOrder: 0; } export interface SavedForLaterCourse extends SavedForLaterCourseBase { diff --git a/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.ts b/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.ts index e95af18..2c7f120 100644 --- a/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.ts +++ b/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.ts @@ -43,7 +43,7 @@ export class RemoveCourseConfirmDialogComponent implements OnInit { console.log(this.course); const id = this.course.id; if (typeof id === 'number') { - this.store.dispatch(new RemoveCourseRequest({ id })); + this.store.dispatch(new RemoveCourseRequest({ recordId: id })); } else { throw new Error('cannot remove a course that does not have an ID'); } diff --git a/src/app/degree-planner/favorites-container/favorites-container.component.ts b/src/app/degree-planner/favorites-container/favorites-container.component.ts index a0a4e5b..766eac9 100644 --- a/src/app/degree-planner/favorites-container/favorites-container.component.ts +++ b/src/app/degree-planner/favorites-container/favorites-container.component.ts @@ -4,6 +4,7 @@ import { Store, select } from '@ngrx/store'; import { SavedForLaterCourse } from '@app/core/models/saved-for-later-course'; import { GlobalState } from '@app/core/state'; import { getSavedForLaterCourses } from '@app/degree-planner/store/selectors'; +import { Course } from '@app/core/models/course'; // rsjx / ngrx import { DegreePlannerState } from '@app/degree-planner/store/state'; @@ -31,21 +32,29 @@ export class SavedForLaterContainerComponent implements OnInit { this.courses$ = this.store.pipe(select(getSavedForLaterCourses)); } - drop(event) { - const newContainer = event.container.id; - const previousContainer = event.previousContainer.id; + drop(event: any) { + const newContainerId = event.container.id; + const previousContainerId = event.previousContainer.id; + const fromTerm = previousContainerId.indexOf('term-') === 0; + const fromDifferentContainer = newContainerId !== previousContainerId; - if (newContainer === previousContainer) { - // If the user dropped a course into the same container do nothing - return; - } else if (previousContainer.indexOf('term-') === 0) { - // If moving from term to to saved for later + if (fromDifferentContainer && fromTerm) { + const course = event.item.data as Course; - const { subjectCode, courseId, id } = event.item.data; this.store.dispatch( - new AddSavedForLaterRequest({ subjectCode, courseId }), + new AddSavedForLaterRequest({ + courseId: course.courseId, + subjectCode: course.subjectCode, + title: course.title, + catalogNumber: course.catalogNumber, + }), + ); + + this.store.dispatch( + new RemoveCourseRequest({ + recordId: course.id as number, + }), ); - this.store.dispatch(new RemoveCourseRequest({ id })); } } } diff --git a/src/app/degree-planner/services/api.service.ts b/src/app/degree-planner/services/api.service.ts index dd7b77b..e2536ca 100644 --- a/src/app/degree-planner/services/api.service.ts +++ b/src/app/degree-planner/services/api.service.ts @@ -12,7 +12,7 @@ import { ConfigService } from '@app/core/config.service'; // Models import { Note } from '@app/core/models/note'; import { Term } from '@app/core/models/term'; -import { Course, CourseBase, SubjectMapping } from '@app/core/models/course'; +import { CourseBase, SubjectMapping } from '@app/core/models/course'; import { DegreePlan } from '@app/core/models/degree-plan'; import { SavedForLaterCourseBase } from '@app/core/models/saved-for-later-course'; @@ -73,7 +73,7 @@ export class DegreePlannerApiService { } public updateCourseTerm(roadmapId, recordId, termCode): Observable<any> { - return this.http.put<Course>( + return this.http.put<CourseBase>( this.config.apiPlannerUrl + '/degreePlan/' + roadmapId + @@ -89,7 +89,7 @@ export class DegreePlannerApiService { const data = { subjectCode: '104', termCode: '0000', - matchText: search + matchText: search, }; return this.http.post('/api/search/v1/autocomplete', data, HTTP_OPTIONS); @@ -100,16 +100,16 @@ export class DegreePlannerApiService { subjectCode: string, courseId: string, termCode: string, - ): Observable<Course> { - return this.http.post<Course>( + ): Observable<CourseBase> { + return this.http.post<CourseBase>( this.config.apiPlannerUrl + '/degreePlan/' + planId + '/courses', { subjectCode, courseId, termCode }, HTTP_OPTIONS, ); } - public removeCourse(planId: number, recordId: string) { - return this.http.delete( + public removeCourse(planId: number, recordId: number): Observable<void> { + return this.http.delete<void>( this.config.apiPlannerUrl + '/degreePlan/' + planId + diff --git a/src/app/degree-planner/store/actions/plan.actions.ts b/src/app/degree-planner/store/actions/plan.actions.ts index 1ce3e17..ff7afaf 100644 --- a/src/app/degree-planner/store/actions/plan.actions.ts +++ b/src/app/degree-planner/store/actions/plan.actions.ts @@ -73,22 +73,36 @@ export class AddCourseResponse implements Action { export class RemoveCourseRequest implements Action { public readonly type = PlanActionTypes.RemoveCourseRequest; - constructor(public payload: { id: number }) {} + constructor(public payload: { recordId: number }) {} } export class RemoveCourseResponse implements Action { public readonly type = PlanActionTypes.RemoveCourseResponse; - constructor(public payload: { id: number }) {} + constructor(public payload: { recordId: number }) {} } export class AddSavedForLaterRequest implements Action { public readonly type = PlanActionTypes.AddSavedForLaterReqeust; - constructor(public payload: { subjectCode: string; courseId: string }) {} + constructor( + public payload: { + subjectCode: string; + courseId: string; + title: string; + catalogNumber: string; + }, + ) {} } export class AddSavedForLaterResponse implements Action { public readonly type = PlanActionTypes.AddSavedForLaterResponse; - constructor(public payload: { subjectCode: string; courseId: string }) {} + constructor( + public payload: { + subjectCode: string; + courseId: string; + title: string; + catalogNumber: string; + }, + ) {} } export class RemoveSavedForLaterRequest 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 cefbda2..100de1c 100644 --- a/src/app/degree-planner/store/effects/plan.effects.ts +++ b/src/app/degree-planner/store/effects/plan.effects.ts @@ -21,12 +21,14 @@ import { RemoveCourseResponse, RemoveSavedForLaterResponse, AddSavedForLaterResponse, + AddCourseRequest, + RemoveCourseRequest, } from '@app/degree-planner/store/actions/plan.actions'; // Models import { DegreePlan } from '@app/core/models/degree-plan'; import { PlannedTerm } from '@app/core/models/planned-term'; -import { SubjectMapping } from '@app/core/models/course'; +import { Course, SubjectMapping, CourseBase } from '@app/core/models/course'; import { SavedForLaterCourse } from '@app/core/models/saved-for-later-course'; @Injectable() @@ -146,7 +148,7 @@ export class DegreePlanEffects { @Effect() AddCourse$ = this.actions$.pipe( - ofType<any>(PlanActionTypes.AddCourseRequest), + ofType<AddCourseRequest>(PlanActionTypes.AddCourseRequest), withLatestFrom(this.store$.select(getDegreePlannerState)), filter(([_, state]) => state.visibleDegreePlan !== undefined), @@ -156,53 +158,48 @@ export class DegreePlanEffects { // TODO error handle the API calls const roadmapId = (state.visibleDegreePlan as DegreePlan).roadmapId; const { subjectCode, termCode, courseId } = action.payload; - return this.api - .addCourse(roadmapId as number, subjectCode, courseId, termCode) - .pipe( - map(response => { - return { - response, - action, - }; - }), - ); - }), - // Wrap data in an Action for dispatch - map(({ response, action }) => { - // TODO add error handleing - return new AddCourseResponse({ course: response }); + const addCourse$ = this.api.addCourse( + roadmapId, + subjectCode, + courseId, + termCode, + ); + + const courseBaseToCourse$ = addCourse$.pipe( + map<CourseBase, Course>(courseBase => ({ + ...courseBase, + subject: state.subjects[courseBase.subjectCode], + })), + ); + + const toSuccessAction$ = courseBaseToCourse$.pipe( + map(course => new AddCourseResponse({ course })), + ); + + return toSuccessAction$; }), ); @Effect() RemoveCourse$ = this.actions$.pipe( - ofType<any>(PlanActionTypes.RemoveCourseRequest), + ofType<RemoveCourseRequest>(PlanActionTypes.RemoveCourseRequest), withLatestFrom(this.store$.select(getDegreePlannerState)), filter(([_, state]) => state.visibleDegreePlan !== undefined), // Get term data for the degree plan specified by the roadmap ID. flatMap(([action, state]) => { - // TODO error handle the API calls const roadmapId = (state.visibleDegreePlan as DegreePlan).roadmapId; - return this.api.removeCourse(roadmapId, action.payload.id).pipe( - map(response => { - return { - response, - action, - }; - }), + const recordId = action.payload.recordId; + + const removeCourse$ = this.api.removeCourse(roadmapId, recordId); + + const toSuccessAction$ = removeCourse$.pipe( + map(() => new RemoveCourseResponse({ recordId })), ); - }), - // Wrap data in an Action for dispatch - map(({ response, action }) => { - if (response === null) { - const { id } = action.payload; - return new RemoveCourseResponse({ id }); - } - return; + return toSuccessAction$; }), ); @@ -267,8 +264,7 @@ export class DegreePlanEffects { // // // Wrap data in an Action for dispatch map(({ response, action }) => { if (response === null) { - const { subjectCode, courseId } = action.payload; - return new AddSavedForLaterResponse({ subjectCode, courseId }); + return new AddSavedForLaterResponse(action.payload); } // return; return; diff --git a/src/app/degree-planner/store/reducer.ts b/src/app/degree-planner/store/reducer.ts index 8a263e4..a89bf68 100644 --- a/src/app/degree-planner/store/reducer.ts +++ b/src/app/degree-planner/store/reducer.ts @@ -17,6 +17,7 @@ import { WriteNoteResponse, DeleteNoteResponse, } from '@app/degree-planner/store/actions/note.actions'; +import { SavedForLaterCourse } from '@app/core/models/saved-for-later-course'; type SupportedActions = | InitialPlanLoadResponse @@ -169,7 +170,7 @@ export function degreePlannerReducer( } case PlanActionTypes.RemoveCourseResponse: { - const { id } = action.payload; + const { recordId: id } = action.payload; // Create new visibleTerms array const newVisibleTerms = state.visibleTerms.map(term => { @@ -195,22 +196,18 @@ export function degreePlannerReducer( } case PlanActionTypes.AddSavedForLaterResponse: { - const { courseId, subjectCode } = action.payload; - - // // Create new saved for later array - const newSavedForLater = [ + const newSavedForLater: SavedForLaterCourse[] = [ ...state.savedForLaterCourses, - // TODO Update this when the API is fixed, the API should be sending a fav course as a response { id: null, - courseId, - subjectCode, - subject: state.subjects[subjectCode], + courseId: action.payload.courseId, + termCode: '0000', topicId: 0, + subjectCode: action.payload.subjectCode, + title: action.payload.title, + catalogNumber: action.payload.catalogNumber, courseOrder: 0, - catalogNumber: '', - title: '', - termCode: '0000', + subject: state.subjects[action.payload.subjectCode], }, ]; return { ...state, savedForLaterCourses: newSavedForLater }; -- GitLab