Skip to content
Snippets Groups Projects
Commit fb32acbe authored by Adrian Orłów's avatar Adrian Orłów
Browse files

Merge remote-tracking branch 'origin/development' into feature/map-data-mgmt

parents c3fc37dc a5230e3f
No related branches found
No related tags found
2 merge requests!223reset the pin numbers before search results are fetch (so the results will be...,!35feat(map): add data management
Pipeline #79932 passed
Showing
with 327 additions and 7 deletions
export { DrugsAccordion } from './DrugsAccordion.component';
import { render, screen } from '@testing-library/react';
import { StoreType } from '@/redux/store';
import {
InitialStoreState,
getReduxWrapperWithStore,
} from '@/utils/testing/getReduxWrapperWithStore';
import { mirnasFixture } from '@/models/fixtures/mirnasFixture';
import { Accordion } from '@/shared/Accordion';
import { MirnaAccordion } from './MirnaAccordion.component';
const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);
return (
render(
<Wrapper>
<Accordion>
<MirnaAccordion />
</Accordion>
</Wrapper>,
),
{
store,
}
);
};
describe('DrugsAccordion - component', () => {
it('should display drugs number after succesfull chemicals search', () => {
renderComponent({
mirnas: { data: mirnasFixture, loading: 'succeeded', error: { name: '', message: '' } },
});
expect(screen.getByText('MiRNA (2)')).toBeInTheDocument();
});
it('should display loading indicator while waiting for chemicals search response', () => {
renderComponent({
mirnas: { data: [], loading: 'pending', error: { name: '', message: '' } },
});
expect(screen.getByText('MiRNA (Loading...)')).toBeInTheDocument();
});
});
import { useAppSelector } from '@/redux/hooks/useAppSelector';
import {
numberOfMirnasSelector,
loadingMirnasStatusSelector,
} from '@/redux/mirnas/mirnas.selectors';
import { AccordionItem, AccordionItemHeading, AccordionItemButton } from '@/shared/Accordion';
export const MirnaAccordion = (): JSX.Element => {
const mirnaNumber = useAppSelector(numberOfMirnasSelector);
const mirnaState = useAppSelector(loadingMirnasStatusSelector);
return (
<AccordionItem>
<AccordionItemHeading>
<AccordionItemButton variant="non-expandable">
MiRNA
{mirnaState === 'pending' && ' (Loading...)'}
{mirnaState === 'succeeded' && ` (${mirnaNumber})`}
</AccordionItemButton>
</AccordionItemHeading>
</AccordionItem>
);
};
export { MirnaAccordion } from './MirnaAccordion.component';
import { PinItem } from './PinsList.types';
import { PinsListItem } from './PinsListItem';
interface PinsListProps {
pinsList: PinItem[];
}
export const PinsList = ({ pinsList }: PinsListProps): JSX.Element => (
<ul className="px-6 py-2">
{pinsList.map(pin => (
<PinsListItem key={pin.name} name={pin.name} />
))}
</ul>
);
export type PinItem = {
name: string;
};
import { Icon } from '@/shared/Icon';
interface PinsListItemProps {
name: string;
}
export const PinsListItem = ({ name }: PinsListItemProps): JSX.Element => (
<div className="flex flex-row justify-between pt-4">
<Icon name="pin" className="mr-2 shrink-0" />
<p className="w-full text-left">{name}</p>
<Icon name="chevron-right" className="h-6 w-6 shrink-0" />
</div>
);
export { PinsListItem } from './PinsListItem.component';
export { PinsList } from './PinsList.component';
import { DrawerHeadingBackwardButton } from '@/shared/DrawerHeadingBackwardButton';
import { PinsList } from './PinsList';
import { PinItem } from './PinsList/PinsList.types';
const PINS_LIST: PinItem[] = [
{ name: 'Glyceraldehyde-3-phosphate dehydrogenase' },
{ name: 'D-3-phosphoglycerate dehydrogenase' },
{ name: 'Glutathione reductase, mitochondrial' },
{ name: 'NADH dehydrogenase [ubiquinone] iron-sulfur protein 8, mitochondrial' },
];
export const Results = (): JSX.Element => {
const drugName = 'Aspirin';
const navigateToGroupedSearchResults = (): void => {};
return (
<div>
<DrawerHeadingBackwardButton
title="Drugs"
value={drugName}
backwardFunction={navigateToGroupedSearchResults}
/>
<PinsList pinsList={PINS_LIST} />
</div>
);
};
export { Results } from './Results.component';
import { BioEntitiesAccordion } from '@/components/Map/Drawer/SearchDrawerContent/BioEntitiesAccordion'; import { BioEntitiesAccordion } from '@/components/Map/Drawer/SearchDrawerContent/BioEntitiesAccordion';
import { DrugsAccordion } from '@/components/Map/Drawer/SearchDrawerContent/DrugsAccordion';
import { ChemicalsAccordion } from '@/components/Map/Drawer/SearchDrawerContent/ChemicalsAccordion';
import { MirnaAccordion } from '@/components/Map/Drawer/SearchDrawerContent/MirnaAccordion';
import { closeDrawer } from '@/redux/drawer/drawer.slice'; import { closeDrawer } from '@/redux/drawer/drawer.slice';
import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
import { IconButton } from '@/shared/IconButton'; import { IconButton } from '@/shared/IconButton';
import { Accordion } from '@/shared/Accordion';
export const CLOSE_BUTTON_ROLE = 'close-drawer-button'; export const CLOSE_BUTTON_ROLE = 'close-drawer-button';
...@@ -28,7 +32,12 @@ export const SearchDrawerContent = (): JSX.Element => { ...@@ -28,7 +32,12 @@ export const SearchDrawerContent = (): JSX.Element => {
/> />
</div> </div>
<div className="px-6"> <div className="px-6">
<BioEntitiesAccordion /> <Accordion allowZeroExpanded>
<BioEntitiesAccordion />
<DrugsAccordion />
<ChemicalsAccordion />
<MirnaAccordion />
</Accordion>
</div> </div>
</div> </div>
); );
......
import { SearchDrawerWrapper } from '@/components/Map/Drawer/SearchDrawerWrapper';
import { StoreType } from '@/redux/store';
import {
InitialStoreState,
getReduxWrapperWithStore,
} from '@/utils/testing/getReduxWrapperWithStore';
import { render, screen } from '@testing-library/react';
const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);
return (
render(
<Wrapper>
<SearchDrawerWrapper />
</Wrapper>,
),
{
store,
}
);
};
describe('SearchDrawerWrapper - component', () => {
it('should display the first step for search', () => {
renderComponent({
drawer: {
isOpen: true,
drawerName: 'search',
searchDrawerState: {
currentStep: 1,
selectedValue: {
name: '',
valueType: 'none',
},
},
},
});
expect(screen.getByTestId('search-first-step')).toBeInTheDocument();
});
it('should display the second step for value type bioEntity', () => {
renderComponent({
drawer: {
isOpen: true,
drawerName: 'search',
searchDrawerState: {
currentStep: 2,
selectedValue: {
model: { name: 'test model bioEntity', id: 'test-id' },
name: 'bio entity second step',
valueType: 'bioEntity',
},
},
},
});
expect(screen.getByTestId('search-second-step')).toBeInTheDocument();
});
it('should display the second step for value type chemicals', () => {
renderComponent({
drawer: {
isOpen: true,
drawerName: 'search',
searchDrawerState: {
currentStep: 2,
selectedValue: {
name: 'chemicals second step',
valueType: 'chemicals',
},
},
},
});
expect(screen.getByTestId('search-second-step')).toBeInTheDocument();
});
it('should display the third step for value type bioEntity', () => {
renderComponent({
drawer: {
isOpen: true,
drawerName: 'search',
searchDrawerState: {
currentStep: 3,
selectedValue: {
model: { name: 'test model bioEntity', id: 'test-id' },
name: 'bio entity third step',
valueType: 'bioEntity',
},
},
},
});
expect(screen.getByTestId('search-third-step')).toBeInTheDocument();
});
it('should display the third step for value type chemicals', () => {
renderComponent({
drawer: {
isOpen: true,
drawerName: 'search',
searchDrawerState: {
currentStep: 3,
selectedValue: {
name: 'chemicals third step',
valueType: 'chemicals',
},
},
},
});
expect(screen.getByTestId('search-third-step')).toBeInTheDocument();
});
});
import { STEP } from '@/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.constants';
import { BIO_ENTITY, DRUGS_CHEMICALS_MIRNA } from '@/constants';
import {
currentStepDrawerStateSelector,
valueTypeDrawerSelector,
} from '@/redux/drawer/drawer.selectors';
import { useSelector } from 'react-redux';
export const SearchDrawerWrapper = (): JSX.Element => {
const currentStep = useSelector(currentStepDrawerStateSelector);
const valueType = useSelector(valueTypeDrawerSelector);
const isBioEntityType = valueType === BIO_ENTITY;
const isChemicalsDrugsOrMirnaType = DRUGS_CHEMICALS_MIRNA.includes(valueType);
return (
<div>
{/* first step for displaying search results, drawers etc */}
{currentStep === STEP.FIRST && <div data-testid="search-first-step">The first step</div>}
{/* 2nd step for bioEntities aka content */}
{currentStep === STEP.SECOND && isBioEntityType && (
<div data-testid="search-second-step">The second step</div>
)}
{/* 2nd step for drugs,chemicals,mirna */}
{currentStep === STEP.SECOND && isChemicalsDrugsOrMirnaType && (
<div data-testid="search-second-step">The second step</div>
)}
{/* last step for bioentity */}
{currentStep === STEP.THIRD && isBioEntityType && (
<div data-testid="search-third-step">The third step</div>
)}
{/* last step for drugs,chemicals,mirna */}
{currentStep === STEP.THIRD && isChemicalsDrugsOrMirnaType && (
<div data-testid="search-third-step">The third step</div>
)}
</div>
);
};
export const STEP = {
FIRST: 1,
SECOND: 2,
THIRD: 3,
};
export { SearchDrawerWrapper } from './SearchDrawerWrapper.component';
...@@ -2,6 +2,9 @@ import { Manrope } from '@next/font/google'; ...@@ -2,6 +2,9 @@ import { Manrope } from '@next/font/google';
import { twMerge } from 'tailwind-merge'; import { twMerge } from 'tailwind-merge';
import { Map } from '@/components/Map'; import { Map } from '@/components/Map';
import { FunctionalArea } from '@/components/FunctionalArea'; import { FunctionalArea } from '@/components/FunctionalArea';
import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
import { useEffect } from 'react';
import { getModels } from '@/redux/models/models.thunks';
const manrope = Manrope({ const manrope = Manrope({
variable: '--font-manrope', variable: '--font-manrope',
...@@ -10,9 +13,17 @@ const manrope = Manrope({ ...@@ -10,9 +13,17 @@ const manrope = Manrope({
subsets: ['latin'], subsets: ['latin'],
}); });
export const MinervaSPA = (): JSX.Element => ( export const MinervaSPA = (): JSX.Element => {
<div className={twMerge('relative', manrope.variable)}> const dispatch = useAppDispatch();
<FunctionalArea />
<Map /> useEffect(() => {
</div> dispatch(getModels());
); }, [dispatch]);
return (
<div className={twMerge('relative', manrope.variable)}>
<FunctionalArea />
<Map />
</div>
);
};
export const SIZE_OF_EMPTY_ARRAY = 0;
export const BASE_API_URL = process.env.NEXT_PUBLIC_BASE_API_URL || ''; export const BASE_API_URL = process.env.NEXT_PUBLIC_BASE_API_URL || '';
export const PROJECT_ID = process.env.NEXT_PUBLIC_PROJECT_ID || ''; export const PROJECT_ID = process.env.NEXT_PUBLIC_PROJECT_ID || '';
export const ZOD_SEED = 997; export const ZOD_SEED = 997;
export const BIO_ENTITY = 'bioEntity';
export const DRUGS_CHEMICALS_MIRNA = ['drugs', 'chemicals', 'mirna'];
import { useEffect, useRef } from 'react';
export default function usePrevious<T>(state: T): T | undefined {
const ref = useRef<T>();
useEffect(() => {
ref.current = state;
});
return ref.current;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment