Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions backend/src/services/target-calculation-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,8 @@
const userTimeSavings = distinctUsers.map(userId => {
const userSurveys = this.surveysWeekly.filter(survey => survey.userId === userId);
const totalPercent = userSurveys.reduce((sum, survey) => {
const percentTimeSaved = typeof survey.percentTimeSaved === 'number' ? survey.percentTimeSaved : 0;
// Always parse percentTimeSaved as float
const percentTimeSaved = survey.percentTimeSaved != null ? parseFloat(survey.percentTimeSaved as any) : 0;

Check failure

Code scanning / ESLint

Disallow the `any` type Error

Unexpected any. Specify a different type.
return sum + percentTimeSaved;
}, 0);
return totalPercent / userSurveys.length; // Average percent time saved per user
Expand All @@ -711,17 +712,17 @@
// Average across all users
const avgPercentTimeSaved = userTimeSavings.reduce((sum, percent) => sum + percent, 0) / userTimeSavings.length;

// Convert settings values to numbers
const hoursPerYear = typeof this.settings.hoursPerYear === 'number' ? this.settings.hoursPerYear : 2000;
const percentCoding = typeof this.settings.percentCoding === 'number' ? this.settings.percentCoding : 50;
// Convert settings values to numbers (parse from string if needed)
const hoursPerYear = this.settings.hoursPerYear != null ? parseFloat(this.settings.hoursPerYear as any) : 2000;

Check failure

Code scanning / ESLint

Disallow the `any` type Error

Unexpected any. Specify a different type.
const percentCoding = this.settings.percentCoding != null ? parseFloat(this.settings.percentCoding as any) : 50;

Check failure

Code scanning / ESLint

Disallow the `any` type Error

Unexpected any. Specify a different type.

// Calculate weekly hours saved based on settings and average percent
const weeklyHours = hoursPerYear / 50; // Assuming 50 working weeks
const weeklyDevHours = weeklyHours * (percentCoding / 100);
const avgWeeklyTimeSaved = weeklyDevHours * (avgPercentTimeSaved / 100);

// Calculate max based on settings
const maxPercentTimeSaved = typeof this.settings.percentTimeSaved === 'number' ? this.settings.percentTimeSaved : 20;
const maxPercentTimeSaved = this.settings.percentTimeSaved != null ? parseFloat(this.settings.percentTimeSaved as any) : 20;

Check failure

Code scanning / ESLint

Disallow the `any` type Error

Unexpected any. Specify a different type.
const maxWeeklyTimeSaved = weeklyDevHours * (maxPercentTimeSaved / 100);

const result = {
Expand Down Expand Up @@ -785,11 +786,11 @@
const adoptedDevs = this.calculateAdoptedDevs().current;
const weeklyTimeSavedHrs = this.calculateWeeklyTimeSavedHrs().current;

// Ensure all values are properly typed as numbers
const hoursPerYear = typeof this.settings.hoursPerYear === 'number' ? this.settings.hoursPerYear : 2000;
// Always parse settings values as numbers (from string if needed)
const hoursPerYear = this.settings.hoursPerYear != null ? parseFloat(this.settings.hoursPerYear as any) : 2000;

Check failure

Code scanning / ESLint

Disallow the `any` type Error

Unexpected any. Specify a different type.
const weeksInYear = Math.round(hoursPerYear / 40) || 50; // Calculate weeks and ensure it's a number

const devCostPerYear = typeof this.settings.devCostPerYear === 'number' ? this.settings.devCostPerYear : 0;
const devCostPerYear = this.settings.devCostPerYear != null ? parseFloat(this.settings.devCostPerYear as any) : 0;

Check failure

Code scanning / ESLint

Disallow the `any` type Error

Unexpected any. Specify a different type.
const hourlyRate = devCostPerYear > 0 ? (devCostPerYear / hoursPerYear) : 50;

const annualSavings = weeklyTimeSavedHrs * weeksInYear * hourlyRate * adoptedDevs;
Expand Down Expand Up @@ -824,8 +825,8 @@
const adoptedDevs = this.calculateAdoptedDevs().current;
const weeklyTimeSavedHrs = this.calculateWeeklyTimeSavedHrs().current;

// Convert hours per year to number
const hoursPerYear = typeof this.settings.hoursPerYear === 'number' ? this.settings.hoursPerYear : 2000;
// Always parse hours per year as number
const hoursPerYear = this.settings.hoursPerYear != null ? parseFloat(this.settings.hoursPerYear as any) : 2000;

Check failure

Code scanning / ESLint

Disallow the `any` type Error

Unexpected any. Specify a different type.
const hoursPerWeek = hoursPerYear / 50 || 40; // Default to 40 if undefined

// Calculate productivity boost factor (not percentage)
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
<div class="page-container">
<div class="page-header">
<h1>Value Modeling & Targeting</h1>
<button mat-stroked-button color="warn" style="margin-left: 2rem;" (click)="resetTargets()">
<mat-icon>refresh</mat-icon>
Recalculate Targets
</button>
<button *ngIf="showSaveAllButton" mat-stroked-button color="primary" style="margin-left: 1rem;" (click)="saveTargets()">
<mat-icon>save</mat-icon>
Save All Targets
</button>
</div>

<h4 style="margin-top: 0">Org Metrics</h4>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
orgDataSource: TableTarget[] = [];
userDataSource: TableTarget[] = [];
impactDataSource: TableTarget[] = [];
showSaveAllButton = false;
private readonly _destroy$ = new Subject<void>();
keyToNameMap: Record<string, string> = {
seats: 'Seats',
Expand Down Expand Up @@ -128,7 +129,9 @@

saveTargets() {
const targets: Targets = this.transformBackToTargets(this.orgDataSource, this.userDataSource, this.impactDataSource);
this.targetsService.saveTargets(targets).subscribe();
this.targetsService.saveTargets(targets).subscribe(() => {
this.showSaveAllButton = false;
});
}

openEditDialog(target: Target) {
Expand All @@ -144,6 +147,17 @@
}
});
}

resetTargets() {
// Call the backend endpoint to recalculate targets
this.targetsService.recalculateTargets().subscribe((result: any) => {

Check failure

Code scanning / ESLint

Disallow the `any` type Error

Unexpected any. Specify a different type.
const targets = result.targets || result; // handle both {targets, logs} and just targets
this.orgDataSource = this.transformTargets(targets.org);
this.userDataSource = this.transformTargets(targets.user);
this.impactDataSource = this.transformTargets(targets.impact);
this.showSaveAllButton = true;
});
}
}

