Skip to content
Merged
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
1 change: 1 addition & 0 deletions report-app/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"browser": "src/main.ts",
"tsConfig": "tsconfig.app.json",
"externalDependencies": [
"firebase-admin",
"@firebase/app",
"@firebase/firestore",
"tiktoken",
Expand Down
4 changes: 2 additions & 2 deletions report-app/src/app/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@
.report-body {
display: flex;
flex-grow: 1;
overflow: hidden;
max-width: var(--main-container-width);
margin: auto;
padding: 0 1rem 2rem;
// Add some padding on the bottom so there's some space for dropdowns to open.
padding: 0 1rem 10rem;
}

.reports-link.active {
Expand Down
6 changes: 6 additions & 0 deletions report-app/src/app/pages/report-list/report-list.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
}
</select>
}
@if (allLabels().length > 0) {
<multi-select
[options]="allLabels()"
[(selected)]="selectedLabels"
[label]="selectedLabels().length === 0 ? 'Filter by labels' : `Showing reports with ${selectedLabels().length} label(s)`"/>
}
</div>
<div class="button-group">
@if (isCompareMode()) {
Expand Down
37 changes: 35 additions & 2 deletions report-app/src/app/pages/report-list/report-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,19 @@ import {MessageSpinner} from '../../shared/message-spinner';
import {Score} from '../../shared/score/score';
import {ProviderLabel} from '../../shared/provider-label';
import {bucketToScoreVariable} from '../../shared/scoring';
import {MultiSelect} from '../../shared/multi-select/multi-select';

@Component({
selector: 'app-report-list',
imports: [RouterLink, DatePipe, StackedBarChart, MessageSpinner, Score, ProviderLabel],
imports: [
RouterLink,
DatePipe,
StackedBarChart,
MessageSpinner,
Score,
ProviderLabel,
MultiSelect,
],
templateUrl: './report-list.html',
styleUrls: ['./report-list.scss'],
})
Expand All @@ -30,6 +39,7 @@ export class ReportListComponent {
protected selectedFramework = signal<string | null>(null);
protected selectedModel = signal<string | null>(null);
protected selectedRunner = signal<string | null>(null);
protected selectedLabels = signal<string[]>([]);

protected allFrameworks = computed(() => {
const frameworks = new Map<string, string>();
Expand Down Expand Up @@ -67,17 +77,40 @@ export class ReportListComponent {
}));
});

protected allLabels = computed(() => {
const labels = new Set<string>();

for (const group of this.allGroups()) {
for (const label of group.labels) {
const trimmed = label.trim();

if (trimmed) {
labels.add(trimmed);
}
}
}

return Array.from(labels)
.sort()
.map(label => ({
label,
value: label,
}));
});

protected reportGroups = computed(() => {
const framework = this.selectedFramework();
const model = this.selectedModel();
const runner = this.selectedRunner();
const labels = this.selectedLabels();
const groups = this.allGroups();

return groups.filter(group => {
const frameworkMatch = !framework || group.framework.fullStackFramework.id === framework;
const modelMatch = !model || group.model === model;
const runnerMatch = !runner || group.runner?.id === runner;
return frameworkMatch && modelMatch && runnerMatch;
const labelsMatch = labels.length === 0 || group.labels.some(l => labels.includes(l.trim()));
return frameworkMatch && modelMatch && runnerMatch && labelsMatch;
});
});

Expand Down
34 changes: 0 additions & 34 deletions report-app/src/app/pages/report-viewer/failed-checks-filter.ts

This file was deleted.

15 changes: 5 additions & 10 deletions report-app/src/app/pages/report-viewer/report-viewer.html
Original file line number Diff line number Diff line change
Expand Up @@ -240,16 +240,11 @@ <h4>Logs</h4>

