From 5175edb39cb9c518dfc3895847aaad080e07a4f2 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <p.gawron@atcomp.pl> Date: Fri, 7 Jun 2024 11:27:35 +0200 Subject: [PATCH] add comment --- .../AddCommentModal.component.tsx | 11 ++++++++--- .../mapRightClick/onMapRightClick.test.ts | 5 +++-- .../listeners/mapRightClick/onMapRightClick.ts | 10 +++++++++- .../mapSingleClick/onMapSingleClick.ts | 10 +++++++++- src/redux/apiPath.ts | 3 ++- src/redux/comment/comment.selectors.ts | 2 ++ src/redux/comment/comment.types.ts | 2 ++ src/redux/comment/thunks/addComment.ts | 11 +++++++---- src/redux/map/map.constants.ts | 14 ++++++++++++++ src/redux/map/map.fixtures.ts | 15 +++++++++++++++ src/redux/map/map.reducers.ts | 17 +++++++++++++++++ src/redux/map/map.slice.ts | 6 ++++++ src/redux/map/map.types.ts | 15 +++++++++++++++ src/redux/models/models.selectors.ts | 6 ++++++ 14 files changed, 115 insertions(+), 12 deletions(-) diff --git a/src/components/FunctionalArea/Modal/AddCommentModal/AddCommentModal.component.tsx b/src/components/FunctionalArea/Modal/AddCommentModal/AddCommentModal.component.tsx index 7d492602..c675aa35 100644 --- a/src/components/FunctionalArea/Modal/AddCommentModal/AddCommentModal.component.tsx +++ b/src/components/FunctionalArea/Modal/AddCommentModal/AddCommentModal.component.tsx @@ -5,14 +5,19 @@ import React from 'react'; import { addComment } from '@/redux/comment/thunks/addComment'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import { currentModelIdSelector } from '@/redux/models/models.selectors'; +import { lastRightClickSelector } from '@/redux/models/models.selectors'; import { closeModal } from '@/redux/modal/modal.slice'; export const AddCommentModal: React.FC = () => { const dispatch = useAppDispatch(); - const modelId = useAppSelector(currentModelIdSelector); + const lastClick = useAppSelector(lastRightClickSelector); - const [data, setData] = React.useState({ email: '', content: '', modelId }); + const [data, setData] = React.useState({ + email: '', + content: '', + modelId: lastClick.modelId, + position: lastClick.position, + }); const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => { const { name, value } = e.target; diff --git a/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.test.ts b/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.test.ts index 2992cfaa..bead3d12 100644 --- a/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.test.ts @@ -8,7 +8,7 @@ import { ELEMENT_SEARCH_RESULT_MOCK_REACTION, } from '@/models/mocks/elementSearchResultMock'; import { waitFor } from '@testing-library/react'; -import { FIRST_ARRAY_ELEMENT, SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; +import { FIRST_ARRAY_ELEMENT, SECOND_ARRAY_ELEMENT, SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; import { onMapRightClick } from './onMapRightClick'; import * as handleDataReset from '../mapSingleClick/handleDataReset'; import * as handleSearchResultForRightClickAction from './handleSearchResultForRightClickAction'; @@ -58,7 +58,8 @@ describe('onMapRightClick - util', () => { it('should fire open context menu handler', async () => { const actions = store.getActions(); expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY); - expect(actions[FIRST_ARRAY_ELEMENT].type).toEqual('contextMenu/openContextMenu'); + expect(actions[FIRST_ARRAY_ELEMENT].type).toEqual('map/updateLastRightClick'); + expect(actions[SECOND_ARRAY_ELEMENT].type).toEqual('contextMenu/openContextMenu'); }); }); diff --git a/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.ts b/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.ts index 2288c0c6..d5d28489 100644 --- a/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.ts @@ -1,9 +1,12 @@ -import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; import { openContextMenu } from '@/redux/contextMenu/contextMenu.slice'; +import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; import { MapSize } from '@/redux/map/map.types'; import { AppDispatch } from '@/redux/store'; import { Coordinate } from 'ol/coordinate'; import { Pixel } from 'ol/pixel'; +import { updateLastRightClick } from '@/redux/map/map.slice'; +import { toLonLat } from 'ol/proj'; +import { latLngToPoint } from '@/utils/map/latLngToPoint'; import { getSearchResults } from '../mapSingleClick/getSearchResults'; import { handleDataReset } from '../mapSingleClick/handleDataReset'; import { handleSearchResultForRightClickAction } from './handleSearchResultForRightClickAction'; @@ -11,6 +14,11 @@ import { handleSearchResultForRightClickAction } from './handleSearchResultForRi /* prettier-ignore */ export const onMapRightClick = (mapSize: MapSize, modelId: number, dispatch: AppDispatch) => async (coordinate: Coordinate, pixel: Pixel): Promise<void> => { + const [lng, lat] = toLonLat(coordinate); + const point = latLngToPoint([lat, lng], mapSize); + + dispatch(updateLastRightClick({coordinates:point, modelId})); + dispatch(handleDataReset); dispatch(openContextMenu(pixel)); diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts index cb09d0a5..e04f2880 100644 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts @@ -4,6 +4,9 @@ import { AppDispatch } from '@/redux/store'; import { Map, MapBrowserEvent } from 'ol'; import { FeatureLike } from 'ol/Feature'; import { Comment } from '@/types/models'; +import { updateLastClick } from '@/redux/map/map.slice'; +import { toLonLat } from 'ol/proj'; +import { latLngToPoint } from '@/utils/map/latLngToPoint'; import { getSearchResults } from './getSearchResults'; import { handleDataReset } from './handleDataReset'; import { handleFeaturesClick } from './handleFeaturesClick'; @@ -14,6 +17,11 @@ export const onMapSingleClick = (mapSize: MapSize, modelId: number, dispatch: AppDispatch, searchDistance: string | undefined, maxZoom: number, zoom: number, isResultDrawerOpen: boolean, comments: Comment[]) => async ({ coordinate, pixel }: Pick<MapBrowserEvent<UIEvent>, 'coordinate' | 'pixel'>, mapInstance: Map): Promise<void> => { + const [lng, lat] = toLonLat(coordinate); + const point = latLngToPoint([lat, lng], mapSize); + + dispatch(updateLastClick({coordinates:point, modelId})); + const featuresAtPixel: FeatureLike[] = []; mapInstance.forEachFeatureAtPixel(pixel, (feature) => featuresAtPixel.push(feature)); const { shouldBlockCoordSearch } = handleFeaturesClick(featuresAtPixel, dispatch, comments); @@ -26,7 +34,7 @@ export const onMapSingleClick = // so we need to reset all the data before updating dispatch(handleDataReset); - const {searchResults, point} = await getSearchResults({ coordinate, mapSize, modelId }); + const {searchResults} = await getSearchResults({ coordinate, mapSize, modelId }); if (!searchResults || searchResults.length === SIZE_OF_EMPTY_ARRAY) { return; } diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts index 822bce33..680df483 100644 --- a/src/redux/apiPath.ts +++ b/src/redux/apiPath.ts @@ -99,5 +99,6 @@ export const apiPath = { logout: (): string => `doLogout`, userPrivileges: (login: string): string => `users/${login}?columns=privileges`, getComments: (): string => `projects/${PROJECT_ID}/comments/models/*/`, - addComment: (modelId: number): string => `projects/${PROJECT_ID}/comments/models/${modelId}/`, + addComment: (modelId: number, x: number, y: number): string => + `projects/${PROJECT_ID}/comments/models/${modelId}/points/${x},${y}/`, }; diff --git a/src/redux/comment/comment.selectors.ts b/src/redux/comment/comment.selectors.ts index 7af687a2..bce68955 100644 --- a/src/redux/comment/comment.selectors.ts +++ b/src/redux/comment/comment.selectors.ts @@ -23,6 +23,8 @@ export const allCommentsSelectorOfCurrentMap = createSelector( return []; } + // eslint-disable-next-line no-console + console.log(commentState.data); return (commentState.data || []) .filter(comment => comment.modelId === currentModelId) .map(comment => { diff --git a/src/redux/comment/comment.types.ts b/src/redux/comment/comment.types.ts index 368782e8..8cb0e4b5 100644 --- a/src/redux/comment/comment.types.ts +++ b/src/redux/comment/comment.types.ts @@ -1,6 +1,7 @@ import { FetchDataState } from '@/types/fetchDataState'; import { BioEntity, Comment, Reaction } from '@/types/models'; import { PayloadAction } from '@reduxjs/toolkit'; +import { Point } from '@/types/map'; export interface CommentsState extends FetchDataState<Comment[], []> { isOpen: boolean; @@ -20,4 +21,5 @@ export type AddCommentProps = { email: string; content: string; modelId: number; + position: Point; }; diff --git a/src/redux/comment/thunks/addComment.ts b/src/redux/comment/thunks/addComment.ts index 37afcf2c..8db1cb94 100644 --- a/src/redux/comment/thunks/addComment.ts +++ b/src/redux/comment/thunks/addComment.ts @@ -8,11 +8,14 @@ import { Comment } from '@/types/models'; import { AddCommentProps } from '@/redux/comment/comment.types'; export const addComment = createAsyncThunk<Comment | null, AddCommentProps, ThunkConfig>( - 'project/getComments', - async ({ email, content, modelId }) => { + 'project/addComment', + async ({ email, content, modelId, position }) => { try { - const payload = { email, content }; - const response = await axiosInstance.post<Comment>(apiPath.addComment(modelId), payload); + const payload = new URLSearchParams({ email, content }); + const response = await axiosInstance.post<Comment>( + apiPath.addComment(modelId, Math.trunc(position.x), Math.trunc(position.y)), + payload, + ); const isDataValid = validateDataUsingZodSchema(response.data, commentSchema); diff --git a/src/redux/map/map.constants.ts b/src/redux/map/map.constants.ts index 70126c71..3b9e9e53 100644 --- a/src/redux/map/map.constants.ts +++ b/src/redux/map/map.constants.ts @@ -39,6 +39,20 @@ export const MAP_DATA_INITIAL_STATE: MapData = { minZoom: DEFAULT_MIN_ZOOM, maxZoom: DEFAULT_MAX_ZOOM, }, + lastClick: { + modelId: MODEL_ID_DEFAULT, + position: { + x: 0, + y: 0, + }, + }, + lastRightClick: { + modelId: MODEL_ID_DEFAULT, + position: { + x: 0, + y: 0, + }, + }, }; export const DEFAULT_POSITION: Point = { x: 0, y: 0, z: 0 }; diff --git a/src/redux/map/map.fixtures.ts b/src/redux/map/map.fixtures.ts index be022b69..049bdc64 100644 --- a/src/redux/map/map.fixtures.ts +++ b/src/redux/map/map.fixtures.ts @@ -1,4 +1,5 @@ import { DEFAULT_ERROR } from '@/constants/errors'; +import { MODEL_ID_DEFAULT } from '@/redux/map/map.constants'; import { MapData, MapState, OppenedMap } from './map.types'; export const openedMapsInitialValueFixture: OppenedMap[] = [ @@ -32,6 +33,20 @@ export const initialMapDataFixture: MapData = { minZoom: 2, maxZoom: 9, }, + lastClick: { + modelId: MODEL_ID_DEFAULT, + position: { + x: 0, + y: 0, + }, + }, + lastRightClick: { + modelId: MODEL_ID_DEFAULT, + position: { + x: 0, + y: 0, + }, + }, }; export const initialMapStateFixture: MapState = { diff --git a/src/redux/map/map.reducers.ts b/src/redux/map/map.reducers.ts index c65bfe97..f193e753 100644 --- a/src/redux/map/map.reducers.ts +++ b/src/redux/map/map.reducers.ts @@ -15,6 +15,7 @@ import { OpenMapAndSetActiveAction, SetActiveMapAction, SetBackgroundAction, + SetLastClickPositionAction, SetLastPositionZoomAction, SetLastPositionZoomWithDeltaAction, SetMapDataAction, @@ -100,6 +101,22 @@ export const setLastPositionZoomReducer = ( state.data.position.initial.z = zoom; }; +export const updateLastClickReducer = ( + state: MapState, + action: SetLastClickPositionAction, +): void => { + state.data.lastClick.modelId = action.payload.modelId; + state.data.lastClick.position = action.payload.coordinates; +}; + +export const updateLastRightClickReducer = ( + state: MapState, + action: SetLastClickPositionAction, +): void => { + state.data.lastRightClick.modelId = action.payload.modelId; + state.data.lastRightClick.position = action.payload.coordinates; +}; + const updateLastPositionOfCurrentlyActiveMap = (state: MapState): void => { const currentMapId = state.data.modelId; const currentOpenedMap = state.openedMaps.find(openedMap => openedMap.modelId === currentMapId); diff --git a/src/redux/map/map.slice.ts b/src/redux/map/map.slice.ts index 46f68b78..3106a118 100644 --- a/src/redux/map/map.slice.ts +++ b/src/redux/map/map.slice.ts @@ -14,6 +14,8 @@ import { setMapBackgroundReducer, setMapDataReducer, setMapPositionReducer, + updateLastClickReducer, + updateLastRightClickReducer, varyPositionZoomReducer, } from './map.reducers'; @@ -31,6 +33,8 @@ const mapSlice = createSlice({ setMapBackground: setMapBackgroundReducer, openMapAndOrSetActiveIfSelected: openMapAndOrSetActiveIfSelectedReducer, setLastPositionZoom: setLastPositionZoomReducer, + updateLastClick: updateLastClickReducer, + updateLastRightClick: updateLastRightClickReducer, }, extraReducers: builder => { initMapPositionReducers(builder); @@ -51,6 +55,8 @@ export const { varyPositionZoom, openMapAndOrSetActiveIfSelected, setLastPositionZoom, + updateLastClick, + updateLastRightClick, } = mapSlice.actions; export default mapSlice.reducer; diff --git a/src/redux/map/map.types.ts b/src/redux/map/map.types.ts index 727df76f..72b600dc 100644 --- a/src/redux/map/map.types.ts +++ b/src/redux/map/map.types.ts @@ -30,6 +30,14 @@ export type MapData = { overlaysIds: number[]; size: MapSize; position: Position; + lastClick: { + position: Point; + modelId: number; + }; + lastRightClick: { + position: Point; + modelId: number; + }; show: { legend: boolean; comments: boolean; @@ -101,6 +109,13 @@ export type SetLastPositionZoomActionPayload = { export type SetLastPositionZoomAction = PayloadAction<SetLastPositionZoomActionPayload>; +export type SetLastClickPositionActionPayload = { + modelId: number; + coordinates: Point; +}; + +export type SetLastClickPositionAction = PayloadAction<SetLastClickPositionActionPayload>; + export type InitMapDataActionPayload = { data: GetUpdatedMapDataResult | object; openedMaps: OppenedMap[]; diff --git a/src/redux/models/models.selectors.ts b/src/redux/models/models.selectors.ts index 99d94b76..406e1f3c 100644 --- a/src/redux/models/models.selectors.ts +++ b/src/redux/models/models.selectors.ts @@ -33,6 +33,12 @@ export const currentModelIdSelector = createSelector( model => model?.idObject || MODEL_ID_DEFAULT, ); +export const lastClickSelector = createSelector(mapDataSelector, mapData => mapData.lastClick); +export const lastRightClickSelector = createSelector( + mapDataSelector, + mapData => mapData.lastRightClick, +); + export const currentModelNameSelector = createSelector( currentModelSelector, model => model?.name || '', -- GitLab