diff --git a/src/app/dars/audit/audit.component.html b/src/app/dars/audit/audit.component.html index bd039f088055bbf2384d80e89b39323b1a6542cf..6a64742dc1241a6026f707977690c4bf3e6c2903 100644 --- a/src/app/dars/audit/audit.component.html +++ b/src/app/dars/audit/audit.component.html @@ -23,8 +23,8 @@ </h3> <div class="audit-section-controles"> - <button mat-stroked-button color="primary">Open All Sections</button> - <button mat-stroked-button color="primary">Close All Sections</button> + <button mat-stroked-button color="primary" (click)="openAllRequirements()">Open All Sections</button> + <button mat-stroked-button color="primary" (click)="closeAllRequirements()">Close All Sections</button> </div> </header> @@ -35,29 +35,65 @@ <p class="tight faded">Courses Used: Using courses from Curse Guide Plan: (Plan name field blank in cobol program "stuinst.)</p> </section> - <section *ngIf="audit.topText.length > 0"> + <!-- <section *ngIf="audit.topText.length > 0"> <p *ngFor="let text of audit.topText" class="text-align-center pre-wrap">{{text}}</p> - </section> - + </section> --> + <section> - <p class="text-align-center">{{audit.completeText}}</p> - </section> + <mat-accordion multi="true" #requirements> - <section *ngFor="let requirement of audit.requirements"> - <h4>{{requirement.requirementName}}</h4> - <p>{{requirement.status.status}} - {{requirement.status.status}}</p> + <!-- START OF REQUIREMENT --> + <ng-container *ngFor="let requirement of audit.requirements"> + + <!-- START OF REQUIREMENT TEXT --> + <ng-container *ngIf="requirement.status.status === 'NONE'; else requirementTemplate"> + <pre *ngFor="let contentType of requirement.requirementLinesGroupedByContentType"> + <p *ngFor="let line of contentType.lines" class="text-align-center">{{line}}</p> + </pre> + </ng-container> + <!-- END OF REQUIREMENT TEXT --> - <div *ngFor="let contentType of requirement.requirementLinesGroupedByContentType"> - <h5>{{contentType.contentType}}</h5> + <!-- START OF ACCORDION REQUIREMENT --> + <ng-template #requirementTemplate> + <mat-expansion-panel> - <p *ngFor="let line of contentType.lines">{{line}}</p> - </div> - </section> + <mat-expansion-panel-header collapsedHeight="auto" expandedHeight="auto"> + <mat-panel-title class="requirement-title status-{{requirement.status.status === 'OK' ? 'ok' : 'no'}}"> + <div class="requirement-icon-outer"> + <mat-icon *ngIf="requirement.status.status === 'OK'" class="requirement-icon ok-icon">check_circle</mat-icon> + <mat-icon *ngIf="requirement.status.status === 'NO'" class="requirement-icon no-icon">cancel</mat-icon> + </div> + <div> + <p *ngFor="let line of getRequirementTitle(requirement)">{{line}}</p> + </div> + </mat-panel-title> + </mat-expansion-panel-header> - <section *ngIf="audit.bottomText.length > 0"> - <p *ngFor="let text of audit.bottomText" class="text-align-center pre-wrap">{{text}}</p> + <div *ngFor="let contentType of getRequirementBody(requirement)"> + + <div class="content-type content-type-{{contentType.contentType}}" matTooltip="{{contentType.contentType}}" matTooltipPosition="left"> + <p *ngFor="let line of contentType.lines">{{line}}</p> + </div> + </div> + + </mat-expansion-panel> + </ng-template> + <!-- END OF ACCORDION REQUIREMENT --> + + </ng-container> + <!-- END OF REQUIREMENT --> + + </mat-accordion> </section> + + + <!-- <section *ngIf="audit.bottomText.length > 0"> + <pre style="margin:auto;"> + <p *ngFor="let text of audit.bottomText">{{text}}</p> + </pre> + </section> --> + <!-- Not sure where this info comes from? --> <!-- <section class="text-align-center"> <h4 class="mat-h2 uppercase faded">At least one requirment has not been satisfied</h4> diff --git a/src/app/dars/audit/audit.component.scss b/src/app/dars/audit/audit.component.scss index 7e191bda02d57076f42b7e75702c8d5c1859394e..f4796d37b6005c188b0705bf2452da18ce5d794a 100644 --- a/src/app/dars/audit/audit.component.scss +++ b/src/app/dars/audit/audit.component.scss @@ -79,3 +79,48 @@ section { .pre-wrap { white-space: pre-wrap; } + +.requirement-title { + display: flex; + justify-content: flex-start; + font-size: 1.35rem; + + &.status-ok { + color: #2e7d32; + } + + &.status-no { + color: #c5050c; + } +} + +.requirement-icon-outer { + margin: 20px 15px 0 0; + font-size: 1.75rem; +} + +.content-type { + margin-bottom: 5px; + + > p { + margin: 2.5px auto; + } +} + +.content-type-okSubrequirementTLine, +.content-type-noSubrequirementTLine { + margin-top: 20px; +} + +.content-type-okSubrequirementCourses, +.content-type-noSubrequirementCourses { + color: #0479a8; + margin-left: 20px; +} + +.content-type-okSubrequirementNeedsSummaryLine, +.content-type-noSubrequirementNeedsSummaryLine, +.content-type-noRequirementNeedsLine { + color: #c5050c; + margin-left: 20px; +} diff --git a/src/app/dars/audit/audit.component.ts b/src/app/dars/audit/audit.component.ts index d77729943a6590ce549a3b75237c18714aa83c2b..24bd027424b697aa5dc4d767f7632470385cc574 100644 --- a/src/app/dars/audit/audit.component.ts +++ b/src/app/dars/audit/audit.component.ts @@ -1,4 +1,11 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, ViewChild } from '@angular/core'; +import { Audit, Requirement, ContentType } from '../models/audit'; +import { DarsApiService } from '../services/api.service'; +import { Store } from '@ngrx/store'; +import { GlobalState } from '@app/core/state'; +import * as selectors from '../store/selectors'; +import { Observable } from 'rxjs'; +import { MatAccordion } from '@angular/material'; @Component({ selector: 'cse-dars-audit', @@ -7,5 +14,33 @@ import { Component, Input } from '@angular/core'; }) export class DarsAuditComponent { public metadata: any = {}; - public audit: any = {}; + public auditId: number; + @Input() audit: Audit; + + @ViewChild('requirements') requirements: MatAccordion; + + public openAllRequirements() { + this.requirements.openAll(); + } + + public closeAllRequirements() { + this.requirements.closeAll(); + } + + public getRequirementTitle(requirement: Requirement): string[] { + const title = requirement.requirementLinesGroupedByContentType.find( + r => + r.contentType === 'okRequirementTitle' || + r.contentType === 'noRequirementTitle', + ); + return title ? title.lines : ['No title found']; + } + + public getRequirementBody(requirement: Requirement): ContentType[] { + return requirement.requirementLinesGroupedByContentType.filter( + r => + r.contentType !== 'okRequirementTitle' && + r.contentType !== 'noRequirementTitle', + ); + } } diff --git a/src/app/dars/dars-view/dars-view.component.html b/src/app/dars/dars-view/dars-view.component.html index 00ef9c9625a3032dfcfbba251e2e56ad4320846d..43460d6e77db0c63093ea9ac7ee3c0fc692ae9c4 100644 --- a/src/app/dars/dars-view/dars-view.component.html +++ b/src/app/dars/dars-view/dars-view.component.html @@ -8,7 +8,7 @@ <div *ngIf="(visibleAuditStatus$ | async) == 'Loaded'; then loadedAudit else loadingAudit"></div> <ng-template #loadedAudit> - <cse-dars-audit></cse-dars-audit> + <cse-dars-audit [audit]="audit$ | async"></cse-dars-audit> </ng-template> <ng-template #loadingAudit> <img id="loading-bucky" src="../../../assets/img/bucky-happy.svg" alt="Happy Bucky Badger"> diff --git a/src/app/dars/dars-view/dars-view.component.ts b/src/app/dars/dars-view/dars-view.component.ts index 0396ee02c11464e720511e69228908910b69f831..fbf5331b773049a2f1aaab2142bca9a12db85812 100644 --- a/src/app/dars/dars-view/dars-view.component.ts +++ b/src/app/dars/dars-view/dars-view.component.ts @@ -8,6 +8,8 @@ import { GlobalState } from '@app/core/state'; import * as selectors from '../store/selectors'; import { Observable } from 'rxjs'; import * as darsActions from '../store/actions'; +import { Audit } from '../models/audit'; +import { DarsApiService } from '../services/api.service'; @Component({ selector: 'cse-dars-view', @@ -17,13 +19,20 @@ import * as darsActions from '../store/actions'; export class DARSViewComponent implements OnInit { public metadataStatus$: Observable<DARSState['metadata']['status']>; public visibleAuditStatus$: Observable<DARSState['visibleAudit']['status']>; + public audit$: Observable<Audit | null>; - constructor(private store: Store<GlobalState>, public dialog: MatDialog) {} + constructor( + private store: Store<GlobalState>, + public dialog: MatDialog, + private api: DarsApiService, + ) {} public ngOnInit() { this.store.dispatch(new darsActions.StartLoadingMetadata()); this.metadataStatus$ = this.store.select(selectors.metadataStatus); this.visibleAuditStatus$ = this.store.select(selectors.visibleAuditStatus); + // this.audit$ = this.store.select(selectors.visibleAudit); + this.audit$ = this.api.getAudit(3); } public openNewAuditOptionsDialog() { @@ -31,7 +40,7 @@ export class DARSViewComponent implements OnInit { } public openAudit(metadata: AuditMetadata) { - this.store.dispatch(new darsActions.StartLoadingAudit({ metadata })); + this.store.dispatch(new darsActions.StartLoadingAudit(metadata)); } public closeAudit() { diff --git a/src/app/dars/metadata-table/metadata-table.component.ts b/src/app/dars/metadata-table/metadata-table.component.ts index 139df52d1896bddbef70b45e83ded9019a92f0bf..40301ce6d9a6346c2cd9dcbe81dbc1b97b34e09a 100644 --- a/src/app/dars/metadata-table/metadata-table.component.ts +++ b/src/app/dars/metadata-table/metadata-table.component.ts @@ -30,6 +30,6 @@ export class DarsMetadataTableComponent implements OnInit { } public openAudit(metadata: AuditMetadata) { - this.store.dispatch(new StartLoadingAudit({ metadata })); + this.store.dispatch(new StartLoadingAudit(metadata)); } } diff --git a/src/app/dars/models/audit.ts b/src/app/dars/models/audit.ts index d318d640eeb364d1ac3864ccc5aee03649bcdc96..d2899eccacaf74eed24bf7472412e335a5aadb5e 100644 --- a/src/app/dars/models/audit.ts +++ b/src/app/dars/models/audit.ts @@ -1,25 +1,27 @@ +export interface ContentType { + contentType: + | 'blankLine' + | 'hText' + | 'noRequirementNeedsLine' + | 'noRequirementTitle' + | 'noSubrequirementAcceptCourses' + | 'noSubrequirementCourses' + | 'noSubrequirementNeedsSummaryLine' + | 'noSubrequirementRejectCourses' + | 'noSubrequirementTLine' + | 'okRequirementTitle' + | 'okSubrequirementAcceptCourses' + | 'okSubrequirementCourses' + | 'okSubrequirementEarnedLine' + | 'okSubrequirementNeedsSummaryLine' + | 'okSubrequirementTLine'; + lines: string[]; +} + export interface Requirement { requirementName: string; status: { status: string; description: string }; - requirementLinesGroupedByContentType: { - contentType: - | 'blankLine' - | 'hText' - | 'noRequirementNeedsLine' - | 'noRequirementTitle' - | 'noSubrequirementAcceptCourses' - | 'noSubrequirementCourses' - | 'noSubrequirementNeedsSummaryLine' - | 'noSubrequirementRejectCourses' - | 'noSubrequirementTLine' - | 'okRequirementTitle' - | 'okSubrequirementAcceptCourses' - | 'okSubrequirementCourses' - | 'okSubrequirementEarnedLine' - | 'okSubrequirementNeedsSummaryLine' - | 'okSubrequirementTLine'; - lines: string[]; - }[]; + requirementLinesGroupedByContentType: ContentType[]; } export interface Audit { diff --git a/src/app/dars/store/actions.ts b/src/app/dars/store/actions.ts index 43d1a9c2ba5a89f4b97bf15d4219e6dc81000a7d..88103373119060a2f8c88d6cb965c31c5047cc1d 100644 --- a/src/app/dars/store/actions.ts +++ b/src/app/dars/store/actions.ts @@ -40,7 +40,7 @@ export class AddAuditMetadata implements Action { export class StartLoadingAudit implements Action { public readonly type = DarsActionTypes.StartLoadingAudit; - constructor(public payload: { metadata: AuditMetadata }) {} + constructor(public payload: AuditMetadata) {} } export class DoneLoadingAudit implements Action { diff --git a/src/app/dars/store/effects.ts b/src/app/dars/store/effects.ts index ec73776b9a436c4cb0170e626336e111456b16e2..82b4b08eb8b97378d3c9153a9036d458db87d407 100644 --- a/src/app/dars/store/effects.ts +++ b/src/app/dars/store/effects.ts @@ -7,7 +7,7 @@ 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, switchMap } from 'rxjs/operators'; +import { flatMap, map, catchError, switchMap, mergeMap } from 'rxjs/operators'; import { DarsApiService } from '../services/api.service'; import { of } from 'rxjs'; import { Alert, DarsDisclaimerAlert } from '@app/core/models/alert'; @@ -70,4 +70,17 @@ export class DARSEffects { // ); // }), ); + + @Effect() + getAudit$ = this.actions$.pipe( + ofType(DarsActionTypes.StartLoadingAudit), + flatMap((action: darsActions.StartLoadingAudit) => { + const metadata = action.payload; + return this.api.getAudit(metadata.darsDegreeAuditReportId).pipe( + map(audit => { + return new darsActions.DoneLoadingAudit({ metadata, audit }); + }), + ); + }), + ); } diff --git a/src/app/dars/store/reducer.ts b/src/app/dars/store/reducer.ts index bbb811d3c7f683ccc8a9c952c75a37534efaab14..e92144a7feed32d40debc2d0de4bfafcf7c492a8 100644 --- a/src/app/dars/store/reducer.ts +++ b/src/app/dars/store/reducer.ts @@ -47,7 +47,7 @@ export function darsReducer( ...state, visibleAudit: { status: 'Loading', - metadata: action.payload.metadata, + metadata: action.payload, }, }; }