<h2>Generated applications</h2>
@if (allFailedChecks().length > 0) {
<details class="filter-dropdown" #dropdown>
<summary>Filter by failed checks ({{ selectedChecks().size }} selected)</summary>
<div class="dropdown-content">
<failed-checks-filter
[allFailedChecks]="allFailedChecks()"
[selectedChecks]="selectedChecks()"
(toggleCheck)="toggleCheckFilter($event)"
/>
</div>
</details>
<multi-select
[label]="`Filter by failed checks (${selectedChecks().length} selected)`"
[options]="allFailedChecks()"
[(selected)]="selectedChecks"
class="check-filter"/>
}
<div class="apps-list">
@for (result of filteredResults(); track result) {
Expand Down
47 changes: 2 additions & 45 deletions report-app/src/app/pages/report-viewer/report-viewer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -147,51 +147,8 @@ lighthouse-category + lighthouse-category {
margin-bottom: 2em;
}

.filter-dropdown {
position: relative;
display: inline-block;

margin-bottom: 1.5rem;
gap: 0.5rem;
background-color: var(--card-bg-color);
padding: 0;
border-radius: var(--control-border-radius);
border: 1px solid var(--border-color);
transition: background-color var(--transition-speed) ease;

&:hover {
background-color: var(--button-active-bg-color);
}

& summary {
cursor: pointer;
padding: 0.5rem 1.25rem;
border-radius: 4px;
background-color: transparent;
list-style: none;
font-weight: 500;
color: var(--text-secondary);
transition: color var(--transition-speed) ease;
}

&[open] .dropdown-content {
display: block;
color: var(--text-primary);
}
}

.dropdown-content {
display: none;
position: absolute;
background-color: var(--card-bg-color);
min-width: 380px;
box-shadow: var(--shadow);
z-index: 1;
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
padding: 10px;
max-height: 300px;
overflow: auto;
.check-filter {
margin-bottom: 1rem;
}

.no-failed-checks {
Expand Down
40 changes: 8 additions & 32 deletions report-app/src/app/pages/report-viewer/report-viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import {
StackedBarChartData,
} from '../../shared/visualization/stacked-bar-chart/stacked-bar-chart';
import {formatFile} from './formatter';
import {FailedChecksFilter} from './failed-checks-filter';
import {MessageSpinner} from '../../shared/message-spinner';
import {createPromptDebuggingZip} from '../../shared/debugging-zip';
import {Score} from '../../shared/score/score';
Expand All @@ -42,6 +41,7 @@ import {ExpansionPanelHeader} from '../../shared/expansion-panel/expansion-panel
import {ProviderLabel} from '../../shared/provider-label';
import {AiAssistant} from '../../shared/ai-assistant/ai-assistant';
import {LighthouseCategory} from './lighthouse-category';
import {MultiSelect} from '../../shared/multi-select/multi-select';

const localReportRegex = /-l\d+$/;

Expand All @@ -51,7 +51,6 @@ const localReportRegex = /-l\d+$/;
CodeViewer,
DatePipe,
DecimalPipe,
FailedChecksFilter,
MessageSpinner,
Score,
ExpansionPanel,
Expand All @@ -60,12 +59,10 @@ const localReportRegex = /-l\d+$/;
NgxJsonViewerModule,
AiAssistant,
LighthouseCategory,
MultiSelect,
],
templateUrl: './report-viewer.html',
styleUrls: ['./report-viewer.scss'],
host: {
'(document:click)': 'closeDropdownIfOpen($event)',
},
})
export class ReportViewer {
private clipboard = inject(Clipboard);
Expand Down Expand Up @@ -107,7 +104,7 @@ export class ReportViewer {
return this.reportsFetcher.reportGroups().find(group => group.id === id);
});

protected selectedChecks = signal<Set<string>>(new Set());
protected selectedChecks = signal<string[]>([]);

protected allFailedChecks = computed(() => {
if (!this.selectedReport.hasValue()) {
Expand Down Expand Up @@ -136,11 +133,11 @@ export class ReportViewer {
}

const failedChecksArray = Array.from(failedChecksMap.entries()).map(([name, count]) => ({
name,
count,
label: `${name} (${count})`,
value: name,
}));

return failedChecksArray.sort((a, b) => a.name.localeCompare(b.name));
return failedChecksArray.sort((a, b) => a.label.localeCompare(b.label));
});

protected filteredResults = computed(() => {
Expand All @@ -151,7 +148,7 @@ export class ReportViewer {
return [];
}

if (checks.size === 0) {
if (checks.length === 0) {
return report.results;
}

Expand All @@ -164,7 +161,7 @@ export class ReportViewer {
if (this.isSkippedAssessment(assessment)) {
continue;
}
if (assessment.successPercentage < 1 && checks.has(assessment.name)) {
if (assessment.successPercentage < 1 && checks.includes(assessment.name)) {
return true;
}
}
Expand Down Expand Up @@ -353,27 +350,6 @@ export class ReportViewer {
return value.state === IndividualAssessmentState.SKIPPED;
}

protected dropdownRef = viewChild<ElementRef>('dropdown');

protected closeDropdownIfOpen(event: MouseEvent): void {
const detailsElement = this.dropdownRef()?.nativeElement;
if (detailsElement?.hasAttribute('open') && !detailsElement.contains(event.target)) {
detailsElement.removeAttribute('open');
}
}

protected toggleCheckFilter(check: string): void {
this.selectedChecks.update(currentChecks => {
const checks = new Set(currentChecks);
if (checks.has(check)) {
checks.delete(check);
} else {
checks.add(check);
}
return checks;
});
}

protected async format(file: LlmResponseFile): Promise<void> {
const result = await formatFile(file, this.selectedReport.value()!.details.summary.framework);
if (typeof result === 'string') {
Expand Down
19 changes: 19 additions & 0 deletions report-app/src/app/shared/multi-select/multi-select.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<button
[class.open]="isOpen()"
(click)="isOpen.set(!isOpen())"
(keydown.escape)="isOpen.set(false)">
{{label()}}

<div class="dropdown">
@for (option of options(); track option.value) {
<label>
<input
type="checkbox"
[checked]="selected().includes(option.value)"
(change)="optionClicked(option)"
/>
{{ option.label }}
</label>
}
</div>
</button>
Loading
Loading