Skip to content
Snippets Groups Projects
Commit 459df684 authored by Adrian Orłów's avatar Adrian Orłów :fire:
Browse files

Merge branch 'MIN-215-display-overlays-for-reactions' into 'development'

feat: add display reaction overlay (MIN-215)

Closes MIN-215

See merge request !110
parents 8f926bf4 fa7817a6
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...,!110feat: add display reaction overlay (MIN-215)
Pipeline #85062 passed
Showing
with 508 additions and 23 deletions
import { LINE_WIDTH } from '@/constants/canvas';
import { initialMapStateFixture } from '@/redux/map/map.fixtures';
import { LinePoint } from '@/types/reactions';
import { usePointToProjection } from '@/utils/map/usePointToProjection';
import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore';
import { renderHook } from '@testing-library/react';
import { Feature } from 'ol';
import { Geometry } from 'ol/geom';
import { createOverlayLineFeature } from './createOverlayLineFeature';
/* eslint-disable no-magic-numbers */
const CASES: [LinePoint, number[]][] = [
[
[
{ x: 0, y: 0 },
{ x: 0, y: 0 },
],
[0, 0, 0, 0],
],
[
[
{ x: 0, y: 0 },
{ x: 100, y: 100 },
],
[0, -238107693, Infinity, 0],
],
[
[
{ x: 100, y: 100 },
{ x: 0, y: 0 },
],
[0, -238107693, Infinity, 0],
],
[
[
{ x: 100, y: 0 },
{ x: 0, y: 100 },
],
[0, 0, 0, 0],
],
[
[
{ x: -50, y: 0 },
{ x: 0, y: -50 },
],
[0, 0, 0, 0],
],
];
const COLOR = '#FFB3B3cc';
const getFeature = (linePoint: LinePoint): Feature<Geometry> => {
const { Wrapper } = getReduxWrapperWithStore({
map: initialMapStateFixture,
});
const {
result: { current: pointToProjection },
} = renderHook(() => usePointToProjection(), {
wrapper: Wrapper,
});
return createOverlayLineFeature(linePoint, { pointToProjection, color: COLOR });
};
describe('createOverlayLineFeature - util', () => {
it.each(CASES)('should return Feature instance', linePoint => {
const feature = getFeature(linePoint);
expect(feature).toBeInstanceOf(Feature);
});
it.each(CASES)('should return Feature instance with valid style and stroke', linePoint => {
const feature = getFeature(linePoint);
const style = feature.getStyle();
expect(style).toMatchObject({
fill_: { color_: COLOR },
stroke_: {
color_: COLOR,
width_: LINE_WIDTH,
},
});
});
it.each(CASES)('should return Feature instance with valid geometry', (linePoint, extent) => {
const feature = getFeature(linePoint);
const geometry = feature.getGeometry();
expect(geometry?.getExtent()).toEqual(extent);
});
});
import { LinePoint } from '@/types/reactions';
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import { Feature } from 'ol';
import { SimpleGeometry } from 'ol/geom';
import { getLineFeature } from '../reactionsLayer/getLineFeature';
import { getOverlayLineFeatureStyle } from './getOverlayLineFeatureStyle';
interface Options {
color: string;
pointToProjection: UsePointToProjectionResult;
}
export const createOverlayLineFeature = (
points: LinePoint,
{ color, pointToProjection }: Options,
): Feature<SimpleGeometry> => {
const feature = getLineFeature(points, pointToProjection);
feature.setStyle(getOverlayLineFeatureStyle(color));
return feature;
};
import { LINE_WIDTH } from '@/constants/canvas';
import { Fill, Stroke, Style } from 'ol/style';
import { getOverlayLineFeatureStyle } from './getOverlayLineFeatureStyle';
const COLORS = ['#000000', '#FFFFFF', '#F5F5F5', '#C0C0C0', '#C0C0C0aa', '#C0C0C0bb'];
describe('getOverlayLineFeatureStyle - util', () => {
it.each(COLORS)('should return Style object', color => {
const result = getOverlayLineFeatureStyle(color);
expect(result).toBeInstanceOf(Style);
});
it.each(COLORS)('should set valid color values for Fill', color => {
const result = getOverlayLineFeatureStyle(color);
const fill = result.getFill();
expect(fill).toBeInstanceOf(Fill);
expect(fill?.getColor()).toBe(color);
});
it.each(COLORS)('should set valid color values for Fill', color => {
const result = getOverlayLineFeatureStyle(color);
const stroke = result.getStroke();
expect(stroke).toBeInstanceOf(Stroke);
expect(stroke?.getColor()).toBe(color);
expect(stroke?.getWidth()).toBe(LINE_WIDTH);
});
});
import { LINE_WIDTH } from '@/constants/canvas';
import { Fill, Stroke, Style } from 'ol/style';
export const getOverlayLineFeatureStyle = (color: string): Style =>
new Style({ fill: new Fill({ color }), stroke: new Stroke({ color, width: LINE_WIDTH }) });
import { renderHook } from '@testing-library/react';
import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore';
import { CONFIGURATION_INITIAL_STORE_MOCKS } from '@/redux/configuration/configuration.mock'; import { CONFIGURATION_INITIAL_STORE_MOCKS } from '@/redux/configuration/configuration.mock';
import { OverlayBioEntityRender } from '@/types/OLrendering'; import { OverlayBioEntityRender } from '@/types/OLrendering';
import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore';
import { renderHook } from '@testing-library/react';
import { useGetOverlayColor } from './useGetOverlayColor'; import { useGetOverlayColor } from './useGetOverlayColor';
describe('useOverlayFeatures - hook', () => { describe('useOverlayFeatures - hook', () => {
...@@ -20,6 +20,7 @@ describe('useOverlayFeatures - hook', () => { ...@@ -20,6 +20,7 @@ describe('useOverlayFeatures - hook', () => {
describe('getOverlayBioEntityColorByAvailableProperties - function', () => { describe('getOverlayBioEntityColorByAvailableProperties - function', () => {
const ENTITY: OverlayBioEntityRender = { const ENTITY: OverlayBioEntityRender = {
type: 'rectangle',
id: 0, id: 0,
modelId: 0, modelId: 0,
x1: 0, x1: 0,
......
/* eslint-disable no-magic-numbers */ /* eslint-disable no-magic-numbers */
import { renderHook } from '@testing-library/react';
import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore';
import { CONFIGURATION_INITIAL_STORE_MOCKS } from '@/redux/configuration/configuration.mock'; import { CONFIGURATION_INITIAL_STORE_MOCKS } from '@/redux/configuration/configuration.mock';
import { OVERLAYS_PUBLIC_FETCHED_STATE_MOCK } from '@/redux/overlays/overlays.mock';
import { mapStateWithCurrentlySelectedMainMapFixture } from '@/redux/map/map.fixtures'; import { mapStateWithCurrentlySelectedMainMapFixture } from '@/redux/map/map.fixtures';
import { MODELS_DATA_MOCK_WITH_MAIN_MAP } from '@/redux/models/models.mock'; import { MODELS_DATA_MOCK_WITH_MAIN_MAP } from '@/redux/models/models.mock';
import { MOCKED_OVERLAY_BIO_ENTITY_RENDER } from '@/redux/overlayBioEntity/overlayBioEntity.mock'; import { MOCKED_OVERLAY_BIO_ENTITY_RENDER } from '@/redux/overlayBioEntity/overlayBioEntity.mock';
import { OVERLAYS_PUBLIC_FETCHED_STATE_MOCK } from '@/redux/overlays/overlays.mock';
import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore';
import { renderHook } from '@testing-library/react';
import { useOverlayFeatures } from './useOverlayFeatures'; import { useOverlayFeatures } from './useOverlayFeatures';
/** /**
...@@ -52,7 +52,9 @@ describe('useOverlayFeatures', () => { ...@@ -52,7 +52,9 @@ describe('useOverlayFeatures', () => {
wrapper: Wrapper, wrapper: Wrapper,
}); });
expect(features).toHaveLength(6); expect(features).toHaveLength(10);
// type: rectangle
expect(features[0].getGeometry()?.getCoordinates()).toEqual([ expect(features[0].getGeometry()?.getCoordinates()).toEqual([
[ [
[-13149141, 18867005], [-13149141, 18867005],
...@@ -65,5 +67,19 @@ describe('useOverlayFeatures', () => { ...@@ -65,5 +67,19 @@ describe('useOverlayFeatures', () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
expect(features[0].getStyle().getFill().getColor()).toBe('#FFFFFFcc'); expect(features[0].getStyle().getFill().getColor()).toBe('#FFFFFFcc');
// type: line
expect(features[7].getGeometry()?.getCoordinates()).toEqual([
[
[-13149141, 18867005],
[-13149141, 18881970],
[-13141659, 18881970],
[-13141659, 18867005],
[-13149141, 18867005],
],
]);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(features[7].getStyle().getFill().getColor()).toBe('#ff0000cc');
}); });
}); });
import { useMemo } from 'react';
import { usePointToProjection } from '@/utils/map/usePointToProjection';
import type Feature from 'ol/Feature';
import type Polygon from 'ol/geom/Polygon';
import { ZERO } from '@/constants/common'; import { ZERO } from '@/constants/common';
import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { useAppSelector } from '@/redux/hooks/useAppSelector';
import { import {
getOverlayOrderSelector, getOverlayOrderSelector,
overlayBioEntitiesForCurrentModelSelector, overlayBioEntitiesForCurrentModelSelector,
} from '@/redux/overlayBioEntity/overlayBioEntity.selector'; } from '@/redux/overlayBioEntity/overlayBioEntity.selector';
import { LinePoint } from '@/types/reactions';
import { usePointToProjection } from '@/utils/map/usePointToProjection';
import type Feature from 'ol/Feature';
import { SimpleGeometry } from 'ol/geom';
import type Polygon from 'ol/geom/Polygon';
import { useMemo } from 'react';
import { createOverlayGeometryFeature } from './createOverlayGeometryFeature'; import { createOverlayGeometryFeature } from './createOverlayGeometryFeature';
import { createOverlayLineFeature } from './createOverlayLineFeature';
import { getPolygonLatitudeCoordinates } from './getPolygonLatitudeCoordinates'; import { getPolygonLatitudeCoordinates } from './getPolygonLatitudeCoordinates';
import { useGetOverlayColor } from './useGetOverlayColor'; import { useGetOverlayColor } from './useGetOverlayColor';
export const useOverlayFeatures = (): Feature<Polygon>[] => { export const useOverlayFeatures = (): Feature<Polygon>[] | Feature<SimpleGeometry>[] => {
const pointToProjection = usePointToProjection(); const pointToProjection = usePointToProjection();
const { getOverlayBioEntityColorByAvailableProperties } = useGetOverlayColor(); const { getOverlayBioEntityColorByAvailableProperties } = useGetOverlayColor();
const overlaysOrder = useAppSelector(getOverlayOrderSelector); const overlaysOrder = useAppSelector(getOverlayOrderSelector);
...@@ -34,12 +37,27 @@ export const useOverlayFeatures = (): Feature<Polygon>[] => { ...@@ -34,12 +37,27 @@ export const useOverlayFeatures = (): Feature<Polygon>[] => {
overlaysOrder.find(({ id }) => id === entity.overlayId)?.index || ZERO, overlaysOrder.find(({ id }) => id === entity.overlayId)?.index || ZERO,
}); });
return createOverlayGeometryFeature( const color = getOverlayBioEntityColorByAvailableProperties(entity);
if (entity.type === 'rectangle') {
return createOverlayGeometryFeature(
[
...pointToProjection({ x: xMin, y: entity.y1 }),
...pointToProjection({ x: xMax, y: entity.y2 }),
],
color,
);
}
return createOverlayLineFeature(
[ [
...pointToProjection({ x: xMin, y: entity.y1 }), { x: entity.x1, y: entity.y1 },
...pointToProjection({ x: xMax, y: entity.y2 }), { x: entity.x2, y: entity.y2 },
], ] as LinePoint,
getOverlayBioEntityColorByAvailableProperties(entity), {
color,
pointToProjection,
},
); );
}), }),
[overlaysOrder, bioEntities, pointToProjection, getOverlayBioEntityColorByAvailableProperties], [overlaysOrder, bioEntities, pointToProjection, getOverlayBioEntityColorByAvailableProperties],
......
import { LinePoint } from '@/types/reactions'; import { LinePoint } from '@/types/reactions';
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import { Feature } from 'ol'; import { Feature } from 'ol';
import { LineString } from 'ol/geom'; import { LineString, SimpleGeometry } from 'ol/geom';
export const getLineFeature = ( export const getLineFeature = (
linePoints: LinePoint, linePoints: LinePoint,
pointToProjection: UsePointToProjectionResult, pointToProjection: UsePointToProjectionResult,
): Feature => { ): Feature<SimpleGeometry> => {
const points = linePoints.map(pointToProjection); const points = linePoints.map(pointToProjection);
return new Feature({ return new Feature({
......
...@@ -2,9 +2,21 @@ import { ZOD_SEED } from '@/constants'; ...@@ -2,9 +2,21 @@ import { ZOD_SEED } from '@/constants';
import { z } from 'zod'; import { z } from 'zod';
// eslint-disable-next-line import/no-extraneous-dependencies // eslint-disable-next-line import/no-extraneous-dependencies
import { createFixture } from 'zod-fixture'; import { createFixture } from 'zod-fixture';
import { overlayBioEntitySchema } from '../overlayBioEntitySchema'; import {
overlayBioEntitySchema,
overlayElementWithBioEntitySchema,
overlayElementWithReactionSchema,
} from '../overlayBioEntitySchema';
export const overlayBioEntityFixture = createFixture(z.array(overlayBioEntitySchema), { export const overlayBioEntityFixture = createFixture(z.array(overlayBioEntitySchema), {
seed: ZOD_SEED, seed: ZOD_SEED,
array: { min: 3, max: 3 }, array: { min: 3, max: 3 },
}); });
export const overlayElementWithReactionFixture = createFixture(overlayElementWithReactionSchema, {
seed: ZOD_SEED,
});
export const overlayElementWithBioEntityFixture = createFixture(overlayElementWithBioEntitySchema, {
seed: ZOD_SEED,
});
import { z } from 'zod'; import { z } from 'zod';
import { overlayLeftBioEntitySchema } from './overlayLeftBioEntitySchema'; import { overlayLeftBioEntitySchema } from './overlayLeftBioEntitySchema';
import { overlayLeftReactionSchema } from './overlayLeftReactionSchema';
import { overlayRightBioEntitySchema } from './overlayRightBioEntitySchema'; import { overlayRightBioEntitySchema } from './overlayRightBioEntitySchema';
export const overlayBioEntitySchema = z.object({ export const overlayElementWithBioEntitySchema = z.object({
left: overlayLeftBioEntitySchema, left: overlayLeftBioEntitySchema,
right: overlayRightBioEntitySchema, right: overlayRightBioEntitySchema,
}); });
export const overlayElementWithReactionSchema = z.object({
left: overlayLeftReactionSchema,
right: overlayRightBioEntitySchema,
});
export const overlayBioEntitySchema = z.union([
overlayElementWithBioEntitySchema,
overlayElementWithReactionSchema,
]);
import { z } from 'zod';
import { lineSchema } from './lineSchema';
import { reactionProduct } from './reactionProduct';
import { referenceSchema } from './referenceSchema';
export const overlayLeftReactionSchema = z.object({
id: z.number(),
notes: z.string(),
idReaction: z.string(),
name: z.string(),
reversible: z.boolean(),
symbol: z.null(),
abbreviation: z.null(),
formula: z.null(),
mechanicalConfidenceScore: z.null(),
lowerBound: z.null(),
upperBound: z.null(),
subsystem: z.null(),
geneProteinReaction: z.null(),
visibilityLevel: z.string(),
z: z.number(),
synonyms: z.array(z.unknown()),
model: z.number(),
kinetics: z.null(),
line: lineSchema,
processCoordinates: z.null(),
stringType: z.string(),
modifiers: z.array(reactionProduct),
reactants: z.array(reactionProduct),
products: z.array(reactionProduct),
elementId: z.string(),
operators: z.array(z.unknown()),
references: z.array(referenceSchema),
});
import { z } from 'zod';
import { lineSchema } from './lineSchema';
export const reactionProduct = z.object({
id: z.number(),
line: lineSchema,
stoichiometry: z.null(),
element: z.number(),
});
...@@ -8,6 +8,7 @@ export const OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK: OverlaysBioEntityState = { ...@@ -8,6 +8,7 @@ export const OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK: OverlaysBioEntityState = {
export const MOCKED_OVERLAY_BIO_ENTITY_RENDER: OverlayBioEntityRender[] = [ export const MOCKED_OVERLAY_BIO_ENTITY_RENDER: OverlayBioEntityRender[] = [
{ {
type: 'rectangle',
id: 1, id: 1,
modelId: 52, modelId: 52,
width: 30, width: 30,
...@@ -21,6 +22,7 @@ export const MOCKED_OVERLAY_BIO_ENTITY_RENDER: OverlayBioEntityRender[] = [ ...@@ -21,6 +22,7 @@ export const MOCKED_OVERLAY_BIO_ENTITY_RENDER: OverlayBioEntityRender[] = [
color: null, color: null,
}, },
{ {
type: 'rectangle',
id: 2, id: 2,
modelId: 52, modelId: 52,
width: 30, width: 30,
...@@ -34,6 +36,7 @@ export const MOCKED_OVERLAY_BIO_ENTITY_RENDER: OverlayBioEntityRender[] = [ ...@@ -34,6 +36,7 @@ export const MOCKED_OVERLAY_BIO_ENTITY_RENDER: OverlayBioEntityRender[] = [
color: null, color: null,
}, },
{ {
type: 'rectangle',
id: 3, id: 3,
modelId: 52, modelId: 52,
width: 40, width: 40,
...@@ -46,4 +49,32 @@ export const MOCKED_OVERLAY_BIO_ENTITY_RENDER: OverlayBioEntityRender[] = [ ...@@ -46,4 +49,32 @@ export const MOCKED_OVERLAY_BIO_ENTITY_RENDER: OverlayBioEntityRender[] = [
value: null, value: null,
color: { rgb: -65536, alpha: 0 }, color: { rgb: -65536, alpha: 0 },
}, },
{
type: 'line',
id: 66143,
modelId: 52,
x1: 4462.61826820353,
x2: 4571.99387254902,
y1: 7105.89040426431,
y2: 6979.823529411765,
width: 109.3756043454905,
height: 126.06687485254497,
value: null,
overlayId: 20,
color: null,
},
{
type: 'line',
id: 66144,
modelId: 52,
x1: 4454.850442288663,
x2: 4463.773636826477,
y1: 7068.434324866321,
y2: 7112.188429617157,
width: 8.923194537814197,
height: 43.75410475083663,
value: null,
overlayId: 20,
color: null,
},
]; ];
...@@ -2,6 +2,8 @@ import { ONE } from '@/constants/common'; ...@@ -2,6 +2,8 @@ import { ONE } from '@/constants/common';
import { overlayBioEntitySchema } from '@/models/overlayBioEntitySchema'; import { overlayBioEntitySchema } from '@/models/overlayBioEntitySchema';
import { OverlayBioEntityRender } from '@/types/OLrendering'; import { OverlayBioEntityRender } from '@/types/OLrendering';
import { OverlayBioEntity } from '@/types/models'; import { OverlayBioEntity } from '@/types/models';
import { getOverlayReactionCoordsFromLine } from '@/utils/overlays/getOverlayReactionCoords';
import { isBioEntity, isReaction } from '@/utils/overlays/overlaysElementsTypeGuards';
import { z } from 'zod'; import { z } from 'zod';
export const parseOverlayBioEntityToOlRenderingFormat = ( export const parseOverlayBioEntityToOlRenderingFormat = (
...@@ -9,8 +11,16 @@ export const parseOverlayBioEntityToOlRenderingFormat = ( ...@@ -9,8 +11,16 @@ export const parseOverlayBioEntityToOlRenderingFormat = (
overlayId: number, overlayId: number,
): OverlayBioEntityRender[] => ): OverlayBioEntityRender[] =>
data.reduce((acc: OverlayBioEntityRender[], entity: OverlayBioEntity) => { data.reduce((acc: OverlayBioEntityRender[], entity: OverlayBioEntity) => {
if (entity.left.x && entity.left.y) { /**
* The're two types of entities - bioentity and reaction
* Bioentity comes with the single only element
* And reaction comes with many different lines that needs to be merged together
* Every reaction line is a different entity after reduce
*/
if (isBioEntity(entity)) {
acc.push({ acc.push({
type: 'rectangle',
id: entity.left.id, id: entity.left.id,
modelId: entity.left.model, modelId: entity.left.model,
x1: entity.left.x, x1: entity.left.x,
...@@ -24,6 +34,31 @@ export const parseOverlayBioEntityToOlRenderingFormat = ( ...@@ -24,6 +34,31 @@ export const parseOverlayBioEntityToOlRenderingFormat = (
color: entity.right.color, color: entity.right.color,
}); });
} }
if (isReaction(entity)) {
const { products, reactants, modifiers } = entity.left;
const lines = [products, reactants, modifiers].flat().map(element => element.line);
const coords = lines.map(getOverlayReactionCoordsFromLine).flat();
const elements = coords.map(
({ x1, x2, y1, y2, id, width, height }): OverlayBioEntityRender => ({
type: 'line',
id,
modelId: entity.left.model,
x1,
x2,
y1,
y2,
width,
height: Math.abs(height),
value: entity.right.value,
overlayId,
color: entity.right.color,
}),
);
acc.push(...elements);
}
return acc; return acc;
}, []); }, []);
......
import { Color } from './models'; import { Color } from './models';
export type OverlayBioEntityRenderType = 'line' | 'rectangle';
export type OverlayBioEntityRender = { export type OverlayBioEntityRender = {
id: number; id: number;
modelId: number; modelId: number;
...@@ -16,4 +18,15 @@ export type OverlayBioEntityRender = { ...@@ -16,4 +18,15 @@ export type OverlayBioEntityRender = {
value: number | null; value: number | null;
overlayId: number; overlayId: number;
color: Color | null; color: Color | null;
type: OverlayBioEntityRenderType;
}; };
export interface OverlayReactionCoords {
x1: number;
x2: number;
y1: number;
y2: number;
id: number;
height: number;
width: number;
}
...@@ -12,7 +12,8 @@ import { configurationSchema, formatSchema, miriamTypesSchema } from '@/models/c ...@@ -12,7 +12,8 @@ import { configurationSchema, formatSchema, miriamTypesSchema } from '@/models/c
import { disease } from '@/models/disease'; import { disease } from '@/models/disease';
import { drugSchema } from '@/models/drugSchema'; import { drugSchema } from '@/models/drugSchema';
import { elementSearchResult, elementSearchResultType } from '@/models/elementSearchResult'; import { elementSearchResult, elementSearchResultType } from '@/models/elementSearchResult';
import { exportNetworkchema, exportElementsSchema } from '@/models/exportSchema'; import { exportElementsSchema, exportNetworkchema } from '@/models/exportSchema';
import { lineSchema } from '@/models/lineSchema';
import { loginSchema } from '@/models/loginSchema'; import { loginSchema } from '@/models/loginSchema';
import { mapBackground } from '@/models/mapBackground'; import { mapBackground } from '@/models/mapBackground';
import { import {
...@@ -23,7 +24,13 @@ import { ...@@ -23,7 +24,13 @@ import {
} from '@/models/mapOverlay'; } from '@/models/mapOverlay';
import { mapModelSchema } from '@/models/modelSchema'; import { mapModelSchema } from '@/models/modelSchema';
import { organism } from '@/models/organism'; import { organism } from '@/models/organism';
import { overlayBioEntitySchema } from '@/models/overlayBioEntitySchema'; import {
overlayBioEntitySchema,
overlayElementWithBioEntitySchema,
overlayElementWithReactionSchema,
} from '@/models/overlayBioEntitySchema';
import { overlayLeftBioEntitySchema } from '@/models/overlayLeftBioEntitySchema';
import { overlayLeftReactionSchema } from '@/models/overlayLeftReactionSchema';
import { import {
overviewImageLink, overviewImageLink,
overviewImageLinkImage, overviewImageLinkImage,
...@@ -67,6 +74,11 @@ export type Configuration = z.infer<typeof configurationSchema>; ...@@ -67,6 +74,11 @@ export type Configuration = z.infer<typeof configurationSchema>;
export type ConfigurationFormatSchema = z.infer<typeof formatSchema>; export type ConfigurationFormatSchema = z.infer<typeof formatSchema>;
export type ConfigurationMiramiTypes = z.infer<typeof miriamTypesSchema>; export type ConfigurationMiramiTypes = z.infer<typeof miriamTypesSchema>;
export type OverlayBioEntity = z.infer<typeof overlayBioEntitySchema>; export type OverlayBioEntity = z.infer<typeof overlayBioEntitySchema>;
export type OverlayElementWithReaction = z.infer<typeof overlayElementWithReactionSchema>;
export type OverlayElementWithBioEntity = z.infer<typeof overlayElementWithBioEntitySchema>;
export type OverlayLeftBioEntity = z.infer<typeof overlayLeftBioEntitySchema>;
export type OverlayLeftReaction = z.infer<typeof overlayLeftReactionSchema>;
export type Line = z.infer<typeof lineSchema>;
export type CreatedOverlayFile = z.infer<typeof createdOverlayFileSchema>; export type CreatedOverlayFile = z.infer<typeof createdOverlayFileSchema>;
export type UploadedOverlayFileContent = z.infer<typeof uploadedOverlayFileContentSchema>; export type UploadedOverlayFileContent = z.infer<typeof uploadedOverlayFileContentSchema>;
export type CreatedOverlay = z.infer<typeof createdOverlaySchema>; export type CreatedOverlay = z.infer<typeof createdOverlaySchema>;
......
import { OverlayReactionCoords } from '@/types/OLrendering';
import { Line } from '@/types/models';
import { getOverlayReactionCoordsFromLine } from './getOverlayReactionCoords';
const LINE_DATA_BASE: Line = {
id: 66141,
width: 1,
color: {
alpha: 255,
rgb: -16777216,
},
z: 0,
segments: [
{
x1: 4457.375604345491,
y1: 7111.933125147456,
x2: 4462.61826820353,
y2: 7105.89040426431,
},
],
startArrow: {
arrowType: 'NONE',
angle: 2.748893571891069,
lineType: 'SOLID',
length: 15,
},
endArrow: {
arrowType: 'NONE',
angle: 2.748893571891069,
lineType: 'SOLID',
length: 15,
},
lineType: 'SOLID',
};
describe('getOverlayReactionCoords - util', () => {
const cases: [Line, OverlayReactionCoords[]][] = [
[
{
...LINE_DATA_BASE,
segments: [
{
x1: 10,
y1: 10,
x2: 100,
y2: 100,
},
],
},
[{ height: -90, id: 66141, width: 90, x1: 10, x2: 100, y1: 10, y2: 100 }],
],
[
{
...LINE_DATA_BASE,
segments: [
{
x1: 10,
y1: 10,
x2: 2000,
y2: 0,
},
],
},
[{ height: 10, id: 66141, width: 1990, x1: 10, x2: 2000, y1: 10, y2: 0 }],
],
[
{
...LINE_DATA_BASE,
segments: [
{
x1: 0,
y1: 0,
x2: 0,
y2: 0,
},
],
},
[{ height: 0, id: 66141, width: 0, x1: 0, x2: 0, y1: 0, y2: 0 }],
],
];
it.each(cases)('should return valid result', (line, result) => {
expect(getOverlayReactionCoordsFromLine(line)).toStrictEqual(result);
});
});
import { OverlayReactionCoords } from '@/types/OLrendering';
import { Line } from '@/types/models';
export const getOverlayReactionCoordsFromLine = (line: Line): OverlayReactionCoords[] =>
line.segments.map(segment => {
const { x1, y1, x2, y2 } = segment;
return {
...segment,
id: line.id,
width: x2 - x1,
height: y1 - y2,
};
});
import {
overlayElementWithBioEntityFixture,
overlayElementWithReactionFixture,
} from '@/models/fixtures/overlayBioEntityFixture';
import { isBioEntity, isReaction } from './overlaysElementsTypeGuards';
describe('overlaysElementsTypeGruards - utils', () => {
describe('isReaction', () => {
describe('when is reaction', () => {
it('should return true', () => {
expect(isReaction(overlayElementWithReactionFixture)).toBe(true);
});
});
describe('when is bioentity', () => {
it('should return false', () => {
expect(isReaction(overlayElementWithBioEntityFixture)).toBe(false);
});
});
});
describe('isBioEntity', () => {
describe('when is reaction', () => {
it('should return false', () => {
expect(isBioEntity(overlayElementWithReactionFixture)).toBe(false);
});
});
describe('when is bioentity', () => {
it('should return true', () => {
expect(isBioEntity(overlayElementWithBioEntityFixture)).toBe(true);
});
});
});
});
import {
OverlayBioEntity,
OverlayElementWithBioEntity,
OverlayElementWithReaction,
OverlayLeftBioEntity,
OverlayLeftReaction,
} from '@/types/models';
export const isReaction = (e: OverlayBioEntity): e is OverlayElementWithReaction =>
(e.left as OverlayLeftReaction).line !== undefined;
export const isBioEntity = (e: OverlayBioEntity): e is OverlayElementWithBioEntity =>
(e.left as OverlayLeftBioEntity).x !== undefined &&
(e.left as OverlayLeftBioEntity).y !== undefined;
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