From 39473db098c7049ff8e69edc7d2f7bc77d60f859 Mon Sep 17 00:00:00 2001 From: Paulina Nogal <pnogal@wisc.edu> Date: Wed, 20 Feb 2019 21:45:27 +0000 Subject: [PATCH] Plan settings menu reorder --- .../degree-planner.component.html | 115 ++++++++++++---- .../degree-planner.component.ts | 49 +++---- .../degree-planner/degree-planner.module.ts | 8 +- .../modify-plan-dialog.component.ts | 53 -------- ...emove-course-confirm-dialog.component.scss | 5 - .../sidenav-menu-item.component.html | 125 ++++++++++++------ .../sidenav-menu-item.component.ts | 39 ++++-- .../store/actions/plan.actions.ts | 2 +- .../store/effects/plan.effects.ts | 21 ++- src/app/degree-planner/store/reducer.ts | 10 +- .../confirm-dialog.component.html | 48 +++++-- .../confirm-dialog.component.ts | 2 +- src/app/shared/dialogs/dialogs.scss | 11 ++ .../prompt-dialog.component.html | 66 ++++++--- .../prompt-dialog.component.scss | 3 + .../prompt-dialog/prompt-dialog.component.ts | 12 +- 16 files changed, 363 insertions(+), 206 deletions(-) delete mode 100644 src/app/degree-planner/dialogs/modify-plan-dialog/modify-plan-dialog.component.ts create mode 100644 src/app/shared/dialogs/prompt-dialog/prompt-dialog.component.scss diff --git a/src/app/degree-planner/degree-planner.component.html b/src/app/degree-planner/degree-planner.component.html index 9935587..7205e64 100644 --- a/src/app/degree-planner/degree-planner.component.html +++ b/src/app/degree-planner/degree-planner.component.html @@ -1,23 +1,49 @@ <mat-sidenav-container hasBackdrop="false"> - <mat-sidenav #addMenu position="end" mode="over" [opened]="isCourseSearchOpen$ | async"> + <mat-sidenav + #addMenu + position="end" + mode="over" + [opened]="isCourseSearchOpen$ | async" + > <mat-toolbar color="primary" class="dialog-toolbar"> <span class="dialog-toolbar-title">Course Search</span> - <button mat-button class="close-btn" (click)="closeCourseSearch();"><i class="material-icons">keyboard_arrow_right</i></button> + <button mat-button class="close-btn" (click)="closeCourseSearch()"> + <i class="material-icons">keyboard_arrow_right</i> + </button> </mat-toolbar> <cse-course-search></cse-course-search> </mat-sidenav> <mat-sidenav-content> - <mat-progress-bar id="loading-plan-progress" mode="indeterminate" *ngIf="isLoadingPlan$ | async"></mat-progress-bar> + <mat-progress-bar + id="loading-plan-progress" + mode="indeterminate" + *ngIf="(isLoadingPlan$ | async)" + ></mat-progress-bar> <mat-sidenav-container id="plans-container"> <!-- Menu side nav --> - <mat-sidenav #rightMenu position="end" [mode]="mobileView.matches ? 'over' : 'side'" [opened]="mobileView.matches ? false : true"> + <mat-sidenav + #rightMenu + position="end" + [mode]="mobileView.matches ? 'over' : 'side'" + [opened]="mobileView.matches ? false : true" + > <cse-sidenav-menu-item></cse-sidenav-menu-item> </mat-sidenav> - <mat-sidenav-content id="degree-plan-wrapper" [ngClass]="{ isLoadingPlan: (isLoadingPlan$ | async) }" *ngIf="(degreePlan$ | async) as degreePlan"> - <div fxLayout="row" fxLayout.lt-sm="column" fxLayoutGap="20px" fxLayoutAlign="start center" style="margin: 24px 0px 24px 24px;"> + <mat-sidenav-content + id="degree-plan-wrapper" + [ngClass]="{ isLoadingPlan: isLoadingPlan$ | async }" + *ngIf="(degreePlan$ | async) as degreePlan" + > + <div + fxLayout="row" + fxLayout.lt-sm="column" + fxLayoutGap="20px" + fxLayoutAlign="start center" + style="margin: 24px 0px 24px 24px;" + > <mat-form-field> <mat-select [disabled]="isLoadingPlan$ | async" @@ -25,46 +51,83 @@ class="degree-plan-selector" [value]="degreePlan.roadmapId" [disableOptionCentering]="true" - (selectionChange)="handleDegreePlanChange($event)"> - + (selectionChange)="handleDegreePlanChange($event)" + > <!-- Render the name of the currently visible degree plan. --> <mat-select-trigger> - <mat-icon class="primary-star" *ngIf="degreePlan.primary">star_rate</mat-icon> - <span class="plan-name">{{degreePlan.name}}</span> + <mat-icon class="primary-star" *ngIf="degreePlan.primary" + >star_rate</mat-icon + > + <span class="plan-name">{{ degreePlan.name }}</span> </mat-select-trigger> <!-- Show all degree plans in the dropdown list and ddd a star next to the user's primary plan. --> - <mat-option *ngFor="let degreePlan of (allDegreePlans$ | async)" [value]="degreePlan.roadmapId"> - <mat-icon class="primary-star" *ngIf="degreePlan.primary">star_rate</mat-icon> - <span class="plan-name">{{degreePlan.name}}</span> + <mat-option + *ngFor="let degreePlan of (allDegreePlans$ | async)" + [value]="degreePlan.roadmapId" + > + <mat-icon class="primary-star" *ngIf="degreePlan.primary" + >star_rate</mat-icon + > + <span class="plan-name">{{ degreePlan.name }}</span> </mat-option> - </mat-select> </mat-form-field> - <button mat-icon-button [matMenuTriggerFor]="degreePlanMenu" [disabled]="isLoadingPlan$ | async"> - <mat-icon>settings</mat-icon> + <button + mat-icon-button + [matMenuTriggerFor]="degreePlanMenu" + [disabled]="isLoadingPlan$ | async" + > + <mat-icon matTooltip="Plan settings" matTooltipPosition="right" + >settings</mat-icon + > </button> <mat-menu #degreePlanMenu="matMenu"> - <button mat-menu-item (click)="onCreatePlanClick()">Create new plan</button> - <button mat-menu-item (click)="onRenamePlanClick(degreePlan)">Rename plan</button> - <button mat-menu-item (click)="onDeletePlanClick(degreePlan)" [disabled]="degreePlan.primary">Delete plan</button> - <button mat-menu-item (click)="onMakePrimayClick(degreePlan)" [disabled]="degreePlan.primary">Make primary</button> - <hr> - <button mat-menu-item (click)="onPrintPlanClick()">Print plan</button> - <button mat-menu-item (click)="onSharePlanClick()">Share plan</button> + <button mat-menu-item (click)="onRenamePlanClick(degreePlan)"> + Rename plan + </button> + <button + mat-menu-item + (click)="onMakePrimayClick(degreePlan)" + [disabled]="degreePlan.primary" + > + Make primary + </button> + <button mat-menu-item (click)="onPrintPlanClick()"> + Print plan + </button> + <button mat-menu-item> + Download PDF + </button> + <button + mat-menu-item + (click)="onDeletePlanClick(degreePlan)" + [disabled]="degreePlan.primary" + > + Delete plan + </button> + <hr /> + <button mat-menu-item (click)="onCreatePlanClick()"> + Add degree plan + </button> </mat-menu> </div> - <div id="year-wrapper" fxLayout="column" fxLayoutGap="20px" fxLayoutAlign="start stretch" style="margin: 24px"> - <div id="year-mask" *ngIf="isLoadingPlan$ | async"></div> + <div + id="year-wrapper" + fxLayout="column" + fxLayoutGap="20px" + fxLayoutAlign="start stretch" + style="margin: 24px" + > + <div id="year-mask" *ngIf="(isLoadingPlan$ | async)"></div> <mat-accordion multi="true"> <ng-container *ngFor="let yearCode of (yearCodes$ | async)"> <cse-year-container [yearCode]="yearCode"></cse-year-container> </ng-container> </mat-accordion> </div> - </mat-sidenav-content> </mat-sidenav-container> </mat-sidenav-content> diff --git a/src/app/degree-planner/degree-planner.component.ts b/src/app/degree-planner/degree-planner.component.ts index 747a889..4db1008 100644 --- a/src/app/degree-planner/degree-planner.component.ts +++ b/src/app/degree-planner/degree-planner.component.ts @@ -1,4 +1,3 @@ -import { ConfirmDialogComponent } from '@app/shared/dialogs/confirm-dialog/confirm-dialog.component'; import { filter, map, @@ -28,13 +27,12 @@ import { ChangePlanName, DeletePlan, } from '@app/degree-planner/store/actions/plan.actions'; - -import { - ModifyPlanDialogComponent, - DialogMode, -} from './dialogs/modify-plan-dialog/modify-plan-dialog.component'; import { PromptDialogComponent } from '@app/shared/dialogs/prompt-dialog/prompt-dialog.component'; -import { CloseCourseSearch } from './store/actions/ui.actions'; +import { ConfirmDialogComponent } from '@app/shared/dialogs/confirm-dialog/confirm-dialog.component'; +import { + ToggleAcademicYear, + CloseCourseSearch, +} from './store/actions/ui.actions'; @Component({ selector: 'cse-degree-planner', @@ -100,26 +98,31 @@ export class DegreePlannerComponent implements OnInit { } public onCreatePlanClick() { - const data: DialogMode = { mode: 'create' }; this.dialog - .open(ModifyPlanDialogComponent, { data }) + .open(PromptDialogComponent, { + data: { + initialValue: name, + title: 'Add degree plan', + confirmText: 'Save', + inputName: 'i.e. Psychology', + }, + }) .afterClosed() - .subscribe((result: { name: string } | undefined) => { - if (result !== undefined && typeof result.name === 'string') { - const name = result.name; - const action = new CreatePlan({ name, primary: false }); + .subscribe((result: { confirmed: boolean; value: string }) => { + const { confirmed, value } = result; + if (confirmed) { + const action = new CreatePlan({ name: value, primary: false }); this.store.dispatch(action); } }); } public onRenamePlanClick(currentPlan: DegreePlan) { - // const data: DialogMode = { mode: 'rename', oldName: currentPlan.name }; this.dialog .open(PromptDialogComponent, { data: { - initalValue: currentPlan.name, - title: 'Rename Degree Plan', + initialValue: currentPlan.name, + title: 'Rename plan', confirmText: 'Save', inputName: 'Plan name', }, @@ -127,7 +130,6 @@ export class DegreePlannerComponent implements OnInit { .afterClosed() .subscribe((result: { confirmed: boolean; value: string }) => { const { confirmed, value } = result; - if (confirmed) { const { roadmapId } = currentPlan; const action = new ChangePlanName({ roadmapId, newName: value }); @@ -136,13 +138,14 @@ export class DegreePlannerComponent implements OnInit { }); } - public onMakePrimayClick(_currentPlan: DegreePlan) { - const data: DialogMode = { mode: 'makePrimary' }; + public onMakePrimayClick(currentPlan: DegreePlan) { this.dialog .open(ConfirmDialogComponent, { data: { + title: 'Are you sure?', + confirmText: 'Change plan', text: - "This will change your primary plan and replace the current courses in your cart with the courses in this plan's term.", + "This will change your primary plan and replace the current courses in your cart with the courses in this plan's active term", }, }) .afterClosed() @@ -159,11 +162,11 @@ export class DegreePlannerComponent implements OnInit { this.snackBar.open('The primary degree plan cannot be deleted'); return; } - - const data: DialogMode = { mode: 'delete', name: currentPlan.name }; this.dialog .open(ConfirmDialogComponent, { data: { + title: 'Are you sure?', + confirmText: 'Delete', text: 'This will delete this plan and course information related to this plan.', }, @@ -171,7 +174,7 @@ export class DegreePlannerComponent implements OnInit { .afterClosed() .pipe(withLatestFrom(this.store)) .subscribe(([result, state]) => { - if (result.confirmed) { + if (typeof result === 'object' && result.confirmed === true) { const { roadmapId } = currentPlan; const deleteAction = new DeletePlan({ roadmapId }); this.store.dispatch(deleteAction); diff --git a/src/app/degree-planner/degree-planner.module.ts b/src/app/degree-planner/degree-planner.module.ts index c38fd13..583c507 100644 --- a/src/app/degree-planner/degree-planner.module.ts +++ b/src/app/degree-planner/degree-planner.module.ts @@ -10,7 +10,6 @@ import { CourseItemComponent } from './shared/course-item/course-item.component' import { NotesDialogComponent } from './dialogs/notes-dialog/notes-dialog.component'; import { DragDropModule } from '@angular/cdk/drag-drop'; import { RemoveCourseConfirmDialogComponent } from './dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component'; -import { ModifyPlanDialogComponent } from './dialogs/modify-plan-dialog/modify-plan-dialog.component'; import { YearContainerComponent } from '@app/degree-planner/year-container/year-container.component'; import { CourseSearchComponent } from '@app/degree-planner/course-search/course-search.component'; @@ -25,14 +24,9 @@ import { CourseSearchComponent } from '@app/degree-planner/course-search/course- SavedForLaterContainerComponent, NotesDialogComponent, RemoveCourseConfirmDialogComponent, - ModifyPlanDialogComponent, YearContainerComponent, CourseSearchComponent, ], - entryComponents: [ - NotesDialogComponent, - RemoveCourseConfirmDialogComponent, - ModifyPlanDialogComponent, - ], + entryComponents: [NotesDialogComponent, RemoveCourseConfirmDialogComponent], }) export class DegreePlannerModule {} 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 deleted file mode 100644 index bcc0321..0000000 --- a/src/app/degree-planner/dialogs/modify-plan-dialog/modify-plan-dialog.component.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { FormGroup, FormControl, Validators } from '@angular/forms'; -import { Component, Input, Inject } from '@angular/core'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; - -export type DialogMode = - | { mode: 'makePrimary' } - | { mode: 'delete'; name: string } - | { mode: 'rename'; oldName: string } - | { mode: 'create' }; - -@Component({ - selector: 'cse-course-details-dialog', - templateUrl: './modify-plan-dialog.component.html', -}) -export class ModifyPlanDialogComponent { - public form: FormGroup; - - constructor( - private dialogRef: MatDialogRef<ModifyPlanDialogComponent>, - @Inject(MAT_DIALOG_DATA) public data: DialogMode, - ) { - const initialName = this.data.mode === 'rename' ? this.data.oldName : ''; - if (this.data.mode === 'rename' || this.data.mode === 'create') { - this.form = new FormGroup({ - planName: new FormControl(initialName, Validators.required), - }); - } else { - this.form = new FormGroup({}); - } - } - - onSubmit() { - switch (this.data.mode) { - case 'makePrimary': - case 'delete': { - this.dialogRef.close({ areYouSure: true }); - break; - } - case 'rename': - case 'create': { - const name = `${this.form.value.planName}`; - this.dialogRef.close({ name }); - break; - } - default: - this.dialogRef.close(); - } - } - - onCancel() { - this.dialogRef.close(); - } -} diff --git a/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.scss b/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.scss index 9a4c055..e69de29 100644 --- a/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.scss +++ b/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.scss @@ -1,5 +0,0 @@ -.dialog-text { - color: #7e7e7e; - font-size: 16px; - margin-top: 1.2em; -} diff --git a/src/app/degree-planner/sidenav-menu-item/sidenav-menu-item.component.html b/src/app/degree-planner/sidenav-menu-item/sidenav-menu-item.component.html index 8c8b15e..d283b6c 100644 --- a/src/app/degree-planner/sidenav-menu-item/sidenav-menu-item.component.html +++ b/src/app/degree-planner/sidenav-menu-item/sidenav-menu-item.component.html @@ -1,46 +1,85 @@ <div id="sidenav-container" fxLayout="column" fxLayout.sm="column"> - <mat-expansion-panel id="course-keys-container" expanded="true"> - <mat-expansion-panel-header> - <mat-panel-title> - <h3>Course Key</h3> - </mat-panel-title> - </mat-expansion-panel-header> - <ul id="course-key-list"> - <li><i class="material-icons in-progress-icon" matTooltip="Course in progress" matTooltipPosition="left">check_circle</i> Course is currently in progress</li> - <li><i class="material-icons problem-icon" matTooltip="Course is waitlisted" matTooltipPosition="left">report_problem</i> Course is waitlisted</li> - <li><i class="material-icons error-icon" matTooltip="Course is incomplete" matTooltipPosition="left">error</i> Course is incomplete</li> - </ul> - </mat-expansion-panel> - <mat-expansion-panel id="course-keys-container" expanded="true"> - <mat-expansion-panel-header> - <mat-panel-title> - <h3>Saved for later</h3> - </mat-panel-title> - </mat-expansion-panel-header> - <cse-saved-for-later-container></cse-saved-for-later-container> - </mat-expansion-panel> + <mat-expansion-panel id="course-keys-container" expanded="true"> + <mat-expansion-panel-header> + <mat-panel-title> + <h3>Course Key</h3> + </mat-panel-title> + </mat-expansion-panel-header> + <ul id="course-key-list"> + <li> + <i + class="material-icons in-progress-icon" + matTooltip="Course in progress" + matTooltipPosition="left" + >check_circle</i + > + Course is currently in progress + </li> + <li> + <i + class="material-icons problem-icon" + matTooltip="Course is waitlisted" + matTooltipPosition="left" + >report_problem</i + > + Course is waitlisted + </li> + <li> + <i + class="material-icons error-icon" + matTooltip="Course is incomplete" + matTooltipPosition="left" + >error</i + > + Course is incomplete + </li> + </ul> + </mat-expansion-panel> + <mat-expansion-panel id="course-keys-container" expanded="true"> + <mat-expansion-panel-header> + <mat-panel-title> + <h3>Saved for later</h3> + </mat-panel-title> + </mat-expansion-panel-header> + <cse-saved-for-later-container></cse-saved-for-later-container> + </mat-expansion-panel> - <mat-expansion-panel id="menu-items-container" expanded="true"> - <mat-expansion-panel-header> - <mat-panel-title> - <h3>Menu</h3> - </mat-panel-title> - </mat-expansion-panel-header> - <div> - <button mat-button class="sidenav-link-btn"><i class="material-icons">print</i> Print</button> - <button mat-button class="sidenav-link-btn"> - <svg class="material-icons" style="width:24px;height:24px" viewBox="0 0 24 24"> - <path fill="#0479a8" d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" /> - </svg> - Download PDF - </button> - <button mat-button class="sidenav-link-btn" (click)="addDegreePlan()"><i class="material-icons">add_box</i> Add Degree Plan</button> - <button mat-button class="sidenav-link-btn" (click)="addAcademicYear()"> - <svg class="material-icons" style="width:24px;height:24px" viewBox="0 0 24 24"> - <path fill="#0479a8" d="M19,19V7H5V19H19M16,1H18V3H19A2,2 0 0,1 21,5V19A2,2 0 0,1 19,21H5C3.89,21 3,20.1 3,19V5C3,3.89 3.89,3 5,3H6V1H8V3H16V1M11,9H13V12H16V14H13V17H11V14H8V12H11V9Z" /> - </svg> - Add Academic Year - </button> - </div> - </mat-expansion-panel> + <mat-expansion-panel id="menu-items-container" expanded="true"> + <mat-expansion-panel-header> + <mat-panel-title> + <h3>Menu</h3> + </mat-panel-title> + </mat-expansion-panel-header> + <div> + <button mat-button class="sidenav-link-btn"> + <i class="material-icons">print</i> Print + </button> + <button mat-button class="sidenav-link-btn"> + <svg + class="material-icons" + style="width:24px;height:24px" + viewBox="0 0 24 24" + > + <path fill="#0479a8" d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" /> + </svg> + Download PDF + </button> + <button mat-button class="sidenav-link-btn" (click)="onCreatePlanClick()"> + <i class="material-icons">add_box</i> Add Degree Plan + </button> + <button mat-button class="sidenav-link-btn" (click)="onAddAcademicYear()"> + <svg + class="material-icons" + style="width:24px;height:24px" + viewBox="0 0 24 24" + > + <path + fill="#0479a8" + d="M19,19V7H5V19H19M16,1H18V3H19A2,2 0 0,1 21,5V19A2,2 0 0,1 19,21H5C3.89,21 3,20.1 3,19V5C3,3.89 3.89,3 5,3H6V1H8V3H16V1M11,9H13V12H16V14H13V17H11V14H8V12H11V9Z" + /> + </svg> + Add Academic Year + </button> + </div> + </mat-expansion-panel> </div> diff --git a/src/app/degree-planner/sidenav-menu-item/sidenav-menu-item.component.ts b/src/app/degree-planner/sidenav-menu-item/sidenav-menu-item.component.ts index 6fa1ed9..bec51a4 100644 --- a/src/app/degree-planner/sidenav-menu-item/sidenav-menu-item.component.ts +++ b/src/app/degree-planner/sidenav-menu-item/sidenav-menu-item.component.ts @@ -2,14 +2,14 @@ import { Component } from '@angular/core'; import { Store } from '@ngrx/store'; import { MatDialog } from '@angular/material'; +import { FormGroup } from '@angular/forms'; +import { MatSnackBar } from '@angular/material'; +import { Observable } from 'rxjs'; // State management import { GlobalState } from '@app/core/state'; import { AddAcademicYearRequest } from '@app/degree-planner/store/actions/addAcademicYear.actions'; -import { - ModifyPlanDialogComponent, - DialogMode, -} from '@app/degree-planner/dialogs/modify-plan-dialog/modify-plan-dialog.component'; +import { PromptDialogComponent } from '@app/shared/dialogs/prompt-dialog/prompt-dialog.component'; import { CreatePlan } from '@app/degree-planner/store/actions/plan.actions'; @Component({ @@ -18,21 +18,34 @@ import { CreatePlan } from '@app/degree-planner/store/actions/plan.actions'; styleUrls: ['./sidenav-menu-item.component.scss'], }) export class SidenavMenuItemComponent { - constructor(private store: Store<GlobalState>, public dialog: MatDialog) {} + public inputForm: FormGroup; + public yearCodes$: Observable<string[]>; + constructor( + private store: Store<GlobalState>, + public dialog: MatDialog, + private snackBar: MatSnackBar, + ) {} - public addAcademicYear() { + public onAddAcademicYear() { this.store.dispatch(new AddAcademicYearRequest()); + this.snackBar.open('New academic year has been created'); } - public addDegreePlan() { - const data: DialogMode = { mode: 'create' }; + public onCreatePlanClick() { this.dialog - .open(ModifyPlanDialogComponent, { data }) + .open(PromptDialogComponent, { + data: { + initialValue: name, + title: 'Add degree plan', + confirmText: 'Save', + inputName: 'i.e. Psychology', + }, + }) .afterClosed() - .subscribe((result: { name: string } | undefined) => { - if (result !== undefined && typeof result.name === 'string') { - const name = result.name; - const action = new CreatePlan({ name, primary: false }); + .subscribe((result: { confirmed: boolean; value: string }) => { + const { confirmed, value } = result; + if (confirmed) { + const action = new CreatePlan({ name: value, primary: false }); this.store.dispatch(action); } }); diff --git a/src/app/degree-planner/store/actions/plan.actions.ts b/src/app/degree-planner/store/actions/plan.actions.ts index 4486af1..6037632 100644 --- a/src/app/degree-planner/store/actions/plan.actions.ts +++ b/src/app/degree-planner/store/actions/plan.actions.ts @@ -54,7 +54,7 @@ export class CreatePlan implements Action { export class CreatePlanSuccess implements Action { public readonly type = PlanActionTypes.CreatePlanSuccess; - constructor(public payload: { newPlan: DegreePlan }) {} + constructor(public payload: { newPlan: DegreePlan; newYears: YearMapping }) {} } export class DeletePlan 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 821e5f6..b6a601d 100644 --- a/src/app/degree-planner/store/effects/plan.effects.ts +++ b/src/app/degree-planner/store/effects/plan.effects.ts @@ -240,10 +240,27 @@ export class DegreePlanEffects { @Effect() createPlan$ = this.actions$.pipe( ofType<CreatePlan>(PlanActionTypes.CreatePlan), - flatMap(action => { + withLatestFrom(this.store$.select(selectors.selectSubjects)), + withLatestFrom(this.store$.select(selectors.selectActiveTermCodes)), + flatMap(([[action, subjects], activeTermCodes]) => { const { name, primary } = action.payload; return this.api.createDegreePlan(name, primary).pipe( - map(newPlan => new CreatePlanSuccess({ newPlan })), + flatMap(newPlan => { + const newYears = loadPlanYears( + this.api, + newPlan.roadmapId, + subjects, + activeTermCodes, + ); + + return forkJoinWithKeys({ + newPlan: of(newPlan), + newYears, + }); + }), + map(({ newPlan, newYears }) => { + return new CreatePlanSuccess({ newPlan, newYears }); + }), tap(() => { const message = `New plan has been created`; this.snackBar.open(message, undefined, { duration: 2000 }); diff --git a/src/app/degree-planner/store/reducer.ts b/src/app/degree-planner/store/reducer.ts index 9fa1c24..162fe78 100644 --- a/src/app/degree-planner/store/reducer.ts +++ b/src/app/degree-planner/store/reducer.ts @@ -14,6 +14,7 @@ import { MakePlanPrimaryFailure, ChangePlanNameSuccess, ChangePlanNameFailure, + CreatePlan, CreatePlanSuccess, DeletePlanSuccess, PlanError, @@ -67,6 +68,7 @@ type SupportedActions = | RemoveSaveForLater | AddSaveForLater | AddAcademicYearRequest + | CreatePlan | CreatePlanSuccess | MakePlanPrimary | MakePlanPrimarySuccess @@ -90,6 +92,9 @@ export function degreePlannerReducer( return { ...state, isLoadingPlan: false }; } + case PlanActionTypes.CreatePlan: { + return { ...state, isLoadingPlan: true }; + } /** * The `InitialPlanLoadResponse` action is triggered on initial Degree * Planner app load. It downloads a list of the user's degree plans and @@ -405,10 +410,13 @@ export function degreePlannerReducer( } case PlanActionTypes.CreatePlanSuccess: { - const { newPlan } = action.payload; + const { newPlan, newYears } = action.payload; return { ...state, + visibleDegreePlan: newPlan, + visibleYears: newYears, allDegreePlans: state.allDegreePlans.concat(newPlan), + isLoadingPlan: false, }; } diff --git a/src/app/shared/dialogs/confirm-dialog/confirm-dialog.component.html b/src/app/shared/dialogs/confirm-dialog/confirm-dialog.component.html index 1728d95..13e3bbe 100644 --- a/src/app/shared/dialogs/confirm-dialog/confirm-dialog.component.html +++ b/src/app/shared/dialogs/confirm-dialog/confirm-dialog.component.html @@ -1,10 +1,38 @@ -<div id="confirmation-dialog" class="mat-dialog-content mat-typography"> - <h1 mat-dialog-title>{{title}}</h1> - <mat-dialog-content> - <p class="dialog-text" *ngFor="let line of text">{{line}}</p> - </mat-dialog-content> - <mat-dialog-actions align="end"> - <button mat-button (click)="cancel()" aria-label="Cancel">{{cancelText}}</button> - <button mat-button [color]="confirmColor" class="mat-button" mat-raised-button (click)="confirm()" aria-label="Confirm">{{confirmText}}</button> - </mat-dialog-actions> -</div> \ No newline at end of file +<mat-toolbar class="dialog-toolbar"> + <h1 class="dialog-toolbar-title">{{ title }}</h1> + <button + mat-button + mat-dialog-close + class="close-btn" + aria-label="Close note dialog" + > + <i class="material-icons">clear</i> + </button> +</mat-toolbar> +<mat-dialog-content + id="confirmation-dialog" + class="mat-typography dialog-with-toolbar" +> + <mat-dialog-content> + <p class="dialog-text" *ngFor="let line of text">{{ line }}</p> + </mat-dialog-content> + <mat-dialog-actions align="end"> + <button + class="confirm-button" + mat-button + (click)="cancel()" + aria-label="Cancel" + > + {{ cancelText }} + </button> + <button + mat-button + class="confirm-button" + mat-raised-button + (click)="confirm()" + aria-label="Confirm" + > + {{ confirmText }} + </button> + </mat-dialog-actions> +</mat-dialog-content> diff --git a/src/app/shared/dialogs/confirm-dialog/confirm-dialog.component.ts b/src/app/shared/dialogs/confirm-dialog/confirm-dialog.component.ts index aca338b..fe708a9 100644 --- a/src/app/shared/dialogs/confirm-dialog/confirm-dialog.component.ts +++ b/src/app/shared/dialogs/confirm-dialog/confirm-dialog.component.ts @@ -19,7 +19,7 @@ export class ConfirmDialogComponent { ) { const { title = 'Are you sure?', - text = 'Are you sure you want to do this?', + text = '', cancelText = 'Cancel', confirmText = 'Confirm', confirmColor = 'primary', diff --git a/src/app/shared/dialogs/dialogs.scss b/src/app/shared/dialogs/dialogs.scss index 27d1b9b..451dc71 100644 --- a/src/app/shared/dialogs/dialogs.scss +++ b/src/app/shared/dialogs/dialogs.scss @@ -7,3 +7,14 @@ margin: 0; width: 400px; } + +.confirm-button { + box-shadow: none; + text-transform: uppercase; + color: #0479a8; +} + +.mat-button, +button.mat-primary { + text-transform: uppercase; +} diff --git a/src/app/shared/dialogs/prompt-dialog/prompt-dialog.component.html b/src/app/shared/dialogs/prompt-dialog/prompt-dialog.component.html index 492a7ea..be5e533 100644 --- a/src/app/shared/dialogs/prompt-dialog/prompt-dialog.component.html +++ b/src/app/shared/dialogs/prompt-dialog/prompt-dialog.component.html @@ -1,19 +1,53 @@ <mat-toolbar color="primary" class="dialog-toolbar"> - <h1 class="dialog-toolbar-title">{{title}}</h1> - <button mat-button mat-dialog-close class="close-btn" aria-label="Close note dialog"><i class="material-icons">clear</i></button> + <h1 class="dialog-toolbar-title">{{ title }}</h1> + <button + mat-button + mat-dialog-close + class="close-btn" + aria-label="Close dialog" + > + <i class="material-icons">clear</i> + </button> </mat-toolbar> -<mat-dialog-content id="confirmation-dialog" class="mat-typography dialog-with-toolbar"> - <mat-dialog-content> - <p class="dialog-text" *ngFor="let line of text">{{line}}</p> +<mat-dialog-content + id="confirmation-dialog" + class="mat-typography dialog-with-toolbar" +> + <mat-dialog-content> + <p class="dialog-text" *ngFor="let line of text">{{ line }}</p> - <form [formGroup]='inputForm' (ngSubmit)="confirm()" fxLayout="column" fxLayoutAlign="space-around none" style="padding: 12px 22px;"> - <mat-form-field> - <input matInput [placeholder]="inputName" formControlName="value"> - </mat-form-field> - </form> - </mat-dialog-content> - <mat-dialog-actions align="end"> - <button mat-button class="btn-secondary" (click)="cancel()" aria-label="Cancel">{{cancelText}}</button> - <button mat-button class="btn-primary mat-button" mat-raised-button (click)="confirm()" aria-label="Confirm">{{confirmText}}</button> - </mat-dialog-actions> -</mat-dialog-content> \ No newline at end of file + <form + [formGroup]="inputForm" + (ngSubmit)="confirm()" + fxLayout="column" + fxLayoutAlign="space-around none" + style="padding: 12px 22px;" + > + <mat-form-field> + <input matInput [placeholder]="inputName" formControlName="value" /> + </mat-form-field> + </form> + </mat-dialog-content> + <mat-dialog-actions align="end"> + <button + mat-button + class="btn-secondary mat-button" + (click)="cancel()" + aria-label="Cancel" + > + {{ cancelText }} + </button> + <button + mat-buttondialogs + with + differe + [color]="confirmColor" + mat-raised-button + (click)="confirm()" + aria-label="Confirm" + [disabled]="inputForm.invalid" + > + {{ confirmText }} + </button> + </mat-dialog-actions> +</mat-dialog-content> diff --git a/src/app/shared/dialogs/prompt-dialog/prompt-dialog.component.scss b/src/app/shared/dialogs/prompt-dialog/prompt-dialog.component.scss new file mode 100644 index 0000000..d602688 --- /dev/null +++ b/src/app/shared/dialogs/prompt-dialog/prompt-dialog.component.scss @@ -0,0 +1,3 @@ +.mat-dialog-content { + padding: 30px 24px 6px 24px !important; +} diff --git a/src/app/shared/dialogs/prompt-dialog/prompt-dialog.component.ts b/src/app/shared/dialogs/prompt-dialog/prompt-dialog.component.ts index c049e41..6a250e2 100644 --- a/src/app/shared/dialogs/prompt-dialog/prompt-dialog.component.ts +++ b/src/app/shared/dialogs/prompt-dialog/prompt-dialog.component.ts @@ -8,6 +8,8 @@ import { FormControl, Validators, } from '@angular/forms'; +import { Observable } from 'rxjs'; +import { Year } from '@app/core/models/year'; @Component({ selector: 'cse-prompt-dialog', @@ -23,10 +25,10 @@ export class PromptDialogComponent implements OnInit { cancelText: string; confirmText: string; confirmColor: string; + public termsByYear$: Observable<Year[]>; inputForm: FormGroup; - initalValue: string; - + initialValue: string; constructor( private dialogRef: MatDialogRef<PromptDialogComponent>, private fb: FormBuilder, @@ -36,7 +38,7 @@ export class PromptDialogComponent implements OnInit { title = 'User Input Required', text = [], inputName = 'Data', - initalValue = '', + initialValue = '', placeholder, tooltip, cancelText = 'Cancel', @@ -52,7 +54,7 @@ export class PromptDialogComponent implements OnInit { this.cancelText = cancelText; this.confirmText = confirmText; this.confirmColor = confirmColor; - this.initalValue = initalValue; + this.initialValue = initialValue; if (typeof text === 'string') { this.text = [text]; @@ -62,7 +64,7 @@ export class PromptDialogComponent implements OnInit { ngOnInit() { // Deafults for input form this.inputForm = this.fb.group({ - value: this.initalValue, + value: [this.initialValue, Validators.required], }); } -- GitLab