Skip to content

Commit 26c8392

Browse files
committed
feat: Update github-usage-report to version 3.1 and enhance file upload component with menu options
1 parent 1c56b41 commit 26c8392

10 files changed

+79
-46
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"@angular/platform-browser": "^19.2.14",
2222
"@angular/platform-browser-dynamic": "^19.2.14",
2323
"@angular/router": "^19.2.14",
24-
"github-usage-report": "3.0",
24+
"github-usage-report": "3.1",
2525
"highcharts": "^11.2.0",
2626
"highcharts-angular": "^4.0.0",
2727
"jspdf": "^2.5.1",
Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
<input type="file" #fileInput name="fileUpload" (change)="onFileSelected($event)" style="display: none;" accept=".csv">
2-
<button mat-fab extended color="primary" (click)="fileInput.click()">
2+
<button style="margin: 40px 20px;" mat-fab extended color="primary" [matMenuTriggerFor]="menu">
33
<mat-icon>upload_file</mat-icon>
44
{{ text }}
5-
</button>
5+
</button>
6+
<mat-menu #menu="matMenu">
7+
<button (click)="this.type = 'metered'; fileInput.click()" mat-menu-item>
8+
Metered billing usage report
9+
</button>
10+
<button disabled (click)="this.type = 'copilot_premium_requests'; fileInput.click()" mat-menu-item>
11+
Copilot premium requests usage report
12+
</button>
13+
</mat-menu>
Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +0,0 @@
1-
button {
2-
margin: 40px 20px;
3-
}

