Path: blob/main/extensions/copilot/test/simulation/workbench/components/amlModeToolbar.tsx
13399 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Badge, Checkbox, Dropdown, Input, Option } from '@fluentui/react-components';6import * as mobxlite from 'mobx-react-lite';7import * as React from 'react';8import { useEffect, useMemo } from 'react';9import { AMLProvider } from '../stores/amlSimulations';10import { SimulationTestsProvider } from '../stores/simulationTestsProvider';11import { AMLPicker } from './amlPicker';12import { createAnnotationFilter, createFilterer, createLanguageFilter, createResultTypeFilter, createTestNameFilter } from './filterUtils';13import { TestFilterer } from './testFilterer';1415type Props = {16amlProvider: AMLProvider;17simulationTestsProvider: SimulationTestsProvider;18onFiltererChange: (filterer: TestFilterer | undefined) => void;19allLanguageIds: readonly string[];20};212223export const AMLModeToolbar = mobxlite.observer(({ amlProvider, simulationTestsProvider, onFiltererChange, allLanguageIds }: Props) => {2425const [resultFilterSelected, setResultFilterSelected] = React.useState<string | undefined>(undefined);26const [languageSelected, setLanguageSelected] = React.useState<string | undefined>(undefined);27const [testNameFilterSelected, setTestNameFilterSelected] = React.useState<string | undefined>(undefined);28const [showOnlyTestsWithAnnotations, setShowOnlyTestsWithAnnotations] = React.useState<boolean | undefined>(undefined);29const [selectedAnnotations, setSelectedAnnotations] = React.useState<string[]>([]);3031// Create a memoized filterer instance that only updates when filter criteria change32const filterer = useMemo(() => {33const predicates = [34createResultTypeFilter(resultFilterSelected),35createLanguageFilter(languageSelected),36createAnnotationFilter(showOnlyTestsWithAnnotations ? new Set(selectedAnnotations) : undefined),37createTestNameFilter(testNameFilterSelected)38];3940return createFilterer(predicates);41}, [resultFilterSelected, languageSelected, showOnlyTestsWithAnnotations, selectedAnnotations, testNameFilterSelected]);4243// Update parent component when filter changes44useEffect(() => {45onFiltererChange(filterer);46}, [filterer, onFiltererChange]);4748const [knownAnnotations, setKnownAnnotations] = React.useState<string[]>([]);49const updateKnownAnnotations = () => {50const newAnnotations = new Set<string>(knownAnnotations);51for (const test of simulationTestsProvider.tests) {52if (test.runnerStatus) {53for (const run of test.runnerStatus.runs) {54for (const annotation of run.annotations) {55newAnnotations.add(annotation.label);56}57}58}59}60setKnownAnnotations([...newAnnotations].sort());61};6263const onLanguageIdChange = (e: React.FormEvent<HTMLSelectElement>) => {64let langId: string | undefined = (e.target as HTMLSelectElement).value;65langId = langId !== 'no-language-filter' ? langId : undefined;66setLanguageSelected(langId);67};6869const onResultFilterChange = (e: React.FormEvent<HTMLSelectElement>) => {70let resultFilter: string | undefined = (e.target as HTMLSelectElement).value;71resultFilter = resultFilter !== 'no-result-filter' ? resultFilter : undefined;72setResultFilterSelected(resultFilter);73};7475const onTestNameFilterChange = (e: React.FormEvent<HTMLInputElement>) => {76let testNameFilter: string | undefined = (e.target as HTMLInputElement).value;77testNameFilter = testNameFilter !== '' ? testNameFilter : undefined;78setTestNameFilterSelected(testNameFilter);79};8081const defaultLanguageId = (languageSelected && allLanguageIds.includes(languageSelected))82? languageSelected : undefined;8384return (85<div className='toolbar' style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>86<div>87<AMLPicker amlProvider={amlProvider} />8889<div className='external-toolbar-filter'>90<label className='title'>Filter by test name</label>91<Input92id='grep'93size='small'94placeholder='grep'95title='Filter by test name'96value={testNameFilterSelected}97onChange={onTestNameFilterChange}98style={{ width: '100px', maxWidth: '25vw', marginLeft: '10px' }}99/>100</div>101102<div className='external-toolbar-filter'>103<label className='title'>Filter by results</label>104<select className='external-toolbar-dropdown' onChange={onResultFilterChange} value={defaultLanguageId}>105<option value='no-result-filter' key='no-result-filter'>All</option>106<option key={'failures'} value={'failures'}>107{'Failures'}108</option>109<option key={'regressions'} value={'regressions'}>110{'Regressions'}111</option>112<option key={'improvements'} value={'improvements'}>113{'Improvements'}114</option>115<option key={'differences'} value={'differences'}>116{'Differences'}117</option>118</select>119</div>120121<div className='external-toolbar-filter'>122<label className='title'>Filter by language</label>123<select className='external-toolbar-dropdown' onChange={onLanguageIdChange} value={defaultLanguageId}>124<option value='no-language-filter' key='no-language-filter'>All</option>125{allLanguageIds.map((langId) => (126<option key={langId} value={langId}>127{langId}128</option>129))}130</select>131</div>132<Checkbox133label='Filter by annotations'134checked={showOnlyTestsWithAnnotations}135onChange={() => setShowOnlyTestsWithAnnotations(!showOnlyTestsWithAnnotations)}136/>137<Dropdown138multiselect139size='small'140placeholder='Select annotations'141defaultValue={selectedAnnotations.length ? selectedAnnotations.join(', ') : undefined}142defaultSelectedOptions={selectedAnnotations}143onOptionSelect={(e, o) => { setSelectedAnnotations(o.selectedOptions); setShowOnlyTestsWithAnnotations(o.selectedOptions.length > 0); }}144onOpenChange={(e, o) => o.open && updateKnownAnnotations()}145>146{knownAnnotations.map((option) => (147<Option key={option} text={option}>148<Badge key={option} shape='square' appearance='outline' size='small'>{option}</Badge>149</Option>150))}151</Dropdown>152</div>153</div>154);155});156157158