Skip to content
Snippets Groups Projects
Commit 060d83ef authored by Isaac Evavold's avatar Isaac Evavold
Browse files

move course effects and actions separate files

parent 587c52c9
No related branches found
No related tags found
No related merge requests found
......@@ -15,6 +15,7 @@ import { SidenavService } from './core/service/sidenav.service';
import { degreePlannerReducer } from '@app/degree-planner/store/reducer';
import { DegreePlanEffects } from '@app/degree-planner/store/effects/plan.effects';
import { NoteEffects } from '@app/degree-planner/store/effects/note.effects';
import { CourseEffects } from '@app/degree-planner/store/effects/course.effects';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { CourseDetailsDialogComponent } from './degree-planner/dialogs/course-details-dialog/course-details-dialog.component';
......@@ -23,7 +24,7 @@ import { CourseDetailsDialogComponent } from './degree-planner/dialogs/course-de
StoreModule.forRoot({
degreePlanner: degreePlannerReducer,
}),
EffectsModule.forRoot([DegreePlanEffects, NoteEffects]),
EffectsModule.forRoot([DegreePlanEffects, NoteEffects, CourseEffects]),
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
......
......@@ -7,7 +7,7 @@ import { SavedForLaterCourse } from '@app/core/models/saved-for-later-course';
import { DegreePlannerState } from '@app/degree-planner/store/state';
import { Store } from '@ngrx/store';
import { RemoveCourseRequest } from '@app/degree-planner/store/actions/plan.actions';
import { RemoveCourseRequest } from '@app/degree-planner/store/actions/course.actions';
@Component({
selector: 'cse-remove-course-confirm-dialog',
......
......@@ -11,7 +11,7 @@ import { DegreePlannerState } from '@app/degree-planner/store/state';
import {
AddSavedForLaterRequest,
RemoveCourseRequest,
} from '@app/degree-planner/store/actions/plan.actions';
} from '@app/degree-planner/store/actions/course.actions';
// Selectors
import { getDropZones } from '@app/degree-planner/store/selectors';
......
import { Action } from '@ngrx/store';
import { Course } from '@app/core/models/course';
export enum CourseActionTypes {
AddCourseRequest = '[Course] Add Course Request',
AddCourseResponse = '[Course] Add Course Response',
RemoveCourseRequest = '[Course] Remove Course Request',
RemoveCourseResponse = '[Course] Remove Course Response',
ChangeCourseTermRequest = '[Course] Change Course Term Request',
ChangeCourseTermResponse = '[Course] Change Course Term Response',
AddSavedForLaterRequest = '[Course] Add Saved For Later Request',
AddSavedForLaterResponse = '[Course] Add Saved For Later Response',
RemoveSavedForLaterRequest = '[Course] Remove Saved For Later Request',
RemoveSavedForLaterResponse = '[Course] Remove Saved For Later Response',
MoveFromSavedToTermRequest = '[Course] Move Course From Saved to Term Request',
MoveFromSavedToTermResponse = '[Course] Move Course From Saved to Term Response',
}
export class ChangeCourseTermRequest implements Action {
public readonly type = CourseActionTypes.ChangeCourseTermRequest;
constructor(public payload: { to: string; from: string; id: number }) {}
}
export class ChangeCourseTermResponse implements Action {
public readonly type = CourseActionTypes.ChangeCourseTermResponse;
constructor(public payload: { to: string; from: string; id: number }) {}
}
export class AddCourseRequest implements Action {
public readonly type = CourseActionTypes.AddCourseRequest;
constructor(
public payload: { subjectCode: string; courseId: string; termCode: string },
) {}
}
export class AddCourseResponse implements Action {
public readonly type = CourseActionTypes.AddCourseResponse;
constructor(public payload: { course: Course }) {}
}
export class RemoveCourseRequest implements Action {
public readonly type = CourseActionTypes.RemoveCourseRequest;
constructor(public payload: { recordId: number }) {}
}
export class RemoveCourseResponse implements Action {
public readonly type = CourseActionTypes.RemoveCourseResponse;
constructor(public payload: { recordId: number }) {}
}
export class AddSavedForLaterRequest implements Action {
public readonly type = CourseActionTypes.AddSavedForLaterRequest;
constructor(
public payload: {
subjectCode: string;
courseId: string;
title: string;
catalogNumber: string;
},
) {}
}
export class AddSavedForLaterResponse implements Action {
public readonly type = CourseActionTypes.AddSavedForLaterResponse;
constructor(
public payload: {
subjectCode: string;
courseId: string;
title: string;
catalogNumber: string;
},
) {}
}
export class RemoveSavedForLaterRequest implements Action {
public readonly type = CourseActionTypes.RemoveSavedForLaterRequest;
constructor(public payload: { subjectCode: string; courseId: string }) {}
}
export class RemoveSavedForLaterResponse implements Action {
public readonly type = CourseActionTypes.RemoveSavedForLaterResponse;
constructor(public payload: { subjectCode: string; courseId: string }) {}
}
......@@ -2,31 +2,12 @@ import { Action } from '@ngrx/store';
import { DegreePlan } from '@app/core/models/degree-plan';
import { PlannedTerm } from '@app/core/models/planned-term';
import { DegreePlannerState } from '@app/degree-planner/store/state';
import { Course } from '@app/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',
AddSavedForLaterRequest = '[Plan] Add Saved For Later Request',
AddSavedForLaterResponse = '[Plan] Add Saved For Later Response',
RemoveSavedForLaterRequest = '[Plan] Remove Saved For Later Request',
RemoveSavedForLaterResponse = '[Plan] Remove Saved For Later Response',
MoveFromSavedToTermRequest = '[Plan] Move Course From Saved to Term Request',
MoveFromSavedToTermResponse = '[Plan] Move Course From Saved to Term Response',
}
export class InitialPlanLoadResponse implements Action {
......@@ -48,69 +29,3 @@ export class ChangeVisiblePlanResponse implements Action {
},
) {}
}
export class ChangeCourseTermRequest implements Action {
public readonly type = PlanActionTypes.ChangeCourseTermRequest;
constructor(public payload: { to: string; from: string; id: number }) {}
}
export class ChangeCourseTermResponse implements Action {
public readonly type = PlanActionTypes.ChangeCourseTermResponse;
constructor(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: { recordId: number }) {}
}
export class RemoveCourseResponse implements Action {
public readonly type = PlanActionTypes.RemoveCourseResponse;
constructor(public payload: { recordId: number }) {}
}
export class AddSavedForLaterRequest implements Action {
public readonly type = PlanActionTypes.AddSavedForLaterRequest;
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;
title: string;
catalogNumber: string;
},
) {}
}
export class RemoveSavedForLaterRequest implements Action {
public readonly type = PlanActionTypes.RemoveSavedForLaterRequest;
constructor(public payload: { subjectCode: string; courseId: string }) {}
}
export class RemoveSavedForLaterResponse implements Action {
public readonly type = PlanActionTypes.RemoveSavedForLaterResponse;
constructor(public payload: { subjectCode: string; courseId: string }) {}
}
// Libraries
import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { map, flatMap, withLatestFrom, filter } from 'rxjs/operators';
import { GlobalState } from '@app/core/state';
import { Store } from '@ngrx/store';
// Services
import { DegreePlannerApiService } from '@app/degree-planner/services/api.service';
import { getDegreePlannerState } from '@app/degree-planner/store/selectors';
// Actions
import {
CourseActionTypes,
ChangeCourseTermResponse,
AddCourseResponse,
RemoveCourseResponse,
RemoveSavedForLaterResponse,
AddSavedForLaterResponse,
AddCourseRequest,
RemoveCourseRequest,
} from '@app/degree-planner/store/actions/course.actions';
// Models
import { DegreePlan } from '@app/core/models/degree-plan';
import { Course, SubjectMapping, CourseBase } from '@app/core/models/course';
import { SavedForLaterCourse } from '@app/core/models/saved-for-later-course';
@Injectable()
export class CourseEffects {
constructor(
private actions$: Actions,
private api: DegreePlannerApiService,
private store$: Store<GlobalState>,
) {}
@Effect()
MoveCourseBetweenTerms$ = this.actions$.pipe(
ofType<any>(CourseActionTypes.ChangeCourseTermRequest),
withLatestFrom(this.store$.select(getDegreePlannerState)),
filter(([_, state]) => typeof state.visibleDegreePlan !== undefined),
// Get term data for the degree plan specified by the roadmap ID.
flatMap(([action, state]) => {
// TODO error handle the API calls
return this.api
.updateCourseTerm(
(state.visibleDegreePlan as DegreePlan).roadmapId,
action.payload.id,
action.payload.to,
)
.pipe(
map(response => {
return {
response,
action,
};
}),
);
}),
// // Wrap data in an Action for dispatch
map(({ response, action }) => {
if (response === 1) {
return new ChangeCourseTermResponse({
id: action.payload.id,
from: action.payload.from,
to: action.payload.to,
});
}
return;
}),
);
@Effect()
AddCourse$ = this.actions$.pipe(
ofType<AddCourseRequest>(CourseActionTypes.AddCourseRequest),
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;
const { subjectCode, termCode, courseId } = action.payload;
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<RemoveCourseRequest>(CourseActionTypes.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]) => {
const roadmapId = (state.visibleDegreePlan as DegreePlan).roadmapId;
const recordId = action.payload.recordId;
const removeCourse$ = this.api.removeCourse(roadmapId, recordId);
const toSuccessAction$ = removeCourse$.pipe(
map(() => new RemoveCourseResponse({ recordId })),
);
return toSuccessAction$;
}),
);
@Effect()
RemoveSavedForLater$ = this.actions$.pipe(
ofType<any>(CourseActionTypes.RemoveSavedForLaterRequest),
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
return this.api
.removeSavedForLater(
action.payload.subjectCode,
action.payload.courseId,
)
.pipe(
map(response => {
return {
response,
action,
};
}),
);
}),
// // Wrap data in an Action for dispatch
map(({ response, action }) => {
if (response === null) {
const { courseId, subjectCode } = action.payload;
return new RemoveSavedForLaterResponse({ courseId, subjectCode });
// TODO Update UI and remove saved response
}
return;
}),
);
@Effect()
SaveForLater$ = this.actions$.pipe(
ofType<any>(CourseActionTypes.AddSavedForLaterRequest),
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
return this.api
.saveForLater(action.payload.subjectCode, action.payload.courseId)
.pipe(
map(response => {
return {
response,
action,
};
}),
);
}),
// // // Wrap data in an Action for dispatch
map(({ response, action }) => {
if (response === null) {
return new AddSavedForLaterResponse(action.payload);
}
// return;
return;
}),
);
private loadSavedForLaterCourses(subjects: SubjectMapping) {
return this.api.getSavedForLaterCourses().pipe(
map(courseBases => {
return courseBases.map<SavedForLaterCourse>(base => {
return {
...base,
subject: subjects[base.subjectCode] as string,
};
});
}),
);
}
}
......@@ -2,7 +2,7 @@
import { Injectable } from '@angular/core';
import { ROOT_EFFECTS_INIT, Actions, Effect, ofType } from '@ngrx/effects';
import { Observable, forkJoin, of } from 'rxjs';
import { map, flatMap, withLatestFrom, filter } from 'rxjs/operators';
import { map, flatMap, withLatestFrom } from 'rxjs/operators';
import { GlobalState } from '@app/core/state';
import { Store } from '@ngrx/store';
......@@ -16,13 +16,6 @@ import {
ChangeVisiblePlanRequest,
ChangeVisiblePlanResponse,
PlanActionTypes,
ChangeCourseTermResponse,
AddCourseResponse,
RemoveCourseResponse,
RemoveSavedForLaterResponse,
AddSavedForLaterResponse,
AddCourseRequest,
RemoveCourseRequest,
} from '@app/degree-planner/store/actions/plan.actions';
// Models
......@@ -107,170 +100,6 @@ export class DegreePlanEffects {
map(payload => new ChangeVisiblePlanResponse(payload)),
);
@Effect()
MoveCourseBetweenTerms$ = this.actions$.pipe(
ofType<any>(PlanActionTypes.ChangeCourseTermRequest),
withLatestFrom(this.store$.select(getDegreePlannerState)),
filter(([_, state]) => typeof state.visibleDegreePlan !== undefined),
// Get term data for the degree plan specified by the roadmap ID.
flatMap(([action, state]) => {
// TODO error handle the API calls
return this.api
.updateCourseTerm(
(state.visibleDegreePlan as DegreePlan).roadmapId,
action.payload.id,
action.payload.to,
)
.pipe(
map(response => {
return {
response,
action,
};
}),
);
}),
// // Wrap data in an Action for dispatch
map(({ response, action }) => {
if (response === 1) {
return new ChangeCourseTermResponse({
id: action.payload.id,
from: action.payload.from,
to: action.payload.to,
});
}
return;
}),
);
@Effect()
AddCourse$ = this.actions$.pipe(
ofType<AddCourseRequest>(PlanActionTypes.AddCourseRequest),
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;
const { subjectCode, termCode, courseId } = action.payload;
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<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]) => {
const roadmapId = (state.visibleDegreePlan as DegreePlan).roadmapId;
const recordId = action.payload.recordId;
const removeCourse$ = this.api.removeCourse(roadmapId, recordId);
const toSuccessAction$ = removeCourse$.pipe(
map(() => new RemoveCourseResponse({ recordId })),
);
return toSuccessAction$;
}),
);
@Effect()
RemoveSavedForLater$ = this.actions$.pipe(
ofType<any>(PlanActionTypes.RemoveSavedForLaterRequest),
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
return this.api
.removeSavedForLater(
action.payload.subjectCode,
action.payload.courseId,
)
.pipe(
map(response => {
return {
response,
action,
};
}),
);
}),
// // Wrap data in an Action for dispatch
map(({ response, action }) => {
if (response === null) {
const { courseId, subjectCode } = action.payload;
return new RemoveSavedForLaterResponse({ courseId, subjectCode });
// TODO Update UI and remove saved response
}
return;
}),
);
@Effect()
SaveForLater$ = this.actions$.pipe(
ofType<any>(PlanActionTypes.AddSavedForLaterRequest),
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
return this.api
.saveForLater(action.payload.subjectCode, action.payload.courseId)
.pipe(
map(response => {
return {
response,
action,
};
}),
);
}),
// // // Wrap data in an Action for dispatch
map(({ response, action }) => {
if (response === null) {
return new AddSavedForLaterResponse(action.payload);
}
// return;
return;
}),
);
private loadSavedForLaterCourses(subjects: SubjectMapping) {
return this.api.getSavedForLaterCourses().pipe(
map(courseBases => {
......
......@@ -6,12 +6,15 @@ import {
PlanActionTypes,
InitialPlanLoadResponse,
ChangeVisiblePlanResponse,
} from '@app/degree-planner/store/actions/plan.actions';
import {
CourseActionTypes,
RemoveCourseResponse,
ChangeCourseTermResponse,
AddCourseResponse,
RemoveSavedForLaterResponse,
AddSavedForLaterResponse,
} from '@app/degree-planner/store/actions/plan.actions';
} from '@app/degree-planner/store/actions/course.actions';
import {
NoteActionTypes,
WriteNoteResponse,
......@@ -123,7 +126,7 @@ export function degreePlannerReducer(
}
}
case PlanActionTypes.ChangeCourseTermResponse: {
case CourseActionTypes.ChangeCourseTermResponse: {
const { to, from, id } = action.payload;
const t = state.visibleTerms.find(term => term.termCode === from);
......@@ -153,7 +156,7 @@ export function degreePlannerReducer(
return state;
}
case PlanActionTypes.AddCourseResponse: {
case CourseActionTypes.AddCourseResponse: {
const { course } = action.payload;
const newVisibleTerms = state.visibleTerms.map(term => {
......@@ -169,7 +172,7 @@ export function degreePlannerReducer(
// return state;
}
case PlanActionTypes.RemoveCourseResponse: {
case CourseActionTypes.RemoveCourseResponse: {
const { recordId: id } = action.payload;
// Create new visibleTerms array
......@@ -183,7 +186,7 @@ export function degreePlannerReducer(
return { ...state, visibleTerms: newVisibleTerms };
}
case PlanActionTypes.RemoveSavedForLaterResponse: {
case CourseActionTypes.RemoveSavedForLaterResponse: {
const { courseId, subjectCode } = action.payload;
// // Create new saved for later array
......@@ -195,7 +198,7 @@ export function degreePlannerReducer(
return { ...state, savedForLaterCourses: newSavedForLater };
}
case PlanActionTypes.AddSavedForLaterResponse: {
case CourseActionTypes.AddSavedForLaterResponse: {
const newSavedForLater: SavedForLaterCourse[] = [
...state.savedForLaterCourses,
{
......
......@@ -16,7 +16,7 @@ import {
ChangeCourseTermRequest,
AddCourseRequest,
RemoveSavedForLaterRequest,
} from '@app/degree-planner/store/actions/plan.actions';
} from '@app/degree-planner/store/actions/course.actions';
// Selectors
import {
......
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