Skip to content
Snippets Groups Projects
Commit 59979c47 authored by mateusz-winiarczyk's avatar mateusz-winiarczyk
Browse files

Merge branch 'MIN-246-boxes-top-right-map-corner' into 'development'

fix(map): the two boxes in the top-right map corner (MIN-246)

Closes MIN-246

See merge request !184
parents d7527586 1f76c171
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...,!184fix(map): the two boxes in the top-right map corner (MIN-246)
Pipeline #89050 passed
import { StoreType } from '@/redux/store';
import { AppDispatch, RootState, StoreType } from '@/redux/store';
import {
InitialStoreState,
getReduxWrapperWithStore,
} from '@/utils/testing/getReduxWrapperWithStore';
import { render, screen } from '@testing-library/react';
import { initialStateFixture } from '@/redux/drawer/drawerFixture';
import { MockStoreEnhanced } from 'redux-mock-store';
import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreActionsListener';
import { PROJECT_STATE_INITIAL_MOCK } from '@/redux/project/project.mock';
import { projectFixture } from '@/models/fixtures/projectFixture';
import { initialMapStateFixture } from '@/redux/map/map.fixtures';
import {
BACKGROUNDS_MOCK,
BACKGROUND_INITIAL_STATE_MOCK,
} from '@/redux/backgrounds/background.mock';
import { FIRST_ARRAY_ELEMENT } from '@/constants/common';
import { USER_INITIAL_STATE_MOCK } from '@/redux/user/user.mock';
import { SEARCH_STATE_INITIAL_MOCK } from '@/redux/search/search.mock';
import { TopBar } from './TopBar.component';
const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
......@@ -22,6 +34,23 @@ const renderComponent = (initialStoreState: InitialStoreState = {}): { store: St
);
};
const renderComponentWithActionListener = (
initialStoreState: InitialStoreState = {},
): { store: MockStoreEnhanced<Partial<RootState>, AppDispatch> } => {
const { Wrapper, store } = getReduxStoreWithActionsListener(initialStoreState);
return (
render(
<Wrapper>
<TopBar />
</Wrapper>,
),
{
store,
}
);
};
describe('TopBar - component', () => {
it('Should contain search bar', () => {
renderComponent();
......@@ -52,4 +81,54 @@ describe('TopBar - component', () => {
expect(isOpen).toBe(true);
expect(drawerName).toBe('overlays');
});
it('should render browse overview images button', () => {
renderComponent();
expect(screen.getByText('Browse overview images')).toBeInTheDocument();
});
it('should open overview image modal on button click', () => {
const { store } = renderComponentWithActionListener({
project: {
...PROJECT_STATE_INITIAL_MOCK,
data: projectFixture,
},
drawer: initialStateFixture,
user: USER_INITIAL_STATE_MOCK,
map: initialMapStateFixture,
search: SEARCH_STATE_INITIAL_MOCK,
backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK },
});
const overviewImageButton = screen.getByText('Browse overview images');
overviewImageButton.click();
const actions = store.getActions();
expect(actions[FIRST_ARRAY_ELEMENT]).toStrictEqual({
payload: projectFixture.topOverviewImage?.idObject,
type: 'modal/openOverviewImagesModalById',
});
});
it('should disable button browse overview images if there are no overview images', () => {
const { store } = renderComponentWithActionListener({
user: USER_INITIAL_STATE_MOCK,
search: SEARCH_STATE_INITIAL_MOCK,
drawer: initialStateFixture,
project: {
...PROJECT_STATE_INITIAL_MOCK,
data: {
...projectFixture,
overviewImageViews: [],
},
},
map: initialMapStateFixture,
backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK },
});
const overviewImageButton = screen.getByText('Browse overview images');
expect(overviewImageButton).toBeDisabled();
overviewImageButton.click();
const actions = store.getActions();
expect(actions).toStrictEqual([]);
});
});
......@@ -3,14 +3,28 @@ import { SearchBar } from '@/components/FunctionalArea/TopBar/SearchBar';
import { openOverlaysDrawer, openSubmapsDrawer } from '@/redux/drawer/drawer.slice';
import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
import { useAppSelector } from '@/redux/hooks/useAppSelector';
import { projectDataSelector } from '@/redux/project/project.selectors';
import {
projectDataSelector,
projectDefaultOverviewImageIdSelector,
projectOverviewImagesSelector,
} from '@/redux/project/project.selectors';
import { Button } from '@/shared/Button';
import { ClearAnchorsButton } from './ClearAnchorsButton';
import { ZERO } from '@/constants/common';
import { useSelector } from 'react-redux';
import { openOverviewImagesModalById } from '@/redux/modal/modal.slice';
import { User } from './User';
import { ClearAnchorsButton } from './ClearAnchorsButton';
export const TopBar = (): JSX.Element => {
const dispatch = useAppDispatch();
const currentProject = useAppSelector(projectDataSelector);
const defaultOverviewImageId = useSelector(projectDefaultOverviewImageIdSelector);
const overviewImages = useSelector(projectOverviewImagesSelector);
const overviewImagesEmpty = overviewImages.length === ZERO;
const handleBrowseOverviewImagesClick = (): void => {
dispatch(openOverviewImagesModalById(defaultOverviewImageId));
};
const onSubmapsClick = (): void => {
dispatch(openSubmapsDrawer());
......@@ -21,7 +35,7 @@ export const TopBar = (): JSX.Element => {
};
return (
<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 pr-6">
<div className="flex h-16 w-full flex-row items-center justify-between overflow-x-auto border-b border-font-500 border-opacity-[0.12] bg-white py-4 pr-6 xl:overflow-x-visible">
<div className="flex flex-row items-center">
<div className="relative flex w-[88px] justify-center">
<User />
......@@ -43,8 +57,18 @@ export const TopBar = (): JSX.Element => {
Overlays
</Button>
</div>
<div className="bg-primary-100 px-4 py-1 text-xs leading-6 text-primary-500">
{currentProject?.name || ''}
<div className="flex items-center">
<Button
className="mx-4 flex-none"
onClick={handleBrowseOverviewImagesClick}
disabled={overviewImagesEmpty}
variantStyles="secondary"
>
Browse overview images
</Button>
<div className="flex-none bg-primary-100 px-4 py-1 text-xs leading-6 text-primary-500">
{currentProject?.name || ''}
</div>
</div>
</div>
);
......
......@@ -44,7 +44,7 @@ export const BackgroundSelector = (): JSX.Element => {
data-testid="background-selector"
className={twMerge('rounded-t bg-white text-xs shadow-primary', !isOpen && 'rounded-b')}
>
<div className={twMerge('flex w-72 flex-col rounded-t py-2 pl-4 pr-3')}>
<div className={twMerge('flex w-[135px] flex-col rounded-t py-2 pl-4 pr-3')}>
<div
className="flex cursor-pointer flex-row items-center justify-between bg-white"
{...getToggleButtonProps()}
......@@ -59,7 +59,7 @@ export const BackgroundSelector = (): JSX.Element => {
</div>
</div>
<ul
className={`absolute z-10 max-h-80 w-72 overflow-scroll rounded-b bg-white p-0 ${
className={`absolute z-10 max-h-80 w-[135px] overflow-scroll rounded-b bg-white p-0 ${
!isOpen && 'hidden'
}`}
{...getMenuProps()}
......
import { FIRST_ARRAY_ELEMENT } from '@/constants/common';
import {
BACKGROUNDS_MOCK,
BACKGROUND_INITIAL_STATE_MOCK,
} from '@/redux/backgrounds/background.mock';
import { initialMapStateFixture } from '@/redux/map/map.fixtures';
import { AppDispatch, RootState, StoreType } from '@/redux/store';
import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreActionsListener';
import { StoreType } from '@/redux/store';
import {
InitialStoreState,
getReduxWrapperWithStore,
} from '@/utils/testing/getReduxWrapperWithStore';
import { render, screen } from '@testing-library/react';
import { MockStoreEnhanced } from 'redux-mock-store';
import { PROJECT_STATE_INITIAL_MOCK } from '@/redux/project/project.mock';
import { projectFixture } from '@/models/fixtures/projectFixture';
import { MapAdditionalOptions } from './MapAdditionalOptions.component';
const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
......@@ -31,71 +21,9 @@ const renderComponent = (initialStoreState: InitialStoreState = {}): { store: St
);
};
const renderComponentWithActionListener = (
initialStoreState: InitialStoreState = {},
): { store: MockStoreEnhanced<Partial<RootState>, AppDispatch> } => {
const { Wrapper, store } = getReduxStoreWithActionsListener(initialStoreState);
return (
render(
<Wrapper>
<MapAdditionalOptions />
</Wrapper>,
),
{
store,
}
);
};
describe('MapAdditionalOptions - component', () => {
it('should display background selector', () => {
renderComponent();
expect(screen.getByTestId('background-selector')).toBeInTheDocument();
});
it('should render browse overview images button', () => {
renderComponent();
expect(screen.getByText('Browse overview images')).toBeInTheDocument();
});
it('should open overview image modal on button click', () => {
const { store } = renderComponentWithActionListener({
project: {
...PROJECT_STATE_INITIAL_MOCK,
data: projectFixture,
},
map: initialMapStateFixture,
backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK },
});
const overviewImageButton = screen.getByText('Browse overview images');
overviewImageButton.click();
const actions = store.getActions();
expect(actions[FIRST_ARRAY_ELEMENT]).toStrictEqual({
payload: projectFixture.topOverviewImage?.idObject,
type: 'modal/openOverviewImagesModalById',
});
});
it('should disable button browse overview images if there are no overview images', () => {
const { store } = renderComponentWithActionListener({
project: {
...PROJECT_STATE_INITIAL_MOCK,
data: {
...projectFixture,
overviewImageViews: [],
},
},
map: initialMapStateFixture,
backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK },
});
const overviewImageButton = screen.getByText('Browse overview images');
expect(overviewImageButton).toBeDisabled();
overviewImageButton.click();
const actions = store.getActions();
expect(actions).toStrictEqual([]);
});
});
import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
import { openOverviewImagesModalById } from '@/redux/modal/modal.slice';
import {
projectDefaultOverviewImageIdSelector,
projectOverviewImagesSelector,
} from '@/redux/project/project.selectors';
import { Button } from '@/shared/Button';
import { useSelector } from 'react-redux';
import { twMerge } from 'tailwind-merge';
import { ZERO } from '@/constants/common';
import { BackgroundSelector } from './BackgroundsSelector';
// top-[calc(64px+40px+24px)] -> TOP_BAR_HEIGHT+MAP_NAVIGATION_HEIGHT+DISTANCE_FROM_MAP_NAVIGATION
export const MapAdditionalOptions = (): JSX.Element => {
const dispatch = useAppDispatch();
const defaultOverviewImageId = useSelector(projectDefaultOverviewImageIdSelector);
const overviewImages = useSelector(projectOverviewImagesSelector);
const overviewImagesEmpty = overviewImages.length === ZERO;
const handleBrowseOverviewImagesClick = (): void => {
dispatch(openOverviewImagesModalById(defaultOverviewImageId));
};
return (
<div className={twMerge('absolute right-6 top-[calc(64px+40px+24px)] z-10 flex')}>
<Button
className="mr-4"
onClick={handleBrowseOverviewImagesClick}
disabled={overviewImagesEmpty}
>
Browse overview images
</Button>
<BackgroundSelector />
</div>
);
};
export const MapAdditionalOptions = (): JSX.Element => (
<div className={twMerge('absolute right-6 top-[calc(64px+40px+24px)] z-10 flex')}>
<BackgroundSelector />
</div>
);
......@@ -2,11 +2,21 @@ import { EMPTY_BACKGROUND_NAME } from '@/constants/backgrounds';
import { createSelector } from '@reduxjs/toolkit';
import { mapDataSelector } from '../map/map.selectors';
import { rootSelector } from '../root/root.selectors';
import { PATHWAYS_AND_COMPARTMENTS_BACKGROUND, SEMANTIC_BACKGROUND } from './backgrounds.constants';
export const backgroundsSelector = createSelector(rootSelector, state => state.backgrounds);
export const backgroundsDataSelector = createSelector(backgroundsSelector, backgrounds => {
return backgrounds?.data || [];
return (backgrounds?.data || []).map(background => {
if (background.name === PATHWAYS_AND_COMPARTMENTS_BACKGROUND) {
return {
...background,
name: SEMANTIC_BACKGROUND,
};
}
return background;
});
});
const MAIN_BACKGROUND = 0;
......
export const BACKGROUNDS_FETCHING_ERROR_PREFIX = 'Failed to fetch backgrounds';
export const PATHWAYS_AND_COMPARTMENTS_BACKGROUND = 'Pathways and compartments';
export const SEMANTIC_BACKGROUND = 'Semantic';
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