diff --git a/src/components/FunctionalArea/Modal/OverviewImagesModal/OverviewImagesModal.constants.ts b/src/components/FunctionalArea/Modal/OverviewImagesModal/OverviewImagesModal.constants.ts new file mode 100644 index 0000000000000000000000000000000000000000..d108d444f510429b33cde666db18f35fbdf017c3 --- /dev/null +++ b/src/components/FunctionalArea/Modal/OverviewImagesModal/OverviewImagesModal.constants.ts @@ -0,0 +1,8 @@ +import { OverviewImageLinkConfigSize } from './OverviewImageModal.types'; + +export const DEFAULT_OVERVIEW_IMAGE_LINK_CONFIG: OverviewImageLinkConfigSize = { + top: 0, + left: 0, + width: 0, + height: 0, +}; diff --git a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/getOverviewImageLinkSize.test.ts b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/getOverviewImageLinkSize.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..2aad19fbfab91a3f9c476c62aa6d2cc8a8abf903 --- /dev/null +++ b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/getOverviewImageLinkSize.test.ts @@ -0,0 +1,108 @@ +import { OverviewImageLink } from '@/types/models'; +import { OverviewImageLinkConfigSize } from '../OverviewImageModal.types'; +import { DEFAULT_OVERVIEW_IMAGE_LINK_CONFIG } from '../OverviewImagesModal.constants'; +import { getOverviewImageLinkSize } from './getOverviewImageLinkSize'; + +describe('getOverviewImageLinkSize - util', () => { + const cases: [ + Pick<OverviewImageLink, 'polygon'>, + { + sizeFactor: number; + }, + OverviewImageLinkConfigSize, + ][] = [ + // invalid polygon + [ + { + polygon: [], + }, + { + sizeFactor: 1, + }, + DEFAULT_OVERVIEW_IMAGE_LINK_CONFIG, + ], + // invalid polygon + [ + { + polygon: [ + { x: 0, y: 0 }, + { x: 0, y: 0 }, + { x: 0, y: 0 }, + ], + }, + { + sizeFactor: 1, + }, + DEFAULT_OVERVIEW_IMAGE_LINK_CONFIG, + ], + // valid polygon with size of 0x0 + [ + { + polygon: [ + { x: 0, y: 0 }, + { x: 0, y: 0 }, + { x: 0, y: 0 }, + { x: 0, y: 0 }, + ], + }, + { + sizeFactor: 1, + }, + { + top: 0, + left: 0, + width: 0, + height: 0, + }, + ], + // valid polygon with size of 20x50 + [ + { + polygon: [ + { x: 10, y: 0 }, + { x: 30, y: 0 }, + { x: 30, y: 50 }, + { x: 10, y: 50 }, + ], + }, + { + sizeFactor: 1, + }, + { + top: 0, + left: 10, + width: 20, + height: 50, + }, + ], + // valid polygon with size of 27x67.5 in scale of 1.35 + [ + { + polygon: [ + { x: 10, y: 0 }, + { x: 30, y: 0 }, + { x: 30, y: 50 }, + { x: 10, y: 50 }, + ], + }, + { + sizeFactor: 1.35, + }, + { + height: 67.5, + left: 13.5, + top: 0, + width: 27, + }, + ], + ]; + + it.each(cases)( + 'should return valid link config size', + (overviewImageWithPolygon, options, finalConfigSize) => { + expect(getOverviewImageLinkSize(overviewImageWithPolygon, options)).toStrictEqual( + finalConfigSize, + ); + }, + ); +}); diff --git a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/getOverviewImageLinkSize.ts b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/getOverviewImageLinkSize.ts index 66a82ad7c2cb69bd564bd488cc98e4af9cb58940..f03b7509f3abe59ed4b23d8eb3cdd32e34703dea 100644 --- a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/getOverviewImageLinkSize.ts +++ b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/getOverviewImageLinkSize.ts @@ -1,14 +1,21 @@ +import { SIZE_OF_ARRAY_WITH_FOUR_ELEMENTS } from '@/constants/common'; import { OverviewImageLink } from '@/types/models'; import { OverviewImageLinkConfigSize } from '../OverviewImageModal.types'; +import { DEFAULT_OVERVIEW_IMAGE_LINK_CONFIG } from '../OverviewImagesModal.constants'; export const getOverviewImageLinkSize = ( - { polygon }: OverviewImageLink, + { polygon }: Pick<OverviewImageLink, 'polygon'>, { sizeFactor, }: { sizeFactor: number; }, ): OverviewImageLinkConfigSize => { + // valid polygon needs to have four points + if (polygon.length < SIZE_OF_ARRAY_WITH_FOUR_ELEMENTS) { + return DEFAULT_OVERVIEW_IMAGE_LINK_CONFIG; + } + const polygonScaled = polygon.map(({ x, y }) => ({ x: x * sizeFactor, y: y * sizeFactor })); const [pointTopLeft, , pointBottomRight] = polygonScaled; const width = pointBottomRight.x - pointTopLeft.x; diff --git a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkActions.test.ts b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkActions.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..c0df892c5e7a03016d752a3d1ae78f208bb33ad9 --- /dev/null +++ b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkActions.test.ts @@ -0,0 +1,306 @@ +import { projectFixture } from '@/models/fixtures/projectFixture'; +import { MODELS_MOCK_SHORT } from '@/models/mocks/modelsMock'; +import { + OVERVIEW_LINK_IMAGE_MOCK, + OVERVIEW_LINK_MODEL_MOCK, +} from '@/models/mocks/overviewImageMocks'; +import { + initialMapDataFixture, + openedMapsInitialValueFixture, + openedMapsThreeSubmapsFixture, +} from '@/redux/map/map.fixtures'; +import { MODAL_INITIAL_STATE_MOCK } from '@/redux/modal/modal.mock'; +import { PROJECT_OVERVIEW_IMAGE_MOCK } from '@/redux/project/project.mock'; +import { OverviewImageLink } from '@/types/models'; +import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreActionsListener'; +import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; +import { renderHook } from '@testing-library/react'; +import { + FIRST_ARRAY_ELEMENT, + NOOP, + SECOND_ARRAY_ELEMENT, + SIZE_OF_EMPTY_ARRAY, + THIRD_ARRAY_ELEMENT, +} from '../../../../../constants/common'; +import { useOverviewImageLinkActions } from './useOverviewImageLinkActions'; + +jest.mock('../../../../../constants/common', () => ({ + ...jest.requireActual('../../../../../constants/common'), + NOOP: jest.fn(), +})); + +describe('useOverviewImageLinkActions - hook', () => { + describe('when clicked on image link', () => { + describe('when image id is NOT valid', () => { + const { Wrapper, store } = getReduxStoreWithActionsListener({ + project: { + data: { + ...projectFixture, + overviewImageViews: [], + topOverviewImage: PROJECT_OVERVIEW_IMAGE_MOCK, + }, + loading: 'succeeded', + error: { message: '', name: '' }, + }, + modal: { + ...MODAL_INITIAL_STATE_MOCK, + overviewImagesState: { + imageId: 0, + }, + }, + map: { + data: { + ...initialMapDataFixture, + modelId: 5053, + }, + loading: 'succeeded', + error: { name: '', message: '' }, + openedMaps: openedMapsThreeSubmapsFixture, + }, + }); + + const { + result: { + current: { handleLinkClick }, + }, + } = renderHook(() => useOverviewImageLinkActions(), { + wrapper: Wrapper, + }); + + it('should NOT fire action set overview image id', () => { + handleLinkClick(OVERVIEW_LINK_IMAGE_MOCK); + const actions = store.getActions(); + expect(actions.length).toEqual(SIZE_OF_EMPTY_ARRAY); + }); + }); + + describe('when image id is valid', () => { + const { Wrapper, store } = getReduxStoreWithActionsListener({ + project: { + data: { + ...projectFixture, + overviewImageViews: [ + { + ...PROJECT_OVERVIEW_IMAGE_MOCK, + height: 500, + width: 500, + }, + ], + topOverviewImage: PROJECT_OVERVIEW_IMAGE_MOCK, + }, + loading: 'succeeded', + error: { message: '', name: '' }, + }, + modal: { + ...MODAL_INITIAL_STATE_MOCK, + overviewImagesState: { + imageId: PROJECT_OVERVIEW_IMAGE_MOCK.idObject, + }, + }, + map: { + data: { + ...initialMapDataFixture, + modelId: 5053, + }, + loading: 'succeeded', + error: { name: '', message: '' }, + openedMaps: openedMapsThreeSubmapsFixture, + }, + }); + + const { + result: { + current: { handleLinkClick }, + }, + } = renderHook(() => useOverviewImageLinkActions(), { + wrapper: Wrapper, + }); + + it('should fire action set overview image id', () => { + handleLinkClick(OVERVIEW_LINK_IMAGE_MOCK); + const actions = store.getActions(); + expect(actions[FIRST_ARRAY_ELEMENT]).toStrictEqual({ + payload: 440, + type: 'modal/setOverviewImageId', + }); + }); + }); + }); + describe('when clicked on model link', () => { + describe('when model is not available', () => {}); + + describe('when model is available', () => { + describe('when map is already opened', () => { + const { Wrapper, store } = getReduxStoreWithActionsListener({ + project: { + data: { + ...projectFixture, + overviewImageViews: [ + { + ...PROJECT_OVERVIEW_IMAGE_MOCK, + height: 500, + width: 500, + }, + ], + topOverviewImage: PROJECT_OVERVIEW_IMAGE_MOCK, + }, + loading: 'succeeded', + error: { message: '', name: '' }, + }, + modal: { + ...MODAL_INITIAL_STATE_MOCK, + overviewImagesState: { + imageId: PROJECT_OVERVIEW_IMAGE_MOCK.idObject, + }, + }, + map: { + data: { + ...initialMapDataFixture, + modelId: 5053, + }, + loading: 'succeeded', + error: { name: '', message: '' }, + openedMaps: openedMapsThreeSubmapsFixture, + }, + models: { + data: MODELS_MOCK_SHORT, + loading: 'succeeded', + error: { name: '', message: '' }, + }, + }); + + const { + result: { + current: { handleLinkClick }, + }, + } = renderHook(() => useOverviewImageLinkActions(), { + wrapper: Wrapper, + }); + + it('should set active map', () => { + handleLinkClick(OVERVIEW_LINK_MODEL_MOCK); + const actions = store.getActions(); + expect(actions[FIRST_ARRAY_ELEMENT]).toStrictEqual({ + payload: { + modelId: 5053, + }, + type: 'map/setActiveMap', + }); + }); + + it('should set map position', () => { + handleLinkClick(OVERVIEW_LINK_MODEL_MOCK); + const actions = store.getActions(); + expect(actions[SECOND_ARRAY_ELEMENT]).toStrictEqual({ + payload: { x: 15570, y: 3016, z: 7 }, + type: 'map/setMapPosition', + }); + }); + + it('should close modal', () => { + handleLinkClick(OVERVIEW_LINK_MODEL_MOCK); + const actions = store.getActions(); + expect(actions[THIRD_ARRAY_ELEMENT]).toStrictEqual({ + payload: undefined, + type: 'modal/closeModal', + }); + }); + }); + + describe('when map is not opened', () => { + const { Wrapper, store } = getReduxStoreWithActionsListener({ + project: { + data: { + ...projectFixture, + overviewImageViews: [ + { + ...PROJECT_OVERVIEW_IMAGE_MOCK, + height: 500, + width: 500, + }, + ], + topOverviewImage: PROJECT_OVERVIEW_IMAGE_MOCK, + }, + loading: 'succeeded', + error: { message: '', name: '' }, + }, + modal: { + ...MODAL_INITIAL_STATE_MOCK, + overviewImagesState: { + imageId: PROJECT_OVERVIEW_IMAGE_MOCK.idObject, + }, + }, + map: { + data: { + ...initialMapDataFixture, + modelId: 5053, + }, + loading: 'succeeded', + error: { name: '', message: '' }, + openedMaps: openedMapsInitialValueFixture, + }, + models: { + data: MODELS_MOCK_SHORT, + loading: 'succeeded', + error: { name: '', message: '' }, + }, + }); + + const { + result: { + current: { handleLinkClick }, + }, + } = renderHook(() => useOverviewImageLinkActions(), { + wrapper: Wrapper, + }); + + it('should open map and set as active', () => { + handleLinkClick(OVERVIEW_LINK_MODEL_MOCK); + const actions = store.getActions(); + expect(actions[FIRST_ARRAY_ELEMENT]).toStrictEqual({ + payload: { + modelId: 5053, + modelName: 'Core PD map', + }, + type: 'map/openMapAndSetActive', + }); + }); + + it('should set map position', () => { + handleLinkClick(OVERVIEW_LINK_MODEL_MOCK); + const actions = store.getActions(); + expect(actions[SECOND_ARRAY_ELEMENT]).toStrictEqual({ + payload: { x: 15570, y: 3016, z: 7 }, + type: 'map/setMapPosition', + }); + }); + + it('should close modal', () => { + handleLinkClick(OVERVIEW_LINK_MODEL_MOCK); + const actions = store.getActions(); + expect(actions[THIRD_ARRAY_ELEMENT]).toStrictEqual({ + payload: undefined, + type: 'modal/closeModal', + }); + }); + }); + }); + }); + describe('when clicked on unsupported link', () => { + const { Wrapper } = getReduxWrapperWithStore(); + const { + result: { + current: { handleLinkClick }, + }, + } = renderHook(() => useOverviewImageLinkActions(), { + wrapper: Wrapper, + }); + + it('should noop', () => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore to simulate invalid link object + handleLinkClick({ link: {} as unknown as OverviewImageLink }); + expect(NOOP).toBeCalled(); + }); + }); +}); diff --git a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkActions.ts b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkActions.ts index fa6c658c192ae69a2196a5ca58b3ba2675aa0350..1388a45a82c05425f769e3d6fff4ce5d05b7c98b 100644 --- a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkActions.ts +++ b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkActions.ts @@ -5,41 +5,45 @@ import { mapOpenedMapsSelector } from '@/redux/map/map.selectors'; import { openMapAndSetActive, setActiveMap, setMapPosition } from '@/redux/map/map.slice'; import { closeModal, setOverviewImageId } from '@/redux/modal/modal.slice'; import { modelsDataSelector } from '@/redux/models/models.selectors'; -import { MapModel, OverviewImageLink } from '@/types/models'; +import { projectOverviewImagesSelector } from '@/redux/project/project.selectors'; +import { MapModel, OverviewImageLink, OverviewImageLinkModel } from '@/types/models'; import { OverviewImageLinkImageHandler, OverviewImageLinkModelHandler, } from '../OverviewImageModal.types'; interface UseOverviewImageLinkActionsResult { - handleOnLinkClick(link: OverviewImageLink): void; + handleLinkClick(link: OverviewImageLink): void; } -export const useOvervieImageLinkActions = (): UseOverviewImageLinkActionsResult => { +export const useOverviewImageLinkActions = (): UseOverviewImageLinkActionsResult => { const dispatch = useAppDispatch(); const openedMaps = useAppSelector(mapOpenedMapsSelector); const models = useAppSelector(modelsDataSelector); + const overviewImages = useAppSelector(projectOverviewImagesSelector); - const isMapAlreadyOpened = (modelId: number): boolean => + const checkIfImageIsAvailable = (imageId: number): boolean => + overviewImages.some(image => image.idObject === imageId); + + const checkIfMapAlreadyOpened = (modelId: number): boolean => openedMaps.some(map => map.modelId === modelId); const getModelById = (modelId: number): MapModel | undefined => models.find(map => map.idObject === modelId); - const onSubmapClick: OverviewImageLinkModelHandler = link => { - const modelId = link.modelLinkId; - const model = getModelById(modelId); - const isMapOpened = isMapAlreadyOpened(modelId); - if (!model) { - return; - } + const handleOpenMap = (model: MapModel): void => { + const modelId = model.idObject; + const isMapOpened = checkIfMapAlreadyOpened(modelId); if (isMapOpened) { dispatch(setActiveMap({ modelId })); - } else { - dispatch(openMapAndSetActive({ modelId, modelName: model.name })); + return; } + dispatch(openMapAndSetActive({ modelId, modelName: model.name })); + }; + + const handleSetMapPosition = (link: OverviewImageLinkModel, model: MapModel): void => { dispatch( setMapPosition({ x: link.modelPoint.x, @@ -47,26 +51,45 @@ export const useOvervieImageLinkActions = (): UseOverviewImageLinkActionsResult z: link.zoomLevel + model.minZoom, }), ); + }; + + const onSubmapClick: OverviewImageLinkModelHandler = link => { + const modelId = link.modelLinkId; + const model = getModelById(modelId); + if (!model) { + return; + } + + handleOpenMap(model); + handleSetMapPosition(link, model); dispatch(closeModal()); }; const onImageClick: OverviewImageLinkImageHandler = link => { + const isImageAvailable = checkIfImageIsAvailable(link.imageLinkId); + if (!isImageAvailable) { + return; + } + dispatch(setOverviewImageId(link.imageLinkId)); }; - const handleOnLinkClick: UseOverviewImageLinkActionsResult['handleOnLinkClick'] = link => { - if ('imageLinkId' in link) { + const handleLinkClick: UseOverviewImageLinkActionsResult['handleLinkClick'] = link => { + const isImageLink = 'imageLinkId' in link; + const isModelLink = 'modelLinkId' in link; + + if (isImageLink) { return onImageClick(link); } - if ('modelLinkId' in link) { + if (isModelLink) { return onSubmapClick(link); } - return NOOP; + return NOOP(); }; return { - handleOnLinkClick, + handleLinkClick, }; }; diff --git a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkElements.test.ts b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkElements.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..308e52405d55345fc2345155ff60abe1abc25da5 --- /dev/null +++ b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkElements.test.ts @@ -0,0 +1,148 @@ +import { ZERO } from '@/constants/common'; +import { projectFixture } from '@/models/fixtures/projectFixture'; +import { MODAL_INITIAL_STATE_MOCK } from '@/redux/modal/modal.mock'; +import { PROJECT_OVERVIEW_IMAGE_MOCK } from '@/redux/project/project.mock'; +import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; +import { renderHook } from '@testing-library/react'; +import { useOverviewImageLinkConfigs } from './useOverviewImageLinkElements'; + +describe('useOverviewImageLinkConfigs - hook', () => { + describe('when currentImage is undefined', () => { + const { Wrapper } = getReduxWrapperWithStore({ + project: { + data: { + ...projectFixture, + overviewImageViews: [], + topOverviewImage: PROJECT_OVERVIEW_IMAGE_MOCK, + }, + loading: 'succeeded', + error: { message: '', name: '' }, + }, + modal: { + ...MODAL_INITIAL_STATE_MOCK, + overviewImagesState: { + imageId: 0, + }, + }, + }); + + const { + result: { current: returnValue }, + } = renderHook( + () => + useOverviewImageLinkConfigs({ + sizeFactor: 1, + }), + { + wrapper: Wrapper, + }, + ); + + it('should return empty array', () => { + expect(returnValue).toStrictEqual([]); + }); + }); + + describe('when sizeFactor is zero', () => { + const { Wrapper } = getReduxWrapperWithStore({ + project: { + data: { + ...projectFixture, + overviewImageViews: [PROJECT_OVERVIEW_IMAGE_MOCK], + topOverviewImage: PROJECT_OVERVIEW_IMAGE_MOCK, + }, + loading: 'succeeded', + error: { message: '', name: '' }, + }, + modal: { + ...MODAL_INITIAL_STATE_MOCK, + overviewImagesState: { + imageId: PROJECT_OVERVIEW_IMAGE_MOCK.idObject, + }, + }, + }); + + const { + result: { current: returnValue }, + } = renderHook( + () => + useOverviewImageLinkConfigs({ + sizeFactor: ZERO, + }), + { + wrapper: Wrapper, + }, + ); + + it('should return empty array', () => { + expect(returnValue).toStrictEqual([]); + }); + }); + + describe('when all args are valid', () => { + const { Wrapper } = getReduxWrapperWithStore({ + project: { + data: { + ...projectFixture, + overviewImageViews: [PROJECT_OVERVIEW_IMAGE_MOCK], + topOverviewImage: PROJECT_OVERVIEW_IMAGE_MOCK, + }, + loading: 'succeeded', + error: { message: '', name: '' }, + }, + modal: { + ...MODAL_INITIAL_STATE_MOCK, + overviewImagesState: { + imageId: PROJECT_OVERVIEW_IMAGE_MOCK.idObject, + }, + }, + }); + + const { + result: { current: returnValue }, + } = renderHook( + () => + useOverviewImageLinkConfigs({ + sizeFactor: 1, + }), + { + wrapper: Wrapper, + }, + ); + + it('should return correct value', () => { + expect(returnValue).toStrictEqual([ + { + idObject: 2062, + size: { top: 2187, left: 515, width: 558, height: 333 }, + onClick: expect.any(Function), + }, + { + idObject: 2063, + size: { top: 1360, left: 2410, width: 282, height: 210 }, + onClick: expect.any(Function), + }, + { + idObject: 2064, + size: { top: 497, left: 2830, width: 426, height: 335 }, + onClick: expect.any(Function), + }, + { + idObject: 2065, + size: { top: 2259, left: 3232, width: 288, height: 197 }, + onClick: expect.any(Function), + }, + { + idObject: 2066, + size: { top: 761, left: 4205, width: 420, height: 341 }, + onClick: expect.any(Function), + }, + { + idObject: 2067, + size: { top: 1971, left: 4960, width: 281, height: 192 }, + onClick: expect.any(Function), + }, + ]); + }); + }); +}); diff --git a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkElements.tsx b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkElements.tsx index 622f8aa83039824658accbbb9b4956577c5ef1dd..6e0150dc37c986fb81881503c9ec81bb7321f691 100644 --- a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkElements.tsx +++ b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkElements.tsx @@ -1,8 +1,9 @@ +import { ZERO } from '@/constants/common'; import { currentOverviewImageSelector } from '@/redux/project/project.selectors'; import { useSelector } from 'react-redux'; import { OverviewImageLinkConfig } from '../OverviewImageModal.types'; import { getOverviewImageLinkSize } from './getOverviewImageLinkSize'; -import { useOvervieImageLinkActions } from './useOverviewImageLinkActions'; +import { useOverviewImageLinkActions } from './useOverviewImageLinkActions'; interface UseOverviewImageLinksArgs { sizeFactor: number; @@ -11,18 +12,14 @@ interface UseOverviewImageLinksArgs { export const useOverviewImageLinkConfigs = ({ sizeFactor, }: UseOverviewImageLinksArgs): OverviewImageLinkConfig[] => { - const { handleOnLinkClick } = useOvervieImageLinkActions(); + const { handleLinkClick } = useOverviewImageLinkActions(); const currentImage = useSelector(currentOverviewImageSelector); - if (!currentImage || !sizeFactor) return []; + if (!currentImage || sizeFactor === ZERO) return []; - const linkConfigs = currentImage.links.map(link => { - return { - idObject: link.idObject, - size: getOverviewImageLinkSize(link, { sizeFactor }), - onClick: () => handleOnLinkClick(link), - }; - }); - - return linkConfigs; + return currentImage.links.map(link => ({ + idObject: link.idObject, + size: getOverviewImageLinkSize(link, { sizeFactor }), + onClick: () => handleLinkClick(link), + })); }; diff --git a/src/constants/common.ts b/src/constants/common.ts index d8772414c1d8377da3b1590922c5aac46a85e106..040d9bb110eca0e3f433aa2202b233c5aa94ba47 100644 --- a/src/constants/common.ts +++ b/src/constants/common.ts @@ -1,8 +1,12 @@ export const SIZE_OF_EMPTY_ARRAY = 0; +export const SIZE_OF_ARRAY_WITH_FOUR_ELEMENTS = 4; + export const ZERO = 0; export const FIRST_ARRAY_ELEMENT = 0; export const ONE = 1; export const SECOND_ARRAY_ELEMENT = 1; +export const THIRD_ARRAY_ELEMENT = 2; + export const NOOP = (): void => {}; diff --git a/src/models/mocks/overviewImageMocks.ts b/src/models/mocks/overviewImageMocks.ts new file mode 100644 index 0000000000000000000000000000000000000000..999063908b5595dc0575d00eaaec26bc089f1713 --- /dev/null +++ b/src/models/mocks/overviewImageMocks.ts @@ -0,0 +1,21 @@ +import { PROJECT_OVERVIEW_IMAGE_MOCK } from '@/redux/project/project.mock'; +import { OverviewImageLinkImage, OverviewImageLinkModel } from '@/types/models'; + +export const OVERVIEW_LINK_IMAGE_MOCK: OverviewImageLinkImage = { + idObject: 1, + polygon: [], + imageLinkId: PROJECT_OVERVIEW_IMAGE_MOCK.idObject, + type: 'OverviewImageLink', +}; + +export const OVERVIEW_LINK_MODEL_MOCK: OverviewImageLinkModel = { + idObject: 1, + polygon: [], + zoomLevel: 5, + modelPoint: { + x: 15570.0, + y: 3016.0, + }, + modelLinkId: 5053, + type: 'OverviewImageLink', +}; diff --git a/src/redux/project/project.selectors.ts b/src/redux/project/project.selectors.ts index 970ef322a089277a96da126713a463695a483a04..f3425d5d0c80a73758cdc90a0e2f22a2f933cae1 100644 --- a/src/redux/project/project.selectors.ts +++ b/src/redux/project/project.selectors.ts @@ -22,6 +22,11 @@ export const currentOverviewImageSelector = createSelector( ), ); +export const projectOverviewImagesSelector = createSelector( + projectDataSelector, + (projectData): OverviewImageView[] => projectData?.overviewImageViews || [], +); + export const projectDirectorySelector = createSelector( projectDataSelector, projectData => projectData?.directory,