From 839a2b1475f7dd75c60c257a62c2cb28da598010 Mon Sep 17 00:00:00 2001 From: Paulina Nogal <pnogal@wisc.edu> Date: Mon, 18 Mar 2019 13:51:31 +0000 Subject: [PATCH] Roenroll 1443 accessibility fixes --- src/app/app.module.ts | 2 + src/app/core/header/header.component.html | 12 +- .../course-search.component.html | 153 ++++++++---- .../degree-planner.component.html | 103 +++++--- .../degree-planner.component.ts | 2 +- .../course-details-dialog.component.ts | 8 +- .../modify-plan-dialog.component.html | 38 ++- .../notes-dialog/notes-dialog.component.html | 128 +++++----- ...emove-course-confirm-dialog.component.html | 54 +++- .../course-item/course-item.component.html | 81 ++++-- .../sidenav-menu-item.component.html | 89 ++++--- .../sidenav-menu-item.component.scss | 11 +- .../sidenav-menu-item.component.ts | 2 +- .../term-container.component.html | 220 +++++++++++------ .../year-container.component.html | 21 +- .../course-details.component.html | 233 ++++++++++++------ .../confirm-dialog.component.html | 32 ++- .../prompt-dialog.component.html | 27 +- .../shared/pipes/academic-year-state.pipe.ts | 6 +- src/app/shared/shared.module.ts | 4 + 20 files changed, 810 insertions(+), 416 deletions(-) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 5c556e5..1731946 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -5,6 +5,7 @@ import { HttpClientModule } from '@angular/common/http'; import { StoreModule } from '@ngrx/store'; import { StoreDevtoolsModule } from '@ngrx/store-devtools'; import { EffectsModule } from '@ngrx/effects'; +import { A11yModule } from '@angular/cdk/a11y'; import { AppRoutingModule } from './app.routing.module'; import { AppComponent } from './app.component'; @@ -37,6 +38,7 @@ import { CourseDetailsDialogComponent } from './degree-planner/dialogs/course-de SharedModule, AppRoutingModule, MatAutocompleteModule, + A11yModule, StoreDevtoolsModule.instrument({ maxAge: 5, }), diff --git a/src/app/core/header/header.component.html b/src/app/core/header/header.component.html index bdf5367..04da852 100644 --- a/src/app/core/header/header.component.html +++ b/src/app/core/header/header.component.html @@ -2,7 +2,6 @@ theme-name="" app-name="Course Search & Enroll" app-url="https://my.wisc.edu"> - <myuw-drawer slot="myuw-navigation" fxShow fxHide.gt-sm> <myuw-drawer-link slot="myuw-drawer-links" @@ -20,7 +19,7 @@ slot="myuw-drawer-links" name="Enrollment" icon="" - href="/enrollment"> + href="/my-courses"> </myuw-drawer-link> <myuw-drawer-link slot="myuw-drawer-links" @@ -34,6 +33,9 @@ slot="myuw-help" myuw-help-title="Need more help?" show-button + alt="Help icon" + matTooltip="Need help?" + matTooltipPosition="below" show-default-content> </myuw-help> @@ -45,6 +47,9 @@ <myuw-profile slot="myuw-profile" + alt="Profile icon" + matTooltip="Profile" + matTooltipPosition="below" session-endpoint="" login-url="" logout-url="http://login.wisc.edu/logout" @@ -54,7 +59,6 @@ <button id="myuw-three-dot" mat-icon-button [matMenuTriggerFor]="mobileActionMenu"> <mat-icon>more_horiz</mat-icon> </button> - </div> </myuw-app-bar> @@ -63,4 +67,4 @@ <button mat-menu-item (click)="downloadPdf()">Download PDF</button> <button mat-menu-item (click)="addPlan()">Add degree plan</button> <button mat-menu-item (click)="addYear()">Add academic year</button> -</mat-menu> +</mat-menu> \ No newline at end of file diff --git a/src/app/degree-planner/course-search/course-search.component.html b/src/app/degree-planner/course-search/course-search.component.html index 0df0024..e40f73c 100644 --- a/src/app/degree-planner/course-search/course-search.component.html +++ b/src/app/degree-planner/course-search/course-search.component.html @@ -1,58 +1,107 @@ -<form [formGroup]='courseSearchForm' (ngSubmit)="formSubmit()" class="add-course-form" fxLayout="column" fxLayoutAlign="space-around none" style="padding: 12px 22px;"> +<form + [formGroup]="courseSearchForm" + (ngSubmit)="formSubmit()" + class="add-course-form" + fxLayout="column" + fxLayoutAlign="space-around none" + style="padding: 12px 22px;"> + <mat-form-field> + <mat-select placeholder="Term" aria-label="Term" formControlName="term"> + <mat-option value="0000">All</mat-option> + <mat-option + *ngFor="let termCode of (activeTerms$ | async)" + [value]="termCode.toString()" + >{{ termCode | getTermDescription }}</mat-option> + </mat-select> + </mat-form-field> - <mat-form-field> - <mat-select placeholder="Term" aria-label="Term" formControlName="term"> - <mat-option value="0000">All</mat-option> - <mat-option *ngFor="let termCode of activeTerms$ | async" [value]="termCode.toString()">{{termCode | getTermDescription}}</mat-option> - </mat-select> - </mat-form-field> + <mat-form-field class="example-full-width"> + <input + type="text" + placeholder="Subject" + aria-label="Subject" + matInput + #subjectInput + formControlName="subject" + [matAutocomplete]="subject"/> + <mat-autocomplete + autoActiveFirstOption + #subject="matAutocomplete" + (optionSelected)="subjectChange($event, subjectInput)"> + <mat-option + *ngFor="let subject of filteredSubjects" + [value]="subject | titlecase" + >{{ subject | titlecase }}</mat-option> + </mat-autocomplete> + </mat-form-field> - <mat-form-field class="example-full-width"> - <input type="text" placeholder="Subject" aria-label="Subject" matInput #subjectInput formControlName="subject" [matAutocomplete]="subject"> - <mat-autocomplete autoActiveFirstOption #subject="matAutocomplete" (optionSelected)="subjectChange($event, subjectInput)"> - <mat-option *ngFor="let subject of filteredSubjects" [value]="subject | titlecase">{{subject | titlecase}}</mat-option> - </mat-autocomplete> - </mat-form-field> - - <mat-form-field> - <div class="search-input-wrapper"> - <input id="keyword-field" matInput placeholder="Keyword, number" formControlName="search" value=""> - <button id="search-button" mat-icon-button aria-label="Search" matSuffix style="margin-top: -10px;"><i class="material-icons">search</i></button> - </div> - </mat-form-field> - - </form> - <div *ngIf="hasResults || isLoading"> - <div class="search-results-toolbar mat-typography" fxLayout="row" fxLayoutAlign="space-between center" style="padding: 12px 22px; background-color: #EDF1F3; min-height: 60px;"> - <h3 *ngIf="isLoading" style="margin: 0px;">Searching for courses...</h3> - <h3 *ngIf="hasResults" style="margin: 0px;">{{queriedCourses.length}} result(s)</h3> - <button *ngIf="hasResults" mat-button (click)="resetSearchForm()">Reset Search</button> - </div> - <mat-progress-bar mode="indeterminate" *ngIf="isLoading"></mat-progress-bar> + <mat-form-field> + <div class="search-input-wrapper"> + <input + cdkFocusInitial + id="keyword-field" + matInput + placeholder="Keyword, number" + formControlName="search" + value=""/> + <button + id="search-button" + mat-icon-button + aria-label="Search" + matSuffix + style="margin-top: -10px;"> + <i class="material-icons" alt="Search icon">search</i> + </button> + </div> + </mat-form-field> +</form> +<div *ngIf="hasResults || isLoading"> + <div + class="search-results-toolbar mat-typography" + fxLayout="row" + fxLayoutAlign="space-between center" + style="padding: 12px 22px; background-color: #EDF1F3; min-height: 60px;"> + <h3 *ngIf="isLoading" style="margin: 0px;">Searching for courses...</h3> + <h3 *ngIf="hasResults" style="margin: 0px;"> + {{ queriedCourses.length }} result(s) + </h3> + <button *ngIf="hasResults" mat-button (click)="resetSearchForm()"> + Reset Search + </button> + </div> + <mat-progress-bar mode="indeterminate" *ngIf="isLoading"></mat-progress-bar> - <div id="course-search-results" fxLayout="column" fxLayoutAlign="space-around none" style="margin-top: 20px; padding: 12px 22px;"> - <div *ngIf="hasResults && queriedCourses.length === 0" class="mat-typography" style="text-align: center;"> - <img style="width: 50%;" src="../../assets/img/bucky-sad.svg" alt="No results found"> - <h3>No search results found.</h3> - </div> + <div + id="course-search-results" + fxLayout="column" + fxLayoutAlign="space-around none" + style="margin-top: 20px; padding: 12px 22px;"> + <div + *ngIf="hasResults && queriedCourses.length === 0" + class="mat-typography" + style="text-align: center;"> + <img + style="width: 50%;" + src="../../assets/img/bucky-sad.svg" + alt="No results found"/> + <h3>No search results found.</h3> + </div> - <div - cdkDropList - id="queried-courses-list" - [cdkDropListData]="queriedCourses" - [cdkDropListConnectedTo]="dropZoneIds$ | async" - > - <div - class="course-wrapper" - cdkDrag - [cdkDragDisabled]="mobileView.matches" - [cdkDragData]="course" - *ngFor="let course of queriedCourses" - > - <div class="course-wrapper-inner"> - <cse-course-item [course]="course" type="search"></cse-course-item> - </div> - </div> + <div + cdkDropList + id="queried-courses-list" + [cdkDropListData]="queriedCourses" + [cdkDropListConnectedTo]="dropZoneIds$ | async"> + <div + class="course-wrapper" + cdkDrag + [cdkDragDisabled]="mobileView.matches" + [cdkDragData]="course" + *ngFor="let course of queriedCourses"> + <div class="course-wrapper-inner"> + <cse-course-item [course]="course" type="search"></cse-course-item> </div> + </div> </div> -</div> \ No newline at end of file + </div> +</div> diff --git a/src/app/degree-planner/degree-planner.component.html b/src/app/degree-planner/degree-planner.component.html index b748b7b..8259e78 100644 --- a/src/app/degree-planner/degree-planner.component.html +++ b/src/app/degree-planner/degree-planner.component.html @@ -3,19 +3,24 @@ #addMenu position="end" mode="over" - [opened]="isCourseSearchOpen$ | async" - > + role="region" + [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> + <i + class="material-icons" + alt="Close course search sidenav icon" + matTooltip="Close sidenav" + matTooltipPosition="above" + >keyboard_arrow_right</i> </button> </mat-toolbar> <cse-course-search></cse-course-search> </mat-sidenav> - <mat-sidenav-content> + <mat-sidenav-content role="main"> <mat-progress-bar id="loading-plan-progress" mode="indeterminate" @@ -26,48 +31,56 @@ <mat-sidenav #rightMenu position="end" + role="region" + cdkFocusRegionEnd [mode]="mobileView.matches ? 'over' : 'side'" - [opened]="mobileView.matches ? false : true" - > + [opened]="mobileView.matches ? false : true"> <cse-sidenav-menu-item></cse-sidenav-menu-item> </mat-sidenav> <mat-sidenav-content id="degree-plan-wrapper" + role="region" + cdkFocusRegionStart [ngClass]="{ isLoadingPlan: isLoadingPlan$ | async }" - *ngIf="(degreePlan$ | async) as degreePlan" - > + *ngIf="(degreePlan$ | async) as degreePlan"> <div fxLayout="row" fxLayoutGap="20px" fxLayoutAlign="start center" - style="margin: 24px 0px 24px 24px;" - > + style="margin: 24px 0px 24px 24px;"> <mat-form-field> <mat-select + aria-label="Degree plans list" [disabled]="isLoadingPlan$ | async" placeholder="Degree Plans" 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 - > + <mat-icon + class="primary-star" + *ngIf="degreePlan.primary" + alt="Primary degree plan star icon" + matTooltip="Primary plan" + matTooltipPosition="above" + >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 - > + [value]="degreePlan.roadmapId"> + <mat-icon + class="primary-star" + *ngIf="degreePlan.primary" + alt="Primary degree plan star icon" + matTooltip="Primary plan" + matTooltipPosition="above" + >star_rate</mat-icon> <span class="plan-name">{{ degreePlan.name }}</span> </mat-option> </mat-select> @@ -75,12 +88,15 @@ <button mat-icon-button + aria-label="Degree plan settings" [matMenuTriggerFor]="degreePlanMenu" - [disabled]="isLoadingPlan$ | async" - > - <mat-icon matTooltip="Plan settings" matTooltipPosition="right" - >settings</mat-icon - > + [disabled]="isLoadingPlan$ | async"> + <mat-icon + aria-label="Degree plan settings" + alt="Degree plan settings icon" + matTooltip="Plan settings" + matTooltipPosition="right" + >settings</mat-icon> </button> <mat-menu #degreePlanMenu="matMenu"> <button mat-menu-item (click)="onRenamePlanClick(degreePlan)"> @@ -89,8 +105,7 @@ <button mat-menu-item (click)="onMakePrimayClick(degreePlan)" - [disabled]="degreePlan.primary" - > + [disabled]="degreePlan.primary"> Make primary </button> <button mat-menu-item (click)="onPrintPlanClick()"> @@ -102,8 +117,7 @@ <button mat-menu-item (click)="onDeletePlanClick(degreePlan)" - [disabled]="degreePlan.primary" - > + [disabled]="degreePlan.primary"> Delete plan </button> <hr /> @@ -112,9 +126,25 @@ </button> </mat-menu> - <button id="menu-toggle-btn" mat-button (click)="rightMenu.toggle()"> - <i *ngIf="rightMenu.opened" class="material-icons">chevron_right</i> - <i *ngIf="!rightMenu.opened" class="material-icons">chevron_left</i> + <button + id="menu-toggle-btn" + mat-button + (click)="rightMenu.toggle()" + aria-label="Toggle sidenav menu"> + <i + *ngIf="rightMenu.opened" + class="material-icons" + alt="Close sidenav icon" + matTooltip="Close sidenav menu" + matTooltipPosition="above" + >chevron_right</i> + <i + *ngIf="!rightMenu.opened" + class="material-icons" + alt="Open sidenav icon" + matTooltip="Open sidenav menu" + matTooltipPosition="above" + >chevron_left</i> </button> </div> @@ -123,8 +153,7 @@ fxLayout="column" fxLayoutGap="20px" fxLayoutAlign="start stretch" - style="margin: 24px" - > + style="margin: 24px"> <div id="year-mask" *ngIf="(isLoadingPlan$ | async)"></div> <mat-accordion multi="true"> <ng-container *ngFor="let yearCode of (yearCodes$ | async)"> @@ -132,6 +161,6 @@ </ng-container> </mat-accordion> </div> - - </mat-sidenav-content> -</mat-sidenav-container> + </mat-sidenav-content> + </mat-sidenav-container> </mat-sidenav-content> + </mat-sidenav-container> diff --git a/src/app/degree-planner/degree-planner.component.ts b/src/app/degree-planner/degree-planner.component.ts index df6fde1..8d7163e 100644 --- a/src/app/degree-planner/degree-planner.component.ts +++ b/src/app/degree-planner/degree-planner.component.ts @@ -118,7 +118,7 @@ export class DegreePlannerComponent implements OnInit, OnDestroy { initialValue: name, title: 'Add degree plan', confirmText: 'Save', - inputName: 'i.e. Psychology', + inputName: 'Plan name', }, }) .afterClosed() diff --git a/src/app/degree-planner/dialogs/course-details-dialog/course-details-dialog.component.ts b/src/app/degree-planner/dialogs/course-details-dialog/course-details-dialog.component.ts index 8d3701f..025ace6 100644 --- a/src/app/degree-planner/dialogs/course-details-dialog/course-details-dialog.component.ts +++ b/src/app/degree-planner/dialogs/course-details-dialog/course-details-dialog.component.ts @@ -6,7 +6,13 @@ import { Component, OnInit } from '@angular/core'; <mat-toolbar color="primary" class="dialog-toolbar"> <span class="dialog-toolbar-title">Course Details</span> <button mat-button mat-dialog-close class="close-btn"> - <i class="material-icons">clear</i> + <i + class="material-icons" + alt="Close course details dialog icon" + matTooltip="Close course details dialog" + matTooltipPosition="above" + >clear</i + > </button> </mat-toolbar> diff --git a/src/app/degree-planner/dialogs/modify-plan-dialog/modify-plan-dialog.component.html b/src/app/degree-planner/dialogs/modify-plan-dialog/modify-plan-dialog.component.html index 8015c45..374f653 100644 --- a/src/app/degree-planner/dialogs/modify-plan-dialog/modify-plan-dialog.component.html +++ b/src/app/degree-planner/dialogs/modify-plan-dialog/modify-plan-dialog.component.html @@ -10,8 +10,13 @@ <span *ngSwitchCase="'rename'">Rename plan</span> <span *ngSwitchCase="'create'">Create plan</span> </span> - <button mat-button mat-dialog-close class="close-btn"> - <i class="material-icons">clear</i> + <button mat-button mat-dialog-close class="close-btn" cdkFocusRegionEnd> + <i + class="material-icons" + alt="Close dialog icon" + matTooltip="Close dialog" + matTooltipPosition="above" + cdkFocusRegionEnd>clear</i> </button> </mat-toolbar> @@ -20,7 +25,12 @@ <div class="rename-plan-content" *ngSwitchCase="'rename'"> <mat-dialog-content [formGroup]="form"> <mat-form-field class="form-field-stretch"> - <input matInput placeholder="Name" formControlName="planName" cdkFocusInitial> + <input + cdkFocusInitial + matInput + placeholder="Name" + formControlName="planName" + cdkFocusInitial/> </mat-form-field> </mat-dialog-content> </div> @@ -28,16 +38,32 @@ <div class="create-plan-content" *ngSwitchCase="'create'"> <mat-dialog-content [formGroup]="form"> <mat-form-field class="form-field-stretch"> - <input matInput placeholder="Name" formControlName="planName" cdkFocusInitial> + <input + cdkFocusInitial + matInput + placeholder="Name" + formControlName="planName" + cdkFocusInitial/> </mat-form-field> </mat-dialog-content> </div> </ng-container> <mat-dialog-actions align="end"> - <button mat-button class="btn-secondary" mat-dialog-close aria-label="Close dialog" (click)="onCancel()">Cancel</button> + <button + mat-button + class="btn-secondary" + mat-dialog-close + aria-label="Close dialog" + (click)="onCancel()"> + Cancel + </button> - <button mat-rasied-button class="btn-primary mat-button" [disabled]="form.invalid" (click)="onSubmit()"> + <button + mat-rasied-button + class="btn-primary mat-button" + [disabled]="form.invalid" + (click)="onSubmit()"> <ng-container [ngSwitch]="data.mode"> <span *ngSwitchCase="'rename'">Rename plan</span> <span *ngSwitchCase="'create'">Create plan</span> diff --git a/src/app/degree-planner/dialogs/notes-dialog/notes-dialog.component.html b/src/app/degree-planner/dialogs/notes-dialog/notes-dialog.component.html index 373a04b..4fe1330 100644 --- a/src/app/degree-planner/dialogs/notes-dialog/notes-dialog.component.html +++ b/src/app/degree-planner/dialogs/notes-dialog/notes-dialog.component.html @@ -1,62 +1,78 @@ <mat-toolbar color="primary" class="dialog-toolbar"> - <h2 class="dialog-toolbar-title">{{ data.hasExistingNote ? 'Edit' : 'Add' }} Note</h2> - <button mat-button mat-dialog-close class="close-btn" aria-label="Close note dialog"><i class="material-icons">clear</i></button> + <h2 class="dialog-toolbar-title"> + {{ data.hasExistingNote ? 'Edit' : 'Add' }} Note + </h2> + <button + mat-button + mat-dialog-close + class="close-btn" + aria-label="Close note dialog" + cdkFocusRegionEnd> + <i + class="material-icons" + alt="Close note dialog icon" + matTooltip="Close note dialog" + matTooltipPosition="above" + >clear</i> + </button> </mat-toolbar> <mat-dialog-content id="note-dialog" class="mat-typography dialog-with-toolbar"> - <div fxLayout="column" fxLayoutAlign="none" fxLayoutGap="10px"> - <div id="note-content"> - <mat-dialog-content [formGroup]="form"> - <mat-form-field> - <textarea - formControlName="textarea" - matInput - mat-autosize="true" - resizeToFitContent - placeholder="i.e. Studying abroad"> - </textarea> - <mat-hint align="start"> - <strong>Your note can be up to {{ MAX_LENGTH }} characters long</strong> - </mat-hint> - <mat-hint align="end" *ngIf="form.value.textarea?.length > 0"> - {{ form.value.textarea.length }} / {{ MAX_LENGTH }} - </mat-hint> - </mat-form-field> - </mat-dialog-content> - </div> - <mat-dialog-actions align="end"> - <button - mat-button - class="btn-secondary" - mat-dialog-close - aria-label="Close note dialog"> - Cancel - </button> - <button - mat-raised-button - id="saveNote" - class="btn-primary mat-button" - (click)="writeNote()" - [disabled]="form.invalid"> - Save - </button> - </mat-dialog-actions> + <div fxLayout="column" fxLayoutAlign="none" fxLayoutGap="10px"> + <div id="note-content"> + <mat-dialog-content [formGroup]="form"> + <mat-form-field> + <textarea + cdkFocusInitial + formControlName="textarea" + matInput + mat-autosize="true" + resizeToFitContent + placeholder="i.e. Studying abroad"> + </textarea> + <mat-hint align="start"> + <strong + >Your note can be up to {{ MAX_LENGTH }} characters long</strong> + </mat-hint> + <mat-hint align="end" *ngIf="form.value.textarea?.length > 0"> + {{ form.value.textarea.length }} / {{ MAX_LENGTH }} + </mat-hint> + </mat-form-field> + </mat-dialog-content> + </div> + <mat-dialog-actions align="end"> + <button + mat-button + class="btn-secondary" + mat-dialog-close + aria-label="Close note dialog"> + Cancel + </button> + <button + mat-raised-button + id="saveNote" + class="btn-primary mat-button" + (click)="writeNote()" + [disabled]="form.invalid"> + Save + </button> + </mat-dialog-actions> - <div id="delete-note-section" *ngIf="data.hasExistingNote"> - <div> - <h2>Delete note</h2> - <p>Once the note is deleted, there is no going back.</p> - </div> - <mat-dialog-actions align="end"> - <button - mat-raised-button - class="btn-delete mat-button" - (click)="deleteNote()" - mat-dialog-close - aria-label="Delete note from selected term"> - Delete - </button> - </mat-dialog-actions> - </div> - </div> + <div id="delete-note-section" *ngIf="data.hasExistingNote"> + <div> + <h2>Delete note</h2> + <p>Once the note is deleted, there is no going back.</p> + </div> + <mat-dialog-actions align="end"> + <button + mat-raised-button + class="btn-delete mat-button" + (click)="deleteNote()" + mat-dialog-close + aria-label="Delete note from selected term"> + Delete + </button> + </mat-dialog-actions> + </div> + </div> </mat-dialog-content> diff --git a/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.html b/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.html index 41ddaf1..62e9505 100644 --- a/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.html +++ b/src/app/degree-planner/dialogs/remove-course-confirm-dialog/remove-course-confirm-dialog.component.html @@ -1,14 +1,44 @@ <mat-toolbar class="dialog-toolbar"> - <h1 class="dialog-toolbar-title">Are you sure?</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">Are you sure?</h1> + <button + mat-button + mat-dialog-close + class="close-btn" + aria-label="Close note dialog"> + <i + class="material-icons" + alt="Close dialog icon" + matTooltip="Close dialog" + matTooltipPosition="above">clear</i> + </button> </mat-toolbar> -<mat-dialog-content id="confirmation-dialog" class="mat-typography dialog-with-toolbar"> - <mat-dialog-content> - <p class="dialog-text" *ngIf="savedForLater">This will remove {{ course.title }} from Saved For Later and My Courses.</p> - <p class="dialog-text" *ngIf="!savedForLater">This will remove {{ course.title }} from your plan and from your cart.</p> - </mat-dialog-content> - <mat-dialog-actions align="end"> - <button mat-button class="mat-button btn-link" mat-dialog-close aria-label="Close dialog">Cancel</button> - <button mat-button class="btn-link" (click)="removeCourse()" mat-dialog-close aria-label="Delete course from selected term">Remove</button> - </mat-dialog-actions> -</mat-dialog-content> \ No newline at end of file +<mat-dialog-content + id="confirmation-dialog" + class="mat-typography dialog-with-toolbar"> + <mat-dialog-content> + <p class="dialog-text" *ngIf="savedForLater"> + This will remove {{ course.title }} from Saved For Later and My Courses. + </p> + <p class="dialog-text" *ngIf="!savedForLater"> + This will remove {{ course.title }} from your plan and from your cart. + </p> + </mat-dialog-content> + <mat-dialog-actions align="end"> + <button + cdkFocusRegionEnd + mat-button + class="mat-button btn-link" + mat-dialog-close + aria-label="Close dialog"> + Cancel + </button> + <button + mat-button + class="btn-link" + (click)="removeCourse()" + mat-dialog-close + aria-label="Delete course from selected term"> + Remove + </button> + </mat-dialog-actions> +</mat-dialog-content> diff --git a/src/app/degree-planner/shared/course-item/course-item.component.html b/src/app/degree-planner/shared/course-item/course-item.component.html index bb67e1b..912f14d 100644 --- a/src/app/degree-planner/shared/course-item/course-item.component.html +++ b/src/app/degree-planner/shared/course-item/course-item.component.html @@ -1,20 +1,29 @@ <div class="course-item {{ disabled ? 'disabled' : '' }}"> <div fxLayout="row" fxLayoutAlign="space-between start"> <div + tabindex="0" fxLayout="column" fxLayoutAlign="space-between start" fxFlex="80" - (click)="openCourseDetailsDialog(course)" - > + aria-labelledby="courseMenu" + isFocusable="true" + isTabbable="true" + cdkFocusInitial + aria-haspopup="true" + (click)="openCourseDetailsDialog(course)"> <div fxLayout="row" fxLayoutAlign="start center"> <div class="icon-number-wrapper"> - <p class="course-number" [ngClass]="{ 'strikethrough': isStruckthrough }"> + <p + cdkFocusRegionStart + class="course-number" + [ngClass]="{ strikethrough: isStruckthrough }"> {{ course.subject }} {{ course.catalogNumber }} </p> <span [ngSwitch]="status"> <i *ngSwitchCase="'InProgress'" class="material-icons in-progress-icon" + alt="Course in progress icon" matTooltip="Course in progress" matTooltipPosition="above"> check_circle @@ -22,13 +31,15 @@ <i *ngSwitchCase="'Waitlisted'" class="material-icons problem-icon" + alt="Course is waitlisted icon" matTooltip="Course is waitlisted" matTooltipPosition="above"> - report_problem + report_problem </i> <i *ngSwitchCase="'Incomplete'" class="material-icons cancel-icon" + alt="Course is incomplete icon" matTooltip="Course is incomplete" matTooltipPosition="above"> cancel @@ -36,6 +47,7 @@ <i *ngSwitchCase="'NotOfferedInTerm'" class="material-icons error-icon" + alt="Course not offered in term icon" matTooltip="Course is not offered in term" matTooltipPosition="above"> error @@ -44,45 +56,67 @@ </div> </div> <div fxLayout="row" fxLayoutAlign="start center"> - <p class="course-title" [ngClass]="{ 'strikethrough': isStruckthrough }">{{ course.title }}</p> + <p class="course-title" [ngClass]="{ strikethrough: isStruckthrough }"> + {{ course.title }} + </p> </div> </div> <div fxLayout="column" fxLayoutAlign="space-between end" fxFlex="20"> <div *ngIf="!disabled" fxLayout="row" fxLayoutAlign="end center"> - <mat-icon + <button + mat-icon-button + aria-label="Open course menu" [matMenuTriggerFor]="courseMenu" - (menuOpened)="onMenuOpen()" - aria-label="Course menu" - matTooltip="Course Menu" - matTooltipPosition="right" - class="material-icons" - >more_horiz</mat-icon - > - <mat-menu #courseMenu="matMenu" class="course-item-menu"> - <button mat-menu-item (click)="openCourseDetailsDialog(course)"> + (menuOpened)="onMenuOpen()"> + <mat-icon + aria-label="Course menu" + alt="Course menu icon" + matTooltip="Course menu" + matTooltipPosition="right" + class="material-icons" + >more_horiz</mat-icon> + </button> + <mat-menu + #courseMenu="matMenu" + class="course-item-menu" + tabindex="0" + isFocusable="true" + isTabbable="true" + cdkFocusInitial> + <button + mat-menu-item + (click)="openCourseDetailsDialog(course)" + aria-label="Open dialog to see course details"> Course Details </button> - <button mat-menu-item [matMenuTriggerFor]="academicYearsGroup"> + <button + mat-menu-item + [matMenuTriggerFor]="academicYearsGroup" + aria-label="Select to move this course to a different term"> Move </button> <mat-menu #academicYearsGroup="matMenu" class="course-item-submenu"> <button mat-menu-item *ngFor="let term of (droppableTermCodes$ | async)" - (click)="onMove(term)" - > + aria-labelledby="Move course to this term" + (click)="onMove(term)"> {{ term | getTermDescription }} </button> </mat-menu> <button mat-menu-item + aria-label="Move this course to Saved for later" *ngIf="type !== 'saved'" - (click)="onSaveForLater()" - > + (click)="onSaveForLater()"> Save for later </button> - <button mat-menu-item *ngIf="type !== 'search'" (click)="onRemove()"> + <button + mat-menu-item + aria-label="Remove this course from my plan" + *ngIf="type !== 'search'" + (click)="onRemove()"> Remove </button> </mat-menu> @@ -91,7 +125,10 @@ <p>{{ course.grade || ' ' }}</p> </div> <div fxLayout="row" fxLayoutAlign="end center"> - <p class="course-credits"> + <p + class="course-credits" + cdkFocusRegionEnd + aria-label="Total number of credits in term"> {{ course.credits ? course.credits : course.creditRange }} Cr </p> </div> 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 aea9342..4bc00cc 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 @@ -5,53 +5,49 @@ <h3>Course Key</h3> </mat-panel-title> </mat-expansion-panel-header> - <ul id="course-key-list"> - <li> + <mat-list id="course-key-list" role="list"> + <mat-list-item role="listitem"> <i class="material-icons in-progress-icon" + alt="Course in progress icon" matTooltip="Course in progress" matTooltipPosition="left" - >check_circle</i - > + >check_circle</i> Course is currently in progress - </li> - <li> + </mat-list-item> + <mat-list-item role="listitem"> <i class="material-icons problem-icon" + alt="Course is waitlisted icon" matTooltip="Course is waitlisted" - matTooltipPosition="left" - >report_problem</i - > + matTooltipPosition="left">report_problem</i> Course is waitlisted - </li> - <li> + </mat-list-item> + <mat-list-item role="listitem"> <i class="material-icons cancel-icon" + alt="Course is incomplete icon" matTooltip="Course is incomplete" - matTooltipPosition="left" - >cancel</i - > + matTooltipPosition="left">cancel</i> Course is incomplete - </li> - <li> + </mat-list-item> + <mat-list-item role="listitem"> <i class="material-icons error-icon" + alt="Course not offered in term icon" matTooltip="Course not offered in term" - matTooltipPosition="left" - >error</i - > + matTooltipPosition="left">error</i> Course not offered in term - </li> - <li> + </mat-list-item> + <mat-list-item> <i class="material-icons not-offered-icon" - matTooltip="Course no longer offered" - matTooltipPosition="left" - >remove</i - > - Course no longer offered - </li> - </ul> + alt="Course no loger offered icon" + matTooltip="Course no loger offered" + matTooltipPosition="left">remove</i> + Course no loger offered + </mat-list-item> + </mat-list> </mat-expansion-panel> <mat-expansion-panel id="course-keys-container" expanded="true"> <mat-expansion-panel-header> @@ -70,27 +66,48 @@ </mat-expansion-panel-header> <div> <button mat-button class="sidenav-link-btn" (click)="print()"> - <i class="material-icons">print</i> Print + <i + class="material-icons" + alt="Print plan icon" + matTooltip="Print plan" + matTooltipPosition="left">print</i> + Print </button> - <a href="/api/degreeplanpdf?roadmapId={{planId}}" mat-button class="sidenav-link-btn"> - <svg class="material-icons" style="width:24px;height:24px" viewBox="0 0 24 24" > + <a + href="/api/degreeplanpdf?roadmapId={{ planId }}" + mat-button + class="sidenav-link-btn"> + <svg + alt="Download PDF icon" + matTooltip="Download PDF" + matTooltipPosition="left" + 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 </a> <button mat-button class="sidenav-link-btn" (click)="onCreatePlanClick()"> - <i class="material-icons">add_box</i> Add Degree Plan + <i + class="material-icons" + alt="Add degree plan icon" + matTooltip="Add degree plan" + matTooltipPosition="left" + >add_box</i> + Add Degree Plan </button> <button mat-button class="sidenav-link-btn" (click)="onAddAcademicYear()"> <svg + alt="Add Academic Year icon" + matTooltip="Add academic year" + matTooltipPosition="left" class="material-icons" style="width:24px;height:24px" - viewBox="0 0 24 24" - > + 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" - /> + 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> diff --git a/src/app/degree-planner/sidenav-menu-item/sidenav-menu-item.component.scss b/src/app/degree-planner/sidenav-menu-item/sidenav-menu-item.component.scss index 546a4f8..31d153c 100644 --- a/src/app/degree-planner/sidenav-menu-item/sidenav-menu-item.component.scss +++ b/src/app/degree-planner/sidenav-menu-item/sidenav-menu-item.component.scss @@ -35,16 +35,9 @@ } #course-key-list { - list-style-type: none; - padding: 20px 0 0px 0; - margin-top: 0px; border-top: 1px solid rgba(0, 0, 0, 0.54); - li { - position: relative; - display: flex; - align-items: center; - padding-bottom: 12px; - padding-left: 1em; + mat-list-item { + font-size: 14px; .material-icons { margin-right: 8px; 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 63f76f4..cccb484 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 @@ -59,7 +59,7 @@ export class SidenavMenuItemComponent implements OnDestroy { data: { title: 'Add degree plan', confirmText: 'Save', - inputName: 'i.e. Psychology', + inputName: 'Plan name', }, }) .afterClosed() diff --git a/src/app/degree-planner/term-container/term-container.component.html b/src/app/degree-planner/term-container/term-container.component.html index 2470413..c30b3bc 100644 --- a/src/app/degree-planner/term-container/term-container.component.html +++ b/src/app/degree-planner/term-container/term-container.component.html @@ -1,93 +1,122 @@ <ng-template #enrolled> <div class="course-list-wrapper"> - <div class="course-list"> - <div class="course-list-inner"> - <ng-container *ngIf="enrolledCourses.length === 0"> - <p *ngIf="(term$ | async).era === 'past'" class="no-courses">No courses taken</p> - <p *ngIf="(term$ | async).era === 'active'" class="no-courses">Not enrolled in any courses</p> - </ng-container> + <div class="course-list"> + <div class="course-list-inner"> + <ng-container *ngIf="enrolledCourses.length === 0"> + <p *ngIf="(term$ | async).era === 'past'" class="no-courses"> + No courses taken + </p> + <p *ngIf="(term$ | async).era === 'active'" class="no-courses"> + Not enrolled in any courses + </p> + </ng-container> - <cse-course-item - *ngFor="let course of enrolledCourses" - type="course" - [disabled]="true" - [course]="course" - [era]="(term$ | async).era"> - </cse-course-item> - </div> - </div> + <cse-course-item + isFocusable="true" + isTabbable="true" + cdkFocusinitial + *ngFor="let course of enrolledCourses" + type="course" + [disabled]="true" + [course]="course" + [era]="(term$ | async).era" + > + </cse-course-item> + </div> + </div> </div> </ng-template> <ng-template #planned> - <div class="course-list-wrapper"> - <div class="course-list" - cdkDropList - id="term-{{ termCode }}" - [cdkDropListData]="(term$ | async).termCode" - [cdkDropListConnectedTo]="dropZoneIds$ | async" - (cdkDropListDropped)="drop($event)" - (cdkDropListEntered)="dragEnter($event)" - (cdkDropListExited)="dragExit($event)" + <div class="course-list-wrapper"> + <div + class="course-list" + cdkDropList + id="term-{{ termCode }}" + [cdkDropListData]="(term$ | async).termCode" + [cdkDropListConnectedTo]="dropZoneIds$ | async" + (cdkDropListDropped)="drop($event)" + (cdkDropListEntered)="dragEnter($event)" + (cdkDropListExited)="dragExit($event)" + > + <div class="course-list-inner term-body"> + <ng-container + *ngIf="plannedCourses.length === 0 && !hasItemDraggedOver" > - <div class="course-list-inner term-body"> - <ng-container *ngIf="plannedCourses.length === 0 && !hasItemDraggedOver"> - <p *ngIf="(term$ | async).era === 'active'" class="no-courses">No Courses in cart</p> - <p *ngIf="(term$ | async).era === 'future'" class="no-courses">No courses planned</p> - <p *ngIf="(term$ | async).era === 'past'" class="no-courses">No courses planned</p> - </ng-container> - <div - cdkDrag - [cdkDragData]="course" - [cdkDragDisabled]="mobileView.matches" - class="course-wrapper" - *ngFor="let course of plannedCourses" - > - <cse-course-item - type="course" - [course]="course" - [era]="(term$ | async).era"> - </cse-course-item> - </div> - </div> - </div> - - <!-- Add course --> - <div class="add-new-wrapper" *ngIf="(term$ | async).era !== 'past'"> - <button - mat-raised-button - class="add-course-button" - (click)="openCourseSearch()" + <p *ngIf="(term$ | async).era === 'active'" class="no-courses"> + No Courses in cart + </p> + <p *ngIf="(term$ | async).era === 'future'" class="no-courses"> + No courses planned + </p> + <p *ngIf="(term$ | async).era === 'past'" class="no-courses"> + No courses planned + </p> + </ng-container> + <div + cdkDrag + [cdkDragData]="course" + [cdkDragDisabled]="mobileView.matches" + class="course-wrapper" + *ngFor="let course of plannedCourses" + > + <cse-course-item + type="course" + [course]="course" + [era]="(term$ | async).era" > - + Add Course - </button> + </cse-course-item> </div> + </div> + </div> + + <!-- Add course --> + <div class="add-new-wrapper" *ngIf="(term$ | async).era !== 'past'"> + <button + mat-raised-button + class="add-course-button" + (click)="openCourseSearch()" + > + + Add Course + </button> </div> + </div> </ng-template> -<mat-card class="term-container" [ngClass]="{ 'no-scrolling': mobileView.matches }"> +<mat-card + class="term-container" + [ngClass]="{ 'no-scrolling': mobileView.matches }" + role="region" + cdkFocusInitial +> <div class="term-inner"> <div fxLayout="row" class="term-header" fxLayoutAlign="space-between center" > - <h2>{{ termCode | getTermDescription }}</h2> + <h2 tabindex="0">{{ termCode | getTermDescription }}</h2> <div fxLayout="row" fxLayoutAlign="space-between center"> - <p class="text-right semi-bold credits"> - <span *ngIf="visibleCredits === 'planned'">{{plannedCredits}} Cr</span> - <span *ngIf="visibleCredits === 'enrolled'">{{enrolledCredits}} Cr</span> + <p class="text-right semi-bold credits" tabindex="1"> + <span *ngIf="visibleCredits === 'planned'" + >{{ plannedCredits }} Cr</span + > + <span *ngIf="visibleCredits === 'enrolled'" + >{{ enrolledCredits }} Cr</span + > </p> <ng-container *ngIf="(note$ | async) as note; else newNote"> <button mat-icon-button + aria-label="Open dialog to edit note in this term" [disabled]="note.isLoaded === false" (click)="openNotesDialog(note)" > <mat-icon - aria-label="Open dialog with notes in this term" + aria-label="Open dialog to edit note in this term" + alt="Edit note icon" color="primary" - matTooltip="Edit Note" + matTooltip="Edit note" matTooltipPosition="above" > insert_drive_file @@ -95,11 +124,16 @@ </button> </ng-container> <ng-template #newNote> - <button mat-icon-button (click)="openNotesDialog()"> + <button + mat-icon-button + (click)="openNotesDialog()" + aria-label="Open dialog to add note in this term" + > <mat-icon - aria-label="Open dialog with notes in this term" + aria-label="Open dialog to add note in this term" + alt="Add note icon" color="primary" - matTooltip="Add Note" + matTooltip="Add note" matTooltipPosition="above" > note_add @@ -131,29 +165,55 @@ </div> <!-- If this term is an active term --> - <ng-container *ngIf="(term$ |async).era === 'active'"> - <mat-tab-group (selectedTabChange)="changeVisibleCredits($event)" [selectedIndex]="1"> - <mat-tab [label]="'In Progress (' + enrolledCourses.length + ')'"><ng-container *ngTemplateOutlet="enrolled"></ng-container></mat-tab> - <mat-tab [label]="'Cart (' + plannedCourses.length + ')'"><ng-container *ngTemplateOutlet="planned"></ng-container></mat-tab> + <ng-container *ngIf="(term$ | async).era === 'active'"> + <mat-tab-group + (selectedTabChange)="changeVisibleCredits($event)" + [selectedIndex]="1" + > + <mat-tab [label]="'In Progress (' + enrolledCourses.length + ')'" + ><ng-container + cdkFocusinitial + *ngTemplateOutlet="enrolled" + ></ng-container + ></mat-tab> + <mat-tab [label]="'Cart (' + plannedCourses.length + ')'" + ><ng-container + cdkFocusinitial + *ngTemplateOutlet="planned" + ></ng-container + ></mat-tab> </mat-tab-group> </ng-container> <!-- If this term is a past term --> - <ng-container *ngIf="(term$ |async).era === 'past'"> - <ng-container *ngIf="plannedCourses.length > 0"> - <mat-tab-group (selectedTabChange)="changeVisibleCredits($event)" [selectedIndex]="0"> - <mat-tab [label]="'Completed (' + enrolledCourses.length + ')'"><ng-container *ngTemplateOutlet="enrolled"></ng-container></mat-tab> - <mat-tab [label]="'Cart (' + plannedCourses.length + ')'"><ng-container *ngTemplateOutlet="planned"></ng-container></mat-tab> - </mat-tab-group> - </ng-container> + <ng-container *ngIf="(term$ | async).era === 'past'"> + <ng-container *ngIf="plannedCourses.length > 0"> + <mat-tab-group + (selectedTabChange)="changeVisibleCredits($event)" + [selectedIndex]="0" + > + <mat-tab [label]="'Completed (' + enrolledCourses.length + ')'" + ><ng-container + cdkFocusinitial + *ngTemplateOutlet="enrolled" + ></ng-container + ></mat-tab> + <mat-tab [label]="'Cart (' + plannedCourses.length + ')'" + ><ng-container + cdkFocusinitial + *ngTemplateOutlet="planned" + ></ng-container + ></mat-tab> + </mat-tab-group> + </ng-container> - <ng-container *ngIf="plannedCourses.length === 0" > - <ng-container *ngTemplateOutlet="enrolled"></ng-container> - </ng-container> + <ng-container *ngIf="plannedCourses.length === 0"> + <ng-container cdkFocusinitial *ngTemplateOutlet="enrolled"></ng-container> + </ng-container> </ng-container> <!-- If this term is a past term --> - <ng-container *ngIf="(term$ |async).era === 'future'"> - <ng-container *ngTemplateOutlet="planned"></ng-container> + <ng-container *ngIf="(term$ | async).era === 'future'"> + <ng-container cdkFocusinitial *ngTemplateOutlet="planned"></ng-container> </ng-container> </mat-card> diff --git a/src/app/degree-planner/year-container/year-container.component.html b/src/app/degree-planner/year-container/year-container.component.html index 5953f23..613fad6 100644 --- a/src/app/degree-planner/year-container/year-container.component.html +++ b/src/app/degree-planner/year-container/year-container.component.html @@ -5,21 +5,20 @@ (closed)="collapseYear()"> <mat-expansion-panel-header> <mat-panel-title> - {{ yearCode | academicYearState:(activeTermCodes$ | async) }} + {{ yearCode | academicYearState: (activeTermCodes$ | async) }} </mat-panel-title> </mat-expansion-panel-header> - <div fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutAlign="start stretch" class="term-container-wrapper"> - <cse-term-container - fxFlex="33%" - [termCode]="yearCode.fall"> + <div + fxLayout="row" + fxLayout.lt-md="column" + fxLayoutGap="20px" + fxLayoutAlign="start stretch" + class="term-container-wrapper"> + <cse-term-container fxFlex="33%" [termCode]="yearCode.fall"> </cse-term-container> - <cse-term-container - fxFlex="33%" - [termCode]="yearCode.spring"> + <cse-term-container fxFlex="33%" [termCode]="yearCode.spring"> </cse-term-container> - <cse-term-container - fxFlex="33%" - [termCode]="yearCode.summer"> + <cse-term-container fxFlex="33%" [termCode]="yearCode.summer"> </cse-term-container> </div> </mat-expansion-panel> diff --git a/src/app/shared/components/course-details/course-details.component.html b/src/app/shared/components/course-details/course-details.component.html index 0362a9d..62b252a 100644 --- a/src/app/shared/components/course-details/course-details.component.html +++ b/src/app/shared/components/course-details/course-details.component.html @@ -1,80 +1,175 @@ -<div id="course-details-content"> +<div id="course-details-content"> <div fxLayout="row"> - <div fxLayout="row" fxLayout.lt-md="column" fxFlex="100" fxLayoutGap="10px" class="course-details-header"> - <div fxFlex="50" class="course-detail-title" fxLayoutAlign="start center"> - <h3>{{ courseDetails.fullCourseDesignation | titlecase }}<span class="course-detail-subtitle">{{ courseDetails.title }}</span></h3> - </div> - <div *ngIf="type === 'search' || type === 'saved'" fxFlex="50" fxLayout="row" fxLayoutAlign="end start" > - <div style="margin-top: 10px;"> - <form [formGroup]='termSelector' (ngSubmit)="addCourseToPlan($event)"> - <mat-form-field style="margin-right:20px;"> - <mat-select placeholder="Term" aria-label="Term" matInput formControlName="term"> - <mat-option *ngFor="let term of (droppableTermCodes$ | async)" [value]="term">{{term | getTermDescription}}</mat-option> - </mat-select> - </mat-form-field> + <div + fxLayout="row" + fxLayout.lt-md="column" + fxFlex="100" + fxLayoutGap="10px" + class="course-details-header" + > + <div fxFlex="50" class="course-detail-title" fxLayoutAlign="start center"> + <h3> + {{ courseDetails.fullCourseDesignation | titlecase + }}<span class="course-detail-subtitle">{{ + courseDetails.title + }}</span> + </h3> + </div> + <div + *ngIf="type === 'search' || type === 'saved'" + fxFlex="50" + fxLayout="row" + fxLayoutAlign="end start" + > + <div style="margin-top: 10px;"> + <form [formGroup]="termSelector" (ngSubmit)="addCourseToPlan($event)"> + <mat-form-field style="margin-right:20px;"> + <mat-select + placeholder="Term" + aria-label="Term" + matInput + role="listbox" + formControlName="term" + cdkFocusInitial + > + <mat-option + role="option" + *ngFor="let term of (droppableTermCodes$ | async)" + [value]="term" + >{{ term | getTermDescription }}</mat-option + > + </mat-select> + </mat-form-field> - <button mat-raised-button color="primary" mat-dialog-close (click)="addCourseToPlan($event)">Add to plan</button> - </form> - </div> - </div> - </div> - </div> + <button + mat-raised-button + color="primary" + mat-dialog-close + (click)="addCourseToPlan($event)" + > + Add to plan + </button> + </form> + </div> + </div> + </div> + </div> - <div fxLayout="column" fxLayoutAlign="space-around start" fxLayoutGap="10px" class="course-details-content"> + <div + fxLayout="column" + fxLayoutAlign="space-around start" + fxLayoutGap="10px" + class="course-details-content" + > <p>{{ courseDetails.description }}</p> - <p *ngIf="courseDetails.enrollmentPrerequisites"><span class="semi-bold">Requisites: </span>{{ courseDetails.enrollmentPrerequisites }}</p> - - <ul class="courseDetails-list"> - <li *ngIf="courseDetails.creditRange"><span class="semi-bold">Credits:</span> {{ courseDetails.creditRange }}</li> - <li *ngIf="courseDetails.levels && courseDetails.levels.length > 0"><span class="semi-bold">Level: </span> - <span *ngFor="let levels of courseDetails.levels"> - <span class="list-comma">{{ levels.description }}</span> - </span> - </li> - <li *ngIf="courseDetails.breadths && courseDetails.breadths.length > 0"><span class="semi-bold">Breadth: </span> - <span *ngFor="let breadths of courseDetails.breadths"> - <span class="list-comma">{{ breadths.description }}</span> - </span> - </li> - <li *ngIf="courseDetails.lettersAndScienceCredits"><span class="semi-bold">L&S Credit Type:</span> - {{ courseDetails.lettersAndScienceCredits.description }} + <p *ngIf="courseDetails.enrollmentPrerequisites"> + <span class="semi-bold">Requisites: </span + >{{ courseDetails.enrollmentPrerequisites }} + </p> + + <ul class="courseDetails-list"> + <li *ngIf="courseDetails.creditRange"> + <span class="semi-bold">Credits:</span> {{ courseDetails.creditRange }} + </li> + <li *ngIf="courseDetails.levels && courseDetails.levels.length > 0"> + <span class="semi-bold">Level: </span> + <span *ngFor="let levels of courseDetails.levels"> + <span class="list-comma">{{ levels.description }}</span> + </span> + </li> + <li *ngIf="courseDetails.breadths && courseDetails.breadths.length > 0"> + <span class="semi-bold">Breadth: </span> + <span *ngFor="let breadths of courseDetails.breadths"> + <span class="list-comma">{{ breadths.description }}</span> + </span> + </li> + <li *ngIf="courseDetails.lettersAndScienceCredits"> + <span class="semi-bold">L&S Credit Type:</span> + {{ courseDetails.lettersAndScienceCredits.description }} + </li> + <li *ngIf="courseDetails.honors"> + <span class="semi-bold">Honors: </span>{{ courseDetails.honors }} + </li> + <li *ngIf="courseDetails.generalEd"> + <span class="semi-bold">General Education: </span + >{{ courseDetails.generalEd.description }} + </li> + <li *ngIf="courseDetails.ethnicStudies"> + <span class="semi-bold">General Education:</span> Ethnic Studies </li> - <li *ngIf="courseDetails.honors"><span class="semi-bold">Honors: </span>{{ courseDetails.honors }}</li> - <li *ngIf="courseDetails.generalEd"><span class="semi-bold">General Education: </span>{{ courseDetails.generalEd.description }}</li> - <li *ngIf="courseDetails.ethnicStudies"><span class="semi-bold">General Education:</span> Ethnic Studies</li> <!-- <li *ngIf="courseDetails."><span class="semi-bold">Class Number:</span> {{ courseDetails.generalEd }}</li> --> - </ul> - - <ul class="courseDetails-list"> - <li *ngIf="courseDetails.lastTaught"><span class="semi-bold">Last Taught: </span>{{ courseDetails.lastTaught | getTermDescription }}</li> - <li *ngIf="courseDetails.typicallyOffered"><span class="semi-bold">Typically Offered: </span>{{ courseDetails.typicallyOffered }}</li> - <li *ngIf="(courseDetails.gradCourseWork || courseDetails.workplaceExperience || courseDetails.foreignLanguage)" ><span class="semi-bold">Course Options:</span> - <ul class="courseDetails-nested-list"> - <li> - <span *ngIf="courseDetails.gradCourseWork">50% Graduate Coursework Requirement</span> - <span *ngIf="courseDetails.workplaceExperience">{{ courseDetails.workplaceExperience.description }}</span> - <span *ngIf="courseDetails.foreignLanguage">{{ courseDetails.foreignLanguage.description }}</span> - </li> - </ul> - </li> - </ul> + </ul> - <p *ngIf="courseDetails.subject.footnotes"><span class="semi-bold">Subject Notes:</span><br> - <span class="subject-notes">{{ courseDetails.subject.footnotes }}</span></p> + <ul class="courseDetails-list"> + <li *ngIf="courseDetails.lastTaught"> + <span class="semi-bold">Last Taught: </span + >{{ courseDetails.lastTaught | getTermDescription }} + </li> + <li *ngIf="courseDetails.typicallyOffered"> + <span class="semi-bold">Typically Offered: </span + >{{ courseDetails.typicallyOffered }} + </li> + <li + *ngIf=" + courseDetails.gradCourseWork || + courseDetails.workplaceExperience || + courseDetails.foreignLanguage + " + > + <span class="semi-bold">Course Options:</span> + <ul class="courseDetails-nested-list"> + <li> + <span *ngIf="courseDetails.gradCourseWork" + >50% Graduate Coursework Requirement</span + > + <span *ngIf="courseDetails.workplaceExperience">{{ + courseDetails.workplaceExperience.description + }}</span> + <span *ngIf="courseDetails.foreignLanguage">{{ + courseDetails.foreignLanguage.description + }}</span> + </li> + </ul> + </li> + </ul> - </div> + <p *ngIf="courseDetails.subject.footnotes"> + <span class="semi-bold">Subject Notes:</span><br /> + <span class="subject-notes">{{ courseDetails.subject.footnotes }}</span> + </p> + </div> - <div class="course-details-footer"> - <p class="semi-bold course-detail-title">{{ courseDetails.subject.description | titlecase }} Information:</p> - <div fxLayout="row"> - <div fxLayout="row" fxFlex="100" fxLayoutGap="10px"> - <div fxFlex="100" fxLayout.lt-sm="column" class="mat-dialog-actions" fxLayoutAlign="start center" fxLayoutAlign.lt-sm="start start"> - <a class="md-primary btn-link mat-button" href="{{ courseDetails.subject.departmentURI }}">Website</a> - <a class="md-primary btn-link mat-button" href="{{ courseDetails.subject.undergraduateCatalogURI }}">Undergraduate Info</a> - <a class="md-primary btn-link mat-button" href="{{ courseDetails.subject.graduateCatalogURI }}">Graduate Info</a> - </div> - </div> - </div> + <div class="course-details-footer"> + <p class="semi-bold course-detail-title"> + {{ courseDetails.subject.description | titlecase }} Information: + </p> + <div fxLayout="row"> + <div fxLayout="row" fxFlex="100" fxLayoutGap="10px"> + <div + fxFlex="100" + fxLayout.lt-sm="column" + class="mat-dialog-actions" + fxLayoutAlign="start center" + fxLayoutAlign.lt-sm="start start" + > + <a + class="md-primary btn-link mat-button" + href="{{ courseDetails.subject.departmentURI }}" + >Website</a + > + <a + class="md-primary btn-link mat-button" + href="{{ courseDetails.subject.undergraduateCatalogURI }}" + >Undergraduate Info</a + > + <a + class="md-primary btn-link mat-button" + href="{{ courseDetails.subject.graduateCatalogURI }}" + >Graduate Info</a + > + </div> + </div> + </div> </div> -</div> \ No newline at end of file +</div> 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 d205380..31136db 100644 --- a/src/app/shared/dialogs/confirm-dialog/confirm-dialog.component.html +++ b/src/app/shared/dialogs/confirm-dialog/confirm-dialog.component.html @@ -1,19 +1,41 @@ <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-button + mat-dialog-close + class="close-btn" + aria-label="Close note dialog" + cdkFocusRegionEnd> + <i + class="material-icons" + alt="Close dialog icon" + matTooltip="Close dialog" + matTooltipPosition="above">clear</i> </button> </mat-toolbar> -<mat-dialog-content id="confirmation-dialog" class="mat-typography dialog-with-toolbar"> +<mat-dialog-content + id="confirmation-dialog" + class="mat-typography dialog-with-toolbar"> <div class="{{ dialogClass }}"> <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"> + <button + class="confirm-button" + mat-button + (click)="cancel()" + aria-label="Cancel"> {{ cancelText }} </button> - <button mat-button color="primary" class="confirm-button" mat-raised-button (click)="confirm()" aria-label="Confirm"> + <button + mat-button + cdkFocusInitial + color="primary" + class="confirm-button" + mat-raised-button + (click)="confirm()" + aria-label="Confirm"> {{ confirmText }} </button> </mat-dialog-actions> 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 be5e533..6a1b726 100644 --- a/src/app/shared/dialogs/prompt-dialog/prompt-dialog.component.html +++ b/src/app/shared/dialogs/prompt-dialog/prompt-dialog.component.html @@ -5,14 +5,18 @@ mat-dialog-close class="close-btn" aria-label="Close dialog" - > - <i class="material-icons">clear</i> + cdkFocusRegionEnd> + <i + class="material-icons" + alt="Close dialog icon" + matTooltip="Close dialog" + matTooltipPosition="above" + >clear</i> </button> </mat-toolbar> <mat-dialog-content id="confirmation-dialog" - class="mat-typography dialog-with-toolbar" -> + class="mat-typography dialog-with-toolbar"> <mat-dialog-content> <p class="dialog-text" *ngFor="let line of text">{{ line }}</p> @@ -21,10 +25,13 @@ (ngSubmit)="confirm()" fxLayout="column" fxLayoutAlign="space-around none" - style="padding: 12px 22px;" - > + style="padding: 12px 22px;"> <mat-form-field> - <input matInput [placeholder]="inputName" formControlName="value" /> + <input + cdkFocusInitial + matInput + [placeholder]="inputName" + formControlName="value"/> </mat-form-field> </form> </mat-dialog-content> @@ -33,8 +40,7 @@ mat-button class="btn-secondary mat-button" (click)="cancel()" - aria-label="Cancel" - > + aria-label="Cancel"> {{ cancelText }} </button> <button @@ -45,8 +51,7 @@ mat-raised-button (click)="confirm()" aria-label="Confirm" - [disabled]="inputForm.invalid" - > + [disabled]="inputForm.invalid"> {{ confirmText }} </button> </mat-dialog-actions> diff --git a/src/app/shared/pipes/academic-year-state.pipe.ts b/src/app/shared/pipes/academic-year-state.pipe.ts index 9fa07f8..8d1a5c5 100644 --- a/src/app/shared/pipes/academic-year-state.pipe.ts +++ b/src/app/shared/pipes/academic-year-state.pipe.ts @@ -14,11 +14,11 @@ export class AcademicYearStatePipe implements PipeTransform { const era = utils.pickYearEra(yearCode, activeTermCodes); switch (era) { case 'past': - return `Past: ${yearCode.fromYear}-${yearCode.toYear}`; + return `Past year: ${yearCode.fromYear}-${yearCode.toYear}`; case 'future': - return `Future: ${yearCode.fromYear}-${yearCode.toYear}`; + return `Future year: ${yearCode.fromYear}-${yearCode.toYear}`; default: - return `Current: ${yearCode.fromYear}-${yearCode.toYear}`; + return `Active year: ${yearCode.fromYear}-${yearCode.toYear}`; } } } diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 1f5827e..6a82d89 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -11,12 +11,14 @@ import { MatCardModule } from '@angular/material/card'; import { MatSelectModule } from '@angular/material/select'; import { MatSidenavModule } from '@angular/material/sidenav'; import { MatExpansionModule } from '@angular/material/expansion'; +import { MatListModule } from '@angular/material/list'; import { MatToolbarModule } from '@angular/material/toolbar'; import { MatDialogModule } from '@angular/material/dialog'; import { MatInputModule } from '@angular/material/input'; import { MatTooltipModule } from '@angular/material/tooltip'; import { MatSnackBarModule } from '@angular/material/snack-bar'; import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { A11yModule } from '@angular/cdk/a11y'; import { GetTermDescriptionPipe } from './pipes/get-term-description.pipe'; import { AcademicYearStatePipe } from './pipes/academic-year-state.pipe'; @@ -43,6 +45,7 @@ const modules = [ MatSelectModule, FlexLayoutModule, MatSidenavModule, + MatListModule, MatToolbarModule, MatDialogModule, MatInputModule, @@ -52,6 +55,7 @@ const modules = [ MatSnackBarModule, MatProgressBarModule, MatProgressSpinnerModule, + A11yModule, ]; const pipes = [ GetTermDescriptionPipe, -- GitLab