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
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export class ChartPieUserComponent implements OnChanges {
}]
};
updateFromInput: boolean = false;
hasUsernameData: boolean = false;

constructor(
private themeService: ThemingService,
Expand All @@ -42,12 +43,19 @@ export class ChartPieUserComponent implements OnChanges {
}

ngOnChanges() {
this.hasUsernameData = this.usageReportService.hasUsernameData;

// If no username data, show usage by repository instead
const groupByField = this.hasUsernameData ? 'username' : 'repositoryName';
const chartTitle = this.hasUsernameData ? 'username' : 'repository';

this.data = this.data.filter((line) => line.unitType === 'minutes');

const aggregatedData = this.data.reduce((acc, line) => {
const index = acc.findIndex((item) => item[0] === line.username);
const fieldValue = groupByField === 'username' ? (line.username || 'Unknown') : (line.repositoryName || 'Unknown');
const index = acc.findIndex((item) => item[0] === fieldValue);
if (index === -1) {
acc.push([line.username, line.value]);
acc.push([fieldValue, line.value]);
} else {
acc[index][1] += line.value;
}
Expand All @@ -72,7 +80,7 @@ export class ChartPieUserComponent implements OnChanges {
data
}];
this.options.title = {
text: `${this.currency === 'minutes' ? 'Usage' : 'Cost'} by username`
text: `${this.currency === 'minutes' ? 'Usage' : 'Cost'} by ${chartTitle}`
};
this.options.tooltip = {
...this.options.tooltip,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<mat-select [(value)]="tableType" (selectionChange)="tableType = $event.value; ngOnChanges()">
<mat-option value="sku">Runner</mat-option>
<mat-option value="repo">Repo</mat-option>
<mat-option value="workflow">Workflow</mat-option>
<mat-option value="user">User</mat-option>
<mat-option value="workflow" [disabled]="!hasWorkflowData" [matTooltip]="!hasWorkflowData ? 'Workflow data not available in summarized reports' : ''">Workflow</mat-option>
<mat-option value="user" [disabled]="!hasUsernameData" [matTooltip]="!hasUsernameData ? 'User data not available in summarized reports' : ''">User</mat-option>
</mat-select>
</mat-form-field>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,31 @@ export class TableWorkflowUsageComponent implements OnChanges, AfterViewInit {
@Input() currency!: string;
dataSource: MatTableDataSource<WorkflowUsageItem | RepoUsageItem | SkuUsageItem> = new MatTableDataSource<any>(); // Initialize the dataSource property
tableType: 'workflow' | 'repo' | 'sku' | 'user' = 'sku';

// Track available grouping options based on CSV format
hasWorkflowData: boolean = false;
hasUsernameData: boolean = false;

@ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;

constructor(
private usageReportService: UsageReportService,
public usageReportService: UsageReportService,
) { }

ngOnChanges() {
// Update available grouping options based on the data
this.hasWorkflowData = this.usageReportService.hasWorkflowData;
this.hasUsernameData = this.usageReportService.hasUsernameData;

// Reset table type if current selection is not available
if (this.tableType === 'workflow' && !this.hasWorkflowData) {
this.tableType = 'sku';
}
if (this.tableType === 'user' && !this.hasUsernameData) {
this.tableType = 'sku';
}

this.initializeColumns();
let usage: WorkflowUsageItem[] | RepoUsageItem[] | SkuUsageItem[] = [];
let usageItems: WorkflowUsageItem[] = (usage as WorkflowUsageItem[]);
Expand All @@ -82,7 +98,7 @@ export class TableWorkflowUsageComponent implements OnChanges, AfterViewInit {
} else if (this.tableType === 'sku') {
return a.sku === this.usageReportService.formatSku(line.sku);
} else if (this.tableType === 'user') {
return a.username === line.username;
return a.username === (line.username || 'Unknown');
}
return false
});
Expand Down Expand Up @@ -130,7 +146,7 @@ export class TableWorkflowUsageComponent implements OnChanges, AfterViewInit {
} else {
acc.push({
workflow: line.workflowName || line.workflowPath || 'Unknown Workflow',
repo: line.repositoryName,
repo: line.repositoryName || 'Unknown Repository',
total: line.quantity,
cost: line.quantity * line.pricePerUnit,
runs: 1,
Expand All @@ -139,7 +155,7 @@ export class TableWorkflowUsageComponent implements OnChanges, AfterViewInit {
avgTime: line.value,
[month]: line.value,
sku: this.usageReportService.formatSku(line.sku),
username: line.username,
username: line.username || 'Unknown',
});
}
return acc;
Expand Down
8 changes: 7 additions & 1 deletion src/app/components/usage/usage.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ <h1>Premium Requests</h1>
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
<mat-form-field style="flex: 1; max-width: 500px;" *ngIf="tabSelected === 'actions'">
<mat-form-field style="flex: 1; max-width: 500px;" *ngIf="tabSelected === 'actions' && hasWorkflowData">
<mat-label>Workflow</mat-label>
<input type="text" placeholder="build.yml" aria-label="Number" matInput [formControl]="workflowControl"
[matAutocomplete]="auto" name="workflow">
Expand All @@ -46,6 +46,12 @@ <h1>Premium Requests</h1>
</button>
}
</mat-form-field>
<span *ngIf="tabSelected === 'actions' && !hasWorkflowData && formatType === 'summarized'"
class="format-notice"
matTooltip="The summarized report format doesn't include workflow details. Use the detailed usage report for workflow-level data.">
<mat-icon>info</mat-icon>
Summarized report
</span>
<div>
<mat-button-toggle-group name="toggleCurrency" aria-label="Toggle Chart" [value]="currency"
(change)="currency = $event.value; changeCurrency($event.value)">
Expand Down
15 changes: 15 additions & 0 deletions src/app/components/usage/usage.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,19 @@ form {

.tab-icon {
margin-right: 8px;
}

.format-notice {
display: flex;
align-items: center;
gap: 4px;
font-size: 12px;
opacity: 0.7;
cursor: help;

mat-icon {
font-size: 16px;
width: 16px;
height: 16px;
}
}
9 changes: 7 additions & 2 deletions src/app/components/usage/usage.component.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { OnInit, ChangeDetectorRef, Component, OnDestroy, isDevMode } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { UsageReport } from 'github-usage-report/src/types';
import { Observable, Subscription, debounceTime, map, startWith } from 'rxjs';
import { CustomUsageReportLine, UsageReportService } from 'src/app/usage-report.service';
import { CustomUsageReportLine, UsageReport, UsageReportService } from 'src/app/usage-report.service';
import { DialogBillingNavigateComponent } from './dialog-billing-navigate';
import { MatDialog } from '@angular/material/dialog';
import { ModelUsageReport } from 'github-usage-report';
Expand Down Expand Up @@ -38,6 +37,8 @@ export class UsageComponent implements OnInit, OnDestroy {
subscriptions: Subscription[] = [];
currency: 'minutes' | 'cost' = 'cost';
tabSelected: 'shared-storage' | 'copilot' | 'actions' = 'actions';
hasWorkflowData: boolean = false;
formatType: 'legacy' | 'summarized' | null = null;

constructor(
private usageReportService: UsageReportService,
Expand Down Expand Up @@ -107,6 +108,10 @@ export class UsageComponent implements OnInit, OnDestroy {
this.usageReportService.getWorkflowsFiltered().subscribe((workflows) => {
this.workflows = workflows;
}),
this.usageReportService.formatType.subscribe((formatType) => {
this.formatType = formatType;
this.hasWorkflowData = this.usageReportService.hasWorkflowData;
}),
);
}

Expand Down
Loading