Skip to content
Snippets Groups Projects
Commit e7f0cbd2 authored by Scott Berg's avatar Scott Berg
Browse files

Add action / effect / reducer for adding a new course and removing a course from terms

parent 8e887594
No related branches found
No related tags found
No related merge requests found
import { Action } from '@ngrx/store';
import { PlannedTerm } from '@app/core/models/planned-term';
import { DegreePlannerState } from '@app/degree-planner/state';
import { Course} from '../../core/models/course';
export enum PlanActionTypes {
InitialPlanLoadResponse = '[Plan] Initial Load Response',
ChangeVisiblePlanRequest = '[Plan] Change Visible Request',
ChangeVisiblePlanResponse = '[Plan] Change Visible Response',
AddCourseRequest = '[Plan] Add Course Request',
AddCourseResponse = '[Plan] Add Course Response',
RemoveCourseRequest = '[Plan] Remove Course Request',
RemoveCourseResponse = '[Plan] Remove Course Response',
ChangeCourseTermRequest = '[Plan] Change Course Term Request',
ChangeCourseTermResponse = '[Plan] Change Course Term Response'
ChangeCourseTermResponse = '[Plan] Change Course Term Response',
MoveFromSavedToTermRequest = '[Plan] Move Course From Saved to Term Request',
MoveFromSavedToTermResponse= '[Plan] Move Course From Saved to Term Response'
}
export class InitialPlanLoadResponse implements Action {
......@@ -40,3 +47,31 @@ export class ChangeCourseTermResponse implements Action {
public payload: {to: string, from: string, id: number}
) {}
}
export class AddCourseRequest implements Action {
public readonly type = PlanActionTypes.AddCourseRequest;
constructor(
public payload: {subjectCode: string, courseId: string, termCode: string}
) {}
}
export class AddCourseResponse implements Action {
public readonly type = PlanActionTypes.AddCourseResponse;
constructor(
public payload: {course: Course}
) {}
}
export class RemoveCourseRequest implements Action {
public readonly type = PlanActionTypes.RemoveCourseRequest;
constructor(
public payload: {id: number}
) {}
}
export class RemoveCourseResponse implements Action {
public readonly type = PlanActionTypes.RemoveCourseResponse;
constructor(
public payload: {id: number}
) {}
}
......@@ -8,7 +8,7 @@ import { Store } from '@ngrx/store';
// Services
import { DegreePlannerApiService } from '@app/degree-planner/services/api.service';
import { getDegreePlannerState } from '@app/degree-planner/selectors';
import { getDegreePlannerState, getVisibleRoadmapId } from '@app/degree-planner/selectors';
// Actions
import {
......@@ -16,7 +16,9 @@ import {
ChangeVisiblePlanRequest,
ChangeVisiblePlanResponse,
PlanActionTypes,
ChangeCourseTermResponse
ChangeCourseTermResponse,
AddCourseResponse,
RemoveCourseResponse
} from '@app/degree-planner/actions/plan.actions';
// Models
......@@ -111,6 +113,81 @@ export class DegreePlanEffects {
})
);
@Effect()
AddCourse$ = this.actions$.pipe(
ofType<any>(PlanActionTypes.AddCourseRequest),
withLatestFrom(this.store$.select(getDegreePlannerState)),
filter(([_, state]) => typeof state.visibleRoadmapId === 'number'),
// Get the roadmap ID from the action.
tap(([action, state]) => {
console.log(action);
console.log(state);
}),
// Get term data for the degree plan specified by the roadmap ID.
flatMap(([action, state]) => {
// TODO error handle the API calls
const roadmapId = state.visibleRoadmapId;
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
console.log('------');
console.log(action);
console.log(response);
console.log('------');
return new AddCourseResponse({ course: response});
})
);
@Effect()
RemoveCourse$ = this.actions$.pipe(
ofType<any>(PlanActionTypes.RemoveCourseRequest),
withLatestFrom(this.store$.select(getDegreePlannerState)),
filter(([_, state]) => typeof state.visibleRoadmapId === 'number'),
// Get the roadmap ID from the action.
tap(([action, state]) => {
console.log(action);
console.log(state);
}),
// Get term data for the degree plan specified by the roadmap ID.
flatMap(([action, state]) => {
// TODO error handle the API calls
return this.api.removeCourse(state.visibleRoadmapId as number, action.payload.id).pipe(
map(response => {
return {
response,
action
};
})
);
}),
// Wrap data in an Action for dispatch
map(({ response, action }) => {
if (response === null) {
const { id } = action.payload;
return new RemoveCourseResponse({ id });
}
return;
})
);
private loadTermsForPlan<T extends { visibleRoadmapId: number }>(stdin: T) {
return forkJoin(
this.api.getAllNotes(stdin.visibleRoadmapId),
......
......@@ -6,8 +6,9 @@ import {
PlanActionTypes,
InitialPlanLoadResponse,
ChangeVisiblePlanResponse,
ChangeCourseTermRequest,
ChangeCourseTermResponse
RemoveCourseResponse,
ChangeCourseTermResponse,
AddCourseResponse
} from '@app/degree-planner/actions/plan.actions';
import {
NoteActionTypes,
......@@ -20,7 +21,9 @@ type SupportedActions =
| ChangeVisiblePlanResponse
| WriteNoteResponse
| DeleteNoteResponse
| ChangeCourseTermResponse;
| ChangeCourseTermResponse
| RemoveCourseResponse
| AddCourseResponse;
export function degreePlannerReducer(
state = INITIAL_DEGREE_PLANNER_STATE,
......@@ -146,6 +149,36 @@ export function degreePlannerReducer(
return state;
}
case PlanActionTypes.AddCourseResponse: {
const { course } = action.payload;
const newVisibleTerms = state.visibleTerms.map(term => {
if (term.termCode === course.termCode) {
term.courses.push(course);
}
return term;
});
return {...state, visibleTerms: newVisibleTerms};
// return {...state, visibleTerms: newVisibleTerms};
// return state;
}
case PlanActionTypes.RemoveCourseResponse: {
const { id } = action.payload;
// Create new visibleTerms array
const newVisibleTerms = state.visibleTerms.map(term => {
term.courses = term.courses.filter(course => {
return course.id !== id;
});
return term;
});
return {...state, visibleTerms: newVisibleTerms};
}
/**
* 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.
......
......@@ -58,6 +58,15 @@ export class DegreePlannerApiService {
roadmapId + '/courses/' + recordId + '?termCode=' + termCode, HTTP_OPTIONS);
}
public addCourse(planId: number, subjectCode: string, courseId: string, termCode: string) {
return this.http.post<Course>(
this.config.apiPlannerUrl + '/degreePlan/' + planId + '/courses', {subjectCode, courseId, termCode }, HTTP_OPTIONS);
}
public removeCourse(planId: number, recordId: string) {
return this.http.delete(this.config.apiPlannerUrl + '/degreePlan/' + planId + '/courses/' + recordId, HTTP_OPTIONS);
}
public createNote(
planId: number,
termCode: string,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment