diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleFeaturesClick.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleFeaturesClick.ts index 752d65715eb7ec29fc9bb913ac8a12fe72d32a4b..fd48e330b1aee1e0fe77abaaf54cf6046381a9b9 100644 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleFeaturesClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleFeaturesClick.ts @@ -5,7 +5,7 @@ import { AppDispatch } from '@/redux/store'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { FeatureLike } from 'ol/Feature'; import { Comment } from '@/types/models'; -import { getCommentElement } from '@/redux/comment/thunks/getComments'; +import { getCommentElement, getCommentReaction } from '@/redux/comment/thunks/getComments'; interface HandleFeaturesClickResult { shouldBlockCoordSearch: boolean; @@ -34,6 +34,7 @@ export const handleFeaturesClick = ( dispatch(getCommentElement({ elementId: Number(elementId), modelId })); dispatch(openBioEntityDrawerById(Number(elementId))); } else if (type === 'REACTION') { + dispatch(getCommentReaction({ elementId: Number(elementId), modelId })); dispatch(openReactionDrawerById(Number(elementId))); } else if (type === 'POINT') { throw new Error(`Opening point comment is not implemented yet`); diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts index 200b9a56cb1758b3956a06bc6137eac7c67d9d1b..d5a42e1ccc9f53ad68f2f0019108fb123d20d571 100644 --- a/src/redux/apiPath.ts +++ b/src/redux/apiPath.ts @@ -22,6 +22,8 @@ const getPublicationsURLSearchParams = ( export const apiPath = { getElementById: (elementId: number, modelId: number): string => `projects/${PROJECT_ID}/models/${modelId}/bioEntities/elements/${elementId}`, + getReactionById: (reactionId: number, modelId: number): string => + `projects/${PROJECT_ID}/models/${modelId}/bioEntities/reactions/?id=${reactionId}`, getBioEntityContentsStringWithQuery: ({ searchQuery, isPerfectMatch, diff --git a/src/redux/comment/comment.constants.ts b/src/redux/comment/comment.constants.ts index b0600d4b22357af89486c357768c145e5d369145..cff58977fcde11178b81d374cfa3698b441c76ad 100644 --- a/src/redux/comment/comment.constants.ts +++ b/src/redux/comment/comment.constants.ts @@ -13,4 +13,5 @@ export const COMMENT_INITIAL_STATE: CommentsState = { error: { name: '', message: '' }, isOpen: false, commentElement: null, + commentReaction: null, }; diff --git a/src/redux/comment/comment.mock.ts b/src/redux/comment/comment.mock.ts index 0320d9aa45e4e24354a03d5c173486ea0136e0ef..be42596a90ce5568c6ed4faca1d230073cd685df 100644 --- a/src/redux/comment/comment.mock.ts +++ b/src/redux/comment/comment.mock.ts @@ -7,4 +7,5 @@ export const COMMENT_INITIAL_STATE_MOCK: CommentsState = { error: DEFAULT_ERROR, isOpen: false, commentElement: null, + commentReaction: null, }; diff --git a/src/redux/comment/comment.reducers.ts b/src/redux/comment/comment.reducers.ts index c06fe01dc894f10bb7cba6304b05422d48ba50ba..b113cdfd76784c4724adbeb1a67fcf3a250d36de 100644 --- a/src/redux/comment/comment.reducers.ts +++ b/src/redux/comment/comment.reducers.ts @@ -1,6 +1,10 @@ import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; import { CommentsState } from '@/redux/comment/comment.types'; -import { getCommentElement, getComments } from '@/redux/comment/thunks/getComments'; +import { + getCommentElement, + getCommentReaction, + getComments, +} from '@/redux/comment/thunks/getComments'; export const getCommentsReducer = (builder: ActionReducerMapBuilder<CommentsState>): void => { builder.addCase(getComments.pending, state => { @@ -34,6 +38,25 @@ export const getCommentElementReducer = (builder: ActionReducerMapBuilder<Commen }); }; +export const getCommentReactionReducer = ( + builder: ActionReducerMapBuilder<CommentsState>, +): void => { + builder.addCase(getCommentReaction.pending, state => { + state.loading = 'pending'; + state.commentReaction = null; + }); + + builder.addCase(getCommentReaction.fulfilled, (state, action) => { + state.loading = 'succeeded'; + state.commentReaction = action.payload; + }); + + builder.addCase(getCommentReaction.rejected, state => { + state.loading = 'failed'; + state.commentReaction = null; + }); +}; + export const showCommentsReducer = (state: CommentsState): void => { state.isOpen = true; }; diff --git a/src/redux/comment/comment.selectors.ts b/src/redux/comment/comment.selectors.ts index da477218a8abbd104b45d147db70be1764403128..7af687a21dc94636d189bb663aba5750e9b7d20a 100644 --- a/src/redux/comment/comment.selectors.ts +++ b/src/redux/comment/comment.selectors.ts @@ -10,6 +10,11 @@ export const commentElementSelector = createSelector( commentState => commentState.commentElement, ); +export const commentReactionSelector = createSelector( + commentSelector, + commentState => commentState.commentReaction, +); + export const allCommentsSelectorOfCurrentMap = createSelector( commentSelector, currentModelIdSelector, diff --git a/src/redux/comment/comment.slice.ts b/src/redux/comment/comment.slice.ts index 355346881a01417d7e777cf0b3fd496bd41badb2..ae4efb8179ecf725686af6f8f93e95187d013323 100644 --- a/src/redux/comment/comment.slice.ts +++ b/src/redux/comment/comment.slice.ts @@ -2,6 +2,7 @@ import { createSlice } from '@reduxjs/toolkit'; import { COMMENT_INITIAL_STATE } from '@/redux/comment/comment.constants'; import { getCommentElementReducer, + getCommentReactionReducer, getCommentsReducer, hideCommentsReducer, showCommentsReducer, @@ -17,6 +18,7 @@ export const commentsSlice = createSlice({ extraReducers: builder => { getCommentsReducer(builder); getCommentElementReducer(builder); + getCommentReactionReducer(builder); }, }); diff --git a/src/redux/comment/comment.types.ts b/src/redux/comment/comment.types.ts index f8d9648b02bbb1fc49da49d57dfd9e74e32c49c7..581da6e4959f40728d402d1dcf51750c731cb15b 100644 --- a/src/redux/comment/comment.types.ts +++ b/src/redux/comment/comment.types.ts @@ -1,10 +1,11 @@ import { FetchDataState } from '@/types/fetchDataState'; -import { BioEntity, Comment } from '@/types/models'; +import { BioEntity, Comment, Reaction } from '@/types/models'; import { PayloadAction } from '@reduxjs/toolkit'; export interface CommentsState extends FetchDataState<Comment[], []> { isOpen: boolean; commentElement: BioEntity | null; + commentReaction: Reaction | null; } export type OpenCommentByIdPayload = number | string; diff --git a/src/redux/comment/thunks/getComments.ts b/src/redux/comment/thunks/getComments.ts index 663bca4eb8f85f3e8fa2fdd8197396b53a8bf470..7f526700e26f80c3120427bf573ec881ce81b3e2 100644 --- a/src/redux/comment/thunks/getComments.ts +++ b/src/redux/comment/thunks/getComments.ts @@ -4,10 +4,12 @@ import { axiosInstance, axiosInstanceNewAPI } from '@/services/api/utils/axiosIn import { ThunkConfig } from '@/types/store'; import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; import { createAsyncThunk } from '@reduxjs/toolkit'; -import { BioEntity, Comment } from '@/types/models'; +import { BioEntity, Comment, Reaction } from '@/types/models'; import { z } from 'zod'; import { bioEntitySchema } from '@/models/bioEntitySchema'; import { GetElementProps } from '@/redux/comment/comment.types'; +import { reactionSchema } from '@/models/reaction'; +import { ZERO } from '@/constants/common'; export const getComments = createAsyncThunk<Comment[], void, ThunkConfig>( 'project/getComments', @@ -40,3 +42,20 @@ export const getCommentElement = createAsyncThunk<BioEntity | null, GetElementPr } }, ); + +export const getCommentReaction = createAsyncThunk<Reaction | null, GetElementProps, ThunkConfig>( + 'project/getCommentReaction', + async ({ elementId, modelId }) => { + try { + const response = await axiosInstance.get<Reaction[]>( + apiPath.getReactionById(elementId, modelId), + ); + + const isDataValid = validateDataUsingZodSchema(response.data, z.array(reactionSchema)); + + return isDataValid && response.data.length > ZERO ? response.data[ZERO] : null; + } catch (error) { + return Promise.reject(error); + } + }, +); diff --git a/src/redux/reactions/reactions.selector.ts b/src/redux/reactions/reactions.selector.ts index 8dbc69904a3a2737dbbf9159989b43a3c4f2c2e0..14590fdaf229a209cbf1b052f4f76be6a5e5c85b 100644 --- a/src/redux/reactions/reactions.selector.ts +++ b/src/redux/reactions/reactions.selector.ts @@ -1,5 +1,6 @@ import { Reaction } from '@/types/models'; import { createSelector } from '@reduxjs/toolkit'; +import { commentReactionSelector } from '@/redux/comment/comment.selectors'; import { currentDrawerReactionIdSelector } from '../drawer/drawer.selectors'; import { currentModelIdSelector } from '../models/models.selectors'; import { rootSelector } from '../root/root.selectors'; @@ -23,9 +24,15 @@ export const allReactionsSelectorOfCurrentMap = createSelector( export const currentDrawerReactionSelector = createSelector( reactionsDataSelector, + commentReactionSelector, currentDrawerReactionIdSelector, - (reactions, currentDrawerReactionId) => - reactions.find(({ id }) => id === currentDrawerReactionId), + (reactions, commentReaction, currentDrawerReactionId) => { + if (commentReaction && commentReaction.id === currentDrawerReactionId) { + return commentReaction; + } + + return reactions.find(({ id }) => id === currentDrawerReactionId); + }, ); export const currentDrawerReactionGroupedReferencesSelector = createSelector(