From dd6156ed878d40c6e07d54b2dfb6cd7d06536979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Or=C5=82=C3=B3w?= <adrian.orlow@fishbrain.com> Date: Mon, 23 Oct 2023 15:53:52 +0200 Subject: [PATCH] feat: add map api comm (no tests) --- .../utils/{ => config}/useOlMapConfig.test.ts | 0 .../utils/{ => config}/useOlMapConfig.ts | 10 ++- .../Map/MapViewer/utils/init/useFirstStage.ts | 23 ++++++ .../Map/MapViewer/utils/init/useOlMapInit.ts | 9 +++ .../MapViewer/utils/init/useSecondStage.ts | 44 +++++++++++ .../Map/MapViewer/utils/init/useThirdStage.ts | 38 ++++++++++ .../Map/MapViewer/utils/useOlMap.ts | 4 +- .../Map/MapViewer/utils/useOlMapInit.ts | 75 ------------------- src/utils/map/useHandleMapChange.ts | 40 ++++++++++ 9 files changed, 163 insertions(+), 80 deletions(-) rename src/components/Map/MapViewer/utils/{ => config}/useOlMapConfig.test.ts (100%) rename src/components/Map/MapViewer/utils/{ => config}/useOlMapConfig.ts (74%) create mode 100644 src/components/Map/MapViewer/utils/init/useFirstStage.ts create mode 100644 src/components/Map/MapViewer/utils/init/useOlMapInit.ts create mode 100644 src/components/Map/MapViewer/utils/init/useSecondStage.ts create mode 100644 src/components/Map/MapViewer/utils/init/useThirdStage.ts delete mode 100644 src/components/Map/MapViewer/utils/useOlMapInit.ts create mode 100644 src/utils/map/useHandleMapChange.ts diff --git a/src/components/Map/MapViewer/utils/useOlMapConfig.test.ts b/src/components/Map/MapViewer/utils/config/useOlMapConfig.test.ts similarity index 100% rename from src/components/Map/MapViewer/utils/useOlMapConfig.test.ts rename to src/components/Map/MapViewer/utils/config/useOlMapConfig.test.ts diff --git a/src/components/Map/MapViewer/utils/useOlMapConfig.ts b/src/components/Map/MapViewer/utils/config/useOlMapConfig.ts similarity index 74% rename from src/components/Map/MapViewer/utils/useOlMapConfig.ts rename to src/components/Map/MapViewer/utils/config/useOlMapConfig.ts index 9ac87292..42d07a05 100644 --- a/src/components/Map/MapViewer/utils/useOlMapConfig.ts +++ b/src/components/Map/MapViewer/utils/config/useOlMapConfig.ts @@ -1,6 +1,9 @@ /* eslint-disable no-magic-numbers */ +import { BASE_MAP_IMAGES_URL } from '@/constants'; import { OPTIONS } from '@/constants/map'; +import { currentBackgroundImagePathSelector } from '@/redux/backgrounds/background.selectors'; import { mapDataPositionSelector, mapDataSizeSelector } from '@/redux/map/map.selectors'; +import { projectDataSelector } from '@/redux/project/project.selectors'; import { Point } from '@/types/map'; import { usePointToProjection } from '@/utils/map/usePointToProjection'; import { View } from 'ol'; @@ -18,6 +21,8 @@ interface UseOlMapConfigResult { export const useOlMapConfig = (): UseOlMapConfigResult => { const mapPosition = useSelector(mapDataPositionSelector); const mapSize = useSelector(mapDataSizeSelector); + const currentBackgroundImagePath = useSelector(currentBackgroundImagePathSelector); + const project = useSelector(projectDataSelector); const pointToProjection = usePointToProjection(); const center = useMemo(() => { @@ -44,15 +49,14 @@ export const useOlMapConfig = (): UseOlMapConfigResult => { new TileLayer({ visible: true, source: new XYZ({ - url: 'https://pdmap.uni.lu/map_images/9d4911bdeeea752f076e57a91d9b1f45/_nested0/{z}/{x}/{y}.PNG', - // TODO: build url from data in redux + url: `${BASE_MAP_IMAGES_URL}/map_images/${project?.directory}/${currentBackgroundImagePath}/{z}/{x}/{y}.PNG`, maxZoom: mapSize.maxZoom, minZoom: mapSize.minZoom, tileSize: mapSize.tileSize, wrapX: OPTIONS.wrapXInTileLayer, }), }), - [mapSize], + [mapSize, currentBackgroundImagePath, project], ); return { diff --git a/src/components/Map/MapViewer/utils/init/useFirstStage.ts b/src/components/Map/MapViewer/utils/init/useFirstStage.ts new file mode 100644 index 00000000..0b8af2ed --- /dev/null +++ b/src/components/Map/MapViewer/utils/init/useFirstStage.ts @@ -0,0 +1,23 @@ +import { PROJECT_ID } from '@/constants'; +import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; +import { getProjectById } from '@/redux/project/project.thunks'; +import { mapLoadingFirstStageInitializedSelector } from '@/redux/root/mapStages.selectors'; +import { useCallback, useEffect } from 'react'; +import { useSelector } from 'react-redux'; + +export const useFirstStage = (): void => { + const dispatch = useAppDispatch(); + const isInitialized = useSelector(mapLoadingFirstStageInitializedSelector); + + const initProjectData = useCallback((): void => { + dispatch(getProjectById(PROJECT_ID)); + }, [dispatch]); + + useEffect(() => { + if (isInitialized) { + return; + } + + initProjectData(); + }, [initProjectData, isInitialized]); +}; diff --git a/src/components/Map/MapViewer/utils/init/useOlMapInit.ts b/src/components/Map/MapViewer/utils/init/useOlMapInit.ts new file mode 100644 index 00000000..2e993841 --- /dev/null +++ b/src/components/Map/MapViewer/utils/init/useOlMapInit.ts @@ -0,0 +1,9 @@ +import { useFirstStage } from './useFirstStage'; +import { useSecondStage } from './useSecondStage'; +import { useThirdStage } from './useThirdStage'; + +export const useOlMapInit = (): void => { + useFirstStage(); + useSecondStage(); + useThirdStage(); +}; diff --git a/src/components/Map/MapViewer/utils/init/useSecondStage.ts b/src/components/Map/MapViewer/utils/init/useSecondStage.ts new file mode 100644 index 00000000..360a56c8 --- /dev/null +++ b/src/components/Map/MapViewer/utils/init/useSecondStage.ts @@ -0,0 +1,44 @@ +import { getAllBackgroundsByProjectId } from '@/redux/backgrounds/backgrounds.thunks'; +import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; +import { getAllModelsByProjectId } from '@/redux/models/models.thunks'; +import { getAllPublicOverlaysByProjectId } from '@/redux/overlays/overlays.thunks'; +import { projectDataSelector } from '@/redux/project/project.selectors'; +import { + mapLoadingFirstStageCompletedSelector, + mapLoadingSecondStageInitializedSelector, +} from '@/redux/root/mapStages.selectors'; +import { AppDispatch } from '@/redux/store'; +import { Project } from '@/types/models'; +import { useCallback, useEffect } from 'react'; +import { useSelector } from 'react-redux'; + +const getMapDataAction = + (project: Project) => + (dispatch: AppDispatch): void => { + dispatch(getAllBackgroundsByProjectId(project.projectId)); + dispatch(getAllPublicOverlaysByProjectId(project.projectId)); + dispatch(getAllModelsByProjectId(project.projectId)); + }; + +export const useSecondStage = (): void => { + const dispatch = useAppDispatch(); + const project = useSelector(projectDataSelector); + const isPreviousCompleted = useSelector(mapLoadingFirstStageCompletedSelector); + const isInitialized = useSelector(mapLoadingSecondStageInitializedSelector); + + const initMapData = useCallback((): void => { + if (!project) { + return; + } + + dispatch(getMapDataAction(project)); + }, [dispatch, project]); + + useEffect(() => { + if (!isPreviousCompleted || isInitialized) { + return; + } + + initMapData(); + }, [initMapData, isInitialized, isPreviousCompleted]); +}; diff --git a/src/components/Map/MapViewer/utils/init/useThirdStage.ts b/src/components/Map/MapViewer/utils/init/useThirdStage.ts new file mode 100644 index 00000000..bb6572a0 --- /dev/null +++ b/src/components/Map/MapViewer/utils/init/useThirdStage.ts @@ -0,0 +1,38 @@ +import { backgroundsDataSelector } from '@/redux/backgrounds/background.selectors'; +import { mapDataSelector } from '@/redux/map/map.selectors'; +import { modelsDataSelector } from '@/redux/models/models.selectors'; +import { mapLoadingAllStagesCompletedSelector } from '@/redux/root/mapStages.selectors'; +import { useHandleMapChange } from '@/utils/map/useHandleMapChange'; +import { useCallback, useEffect } from 'react'; +import { useSelector } from 'react-redux'; + +const FIRST = 0; + +export const useThirdStage = (): void => { + const map = useSelector(mapDataSelector); + const models = useSelector(modelsDataSelector); + const backgrounds = useSelector(backgroundsDataSelector); + const loadingCompleted = useSelector(mapLoadingAllStagesCompletedSelector); + const handleMapChange = useHandleMapChange(); + + const setDefaultMapModelData = useCallback(() => { + const defaultBackground = backgrounds?.[FIRST]; + const defaultModel = models?.[FIRST]; + if (map.modelId || !defaultModel || !defaultBackground) { + return; + } + + handleMapChange({ + model: defaultModel, + background: defaultBackground, + }); + }, [backgrounds, models, map, handleMapChange]); + + useEffect(() => { + if (!loadingCompleted) { + return; + } + + setDefaultMapModelData(); + }, [setDefaultMapModelData, loadingCompleted]); +}; diff --git a/src/components/Map/MapViewer/utils/useOlMap.ts b/src/components/Map/MapViewer/utils/useOlMap.ts index b7525d19..c17fc281 100644 --- a/src/components/Map/MapViewer/utils/useOlMap.ts +++ b/src/components/Map/MapViewer/utils/useOlMap.ts @@ -1,8 +1,8 @@ import Map from 'ol/Map'; import React, { MutableRefObject, useEffect, useState } from 'react'; import { MapInstance } from '../MapViewer.types'; -import { useOlMapConfig } from './useOlMapConfig'; -import { useOlMapInit } from './useOlMapInit'; +import { useOlMapConfig } from './config/useOlMapConfig'; +import { useOlMapInit } from './init/useOlMapInit'; interface UseOlMapInput { target?: HTMLElement; diff --git a/src/components/Map/MapViewer/utils/useOlMapInit.ts b/src/components/Map/MapViewer/utils/useOlMapInit.ts deleted file mode 100644 index 335758e7..00000000 --- a/src/components/Map/MapViewer/utils/useOlMapInit.ts +++ /dev/null @@ -1,75 +0,0 @@ -/* eslint-disable no-magic-numbers */ -// TODO: Remove mocks and implement communication with API - -import { DEFAULT_ZOOM } from '@/constants/map'; -import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; -import { setMapData } from '@/redux/map/map.slice'; -import { useCallback, useEffect } from 'react'; - -const MOCK_PROJECT = { - version: '', - disease: { - link: 'http://id.nlm.nih.gov/mesh/D010300', - type: 'MESH_2012', - resource: 'D010300', - id: 3211856, - annotatorClassName: '', - }, - idObject: 6065, - status: 'Ok', - directory: '9d4911bdeeea752f076e57a91d9b1f45', - progress: 100, - notifyEmail: 'ewa.smula@uni.lu', - logEntries: true, - name: "Parkinson's disease map", - sharedInMinervaNet: true, - owner: 'ewa.smula', - projectId: 'pd_map_winter_23', - creationDate: '2023-02-15 16:35:11', - mapCanvasType: 'OPEN_LAYERS', -}; - -const MOCK_MODEL = { - idObject: 5053, - width: 26779.25, - height: 13503, - defaultCenterX: null, - defaultCenterY: null, - description: '', - name: 'Core PD map', - defaultZoomLevel: null, - tileSize: 256, - references: [], - authors: [], - creationDate: null, - modificationDates: [], - minZoom: 2, - maxZoom: 9, -}; - -export const useOlMapInit = (): void => { - const dispatch = useAppDispatch(); - - const mapInit = useCallback(() => { - dispatch( - setMapData({ - meshId: MOCK_PROJECT.disease.resource, - modelId: MOCK_MODEL.idObject, - size: { - width: MOCK_MODEL.width, - height: MOCK_MODEL.height, - tileSize: MOCK_MODEL.tileSize, - minZoom: MOCK_MODEL.minZoom, - maxZoom: MOCK_MODEL.maxZoom, - }, - position: { - x: MOCK_MODEL.defaultCenterX || MOCK_MODEL.width / 2, - y: MOCK_MODEL.defaultCenterY || MOCK_MODEL.height / 2, - z: MOCK_MODEL.defaultZoomLevel || DEFAULT_ZOOM, - }, - }), - ); - }, [dispatch]); - - useEffect(() => mapInit(), [mapInit]); -}; diff --git a/src/utils/map/useHandleMapChange.ts b/src/utils/map/useHandleMapChange.ts new file mode 100644 index 00000000..94bcaf91 --- /dev/null +++ b/src/utils/map/useHandleMapChange.ts @@ -0,0 +1,40 @@ +import { DEFAULT_ZOOM } from '@/constants/map'; +import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; +import { setMapData } from '@/redux/map/map.slice'; +import { MapBackground, MapModel } from '@/types/models'; + +interface HandleMapChangeArgs { + model: MapModel; + background?: MapBackground; +} + +type UseHandleMapChangeFunction = (args: HandleMapChangeArgs) => void; + +const HALF = 2; + +export const useHandleMapChange = (): UseHandleMapChangeFunction => { + const dispatch = useAppDispatch(); + + const handleMapChange = ({ model, background }: HandleMapChangeArgs): void => { + dispatch( + setMapData({ + modelId: model.idObject, + backgroundId: background?.id, + size: { + width: model.width, + height: model.height, + tileSize: model.tileSize, + minZoom: model.minZoom, + maxZoom: model.maxZoom, + }, + position: { + x: model.defaultCenterX || model.width / HALF, + y: model.defaultCenterY || model.height / HALF, + z: model.defaultZoomLevel || DEFAULT_ZOOM, + }, + }), + ); + }; + + return handleMapChange; +}; -- GitLab