src/app/components/usage/file-upload/file-upload.component.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@ import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@
88
})
99
export class FileUploadComponent {
1010
@Input() text: string = 'Choose File';
11-
@Output() fileText = new EventEmitter<string>();
11+
@Output() fileText = new EventEmitter<{
12+
type: 'metered' | 'copilot_premium_requests';
13+
fileText: string;
14+
}>();
1215
@ViewChild('fileUpload', { static: false }) fileUpload!: ElementRef; // Add this line
16+
type?: 'metered' | 'copilot_premium_requests';
1317

1418
constructor() {
1519
this.fileUpload = new ElementRef(null);
@@ -23,7 +27,10 @@ export class FileUploadComponent {
2327
const reader = new FileReader();
2428
reader.onload = () => {
2529
const fileText = reader.result as string;
26-
this.fileText.emit(fileText); // emit the file text to the parent component
30+
this.fileText.emit({
31+
type: this.type || 'metered',
32+
fileText
33+
}); // emit the file text to the parent component
2734
};
2835
reader.readAsText(file);
2936
}

src/app/components/usage/usage.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ <h1 class="mat-headline-2" style="user-select: none; font-weight: 800; text-alig
77
</h2> -->
88
</div>
99
<div class="flex-center-horizontally full-width">
10-
<app-file-upload [text]="status" (fileText)="onFileText($event)"></app-file-upload>
10+
<app-file-upload [text]="status" (fileText)="onFileText($event.fileText, $event.type)"></app-file-upload>
1111
</div>
1212

1313
<mat-progress-bar *ngIf="progress && progress < 99" mode="determinate" [value]="progress"></mat-progress-bar>

src/app/components/usage/usage.component.ts

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@ import { Observable, Subscription, debounceTime, map, startWith } from 'rxjs';
55
import { CustomUsageReportLine, UsageReportService } from 'src/app/usage-report.service';
66
import { DialogBillingNavigateComponent } from './dialog-billing-navigate';
77
import { MatDialog } from '@angular/material/dialog';
8+
import { ModelUsageReport } from 'github-usage-report';
89

910
@Component({
10-
selector: 'app-usage',
11-
templateUrl: './usage.component.html',
12-
styleUrls: ['./usage.component.scss'],
13-
standalone: false
11+
selector: 'app-usage',
12+
templateUrl: './usage.component.html',
13+
styleUrls: ['./usage.component.scss'],
14+
standalone: false
1415
})
1516
export class UsageComponent implements OnInit, OnDestroy {
1617
usage!: UsageReport;
18+
usageCopilotPremiumRequests!: ModelUsageReport;
1719
usageLines = {} as {
1820
sharedStorage: CustomUsageReportLine[],
1921
codespaces: CustomUsageReportLine[],
@@ -92,31 +94,38 @@ export class UsageComponent implements OnInit, OnDestroy {
9294
this.subscriptions.forEach(subscription => subscription.unsubscribe());
9395
}
9496

95-
async onFileText(fileText: string) {
97+
async onFileText(fileText: string, type: 'metered' | 'copilot_premium_requests') {
9698
this.status = 'Parsing File...';
97-
const usage = await this.usageReportService.setUsageReportData(fileText, async (_: any, progress: any): Promise<any> => {
98-
return await new Promise((resolve) => {
99-
if (progress === this.progress) return resolve('');
100-
setTimeout(() => {
101-
this.progress = progress;
102-
this.status = `Parsing File... ${progress}%`
103-
resolve('');
104-
}, 0)
105-
});
106-
}).then(async (usage) => {
107-
this.status = 'Loading... Be patient, this may take a while.';
108-
return new Promise<UsageReport>(resolve => setTimeout(() => resolve(usage), 100));
109-
});
110-
this.minDate = new Date(usage.lines[0]?.date);
111-
this.maxDate = new Date(usage.lines[usage.lines.length - 1]?.date);
99+
100+
const progressFunction = async (_: any, progress: any): Promise<any> => {
101+
return await new Promise((resolve) => {
102+
if (progress === this.progress) return resolve('');
103+
this.progress = progress;
104+
this.status = `Parsing File... ${progress}%`
105+
resolve('');
106+
});
107+
};
108+
const usage = await (type === 'metered' ? this.usageReportService.setUsageReportData(fileText, progressFunction) : type === 'copilot_premium_requests' ? this.usageReportService.setUsageReportCopilotPremiumRequests(fileText, progressFunction) : null);
109+
if (!usage) {
110+
this.status = 'Error parsing file. Please check the file format.';
111+
return;
112+
}
113+
const firstLine = usage.lines[0];
114+
const lastLine = usage.lines[usage.lines.length - 1];
115+
this.minDate = new Date(firstLine && 'date' in firstLine ? firstLine.date : new Date());
116+
this.maxDate = new Date(lastLine && 'date' in lastLine ? lastLine.date : new Date());
112117
// make the date 00:00:00
113118
this.minDate.setHours(0, 0, 0, 0);
114119
this.maxDate.setHours(0, 0, 0, 0);
115120
this.range.controls.start.setValue(this.minDate, { emitEvent: false });
116121
this.range.controls.end.setValue(this.maxDate, { emitEvent: false });
122+
if (type === 'copilot_premium_requests') {
123+
this.usageCopilotPremiumRequests = usage as ModelUsageReport;
124+
} else {
125+
this.usage = usage as UsageReport;
126+
}
117127
this.status = 'Usage Report';
118128
this.progress = null;
119-
this.usage = usage;
120129
this.cdr.detectChanges();
121130
}
122131

src/app/usage-report.service.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { TitleCasePipe } from '@angular/common';
22
import { Injectable } from '@angular/core';
3-
import { readGithubUsageReport, UsageReport, UsageReportLine } from 'github-usage-report';
3+
import { ModelUsageReport, readGithubUsageReport, readModelUsageReport, UsageReport, UsageReportLine } from 'github-usage-report';
44
import { BehaviorSubject, Observable, map } from 'rxjs';
55

66
interface Filter {
@@ -25,7 +25,9 @@ export interface CustomUsageReport extends UsageReport {
2525
})
2626
export class UsageReportService {
2727
usageReportData!: string;
28+
usageReportPremiumRequestsData!: string;
2829
usageReport!: CustomUsageReport;
30+
usageReportCopilotPremiumRequests!: ModelUsageReport;
2931
usageReportFiltered: BehaviorSubject<CustomUsageReportLine[]> = new BehaviorSubject<CustomUsageReportLine[]>([]);
3032
usageReportFilteredProduct: { [key: string]: Observable<CustomUsageReportLine[]> } = {};
3133
filters: Filter = {
@@ -141,6 +143,14 @@ export class UsageReportService {
141143
this.valueType.next(value);
142144
}
143145

146+
async setUsageReportCopilotPremiumRequests(usageReportData: string, cb?: (usageReport: CustomUsageReport, percent: number) => void): Promise<ModelUsageReport> {
147+
this.usageReportPremiumRequestsData = usageReportData;
148+
await readModelUsageReport(this.usageReportPremiumRequestsData).then((report) => {
149+
this.usageReportCopilotPremiumRequests = report;
150+
});
151+
return this.usageReportCopilotPremiumRequests;
152+
}
153+
144154
async setUsageReportData(usageReportData: string, cb?: (usageReport: CustomUsageReport, percent: number) => void): Promise<CustomUsageReport> {
145155
this.usageReportData = usageReportData;
146156
this.usageReport = await readGithubUsageReport(this.usageReportData) as CustomUsageReport;

src/highcharts.theme.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@ const yAxisConfig: Highcharts.YAxisOptions = {
3636
...xAxisConfig
3737
};
3838
export const colors = (style: string = 'emphasis') => [
39-
`var()`,
40-
`var()`,
41-
`var()`,
42-
`var()`,
43-
`var()`,
44-
`var()`,
45-
`var()`,
46-
`var()`,
47-
`var()`,
48-
`var()`,
39+
`var(--data-blue-color-${style}, var(--data-blue-color))`,
40+
`var(--data-green-color-${style}, var(--data-green-color))`,
41+
`var(--data-orange-color-${style}, var(--data-orange-color))`,
42+
`var(--data-pink-color-${style}, var(--data-pink-color))`,
43+
`var(--data-yellow-color-${style}, var(--data-yellow-color))`,
44+
`var(--data-red-color-${style}, var(--data-red-color))`,
45+
`var(--data-purple-color-${style}, var(--data-purple-color))`,
46+
`var(--data-auburn-color-${style}, var(--data-auburn-color))`,
47+
`var(--data-teal-color-${style}, var(--data-teal-color))`,
48+
`var(--data-gray-color-${style}, var(--data-gray-color))`,
4949
]
5050
const theme: Highcharts.Options = {
5151
colors: [

src/material.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { MatChipsModule } from '@angular/material/chips';
1919
import { MatTabsModule } from '@angular/material/tabs';
2020
import { MatListModule } from '@angular/material/list';
2121
import { MatTooltipModule } from '@angular/material/tooltip';
22+
import { MatMenuModule } from '@angular/material/menu';
2223

2324
@NgModule({
2425
exports: [
@@ -45,7 +46,8 @@ import { MatTooltipModule } from '@angular/material/tooltip';
4546
MatChipsModule,
4647
MatTabsModule,
4748
MatListModule,
48-
MatTooltipModule
49+
MatTooltipModule,
50+
MatMenuModule
4951
]
5052
})
5153
export class MaterialModule { }

0 commit comments

Comments
 (0)