Skip to content

Commit 5776ea3

Browse files
authored
Merge pull request #308 from NREL/issue-264
Issue 264: Maintenance Cost KPI
2 parents 70d363f + 5fb2f0e commit 5776ea3

File tree

13 files changed

+340
-52
lines changed

13 files changed

+340
-52
lines changed

src/app/setup-wizard/data-collection/on-site-assessment/neb-forms-accordion/neb-setup-form/performance-metric-impact-form/performance-metric-impact-form.component.html

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,13 @@
5353
</div>
5454
</div>
5555
</div>
56+
<div class="form-block">
57+
<app-kpm-details-form [keyPerformanceMetric]="keyPerformanceMetric"
58+
[disableForm]="(metricHasOtherImpacts && !overrideBaseline)" (emitSave)="savePerformanceMetric()"
59+
(emitCalculate)="calculateCostFromKPM($event)" [context]="'onSite'"></app-kpm-details-form>
5660

57-
<ng-template [ngIf]="keyPerformanceMetric.isQuantitative" [ngIfElse]="qualitativeMetricBlock">
58-
<div class="form-block">
59-
<app-kpm-details-form [keyPerformanceMetric]="keyPerformanceMetric"
60-
[disableForm]="(metricHasOtherImpacts && !overrideBaseline)" (emitSave)="savePerformanceMetric()"
61-
(emitCalculate)="calculateCost()" [context]="'onSite'"></app-kpm-details-form>
61+
62+
<ng-template [ngIf]="keyPerformanceMetric.isQuantitative">
6263
<div class="row">
6364
<label class="col-sm-6 col-form-label" for="modificationValue">
6465
Impact on KPM
@@ -111,13 +112,8 @@
111112
</ng-template>
112113
</div>
113114
</div>
114-
</div>
115-
</ng-template>
116-
<ng-template #qualitativeMetricBlock>
117-
<div class="alert alert-info small">
118-
Quantitative results unavailable at this time.
119-
</div>
120-
</ng-template>
115+
</ng-template>
116+
</div>
121117
</div>
122118
</ng-template>
123119
<ng-template #missingMetricBlock>

src/app/setup-wizard/data-collection/on-site-assessment/neb-forms-accordion/neb-setup-form/performance-metric-impact-form/performance-metric-impact-form.component.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ export class PerformanceMetricImpactFormComponent {
8383
await this.keyPerformanceMetricImpactIdbService.asyncUpdate(this.keyPerformanceMetricImpact);
8484
}
8585

