diff --git a/CSETWebApi/CSETWeb_Api/CSETWeb_ApiCore/Controllers/ReportsCmuController.cs b/CSETWebApi/CSETWeb_Api/CSETWeb_ApiCore/Controllers/ReportsCmuController.cs new file mode 100644 index 0000000000..6989068ae1 --- /dev/null +++ b/CSETWebApi/CSETWeb_Api/CSETWeb_ApiCore/Controllers/ReportsCmuController.cs @@ -0,0 +1,96 @@ +//////////////////////////////// +// +// Copyright 2023 Battelle Energy Alliance, LLC +// +// +//////////////////////////////// +using CSETWebCore.DataLayer.Model; +using CSETWebCore.Helpers.ReportWidgets; +using CSETWebCore.Interfaces.AdminTab; +using CSETWebCore.Interfaces.Assessment; +using CSETWebCore.Interfaces.Crr; +using CSETWebCore.Interfaces.Demographic; +using CSETWebCore.Interfaces.Helpers; +using CSETWebCore.Interfaces.Reports; +using Microsoft.AspNetCore.Mvc; +using System.Xml.Linq; +using System.Linq; +using System.Collections.Generic; + +namespace CSETWebCore.Api.Controllers +{ + /// + /// Common API intended to supply report content for EDM, CRR and IMR. + /// + public class ReportsCmuController : Controller + { + private readonly ITokenManager _token; + private readonly ICrrScoringHelper _crr; + private readonly IAssessmentBusiness _assessment; + private readonly IDemographicBusiness _demographic; + private readonly IAssessmentUtil _assessmentUtil; + private readonly IAdminTabBusiness _adminTabBusiness; + private readonly IReportsDataBusiness _report; + private readonly CSETContext _context; + + public ReportsCmuController(ITokenManager token, ICrrScoringHelper crr, IAssessmentBusiness assessment, + IDemographicBusiness demographic, IReportsDataBusiness report, + IAssessmentUtil assessmentUtil, IAdminTabBusiness admin, CSETContext context) + { + _token = token; + _crr = crr; + _assessment = assessment; + _demographic = demographic; + _report = report; + _assessmentUtil = assessmentUtil; + _adminTabBusiness = admin; + _context = context; + } + + + /// + /// Gets the charts for Mil1 Performance and returns them in a list of raw HTML strings. + /// + /// + [HttpGet] + [Route("api/report/cmu/goalperformance")] + public IActionResult GetGoalPerformance() + { + var assessmentId = _token.AssessmentForUser(); + _crr.InstantiateScoringHelper(assessmentId); + var XDocument = _crr.XDoc; + + List scoreBarCharts = new List(); + List stackedBarCharts = new List(); + + foreach (XElement domain in XDocument.Root.Elements()) + { + var domainScores = _crr.MIL1DomainAnswerDistrib(domain.Attribute("abbreviation").Value); + var barChartInput = new BarChartInput() { Height = 50, Width = 75 }; + barChartInput.IncludePercentFirstBar = true; + barChartInput.AnswerCounts = new List { domainScores.Green, domainScores.Yellow, domainScores.Red }; + scoreBarCharts.Add(new ScoreBarChart(barChartInput).ToString()); + + var goals = domain.Descendants("Mil").FirstOrDefault().Descendants("Goal"); + + foreach (XElement goal in goals) + { + var goalScores = _crr.GoalAnswerDistrib(domain.Attribute("abbreviation").Value, + goal.Attribute("abbreviation").Value); + var stackedBarChartInput = new BarChartInput() { Height = 10, Width = 265 }; + stackedBarChartInput.AnswerCounts = new List { goalScores.Green, goalScores.Yellow, goalScores.Red }; + + stackedBarCharts.Add(new { Title = goal.Attribute("title").Value, Chart = new ScoreStackedBarChart(stackedBarChartInput).ToString() }); + } + } + + return Ok(new { ScoreBarCharts = scoreBarCharts, StackedBarCharts = stackedBarCharts }); + } + + + public IActionResult Index() + { + return View(); + } + } +} diff --git a/CSETWebNg/src/app/app-routing.module.ts b/CSETWebNg/src/app/app-routing.module.ts index 6cdf13e2d2..edde35d26b 100644 --- a/CSETWebNg/src/app/app-routing.module.ts +++ b/CSETWebNg/src/app/app-routing.module.ts @@ -201,6 +201,7 @@ import { HydroActionItemsReportComponent } from './reports/hydro/hydro-action-it import { SdAnswerSummaryComponent } from './assessment/results/sd/sd-answer-summary/sd-answer-summary.component'; import { SdAnswerSummaryReportComponent } from './reports/sd/sd-answer-summary-report/sd-answer-summary-report.component'; import { KeyReportComponent } from './assessment/results/reports/key-report/key-report.component'; +import { ImrReportComponent } from './reports/imr/imr-report/imr-report.component'; const appRoutes: Routes = [ @@ -477,6 +478,7 @@ const appRoutes: Routes = [ { path: 'crrCommentsMarked', component: CrrCommentsMarkedComponent }, { path: 'rrareport', component: RraReportComponent }, { path: 'rraDeficiencyReport', component: RraDeficiencyComponent }, + { path: 'imrreport', component: ImrReportComponent }, { path: 'vadrDeficiencyReport', component: VadrDeficiencyComponent }, { path: 'vadrOpenEndedReport', component: OpenEndedQuestionsComponent }, { path: 'cisSurveyReport', component: CisSurveyComponent }, diff --git a/CSETWebNg/src/app/app.module.ts b/CSETWebNg/src/app/app.module.ts index 73b82ecbc1..5333b4aa5b 100644 --- a/CSETWebNg/src/app/app.module.ts +++ b/CSETWebNg/src/app/app.module.ts @@ -578,6 +578,10 @@ import { HydroActionItemsReportComponent } from './reports/hydro/hydro-action-it import { SdAnswerSummaryComponent } from './assessment/results/sd/sd-answer-summary/sd-answer-summary.component'; import { SdAnswerSummaryReportComponent } from './reports/sd/sd-answer-summary-report/sd-answer-summary-report.component'; import { KeyReportComponent } from './assessment/results/reports/key-report/key-report.component'; +import { ImrReportComponent } from './reports/imr/imr-report/imr-report.component'; +import { CmuPerformanceSummaryComponent } from './reports/cmu/cmu-performance-summary/cmu-performance-summary.component'; +import { CmuGoalPerfStackedBarComponent } from './reports/cmu/cmu-goal-perf-stacked-bar/cmu-goal-perf-stacked-bar.component'; +import { CmuResultsDetailComponent } from './reports/cmu/cmu-results-detail/cmu-results-detail.component'; @@ -1017,6 +1021,8 @@ import { KeyReportComponent } from './assessment/results/reports/key-report/key- CrrNistCsfCatSummaryComponent, CrrNistCsfCatPerformanceComponent, CrrSideTocComponent, + CmuPerformanceSummaryComponent, + ImrReportComponent, ReferencesBlockComponent, NewAssessmentDialogComponent, CrrMainTocComponent, @@ -1113,6 +1119,8 @@ import { KeyReportComponent } from './assessment/results/reports/key-report/key- SdAnswerSummaryReportComponent, SdAnswerSummaryComponent, KeyReportComponent, + CmuGoalPerfStackedBarComponent, + CmuResultsDetailComponent, ], providers: [ ConfigService, diff --git a/CSETWebNg/src/app/assessment/questions/maturity-questions/maturity-questions.component.html b/CSETWebNg/src/app/assessment/questions/maturity-questions/maturity-questions.component.html index a2aabd848e..e40939437c 100644 --- a/CSETWebNg/src/app/assessment/questions/maturity-questions/maturity-questions.component.html +++ b/CSETWebNg/src/app/assessment/questions/maturity-questions/maturity-questions.component.html @@ -70,7 +70,7 @@

{{ groupingTitle }}

- Unanswered questions are calculated as a '{{questionsSvc.answerButtonLabel(modelId, this.assessSvc.assessment?.maturityModel?.modelId == 12 ? 'NI' : 'N')}}' response + Unanswered questions are calculated as a '{{questionsSvc.answerButtonLabel(modelName, this.assessSvc.assessment?.maturityModel?.modelId == 12 ? 'NI' : 'N')}}' response

diff --git a/CSETWebNg/src/app/assessment/questions/maturity-questions/maturity-questions.component.ts b/CSETWebNg/src/app/assessment/questions/maturity-questions/maturity-questions.component.ts index 0aac840199..b1c603ac62 100644 --- a/CSETWebNg/src/app/assessment/questions/maturity-questions/maturity-questions.component.ts +++ b/CSETWebNg/src/app/assessment/questions/maturity-questions/maturity-questions.component.ts @@ -154,6 +154,7 @@ export class MaturityQuestionsComponent implements OnInit, AfterViewInit { this.assessSvc.assessment.maturityModel.answerOptions = response.answerOptions; this.filterSvc.answerOptions = response.answerOptions; this.filterSvc.maturityModelId = response.modelId; + this.filterSvc.maturityModelName = response.modelName; this.pageTitle = this.questionsAlias + ' - ' + this.modelName; this.glossarySvc.glossaryEntries = response.glossary; diff --git a/CSETWebNg/src/app/assessment/questions/question-block-ise/question-block-ise.component.html b/CSETWebNg/src/app/assessment/questions/question-block-ise/question-block-ise.component.html index a93f997abd..f505ffd7d0 100644 --- a/CSETWebNg/src/app/assessment/questions/question-block-ise/question-block-ise.component.html +++ b/CSETWebNg/src/app/assessment/questions/question-block-ise/question-block-ise.component.html @@ -108,11 +108,11 @@
diff --git a/CSETWebNg/src/app/assessment/questions/question-block-ise/question-block-ise.component.ts b/CSETWebNg/src/app/assessment/questions/question-block-ise/question-block-ise.component.ts index 961336a14e..93d9551d19 100644 --- a/CSETWebNg/src/app/assessment/questions/question-block-ise/question-block-ise.component.ts +++ b/CSETWebNg/src/app/assessment/questions/question-block-ise/question-block-ise.component.ts @@ -90,6 +90,7 @@ export class QuestionBlockIseComponent implements OnInit { autoGenerateInProgress: boolean = false; maturityModelId: number; + maturityModelName: string; /** @@ -119,6 +120,7 @@ export class QuestionBlockIseComponent implements OnInit { if (this.assessSvc.assessment.maturityModel.modelName != null) { this.answerOptions = this.assessSvc.assessment.maturityModel.answerOptions; this.maturityModelId = this.assessSvc.assessment.maturityModel.modelId; + this.maturityModelName = this.assessSvc.assessment.maturityModel.modelName; this.iseExamLevel = this.ncuaSvc.getExamLevel(); @@ -197,8 +199,8 @@ export class QuestionBlockIseComponent implements OnInit { return "break-all"; } - displayTooltip(maturityModelId: number, option: string) { - let toolTip = this.questionsSvc.answerDisplayLabel(maturityModelId, option); + displayTooltip(maturityModelName: string, option: string) { + let toolTip = this.questionsSvc.answerDisplayLabel(maturityModelName, option); if (toolTip === 'Yes' || toolTip === 'No') { toolTip = ""; } diff --git a/CSETWebNg/src/app/assessment/questions/question-block-maturity/question-block-maturity.component.html b/CSETWebNg/src/app/assessment/questions/question-block-maturity/question-block-maturity.component.html index d88fa3ddb3..c478467d33 100644 --- a/CSETWebNg/src/app/assessment/questions/question-block-maturity/question-block-maturity.component.html +++ b/CSETWebNg/src/app/assessment/questions/question-block-maturity/question-block-maturity.component.html @@ -92,11 +92,11 @@
@@ -148,11 +148,11 @@
diff --git a/CSETWebNg/src/app/assessment/questions/question-block-maturity/question-block-maturity.component.ts b/CSETWebNg/src/app/assessment/questions/question-block-maturity/question-block-maturity.component.ts index b07f5375b0..378e10ce3c 100644 --- a/CSETWebNg/src/app/assessment/questions/question-block-maturity/question-block-maturity.component.ts +++ b/CSETWebNg/src/app/assessment/questions/question-block-maturity/question-block-maturity.component.ts @@ -61,6 +61,7 @@ export class QuestionBlockMaturityComponent implements OnInit { showQuestionIds = false; maturityModelId: number; + maturityModelName: string; /** @@ -86,6 +87,7 @@ export class QuestionBlockMaturityComponent implements OnInit { if (this.assessSvc.assessment.maturityModel.modelName != null) { this.answerOptions = this.assessSvc.assessment.maturityModel.answerOptions; this.maturityModelId = this.assessSvc.assessment.maturityModel.modelId; + this.maturityModelName = this.assessSvc.assessment.maturityModel.modelName; } this.refreshReviewIndicator(); @@ -131,13 +133,12 @@ export class QuestionBlockMaturityComponent implements OnInit { /** * Determines if the level indicator should show or be - * hidden. Someday this behavior might be stored - * in the database as some model-specific behavior. + * hidden. Use config moduleBehavior to define this. */ showLevelIndicator(q): boolean { - // CPG (11) does not have levels - don't show the indicator - if ([11].indexOf(q.maturityModelId) >= 0) { - return false; + const behavior = this.configSvc.config.moduleBehaviors.find(m => m.moduleName == this.assessSvc.assessment.maturityModel.modelName) + if (!!behavior) { + return behavior.showMaturityLevelBadge ?? true; } return true; diff --git a/CSETWebNg/src/app/assessment/questions/question-block-vadr/question-block-vadr.component.html b/CSETWebNg/src/app/assessment/questions/question-block-vadr/question-block-vadr.component.html index 6e051ac6ed..95dd81071d 100644 --- a/CSETWebNg/src/app/assessment/questions/question-block-vadr/question-block-vadr.component.html +++ b/CSETWebNg/src/app/assessment/questions/question-block-vadr/question-block-vadr.component.html @@ -106,11 +106,11 @@
@@ -180,11 +180,11 @@
diff --git a/CSETWebNg/src/app/assessment/questions/question-block/question-block.component.html b/CSETWebNg/src/app/assessment/questions/question-block/question-block.component.html index 3efe89b17f..222e916d5d 100644 --- a/CSETWebNg/src/app/assessment/questions/question-block/question-block.component.html +++ b/CSETWebNg/src/app/assessment/questions/question-block/question-block.component.html @@ -67,19 +67,19 @@ [class.answer-selected]="mySubCategory.subCategoryAnswer === 'Y'"> {{questionsSvc.answerButtonLabel(0, 'Y')}} + [checked]="mySubCategory.subCategoryAnswer === 'Y'">{{questionsSvc.answerButtonLabel('', 'Y')}}