Skip to content
Snippets Groups Projects
Commit 0dda20f3 authored by Tadeusz Miesiąc's avatar Tadeusz Miesiąc
Browse files

feat(drawer component): drawer component

parent b3dc3bc7
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...,!46feat(submaps drawer component): submaps drawer component
Pipeline #80431 passed
Showing
with 6603 additions and 6279 deletions
...@@ -32,7 +32,7 @@ export const useParamsQuery = (): UseParamsQuery => { ...@@ -32,7 +32,7 @@ export const useParamsQuery = (): UseParamsQuery => {
useEffect(() => { useEffect(() => {
if (searchParams?.search) dispatch(getSearchData(searchParams.search as string)); if (searchParams?.search) dispatch(getSearchData(searchParams.search as string));
}, [dispatch]); }, [dispatch, searchParams.search]);
return { setSearchQueryInRouter, searchParams }; return { setSearchQueryInRouter, searchParams };
}; };
import { SearchBar } from '@/components/FunctionalArea/TopBar/SearchBar'; import { SearchBar } from '@/components/FunctionalArea/TopBar/SearchBar';
import { UserAvatar } from '@/components/FunctionalArea/TopBar/UserAvatar'; import { UserAvatar } from '@/components/FunctionalArea/TopBar/UserAvatar';
import { openSubmapsDrawer } from '@/redux/drawer/drawer.slice';
import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
import { Button } from '@/shared/Button'; import { Button } from '@/shared/Button';
export const TopBar = (): JSX.Element => ( export const TopBar = (): JSX.Element => {
<div className="flex h-16 w-full flex-row items-center justify-between border-b border-font-500 border-opacity-[0.12] bg-white py-4 pl-7 pr-6"> const dispatch = useAppDispatch();
<div className="flex flex-row items-center">
<UserAvatar /> const onSubmapsClick = (): void => {
<SearchBar /> dispatch(openSubmapsDrawer());
<Button icon="plus" isIcon isFrontIcon className="ml-8 mr-4"> };
Submaps
</Button> return (
<Button icon="plus" isIcon isFrontIcon> <div className="flex h-16 w-full flex-row items-center justify-between border-b border-font-500 border-opacity-[0.12] bg-white py-4 pl-7 pr-6">
Overlays <div className="flex flex-row items-center">
</Button> <UserAvatar />
</div> <SearchBar />
<div className="bg-primary-100 px-4 py-1 text-xs leading-6 text-primary-500"> <Button icon="plus" isIcon isFrontIcon className="ml-8 mr-4" onClick={onSubmapsClick}>
Parkinson disease map Submaps
</Button>
<Button icon="plus" isIcon isFrontIcon>
Overlays
</Button>
</div>
<div className="bg-primary-100 px-4 py-1 text-xs leading-6 text-primary-500">
Parkinson disease map
</div>
</div> </div>
</div> );
); };
import { openSearchDrawer } from '@/redux/drawer/drawer.slice'; import { openSearchDrawer, openSubmapsDrawer } from '@/redux/drawer/drawer.slice';
import { StoreType } from '@/redux/store'; import { StoreType } from '@/redux/store';
import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore';
import { act, fireEvent, render, screen } from '@testing-library/react'; import { act, fireEvent, render, screen } from '@testing-library/react';
...@@ -63,4 +63,18 @@ describe('Drawer - component', () => { ...@@ -63,4 +63,18 @@ describe('Drawer - component', () => {
expect(screen.queryByTestId('search-drawer-content')).not.toBeInTheDocument(); expect(screen.queryByTestId('search-drawer-content')).not.toBeInTheDocument();
}); });
}); });
describe('submap drawer', () => {
it('should open drawer and display submaps', async () => {
const { store } = renderComponent();
expect(screen.queryByTestId('submap-drawer')).not.toBeInTheDocument();
await act(() => {
store.dispatch(openSubmapsDrawer());
});
expect(screen.getByTestId('submap-drawer')).toBeInTheDocument();
});
});
}); });
...@@ -3,6 +3,7 @@ import { drawerSelector } from '@/redux/drawer/drawer.selectors'; ...@@ -3,6 +3,7 @@ import { drawerSelector } from '@/redux/drawer/drawer.selectors';
import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { useAppSelector } from '@/redux/hooks/useAppSelector';
import { twMerge } from 'tailwind-merge'; import { twMerge } from 'tailwind-merge';
import { SearchDrawerWrapper as SearchDrawerContent } from './SearchDrawerWrapper'; import { SearchDrawerWrapper as SearchDrawerContent } from './SearchDrawerWrapper';
import { SubmapsDrawer } from './SubmapsDrawer';
export const Drawer = (): JSX.Element => { export const Drawer = (): JSX.Element => {
const { isOpen, drawerName } = useAppSelector(drawerSelector); const { isOpen, drawerName } = useAppSelector(drawerSelector);
...@@ -10,12 +11,13 @@ export const Drawer = (): JSX.Element => { ...@@ -10,12 +11,13 @@ export const Drawer = (): JSX.Element => {
return ( return (
<div <div
className={twMerge( className={twMerge(
'absolute left-[88px] top-[104px] z-10 h-calc-drawer w-[432px] -translate-x-full transform bg-white-pearl text-font-500 transition-all duration-500', 'absolute bottom-0 left-[88px] top-[104px] z-10 h-calc-drawer w-[432px] -translate-x-full transform bg-white-pearl text-font-500 transition-all duration-500',
isOpen && 'translate-x-0', isOpen && 'translate-x-0',
)} )}
role={DRAWER_ROLE} role={DRAWER_ROLE}
> >
{isOpen && drawerName === 'search' && <SearchDrawerContent />} {isOpen && drawerName === 'search' && <SearchDrawerContent />}
{isOpen && drawerName === 'submaps' && <SubmapsDrawer />}
</div> </div>
); );
}; };
import { Button } from '@/shared/Button';
import { IconButton } from '@/shared/IconButton';
interface SubmapItemProps {
modelName: string;
}
export const SubmpamItem = ({ modelName }: SubmapItemProps): JSX.Element => (
<div className="flex flex-row flex-nowrap items-center justify-between border-b py-6">
{modelName}
<div className="flex flex-row flex-nowrap items-center">
<Button variantStyles="ghost" className="mr-4">
Download
</Button>
<IconButton
icon="chevron-right"
className="h-6 w-6 bg-white-pearl"
classNameIcon="fill-font-500 h-6 w-6"
/>
</div>
</div>
);
import {
InitialStoreState,
getReduxWrapperWithStore,
} from '@/utils/testing/getReduxWrapperWithStore';
import { render, screen } from '@testing-library/react';
import { StoreType } from '@/redux/store';
import { MODELS_MOCK_SHORT } from '@/models/mocks/modelsMock';
import { openedDrawerSubmapsFixture } from '@/redux/drawer/drawerFixture';
import { SubmapsDrawer } from './SubmapsDrawer';
const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);
return (
render(
<Wrapper>
<SubmapsDrawer />
</Wrapper>,
),
{
store,
}
);
};
describe('SubmapsDrawer - component', () => {
it('should display drawer heading and list of submaps', () => {
renderComponent({
models: { data: MODELS_MOCK_SHORT, loading: 'succeeded', error: { name: '', message: '' } },
});
expect(screen.getByText('Core PD map')).toBeInTheDocument();
expect(screen.getByText('Histamine signaling')).toBeInTheDocument();
expect(screen.getByText('PRKN substrates')).toBeInTheDocument();
});
it('should close drawer after clicking close button', () => {
const { store } = renderComponent({
models: { data: MODELS_MOCK_SHORT, loading: 'succeeded', error: { name: '', message: '' } },
drawer: openedDrawerSubmapsFixture,
});
const closeButton = screen.getByRole('close-drawer-button');
closeButton.click();
const {
drawer: { isOpen },
} = store.getState();
expect(isOpen).toBe(false);
});
});
import { useAppSelector } from '@/redux/hooks/useAppSelector';
import { modelsDataSelector } from '@/redux/models/models.selectors';
import { DrawerHeading } from '@/shared/DrawerHeading';
import { SubmpamItem } from './SubmapItem/SubmapItem.component';
export const SubmapsDrawer = (): JSX.Element => {
const models = useAppSelector(modelsDataSelector);
return (
<div data-testid="submap-drawer">
<DrawerHeading title="Submaps" />
<ul className="overflow-y-auto px-6">
{models.map(model => (
<SubmpamItem key={model.idObject} modelName={model.name} />
))}
</ul>
</div>
);
};
export { SubmapsDrawer } from './SubmapsDrawer';
...@@ -403,3 +403,57 @@ export const MODELS_MOCK: MapModel[] = [ ...@@ -403,3 +403,57 @@ export const MODELS_MOCK: MapModel[] = [
maxZoom: 7, maxZoom: 7,
}, },
]; ];
export const MODELS_MOCK_SHORT: MapModel[] = [
{
idObject: 5053,
width: 26779.25,
height: 13503.0,
defaultCenterX: null,
defaultCenterY: null,
description: '',
name: 'Core PD map',
defaultZoomLevel: null,
tileSize: 256,
references: [],
authors: [],
creationDate: null,
modificationDates: [],
minZoom: 2,
maxZoom: 9,
},
{
idObject: 5052,
width: 3511.09375,
height: 1312.125,
defaultCenterX: null,
defaultCenterY: null,
description: '',
name: 'Histamine signaling',
defaultZoomLevel: null,
tileSize: 256,
references: [],
authors: [],
creationDate: null,
modificationDates: [],
minZoom: 2,
maxZoom: 6,
},
{
idObject: 5054,
width: 1652.75,
height: 1171.9429798877356,
defaultCenterX: null,
defaultCenterY: null,
description: '',
name: 'PRKN substrates',
defaultZoomLevel: null,
tileSize: 256,
references: [],
authors: [],
creationDate: null,
modificationDates: [],
minZoom: 2,
maxZoom: 5,
},
];
...@@ -10,6 +10,7 @@ import drawerReducer, { ...@@ -10,6 +10,7 @@ import drawerReducer, {
displayGroupedSearchResults, displayGroupedSearchResults,
openDrawer, openDrawer,
openSearchDrawer, openSearchDrawer,
openSubmapsDrawer,
} from './drawer.slice'; } from './drawer.slice';
import type { DrawerState } from './drawer.types'; import type { DrawerState } from './drawer.types';
...@@ -79,6 +80,15 @@ describe('drawer reducer', () => { ...@@ -79,6 +80,15 @@ describe('drawer reducer', () => {
expect(currentStep).toEqual(STEP.FIRST); expect(currentStep).toEqual(STEP.FIRST);
}); });
it('should update the store after openSubmapsDrawer action', async () => {
const { type } = await store.dispatch(openSubmapsDrawer());
const { isOpen, drawerName } = store.getState().drawer;
expect(type).toBe('drawer/openSubmapsDrawer');
expect(isOpen).toBe(true);
expect(drawerName).toEqual('submaps');
});
it('should update the store after closeDrawerReducer action', async () => { it('should update the store after closeDrawerReducer action', async () => {
const { type } = await store.dispatch(closeDrawer()); const { type } = await store.dispatch(closeDrawer());
const { const {
......
...@@ -14,6 +14,11 @@ export const openSearchDrawerReducer = (state: DrawerState): void => { ...@@ -14,6 +14,11 @@ export const openSearchDrawerReducer = (state: DrawerState): void => {
state.searchDrawerState.currentStep = STEP.FIRST; state.searchDrawerState.currentStep = STEP.FIRST;
}; };
export const openSubmapsDrawerReducer = (state: DrawerState): void => {
state.isOpen = true;
state.drawerName = 'submaps';
};
export const closeDrawerReducer = (state: DrawerState): void => { export const closeDrawerReducer = (state: DrawerState): void => {
state.isOpen = false; state.isOpen = false;
state.drawerName = 'none'; state.drawerName = 'none';
......
...@@ -9,6 +9,7 @@ import { ...@@ -9,6 +9,7 @@ import {
displayMirnaListReducer, displayMirnaListReducer,
openDrawerReducer, openDrawerReducer,
openSearchDrawerReducer, openSearchDrawerReducer,
openSubmapsDrawerReducer,
} from './drawer.reducers'; } from './drawer.reducers';
const initialState: DrawerState = { const initialState: DrawerState = {
...@@ -27,6 +28,7 @@ const drawerSlice = createSlice({ ...@@ -27,6 +28,7 @@ const drawerSlice = createSlice({
reducers: { reducers: {
openDrawer: openDrawerReducer, openDrawer: openDrawerReducer,
openSearchDrawer: openSearchDrawerReducer, openSearchDrawer: openSearchDrawerReducer,
openSubmapsDrawer: openSubmapsDrawerReducer,
closeDrawer: closeDrawerReducer, closeDrawer: closeDrawerReducer,
displayDrugsList: displayDrugsListReducer, displayDrugsList: displayDrugsListReducer,
displayChemicalsList: displayChemicalsListReducer, displayChemicalsList: displayChemicalsListReducer,
...@@ -39,6 +41,7 @@ const drawerSlice = createSlice({ ...@@ -39,6 +41,7 @@ const drawerSlice = createSlice({
export const { export const {
openDrawer, openDrawer,
openSearchDrawer, openSearchDrawer,
openSubmapsDrawer,
closeDrawer, closeDrawer,
displayDrugsList, displayDrugsList,
displayChemicalsList, displayChemicalsList,
......
...@@ -10,6 +10,16 @@ export const initialStateFixture: DrawerState = { ...@@ -10,6 +10,16 @@ export const initialStateFixture: DrawerState = {
}, },
}; };
export const openedDrawerSubmapsFixture: DrawerState = {
isOpen: true,
drawerName: 'submaps',
searchDrawerState: {
currentStep: 0,
stepType: 'none',
selectedValue: undefined,
},
};
export const drawerSearchStepOneFixture: DrawerState = { export const drawerSearchStepOneFixture: DrawerState = {
isOpen: true, isOpen: true,
drawerName: 'search', drawerName: 'search',
......
import { StoreType } from '@/redux/store';
import { render, screen } from '@testing-library/react';
import {
InitialStoreState,
getReduxWrapperWithStore,
} from '@/utils/testing/getReduxWrapperWithStore';
import { openedDrawerSubmapsFixture } from '@/redux/drawer/drawerFixture';
import { DrawerHeading } from './DrawerHeading.component';
const renderComponent = (
title: string,
initialStoreState: InitialStoreState = {},
): { store: StoreType } => {
const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);
return (
render(
<Wrapper>
<DrawerHeading title={title} />
</Wrapper>,
),
{
store,
}
);
};
describe('DrawerHeading - component', () => {
it('should display passed title', () => {
renderComponent('Example');
expect(screen.getByText('Example')).toBeInTheDocument();
});
it('should call class drawer on close button click', () => {
const { store } = renderComponent('Example', {
drawer: {
...openedDrawerSubmapsFixture,
},
});
expect(store.getState().drawer.isOpen).toBe(true);
const closeButton = screen.getByRole('close-drawer-button');
closeButton.click();
expect(store.getState().drawer.isOpen).toBe(false);
});
});
import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
import { IconButton } from '@/shared/IconButton';
import { closeDrawer } from '@/redux/drawer/drawer.slice';
import { CLOSE_BUTTON_ROLE } from '../DrawerHeadingBackwardButton/DrawerHeadingBackwardButton.constants';
interface DrawerHeadingProps {
title: string;
}
export const DrawerHeading = ({ title }: DrawerHeadingProps): JSX.Element => {
const dispatch = useAppDispatch();
const onCloseButtonClick = (): void => {
dispatch(closeDrawer());
};
return (
<div className="flex items-center justify-between border-b border-b-divide px-6">
<div className=" py-8 text-xl">
<span className="font-semibold">{title}</span>
</div>
<IconButton
className="bg-white-pearl"
classNameIcon="fill-font-500"
icon="close"
role={CLOSE_BUTTON_ROLE}
onClick={onCloseButtonClick}
/>
</div>
);
};
export { DrawerHeading } from './DrawerHeading.component';
export type DrawerName = 'none' | 'search' | 'project-info' | 'plugins' | 'export' | 'legend'; export type DrawerName =
| 'none'
| 'search'
| 'project-info'
| 'plugins'
| 'export'
| 'legend'
| 'submaps';
This diff is collapsed.
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