86+
calculateCostFromKPM(kpmChanges: {modifiedMethod: boolean, updateBaseline: boolean}){
87+
if(kpmChanges.modifiedMethod){
88+
this.keyPerformanceMetricImpact.modificationValue = undefined;
89+
}
90+
this.calculateCost();
91+
}
92+
93+
8694
calculateCost() {
8795
if (this.keyPerformanceMetric.calculationMethod == 'costPerUnit') {
8896
this.keyPerformanceMetricImpact.costAdjustment = (this.keyPerformanceMetricImpact.modificationValue * this.keyPerformanceMetric.costPerValue);

src/app/setup-wizard/pre-visit/company-kpi-details/company-kpi-details.component.html

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,34 @@ <h6>
9595
Associated Key Performance Metrics
9696
</div>
9797
<div>
98-
<button class="btn btn-outline-metric btn-sm" (click)="addPerformanceMetric()">
99-
<fa-icon [icon]="faPlus"></fa-icon>
100-
Add New Metric
101-
</button>
98+
<ng-template [ngIf]="keyPerformanceIndicator.optionValue != 'other'"
99+
[ngIfElse]="customAddBlock">
100+
<div class="dropdown">
101+
<button class="btn btn-outline-metric btn-sm dropdown-toggle" type="button"
102+
data-bs-toggle="dropdown" aria-expanded="false"
103+
(click)="toggleAddMetricDropdown()">
104+
<fa-icon [icon]="faPlus"></fa-icon> Add Performance Metric
105+
</button>
106+
<ul class="dropdown-menu" [ngClass]="{'show': showAddMetricDropdown}">
107+
<li>
108+
<a class="dropdown-item" (click)="addPerformanceMetric()">
109+
<fa-icon [icon]="faPlus"></fa-icon> Add Custom Performance Metric
110+
</a>
111+
</li>
112+
<li>
113+
<a class="dropdown-item" (click)="showSuggestedMetrics()">
114+
<fa-icon [icon]="faSearchPlus"></fa-icon> Search Performance Metric
115+
</a>
116+
</li>
117+
</ul>
118+
</div>
119+
</ng-template>
120+
<ng-template #customAddBlock>
121+
<button class="btn btn-outline-metric btn-sm" (click)="addPerformanceMetric()">
122+
<fa-icon [icon]="faPlus"></fa-icon>
123+
Add Custom Performance Metric
124+
</button>
125+
</ng-template>
102126
</div>
103127
</div>
104128
</h6>
@@ -244,4 +268,8 @@ <h6>
244268
KPM</button>
245269
</div>
246270
</ng-template>
247-
</div>
271+
</div>
272+
273+
274+
<app-kpm-database-modal *ngIf="displayAddMetricModal" (emitClose)="closeSuggestedMetrics()"
275+
[keyPerformanceIndicator]="keyPerformanceIndicator" (emitAddMetrics)="addMetrics($event)"></app-kpm-database-modal>

src/app/setup-wizard/pre-visit/company-kpi-details/company-kpi-details.component.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Component } from '@angular/core';
22
import { ActivatedRoute, Router } from '@angular/router';
3-
import { IconDefinition, faBullseye, faChartBar, faChevronLeft, faChevronRight, faCircleQuestion, faClose, faContactBook, faPlus, faScaleUnbalancedFlip, faTrash, faUser } from '@fortawesome/free-solid-svg-icons';
3+
import { IconDefinition, faBullseye, faChartBar, faChevronLeft, faChevronRight, faCircleQuestion, faClose, faContactBook, faPlus, faScaleUnbalancedFlip, faSearchPlus, faTrash, faUser } from '@fortawesome/free-solid-svg-icons';
44
import { IdbOnSiteVisit } from 'src/app/models/onSiteVisit';
55
import { OnSiteVisitIdbService } from 'src/app/indexed-db/on-site-visit-idb.service';
66
import { CompanyIdbService } from 'src/app/indexed-db/company-idb.service';
@@ -30,6 +30,7 @@ export class CompanyKpiDetailsComponent {
3030
faContactBook: IconDefinition = faContactBook;
3131
faClose: IconDefinition = faClose;
3232
faTrash: IconDefinition = faTrash;
33+
faSearchPlus: IconDefinition = faSearchPlus;
3334

3435
keyPerformanceIndicator: IdbKeyPerformanceIndicator;
3536
primaryKPIs: Array<PrimaryKPI> = PrimaryKPIs;
@@ -61,6 +62,9 @@ export class CompanyKpiDetailsComponent {
6162

6263
timeOptions: Array<string> = ['day', 'week', 'month', 'year'];
6364
dropdownMenuGuid: string;
65+
66+
displayAddMetricModal: boolean = false;
67+
showAddMetricDropdown: boolean = false;
6468
constructor(private router: Router,
6569
private onSiteVisitIdbService: OnSiteVisitIdbService,
6670
private keyPerformanceIndicatorIdbService: KeyPerformanceIndicatorsIdbService,
@@ -90,6 +94,7 @@ export class CompanyKpiDetailsComponent {
9094
let kpiGuid: string = params['id'];
9195
this.keyPerformanceIndicator = this.keyPerformanceIndicatorIdbService.getByGuid(kpiGuid);
9296
this.setIndexValues();
97+
this.showAddMetricDropdown = false;
9398
});
9499
}
95100

@@ -172,6 +177,9 @@ export class CompanyKpiDetailsComponent {
172177
}
173178

174179
addPerformanceMetric() {
180+
if (this.showAddMetricDropdown) {
181+
this.showAddMetricDropdown = false;
182+
}
175183
let newCustomKPM: KeyPerformanceMetric = getCustomKPM(this.keyPerformanceIndicator.optionValue, this.keyPerformanceIndicator.guid);
176184
this.keyPerformanceIndicator.performanceMetrics.unshift(newCustomKPM);
177185
this.saveChanges();
@@ -211,4 +219,27 @@ export class CompanyKpiDetailsComponent {
211219
this.dropdownMenuGuid = undefined;
212220
}
213221
}
222+
223+
toggleAddMetricDropdown() {
224+
this.showAddMetricDropdown = !this.showAddMetricDropdown;
225+
}
226+
227+
showSuggestedMetrics() {
228+
if (this.showAddMetricDropdown) {
229+
this.showAddMetricDropdown = false;
230+
}
231+
this.displayAddMetricModal = true;
232+
}
233+
234+
closeSuggestedMetrics() {
235+
this.displayAddMetricModal = false;
236+
}
237+
238+
addMetrics(metrics: Array<KeyPerformanceMetric>) {
239+
metrics.forEach(metric => {
240+
this.keyPerformanceIndicator.performanceMetrics.unshift(metric);
241+
})
242+
this.saveChanges();
243+
}
244+
214245
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.popup-header{
2+
font-weight: normal;
3+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<div [ngClass]="{'window-overlay': displayModal}"></div>
2+
<div class="popup" [ngClass]="{'open': displayModal }">
3+
<div class="popup-header">KPMs Typically Associated With
4+
<span class="bold" [innerHTML]="keyPerformanceIndicator.htmlLabel"></span>
5+
<button type="button" class="btn-close float-end" aria-label="Close" (click)="closeModal()"></button>
6+
</div>
7+
<div class="popup-body">
8+
<ng-template [ngIf]="keyPerformanceMetricOptions.length > 0" [ngIfElse]="noOptionsBlock">
9+
<table class="table table-bordered table-hover table-sm">
10+
<tbody>
11+
<tr class="clickable" (click)="toggleMetric(performanceMetric)"
12+
*ngFor="let performanceMetric of keyPerformanceMetricOptions">
13+
<td class="add-td text-center">
14+
<a class="click-link">
15+
<ng-template [ngIf]="addMetricValues.includes(performanceMetric.value)"
16+
[ngIfElse]="addMetricBlock">
17+
<fa-icon [icon]="faCheck"></fa-icon>
18+
</ng-template>
19+
<ng-template #addMetricBlock>
20+
<fa-icon [icon]="faPlus"></fa-icon>
21+
</ng-template>
22+
</a>
23+
</td>
24+
<td>
25+
<span [innerHTML]="performanceMetric.htmlLabel"></span>
26+
</td>
27+
</tr>
28+
</tbody>
29+
</table>
30+
</ng-template>
31+
<ng-template #noOptionsBlock>
32+
<div class="alert alert-info">
33+
All metrics in our system that are associated with <span class="bold"
34+
[innerHTML]="keyPerformanceIndicator.htmlLabel"></span> are being tracked.
35+
</div>
36+
</ng-template>
37+
<hr>
38+
</div>
39+
<div class="popup-footer d-flex justify-content-end">
40+
<button class="btn btn-secondary btn-sm me-2" (click)="closeModal()">Cancel</button>
41+
<button class="btn btn-sm btn-success" (click)="addMetrics()" [disabled]="addMetricValues.length == 0"><fa-icon
42+
[icon]="faPlus"></fa-icon> Add {{addMetricValues.length}}
43+
Metrics</button>
44+
</div>
45+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { KpmDatabaseModalComponent } from './kpm-database-modal.component';
4+
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
5+
import { getNewKeyPerformanceIndicator } from 'src/app/models/keyPerformanceIndicator';
6+
import { KeyPerformanceIndicatorOption } from 'src/app/shared/constants/keyPerformanceIndicatorOptions';
7+
8+
describe('KpmDatabaseModalComponent', () => {
9+
let component: KpmDatabaseModalComponent;
10+
let fixture: ComponentFixture<KpmDatabaseModalComponent>;
11+
12+
beforeEach(async () => {
13+
await TestBed.configureTestingModule({
14+
imports: [FontAwesomeModule],
15+
declarations: [KpmDatabaseModalComponent]
16+
})
17+
.compileComponents();
18+
19+
fixture = TestBed.createComponent(KpmDatabaseModalComponent);
20+
component = fixture.componentInstance;
21+
let tmpIndicatorOption: KeyPerformanceIndicatorOption = {
22+
primaryKPI: 'Operations',
23+
label: '',
24+
htmlLabel: '',
25+
optionValue: 'chemicalEmissions'
26+
}
27+
component.keyPerformanceIndicator = getNewKeyPerformanceIndicator('', '', tmpIndicatorOption, false)
28+
fixture.detectChanges();
29+
});
30+
31+
it('should create', () => {
32+
expect(component).toBeTruthy();
33+
});
34+
});
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core';
2+
import { faCheck, faPlus, IconDefinition } from '@fortawesome/free-solid-svg-icons';
3+
import { IdbKeyPerformanceIndicator } from 'src/app/models/keyPerformanceIndicator';
4+
import { getPerformanceMetrics, KeyPerformanceMetric, KeyPerformanceMetricValue } from 'src/app/shared/constants/keyPerformanceMetrics';
5+
6+
@Component({
7+
selector: 'app-kpm-database-modal',
8+
templateUrl: './kpm-database-modal.component.html',
9+
styleUrl: './kpm-database-modal.component.css'
10+
})
11+
export class KpmDatabaseModalComponent {
12+
@Output('emitClose')
13+
emitClose: EventEmitter<boolean> = new EventEmitter<boolean>();
14+
@Input({ required: true })
15+
keyPerformanceIndicator: IdbKeyPerformanceIndicator;
16+
@Output()
17+
emitAddMetrics: EventEmitter<Array<KeyPerformanceMetric>> = new EventEmitter<Array<KeyPerformanceMetric>>();
18+
19+
faPlus: IconDefinition = faPlus;
20+
faCheck: IconDefinition = faCheck;
21+
displayModal: boolean = false;
22+
23+
keyPerformanceMetricOptions: Array<KeyPerformanceMetric>;
24+
addMetricValues: Array<KeyPerformanceMetricValue> = [];
25+
constructor(private cd: ChangeDetectorRef) {
26+
27+
}
28+
29+
ngOnInit() {
30+
let currentTrackedMetrics: Array<KeyPerformanceMetricValue> = this.keyPerformanceIndicator.performanceMetrics.flatMap(metric => {
31+
return metric.value;
32+
})
33+
34+
this.keyPerformanceMetricOptions = new Array();
35+
36+
let tmpKeyPerformanceMetricOptions: Array<KeyPerformanceMetric> = getPerformanceMetrics(this.keyPerformanceIndicator.optionValue, this.keyPerformanceIndicator.guid)
37+
tmpKeyPerformanceMetricOptions.forEach(option => {
38+
if (currentTrackedMetrics.includes(option.value) == false) {
39+
this.keyPerformanceMetricOptions.push(option);
40+
}
41+
});
42+
}
43+
44+
ngAfterViewInit() {
45+
this.displayModal = true;
46+
this.cd.detectChanges();
47+
}
48+
49+
closeModal() {
50+
this.displayModal = false;
51+
this.emitClose.emit(true);
52+
}
53+
54+
toggleMetric(keyPerformanceMetric: KeyPerformanceMetric) {
55+
if (this.addMetricValues.includes(keyPerformanceMetric.value)) {
56+
this.addMetricValues = this.addMetricValues.filter(value => {
57+
return value != keyPerformanceMetric.value
58+
});
59+
} else {
60+
this.addMetricValues.push(keyPerformanceMetric.value);
61+
}
62+
}
63+
64+
addMetrics() {
65+
let metricsToAdd: Array<KeyPerformanceMetric> = this.keyPerformanceMetricOptions.filter(option => {
66+
return this.addMetricValues.includes(option.value)
67+
})
68+
this.emitAddMetrics.emit(metricsToAdd);
69+
this.closeModal();
70+
}
71+
}

src/app/setup-wizard/setup-wizard.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import { SetupWizardHelpPanelModule } from './setup-wizard-help-panel/setup-wiza
6262
import { LabelWithTooltipModule } from '../shared/label-with-tooltip/label-with-tooltip.module';
6363
import { KpmDetailsFormModule } from '../shared/kpm-details-form/kpm-details-form.module';
6464
import { KpiDescriptionPipe } from './pre-visit/company-kpi-details/kpi-description.pipe';
65+
import { KpmDatabaseModalComponent } from './pre-visit/company-kpi-details/kpm-database-modal/kpm-database-modal.component';
6566

6667
@NgModule({
6768
declarations: [
@@ -114,7 +115,8 @@ import { KpiDescriptionPipe } from './pre-visit/company-kpi-details/kpi-descript
114115
KpmImpactsTableComponent,
115116
EnergyOpportunityNebsTableComponent,
116117
EnergyOpportunityNebsListPipe,
117-
KpiDescriptionPipe
118+
KpiDescriptionPipe,
119+
KpmDatabaseModalComponent
118120
],
119121
imports: [
120122
CommonModule,

src/app/shared/constants/keyPerformanceIndicatorOptions.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export type KeyPerformanceIndicatorValue =
1919
'improveSpaceUtilization' |
2020
'employeeEngagementWorkforceDevelopment' |
2121
'employeeEngagementWorkingEnvironment' |
22+
'maintenanceExpense' |
2223
'other';
2324

2425
export interface KeyPerformanceIndicatorOption {
@@ -67,8 +68,8 @@ export const KeyPerformanceIndicatorOptions: Array<KeyPerformanceIndicatorOption
6768
},
6869
{
6970
primaryKPI: 'Operations',
70-
label: 'Reduce Expense Cost',
71-
htmlLabel: 'Reduce Expense Cost',
71+
label: 'Expense Cost',
72+
htmlLabel: 'Expense Cost',
7273
optionValue: 'reduceExpenseCost'
7374
},
7475
{
@@ -137,4 +138,10 @@ export const KeyPerformanceIndicatorOptions: Array<KeyPerformanceIndicatorOption
137138
htmlLabel: 'Employee Engagement - Workforce Development',
138139
optionValue: 'employeeEngagementWorkforceDevelopment'
139140
},
141+
{
142+
primaryKPI: 'Operations',
143+
label: 'Maintenance Expense',
144+
htmlLabel: 'Maintenance Expense',
145+
optionValue: 'maintenanceExpense'
146+
},
140147
]

0 commit comments

Comments
 (0)