From 726d0cae8470a5ae57193727fa42f33af8576755 Mon Sep 17 00:00:00 2001 From: Scott Berg <saberg3@wisc.edu> Date: Tue, 12 Feb 2019 16:03:11 -0600 Subject: [PATCH] ROENROLL-1358 --- .../modify-plan-dialog.component.ts | 10 ++++- .../store/actions/plan.actions.ts | 19 ++++++++ .../store/effects/plan.effects.ts | 43 ++++++++++++++++++- src/app/degree-planner/store/reducer.ts | 37 ++++++++++------ 4 files changed, 94 insertions(+), 15 deletions(-) diff --git a/src/app/degree-planner/dialogs/modify-plan-dialog/modify-plan-dialog.component.ts b/src/app/degree-planner/dialogs/modify-plan-dialog/modify-plan-dialog.component.ts index c863905..125dc01 100644 --- a/src/app/degree-planner/dialogs/modify-plan-dialog/modify-plan-dialog.component.ts +++ b/src/app/degree-planner/dialogs/modify-plan-dialog/modify-plan-dialog.component.ts @@ -1,5 +1,12 @@ import { FormGroup, FormControl } from '@angular/forms'; import { Component, OnInit } from '@angular/core'; +import { Store } from '@ngrx/store'; + +// Models +import { GlobalState } from '@app/core/state'; + +// Actions +import { ChangePlanName } from '@app/degree-planner/store/actions/plan.actions'; @Component({ selector: 'cse-course-details-dialog', @@ -8,7 +15,7 @@ import { Component, OnInit } from '@angular/core'; export class ModifyPlanDialogComponent implements OnInit { public form: FormGroup; - constructor() { + constructor(private store: Store<GlobalState>) { this.form = new FormGroup({ planName: new FormControl(), }); @@ -17,6 +24,7 @@ export class ModifyPlanDialogComponent implements OnInit { ngOnInit() {} renamePlanSave() { + this.store.dispatch(new ChangePlanName(this.form.value.planName)); console.log('PUT /degreePlan/<planId> { primary: <bool>, name: <string> }'); } makePlanPrimarySave() { diff --git a/src/app/degree-planner/store/actions/plan.actions.ts b/src/app/degree-planner/store/actions/plan.actions.ts index fea706a..53a4098 100644 --- a/src/app/degree-planner/store/actions/plan.actions.ts +++ b/src/app/degree-planner/store/actions/plan.actions.ts @@ -14,6 +14,10 @@ export enum PlanActionTypes { MakePlanPrimary = '[Plan] Make Plan Primary', MakePlanPrimarySuccess = '[Plan] Make Plan Primary Success', MakePlanPrimaryFailure = '[Plan] Make Plan Primary Failure', + + ChangePlanName = '[Plan] Change Plan Name', + ChangePlanNameSuccess = '[Plan] Change Plan Name Success', + ChangePlanNameFailure = '[Plan] Change Plan Name Failure', } export class InitialLoadSuccess implements Action { @@ -55,3 +59,18 @@ export class MakePlanPrimaryFailure implements Action { public readonly type = PlanActionTypes.MakePlanPrimaryFailure; constructor() {} } + +export class ChangePlanName implements Action { + public readonly type = PlanActionTypes.ChangePlanName; + constructor(public name: string) {} +} + +export class ChangePlanNameSuccess implements Action { + public readonly type = PlanActionTypes.ChangePlanNameSuccess; + constructor(public name: string) {} +} + +export class ChangePlanNameFailure implements Action { + public readonly type = PlanActionTypes.ChangePlanNameFailure; + constructor(public name: string) {} +} diff --git a/src/app/degree-planner/store/effects/plan.effects.ts b/src/app/degree-planner/store/effects/plan.effects.ts index 27b3b7c..5c6d97f 100644 --- a/src/app/degree-planner/store/effects/plan.effects.ts +++ b/src/app/degree-planner/store/effects/plan.effects.ts @@ -23,9 +23,10 @@ import { SwitchPlanSuccess, PlanActionTypes, PlanError, - MakePlanPrimary, MakePlanPrimarySuccess, MakePlanPrimaryFailure, + ChangePlanNameSuccess, + ChangePlanNameFailure, } from '@app/degree-planner/store/actions/plan.actions'; // Models @@ -149,6 +150,46 @@ export class DegreePlanEffects { }), ); + @Effect() + ChangePlanName$ = this.actions$.pipe( + ofType<any>(PlanActionTypes.ChangePlanName), + + 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]) => { + console.log(action); + const { name } = action; + + const { + roadmapId, + name: previousName, + primary, + } = state.visibleDegreePlan as DegreePlan; + + action.previousName = previousName; + // TODO error handle the API calls + return this.api.updatePlan(roadmapId, name, primary).pipe( + map(response => { + return { + response, + action, + }; + }), + ); + }), + + // // Wrap data in an Action for dispatch + map(({ response, action }) => { + if (response === 1) { + return new ChangePlanNameSuccess(action.name); + } else { + return new ChangePlanNameFailure(action.previousName); + } + }), + ); + private loadSavedForLaterCourses(subjects: SubjectMapping) { return this.api.getSavedForLaterCourses().pipe( map(courseBases => { diff --git a/src/app/degree-planner/store/reducer.ts b/src/app/degree-planner/store/reducer.ts index 39f3209..5927ac1 100644 --- a/src/app/degree-planner/store/reducer.ts +++ b/src/app/degree-planner/store/reducer.ts @@ -9,6 +9,8 @@ import { MakePlanPrimary, MakePlanPrimarySuccess, MakePlanPrimaryFailure, + ChangePlanNameSuccess, + ChangePlanNameFailure, } from '@app/degree-planner/store/actions/plan.actions'; import { CourseActionTypes, @@ -26,7 +28,7 @@ import { import { AddAcademicYearActionTypes, AddAcademicYearRequest, - } from '@app/degree-planner/store/actions/addAcademicYear.actions'; +} from '@app/degree-planner/store/actions/addAcademicYear.actions'; import { SavedForLaterCourse } from '@app/core/models/saved-for-later-course'; import { DegreePlan } from '@app/core/models/degree-plan'; @@ -43,7 +45,9 @@ type SupportedActions = | AddAcademicYearRequest | MakePlanPrimary | MakePlanPrimarySuccess - | MakePlanPrimaryFailure; + | MakePlanPrimaryFailure + | ChangePlanNameSuccess + | ChangePlanNameFailure; export function degreePlannerReducer( state = INITIAL_DEGREE_PLANNER_STATE, @@ -72,9 +76,9 @@ export function degreePlannerReducer( /** * The `AddAcademicYearRequest` action is triggered after `addAcademicYear()` * function runs. A new academic year container with three terms will be created. - */ + */ case AddAcademicYearActionTypes.AddAcademicYearRequest: { - const originalTerms = state.visibleTerms.map( term => { + const originalTerms = state.visibleTerms.map(term => { return parseInt(term.termCode.substr(0, 3), 10); }); @@ -82,15 +86,9 @@ export function degreePlannerReducer( const newVisibleTerms = [ ...state.visibleTerms, - { termCode: `${newAcademicYearCode}2`, - courses: [] - }, - { termCode: `${newAcademicYearCode}4`, - courses: [] - }, - { termCode: `${newAcademicYearCode}6`, - courses: [] - } + { termCode: `${newAcademicYearCode}2`, courses: [] }, + { termCode: `${newAcademicYearCode}4`, courses: [] }, + { termCode: `${newAcademicYearCode}6`, courses: [] }, ]; return { ...state, visibleTerms: newVisibleTerms }; } @@ -290,6 +288,19 @@ export function degreePlannerReducer( return state; } + case PlanActionTypes.ChangePlanNameSuccess: + case PlanActionTypes.ChangePlanNameFailure: { + // TODO add global loading state + + // Update the visible plan object + const newVisibleDegreePlan = { + ...(state.visibleDegreePlan as DegreePlan), + name: action.name, + }; + + return { ...state, visibleDegreePlan: newVisibleDegreePlan }; + } + /** * It's okay if the action didn't match any of the cases above. If that's * the case, just return the existing state object. -- GitLab