From 3fec3d81605b6086da35817098f2b004389cea09 Mon Sep 17 00:00:00 2001 From: "jvanboxtel@wisc.edu" <jvanboxtel@wisc.edu> Date: Fri, 7 Jun 2019 09:34:57 -0500 Subject: [PATCH] ROENROLL-1792 --- src/app/core/actions.ts | 9 +++ src/app/core/models/alert.ts | 9 +++ src/app/core/models/user-preferences.ts | 1 + .../dars/dars-view/dars-view.component.html | 1 + src/app/dars/dars.module.ts | 1 + src/app/dars/store/actions.ts | 7 +++ src/app/dars/store/effects.ts | 63 ++++++++++++++++--- src/app/dars/store/state.ts | 3 + .../degree-planner/degree-planner.module.ts | 4 +- .../store/actions/ui.actions.ts | 10 +-- src/app/degree-planner/store/reducer.ts | 5 +- .../alert-container.component.html | 0 .../alert-container.component.scss | 0 .../alert-container.component.ts | 2 +- src/app/shared/shared.module.ts | 10 ++- src/assets/mock-data/metadata-response.json | 17 +++++ 16 files changed, 123 insertions(+), 19 deletions(-) rename src/app/{degree-planner => shared/components}/alert-container/alert-container.component.html (100%) rename src/app/{degree-planner => shared/components}/alert-container/alert-container.component.scss (100%) rename src/app/{degree-planner => shared/components}/alert-container/alert-container.component.ts (93%) create mode 100644 src/assets/mock-data/metadata-response.json diff --git a/src/app/core/actions.ts b/src/app/core/actions.ts index 907f1ab..0b224cb 100644 --- a/src/app/core/actions.ts +++ b/src/app/core/actions.ts @@ -5,7 +5,16 @@ export enum UserPreferencesActionTypes { UpdateUserPreferences = '[User Preferences] Update', } +export enum NotificationActionTypes { + DismissAlert = '[UI] Dismiss alert', +} + export class UpdateUserPreferences implements Action { public readonly type = UserPreferencesActionTypes.UpdateUserPreferences; constructor(public payload: Partial<UserPreferences>) {} } + +export class DismissAlert implements Action { + public readonly type = NotificationActionTypes.DismissAlert; + constructor(public payload: { key: string }) {} +} diff --git a/src/app/core/models/alert.ts b/src/app/core/models/alert.ts index 1d78964..ad6cfe4 100644 --- a/src/app/core/models/alert.ts +++ b/src/app/core/models/alert.ts @@ -13,3 +13,12 @@ export class DisclaimerAlert implements Alert { constructor(public callback: Alert['callback']) {} } + +export class DarsDisclaimerAlert implements Alert { + public readonly key = 'disclaimerAlert'; + public readonly title = 'This is a planning tool Dars.'; + public readonly message = + 'If you have questions about your plan or degree, please contact your advisor.'; + + constructor(public callback: Alert['callback']) {} +} diff --git a/src/app/core/models/user-preferences.ts b/src/app/core/models/user-preferences.ts index cc01a77..a201713 100644 --- a/src/app/core/models/user-preferences.ts +++ b/src/app/core/models/user-preferences.ts @@ -3,4 +3,5 @@ export interface UserPreferences { degreePlannerSelectedPlan?: number; degreePlannerHasDismissedDisclaimer?: boolean; degreePlannerHasDismissedIEWarning?: boolean; + darsHasDismissedDisclaimer?: boolean; } diff --git a/src/app/dars/dars-view/dars-view.component.html b/src/app/dars/dars-view/dars-view.component.html index f296898..00ef9c9 100644 --- a/src/app/dars/dars-view/dars-view.component.html +++ b/src/app/dars/dars-view/dars-view.component.html @@ -20,6 +20,7 @@ <!-- Main DARS Content --> <div id="dars-main"> + <cse-alert-container></cse-alert-container> <h2 class="mat-h1">Completed Audit Requests</h2> <div id="dars-header-bar"> diff --git a/src/app/dars/dars.module.ts b/src/app/dars/dars.module.ts index 08b9305..1a2b72c 100644 --- a/src/app/dars/dars.module.ts +++ b/src/app/dars/dars.module.ts @@ -7,6 +7,7 @@ import { DarsAuditComponent } from './audit/audit.component'; import { DarsMetadataTableComponent } from './metadata-table/metadata-table.component'; import { NewAuditOptionsComponent } from './dars-view/new-audit-options/new-audit-options.component'; import { MatStepperModule } from '@angular/material'; +import { AlertContainerComponent } from '../shared/components/alert-container/alert-container.component'; @NgModule({ imports: [ diff --git a/src/app/dars/store/actions.ts b/src/app/dars/store/actions.ts index 6124756..43d1a9c 100644 --- a/src/app/dars/store/actions.ts +++ b/src/app/dars/store/actions.ts @@ -1,3 +1,4 @@ +import { DARSState } from '@app/dars/store/state'; import { Action } from '@ngrx/store'; import { AuditMetadata } from '../models/audit-metadata'; import { Audit } from '../models/audit'; @@ -5,6 +6,7 @@ import { Audit } from '../models/audit'; export enum DarsActionTypes { ErrorLoadingMetadata = '[DARS] Error Loading Metadata', StartLoadingMetadata = '[DARS] Start Loading Metadata', + DoneLoadingMetadata = '[DARS] Done Loading Metadata', ErrorLoadingAudit = '[DARS] Error Loading Audit', AddAuditMetadata = '[DARS] Add Audit Metadata', StartLoadingAudit = '[DARS] Start Loading Audit', @@ -21,6 +23,11 @@ export class StartLoadingMetadata implements Action { public readonly type = DarsActionTypes.StartLoadingMetadata; } +export class DoneLoadingMetadata implements Action { + public readonly type = DarsActionTypes.DoneLoadingMetadata; + constructor(public payload: DARSState) {} +} + export class ErrorLoadingAudit implements Action { public readonly type = DarsActionTypes.ErrorLoadingAudit; constructor(public payload: { message: string }) {} diff --git a/src/app/dars/store/effects.ts b/src/app/dars/store/effects.ts index 150fe2a..ec73776 100644 --- a/src/app/dars/store/effects.ts +++ b/src/app/dars/store/effects.ts @@ -1,26 +1,73 @@ +import { visibleAudit } from './selectors'; +import { UpdateUserPreferences } from './../../core/actions'; +import { GlobalState } from '@app/core/state'; +import { Store } from '@ngrx/store'; +import { forkJoinWithKeys } from '@app/degree-planner/shared/utils'; import { Injectable } from '@angular/core'; import { Actions, Effect, ofType } from '@ngrx/effects'; import { DarsActionTypes } from '@app/dars/store/actions'; import * as darsActions from '@app/dars/store/actions'; -import { flatMap, map, catchError } from 'rxjs/operators'; +import { flatMap, map, catchError, switchMap } from 'rxjs/operators'; import { DarsApiService } from '../services/api.service'; import { of } from 'rxjs'; +import { Alert, DarsDisclaimerAlert } from '@app/core/models/alert'; +import { DegreePlannerApiService } from '@app/degree-planner/services/api.service'; +import { INITIAL_DARS_STATE } from './state'; @Injectable() export class DARSEffects { - constructor(private actions$: Actions, private api: DarsApiService) {} + constructor( + private actions$: Actions, + private api: DarsApiService, + private degreeAPI: DegreePlannerApiService, + private store$: Store<GlobalState>, + ) {} @Effect() load$ = this.actions$.pipe( ofType(DarsActionTypes.StartLoadingMetadata), - flatMap(() => this.api.getAudits()), - map(metadata => new darsActions.AddAuditMetadata({ metadata })), - catchError(() => { - return of( - new darsActions.ErrorLoadingMetadata({ - message: 'Unable to load audit metadata. Please try again', + + flatMap(() => { + return forkJoinWithKeys({ + metadata: this.api.getAudits(), + userPreferences: this.degreeAPI.getUserPreferences(), + }); + }), + + flatMap(({ metadata, userPreferences }) => { + const alerts: Alert[] = []; + if (userPreferences.darsHasDismissedDisclaimer !== true) { + alerts.push( + new DarsDisclaimerAlert(() => { + this.store$.dispatch( + new UpdateUserPreferences({ + darsHasDismissedDisclaimer: true, + }), + ); + }), + ); + } + + return forkJoinWithKeys({ + metadata: of(metadata), + visibleAudit: of({}), + alerts: of(alerts), + }).pipe( + switchMap(payload => { + return [ + new darsActions.AddAuditMetadata({ metadata }), + new UpdateUserPreferences(userPreferences), + ]; }), ); }), + + // catchError(() => { + // return of( + // new darsActions.ErrorLoadingMetadata({ + // message: 'Unable to load audit metadata. Please try again', + // }), + // ); + // }), ); } diff --git a/src/app/dars/store/state.ts b/src/app/dars/store/state.ts index 8986599..c299147 100644 --- a/src/app/dars/store/state.ts +++ b/src/app/dars/store/state.ts @@ -1,3 +1,4 @@ +import { Alert } from './../../core/models/alert'; import { AuditMetadata } from '../models/audit-metadata'; import { Audit } from '../models/audit'; @@ -11,9 +12,11 @@ export interface DARSState { | { status: 'NotLoaded' } | { status: 'Loading'; metadata: AuditMetadata } | { status: 'Loaded'; metadata: AuditMetadata; audit: Audit }; + alerts: Alert[]; } export const INITIAL_DARS_STATE: DARSState = { metadata: { status: 'Loading' }, visibleAudit: { status: 'NotLoaded' }, + alerts: [], }; diff --git a/src/app/degree-planner/degree-planner.module.ts b/src/app/degree-planner/degree-planner.module.ts index a3d71e6..1a58879 100644 --- a/src/app/degree-planner/degree-planner.module.ts +++ b/src/app/degree-planner/degree-planner.module.ts @@ -10,7 +10,7 @@ import { DragDropModule } from '@angular/cdk/drag-drop'; import { RemoveCourseConfirmDialogComponent } from './dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component'; import { YearContainerComponent } from '@app/degree-planner/year-container/year-container.component'; import { CourseSearchComponent } from '@app/degree-planner/course-search/course-search.component'; -import { AlertContainerComponent } from './alert-container/alert-container.component'; +import { AlertContainerComponent } from '../shared/components/alert-container/alert-container.component'; import { EffectsModule } from '@ngrx/effects'; import { DegreePlanEffects } from './store/effects/plan.effects'; import { NoteEffects } from './store/effects/note.effects'; @@ -38,7 +38,7 @@ import { ErrorEffects } from './store/effects/error.effects'; NotesDialogComponent, RemoveCourseConfirmDialogComponent, YearContainerComponent, - AlertContainerComponent, + // AlertContainerComponent, CourseSearchComponent, ], entryComponents: [NotesDialogComponent, RemoveCourseConfirmDialogComponent], diff --git a/src/app/degree-planner/store/actions/ui.actions.ts b/src/app/degree-planner/store/actions/ui.actions.ts index 0600458..2fce691 100644 --- a/src/app/degree-planner/store/actions/ui.actions.ts +++ b/src/app/degree-planner/store/actions/ui.actions.ts @@ -16,7 +16,7 @@ export enum UIActionTypes { OpenSidenav = '[UI] Open Sidenav', CloseSidenav = '[UI] Close Sidenav', - DismissAlert = '[UI] Dismiss Disclaimer Alert', + // DismissAlert = '[UI] Dismiss Disclaimer Alert', UpdateUserPreferences = '[UI] Update User Preferences', @@ -66,10 +66,10 @@ export class CloseSidenav implements Action { public readonly type = UIActionTypes.CloseSidenav; } -export class DismissAlert implements Action { - public readonly type = UIActionTypes.DismissAlert; - constructor(public payload: { key: string }) {} -} +// export class DismissAlert implements Action { +// public readonly type = UIActionTypes.DismissAlert; +// constructor(public payload: { key: string }) {} +// } export class AddAcademicYear implements Action { public readonly type = UIActionTypes.AddAcademicYear; diff --git a/src/app/degree-planner/store/reducer.ts b/src/app/degree-planner/store/reducer.ts index 3b8f0f7..1770f8f 100644 --- a/src/app/degree-planner/store/reducer.ts +++ b/src/app/degree-planner/store/reducer.ts @@ -6,6 +6,7 @@ import * as planActions from '@app/degree-planner/store/actions/plan.actions'; import * as courseActions from '@app/degree-planner/store/actions/course.actions'; import * as noteActions from '@app/degree-planner/store/actions/note.actions'; import * as uiActions from '@app/degree-planner/store/actions/ui.actions'; +import * as globalActions from '@app/core/actions'; import { SavedForLaterCourse } from '@app/core/models/saved-for-later-course'; import { DegreePlan } from '@app/core/models/degree-plan'; import { Year, YearMapping } from '@app/core/models/year'; @@ -41,7 +42,7 @@ type SupportedActions = | planActions.DeletePlanSuccess | uiActions.ExpandAcademicYear | uiActions.CollapseAcademicYear - | uiActions.DismissAlert + | globalActions.DismissAlert | uiActions.OpenCourseSearch | uiActions.CloseCourseSearch | uiActions.ToggleCourseSearch @@ -143,7 +144,7 @@ export function degreePlannerReducer( return newState; } - case uiActions.UIActionTypes.DismissAlert: { + case globalActions.NotificationActionTypes.DismissAlert: { const keyToRemove = action.payload.key; const newAlerts = state.alerts.filter(({ key }) => key !== keyToRemove); return { ...state, alerts: newAlerts }; diff --git a/src/app/degree-planner/alert-container/alert-container.component.html b/src/app/shared/components/alert-container/alert-container.component.html similarity index 100% rename from src/app/degree-planner/alert-container/alert-container.component.html rename to src/app/shared/components/alert-container/alert-container.component.html diff --git a/src/app/degree-planner/alert-container/alert-container.component.scss b/src/app/shared/components/alert-container/alert-container.component.scss similarity index 100% rename from src/app/degree-planner/alert-container/alert-container.component.scss rename to src/app/shared/components/alert-container/alert-container.component.scss diff --git a/src/app/degree-planner/alert-container/alert-container.component.ts b/src/app/shared/components/alert-container/alert-container.component.ts similarity index 93% rename from src/app/degree-planner/alert-container/alert-container.component.ts rename to src/app/shared/components/alert-container/alert-container.component.ts index 8eabe02..53ed031 100644 --- a/src/app/degree-planner/alert-container/alert-container.component.ts +++ b/src/app/shared/components/alert-container/alert-container.component.ts @@ -4,7 +4,7 @@ import { GlobalState } from '@app/core/state'; import * as selectors from '@app/degree-planner/store/selectors'; import { Alert } from '@app/core/models/alert'; import { Observable } from 'rxjs'; -import { DismissAlert } from '../store/actions/ui.actions'; +import { DismissAlert } from '@app/core/actions'; @Component({ selector: 'cse-alert-container', diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index aeb5f72..b877a58 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -1,3 +1,4 @@ +import { AlertContainerComponent } from './components/alert-container/alert-container.component'; import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; @@ -85,7 +86,13 @@ const directives = [ClickStopPropagationDirective]; @NgModule({ imports: [modules], - exports: [modules, pipes, directives, CourseDetailsComponent], + exports: [ + modules, + pipes, + directives, + CourseDetailsComponent, + AlertContainerComponent, + ], entryComponents: [ConfirmDialogComponent, PromptDialogComponent], declarations: [ pipes, @@ -97,6 +104,7 @@ const directives = [ClickStopPropagationDirective]; IE11WarningDialogComponent, ConfirmDialogComponent, PromptDialogComponent, + AlertContainerComponent, ], }) export class SharedModule {} diff --git a/src/assets/mock-data/metadata-response.json b/src/assets/mock-data/metadata-response.json new file mode 100644 index 0000000..9c59547 --- /dev/null +++ b/src/assets/mock-data/metadata-response.json @@ -0,0 +1,17 @@ +[ + { + "darsJobId": "abc123", + "darsAuditRunDate": "2019-02-04T20:41:31Z", + "sisEmplId": "string", + "darsInstitutionCode": "L&S", + "darsInstitutionCodeDescription": "Letters & Science, College of", + "darsDegreeProgramCode": "BA 916", + "darsStatusOfDegreeAuditRequest": "new", + "darsHonorsOptionCode": "Z", + "darsHonorsOptionDescription": "Omit Major, Include Liberal Arts", + "darsDegreeAuditReportId": 0, + "darsCatalogYearTerm": "20121", + "whichEnrolledCoursesIncluded": "previous", + "degreePlannerPlanName": "string" + } +] -- GitLab