@Component({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class TimeSavedChartComponent implements OnInit, OnChanges {
text: 'Time Saved (Hrs per Week)'
},
min: 0,
max: 10,
max: 10, // Will be updated dynamically
labels: {
format: '{value}hrs'
},
Expand All @@ -45,7 +45,7 @@ export class TimeSavedChartComponent implements OnInit, OnChanges {
}
}],
plotLines: [{
value: 5,
value: 5, // Will be updated dynamically
color: 'var(--sys-primary)',
dashStyle: 'Dash',
width: 2,
Expand Down Expand Up @@ -91,6 +91,7 @@ export class TimeSavedChartComponent implements OnInit, OnChanges {
this._chartOptions.yAxis = Object.assign({}, this.chartOptions?.yAxis, this._chartOptions.yAxis);
this._chartOptions.tooltip = Object.assign({}, this.chartOptions?.tooltip, this._chartOptions.tooltip);
this._chartOptions = Object.assign({}, this.chartOptions, this._chartOptions);
this.updateYAxisFromTargets();
}

ngOnChanges() {
Expand All @@ -101,6 +102,41 @@ export class TimeSavedChartComponent implements OnInit, OnChanges {
};
this.updateFlag = true;
}
this.updateYAxisFromTargets();
}

private updateYAxisFromTargets() {
if (this.targets?.user?.weeklyTimeSavedHrs) {
const targetValue = this.targets.user.weeklyTimeSavedHrs.target;
const maxValue = Math.max(
targetValue * 1.5,
this.targets.user.weeklyTimeSavedHrs.max || 10,
10
);
const yAxis = {
...this._chartOptions.yAxis,
max: maxValue,
plotLines: [{
value: targetValue,
color: 'var(--sys-primary)',
dashStyle: 'Dash' as Highcharts.DashStyleValue,
width: 2,
label: {
text: 'Target Level',
align: 'left' as Highcharts.AlignValue,
style: {
color: 'var(--sys-primary)'
}
},
zIndex: 2
}]
};
this._chartOptions = {
...this._chartOptions,
yAxis
};
this.updateFlag = true;
}
}

}
5 changes: 5 additions & 0 deletions frontend/src/app/services/api/targets.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,10 @@
saveTargets(targets: Targets) {
return this.http.post<Targets>(`${this.apiUrl}`, targets);
}

recalculateTargets() {
// Calls the backend endpoint to recalculate targets
return this.http.get<any>(`${this.apiUrl}/calculate`);

Check failure

Code scanning / ESLint

Disallow the `any` type Error

Unexpected any. Specify a different type.
}
}

Loading