Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • minerva/frontend
1 result
Show changes
Commits on Source (8)
Showing
with 423 additions and 28 deletions
......@@ -8,26 +8,18 @@ import {
} from '@/redux/search/search.selectors';
import { getSearchData } from '@/redux/search/search.thunks';
import Image from 'next/image';
import { ChangeEvent, KeyboardEvent, useEffect, useState } from 'react';
import { ChangeEvent, KeyboardEvent, useState } from 'react';
import { useSelector } from 'react-redux';
import { useRouter } from 'next/router';
import { getDefaultSearchTab, getSearchValuesArrayAndTrimToSeven } from './SearchBar.utils';
const ENTER_KEY_CODE = 'Enter';
export const SearchBar = (): JSX.Element => {
const [searchValue, setSearchValue] = useState<string>('');
const isPendingSearchStatus = useSelector(isPendingSearchStatusSelector);
const isDrawerOpen = useSelector(isDrawerOpenSelector);
const isPerfectMatch = useSelector(perfectMatchSelector);
const [searchValue, setSearchValue] = useState<string>('');
const dispatch = useAppDispatch();
const { query } = useRouter();
useEffect(() => {
if (!searchValue && query.searchValue) {
setSearchValue(String(query.searchValue));
}
}, [searchValue, query]);
const openSearchDrawerIfClosed = (defaultSearchTab: string): void => {
if (!isDrawerOpen) {
......@@ -35,8 +27,9 @@ export const SearchBar = (): JSX.Element => {
}
};
const onSearchChange = (event: ChangeEvent<HTMLInputElement>): void =>
const onSearchChange = (event: ChangeEvent<HTMLInputElement>): void => {
setSearchValue(event.target.value);
};
const onSearchClick = (): void => {
const searchValues = getSearchValuesArrayAndTrimToSeven(searchValue);
......
/* eslint-disable no-magic-numbers */
import { drugsFixture } from '@/models/fixtures/drugFixtures';
import { chemicalsFixture } from '@/models/fixtures/chemicalsFixture';
import { drugsFixture } from '@/models/fixtures/drugFixtures';
import { StoreType } from '@/redux/store';
import {
InitialStoreState,
getReduxWrapperWithStore,
} from '@/utils/testing/getReduxWrapperWithStore';
import { render, screen } from '@testing-library/react';
import { PinItem, PinType } from '../PinsList/PinsList.types';
import { PinItem, PinTypeWithNone } from '../PinsList/PinsList.types';
import { AccordionsDetails } from './AccordionsDetails.component';
const DRUGS_PINS_LIST = drugsFixture.map(drug => ({
......@@ -24,7 +24,7 @@ const CHEMICALS_PINS_LIST = chemicalsFixture.map(chemical => ({
const renderComponent = (
pinsList: PinItem[],
type: PinType,
type: PinTypeWithNone,
initialStoreState: InitialStoreState = {},
): { store: StoreType } => {
const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);
......
......@@ -5,7 +5,7 @@ import {
AccordionItemHeading,
AccordionItemPanel,
} from '@/shared/Accordion';
import { PinItem, PinType } from '../PinsList/PinsList.types';
import { PinItem, PinTypeWithNone } from '../PinsList/PinsList.types';
import {
getAdditionalInfo,
getEntityDescriptions,
......@@ -15,7 +15,7 @@ import {
interface AccordionsDetailsProps {
pinsList: PinItem[];
type: PinType;
type: PinTypeWithNone;
}
export const AccordionsDetails = ({ pinsList, type }: AccordionsDetailsProps): JSX.Element => {
......
import { PinItem, PinType } from '../PinsList/PinsList.types';
import { PinItem, PinTypeWithNone } from '../PinsList/PinsList.types';
export const getEntityNames = (pinsList: PinItem[]): string => {
let name = '';
......@@ -34,7 +34,7 @@ export const getEntitySynonyms = (pinsList: PinItem[]): string => {
return synonyms;
};
export const getAdditionalInfo = (pinsList: PinItem[], type: PinType): string => {
export const getAdditionalInfo = (pinsList: PinItem[], type: PinTypeWithNone): string => {
if (type === 'drugs') {
return pinsList
.map(element => ('bloodBrainBarrier' in element.data ? element.data.bloodBrainBarrier : ''))
......
import { assertNever } from '@/utils/assertNever';
import { AccordionsDetails } from '../AccordionsDetails/AccordionsDetails.component';
import { PinItem, PinType } from './PinsList.types';
import { PinItem, PinTypeWithNone } from './PinsList.types';
import { PinsListItem } from './PinsListItem';
interface PinsListProps {
pinsList: PinItem[];
type: PinType;
type: PinTypeWithNone;
}
export const PinsList = ({ pinsList, type }: PinsListProps): JSX.Element => {
......
import { Drug, Chemical, Mirna } from '@/types/models';
import { Chemical, Drug, Mirna } from '@/types/models';
import { PinType } from '@/types/pin';
export type PinItem = {
id: string | number;
......@@ -6,4 +7,4 @@ export type PinItem = {
data: Drug | Chemical | Mirna;
};
export type PinType = 'chemicals' | 'drugs' | 'mirna' | 'bioEntity' | 'none';
export type PinTypeWithNone = PinType | 'none';
import { twMerge } from 'tailwind-merge';
import { Icon } from '@/shared/Icon';
import { PinDetailsItem } from '@/types/models';
import { twMerge } from 'tailwind-merge';
import { PinTypeWithNone } from '../PinsList.types';
import { getPinColor } from './PinsListItem.component.utils';
import { PinType } from '../PinsList.types';
interface MirnaPinsListItemProps {
name: string;
type: PinType;
type: PinTypeWithNone;
pin: PinDetailsItem;
}
......
import { PinType } from '../PinsList.types';
import { PinTypeWithNone } from '../PinsList.types';
export const getPinColor = (type: PinType): string => {
const pinColors: Record<PinType, string> = {
export const getPinColor = (type: PinTypeWithNone): string => {
const pinColors: Record<PinTypeWithNone, string> = {
bioEntity: 'fill-primary-500',
drugs: 'fill-orange',
chemicals: 'fill-purple',
......
import { ONE } from '@/constants/common';
import { BioEntity } from '@/types/models';
import { PinType } from '@/types/pin';
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import { Feature } from 'ol';
import { getBioEntitySingleFeature } from './getBioEntitySingleFeature';
export const getBioEntitiesFeatures = (
bioEntites: BioEntity[],
{
pointToProjection,
type,
}: {
pointToProjection: UsePointToProjectionResult;
type: PinType;
},
): Feature[] => {
return bioEntites.map((bioEntity, index) =>
getBioEntitySingleFeature(bioEntity, {
pointToProjection,
type,
// pin's index number
value: index + ONE,
}),
);
};
import { bioEntitiesContentFixture } from '@/models/fixtures/bioEntityContentsFixture';
import { initialMapStateFixture } from '@/redux/map/map.fixtures';
import { PinType } from '@/types/pin';
import { UsePointToProjectionResult, usePointToProjection } from '@/utils/map/usePointToProjection';
import {
GetReduxWrapperUsingSliceReducer,
getReduxWrapperWithStore,
} from '@/utils/testing/getReduxWrapperWithStore';
import { renderHook } from '@testing-library/react';
import { Feature } from 'ol';
import Style from 'ol/style/Style';
import { getBioEntitiesFeatures } from './getBioEntitiesFeatures';
const getPointToProjection = (
wrapper: ReturnType<GetReduxWrapperUsingSliceReducer>['Wrapper'],
): UsePointToProjectionResult => {
const { result: usePointToProjectionHook } = renderHook(() => usePointToProjection(), {
wrapper,
});
return usePointToProjectionHook.current;
};
describe('getBioEntitiesFeatures - subUtil', () => {
const { Wrapper } = getReduxWrapperWithStore({
map: initialMapStateFixture,
});
const bioEntititesContent = bioEntitiesContentFixture;
const bioEntities = bioEntititesContent.map(({ bioEntity }) => bioEntity);
const pointToProjection = getPointToProjection(Wrapper);
const pinTypes: PinType[] = ['bioEntity', 'drugs', 'chemicals', 'mirna'];
it.each(pinTypes)('should return array of instances of Feature with Style type=%s', type => {
const result = getBioEntitiesFeatures(bioEntities, {
pointToProjection,
type,
});
result.forEach(resultElement => {
expect(resultElement).toBeInstanceOf(Feature);
expect(resultElement.getStyle()).toBeInstanceOf(Style);
});
});
});
import { PINS_COLORS } from '@/constants/canvas';
import { bioEntityContentFixture } from '@/models/fixtures/bioEntityContentsFixture';
import { initialMapStateFixture } from '@/redux/map/map.fixtures';
import { PinType } from '@/types/pin';
import { UsePointToProjectionResult, usePointToProjection } from '@/utils/map/usePointToProjection';
import {
GetReduxWrapperUsingSliceReducer,
getReduxWrapperWithStore,
} from '@/utils/testing/getReduxWrapperWithStore';
import { renderHook } from '@testing-library/react';
import { Feature } from 'ol';
import Style from 'ol/style/Style';
import { getBioEntitySingleFeature } from './getBioEntitySingleFeature';
import * as getPinStyle from './getPinStyle';
jest.mock('./getPinStyle', () => ({
__esModule: true,
...jest.requireActual('./getPinStyle'),
}));
const getPinStyleSpy = jest.spyOn(getPinStyle, 'getPinStyle');
const getPointToProjection = (
wrapper: ReturnType<GetReduxWrapperUsingSliceReducer>['Wrapper'],
): UsePointToProjectionResult => {
const { result: usePointToProjectionHook } = renderHook(() => usePointToProjection(), {
wrapper,
});
return usePointToProjectionHook.current;
};
describe('getBioEntitySingleFeature - subUtil', () => {
const { Wrapper } = getReduxWrapperWithStore({
map: initialMapStateFixture,
});
const { bioEntity } = bioEntityContentFixture;
const pointToProjection = getPointToProjection(Wrapper);
const value = 1448;
const pinTypes: PinType[] = ['bioEntity', 'drugs', 'chemicals', 'mirna'];
it.each(pinTypes)('should return instance of Feature with Style type=%s', type => {
const result = getBioEntitySingleFeature(bioEntity, {
pointToProjection,
type,
value,
});
const style = result.getStyle() as Style;
expect(result).toBeInstanceOf(Feature);
expect(style).toBeInstanceOf(Style);
});
it.each(pinTypes)('should run getPinStyle with valid args for type=%s', async type => {
getBioEntitySingleFeature(bioEntity, {
pointToProjection,
type,
value,
});
expect(getPinStyleSpy).toHaveBeenCalledWith({
color: PINS_COLORS[type],
value,
});
});
});
import { PINS_COLORS } from '@/constants/canvas';
import { BioEntity } from '@/types/models';
import { PinType } from '@/types/pin';
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import { Feature } from 'ol';
import { getPinFeature } from './getPinFeature';
import { getPinStyle } from './getPinStyle';
export const getBioEntitySingleFeature = (
bioEntity: BioEntity,
{
pointToProjection,
type,
value,
}: {
pointToProjection: UsePointToProjectionResult;
type: PinType;
value: number;
},
): Feature => {
const feature = getPinFeature(bioEntity, pointToProjection);
const style = getPinStyle({
color: PINS_COLORS[type],
value,
});
feature.setStyle(style);
return feature;
};
import { HALF } from '@/constants/dividers';
import { bioEntityContentFixture } from '@/models/fixtures/bioEntityContentsFixture';
import { initialMapStateFixture } from '@/redux/map/map.fixtures';
import { usePointToProjection } from '@/utils/map/usePointToProjection';
import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore';
import { renderHook } from '@testing-library/react';
import { Feature } from 'ol';
import { getPinFeature } from './getPinFeature';
describe('getPinFeature - subUtil', () => {
const { Wrapper } = getReduxWrapperWithStore({
map: initialMapStateFixture,
});
const { bioEntity } = bioEntityContentFixture;
const { result: usePointToProjectionHook } = renderHook(() => usePointToProjection(), {
wrapper: Wrapper,
});
const pointToProjection = usePointToProjectionHook.current;
const result = getPinFeature(bioEntity, pointToProjection);
it('should return instance of Feature', () => {
expect(result).toBeInstanceOf(Feature);
});
it('should return id as name', () => {
expect(result.get('name')).toBe(bioEntity.id);
});
it('should return point parsed with point to projection', () => {
const [x, y] = result.getGeometry()?.getExtent() || [];
const geometryPoint = pointToProjection({
x: bioEntity.x + bioEntity.width / HALF,
y: bioEntity.y + bioEntity.height / HALF,
});
expect([x, y]).toStrictEqual(geometryPoint);
});
});
import { HALF } from '@/constants/dividers';
import { BioEntity } from '@/types/models';
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import { Feature } from 'ol';
import { Point } from 'ol/geom';
export const getPinFeature = (
{ x, y, width, height, id }: BioEntity,
pointToProjection: UsePointToProjectionResult,
): Feature => {
const point = {
x: x + width / HALF,
y: y + height / HALF,
};
return new Feature({
geometry: new Point(pointToProjection(point)),
name: id,
});
};
import { PIN_SIZE } from '@/constants/canvas';
import { ZERO } from '@/constants/common';
import Style from 'ol/style/Style';
import { getPinStyle } from './getPinStyle';
describe('getPinStyle - subUtil', () => {
const input = {
color: '#000000',
value: 420,
};
const result = getPinStyle(input);
it('should return instance of Style', () => {
expect(result).toBeInstanceOf(Style);
});
it('should return image object with displacament of pin size height', () => {
const image = result.getImage();
expect(image.getDisplacement()).toStrictEqual([ZERO, PIN_SIZE.height]);
});
it('should return image of pin size', () => {
const image = result.getImage();
expect(image.getImageSize()).toStrictEqual([PIN_SIZE.width, PIN_SIZE.height]);
});
});
import { PIN_SIZE } from '@/constants/canvas';
import { ZERO } from '@/constants/common';
import Icon from 'ol/style/Icon';
import Style from 'ol/style/Style';
import { getCanvasIcon } from '../getCanvasIcon';
export const getPinStyle = ({ value, color }: { value: number; color: string }): Style =>
new Style({
image: new Icon({
displacement: [ZERO, PIN_SIZE.height],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
img: getCanvasIcon({
color,
value,
}),
}),
});
import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore';
import { renderHook } from '@testing-library/react';
import VectorLayer from 'ol/layer/Vector';
import { useOlMapPinsLayer } from './useOlMapPinsLayer';
describe('useOlMapPinsLayer - util', () => {
const { Wrapper } = getReduxWrapperWithStore();
it('should return VectorLayer', () => {
const { result } = renderHook(() => useOlMapPinsLayer(), {
wrapper: Wrapper,
});
expect(result.current).toBeInstanceOf(VectorLayer);
expect(result.current.getSourceState()).toBe('ready');
});
});
/* eslint-disable no-magic-numbers */
import { PIN_SIZE } from '@/constants/canvas';
import { allBioEntitesSelectorOfCurrentMap } from '@/redux/bioEntity/bioEntity.selectors';
import { BioEntity } from '@/types/models';
import { UsePointToProjectionResult, usePointToProjection } from '@/utils/map/usePointToProjection';
import { Feature } from 'ol';
import { Point as OlPoint } from 'ol/geom';
import { searchedBioEntitesSelectorOfCurrentMap } from '@/redux/bioEntity/bioEntity.selectors';
import { searchedChemicalsBioEntitesOfCurrentMapSelector } from '@/redux/chemicals/chemicals.selectors';
import { searchedDrugsBioEntitesOfCurrentMapSelector } from '@/redux/drugs/drugs.selectors';
import { usePointToProjection } from '@/utils/map/usePointToProjection';
import BaseLayer from 'ol/layer/Base';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import Icon from 'ol/style/Icon';
import Style from 'ol/style/Style';
import { useMemo } from 'react';
import { useSelector } from 'react-redux';
import { getCanvasIcon } from './getCanvasIcon';
const getPinFeature = (
{ x, y, width, height, name }: BioEntity,
pointToProjection: UsePointToProjectionResult,
): Feature => {
const point = {
x: x + width / 2,
y: y + height / 2,
};
return new Feature({
geometry: new OlPoint(pointToProjection(point)),
name,
});
};
const getPinStyle = ({ value, color }: { value: number; color: string }): Style =>
new Style({
image: new Icon({
displacement: [0, PIN_SIZE.height],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
img: getCanvasIcon({
color,
value,
}),
}),
});
import { getBioEntitiesFeatures } from './getBioEntitiesFeatures';
export const useOlMapPinsLayer = (): BaseLayer => {
const pointToProjection = usePointToProjection();
const bioEntites = useSelector(allBioEntitesSelectorOfCurrentMap);
const contentBioEntites = useSelector(searchedBioEntitesSelectorOfCurrentMap);
const chemicalsBioEntities = useSelector(searchedChemicalsBioEntitesOfCurrentMapSelector);
const drugsBioEntities = useSelector(searchedDrugsBioEntitesOfCurrentMapSelector);
const bioEntityFeatures = useMemo(
() =>
bioEntites.map(({ bioEntity }, index) => {
const feature = getPinFeature(bioEntity, pointToProjection);
const style = getPinStyle({
color: '#106AD7',
value: index + 1,
});
feature.setStyle(style);
return feature;
}),
[bioEntites, pointToProjection],
[
getBioEntitiesFeatures(contentBioEntites, { pointToProjection, type: 'bioEntity' }),
getBioEntitiesFeatures(chemicalsBioEntities, { pointToProjection, type: 'chemicals' }),
getBioEntitiesFeatures(drugsBioEntities, { pointToProjection, type: 'drugs' }),
].flat(),
[contentBioEntites, drugsBioEntities, chemicalsBioEntities, pointToProjection],
);
const vectorSource = useMemo(() => {
......
import { initialMapStateFixture } from '@/redux/map/map.fixtures';
import { LinePoint } from '@/types/reactions';
import { UsePointToProjectionResult, usePointToProjection } from '@/utils/map/usePointToProjection';
import {
GetReduxWrapperUsingSliceReducer,
getReduxWrapperWithStore,
} from '@/utils/testing/getReduxWrapperWithStore';
import { renderHook } from '@testing-library/react';
import { Feature } from 'ol';
import { LineString } from 'ol/geom';
import { getLineFeature } from './getLineFeature';
const getPointToProjection = (
wrapper: ReturnType<GetReduxWrapperUsingSliceReducer>['Wrapper'],
): UsePointToProjectionResult => {
const { result: usePointToProjectionHook } = renderHook(() => usePointToProjection(), {
wrapper,
});
return usePointToProjectionHook.current;
};
describe('getLineFeature', () => {
const { Wrapper } = getReduxWrapperWithStore({
map: initialMapStateFixture,
});
const pointToProjection = getPointToProjection(Wrapper);
const linePoints: LinePoint = [
{
x: 16,
y: 32,
},
{
x: 54,
y: 16,
},
];
it('should return valid Feature object', () => {
const result = getLineFeature(linePoints, pointToProjection);
expect(result).toBeInstanceOf(Feature);
});
it('should return valid Feature object with LineString geometry', () => {
const result = getLineFeature(linePoints, pointToProjection);
const geometry = result.getGeometry();
expect(geometry).toBeInstanceOf(LineString);
// eslint-disable-next-line no-magic-numbers
expect(geometry?.getExtent()).toStrictEqual([Infinity, -238107693, Infinity, -238107693]);
});
});
import { LinePoint } from '@/types/reactions';
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import { Feature } from 'ol';
import { LineString } from 'ol/geom';
export const getLineFeature = (
linePoints: LinePoint,
pointToProjection: UsePointToProjectionResult,
): Feature => {
const points = linePoints.map(pointToProjection);
return new Feature({
geometry: new LineString(points),
});
};