diff --git a/portal/src/app/components/all-experiments/Experiments.module.scss b/portal/src/app/components/all-experiments/Experiments.module.scss index 7fc3fb5f..866d147f 100644 --- a/portal/src/app/components/all-experiments/Experiments.module.scss +++ b/portal/src/app/components/all-experiments/Experiments.module.scss @@ -1,10 +1,8 @@ @import "src/styles/variables-keys"; .experiments_wrapper { - padding-block-start: 40px; - padding-block-end: 40px; - padding-inline-start: 80px; - padding-inline-end: 80px; + padding-inline: 80px; + padding-block: 40px; } .title_options_container { @@ -48,8 +46,7 @@ } .experiments_table { - margin-block-start: 60px; - margin-block-end: 60px; + margin-block: 60px; th, td { text-align: left; @@ -86,7 +83,7 @@ inline-size: 100%; block-size: 100%; position: absolute; - background-color: #fff; + background-color: var($primaryWhite); opacity: 0.6; inset-block-start: 0; inset-inline-start: 0; diff --git a/portal/src/app/components/all-experiments/Experiments.tsx b/portal/src/app/components/all-experiments/Experiments.tsx index 67f76dd5..0d8c83e5 100644 --- a/portal/src/app/components/all-experiments/Experiments.tsx +++ b/portal/src/app/components/all-experiments/Experiments.tsx @@ -1,7 +1,7 @@ import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; import styles from './Experiments.module.scss'; import cn from 'classnames'; -import { ExperimentData, IUseExperimentsData, useExperimentsData } from './hooks'; +import { IUseExperimentsData, useExperimentsData } from './hooks'; import { FetchDataStatus, IHttp, useFetch } from '../../shared/hooks/useFetch'; import { Spinner, SpinnerSize } from '../../shared/components/att-spinner'; import { ALL_EXPERIMENTS_TABLE_EN } from './translate/en'; @@ -20,15 +20,18 @@ import TrashHoverSvg from '../../../assets/images/trash-hover.svg'; import DuplicateSvg from '../../../assets/images/duplicate.svg'; import { DeleteExperimentModal } from '../home/components/experiment/components/delete-experiment-modal'; import { parseExperimentsData } from './utils/parse-experiments-data.utils'; +import { ISpinner, useSpinnerContext } from '../../shared/context/spinner'; +import { ExperimentData } from './models/experiments.interface'; const DeleteAriaLabel: string = ALL_EXPERIMENTS_TABLE_EN.BUTTONS.DELETE; const DuplicateAriaLabel: string = ALL_EXPERIMENTS_TABLE_EN.TABLE_COLUMNS.LINKS.DUPLICATE; export const Experiments: React.FC = () => { - const { test_suites, status }: IUseExperimentsData = useExperimentsData(); + const { testSuites, status }: IUseExperimentsData = useExperimentsData(); const [openDeleteModal, setOpenDeleteModal] = useState(false); const [checkedRows, setCheckedRows] = useState>({}); - const experimentsData = useMemo(() => (parseExperimentsData(test_suites)), [test_suites]); + const experimentsData = useMemo(() => (testSuites ? parseExperimentsData(testSuites): []), [testSuites]); + const { isSpinnerOn }: ISpinner = useSpinnerContext(); const navigate = useNavigate(); const { post, status: deleteStatus, error: deleteError, cancelRequest: cancelRequestDelete }: IHttp @@ -142,10 +145,11 @@ export const Experiments: React.FC = () => { return (
- {status === FetchDataStatus.Fetching ? renderSpinner() : ( - <> + <> + {isSpinnerOn && renderSpinner()} + { status === FetchDataStatus.Success &&
- + {Object.values(checkedRows).some((value: boolean) => value) && ( )}
- {experimentsData.length > 0 && } - {openDeleteModal && } - - )} + } + {experimentsData.length > 0 &&
} + {openDeleteModal && } + ); } function renderSpinner() { return ( -
-
- +
+
+ +
-
); } diff --git a/portal/src/app/components/all-experiments/hooks/useExperimentsData.test.ts b/portal/src/app/components/all-experiments/hooks/useExperimentsData.test.ts index cee957b7..9318385d 100644 --- a/portal/src/app/components/all-experiments/hooks/useExperimentsData.test.ts +++ b/portal/src/app/components/all-experiments/hooks/useExperimentsData.test.ts @@ -1,6 +1,7 @@ import { renderHook } from '@testing-library/react'; import { useFetch } from '../../../shared/hooks/useFetch'; -import { Experiment, useExperimentsData } from './useExperimentsData'; +import { Experiment } from '../models/experiments.interface'; +import { useExperimentsData } from './useExperimentsData'; jest.mock('../../../shared/hooks/useFetch', () => ({ useFetch: jest.fn(), @@ -64,6 +65,6 @@ describe('useExperimentsData', () => { }); const { result } = renderHook(() => useExperimentsData()); - expect(result.current.test_suites.length).toEqual(allExperimentsMockData.length); + expect(result.current.testSuites.length).toEqual(allExperimentsMockData.length); }); }); \ No newline at end of file diff --git a/portal/src/app/components/all-experiments/hooks/useExperimentsData.ts b/portal/src/app/components/all-experiments/hooks/useExperimentsData.ts index b10563e2..4e872e5e 100644 --- a/portal/src/app/components/all-experiments/hooks/useExperimentsData.ts +++ b/portal/src/app/components/all-experiments/hooks/useExperimentsData.ts @@ -3,22 +3,12 @@ import { useEffect, useState } from 'react'; import { APIS } from '../../../apis'; import { useFetchSpinner } from '../../../shared/hooks/useFetchSpinner'; import { useErrorMessage } from '../../../hooks/useErrorMessage'; -import { ITestRunResult, ITestRunResultData } from '../../../shared/models/test-run-result.interface'; - -export type TestRunSubset = Pick; -export type Experiment = Pick & { test_runs: TestRunSubset[] }; +import { Experiment } from '../models/experiments.interface'; export interface IUseExperimentsData { - test_suites: Experiment[]; + testSuites: Experiment[]; status: FetchDataStatus; } -export interface ExperimentData { - id: number; - name: string; - algorithms: string[]; - iterations: number[]; - end_time: number; -}; export function useExperimentsData(): IUseExperimentsData { const [allExperiments, setAllExperiments] = useState([]); @@ -38,5 +28,5 @@ export function useExperimentsData(): IUseExperimentsData { } }, [data, status, allExperiments]); - return { test_suites: allExperiments, status }; + return { testSuites: allExperiments, status }; } diff --git a/portal/src/app/components/all-experiments/models/experiments.interface.ts b/portal/src/app/components/all-experiments/models/experiments.interface.ts new file mode 100644 index 00000000..ab9f8f73 --- /dev/null +++ b/portal/src/app/components/all-experiments/models/experiments.interface.ts @@ -0,0 +1,12 @@ +import { ITestRunResult, ITestRunResultData } from '../../../shared/models/test-run-result.interface'; + +export type TestRunSubset = Pick; +export type Experiment = Pick & { test_runs: TestRunSubset[] }; + +export interface ExperimentData { + id: number; + name: string; + algorithms: string[]; + iterations: number[]; + end_time: number; +}; diff --git a/portal/src/app/components/all-experiments/utils/parse-experiments-data.utils.test.ts b/portal/src/app/components/all-experiments/utils/parse-experiments-data.utils.test.ts index 241ed2ff..6695e3da 100644 --- a/portal/src/app/components/all-experiments/utils/parse-experiments-data.utils.test.ts +++ b/portal/src/app/components/all-experiments/utils/parse-experiments-data.utils.test.ts @@ -1,6 +1,6 @@ import { parseExperimentsData } from './parse-experiments-data.utils'; import { ITestRunResultData } from '../../../shared/models/test-run-result.interface'; -import { Experiment, ExperimentData } from '../hooks'; +import { Experiment, ExperimentData } from '../models/experiments.interface'; describe('parseExperimentsData', () => { it('should parse experiments data correctly', () => { diff --git a/portal/src/app/components/all-experiments/utils/parse-experiments-data.utils.ts b/portal/src/app/components/all-experiments/utils/parse-experiments-data.utils.ts index f1abd602..3ddfa6ac 100644 --- a/portal/src/app/components/all-experiments/utils/parse-experiments-data.utils.ts +++ b/portal/src/app/components/all-experiments/utils/parse-experiments-data.utils.ts @@ -1,4 +1,4 @@ -import { Experiment, ExperimentData, TestRunSubset } from '../hooks'; +import { Experiment, ExperimentData, TestRunSubset } from '../models/experiments.interface'; export function parseExperimentsData(test_suites: Experiment[]) { const experimentsData: ExperimentData[] = []; diff --git a/portal/src/app/components/home/Home.tsx b/portal/src/app/components/home/Home.tsx index d762aa59..e05f1b2b 100644 --- a/portal/src/app/components/home/Home.tsx +++ b/portal/src/app/components/home/Home.tsx @@ -6,7 +6,7 @@ import { SubHeader } from "../sub-header"; import { useCallback, useEffect, useState } from 'react'; import styles from './Home.module.scss'; import { useLocation, useNavigate } from "react-router-dom"; -import { ExperimentData } from "../all-experiments/hooks"; +import { ExperimentData } from "../all-experiments/models/experiments.interface"; export const Home: React.FC = () => { const [isSubHeaderOpen, setIsSubHeaderOpen] = useState(true); @@ -32,7 +32,7 @@ export const HomeContent: React.FC = () => { useEffect(() => { // Clear the state after the duplicate data has been created setDuplicateData(undefined); - }, [location]); + }, []); useEffect(() => { if (status === FetchDataStatus.Success && testSuiteId) { diff --git a/portal/src/app/components/protocol-query/ProtocolQuery.tsx b/portal/src/app/components/protocol-query/ProtocolQuery.tsx index f03a41cc..c4865ea5 100644 --- a/portal/src/app/components/protocol-query/ProtocolQuery.tsx +++ b/portal/src/app/components/protocol-query/ProtocolQuery.tsx @@ -10,7 +10,7 @@ import { Spinner, SpinnerSize } from '../../shared/components/att-spinner'; import { useGetAlgorithms, useGetIterations } from './hooks'; import { handleAlgorithmsSelection } from './utils'; import { AlgorithmsSelectorCustomOption, IterationsSelectorCustomOption } from '../../shared/components/selector-custom-option'; -import { ExperimentData } from '../all-experiments/hooks'; +import { ExperimentData } from '../all-experiments/models/experiments.interface'; import { useDuplicateData } from './hooks'; export type SelectOptionType = AttSelectOption | Options | null; diff --git a/portal/src/app/components/protocol-query/hooks/useDuplicateData.test.ts b/portal/src/app/components/protocol-query/hooks/useDuplicateData.test.ts index ad54f078..b1eefe96 100644 --- a/portal/src/app/components/protocol-query/hooks/useDuplicateData.test.ts +++ b/portal/src/app/components/protocol-query/hooks/useDuplicateData.test.ts @@ -1,7 +1,7 @@ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; import { useDuplicateData, DuplicateData } from './useDuplicateData'; import { AttSelectOption } from '../../../shared/components/att-select'; -import { ExperimentData } from '../../all-experiments/hooks'; +import { ExperimentData } from '../../all-experiments/models/experiments.interface'; describe('useDuplicateData', () => { it('should set experiment name, algorithms, and iterations count when duplicate data is provided', () => { diff --git a/portal/src/app/components/protocol-query/hooks/useDuplicateData.ts b/portal/src/app/components/protocol-query/hooks/useDuplicateData.ts index d2e9b7c3..8cf59d88 100644 --- a/portal/src/app/components/protocol-query/hooks/useDuplicateData.ts +++ b/portal/src/app/components/protocol-query/hooks/useDuplicateData.ts @@ -1,6 +1,6 @@ import { useEffect } from 'react'; import { AttSelectOption } from '../../../shared/components/att-select'; -import { ExperimentData } from '../../all-experiments/hooks'; +import { ExperimentData } from '../../all-experiments/models/experiments.interface'; export type DuplicateData = { data: ExperimentData | undefined,