From c3b9e2fad3d31c1e50e39ffd198c10af11f58196 Mon Sep 17 00:00:00 2001
From: mateusz-winiarczyk <mateusz.winiarczyk@appunite.com>
Date: Fri, 8 Mar 2024 11:37:29 +0100
Subject: [PATCH] feat(pluginevents): add dispatching event onsearch on map
 click (MIN-296)

---
 .../handleSearchResultForRightClickAction.ts  |  2 +-
 .../mapSingleClick/handleAliasResults.test.ts |  5 +-
 .../mapSingleClick/handleAliasResults.ts      | 12 ++++-
 .../handleReactionResults.test.ts             |  5 +-
 .../mapSingleClick/handleReactionResults.ts   | 11 ++++-
 .../handleSearchResultAction.ts               |  2 +-
 src/redux/bioEntity/bioEntity.thunks.test.ts  | 49 ++++++++++++++++++-
 src/redux/bioEntity/bioEntity.thunks.ts       | 15 ++++--
 .../pluginsEventBus/pluginsEventBus.types.ts  | 11 ++++-
 9 files changed, 98 insertions(+), 14 deletions(-)

diff --git a/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleSearchResultForRightClickAction.ts b/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleSearchResultForRightClickAction.ts
index 858b57fb..29056a8f 100644
--- a/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleSearchResultForRightClickAction.ts
+++ b/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleSearchResultForRightClickAction.ts
@@ -20,5 +20,5 @@ export const handleSearchResultForRightClickAction = async ({
     REACTION: handleReactionResults,
   }[type];
 
-  await action(dispatch)(closestSearchResult);
+  await action(dispatch, closestSearchResult)(closestSearchResult);
 };
diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.test.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.test.ts
index 44ac11c9..1d8a0df8 100644
--- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.test.ts
+++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.test.ts
@@ -24,7 +24,10 @@ describe('handleAliasResults - util', () => {
     .reply(HttpStatusCode.Ok, bioEntityResponseFixture);
 
   beforeAll(async () => {
-    handleAliasResults(dispatch)(ELEMENT_SEARCH_RESULT_MOCK_ALIAS);
+    handleAliasResults(
+      dispatch,
+      ELEMENT_SEARCH_RESULT_MOCK_ALIAS,
+    )(ELEMENT_SEARCH_RESULT_MOCK_ALIAS);
   });
 
   it('should run openBioEntityDrawerById as first action', async () => {
diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.ts
index cd7aefe9..cd386b1c 100644
--- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.ts
+++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.ts
@@ -3,10 +3,11 @@ import { openBioEntityDrawerById } from '@/redux/drawer/drawer.slice';
 import { AppDispatch } from '@/redux/store';
 import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds';
 import { ElementSearchResult } from '@/types/models';
+import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus';
 
 /* prettier-ignore */
 export const handleAliasResults =
-  (dispatch: AppDispatch, hasFitBounds?: boolean, fitBoundsZoom?: number) =>
+  (dispatch: AppDispatch, closestSearchResult: ElementSearchResult, hasFitBounds?: boolean, fitBoundsZoom?: number) =>
     async ({ id }: ElementSearchResult): Promise<void> => {
 
       dispatch(openBioEntityDrawerById(id));
@@ -16,7 +17,14 @@ export const handleAliasResults =
           isPerfectMatch: true
         }),
       )
-        .unwrap().then(() => {
+        .unwrap().then((bioEntityContents) => {
+
+          PluginsEventBus.dispatchEvent('onSearch', {
+            type: 'bioEntity',
+            searchValues: [closestSearchResult],
+            results: [bioEntityContents],
+          });
+
           if (hasFitBounds) {
             searchFitBounds(fitBoundsZoom);
           }
diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.test.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.test.ts
index b514095b..020f0c64 100644
--- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.test.ts
+++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.test.ts
@@ -33,7 +33,10 @@ describe('handleReactionResults - util', () => {
     .reply(HttpStatusCode.Ok, reactionsFixture);
 
   beforeAll(async () => {
-    handleReactionResults(dispatch)(ELEMENT_SEARCH_RESULT_MOCK_REACTION);
+    handleReactionResults(
+      dispatch,
+      ELEMENT_SEARCH_RESULT_MOCK_REACTION,
+    )(ELEMENT_SEARCH_RESULT_MOCK_REACTION);
   });
 
   it('should run getReactionsByIds as first action', () => {
diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts
index d8282817..24332182 100644
--- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts
+++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts
@@ -6,10 +6,11 @@ import { AppDispatch } from '@/redux/store';
 import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds';
 import { ElementSearchResult, Reaction } from '@/types/models';
 import { PayloadAction } from '@reduxjs/toolkit';
+import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus';
 
 /* prettier-ignore */
 export const handleReactionResults =
-  (dispatch: AppDispatch, hasFitBounds?: boolean, fitBoundsZoom?: number) =>
+  (dispatch: AppDispatch, closestSearchResult: ElementSearchResult, hasFitBounds?: boolean, fitBoundsZoom?: number) =>
     async ({ id }: ElementSearchResult): Promise<void> => {
       const data = await dispatch(getReactionsByIds([id])) as PayloadAction<Reaction[] | undefined>;
       const payload = data?.payload;
@@ -30,7 +31,13 @@ export const handleReactionResults =
           searchQueries: bioEntitiesIds,
           isPerfectMatch: true },
         )
-      ).unwrap().then(() => {
+      ).unwrap().then((bioEntityContents) => {
+        PluginsEventBus.dispatchEvent('onSearch', {
+          type: 'bioEntity',
+          searchValues: [closestSearchResult],
+          results: [bioEntityContents],
+        });
+
         if (hasFitBounds) {
           searchFitBounds(fitBoundsZoom);
         }
diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction.ts
index c3663e41..39dea100 100644
--- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction.ts
+++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction.ts
@@ -25,7 +25,7 @@ export const handleSearchResultAction = async ({
     REACTION: handleReactionResults,
   }[type];
 
-  await action(dispatch, hasFitBounds, fitBoundsZoom)(closestSearchResult);
+  await action(dispatch, closestSearchResult, hasFitBounds, fitBoundsZoom)(closestSearchResult);
 
   if (type === 'ALIAS') {
     PluginsEventBus.dispatchEvent('onBioEntityClick', closestSearchResult);
diff --git a/src/redux/bioEntity/bioEntity.thunks.test.ts b/src/redux/bioEntity/bioEntity.thunks.test.ts
index b45d1941..9757ab4b 100644
--- a/src/redux/bioEntity/bioEntity.thunks.test.ts
+++ b/src/redux/bioEntity/bioEntity.thunks.test.ts
@@ -7,7 +7,7 @@ import {
 import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse';
 import { HttpStatusCode } from 'axios';
 import contentsReducer from './bioEntity.slice';
-import { getBioEntity } from './bioEntity.thunks';
+import { getBioEntity, getMultiBioEntity } from './bioEntity.thunks';
 import { BioEntityContentsState } from './bioEntity.types';
 
 const mockedAxiosClient = mockNetworkNewAPIResponse();
@@ -56,4 +56,51 @@ describe('bioEntityContents thunks', () => {
       expect(payload).toEqual(undefined);
     });
   });
+  describe('getMultiBioEntity', () => {
+    it('should return transformed bioEntityContent array', async () => {
+      mockedAxiosClient
+        .onGet(
+          apiPath.getBioEntityContentsStringWithQuery({
+            searchQuery: SEARCH_QUERY,
+            isPerfectMatch: false,
+          }),
+        )
+        .reply(HttpStatusCode.Ok, bioEntityResponseFixture);
+
+      const data = await store
+        .dispatch(
+          getMultiBioEntity({
+            searchQueries: [SEARCH_QUERY],
+            isPerfectMatch: false,
+          }),
+        )
+        .unwrap();
+
+      expect(data).toEqual(bioEntityResponseFixture.content);
+    });
+    it('should combine all returned bioEntityContent arrays and return array with all provided bioEntityContent elements', async () => {
+      mockedAxiosClient
+        .onGet(
+          apiPath.getBioEntityContentsStringWithQuery({
+            searchQuery: SEARCH_QUERY,
+            isPerfectMatch: false,
+          }),
+        )
+        .reply(HttpStatusCode.Ok, bioEntityResponseFixture);
+
+      const data = await store
+        .dispatch(
+          getMultiBioEntity({
+            searchQueries: [SEARCH_QUERY, SEARCH_QUERY],
+            isPerfectMatch: false,
+          }),
+        )
+        .unwrap();
+
+      expect(data).toEqual([
+        ...bioEntityResponseFixture.content,
+        ...bioEntityResponseFixture.content,
+      ]);
+    });
+  });
 });
diff --git a/src/redux/bioEntity/bioEntity.thunks.ts b/src/redux/bioEntity/bioEntity.thunks.ts
index e1b59d1e..32185755 100644
--- a/src/redux/bioEntity/bioEntity.thunks.ts
+++ b/src/redux/bioEntity/bioEntity.thunks.ts
@@ -1,5 +1,5 @@
 import { PerfectMultiSearchParams, PerfectSearchParams } from '@/types/search';
-import { createAsyncThunk } from '@reduxjs/toolkit';
+import { PayloadAction, createAsyncThunk } from '@reduxjs/toolkit';
 import { bioEntityResponseSchema } from '@/models/bioEntityResponseSchema';
 import { apiPath } from '@/redux/apiPath';
 import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance';
@@ -25,17 +25,26 @@ export const getBioEntity = createAsyncThunk(
 );
 
 type GetMultiBioEntityProps = PerfectMultiSearchParams;
+type GetMultiBioEntityActions = PayloadAction<BioEntityContent[] | undefined>[];
 
 export const getMultiBioEntity = createAsyncThunk(
   'project/getMultiBioEntity',
   async (
     { searchQueries, isPerfectMatch }: GetMultiBioEntityProps,
     { dispatch },
-  ): Promise<void> => {
+  ): Promise<BioEntityContent[]> => {
     const asyncGetBioEntityFunctions = searchQueries.map(searchQuery =>
       dispatch(getBioEntity({ searchQuery, isPerfectMatch })),
     );
 
-    await Promise.all(asyncGetBioEntityFunctions);
+    const bioEntityContentsActions = (await Promise.all(
+      asyncGetBioEntityFunctions,
+    )) as GetMultiBioEntityActions;
+
+    const bioEntityContents = bioEntityContentsActions
+      .map(bioEntityContentsAction => bioEntityContentsAction.payload || [])
+      .flat();
+
+    return bioEntityContents;
   },
 );
diff --git a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts
index 7679bb0a..2122a199 100644
--- a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts
+++ b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts
@@ -1,4 +1,11 @@
-import { BioEntityContent, Chemical, CreatedOverlay, Drug, MapOverlay } from '@/types/models';
+import {
+  BioEntityContent,
+  Chemical,
+  CreatedOverlay,
+  Drug,
+  ElementSearchResult,
+  MapOverlay,
+} from '@/types/models';
 import { dispatchEvent } from './pluginsEventBus';
 
 export type BackgroundEvents = 'onBackgroundOverlayChange';
@@ -36,7 +43,7 @@ export type ClickedBioEntity = {
 
 export type SearchDataBioEntity = {
   type: 'bioEntity';
-  searchValues: string[];
+  searchValues: string[] | ElementSearchResult[];
   results: BioEntityContent[][];
 };
 
-- 
GitLab